From a786c85c4fd4669406baa4b6f9c7c2ef1bef12dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 7 Jul 2024 10:14:40 +0300 Subject: [PATCH] taginject: Modify existing tag events of the selected scope Not doing so would mean that tags would be overidden by any tag events sent by upstream. Also only send a tag event directly if upstream never sent one. By default use GST_TAG_MERGE_REPLACE to override tags that exist in both the upstream event and this element with the ones from this element, but provide a new "merge-mode" property to adjust the behaviour. Part-of: --- .../docs/gst_plugins_cache.json | 12 ++++ .../gst/debugutils/gsttaginject.c | 57 ++++++++++++++++++- .../gst/debugutils/gsttaginject.h | 1 + 3 files changed, 69 insertions(+), 1 deletion(-) diff --git a/subprojects/gst-plugins-good/docs/gst_plugins_cache.json b/subprojects/gst-plugins-good/docs/gst_plugins_cache.json index 8a58e8ad7e..2269260b70 100644 --- a/subprojects/gst-plugins-good/docs/gst_plugins_cache.json +++ b/subprojects/gst-plugins-good/docs/gst_plugins_cache.json @@ -4935,6 +4935,18 @@ } }, "properties": { + "merge-mode": { + "blurb": "Merge mode to merge tags from this element with upstream tags", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "replace (2)", + "mutable": "null", + "readable": true, + "type": "GstTagMergeMode", + "writable": true + }, "scope": { "blurb": "Scope of tags to inject (stream | global)", "conditionally-available": false, diff --git a/subprojects/gst-plugins-good/gst/debugutils/gsttaginject.c b/subprojects/gst-plugins-good/gst/debugutils/gsttaginject.c index 0ac5acbc35..57dd26854b 100644 --- a/subprojects/gst-plugins-good/gst/debugutils/gsttaginject.c +++ b/subprojects/gst-plugins-good/gst/debugutils/gsttaginject.c @@ -63,7 +63,8 @@ GST_DEBUG_CATEGORY_STATIC (gst_tag_inject_debug); enum { PROP_TAGS = 1, - PROP_SCOPE + PROP_SCOPE, + PROP_MERGE_MODE }; @@ -80,6 +81,8 @@ static void gst_tag_inject_get_property (GObject * object, guint prop_id, static GstFlowReturn gst_tag_inject_transform_ip (GstBaseTransform * trans, GstBuffer * buf); +static gboolean gst_tag_inject_sink_event (GstBaseTransform * trans, + GstEvent * event); static gboolean gst_tag_inject_start (GstBaseTransform * trans); @@ -131,6 +134,19 @@ gst_tag_inject_class_init (GstTagInjectClass * klass) GST_TYPE_TAG_SCOPE, GST_TAG_SCOPE_STREAM, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * taginject:merge-mode: + * + * Merge mode to merge tags from this element with upstream tags. + * + * Since: 1.26 + **/ + g_object_class_install_property (gobject_class, PROP_MERGE_MODE, + g_param_spec_enum ("merge-mode", "Merge Mode", + "Merge mode to merge tags from this element with upstream tags", + GST_TYPE_TAG_MERGE_MODE, GST_TAG_MERGE_REPLACE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + gobject_class->finalize = gst_tag_inject_finalize; gst_element_class_set_static_metadata (gstelement_class, @@ -141,6 +157,8 @@ gst_tag_inject_class_init (GstTagInjectClass * klass) gstbasetrans_class->transform_ip = GST_DEBUG_FUNCPTR (gst_tag_inject_transform_ip); + gstbasetrans_class->sink_event = + GST_DEBUG_FUNCPTR (gst_tag_inject_sink_event); gstbasetrans_class->start = GST_DEBUG_FUNCPTR (gst_tag_inject_start); } @@ -154,6 +172,7 @@ gst_tag_inject_init (GstTagInject * self) self->tags = NULL; self->tags_scope = GST_TAG_SCOPE_STREAM; + self->merge_mode = GST_TAG_MERGE_REPLACE; } static GstFlowReturn @@ -174,6 +193,36 @@ gst_tag_inject_transform_ip (GstBaseTransform * trans, GstBuffer * buf) return GST_FLOW_OK; } +static gboolean +gst_tag_inject_sink_event (GstBaseTransform * trans, GstEvent * event) +{ + GstTagInject *self = GST_TAG_INJECT (trans); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_TAG:{ + GstTagList *tags; + + gst_event_parse_tag (event, &tags); + if (gst_tag_list_get_scope (tags) == self->tags_scope) { + GstTagList *new_tags; + guint32 seqnum = gst_event_get_seqnum (event); + + new_tags = gst_tag_list_merge (tags, self->tags, self->merge_mode); + gst_tag_list_set_scope (new_tags, self->tags_scope); + gst_event_unref (event); + event = gst_event_new_tag (new_tags); + gst_event_set_seqnum (event, seqnum); + + self->tags_sent = TRUE; + } + } + default: + break; + } + + return GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans, event); +} + static void gst_tag_inject_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) @@ -200,6 +249,9 @@ gst_tag_inject_set_property (GObject * object, guint prop_id, if (self->tags) gst_tag_list_set_scope (self->tags, self->tags_scope); break; + case PROP_MERGE_MODE: + self->merge_mode = g_value_get_enum (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -220,6 +272,9 @@ gst_tag_inject_get_property (GObject * object, guint prop_id, GValue * value, case PROP_SCOPE: g_value_set_enum (value, self->tags_scope); break; + case PROP_MERGE_MODE: + g_value_set_enum (value, self->merge_mode); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/subprojects/gst-plugins-good/gst/debugutils/gsttaginject.h b/subprojects/gst-plugins-good/gst/debugutils/gsttaginject.h index 8e59858b61..7d9fd3cba9 100644 --- a/subprojects/gst-plugins-good/gst/debugutils/gsttaginject.h +++ b/subprojects/gst-plugins-good/gst/debugutils/gsttaginject.h @@ -54,6 +54,7 @@ struct _GstTagInject GstTagList *tags; gboolean tags_sent; GstTagScope tags_scope; + GstTagMergeMode merge_mode; }; struct _GstTagInjectClass