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.
This commit is contained in:
Sebastian Dröge 2012-07-27 23:52:12 +02:00
parent c8840b8270
commit 826a8d643d
7 changed files with 70 additions and 10 deletions

View file

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

View file

@ -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 */

View file

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

View file

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

View file

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

View file

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

View file

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