Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
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
5 changes: 5 additions & 0 deletions docs/source/elements/gvawatermark.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ Element Properties:
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.
The gvafpscounter element must be present in the pipeline.
e.g. ... ! gwatermark disp-avgfps=true ! gvafpscounter ! ...
flags: readable, writable
Boolean. Default: false
message-forward : Forwards all children messages
flags: readable, writable
Boolean. Default: false
Expand Down
104 changes: 87 additions & 17 deletions src/monolithic/gst/elements/gvawatermark/gstgvawatermarkimpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
#include <safe_arithmetic.hpp>

#include "gva_caps.h"
#include "gva_utils.h"
#include "inference_backend/buffer_mapper.h"
#include "so_loader.h"
#include "utils.h"
Expand Down Expand Up @@ -115,7 +114,7 @@ InferenceBackend::MemoryType memoryTypeFromCaps(GstCaps *caps) {
} // namespace

struct Impl {
Impl(GstVideoInfo *info, InferenceBackend::MemoryType mem_type);
Impl(GstVideoInfo *info, InferenceBackend::MemoryType mem_type, GstElement *element, bool disp_avgfps);
bool extract_primitives(GstBuffer *buffer);
int get_num_primitives() const;
bool render(GstBuffer *buffer);
Expand All @@ -133,7 +132,7 @@ struct Impl {
void preparePrimsForKeypointConnections(GstStructure *s, const std::vector<float> &keypoints_data,
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();
std::unique_ptr<Renderer> createRenderer(std::shared_ptr<ColorConverter> converter);

std::unique_ptr<Renderer> createGPURenderer(dlstreamer::ImageFormat format,
Expand All @@ -144,6 +143,8 @@ struct Impl {
std::unique_ptr<Renderer> createOpenCVRenderer(std::shared_ptr<ColorConverter> converter);

GstVideoInfo *_vinfo;
GstElement *_element;
GstElement *_gvafpscounter_element;
std::string _backend_type;
InferenceBackend::MemoryType _mem_type;

Expand All @@ -163,9 +164,10 @@ struct Impl {
const double scale = 1.0;
} _font;
const bool _obb = false;
bool _disp_avgfps = false;
};

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

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 @@ -189,6 +191,9 @@ 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);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
Expand All @@ -211,6 +216,9 @@ 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);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
Expand Down Expand Up @@ -326,7 +334,8 @@ static gboolean gst_gva_watermark_impl_set_caps(GstBaseTransform *trans, GstCaps
#endif

try {
gvawatermark->impl = std::make_shared<Impl>(&gvawatermark->info, mem_type);
gvawatermark->impl =
std::make_shared<Impl>(&gvawatermark->info, mem_type, GST_ELEMENT(trans), gvawatermark->disp_avgfps);
} 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 @@ -662,9 +671,17 @@ static void gst_gva_watermark_impl_class_init(GstGvaWatermarkImplClass *klass) {
"If true, draw oriented bounding box instead of object mask",
false,
(GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
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)));
}

Impl::Impl(GstVideoInfo *info, InferenceBackend::MemoryType mem_type) : _vinfo(info), _mem_type(mem_type) {
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) {
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 @@ -680,6 +697,10 @@ Impl::Impl(GstVideoInfo *info, InferenceBackend::MemoryType mem_type) : _vinfo(i

_renderer = createRenderer(std::move(converter));
_renderer_opencv = createOpenCVRenderer(std::move(converterBGR));

// Find gvafpscounter element in the pipeline to put avg-fps on output video
if (_disp_avgfps)
find_gvafpscounter_element();
}

size_t get_keypoint_index_by_name(const gchar *target_name, GValueArray *names) {
Expand All @@ -697,6 +718,52 @@ size_t get_keypoint_index_by_name(const gchar *target_name, GValueArray *names)
return names->n_values;
}

void Impl::find_gvafpscounter_element() {
_gvafpscounter_element = nullptr;

if (!_element)
return;

GstObject *parent = GST_OBJECT_PARENT(GST_ELEMENT(_element));
GstElement *pipeline = nullptr;
// Traverse up the hierarchy to find the pipeline
while (parent && !GST_IS_PIPELINE(parent)) {
parent = GST_OBJECT_PARENT(parent);
}
if (parent && GST_IS_PIPELINE(parent)) {
pipeline = GST_ELEMENT(parent);
}
if (pipeline) {
GstIterator *it = gst_bin_iterate_elements(GST_BIN(pipeline));
GValue value = G_VALUE_INIT;
gboolean done = FALSE;
while (!done) {
switch (gst_iterator_next(it, &value)) {
case GST_ITERATOR_OK: {
GstElement *element = GST_ELEMENT(g_value_get_object(&value));
const gchar *factory_name = GST_OBJECT_NAME(gst_element_get_factory(element));
if (g_str_has_prefix(factory_name, "gvafpscounter")) {
_gvafpscounter_element = element;
// No need to continue searching
done = TRUE;
}
g_value_reset(&value);
break;
}
case GST_ITERATOR_RESYNC:
gst_iterator_resync(it);
break;
case GST_ITERATOR_ERROR:
case GST_ITERATOR_DONE:
done = TRUE;
break;
}
}
g_value_unset(&value);
gst_iterator_free(it);
}
}

bool Impl::extract_primitives(GstBuffer *buffer) {
ITT_TASK(__FUNCTION__);

Expand Down Expand Up @@ -783,17 +850,6 @@ void Impl::preparePrimsForRoi(GVA::RegionOfInterest &roi, std::vector<render::Pr
GVA::Rect<double> rect = {safe_convert<double>(rect_u32.x), safe_convert<double>(rect_u32.y),
safe_convert<double>(rect_u32.w), safe_convert<double>(rect_u32.h)};

// auto rect = roi.normalized_rect(_vinfo->width, _vinfo->height);
// if (rect.w && rect.h) {
// rect.x *= _vinfo->width;
// rect.y *= _vinfo->height;
// rect.w *= _vinfo->width;
// rect.h *= _vinfo->height;
// } else {
// auto rect_u32 = roi.rect();
// rect = {safe_convert<double>(rect_u32.x), safe_convert<double>(rect_u32.y), safe_convert<double>(rect_u32.w),
// safe_convert<double>(rect_u32.h)};
// }
clip_rect(rect.x, rect.y, rect.w, rect.h, _vinfo);

std::ostringstream text;
Expand Down Expand Up @@ -829,6 +885,20 @@ void Impl::preparePrimsForRoi(GVA::RegionOfInterest &roi, std::vector<render::Pr
pos.y = rect.y + 30.f;
prims.emplace_back(render::Text(text.str(), pos, _font.type, _font.scale, color));
}

// put avg-fps from gvafpscounter element
if (_gvafpscounter_element != nullptr) {
std::ostringstream fpstext;
gfloat avg_fps = 0.0f;
g_object_get(_gvafpscounter_element, "avg-fps", &avg_fps, NULL);
if (avg_fps > 0.0f) {
fpstext << "[avg " << std::fixed << std::setprecision(1) << avg_fps << " FPS]";
if (fpstext.str().size() != 0) {
cv::Point2f pos(_vinfo->width * 0.7, _vinfo->height - 20.f);
prims.emplace_back(render::Text(fpstext.str(), pos, _font.type, _font.scale * 0.7, indexToColor(1)));
}
}
}
}

void Impl::preparePrimsForTensor(const GVA::Tensor &tensor, GVA::Rect<double> rect, std::vector<render::Prim> &prims,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ struct _GstGvaWatermarkImpl {
GstVideoInfo info;
gchar *device;
bool obb;
bool disp_avgfps;
std::shared_ptr<struct Impl> impl;
InferenceBackend::MemoryType negotiated_mem_type = InferenceBackend::MemoryType::ANY;

Expand Down
16 changes: 15 additions & 1 deletion src/monolithic/gst/elements/gvawatermark/gvawatermark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ GST_DEBUG_CATEGORY_STATIC(gst_gva_watermark_debug_category);

#define DEFAULT_DEVICE "CPU"

enum { PROP_0, PROP_DEVICE, PROP_OBB };
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,
Expand Down Expand Up @@ -97,6 +97,13 @@ static void gst_gva_watermark_class_init(GstGvaWatermarkClass *klass) {
"If true, draw oriented bounding box instead of object mask",
false,
(GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
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)));
}

static void gst_gva_watermark_init(GstGvaWatermark *self) {
Expand Down Expand Up @@ -176,6 +183,10 @@ 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);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
break;
Expand All @@ -194,6 +205,9 @@ 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);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
break;
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 @@ -30,6 +30,7 @@ struct _GstGvaWatermark {
GstPad *srcpad;
gchar *device;
bool obb;
bool disp_avgfps;

bool use_watermarkimpl_only;

Expand Down
Loading