Skip to content

Commit 08fca19

Browse files
authored
Add display configuration options to gvawatermark element (#497)
* Add display configuration options to gvawatermark element * Rename display configuration properties in gvawatermark element for consistency. * Remove default display configuration values in gvawatermark element for improved flexibility. * Update copyright year to 2026 in watermark-related files
1 parent 773ab1a commit 08fca19

File tree

5 files changed

+165
-55
lines changed

5 files changed

+165
-55
lines changed

docs/source/elements/gvawatermark.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,20 @@ Element Properties:
6666
async-handling : The bin will handle Asynchronous state changes
6767
flags: readable, writable
6868
Boolean. Default: false
69+
displ-cfg : Comma separated list of KEY=VALUE parameters of displayed notations.
70+
Available options:
71+
show-labels=true|false - enable/disable display of text labels (default true)
72+
text-scale=<0.1-2.0> - scale factor for text labels (default 1.0)
73+
e.g.: displ-cfg=show-labels=off
74+
e.g.: displ-cfg=text-scale=0.5
75+
flags: readable, writable
76+
String. Default: "show-labels=true,text-scale=1.0"
6977
device : Supported devices are CPU and GPU. Default is CPU on system memory and GPU on video memory
7078
flags: readable, writable
7179
String. Default: null
72-
disp-avgfps : If true, display the average FPS read from gvafpscounter element on the output video.
80+
displ-avgfps : If true, display the average FPS read from gvafpscounter element on the output video.
7381
The gvafpscounter element must be present in the pipeline.
74-
e.g. ... ! gwatermark disp-avgfps=true ! gvafpscounter ! ...
82+
e.g. ... ! gvawatermark displ-avgfps=true ! gvafpscounter ! ...
7583
flags: readable, writable
7684
Boolean. Default: false
7785
message-forward : Forwards all children messages

src/monolithic/gst/elements/gvawatermark/gstgvawatermarkimpl.cpp

Lines changed: 104 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (C) 2018-2025 Intel Corporation
2+
* Copyright (C) 2018-2026 Intel Corporation
33
*
44
* SPDX-License-Identifier: MIT
55
******************************************************************************/
@@ -114,7 +114,8 @@ InferenceBackend::MemoryType memoryTypeFromCaps(GstCaps *caps) {
114114
} // namespace
115115

116116
struct Impl {
117-
Impl(GstVideoInfo *info, InferenceBackend::MemoryType mem_type, GstElement *element, bool disp_avgfps);
117+
Impl(GstVideoInfo *info, InferenceBackend::MemoryType mem_type, GstElement *element, bool displ_avgfps,
118+
gchar *displ_cfg);
118119
bool extract_primitives(GstBuffer *buffer);
119120
int get_num_primitives() const;
120121
bool render(GstBuffer *buffer);
@@ -133,6 +134,7 @@ struct Impl {
133134
const std::vector<uint32_t> &dims, const std::vector<float> &confidence,
134135
const GVA::Rect<double> &rectangle, std::vector<render::Prim> &prims) const;
135136
void find_gvafpscounter_element();
137+
void parse_displ_config();
136138
std::unique_ptr<Renderer> createRenderer(std::shared_ptr<ColorConverter> converter);
137139

138140
std::unique_ptr<Renderer> createGPURenderer(dlstreamer::ImageFormat format,
@@ -164,10 +166,14 @@ struct Impl {
164166
const double scale = 1.0;
165167
} _font;
166168
const bool _obb = false;
167-
bool _disp_avgfps = false;
168-
};
169+
bool _displ_avgfps = false;
170+
gchar *_displ_cfg = nullptr;
169171

170-
enum { PROP_0, PROP_DEVICE, PROP_OBB, PROP_DISP_AVGFPS };
172+
struct DisplCfg {
173+
bool show_labels = true;
174+
double text_scale = 1.0;
175+
} _displCfg;
176+
};
171177

172178
G_DEFINE_TYPE_WITH_CODE(GstGvaWatermarkImpl, gst_gva_watermark_impl, GST_TYPE_BASE_TRANSFORM,
173179
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
176182
static void gst_gva_watermark_impl_init(GstGvaWatermarkImpl *gvawatermark) {
177183
gvawatermark->device = DEFAULT_DEVICE;
178184
gvawatermark->obb = false;
185+
gvawatermark->displ_avgfps = false;
186+
gvawatermark->displ_cfg = nullptr;
179187
}
180188

181189
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
191199
case PROP_OBB:
192200
gvawatermark->obb = g_value_get_boolean(value);
193201
break;
194-
case PROP_DISP_AVGFPS:
195-
gvawatermark->disp_avgfps = g_value_get_boolean(value);
202+
case PROP_DISPL_AVGFPS:
203+
gvawatermark->displ_avgfps = g_value_get_boolean(value);
204+
break;
205+
case PROP_DISPL_CFG:
206+
g_free(gvawatermark->displ_cfg);
207+
gvawatermark->displ_cfg = g_value_dup_string(value);
196208
break;
197209
default:
198210
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
216228
case PROP_OBB:
217229
g_value_set_boolean(value, self->obb);
218230
break;
219-
case PROP_DISP_AVGFPS:
220-
g_value_set_boolean(value, self->disp_avgfps);
231+
case PROP_DISPL_AVGFPS:
232+
g_value_set_boolean(value, self->displ_avgfps);
233+
break;
234+
case PROP_DISPL_CFG:
235+
g_value_set_string(value, self->displ_cfg);
221236
break;
222237
default:
223238
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
334349
#endif
335350

336351
try {
337-
gvawatermark->impl =
338-
std::make_shared<Impl>(&gvawatermark->info, mem_type, GST_ELEMENT(trans), gvawatermark->disp_avgfps);
352+
gvawatermark->impl = std::make_shared<Impl>(&gvawatermark->info, mem_type, GST_ELEMENT(trans),
353+
gvawatermark->displ_avgfps, gvawatermark->displ_cfg);
339354
} catch (const std::exception &e) {
340355
GST_ELEMENT_ERROR(gvawatermark, CORE, FAILED, ("Could not initialize"),
341356
("Cannot create watermark instance. %s", Utils::createNestedErrorMsg(e).c_str()));
@@ -660,28 +675,44 @@ static void gst_gva_watermark_impl_class_init(GstGvaWatermarkImplClass *klass) {
660675
base_transform_class->transform_ip = GST_DEBUG_FUNCPTR(gst_gva_watermark_impl_transform_ip);
661676
base_transform_class->propose_allocation = GST_DEBUG_FUNCPTR(gst_gva_watermark_impl_propose_allocation);
662677

678+
const auto kDefaultGParamFlags =
679+
static_cast<GParamFlags>(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
680+
663681
g_object_class_install_property(
664682
gobject_class, PROP_DEVICE,
665683
g_param_spec_string(
666684
"device", "Target device",
667685
"Supported devices are CPU and GPU. Default is CPU on system memory and GPU on video memory",
668-
DEFAULT_DEVICE, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
686+
DEFAULT_DEVICE, kDefaultGParamFlags));
687+
669688
g_object_class_install_property(gobject_class, PROP_OBB,
670689
g_param_spec_boolean("obb", "Oriented Bounding Box",
671690
"If true, draw oriented bounding box instead of object mask",
672-
false,
673-
(GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
691+
false, kDefaultGParamFlags));
692+
674693
g_object_class_install_property(
675-
gobject_class, PROP_DISP_AVGFPS,
676-
g_param_spec_boolean("disp-avgfps", "Display Average FPS",
694+
gobject_class, PROP_DISPL_AVGFPS,
695+
g_param_spec_boolean("displ-avgfps", "Display Average FPS",
677696
"If true, display the average FPS read from gvafpscounter element on the output video."
678697
"The gvafpscounter element must be present in the pipeline."
679-
"e.g. gwatermark ! gvafpscounter ! ...",
680-
false, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
698+
"e.g. gvawatermark displ-avgfps=true ! gvafpscounter ! ...",
699+
false, kDefaultGParamFlags));
700+
701+
g_object_class_install_property(
702+
gobject_class, PROP_DISPL_CFG,
703+
g_param_spec_string("displ-cfg", "Gvawatermark element display configuration",
704+
"Comma separated list of KEY=VALUE parameters of displayed notations.\n"
705+
"\t\t\tAvailable options: \n"
706+
"\t\t\tshow-labels=true|false - enable/disable display of text labels (default true)\n"
707+
"\t\t\ttext-scale=<0.1-2.0> - scale factor for text labels (default 1.0)\n"
708+
"\t\t\te.g.: displ-cfg=show-labels=off\n"
709+
"\t\t\te.g.: displ-cfg=text-scale=0.5",
710+
nullptr, kDefaultGParamFlags));
681711
}
682712

683-
Impl::Impl(GstVideoInfo *info, InferenceBackend::MemoryType mem_type, GstElement *element, bool disp_avgfps)
684-
: _vinfo(info), _element(element), _mem_type(mem_type), _disp_avgfps(disp_avgfps) {
713+
Impl::Impl(GstVideoInfo *info, InferenceBackend::MemoryType mem_type, GstElement *element, bool displ_avgfps,
714+
gchar *displ_cfg)
715+
: _vinfo(info), _element(element), _mem_type(mem_type), _displ_avgfps(displ_avgfps), _displ_cfg(displ_cfg) {
685716
assert(_vinfo);
686717
if (GST_VIDEO_INFO_COLORIMETRY(_vinfo).matrix == GstVideoColorMatrix::GST_VIDEO_COLOR_MATRIX_UNKNOWN)
687718
throw std::runtime_error("GST_VIDEO_COLOR_MATRIX_UNKNOWN");
@@ -699,8 +730,12 @@ Impl::Impl(GstVideoInfo *info, InferenceBackend::MemoryType mem_type, GstElement
699730
_renderer_opencv = createOpenCVRenderer(std::move(converterBGR));
700731

701732
// Find gvafpscounter element in the pipeline to put avg-fps on output video
702-
if (_disp_avgfps)
733+
if (_displ_avgfps)
703734
find_gvafpscounter_element();
735+
736+
// Parse display configuration
737+
if (_displ_cfg)
738+
parse_displ_config();
704739
}
705740

706741
size_t get_keypoint_index_by_name(const gchar *target_name, GValueArray *names) {
@@ -761,6 +796,13 @@ void Impl::find_gvafpscounter_element() {
761796
g_value_unset(&value);
762797
gst_iterator_free(it);
763798
}
799+
800+
if (_gvafpscounter_element == nullptr) {
801+
GST_WARNING_OBJECT(
802+
_element, "displ-avgfps property is set to true, but gvafpscounter element is not found in the pipeline. "
803+
"Average FPS will not be displayed on output video.");
804+
_displ_avgfps = false;
805+
}
764806
}
765807

766808
bool Impl::extract_primitives(GstBuffer *buffer) {
@@ -878,15 +920,17 @@ void Impl::preparePrimsForRoi(GVA::RegionOfInterest &roi, std::vector<render::Pr
878920
prims.emplace_back(render::Rect(bbox_rect, color, _thickness, roi.rotation()));
879921

880922
// put text
881-
if (text.str().size() != 0) {
882-
cv::Point2f pos(rect.x, rect.y - 5.f);
883-
if (pos.y < 0)
884-
pos.y = rect.y + 30.f;
885-
prims.emplace_back(render::Text(text.str(), pos, _font.type, _font.scale, color));
886-
}
923+
if (_displCfg.show_labels)
924+
if (text.str().size() != 0) {
925+
cv::Point2f pos(rect.x, rect.y - 5.f);
926+
if (pos.y < 0)
927+
pos.y = rect.y + 30.f;
928+
double scale = (_displCfg.text_scale != _font.scale) ? _displCfg.text_scale : _font.scale;
929+
prims.emplace_back(render::Text(text.str(), pos, _font.type, scale, color));
930+
}
887931

888932
// put avg-fps from gvafpscounter element
889-
if (_gvafpscounter_element != nullptr) {
933+
if (_displ_avgfps) {
890934
std::ostringstream fpstext;
891935
gfloat avg_fps = 0.0f;
892936
g_object_get(_gvafpscounter_element, "avg-fps", &avg_fps, NULL);
@@ -1094,6 +1138,38 @@ void Impl::preparePrimsForKeypointConnections(GstStructure *s, const std::vector
10941138
g_value_array_free(point_names);
10951139
}
10961140

1141+
void Impl::parse_displ_config() {
1142+
// Parse watermark display configuration
1143+
std::string displcfg_str = std::string(_displ_cfg);
1144+
auto cfg = Utils::stringToMap(displcfg_str);
1145+
auto iter = cfg.end();
1146+
try {
1147+
iter = cfg.find("text-scale");
1148+
if (iter != cfg.end()) {
1149+
_displCfg.text_scale = std::stof(iter->second);
1150+
if (_displCfg.text_scale > 2.0 || _displCfg.text_scale < 0.1) {
1151+
_displCfg.text_scale = 1.0;
1152+
GST_WARNING(
1153+
"[gvawatermarkimpl] 'text-scale' parameter value is out of range (0.1, 2.0], set to default 1.0");
1154+
}
1155+
cfg.erase(iter);
1156+
}
1157+
iter = cfg.find("show-labels");
1158+
if (iter != cfg.end()) {
1159+
if (iter->second == "true" || iter->second == "false") {
1160+
_displCfg.show_labels = (iter->second == "true");
1161+
}
1162+
cfg.erase(iter);
1163+
}
1164+
} catch (...) {
1165+
if (iter == cfg.end())
1166+
std::throw_with_nested(
1167+
std::runtime_error("[gvawatermarkimpl] Error occured while parsing key/value parameters"));
1168+
std::throw_with_nested(
1169+
std::runtime_error("[gvawatermarkimpl] Invalid value provided for parameter: " + iter->first));
1170+
}
1171+
}
1172+
10971173
std::unique_ptr<Renderer> Impl::createRenderer(std::shared_ptr<ColorConverter> converter) {
10981174

10991175
dlstreamer::ImageFormat format = dlstreamer::gst_format_to_video_format(GST_VIDEO_INFO_FORMAT(_vinfo));

src/monolithic/gst/elements/gvawatermark/gstgvawatermarkimpl.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (C) 2018-2025 Intel Corporation
2+
* Copyright (C) 2018-2026 Intel Corporation
33
*
44
* SPDX-License-Identifier: MIT
55
******************************************************************************/
@@ -40,8 +40,9 @@ struct _GstGvaWatermarkImpl {
4040
GstBaseTransform base_transform;
4141
GstVideoInfo info;
4242
gchar *device;
43+
gchar *displ_cfg;
4344
bool obb;
44-
bool disp_avgfps;
45+
bool displ_avgfps;
4546
std::shared_ptr<struct Impl> impl;
4647
InferenceBackend::MemoryType negotiated_mem_type = InferenceBackend::MemoryType::ANY;
4748

@@ -63,6 +64,8 @@ struct _GstGvaWatermarkImplClass {
6364

6465
GType gst_gva_watermark_impl_get_type(void);
6566

67+
enum { PROP_0, PROP_DEVICE, PROP_OBB, PROP_DISPL_AVGFPS, PROP_DISPL_CFG };
68+
6669
G_END_DECLS
6770

6871
#endif

0 commit comments

Comments
 (0)