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: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7145>
This commit is contained in:
Sebastian Dröge 2024-07-07 10:14:40 +03:00 committed by GStreamer Marge Bot
parent a36b3d9fcd
commit a786c85c4f
3 changed files with 69 additions and 1 deletions

View file

@ -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,

View file

@ -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;

View file

@ -54,6 +54,7 @@ struct _GstTagInject
GstTagList *tags;
gboolean tags_sent;
GstTagScope tags_scope;
GstTagMergeMode merge_mode;
};
struct _GstTagInjectClass