From 826a8d643df4ab32d19abb26ebec512981f8a653 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 27 Jul 2012 23:52:12 +0200 Subject: [PATCH] tag: Add a scope to taglists This specifies if a given taglist applies to the complete medium or only this specific stream. By default a taglist has a stream scope. Fixes bug #677619. --- gst/gstevent.c | 13 ++++++++----- gst/gstevent.h | 2 +- gst/gsttaglist.c | 37 ++++++++++++++++++++++++++++++++++++ gst/gsttaglist.h | 17 +++++++++++++++++ libs/gst/base/gstbaseparse.c | 7 +++++-- tests/check/gst/gstevent.c | 2 +- tests/check/gst/gstutils.c | 2 +- 7 files changed, 70 insertions(+), 10 deletions(-) diff --git a/gst/gstevent.c b/gst/gstevent.c index 20961760a7..3bb4d7f48e 100644 --- a/gst/gstevent.c +++ b/gst/gstevent.c @@ -984,26 +984,29 @@ gst_event_copy_segment (GstEvent * event, GstSegment * segment) /** * gst_event_new_tag: - * @name: (transfer none): the name of the event * @taglist: (transfer full): metadata list. The event will take ownership * of the taglist. * * Generates a metadata tag event from the given @taglist. * - * Since the TAG event has the %GST_EVENT_TYPE_STICKY_MULTI flag set, the - * @name will be used to keep track of multiple tag events. + * The scope of the taglist specifies if the taglist applies to the + * complete medium or only to this specific stream. As the tag event + * is a sticky event, elements should merge tags received from + * upstream with a given scope with their own tags with the same + * scope and create a new tag event from it. * * Returns: (transfer full): a new #GstEvent */ GstEvent * -gst_event_new_tag (const gchar * name, GstTagList * taglist) +gst_event_new_tag (GstTagList * taglist) { GstStructure *s; GValue val = G_VALUE_INIT; + const gchar *names[] = { "GstTagList-stream", "GstTagList-global" }; g_return_val_if_fail (taglist != NULL, NULL); - s = gst_structure_new_empty (name); + s = gst_structure_new_empty (names[gst_tag_list_get_scope (taglist)]); g_value_init (&val, GST_TYPE_TAG_LIST); g_value_take_boxed (&val, taglist); gst_structure_id_take_value (s, GST_QUARK (TAGLIST), &val); diff --git a/gst/gstevent.h b/gst/gstevent.h index 16004ccc13..00d8d18690 100644 --- a/gst/gstevent.h +++ b/gst/gstevent.h @@ -518,7 +518,7 @@ void gst_event_parse_segment (GstEvent *event, const GstSegme void gst_event_copy_segment (GstEvent *event, GstSegment *segment); /* tag event */ -GstEvent* gst_event_new_tag (const gchar *name, GstTagList *taglist) G_GNUC_MALLOC; +GstEvent* gst_event_new_tag (GstTagList *taglist) G_GNUC_MALLOC; void gst_event_parse_tag (GstEvent *event, GstTagList **taglist); /* TOC event */ diff --git a/gst/gsttaglist.c b/gst/gsttaglist.c index 1da2ca8784..7de389fc60 100644 --- a/gst/gsttaglist.c +++ b/gst/gsttaglist.c @@ -57,9 +57,11 @@ typedef struct _GstTagListImpl GstTagList taglist; GstStructure *structure; + GstTagScope scope; } GstTagListImpl; #define GST_TAG_LIST_STRUCTURE(taglist) ((GstTagListImpl*)(taglist))->structure +#define GST_TAG_LIST_SCOPE(taglist) ((GstTagListImpl*)(taglist))->scope typedef struct { @@ -670,6 +672,7 @@ gst_tag_list_new_internal (GstStructure * s) (GstMiniObjectFreeFunction) __gst_tag_list_free); GST_TAG_LIST_STRUCTURE (tag_list) = s; + GST_TAG_LIST_SCOPE (tag_list) = GST_TAG_SCOPE_STREAM; #ifdef DEBUG_REFCOUNT GST_CAT_TRACE (GST_CAT_TAGS, "created taglist %p", tag_list); @@ -783,6 +786,40 @@ gst_tag_list_new_valist (va_list var_args) return list; } +/** + * gst_tag_list_set_scope: + * @list: a #GstTagList + * @scope: new scope for @list + * + * Sets the scope of @list to @scope. By default the scope + * of a taglist is #GST_TAG_SCOPE_STREAM. + * + */ +void +gst_tag_list_set_scope (GstTagList * list, GstTagScope scope) +{ + g_return_if_fail (GST_IS_TAG_LIST (list)); + g_return_if_fail (gst_tag_list_is_writable (list)); + + GST_TAG_LIST_SCOPE (list) = scope; +} + +/** + * gst_tag_list_get_scope: + * @list: a #GstTagList + * + * Gets the scope of @list. + * + * Returns: The scope of @list + */ +GstTagScope +gst_tag_list_get_scope (const GstTagList * list) +{ + g_return_val_if_fail (GST_IS_TAG_LIST (list), GST_TAG_SCOPE_STREAM); + + return GST_TAG_LIST_SCOPE (list); +} + /** * gst_tag_list_to_string: * @list: a #GstTagList diff --git a/gst/gsttaglist.h b/gst/gsttaglist.h index dcbe37ad62..e6f1648d42 100644 --- a/gst/gsttaglist.h +++ b/gst/gsttaglist.h @@ -211,10 +211,27 @@ GstTagFlag gst_tag_get_flag (const gchar * tag); gboolean gst_tag_is_fixed (const gchar * tag); /* tag lists */ + +/** + * GstTagEventScope: + * @GST_TAG_SCOPE_STREAM: tags specific to this single stream + * @GST_TAG_SCOPE_GLOBAL: global tags for the complete medium + * + * GstTagScope specifies if a taglist applies to the complete + * medium or only to one single stream. + */ +typedef enum { + GST_TAG_SCOPE_STREAM, + GST_TAG_SCOPE_GLOBAL +} GstTagScope; + GstTagList * gst_tag_list_new_empty (void) G_GNUC_MALLOC; GstTagList * gst_tag_list_new (const gchar * tag, ...) G_GNUC_MALLOC; GstTagList * gst_tag_list_new_valist (va_list var_args) G_GNUC_MALLOC; +void gst_tag_list_set_scope (GstTagList * list, GstTagScope scope); +GstTagScope gst_tag_list_get_scope (const GstTagList * list); + gchar * gst_tag_list_to_string (const GstTagList * list) G_GNUC_MALLOC; GstTagList * gst_tag_list_new_from_string (const gchar * str) G_GNUC_MALLOC; diff --git a/libs/gst/base/gstbaseparse.c b/libs/gst/base/gstbaseparse.c index edaedcc9fe..349a202ec7 100644 --- a/libs/gst/base/gstbaseparse.c +++ b/libs/gst/base/gstbaseparse.c @@ -1404,8 +1404,7 @@ gst_base_parse_post_bitrates (GstBaseParse * parse, gboolean post_min, parse->priv->max_bitrate); if (taglist != NULL) { - gst_pad_push_event (parse->srcpad, gst_event_new_tag ("GstParser", - taglist)); + gst_pad_push_event (parse->srcpad, gst_event_new_tag (taglist)); } } @@ -3983,6 +3982,10 @@ gst_base_parse_handle_tag (GstBaseParse * parse, GstEvent * event) gst_event_parse_tag (event, &taglist); + /* We only care about stream tags here */ + if (gst_tag_list_get_scope (taglist) != GST_TAG_SCOPE_STREAM) + return; + if (gst_tag_list_get_uint (taglist, GST_TAG_MINIMUM_BITRATE, &tmp)) { GST_DEBUG_OBJECT (parse, "upstream min bitrate %d", tmp); parse->priv->post_min_bitrate = FALSE; diff --git a/tests/check/gst/gstevent.c b/tests/check/gst/gstevent.c index 5e805cca4c..fc215f2286 100644 --- a/tests/check/gst/gstevent.c +++ b/tests/check/gst/gstevent.c @@ -185,7 +185,7 @@ GST_START_TEST (create_events) GstTagList *taglist = gst_tag_list_new_empty (); GstTagList *tl2 = NULL; - event = gst_event_new_tag ("test", taglist); + event = gst_event_new_tag (taglist); fail_if (taglist == NULL); fail_if (event == NULL); fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_TAG); diff --git a/tests/check/gst/gstutils.c b/tests/check/gst/gstutils.c index 046187bdfd..e0d0ff365a 100644 --- a/tests/check/gst/gstutils.c +++ b/tests/check/gst/gstutils.c @@ -504,7 +504,7 @@ GST_START_TEST (test_element_found_tags) gst_element_set_state (pipeline, GST_STATE_PLAYING); srcpad = gst_element_get_static_pad (fakesrc, "src"); - gst_pad_push_event (srcpad, gst_event_new_tag ("test", list)); + gst_pad_push_event (srcpad, gst_event_new_tag (list)); gst_object_unref (srcpad); bus = gst_element_get_bus (pipeline);