Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/source/elements/gvawatermark.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ Element Properties:
async-handling : The bin will handle Asynchronous state changes
flags: readable, writable
Boolean. Default: false
cfg : Comma separated list of KEY=VALUE parameters specific to. Please see user guide for more details.
Available options:
show-labels=true|false - enable/disable display of text labels (default true)
text-scale=<0.1-2.0> - scale factor for text labels (default 1.0)
e.g.: cfg=show-labels=off
e.g.: cfg=text-scale=0.5
flags: readable, writable
String. Default: "show-labels=true,text-scale=1.0"
device : Supported devices are CPU and GPU. Default is CPU on system memory and GPU on video memory
flags: readable, writable
String. Default: null
Expand Down
106 changes: 88 additions & 18 deletions src/monolithic/gst/elements/gvawatermark/gstgvawatermarkimpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@ InferenceBackend::MemoryType memoryTypeFromCaps(GstCaps *caps) {
} // namespace

struct Impl {
Impl(GstVideoInfo *info, InferenceBackend::MemoryType mem_type, GstElement *element, bool disp_avgfps);
Impl(GstVideoInfo *info, InferenceBackend::MemoryType mem_type, GstElement *element, bool disp_avgfps,
gchar *displ_cfg);
bool extract_primitives(GstBuffer *buffer);
int get_num_primitives() const;
bool render(GstBuffer *buffer);
Expand All @@ -133,6 +134,7 @@ struct Impl {
const std::vector<uint32_t> &dims, const std::vector<float> &confidence,
const GVA::Rect<double> &rectangle, std::vector<render::Prim> &prims) const;
void find_gvafpscounter_element();
void parse_displ_config();
std::unique_ptr<Renderer> createRenderer(std::shared_ptr<ColorConverter> converter);

std::unique_ptr<Renderer> createGPURenderer(dlstreamer::ImageFormat format,
Expand Down Expand Up @@ -165,9 +167,13 @@ struct Impl {
} _font;
const bool _obb = false;
bool _disp_avgfps = false;
};
gchar *_displ_cfg = nullptr;

enum { PROP_0, PROP_DEVICE, PROP_OBB, PROP_DISP_AVGFPS };
struct DisplCfg {
bool show_labels = true;
double text_scale = 1.0;
} _displCfg;
};

