diff --git a/docs/source/elements/gvawatermark.md b/docs/source/elements/gvawatermark.md index 69090622..cae47b4a 100644 --- a/docs/source/elements/gvawatermark.md +++ b/docs/source/elements/gvawatermark.md @@ -66,12 +66,20 @@ Element Properties: async-handling : The bin will handle Asynchronous state changes flags: readable, writable Boolean. Default: false + displ-cfg : Comma separated list of KEY=VALUE parameters of displayed notations. + 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.: displ-cfg=show-labels=off + e.g.: displ-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 - disp-avgfps : If true, display the average FPS read from gvafpscounter element on the output video. + displ-avgfps : 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 disp-avgfps=true ! gvafpscounter ! ... + e.g. ... ! gvawatermark displ-avgfps=true ! gvafpscounter ! ... flags: readable, writable Boolean. Default: false message-forward : Forwards all children messages diff --git a/src/monolithic/gst/elements/gvawatermark/gstgvawatermarkimpl.cpp b/src/monolithic/gst/elements/gvawatermark/gstgvawatermarkimpl.cpp index 169459c2..cfa2a912 100644 --- a/src/monolithic/gst/elements/gvawatermark/gstgvawatermarkimpl.cpp +++ b/src/monolithic/gst/elements/gvawatermark/gstgvawatermarkimpl.cpp @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2018-2025 Intel Corporation + * Copyright (C) 2018-2026 Intel Corporation * * SPDX-License-Identifier: MIT ******************************************************************************/ @@ -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 displ_avgfps, + gchar *displ_cfg); bool extract_primitives(GstBuffer *buffer); int get_num_primitives() const; bool render(GstBuffer *buffer); @@ -133,6 +134,7 @@ struct Impl { const std::vector &dims, const std::vector &confidence, const GVA::Rect &rectangle, std::vector &prims) const; void find_gvafpscounter_element(); + void parse_displ_config(); std::unique_ptr createRenderer(std::shared_ptr converter); std::unique_ptr createGPURenderer(dlstreamer::ImageFormat format, @@ -164,10 +166,14 @@ struct Impl { const double scale = 1.0; } _font; const bool _obb = false; - bool _disp_avgfps = false; -}; + bool _displ_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, @@ -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->displ_avgfps = false; + gvawatermark->displ_cfg = nullptr; } void gst_gva_watermark_impl_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { @@ -191,8 +199,12 @@ void gst_gva_watermark_impl_set_property(GObject *object, guint prop_id, const G case PROP_OBB: gvawatermark->obb = g_value_get_boolean(value); break; - case PROP_DISP_AVGFPS: - gvawatermark->disp_avgfps = g_value_get_boolean(value); + case PROP_DISPL_AVGFPS: + gvawatermark->displ_avgfps = g_value_get_boolean(value); + break; + case PROP_DISPL_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); @@ -216,8 +228,11 @@ void gst_gva_watermark_impl_get_property(GObject *object, guint prop_id, GValue case PROP_OBB: g_value_set_boolean(value, self->obb); break; - case PROP_DISP_AVGFPS: - g_value_set_boolean(value, self->disp_avgfps); + case PROP_DISPL_AVGFPS: + g_value_set_boolean(value, self->displ_avgfps); + break; + case PROP_DISPL_CFG: + g_value_set_string(value, self->displ_cfg); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); @@ -334,8 +349,8 @@ static gboolean gst_gva_watermark_impl_set_caps(GstBaseTransform *trans, GstCaps #endif try { - gvawatermark->impl = - std::make_shared(&gvawatermark->info, mem_type, GST_ELEMENT(trans), gvawatermark->disp_avgfps); + gvawatermark->impl = std::make_shared(&gvawatermark->info, mem_type, GST_ELEMENT(trans), + gvawatermark->displ_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())); @@ -660,28 +675,44 @@ 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(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", + gobject_class, PROP_DISPL_AVGFPS, + g_param_spec_boolean("displ-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))); + "e.g. gvawatermark displ-avgfps=true ! gvafpscounter ! ...", + false, kDefaultGParamFlags)); + + g_object_class_install_property( + gobject_class, PROP_DISPL_CFG, + g_param_spec_string("displ-cfg", "Gvawatermark element display configuration", + "Comma separated list of KEY=VALUE parameters of displayed notations.\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.: displ-cfg=show-labels=off\n" + "\t\t\te.g.: displ-cfg=text-scale=0.5", + nullptr, 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 displ_avgfps, + gchar *displ_cfg) + : _vinfo(info), _element(element), _mem_type(mem_type), _displ_avgfps(displ_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"); @@ -699,8 +730,12 @@ Impl::Impl(GstVideoInfo *info, InferenceBackend::MemoryType mem_type, GstElement _renderer_opencv = createOpenCVRenderer(std::move(converterBGR)); // Find gvafpscounter element in the pipeline to put avg-fps on output video - if (_disp_avgfps) + if (_displ_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) { @@ -761,6 +796,13 @@ void Impl::find_gvafpscounter_element() { g_value_unset(&value); gst_iterator_free(it); } + + if (_gvafpscounter_element == nullptr) { + GST_WARNING_OBJECT( + _element, "displ-avgfps property is set to true, but gvafpscounter element is not found in the pipeline. " + "Average FPS will not be displayed on output video."); + _displ_avgfps = false; + } } bool Impl::extract_primitives(GstBuffer *buffer) { @@ -878,15 +920,17 @@ void Impl::preparePrimsForRoi(GVA::RegionOfInterest &roi, std::vectorsecond); + 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 Impl::createRenderer(std::shared_ptr converter) { dlstreamer::ImageFormat format = dlstreamer::gst_format_to_video_format(GST_VIDEO_INFO_FORMAT(_vinfo)); diff --git a/src/monolithic/gst/elements/gvawatermark/gstgvawatermarkimpl.h b/src/monolithic/gst/elements/gvawatermark/gstgvawatermarkimpl.h index af583ac2..0a2db5d0 100644 --- a/src/monolithic/gst/elements/gvawatermark/gstgvawatermarkimpl.h +++ b/src/monolithic/gst/elements/gvawatermark/gstgvawatermarkimpl.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2018-2025 Intel Corporation + * Copyright (C) 2018-2026 Intel Corporation * * SPDX-License-Identifier: MIT ******************************************************************************/ @@ -40,8 +40,9 @@ struct _GstGvaWatermarkImpl { GstBaseTransform base_transform; GstVideoInfo info; gchar *device; + gchar *displ_cfg; bool obb; - bool disp_avgfps; + bool displ_avgfps; std::shared_ptr impl; InferenceBackend::MemoryType negotiated_mem_type = InferenceBackend::MemoryType::ANY; @@ -63,6 +64,8 @@ struct _GstGvaWatermarkImplClass { GType gst_gva_watermark_impl_get_type(void); +enum { PROP_0, PROP_DEVICE, PROP_OBB, PROP_DISPL_AVGFPS, PROP_DISPL_CFG }; + G_END_DECLS #endif diff --git a/src/monolithic/gst/elements/gvawatermark/gvawatermark.cpp b/src/monolithic/gst/elements/gvawatermark/gvawatermark.cpp index fe7bd969..b91892ac 100644 --- a/src/monolithic/gst/elements/gvawatermark/gvawatermark.cpp +++ b/src/monolithic/gst/elements/gvawatermark/gvawatermark.cpp @@ -1,10 +1,11 @@ /******************************************************************************* - * Copyright (C) 2021-2025 Intel Corporation + * Copyright (C) 2021-2026 Intel Corporation * * SPDX-License-Identifier: MIT ******************************************************************************/ #include "gvawatermark.h" +#include "gstgvawatermarkimpl.h" #include "gvawatermarkcaps.h" #include "scope_guard.h" @@ -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")); @@ -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; @@ -87,23 +85,36 @@ 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(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + const auto kDefaultGParamFlags = + static_cast(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))); + gobject_class, PROP_DISPL_AVGFPS, + g_param_spec_boolean( + "displ-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.: ... ! gvawatermark displ-avgfps=true ! gvafpscounter ! ...", + false, kDefaultGParamFlags)); + + g_object_class_install_property( + gobject_class, PROP_DISPL_CFG, + g_param_spec_string("displ-cfg", "Gvawatermark display configuration", + "Comma separated list of KEY=VALUE parameters of displayed notations.\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.: displ-cfg=show-labels=off\n" + "\t\t\te.g.: displ-cfg=text-scale=0.5", + nullptr, kDefaultGParamFlags)); } static void gst_gva_watermark_init(GstGvaWatermark *self) { @@ -183,9 +194,14 @@ void gst_gva_watermark_set_property(GObject *object, guint property_id, const GV gvawatermark->obb = g_value_get_boolean(value); g_object_set(gvawatermark->watermarkimpl, "obb", gvawatermark->obb, nullptr); break; - case PROP_DISP_AVGFPS: - gvawatermark->disp_avgfps = g_value_get_boolean(value); - g_object_set(gvawatermark->watermarkimpl, "disp-avgfps", gvawatermark->disp_avgfps, nullptr); + case PROP_DISPL_AVGFPS: + gvawatermark->displ_avgfps = g_value_get_boolean(value); + g_object_set(gvawatermark->watermarkimpl, "displ-avgfps", gvawatermark->displ_avgfps, nullptr); + break; + case PROP_DISPL_CFG: + g_free(gvawatermark->displ_cfg); + gvawatermark->displ_cfg = g_value_dup_string(value); + g_object_set(gvawatermark->watermarkimpl, "displ-cfg", gvawatermark->displ_cfg, nullptr); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); @@ -205,8 +221,11 @@ void gst_gva_watermark_get_property(GObject *object, guint property_id, GValue * case PROP_OBB: g_value_set_boolean(value, gvawatermark->obb); break; - case PROP_DISP_AVGFPS: - g_value_set_boolean(value, gvawatermark->disp_avgfps); + case PROP_DISPL_AVGFPS: + g_value_set_boolean(value, gvawatermark->displ_avgfps); + break; + case PROP_DISPL_CFG: + g_value_set_string(value, gvawatermark->displ_cfg); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); @@ -227,6 +246,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); } diff --git a/src/monolithic/gst/elements/gvawatermark/gvawatermark.h b/src/monolithic/gst/elements/gvawatermark/gvawatermark.h index 6eb5efb6..81fc8750 100644 --- a/src/monolithic/gst/elements/gvawatermark/gvawatermark.h +++ b/src/monolithic/gst/elements/gvawatermark/gvawatermark.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2021-2025 Intel Corporation + * Copyright (C) 2021-2026 Intel Corporation * * SPDX-License-Identifier: MIT ******************************************************************************/ @@ -29,8 +29,9 @@ struct _GstGvaWatermark { GstPad *sinkpad; GstPad *srcpad; gchar *device; + gchar *displ_cfg; bool obb; - bool disp_avgfps; + bool displ_avgfps; bool use_watermarkimpl_only;