Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
103 changes: 86 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 = nullptr;
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,51 @@ size_t get_keypoint_index_by_name(const gchar *target_name, GValueArray *names)
return names->n_values;
}

void Impl::find_gvafpscounter_element() {

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 +849,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 +884,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