G_DEFINE_TYPE_WITH_CODE(GstGvaWatermarkImpl, gst_gva_watermark_impl, GST_TYPE_BASE_TRANSFORM,
GST_DEBUG_CATEGORY_INIT(gst_gva_watermark_impl_debug_category, "gvawatermarkimpl", 0,
Expand All @@ -176,6 +182,8 @@ G_DEFINE_TYPE_WITH_CODE(GstGvaWatermarkImpl, gst_gva_watermark_impl, GST_TYPE_BA
static void gst_gva_watermark_impl_init(GstGvaWatermarkImpl *gvawatermark) {
gvawatermark->device = DEFAULT_DEVICE;
gvawatermark->obb = false;
gvawatermark->disp_avgfps = false;
gvawatermark->displ_cfg = nullptr;
}

void gst_gva_watermark_impl_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) {
Expand All @@ -194,6 +202,10 @@ void gst_gva_watermark_impl_set_property(GObject *object, guint prop_id, const G
case PROP_DISP_AVGFPS:
gvawatermark->disp_avgfps = g_value_get_boolean(value);
break;
case PROP_CFG:
g_free(gvawatermark->displ_cfg);
gvawatermark->displ_cfg = g_value_dup_string(value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
Expand All @@ -219,6 +231,9 @@ void gst_gva_watermark_impl_get_property(GObject *object, guint prop_id, GValue
case PROP_DISP_AVGFPS:
g_value_set_boolean(value, self->disp_avgfps);
break;
case PROP_CFG:
g_value_set_string(value, self->displ_cfg);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
Expand Down Expand Up @@ -334,8 +349,8 @@ static gboolean gst_gva_watermark_impl_set_caps(GstBaseTransform *trans, GstCaps
#endif

try {
gvawatermark->impl =
std::make_shared<Impl>(&gvawatermark->info, mem_type, GST_ELEMENT(trans), gvawatermark->disp_avgfps);
gvawatermark->impl = std::make_shared<Impl>(&gvawatermark->info, mem_type, GST_ELEMENT(trans),
gvawatermark->disp_avgfps, gvawatermark->displ_cfg);
} catch (const std::exception &e) {
GST_ELEMENT_ERROR(gvawatermark, CORE, FAILED, ("Could not initialize"),
("Cannot create watermark instance. %s", Utils::createNestedErrorMsg(e).c_str()));
Expand Down Expand Up @@ -660,28 +675,45 @@ static void gst_gva_watermark_impl_class_init(GstGvaWatermarkImplClass *klass) {
base_transform_class->transform_ip = GST_DEBUG_FUNCPTR(gst_gva_watermark_impl_transform_ip);
base_transform_class->propose_allocation = GST_DEBUG_FUNCPTR(gst_gva_watermark_impl_propose_allocation);

const auto kDefaultGParamFlags =
static_cast<GParamFlags>(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);

g_object_class_install_property(
gobject_class, PROP_DEVICE,
g_param_spec_string(
"device", "Target device",
"Supported devices are CPU and GPU. Default is CPU on system memory and GPU on video memory",
DEFAULT_DEVICE, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
DEFAULT_DEVICE, kDefaultGParamFlags));

g_object_class_install_property(gobject_class, PROP_OBB,
g_param_spec_boolean("obb", "Oriented Bounding Box",
"If true, draw oriented bounding box instead of object mask",
false,
(GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
false, kDefaultGParamFlags));

g_object_class_install_property(
gobject_class, PROP_DISP_AVGFPS,
g_param_spec_boolean("disp-avgfps", "Display Average FPS",
"If true, display the average FPS read from gvafpscounter element on the output video."
"The gvafpscounter element must be present in the pipeline."
"e.g. gwatermark ! gvafpscounter ! ...",
false, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
false, kDefaultGParamFlags));

g_object_class_install_property(
gobject_class, PROP_CFG,
g_param_spec_string(
"cfg", "Watermark display configuration",
"Comma separated list of KEY=VALUE parameters specific to. Please see user guide for more details.\n"
"\t\t\tAvailable options: \n"
"\t\t\tshow-labels=true|false - enable/disable display of text labels (default true)\n"
"\t\t\ttext-scale=<0.1-2.0> - scale factor for text labels (default 1.0)\n"
"\t\t\te.g.: cfg=show-labels=off\n"
"\t\t\te.g.: cfg=text-scale=0.5",
"show-labels=true,text-scale=1.0", kDefaultGParamFlags));
}

Impl::Impl(GstVideoInfo *info, InferenceBackend::MemoryType mem_type, GstElement *element, bool disp_avgfps)
: _vinfo(info), _element(element), _mem_type(mem_type), _disp_avgfps(disp_avgfps) {
Impl::Impl(GstVideoInfo *info, InferenceBackend::MemoryType mem_type, GstElement *element, bool disp_avgfps,
gchar *displ_cfg)
: _vinfo(info), _element(element), _mem_type(mem_type), _disp_avgfps(disp_avgfps), _displ_cfg(displ_cfg) {
assert(_vinfo);
if (GST_VIDEO_INFO_COLORIMETRY(_vinfo).matrix == GstVideoColorMatrix::GST_VIDEO_COLOR_MATRIX_UNKNOWN)
throw std::runtime_error("GST_VIDEO_COLOR_MATRIX_UNKNOWN");
Expand All @@ -701,6 +733,10 @@ Impl::Impl(GstVideoInfo *info, InferenceBackend::MemoryType mem_type, GstElement
// Find gvafpscounter element in the pipeline to put avg-fps on output video
if (_disp_avgfps)
find_gvafpscounter_element();

// Parse display configuration
if (_displ_cfg)
parse_displ_config();
}

size_t get_keypoint_index_by_name(const gchar *target_name, GValueArray *names) {
Expand Down Expand Up @@ -878,15 +914,17 @@ void Impl::preparePrimsForRoi(GVA::RegionOfInterest &roi, std::vector<render::Pr
prims.emplace_back(render::Rect(bbox_rect, color, _thickness, roi.rotation()));

// put text
if (text.str().size() != 0) {
cv::Point2f pos(rect.x, rect.y - 5.f);
if (pos.y < 0)
pos.y = rect.y + 30.f;
prims.emplace_back(render::Text(text.str(), pos, _font.type, _font.scale, color));
}
if (_displCfg.show_labels)
if (text.str().size() != 0) {
cv::Point2f pos(rect.x, rect.y - 5.f);
if (pos.y < 0)
pos.y = rect.y + 30.f;
double scale = (_displCfg.text_scale != _font.scale) ? _displCfg.text_scale : _font.scale;
prims.emplace_back(render::Text(text.str(), pos, _font.type, scale, color));
}

// put avg-fps from gvafpscounter element
if (_gvafpscounter_element != nullptr) {
if (_disp_avgfps && _gvafpscounter_element != nullptr) {
std::ostringstream fpstext;
gfloat avg_fps = 0.0f;
g_object_get(_gvafpscounter_element, "avg-fps", &avg_fps, NULL);
Expand Down Expand Up @@ -1094,6 +1132,38 @@ void Impl::preparePrimsForKeypointConnections(GstStructure *s, const std::vector
g_value_array_free(point_names);
}

void Impl::parse_displ_config() {
// Parse watermark display configuration
std::string displcfg_str = std::string(_displ_cfg);
auto cfg = Utils::stringToMap(displcfg_str);
auto iter = cfg.end();
try {
iter = cfg.find("text-scale");
if (iter != cfg.end()) {
_displCfg.text_scale = std::stof(iter->second);
if (_displCfg.text_scale > 2.0 || _displCfg.text_scale < 0.1) {
_displCfg.text_scale = 1.0;
GST_WARNING(
"[gvawatermarkimpl] 'text-scale' parameter value is out of range (0.1, 2.0], set to default 1.0");
}
cfg.erase(iter);
}
iter = cfg.find("show-labels");
if (iter != cfg.end()) {
if (iter->second == "true" || iter->second == "false") {
_displCfg.show_labels = (iter->second == "true");
}
cfg.erase(iter);
}
} catch (...) {
if (iter == cfg.end())
std::throw_with_nested(
std::runtime_error("[gvawatermarkimpl] Error occured while parsing key/value parameters"));
std::throw_with_nested(
std::runtime_error("[gvawatermarkimpl] Invalid value provided for parameter: " + iter->first));
}
}

std::unique_ptr<Renderer> Impl::createRenderer(std::shared_ptr<ColorConverter> converter) {

dlstreamer::ImageFormat format = dlstreamer::gst_format_to_video_format(GST_VIDEO_INFO_FORMAT(_vinfo));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ struct _GstGvaWatermarkImpl {
GstBaseTransform base_transform;
GstVideoInfo info;
gchar *device;
gchar *displ_cfg;
bool obb;
bool disp_avgfps;
std::shared_ptr<struct Impl> impl;
Expand All @@ -63,6 +64,8 @@ struct _GstGvaWatermarkImplClass {

GType gst_gva_watermark_impl_get_type(void);

enum { PROP_0, PROP_DEVICE, PROP_OBB, PROP_DISP_AVGFPS, PROP_CFG };

G_END_DECLS

#endif
51 changes: 37 additions & 14 deletions src/monolithic/gst/elements/gvawatermark/gvawatermark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
******************************************************************************/

#include "gvawatermark.h"
#include "gstgvawatermarkimpl.h"
#include "gvawatermarkcaps.h"

#include "scope_guard.h"
Expand All @@ -21,8 +22,6 @@ GST_DEBUG_CATEGORY_STATIC(gst_gva_watermark_debug_category);

#define DEFAULT_DEVICE "CPU"

enum { PROP_0, PROP_DEVICE, PROP_OBB, PROP_DISP_AVGFPS };

G_DEFINE_TYPE_WITH_CODE(GstGvaWatermark, gst_gva_watermark, GST_TYPE_BIN,
GST_DEBUG_CATEGORY_INIT(gst_gva_watermark_debug_category, "gvawatermark", 0,
"debug category for gvawatermark element"));
Expand All @@ -40,7 +39,6 @@ static GstStateChangeReturn gva_watermark_change_state(GstElement *element, GstS
static gboolean gst_gva_watermark_sink_event(GstPad *pad, GstObject *parent, GstEvent *event);

namespace {

static const gchar *get_caps_str_with_feature(CapsFeature mem_type) {
if (mem_type == VA_SURFACE_CAPS_FEATURE)
return "video/x-raw(" VASURFACE_FEATURE_STR "), format=" WATERMARK_PREFERRED_REMOTE_FORMAT;
Expand Down Expand Up @@ -87,23 +85,37 @@ static void gst_gva_watermark_class_init(GstGvaWatermarkClass *klass) {
gobject_class->get_property = gst_gva_watermark_get_property;
gobject_class->finalize = gst_gva_watermark_finalize;

g_object_class_install_property(
gobject_class, PROP_DEVICE,
g_param_spec_string("device", "Target device", "CPU or GPU. Default is CPU.", DEFAULT_DEVICE,
static_cast<GParamFlags>(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
const auto kDefaultGParamFlags =
static_cast<GParamFlags>(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);

g_object_class_install_property(gobject_class, PROP_DEVICE,
g_param_spec_string("device", "Target device", "CPU or GPU. Default is CPU.",
DEFAULT_DEVICE, kDefaultGParamFlags));

g_object_class_install_property(gobject_class, PROP_OBB,
g_param_spec_boolean("obb", "Oriented Bounding Box",
"If true, draw oriented bounding box instead of object mask",
false,
(GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
false, kDefaultGParamFlags));
g_object_class_install_property(
gobject_class, PROP_DISP_AVGFPS,
g_param_spec_boolean("disp-avgfps", "Display Average FPS",
"If true, display the average FPS read from gvafpscounter element on the output video.\n"
"\t\t\tThe gvafpscounter element must be present in the pipeline.\n"
"\t\t\te.g. ... ! gwatermark ! gvafpscounter ! ...",
false, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
g_param_spec_boolean(
"disp-avgfps", "Display Average FPS",
"If true, display the average FPS read from gvafpscounter element on the output video, (default false)\n"
"\t\t\tThe gvafpscounter element must be present in the pipeline.\n"
"\t\t\te.g.: ... ! gwatermark ! gvafpscounter ! ...",
false, kDefaultGParamFlags));

g_object_class_install_property(
gobject_class, PROP_CFG,
g_param_spec_string(
"cfg", "Watermark display configuration",
"Comma separated list of KEY=VALUE parameters specific to. Please see user guide for more details.\n"
"\t\t\tAvailable options: \n"
"\t\t\tshow-labels=true|false - enable/disable display of text labels (default true)\n"
"\t\t\ttext-scale=<0.1-2.0> - scale factor for text labels (default 1.0)\n"
"\t\t\te.g.: cfg=show-labels=off\n"
"\t\t\te.g.: cfg=text-scale=0.5",
"show-labels=true,text-scale=1.0", kDefaultGParamFlags));
}

static void gst_gva_watermark_init(GstGvaWatermark *self) {
Expand Down Expand Up @@ -187,6 +199,11 @@ void gst_gva_watermark_set_property(GObject *object, guint property_id, const GV
gvawatermark->disp_avgfps = g_value_get_boolean(value);
g_object_set(gvawatermark->watermarkimpl, "disp-avgfps", gvawatermark->disp_avgfps, nullptr);
break;
case PROP_CFG:
g_free(gvawatermark->displ_cfg);
gvawatermark->displ_cfg = g_value_dup_string(value);
g_object_set(gvawatermark->watermarkimpl, "cfg", gvawatermark->displ_cfg, nullptr);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
break;
Expand All @@ -208,6 +225,9 @@ void gst_gva_watermark_get_property(GObject *object, guint property_id, GValue *
case PROP_DISP_AVGFPS:
g_value_set_boolean(value, gvawatermark->disp_avgfps);
break;
case PROP_CFG:
g_value_set_string(value, gvawatermark->displ_cfg);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
break;
Expand All @@ -227,6 +247,9 @@ void gst_gva_watermark_finalize(GObject *object) {
g_free(gvawatermark->device);
gvawatermark->device = nullptr;

g_free(gvawatermark->displ_cfg);
gvawatermark->displ_cfg = nullptr;

G_OBJECT_CLASS(gst_gva_watermark_parent_class)->finalize(object);
}

Expand Down
1 change: 1 addition & 0 deletions src/monolithic/gst/elements/gvawatermark/gvawatermark.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ struct _GstGvaWatermark {
GstPad *sinkpad;
GstPad *srcpad;
gchar *device;
gchar *displ_cfg;
bool obb;
bool disp_avgfps;

Expand Down
Loading