diff options
author | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2012-06-08 09:16:25 +0200 |
---|---|---|
committer | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2012-06-08 09:16:25 +0200 |
commit | bed72dff4210fac83b878ac3b0f3ecb78d30d1d2 (patch) | |
tree | 9dd932b51f35262b1051648bb79e174f72d275da /gst | |
parent | 50f12103f5a136f45bd274ac6a99006a3db5ca4d (diff) |
Imported Upstream version 0.11.92upstream/0.11.92
Diffstat (limited to 'gst')
-rw-r--r-- | gst/Makefile.in | 9 | ||||
-rw-r--r-- | gst/gst.c | 3 | ||||
-rw-r--r-- | gst/gst_private.h | 47 | ||||
-rw-r--r-- | gst/gstbin.c | 94 | ||||
-rw-r--r-- | gst/gstcaps.c | 2 | ||||
-rw-r--r-- | gst/gstcompat.h | 2 | ||||
-rw-r--r-- | gst/gstdebugutils.c | 2 | ||||
-rw-r--r-- | gst/gstelement.c | 48 | ||||
-rw-r--r-- | gst/gstelementfactory.c | 34 | ||||
-rw-r--r-- | gst/gstelementfactory.h | 41 | ||||
-rw-r--r-- | gst/gstevent.c | 36 | ||||
-rw-r--r-- | gst/gstevent.h | 6 | ||||
-rw-r--r-- | gst/gstmessage.c | 24 | ||||
-rw-r--r-- | gst/gstpad.c | 139 | ||||
-rw-r--r-- | gst/gstpad.h | 20 | ||||
-rw-r--r-- | gst/gstpluginfeature.c | 20 | ||||
-rw-r--r-- | gst/gstpluginfeature.h | 33 | ||||
-rw-r--r-- | gst/gstquark.c | 6 | ||||
-rw-r--r-- | gst/gstquark.h | 14 | ||||
-rw-r--r-- | gst/gstquery.c | 6 | ||||
-rw-r--r-- | gst/gstregistry.c | 2 | ||||
-rw-r--r-- | gst/gststructure.c | 2 | ||||
-rw-r--r-- | gst/gsttaglist.c | 446 | ||||
-rw-r--r-- | gst/gsttaglist.h | 123 | ||||
-rw-r--r-- | gst/gsttagsetter.c | 4 | ||||
-rw-r--r-- | gst/gsttoc.c | 271 | ||||
-rw-r--r-- | gst/gsttoc.h | 10 | ||||
-rw-r--r-- | gst/gsturi.c | 3 | ||||
-rw-r--r-- | gst/gstutils.c | 7 | ||||
-rw-r--r-- | gst/parse/Makefile.in | 9 |
30 files changed, 914 insertions, 549 deletions
diff --git a/gst/Makefile.in b/gst/Makefile.in index 008347b..2e6f45d 100644 --- a/gst/Makefile.in +++ b/gst/Makefile.in @@ -53,6 +53,7 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ +target_triplet = @target@ @HAVE_INTROSPECTION_TRUE@am__append_1 = $(BUILT_GIRSOURCES) $(typelibs_DATA) subdir = gst DIST_COMMON = $(libgstreamer_@GST_API_VERSION@include_HEADERS) \ @@ -412,6 +413,10 @@ GST_VERSION_MICRO = @GST_VERSION_MICRO@ GST_VERSION_MINOR = @GST_VERSION_MINOR@ GST_VERSION_NANO = @GST_VERSION_NANO@ GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ HAVE_DOCBOOK2HTML = @HAVE_DOCBOOK2HTML@ HAVE_DOCBOOK2PS = @HAVE_DOCBOOK2PS@ HAVE_DVIPS = @HAVE_DVIPS@ @@ -564,7 +569,11 @@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ +target = @target@ target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ @@ -139,7 +139,7 @@ extern gboolean _priv_gst_disable_registry_update; #endif #ifndef GST_DISABLE_GST_DEBUG -extern const gchar *priv_gst_dump_dot_dir; +const gchar *priv_gst_dump_dot_dir; #endif /* defaults */ @@ -746,7 +746,6 @@ init_post (GOptionContext * context, GOptionGroup * group, gpointer data, g_type_class_ref (gst_param_spec_fraction_get_type ()); _priv_gst_tag_initialize (); - _priv_gst_toc_initialize (); gst_parse_context_get_type (); _priv_gst_plugin_initialize (); diff --git a/gst/gst_private.h b/gst/gst_private.h index f44c6f3..c15c8fa 100644 --- a/gst/gst_private.h +++ b/gst/gst_private.h @@ -113,7 +113,6 @@ void _priv_gst_sample_initialize (void); void _priv_gst_tag_initialize (void); void _priv_gst_value_initialize (void); void _priv_gst_debug_init (void); -void _priv_gst_toc_initialize (void); /* TOC functions */ /* These functions are used to parse TOC messages, events and queries */ @@ -296,6 +295,27 @@ struct _GstPluginClass { gpointer _gst_reserved[GST_PADDING]; }; +struct _GstPluginFeature { + GstObject object; + + /*< private >*/ + gboolean loaded; + guint rank; + + const gchar *plugin_name; + GstPlugin *plugin; /* weak ref */ + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstPluginFeatureClass { + GstObjectClass parent_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + #include "gsttypefind.h" struct _GstTypeFindFactory { @@ -319,6 +339,31 @@ struct _GstTypeFindFactoryClass { gpointer _gst_reserved[GST_PADDING]; }; +struct _GstElementFactory { + GstPluginFeature parent; + + GType type; /* unique GType of element or 0 if not loaded */ + + gpointer metadata; + + GList * staticpadtemplates; /* GstStaticPadTemplate list */ + guint numpadtemplates; + + /* URI interface stuff */ + GstURIType uri_type; + gchar ** uri_protocols; + + GList * interfaces; /* interface type names this element implements */ + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstElementFactoryClass { + GstPluginFeatureClass parent_class; + + gpointer _gst_reserved[GST_PADDING]; +}; G_END_DECLS #endif /* __GST_PRIVATE_H__ */ diff --git a/gst/gstbin.c b/gst/gstbin.c index 665259e..d5ce5f6 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -2152,7 +2152,7 @@ gst_bin_element_set_state (GstBin * bin, GstElement * element, GstState next) { GstStateChangeReturn ret; - GstState pending, child_current, child_pending; + GstState child_current, child_pending; gboolean locked; GList *found; @@ -2182,17 +2182,76 @@ gst_bin_element_set_state (GstBin * bin, GstElement * element, goto no_preroll; } - GST_OBJECT_LOCK (bin); - pending = GST_STATE_PENDING (bin); + GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, + "current %s pending %s, desired next %s", + gst_element_state_get_name (child_current), + gst_element_state_get_name (child_pending), + gst_element_state_get_name (next)); /* Try not to change the state of elements that are already in the state we're * going to */ - if (!(next == GST_STATE_PLAYING || child_pending != GST_STATE_VOID_PENDING || - (child_pending == GST_STATE_VOID_PENDING && - ((pending > child_current && next > child_current) || - (pending < child_current && next < child_current))))) + if (child_current == next && child_pending == GST_STATE_VOID_PENDING) { + /* child is already at the requested state, return previous return. Note that + * if the child has a pending state to next, we will still call the + * set_state function */ goto unneeded; + } else if (next > current) { + /* upward state change */ + if (child_pending == GST_STATE_VOID_PENDING) { + /* .. and the child is not busy doing anything */ + if (child_current > next) { + /* .. and is already past the requested state, assume it got there + * without error */ + ret = GST_STATE_CHANGE_SUCCESS; + goto unneeded; + } + } else if (child_pending > child_current) { + /* .. and the child is busy going upwards */ + if (child_current >= next) { + /* .. and is already past the requested state, assume it got there + * without error */ + ret = GST_STATE_CHANGE_SUCCESS; + goto unneeded; + } + } else { + /* .. and the child is busy going downwards */ + if (child_current > next) { + /* .. and is already past the requested state, assume it got there + * without error */ + ret = GST_STATE_CHANGE_SUCCESS; + goto unneeded; + } + } + } else if (next < current) { + /* downward state change */ + if (child_pending == GST_STATE_VOID_PENDING) { + /* .. and the child is not busy doing anything */ + if (child_current < next) { + /* .. and is already past the requested state, assume it got there + * without error */ + ret = GST_STATE_CHANGE_SUCCESS; + goto unneeded; + } + } else if (child_pending < child_current) { + /* .. and the child is busy going downwards */ + if (child_current <= next) { + /* .. and is already past the requested state, assume it got there + * without error */ + ret = GST_STATE_CHANGE_SUCCESS; + goto unneeded; + } + } else { + /* .. and the child is busy going upwards */ + if (child_current < next) { + /* .. and is already past the requested state, assume it got there + * without error */ + ret = GST_STATE_CHANGE_SUCCESS; + goto unneeded; + } + } + } + GST_OBJECT_LOCK (bin); /* the element was busy with an upwards async state change, we must wait for * an ASYNC_DONE message before we attemp to change the state. */ if ((found = @@ -2234,25 +2293,22 @@ locked: GST_STATE_UNLOCK (element); return ret; } -was_busy: - { - GST_DEBUG_OBJECT (element, "element was busy, delaying state change"); - GST_OBJECT_UNLOCK (bin); - GST_STATE_UNLOCK (element); - return GST_STATE_CHANGE_ASYNC; - } unneeded: { GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, - "skipping transition from %s to %s, since bin pending" - " is %s : last change state return follows", + "skipping transition from %s to %s", gst_element_state_get_name (child_current), - gst_element_state_get_name (next), - gst_element_state_get_name (pending)); - GST_OBJECT_UNLOCK (bin); + gst_element_state_get_name (next)); GST_STATE_UNLOCK (element); return ret; } +was_busy: + { + GST_DEBUG_OBJECT (element, "element was busy, delaying state change"); + GST_OBJECT_UNLOCK (bin); + GST_STATE_UNLOCK (element); + return GST_STATE_CHANGE_ASYNC; + } } /* gst_iterator_fold functions for pads_activate diff --git a/gst/gstcaps.c b/gst/gstcaps.c index 2f4a341..ec95ed5 100644 --- a/gst/gstcaps.c +++ b/gst/gstcaps.c @@ -177,7 +177,7 @@ _gst_caps_free (GstCaps * caps) g_ptr_array_free (GST_CAPS_ARRAY (caps), TRUE); #ifdef DEBUG_REFCOUNT - GST_CAT_LOG (GST_CAT_CAPS, "freeing caps %p", caps); + GST_CAT_TRACE (GST_CAT_CAPS, "freeing caps %p", caps); #endif g_slice_free1 (GST_MINI_OBJECT_SIZE (caps), caps); } diff --git a/gst/gstcompat.h b/gst/gstcompat.h index a35c6ce..97728f4 100644 --- a/gst/gstcompat.h +++ b/gst/gstcompat.h @@ -56,6 +56,8 @@ G_BEGIN_DECLS #define gst_adapter_prev_timestamp gst_adapter_prev_pts +#define gst_tag_list_free(taglist) gst_tag_list_unref(taglist) + #ifndef GST_DISABLE_DEPRECATED #endif /* not GST_DISABLE_DEPRECATED */ diff --git a/gst/gstdebugutils.c b/gst/gstdebugutils.c index 8e31bde..e67a77c 100644 --- a/gst/gstdebugutils.c +++ b/gst/gstdebugutils.c @@ -54,7 +54,7 @@ /*** PIPELINE GRAPHS **********************************************************/ -const gchar *priv_gst_dump_dot_dir; /* NULL *//* set from gst.c */ +extern const gchar *priv_gst_dump_dot_dir; /* NULL *//* set from gst.c */ const gchar spaces[] = { " " /* 32 */ diff --git a/gst/gstelement.c b/gst/gstelement.c index b3366f4..2962830 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -325,7 +325,7 @@ gst_element_release_request_pad (GstElement * element, GstPad * pad) /* if the element implements a custom release function we call that, else we * simply remove the pad from the element */ if (oclass->release_pad) - (oclass->release_pad) (element, pad); + oclass->release_pad (element, pad); else gst_element_remove_pad (element, pad); } @@ -1523,9 +1523,10 @@ gst_element_default_send_event (GstElement * element, GstEvent * event) * This function takes owership of the provided event so you should * gst_event_ref() it if you want to reuse the event after this call. * - * Returns: %TRUE if the event was handled. - * * MT safe. + * + * Returns: %TRUE if the event was handled. Events that trigger a preroll (such + * as flushing seeks and steps) will emit %GST_MESSAGE_ASYNC_DONE. */ gboolean gst_element_send_event (GstElement * element, GstEvent * event) @@ -1564,9 +1565,10 @@ gst_element_send_event (GstElement * element, GstEvent * event) * the parameters. The seek event is sent to the element using * gst_element_send_event(). * - * Returns: %TRUE if the event was handled. - * * MT safe. + * + * Returns: %TRUE if the event was handled. Flushing seeks will trigger a + * preroll, which will emit %GST_MESSAGE_ASYNC_DONE. */ gboolean gst_element_seek (GstElement * element, gdouble rate, GstFormat format, @@ -2826,6 +2828,7 @@ gst_element_dispose (GObject * object) GstClock **clock_p; GstBus **bus_p; GstElementClass *oclass; + GList *walk; oclass = GST_ELEMENT_GET_CLASS (element); @@ -2834,23 +2837,32 @@ gst_element_dispose (GObject * object) if (GST_STATE (element) != GST_STATE_NULL) goto not_null; - GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element, - "removing %d pads", g_list_length (element->pads)); - /* first we break all our links with the outside */ - while (element->pads && element->pads->data) { - GstPad *pad = GST_PAD_CAST (element->pads->data); + /* start by releasing all request pads, this might also remove some dynamic + * pads */ + walk = element->pads; + while (walk) { + GstPad *pad = GST_PAD_CAST (walk->data); + + walk = walk->next; - /* don't call _remove_pad with NULL */ if (oclass->release_pad && GST_PAD_PAD_TEMPLATE (pad) && GST_PAD_TEMPLATE_PRESENCE (GST_PAD_PAD_TEMPLATE (pad)) - == GST_PAD_REQUEST) - (oclass->release_pad) (element, GST_PAD_CAST (element->pads->data)); - else - gst_element_remove_pad (element, GST_PAD_CAST (element->pads->data)); + == GST_PAD_REQUEST) { + GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element, + "removing request pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + oclass->release_pad (element, pad); + } } - if (G_UNLIKELY (element->pads != NULL)) { - g_critical ("could not remove pads from element %s", - GST_STR_NULL (GST_OBJECT_NAME (object))); + /* remove the remaining pads */ + while (element->pads) { + GstPad *pad = GST_PAD_CAST (element->pads->data); + GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element, + "removing pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + if (!gst_element_remove_pad (element, pad)) { + /* only happens when someone unparented our pad.. */ + g_critical ("failed to remove pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + break; + } } GST_OBJECT_LOCK (element); diff --git a/gst/gstelementfactory.c b/gst/gstelementfactory.c index b11abfc..a8ef9fe 100644 --- a/gst/gstelementfactory.c +++ b/gst/gstelementfactory.c @@ -510,6 +510,40 @@ gst_element_factory_get_metadata (GstElementFactory * factory, } /** + * gst_element_factory_get_metadata_keys: + * @factory,: a #GstElementFactory + * + * Get the available keys for the metadata on @factory. + * + * Returns: a %NULL-terminated array of key strings, or %NULL when + * there is no metadata. Free with g_strfreev() when no longer needd. + */ +gchar ** +gst_element_factory_get_metadata_keys (GstElementFactory * factory) +{ + GstStructure *metadata; + gchar **arr; + gint i, num; + + g_return_val_if_fail (GST_IS_ELEMENT_FACTORY (factory), NULL); + + metadata = (GstStructure *) factory->metadata; + if (metadata == NULL) + return NULL; + + num = gst_structure_n_fields (metadata); + if (num == 0) + return NULL; + + arr = g_new (gchar *, num + 1); + for (i = 0; i < num; ++i) { + arr[i] = g_strdup (gst_structure_nth_field_name (metadata, i)); + } + arr[i] = NULL; + return arr; +} + +/** * gst_element_factory_get_num_pad_templates: * @factory: a #GstElementFactory * diff --git a/gst/gstelementfactory.h b/gst/gstelementfactory.h index b2dff92..601c9d6 100644 --- a/gst/gstelementfactory.h +++ b/gst/gstelementfactory.h @@ -24,16 +24,19 @@ #ifndef __GST_ELEMENT_FACTORY_H__ #define __GST_ELEMENT_FACTORY_H__ +/** + * GstElementFactory: + * + * The opaque #GstElementFactory data structure. + */ typedef struct _GstElementFactory GstElementFactory; typedef struct _GstElementFactoryClass GstElementFactoryClass; #include <gst/gstconfig.h> #include <gst/gstelement.h> -#include <gst/gstobject.h> +#include <gst/gstpad.h> #include <gst/gstplugin.h> #include <gst/gstpluginfeature.h> -#include <gst/gstpadtemplate.h> -#include <gst/gstiterator.h> #include <gst/gsturi.h> G_BEGIN_DECLS @@ -47,37 +50,6 @@ G_BEGIN_DECLS #define GST_IS_ELEMENT_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ELEMENT_FACTORY)) #define GST_ELEMENT_FACTORY_CAST(obj) ((GstElementFactory *)(obj)) -/** - * GstElementFactory: - * - * The opaque #GstElementFactory data structure. - */ -struct _GstElementFactory { - GstPluginFeature parent; - - GType type; /* unique GType of element or 0 if not loaded */ - - gpointer metadata; - - GList * staticpadtemplates; /* GstStaticPadTemplate list */ - guint numpadtemplates; - - /* URI interface stuff */ - GstURIType uri_type; - gchar ** uri_protocols; - - GList * interfaces; /* interface type names this element implements */ - - /*< private >*/ - gpointer _gst_reserved[GST_PADDING]; -}; - -struct _GstElementFactoryClass { - GstPluginFeatureClass parent_class; - - gpointer _gst_reserved[GST_PADDING]; -}; - GType gst_element_factory_get_type (void); GstElementFactory * gst_element_factory_find (const gchar *name); @@ -85,6 +57,7 @@ GstElementFactory * gst_element_factory_find (const gchar *na GType gst_element_factory_get_element_type (GstElementFactory *factory); const gchar * gst_element_factory_get_metadata (GstElementFactory *factory, const gchar *key); +gchar ** gst_element_factory_get_metadata_keys (GstElementFactory *factory); guint gst_element_factory_get_num_pad_templates (GstElementFactory *factory); const GList * gst_element_factory_get_static_pad_templates (GstElementFactory *factory); diff --git a/gst/gstevent.c b/gst/gstevent.c index e496f40..3ba388a 100644 --- a/gst/gstevent.c +++ b/gst/gstevent.c @@ -992,19 +992,30 @@ 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. + * * Returns: (transfer full): a new #GstEvent */ GstEvent * -gst_event_new_tag (GstTagList * taglist) +gst_event_new_tag (const gchar * name, GstTagList * taglist) { + GstStructure *s; + GValue val = G_VALUE_INIT; + g_return_val_if_fail (taglist != NULL, NULL); - return gst_event_new_custom (GST_EVENT_TAG, (GstStructure *) taglist); + s = gst_structure_new_empty (name); + g_value_init (&val, GST_TYPE_TAG_LIST); + g_value_take_boxed (&val, taglist); + gst_structure_id_take_value (s, GST_QUARK (TAGLIST), &val); + return gst_event_new_custom (GST_EVENT_TAG, s); } /** @@ -1020,11 +1031,16 @@ gst_event_new_tag (GstTagList * taglist) void gst_event_parse_tag (GstEvent * event, GstTagList ** taglist) { + const GValue *val; + g_return_if_fail (GST_IS_EVENT (event)); g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_TAG); + val = gst_structure_id_get_value (GST_EVENT_STRUCTURE (event), + GST_QUARK (TAGLIST)); + if (taglist) - *taglist = (GstTagList *) GST_EVENT_STRUCTURE (event); + *taglist = (GstTagList *) g_value_get_boxed (val); } /* buffersize event */ @@ -1252,13 +1268,13 @@ gst_event_parse_qos (GstEvent * event, GstQOSType * type, * from the newly configured start position. * * For negative rates, playback will start from the newly configured stop - * position (if any). If the stop position if updated, it must be different from - * -1 for negative rates. + * position (if any). If the stop position is updated, it must be different from + * -1 (#GST_CLOCK_TIME_NONE) for negative rates. * * It is not possible to seek relative to the current playback position, to do * this, PAUSE the pipeline, query the current playback position with * #GST_QUERY_POSITION and update the playback segment current position with a - * #GST_SEEK_TYPE_SET to the desired position. + * #GST_SEEK_TYPE_SET to the desired position. * * Returns: (transfer full): a new seek event. */ @@ -1539,19 +1555,22 @@ gst_event_new_reconfigure (void) /** * gst_event_new_sink_message: + * @name: a name for the event * @msg: (transfer none): the #GstMessage to be posted * * Create a new sink-message event. The purpose of the sink-message event is * to instruct a sink to post the message contained in the event synchronized * with the stream. * + * @name is used to store multiple sticky events on one pad. + * * Returns: (transfer full): a new #GstEvent * * Since: 0.10.26 */ /* FIXME 0.11: take ownership of msg for consistency? */ GstEvent * -gst_event_new_sink_message (GstMessage * msg) +gst_event_new_sink_message (const gchar * name, GstMessage * msg) { GstEvent *event; GstStructure *structure; @@ -1560,7 +1579,7 @@ gst_event_new_sink_message (GstMessage * msg) GST_CAT_INFO (GST_CAT_EVENT, "creating sink-message event"); - structure = gst_structure_new_id (GST_QUARK (EVENT_SINK_MESSAGE), + structure = gst_structure_new_id (g_quark_from_string (name), GST_QUARK (MESSAGE), GST_TYPE_MESSAGE, msg, NULL); event = gst_event_new_custom (GST_EVENT_SINK_MESSAGE, structure); @@ -1615,6 +1634,7 @@ gst_event_new_stream_start (void) /** * gst_event_new_toc: + * @name: a name for the event * @toc: #GstToc structure. * @updated: whether @toc was updated or not. * diff --git a/gst/gstevent.h b/gst/gstevent.h index b8609e9..35ebba8 100644 --- a/gst/gstevent.h +++ b/gst/gstevent.h @@ -152,7 +152,7 @@ typedef enum { GST_EVENT_BUFFERSIZE = GST_EVENT_MAKE_TYPE (90, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY)), GST_EVENT_SINK_MESSAGE = GST_EVENT_MAKE_TYPE (100, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY) | FLAG(STICKY_MULTI)), GST_EVENT_EOS = GST_EVENT_MAKE_TYPE (110, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY)), - GST_EVENT_TOC = GST_EVENT_MAKE_TYPE (120, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY) | FLAG(STICKY_MULTI)), + GST_EVENT_TOC = GST_EVENT_MAKE_TYPE (120, FLAG(DOWNSTREAM) | FLAG(SERIALIZED) | FLAG(STICKY)), /* non-sticky downstream serialized */ GST_EVENT_SEGMENT_DONE = GST_EVENT_MAKE_TYPE (150, FLAG(DOWNSTREAM) | FLAG(SERIALIZED)), @@ -523,7 +523,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 (GstTagList *taglist) G_GNUC_MALLOC; +GstEvent* gst_event_new_tag (const gchar *name, GstTagList *taglist) G_GNUC_MALLOC; void gst_event_parse_tag (GstEvent *event, GstTagList **taglist); /* TOC event */ @@ -538,7 +538,7 @@ void gst_event_parse_buffer_size (GstEvent *event, GstFormat *for gint64 *maxsize, gboolean *async); /* sink message */ -GstEvent* gst_event_new_sink_message (GstMessage *msg) G_GNUC_MALLOC; +GstEvent* gst_event_new_sink_message (const gchar *name, GstMessage *msg) G_GNUC_MALLOC; void gst_event_parse_sink_message (GstEvent *event, GstMessage **msg); /* QOS events */ diff --git a/gst/gstmessage.c b/gst/gstmessage.c index 6b8b2c0..4eef4ac 100644 --- a/gst/gstmessage.c +++ b/gst/gstmessage.c @@ -480,13 +480,17 @@ gst_message_new_info (GstObject * src, GError * error, const gchar * debug) GstMessage * gst_message_new_tag (GstObject * src, GstTagList * tag_list) { + GstStructure *s; GstMessage *message; + GValue val = G_VALUE_INIT; - g_return_val_if_fail (GST_IS_STRUCTURE (tag_list), NULL); - - message = - gst_message_new_custom (GST_MESSAGE_TAG, src, (GstStructure *) tag_list); + g_return_val_if_fail (GST_IS_TAG_LIST (tag_list), NULL); + s = gst_structure_new_id_empty (GST_QUARK (MESSAGE_TAG)); + g_value_init (&val, GST_TYPE_TAG_LIST); + g_value_take_boxed (&val, tag_list); + gst_structure_id_take_value (s, GST_QUARK (TAGLIST), &val); + message = gst_message_new_custom (GST_MESSAGE_TAG, src, s); return message; } @@ -1004,7 +1008,7 @@ gst_message_has_name (GstMessage * message, const gchar * name) * gst_message_parse_tag (msg, &tags); * g_print ("Got tags from element %s\n", GST_OBJECT_NAME (msg->src)); * handle_tags (tags); - * gst_tag_list_free (tags); + * gst_tag_list_unref (tags); * break; * } * ... @@ -1017,16 +1021,12 @@ gst_message_has_name (GstMessage * message, const gchar * name) void gst_message_parse_tag (GstMessage * message, GstTagList ** tag_list) { - GstStructure *ret; - g_return_if_fail (GST_IS_MESSAGE (message)); g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_TAG); g_return_if_fail (tag_list != NULL); - ret = gst_structure_copy (GST_MESSAGE_STRUCTURE (message)); - gst_structure_remove_field (ret, "source-pad"); - - *tag_list = (GstTagList *) ret; + gst_structure_id_get (GST_MESSAGE_STRUCTURE (message), + GST_QUARK (TAGLIST), GST_TYPE_TAG_LIST, tag_list, NULL); } /** @@ -2210,7 +2210,7 @@ gst_message_new_toc (GstObject * src, GstToc * toc, gboolean updated) * @toc: (out): return location for the TOC. * @updated: (out): return location for the updated flag. * - * Extract the TOC from the #GstMessage. The TOC returned in the + * Extract thef TOC from the #GstMessage. The TOC returned in the * output argument is a copy; the caller must free it with * gst_toc_free() when done. * diff --git a/gst/gstpad.c b/gst/gstpad.c index 0464209..73981f3 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -2637,12 +2637,6 @@ gst_pad_event_default (GstPad * pad, GstObject * parent, GstEvent * event) GST_LOG_OBJECT (pad, "default event handler"); switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_EOS: - { - GST_DEBUG_OBJECT (pad, "pausing task because of eos"); - gst_pad_pause_task (pad); - break; - } case GST_EVENT_CAPS: forward = GST_PAD_IS_PROXY_CAPS (pad); result = TRUE; @@ -3151,11 +3145,21 @@ done: GST_OBJECT_UNLOCK (pad); } +typedef struct +{ + GstFlowReturn ret; + + /* If TRUE and ret is not OK this means + * that pushing the EOS event failed + */ + gboolean was_eos; +} PushStickyData; + /* should be called with pad LOCK */ static gboolean push_sticky (GstPad * pad, PadEvent * ev, gpointer user_data) { - GstFlowReturn *data = user_data; + PushStickyData *data = user_data; GstEvent *event = ev->event; if (ev->received) { @@ -3164,10 +3168,10 @@ push_sticky (GstPad * pad, PadEvent * ev, gpointer user_data) return TRUE; } - *data = gst_pad_push_event_unchecked (pad, gst_event_ref (event), + data->ret = gst_pad_push_event_unchecked (pad, gst_event_ref (event), GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM); - switch (*data) { + switch (data->ret) { case GST_FLOW_OK: ev->received = TRUE; GST_DEBUG_OBJECT (pad, "event %s marked received", @@ -3175,16 +3179,21 @@ push_sticky (GstPad * pad, PadEvent * ev, gpointer user_data) break; case GST_FLOW_NOT_LINKED: /* not linked is not a problem, we are sticky so the event will be - * sent later */ + * sent later but only for non-EOS events */ GST_DEBUG_OBJECT (pad, "pad was not linked"); - *data = GST_FLOW_OK; + if (GST_EVENT_TYPE (event) != GST_EVENT_EOS) + data->ret = GST_FLOW_OK; /* fallthrough */ default: GST_DEBUG_OBJECT (pad, "mark pending events"); GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS); break; } - return *data == GST_FLOW_OK; + + if (data->ret != GST_FLOW_OK && GST_EVENT_TYPE (event) == GST_EVENT_EOS) + data->was_eos = TRUE; + + return data->ret == GST_FLOW_OK; } /* check sticky events and push them when needed. should be called @@ -3192,15 +3201,31 @@ push_sticky (GstPad * pad, PadEvent * ev, gpointer user_data) static inline GstFlowReturn check_sticky (GstPad * pad) { - GstFlowReturn ret = GST_FLOW_OK; + PushStickyData data = { GST_FLOW_OK, FALSE }; if (G_UNLIKELY (GST_PAD_HAS_PENDING_EVENTS (pad))) { GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_PENDING_EVENTS); GST_DEBUG_OBJECT (pad, "pushing all sticky events"); - events_foreach (pad, push_sticky, &ret); + events_foreach (pad, push_sticky, &data); + + /* If there's an EOS event we must push it downstream + * even if sending a previous sticky event failed. + * Otherwise the pipeline might wait forever for EOS. + * + * Only do this if pushing another event than the EOS + * event failed. + */ + if (data.ret != GST_FLOW_OK && !data.was_eos) { + PadEvent *ev = find_event_by_type (pad, GST_EVENT_EOS, 0); + + if (ev && !ev->received) { + data.ret = gst_pad_push_event_unchecked (pad, gst_event_ref (ev->event), + GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM); + } + } } - return ret; + return data.ret; } @@ -3473,6 +3498,9 @@ gst_pad_chain_data_unchecked (GstPad * pad, GstPadProbeType type, void *data) if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) goto flushing; + if (G_UNLIKELY (GST_PAD_IS_EOS (pad))) + goto eos; + if (G_UNLIKELY (GST_PAD_MODE (pad) != GST_PAD_MODE_PUSH)) goto wrong_mode; @@ -3534,6 +3562,14 @@ flushing: gst_mini_object_unref (GST_MINI_OBJECT_CAST (data)); return GST_FLOW_FLUSHING; } +eos: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "chaining, but pad was EOS"); + GST_OBJECT_UNLOCK (pad); + GST_PAD_STREAM_UNLOCK (pad); + gst_mini_object_unref (GST_MINI_OBJECT_CAST (data)); + return GST_FLOW_EOS; + } wrong_mode: { g_critical ("chain on pad %s:%s but it was not in push mode", @@ -3682,6 +3718,9 @@ gst_pad_push_data (GstPad * pad, GstPadProbeType type, void *data) if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) goto flushing; + if (G_UNLIKELY (GST_PAD_IS_EOS (pad))) + goto eos; + if (G_UNLIKELY (GST_PAD_MODE (pad) != GST_PAD_MODE_PUSH)) goto wrong_mode; @@ -3727,6 +3766,13 @@ flushing: gst_mini_object_unref (GST_MINI_OBJECT_CAST (data)); return GST_FLOW_FLUSHING; } +eos: + { + GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "pushing, but pad was EOS"); + GST_OBJECT_UNLOCK (pad); + gst_mini_object_unref (GST_MINI_OBJECT_CAST (data)); + return GST_FLOW_EOS; + } wrong_mode: { g_critical ("pushing on pad %s:%s but it was not activated in push mode", @@ -4289,6 +4335,7 @@ gst_pad_push_event_unchecked (GstPad * pad, GstEvent * event, /* Remove sticky EOS events */ GST_LOG_OBJECT (pad, "Removing pending EOS events"); remove_event_by_type (pad, GST_EVENT_EOS); + GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_EOS); type |= GST_PAD_PROBE_TYPE_EVENT_FLUSH; break; @@ -4297,6 +4344,11 @@ gst_pad_push_event_unchecked (GstPad * pad, GstEvent * event, if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) goto flushed; + /* No need to check for EOS here as either the caller (gst_pad_push_event()) + * checked already or this is called as part of pushing sticky events, + * in which case we still want to forward the EOS event downstream. + */ + switch (GST_EVENT_TYPE (event)) { case GST_EVENT_SEGMENT: /* pass the adjusted segment event on. We need to do this even if @@ -4378,6 +4430,11 @@ not_linked: GST_DEBUG_OBJECT (pad, "Dropping event because pad is not linked"); GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS); gst_event_unref (event); + + /* unlinked pads should not influence latency configuration */ + if (event_type == GST_EVENT_LATENCY) + return GST_FLOW_OK; + return GST_FLOW_NOT_LINKED; } idle_probe_stopped: @@ -4406,7 +4463,7 @@ idle_probe_stopped: gboolean gst_pad_push_event (GstPad * pad, GstEvent * event) { - gboolean res; + gboolean res = FALSE; GstPadProbeType type; gboolean sticky, serialized; @@ -4434,12 +4491,17 @@ gst_pad_push_event (GstPad * pad, GstEvent * event) if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) goto flushed; + if (G_UNLIKELY (GST_PAD_IS_EOS (pad))) + goto eos; + /* srcpad sticky events are store immediately, the received flag is set * to FALSE and will be set to TRUE when we can successfully push the * event to the peer pad */ if (gst_pad_store_sticky_event (pad, event, TRUE)) { GST_DEBUG_OBJECT (pad, "event %s updated", GST_EVENT_TYPE_NAME (event)); } + if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) + GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_EOS); } if (GST_PAD_IS_SRC (pad) && (serialized || sticky)) { /* all serialized or sticky events on the srcpad trigger push of @@ -4450,8 +4512,14 @@ gst_pad_push_event (GstPad * pad, GstEvent * event) /* other events are pushed right away */ res = (gst_pad_push_event_unchecked (pad, event, type) == GST_FLOW_OK); } else { + /* Errors in sticky event pushing are no problem and ignored here + * as they will cause more meaningful errors during data flow. + * For EOS events, that are not followed by data flow, we still + * return FALSE here though. + */ + if (GST_EVENT_TYPE (event) != GST_EVENT_EOS) + res = TRUE; gst_event_unref (event); - res = TRUE; } GST_OBJECT_UNLOCK (pad); @@ -4478,13 +4546,20 @@ flushed: gst_event_unref (event); return FALSE; } +eos: + { + GST_DEBUG_OBJECT (pad, "We're EOS"); + GST_OBJECT_UNLOCK (pad); + gst_event_unref (event); + return FALSE; + } } /* Check if we can call the event function with the given event */ static GstFlowReturn pre_eventfunc_check (GstPad * pad, GstEvent * event) { - GstCaps *caps, *templ; + GstCaps *caps; switch (GST_EVENT_TYPE (event)) { case GST_EVENT_CAPS: @@ -4492,12 +4567,8 @@ pre_eventfunc_check (GstPad * pad, GstEvent * event) /* backwards compatibility mode for caps */ gst_event_parse_caps (event, &caps); - /* See if pad accepts the caps */ - templ = gst_pad_get_pad_template_caps (pad); - if (!gst_caps_is_subset (caps, templ)) + if (!gst_pad_query_accept_caps (pad, caps)) goto not_accepted; - - gst_caps_unref (templ); break; } default: @@ -4508,11 +4579,8 @@ pre_eventfunc_check (GstPad * pad, GstEvent * event) /* ERRORS */ not_accepted: { - gst_caps_unref (templ); GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "caps %" GST_PTR_FORMAT " not accepted", caps); - GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, - "no intersection with template %" GST_PTR_FORMAT, templ); return GST_FLOW_NOT_NEGOTIATED; } } @@ -4554,6 +4622,7 @@ gst_pad_send_event_unchecked (GstPad * pad, GstEvent * event, /* Remove pending EOS events */ GST_LOG_OBJECT (pad, "Removing pending EOS events"); remove_event_by_type (pad, GST_EVENT_EOS); + GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_EOS); GST_OBJECT_UNLOCK (pad); /* grab stream lock */ @@ -4574,6 +4643,9 @@ gst_pad_send_event_unchecked (GstPad * pad, GstEvent * event, goto flushing; if (serialized) { + if (G_UNLIKELY (GST_PAD_IS_EOS (pad))) + goto eos; + /* lock order: STREAM_LOCK, LOCK, recheck flushing. */ GST_OBJECT_UNLOCK (pad); GST_PAD_STREAM_LOCK (pad); @@ -4581,6 +4653,9 @@ gst_pad_send_event_unchecked (GstPad * pad, GstEvent * event, GST_OBJECT_LOCK (pad); if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) goto flushing; + + if (G_UNLIKELY (GST_PAD_IS_EOS (pad))) + goto eos; } switch (GST_EVENT_TYPE (event)) { @@ -4635,6 +4710,8 @@ gst_pad_send_event_unchecked (GstPad * pad, GstEvent * event, /* after the event function accepted the event, we can store the sticky * event on the pad */ gst_pad_store_sticky_event (pad, event, FALSE); + if (event_type == GST_EVENT_EOS) + GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_EOS); } gst_event_unref (event); } @@ -4655,6 +4732,16 @@ flushing: gst_event_unref (event); return GST_FLOW_FLUSHING; } +eos: + { + GST_OBJECT_UNLOCK (pad); + if (need_unlock) + GST_PAD_STREAM_UNLOCK (pad); + GST_CAT_INFO_OBJECT (GST_CAT_EVENT, pad, + "Received event on EOS pad. Discarding"); + gst_event_unref (event); + return GST_FLOW_EOS; + } probe_stopped: { GST_OBJECT_UNLOCK (pad); diff --git a/gst/gstpad.h b/gst/gstpad.h index df66794..4e93f07 100644 --- a/gst/gstpad.h +++ b/gst/gstpad.h @@ -590,7 +590,8 @@ typedef gboolean (*GstPadStickyEventsForeachFunction) (GstPad *pad, GstEvent ** /** * GstPadFlags: * @GST_PAD_FLAG_BLOCKED: is dataflow on a pad blocked - * @GST_PAD_FLAG_FLUSHING: is pad refusing buffers + * @GST_PAD_FLAG_FLUSHING: is pad flushing + * @GST_PAD_FLAG_EOS: is pad in EOS state * @GST_PAD_FLAG_BLOCKING: is pad currently blocking on a buffer or event * @GST_PAD_FLAG_NEED_PARENT: ensure that there is a parent object before calling * into the pad callbacks. @@ -614,13 +615,14 @@ typedef gboolean (*GstPadStickyEventsForeachFunction) (GstPad *pad, GstEvent ** typedef enum { GST_PAD_FLAG_BLOCKED = (GST_OBJECT_FLAG_LAST << 0), GST_PAD_FLAG_FLUSHING = (GST_OBJECT_FLAG_LAST << 1), - GST_PAD_FLAG_BLOCKING = (GST_OBJECT_FLAG_LAST << 2), - GST_PAD_FLAG_NEED_PARENT = (GST_OBJECT_FLAG_LAST << 3), - GST_PAD_FLAG_NEED_RECONFIGURE = (GST_OBJECT_FLAG_LAST << 4), - GST_PAD_FLAG_PENDING_EVENTS = (GST_OBJECT_FLAG_LAST << 5), - GST_PAD_FLAG_FIXED_CAPS = (GST_OBJECT_FLAG_LAST << 6), - GST_PAD_FLAG_PROXY_CAPS = (GST_OBJECT_FLAG_LAST << 7), - GST_PAD_FLAG_PROXY_ALLOCATION = (GST_OBJECT_FLAG_LAST << 8), + GST_PAD_FLAG_EOS = (GST_OBJECT_FLAG_LAST << 2), + GST_PAD_FLAG_BLOCKING = (GST_OBJECT_FLAG_LAST << 3), + GST_PAD_FLAG_NEED_PARENT = (GST_OBJECT_FLAG_LAST << 4), + GST_PAD_FLAG_NEED_RECONFIGURE = (GST_OBJECT_FLAG_LAST << 5), + GST_PAD_FLAG_PENDING_EVENTS = (GST_OBJECT_FLAG_LAST << 6), + GST_PAD_FLAG_FIXED_CAPS = (GST_OBJECT_FLAG_LAST << 7), + GST_PAD_FLAG_PROXY_CAPS = (GST_OBJECT_FLAG_LAST << 8), + GST_PAD_FLAG_PROXY_ALLOCATION = (GST_OBJECT_FLAG_LAST << 9), /* padding */ GST_PAD_FLAG_LAST = (GST_OBJECT_FLAG_LAST << 16) } GstPadFlags; @@ -755,6 +757,8 @@ struct _GstPadClass { #define GST_PAD_SET_FLUSHING(pad) (GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_FLUSHING)) #define GST_PAD_UNSET_FLUSHING(pad) (GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_FLUSHING)) +#define GST_PAD_IS_EOS(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_EOS)) + #define GST_PAD_NEEDS_RECONFIGURE(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_NEED_RECONFIGURE)) #define GST_PAD_HAS_PENDING_EVENTS(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_PENDING_EVENTS)) #define GST_PAD_IS_FIXED_CAPS(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_FIXED_CAPS)) diff --git a/gst/gstpluginfeature.c b/gst/gstpluginfeature.c index e61fee2..3e1228e 100644 --- a/gst/gstpluginfeature.c +++ b/gst/gstpluginfeature.c @@ -180,6 +180,26 @@ gst_plugin_feature_get_rank (GstPluginFeature * feature) } /** + * gst_plugin_feature_get_plugin: + * @feature: a feature + * + * Get the plugin that provides this feature. + * + * Returns: (transfer full): the plugin that provides this feature, or %NULL. + * Unref with gst_object_unref() when no longer needed. + */ +GstPlugin * +gst_plugin_feature_get_plugin (GstPluginFeature * feature) +{ + g_return_val_if_fail (GST_IS_PLUGIN_FEATURE (feature), NULL); + + if (feature->plugin == NULL) + return NULL; + + return (GstPlugin *) gst_object_ref (feature->plugin); +} + +/** * gst_plugin_feature_list_free: * @list: (transfer full) (element-type Gst.PluginFeature): list * of #GstPluginFeature diff --git a/gst/gstpluginfeature.h b/gst/gstpluginfeature.h index b99d9ee..a372281 100644 --- a/gst/gstpluginfeature.h +++ b/gst/gstpluginfeature.h @@ -38,6 +38,11 @@ G_BEGIN_DECLS #define GST_PLUGIN_FEATURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_PLUGIN_FEATURE, GstPluginFeatureClass)) #define GST_PLUGIN_FEATURE_CAST(obj) ((GstPluginFeature*)(obj)) +/** + * GstPluginFeature: + * + * Opaque #GstPluginFeature structure. + */ typedef struct _GstPluginFeature GstPluginFeature; typedef struct _GstPluginFeatureClass GstPluginFeatureClass; @@ -85,32 +90,6 @@ typedef enum { #define gst_plugin_feature_set_name(feature,name) gst_object_set_name(GST_OBJECT_CAST(feature),name) /** - * GstPluginFeature: - * - * Opaque #GstPluginFeature structure. - */ -struct _GstPluginFeature { - GstObject object; - - /*< private >*/ - gboolean loaded; - guint rank; - - const gchar *plugin_name; - GstPlugin *plugin; /* weak ref */ - - /*< private >*/ - gpointer _gst_reserved[GST_PADDING]; -}; - -struct _GstPluginFeatureClass { - GstObjectClass parent_class; - - /*< private >*/ - gpointer _gst_reserved[GST_PADDING]; -}; - -/** * GstPluginFeatureFilter: * @feature: the pluginfeature to check * @user_data: the user_data that has been passed on e.g. @@ -133,6 +112,8 @@ GstPluginFeature * void gst_plugin_feature_set_rank (GstPluginFeature *feature, guint rank); guint gst_plugin_feature_get_rank (GstPluginFeature *feature); +GstPlugin * gst_plugin_feature_get_plugin (GstPluginFeature *feature); + void gst_plugin_feature_list_free (GList *list); GList *gst_plugin_feature_list_copy (GList *list) G_GNUC_MALLOC; void gst_plugin_feature_list_debug (GList *list); diff --git a/gst/gstquark.c b/gst/gstquark.c index d7b6b6d..2d55fa3 100644 --- a/gst/gstquark.c +++ b/gst/gstquark.c @@ -58,9 +58,11 @@ static const gchar *_quark_strings[] = { "allocator", "GstEventFlushStop", "options", "GstQueryAcceptCaps", "result", "GstQueryCaps", "filter", "modes", "GstEventStreamConfig", "setup-data", "stream-headers", "GstEventGap", "GstQueryDrain", "params", - "toc-select", "uid", "toc", GST_ELEMENT_METADATA_LONGNAME, + "GstEventTocSelect", "uid", "GstQueryToc", GST_ELEMENT_METADATA_LONGNAME, GST_ELEMENT_METADATA_KLASS, GST_ELEMENT_METADATA_DESCRIPTION, - GST_ELEMENT_METADATA_AUTHOR + GST_ELEMENT_METADATA_AUTHOR, "toc", "toc-entry", "updated", "extend-uid", + "uid", "tags", "sub-entries", "info", "info-structure", + "time-structure", "GstMessageTag", "GstEventTag" }; GQuark _priv_gst_quark_table[GST_QUARK_MAX]; diff --git a/gst/gstquark.h b/gst/gstquark.h index 8f8968f..969ce79 100644 --- a/gst/gstquark.h +++ b/gst/gstquark.h @@ -171,7 +171,19 @@ typedef enum _GstQuarkId GST_QUARK_ELEMENT_METADATA_KLASS = 142, GST_QUARK_ELEMENT_METADATA_DESCRIPTION = 143, GST_QUARK_ELEMENT_METADATA_AUTHOR = 144, - GST_QUARK_MAX = 145 + GST_QUARK_TOC = 145, + GST_QUARK_TOC_ENTRY = 146, + GST_QUARK_UPDATED = 147, + GST_QUARK_EXTEND_UID = 148, + GST_QUARK_TOC_UID = 149, + GST_QUARK_TAGS = 150, + GST_QUARK_SUB_ENTRIES = 151, + GST_QUARK_INFO = 152, + GST_QUARK_INFO_STRUCTURE = 153, + GST_QUARK_TIME_STRUCTURE = 154, + GST_QUARK_MESSAGE_TAG = 155, + GST_QUARK_EVENT_TAG = 156, + GST_QUARK_MAX = 157 } GstQuarkId; extern GQuark _priv_gst_quark_table[GST_QUARK_MAX]; diff --git a/gst/gstquery.c b/gst/gstquery.c index 4aaa17e..5fadc9d 100644 --- a/gst/gstquery.c +++ b/gst/gstquery.c @@ -2197,7 +2197,7 @@ gst_query_parse_accept_caps_result (GstQuery * query, gboolean * result) * * Constructs a new query object for querying the caps. * - * The CAPS query should return the* allowable caps for a pad in the context + * The CAPS query should return the allowable caps for a pad in the context * of the element's state, its link to other elements, and the devices or files * it has opened. These caps must be a subset of the pad template caps. In the * NULL state with no links, the CAPS query should ideally return the same caps @@ -2210,6 +2210,10 @@ gst_query_parse_accept_caps_result (GstQuery * query, gboolean * result) * the CAPS query should return the most specific caps it reasonably can, since this * helps with autoplugging. * + * The @filter is used to restrict the result caps, only the caps matching + * @filter should be returned from the CAPS query. Specifying a filter might + * greatly reduce the amount of processing an element needs to do. + * * Free-function: gst_query_unref * * Returns: (transfer full): a new #GstQuery diff --git a/gst/gstregistry.c b/gst/gstregistry.c index 0575709..c77cffe 100644 --- a/gst/gstregistry.c +++ b/gst/gstregistry.c @@ -1664,7 +1664,7 @@ ensure_current_registry (GError ** error) registry_file = g_strdup (g_getenv ("GST_REGISTRY")); if (registry_file == NULL) { registry_file = g_build_filename (g_get_user_cache_dir (), - "gstreamer-" GST_API_VERSION, "registry." HOST_CPU ".bin", NULL); + "gstreamer-" GST_API_VERSION, "registry." TARGET_CPU ".bin", NULL); } if (!_gst_disable_registry_cache) { diff --git a/gst/gststructure.c b/gst/gststructure.c index 8065b31..fdc65e1 100644 --- a/gst/gststructure.c +++ b/gst/gststructure.c @@ -1828,7 +1828,7 @@ priv_gst_structure_append_to_gstring (const GstStructure * structure, * * Free-function: g_free * - * Returns: (transfer full)L a pointer to string allocated by g_malloc(). + * Returns: (transfer full): a pointer to string allocated by g_malloc(). * g_free() after usage. */ gchar * diff --git a/gst/gsttaglist.c b/gst/gsttaglist.c index c1a2ab0..5658fe7 100644 --- a/gst/gsttaglist.c +++ b/gst/gsttaglist.c @@ -47,14 +47,22 @@ #include <gobject/gvaluecollector.h> #include <string.h> +/* FIXME: add category for tags */ +#define GST_CAT_TAGS GST_CAT_DEFAULT + #define GST_TAG_IS_VALID(tag) (gst_tag_get_info (tag) != NULL) /* FIXME 0.11: make taglists refcounted maybe? */ /* a tag list is basically a structure, but we don't make this fact public */ -struct _GstTagList +typedef struct _GstTagListImpl { - GstStructure structure; -}; + GstTagList taglist; + + GstStructure *structure; +} GstTagListImpl; + +#define GST_TAG_LIST_STRUCTURE(taglist) ((GstTagListImpl*)(taglist))->structure + /* FIXME 0.11: use GParamSpecs or something similar for tag registrations, * possibly even gst_tag_register(). Especially value ranges might be @@ -64,8 +72,8 @@ typedef struct { GType type; /* type the data is in */ - gchar *nick; /* translated name */ - gchar *blurb; /* translated description of type */ + const gchar *nick; /* translated short description */ + const gchar *blurb; /* translated long description */ GstTagMergeFunc merge_func; /* functions to merge the values */ GstTagFlag flag; /* type of tag */ @@ -82,298 +90,307 @@ static GMutex __tag_mutex; /* tags hash table: maps tag name string => GstTagInfo */ static GHashTable *__tags; -G_DEFINE_BOXED_TYPE (GstTagList, gst_tag_list, - (GBoxedCopyFunc) gst_tag_list_copy, (GBoxedFreeFunc) gst_tag_list_free); +GST_DEFINE_MINI_OBJECT_TYPE (GstTagList, gst_tag_list); + +static void __gst_tag_list_free (GstTagList * list); +static GstTagList *__gst_tag_list_copy (const GstTagList * list); /* FIXME: had code: * g_value_register_transform_func (_gst_tag_list_type, G_TYPE_STRING, * _gst_structure_transform_to_string); */ - void _priv_gst_tag_initialize (void) { g_mutex_init (&__tag_mutex); __tags = g_hash_table_new (g_str_hash, g_str_equal); - gst_tag_register (GST_TAG_TITLE, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_TITLE, GST_TAG_FLAG_META, G_TYPE_STRING, _("title"), _("commonly used title"), gst_tag_merge_strings_with_comma); - gst_tag_register (GST_TAG_TITLE_SORTNAME, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_TITLE_SORTNAME, GST_TAG_FLAG_META, G_TYPE_STRING, _("title sortname"), _("commonly used title for sorting purposes"), NULL); - gst_tag_register (GST_TAG_ARTIST, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_ARTIST, GST_TAG_FLAG_META, G_TYPE_STRING, _("artist"), _("person(s) responsible for the recording"), gst_tag_merge_strings_with_comma); - gst_tag_register (GST_TAG_ARTIST_SORTNAME, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_ARTIST_SORTNAME, GST_TAG_FLAG_META, G_TYPE_STRING, _("artist sortname"), _("person(s) responsible for the recording for sorting purposes"), NULL); - gst_tag_register (GST_TAG_ALBUM, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_ALBUM, GST_TAG_FLAG_META, G_TYPE_STRING, _("album"), _("album containing this data"), gst_tag_merge_strings_with_comma); - gst_tag_register (GST_TAG_ALBUM_SORTNAME, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_ALBUM_SORTNAME, GST_TAG_FLAG_META, G_TYPE_STRING, _("album sortname"), _("album containing this data for sorting purposes"), NULL); - gst_tag_register (GST_TAG_ALBUM_ARTIST, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_ALBUM_ARTIST, GST_TAG_FLAG_META, G_TYPE_STRING, _("album artist"), _("The artist of the entire album, as it should be displayed"), gst_tag_merge_strings_with_comma); - gst_tag_register (GST_TAG_ALBUM_ARTIST_SORTNAME, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_ALBUM_ARTIST_SORTNAME, GST_TAG_FLAG_META, G_TYPE_STRING, _("album artist sortname"), _("The artist of the entire album, as it should be sorted"), NULL); - gst_tag_register (GST_TAG_DATE, GST_TAG_FLAG_META, G_TYPE_DATE, + gst_tag_register_static (GST_TAG_DATE, GST_TAG_FLAG_META, G_TYPE_DATE, _("date"), _("date the data was created (as a GDate structure)"), NULL); - gst_tag_register (GST_TAG_DATE_TIME, GST_TAG_FLAG_META, GST_TYPE_DATE_TIME, - _("datetime"), + gst_tag_register_static (GST_TAG_DATE_TIME, GST_TAG_FLAG_META, + GST_TYPE_DATE_TIME, _("datetime"), _("date and time the data was created (as a GstDateTime structure)"), NULL); - gst_tag_register (GST_TAG_GENRE, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_GENRE, GST_TAG_FLAG_META, G_TYPE_STRING, _("genre"), _("genre this data belongs to"), gst_tag_merge_strings_with_comma); - gst_tag_register (GST_TAG_COMMENT, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_COMMENT, GST_TAG_FLAG_META, G_TYPE_STRING, _("comment"), _("free text commenting the data"), gst_tag_merge_use_first); - gst_tag_register (GST_TAG_EXTENDED_COMMENT, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_EXTENDED_COMMENT, GST_TAG_FLAG_META, G_TYPE_STRING, _("extended comment"), _("free text commenting the data in key=value or key[en]=comment form"), gst_tag_merge_use_first); - gst_tag_register (GST_TAG_TRACK_NUMBER, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_TRACK_NUMBER, GST_TAG_FLAG_META, G_TYPE_UINT, _("track number"), _("track number inside a collection"), gst_tag_merge_use_first); - gst_tag_register (GST_TAG_TRACK_COUNT, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_TRACK_COUNT, GST_TAG_FLAG_META, G_TYPE_UINT, _("track count"), _("count of tracks inside collection this track belongs to"), gst_tag_merge_use_first); - gst_tag_register (GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_FLAG_META, G_TYPE_UINT, _("disc number"), _("disc number inside a collection"), gst_tag_merge_use_first); - gst_tag_register (GST_TAG_ALBUM_VOLUME_COUNT, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_ALBUM_VOLUME_COUNT, GST_TAG_FLAG_META, G_TYPE_UINT, _("disc count"), _("count of discs inside collection this disc belongs to"), gst_tag_merge_use_first); - gst_tag_register (GST_TAG_LOCATION, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_LOCATION, GST_TAG_FLAG_META, G_TYPE_STRING, _("location"), _("Origin of media as a URI (location, where the " "original of the file or stream is hosted)"), gst_tag_merge_strings_with_comma); - gst_tag_register (GST_TAG_HOMEPAGE, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_HOMEPAGE, GST_TAG_FLAG_META, G_TYPE_STRING, _("homepage"), _("Homepage for this media (i.e. artist or movie homepage)"), gst_tag_merge_strings_with_comma); - gst_tag_register (GST_TAG_DESCRIPTION, GST_TAG_FLAG_META, G_TYPE_STRING, - _("description"), _("short text describing the content of the data"), + gst_tag_register_static (GST_TAG_DESCRIPTION, GST_TAG_FLAG_META, + G_TYPE_STRING, _("description"), + _("short text describing the content of the data"), gst_tag_merge_strings_with_comma); - gst_tag_register (GST_TAG_VERSION, GST_TAG_FLAG_META, G_TYPE_STRING, + gst_tag_register_static (GST_TAG_VERSION, GST_TAG_FLAG_META, G_TYPE_STRING, _("version"), _("version of this data"), NULL); - gst_tag_register (GST_TAG_ISRC, GST_TAG_FLAG_META, G_TYPE_STRING, _("ISRC"), + gst_tag_register_static (GST_TAG_ISRC, GST_TAG_FLAG_META, G_TYPE_STRING, + _("ISRC"), _ ("International Standard Recording Code - see http://www.ifpi.org/isrc/"), NULL); /* FIXME: organization (fix what? tpm) */ - gst_tag_register (GST_TAG_ORGANIZATION, GST_TAG_FLAG_META, G_TYPE_STRING, - _("organization"), _("organization"), gst_tag_merge_strings_with_comma); - gst_tag_register (GST_TAG_COPYRIGHT, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_ORGANIZATION, GST_TAG_FLAG_META, + G_TYPE_STRING, _("organization"), _("organization"), + gst_tag_merge_strings_with_comma); + gst_tag_register_static (GST_TAG_COPYRIGHT, GST_TAG_FLAG_META, G_TYPE_STRING, _("copyright"), _("copyright notice of the data"), NULL); - gst_tag_register (GST_TAG_COPYRIGHT_URI, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_COPYRIGHT_URI, GST_TAG_FLAG_META, G_TYPE_STRING, _("copyright uri"), _("URI to the copyright notice of the data"), NULL); - gst_tag_register (GST_TAG_ENCODED_BY, GST_TAG_FLAG_META, G_TYPE_STRING, + gst_tag_register_static (GST_TAG_ENCODED_BY, GST_TAG_FLAG_META, G_TYPE_STRING, _("encoded by"), _("name of the encoding person or organization"), gst_tag_merge_strings_with_comma); - gst_tag_register (GST_TAG_CONTACT, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_CONTACT, GST_TAG_FLAG_META, G_TYPE_STRING, _("contact"), _("contact information"), gst_tag_merge_strings_with_comma); - gst_tag_register (GST_TAG_LICENSE, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_LICENSE, GST_TAG_FLAG_META, G_TYPE_STRING, _("license"), _("license of data"), NULL); - gst_tag_register (GST_TAG_LICENSE_URI, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_LICENSE_URI, GST_TAG_FLAG_META, G_TYPE_STRING, _("license uri"), _("URI to the license of the data"), NULL); - gst_tag_register (GST_TAG_PERFORMER, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_PERFORMER, GST_TAG_FLAG_META, G_TYPE_STRING, _("performer"), _("person(s) performing"), gst_tag_merge_strings_with_comma); - gst_tag_register (GST_TAG_COMPOSER, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_COMPOSER, GST_TAG_FLAG_META, G_TYPE_STRING, _("composer"), _("person(s) who composed the recording"), gst_tag_merge_strings_with_comma); - gst_tag_register (GST_TAG_DURATION, GST_TAG_FLAG_DECODED, + gst_tag_register_static (GST_TAG_DURATION, GST_TAG_FLAG_DECODED, G_TYPE_UINT64, _("duration"), _("length in GStreamer time units (nanoseconds)"), NULL); - gst_tag_register (GST_TAG_CODEC, GST_TAG_FLAG_ENCODED, + gst_tag_register_static (GST_TAG_CODEC, GST_TAG_FLAG_ENCODED, G_TYPE_STRING, _("codec"), _("codec the data is stored in"), gst_tag_merge_strings_with_comma); - gst_tag_register (GST_TAG_VIDEO_CODEC, GST_TAG_FLAG_ENCODED, + gst_tag_register_static (GST_TAG_VIDEO_CODEC, GST_TAG_FLAG_ENCODED, G_TYPE_STRING, _("video codec"), _("codec the video data is stored in"), NULL); - gst_tag_register (GST_TAG_AUDIO_CODEC, GST_TAG_FLAG_ENCODED, + gst_tag_register_static (GST_TAG_AUDIO_CODEC, GST_TAG_FLAG_ENCODED, G_TYPE_STRING, _("audio codec"), _("codec the audio data is stored in"), NULL); - gst_tag_register (GST_TAG_SUBTITLE_CODEC, GST_TAG_FLAG_ENCODED, + gst_tag_register_static (GST_TAG_SUBTITLE_CODEC, GST_TAG_FLAG_ENCODED, G_TYPE_STRING, _("subtitle codec"), _("codec the subtitle data is stored in"), NULL); - gst_tag_register (GST_TAG_CONTAINER_FORMAT, GST_TAG_FLAG_ENCODED, + gst_tag_register_static (GST_TAG_CONTAINER_FORMAT, GST_TAG_FLAG_ENCODED, G_TYPE_STRING, _("container format"), _("container format the data is stored in"), NULL); - gst_tag_register (GST_TAG_BITRATE, GST_TAG_FLAG_ENCODED, + gst_tag_register_static (GST_TAG_BITRATE, GST_TAG_FLAG_ENCODED, G_TYPE_UINT, _("bitrate"), _("exact or average bitrate in bits/s"), NULL); - gst_tag_register (GST_TAG_NOMINAL_BITRATE, GST_TAG_FLAG_ENCODED, + gst_tag_register_static (GST_TAG_NOMINAL_BITRATE, GST_TAG_FLAG_ENCODED, G_TYPE_UINT, _("nominal bitrate"), _("nominal bitrate in bits/s"), NULL); - gst_tag_register (GST_TAG_MINIMUM_BITRATE, GST_TAG_FLAG_ENCODED, + gst_tag_register_static (GST_TAG_MINIMUM_BITRATE, GST_TAG_FLAG_ENCODED, G_TYPE_UINT, _("minimum bitrate"), _("minimum bitrate in bits/s"), NULL); - gst_tag_register (GST_TAG_MAXIMUM_BITRATE, GST_TAG_FLAG_ENCODED, + gst_tag_register_static (GST_TAG_MAXIMUM_BITRATE, GST_TAG_FLAG_ENCODED, G_TYPE_UINT, _("maximum bitrate"), _("maximum bitrate in bits/s"), NULL); - gst_tag_register (GST_TAG_ENCODER, GST_TAG_FLAG_ENCODED, + gst_tag_register_static (GST_TAG_ENCODER, GST_TAG_FLAG_ENCODED, G_TYPE_STRING, _("encoder"), _("encoder used to encode this stream"), NULL); - gst_tag_register (GST_TAG_ENCODER_VERSION, GST_TAG_FLAG_ENCODED, + gst_tag_register_static (GST_TAG_ENCODER_VERSION, GST_TAG_FLAG_ENCODED, G_TYPE_UINT, _("encoder version"), _("version of the encoder used to encode this stream"), NULL); - gst_tag_register (GST_TAG_SERIAL, GST_TAG_FLAG_ENCODED, + gst_tag_register_static (GST_TAG_SERIAL, GST_TAG_FLAG_ENCODED, G_TYPE_UINT, _("serial"), _("serial number of track"), NULL); - gst_tag_register (GST_TAG_TRACK_GAIN, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_TRACK_GAIN, GST_TAG_FLAG_META, G_TYPE_DOUBLE, _("replaygain track gain"), _("track gain in db"), NULL); - gst_tag_register (GST_TAG_TRACK_PEAK, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_TRACK_PEAK, GST_TAG_FLAG_META, G_TYPE_DOUBLE, _("replaygain track peak"), _("peak of the track"), NULL); - gst_tag_register (GST_TAG_ALBUM_GAIN, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_ALBUM_GAIN, GST_TAG_FLAG_META, G_TYPE_DOUBLE, _("replaygain album gain"), _("album gain in db"), NULL); - gst_tag_register (GST_TAG_ALBUM_PEAK, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_ALBUM_PEAK, GST_TAG_FLAG_META, G_TYPE_DOUBLE, _("replaygain album peak"), _("peak of the album"), NULL); - gst_tag_register (GST_TAG_REFERENCE_LEVEL, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_REFERENCE_LEVEL, GST_TAG_FLAG_META, G_TYPE_DOUBLE, _("replaygain reference level"), _("reference level of track and album gain values"), NULL); - gst_tag_register (GST_TAG_LANGUAGE_CODE, GST_TAG_FLAG_META, G_TYPE_STRING, - _("language code"), + gst_tag_register_static (GST_TAG_LANGUAGE_CODE, GST_TAG_FLAG_META, + G_TYPE_STRING, _("language code"), _("language code for this stream, conforming to ISO-639-1 or ISO-639-2"), NULL); - gst_tag_register (GST_TAG_LANGUAGE_NAME, GST_TAG_FLAG_META, G_TYPE_STRING, - _("language name"), + gst_tag_register_static (GST_TAG_LANGUAGE_NAME, GST_TAG_FLAG_META, + G_TYPE_STRING, _("language name"), _("freeform name of the language this stream is in"), NULL); - gst_tag_register (GST_TAG_IMAGE, GST_TAG_FLAG_META, GST_TYPE_SAMPLE, + gst_tag_register_static (GST_TAG_IMAGE, GST_TAG_FLAG_META, GST_TYPE_SAMPLE, _("image"), _("image related to this stream"), gst_tag_merge_use_first); - gst_tag_register (GST_TAG_PREVIEW_IMAGE, GST_TAG_FLAG_META, GST_TYPE_SAMPLE, + gst_tag_register_static (GST_TAG_PREVIEW_IMAGE, GST_TAG_FLAG_META, + GST_TYPE_SAMPLE, /* TRANSLATORS: 'preview image' = image that shows a preview of the full image */ _("preview image"), _("preview image related to this stream"), NULL); - gst_tag_register (GST_TAG_ATTACHMENT, GST_TAG_FLAG_META, GST_TYPE_SAMPLE, - _("attachment"), _("file attached to this stream"), + gst_tag_register_static (GST_TAG_ATTACHMENT, GST_TAG_FLAG_META, + GST_TYPE_SAMPLE, _("attachment"), _("file attached to this stream"), gst_tag_merge_use_first); - gst_tag_register (GST_TAG_BEATS_PER_MINUTE, GST_TAG_FLAG_META, G_TYPE_DOUBLE, - _("beats per minute"), _("number of beats per minute in audio"), NULL); - gst_tag_register (GST_TAG_KEYWORDS, GST_TAG_FLAG_META, G_TYPE_STRING, + gst_tag_register_static (GST_TAG_BEATS_PER_MINUTE, GST_TAG_FLAG_META, + G_TYPE_DOUBLE, _("beats per minute"), + _("number of beats per minute in audio"), NULL); + gst_tag_register_static (GST_TAG_KEYWORDS, GST_TAG_FLAG_META, G_TYPE_STRING, _("keywords"), _("comma separated keywords describing the content"), gst_tag_merge_strings_with_comma); - gst_tag_register (GST_TAG_GEO_LOCATION_NAME, GST_TAG_FLAG_META, G_TYPE_STRING, - _("geo location name"), _("human readable descriptive location of where " + gst_tag_register_static (GST_TAG_GEO_LOCATION_NAME, GST_TAG_FLAG_META, + G_TYPE_STRING, _("geo location name"), + _("human readable descriptive location of where " "the media has been recorded or produced"), NULL); - gst_tag_register (GST_TAG_GEO_LOCATION_LATITUDE, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_GEO_LOCATION_LATITUDE, GST_TAG_FLAG_META, G_TYPE_DOUBLE, _("geo location latitude"), _("geo latitude location of where the media has been recorded or " "produced in degrees according to WGS84 (zero at the equator, " "negative values for southern latitudes)"), NULL); - gst_tag_register (GST_TAG_GEO_LOCATION_LONGITUDE, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_GEO_LOCATION_LONGITUDE, GST_TAG_FLAG_META, G_TYPE_DOUBLE, _("geo location longitude"), _("geo longitude location of where the media has been recorded or " "produced in degrees according to WGS84 (zero at the prime meridian " "in Greenwich/UK, negative values for western longitudes)"), NULL); - gst_tag_register (GST_TAG_GEO_LOCATION_ELEVATION, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_GEO_LOCATION_ELEVATION, GST_TAG_FLAG_META, G_TYPE_DOUBLE, _("geo location elevation"), _("geo elevation of where the media has been recorded or produced in " "meters according to WGS84 (zero is average sea level)"), NULL); - gst_tag_register (GST_TAG_GEO_LOCATION_COUNTRY, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_GEO_LOCATION_COUNTRY, GST_TAG_FLAG_META, G_TYPE_STRING, _("geo location country"), _("country (english name) where the media has been recorded " "or produced"), NULL); - gst_tag_register (GST_TAG_GEO_LOCATION_CITY, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_GEO_LOCATION_CITY, GST_TAG_FLAG_META, G_TYPE_STRING, _("geo location city"), _("city (english name) where the media has been recorded " "or produced"), NULL); - gst_tag_register (GST_TAG_GEO_LOCATION_SUBLOCATION, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_GEO_LOCATION_SUBLOCATION, GST_TAG_FLAG_META, G_TYPE_STRING, _("geo location sublocation"), _("a location whithin a city where the media has been produced " "or created (e.g. the neighborhood)"), NULL); - gst_tag_register (GST_TAG_GEO_LOCATION_HORIZONTAL_ERROR, GST_TAG_FLAG_META, - G_TYPE_DOUBLE, _("geo location horizontal error"), + gst_tag_register_static (GST_TAG_GEO_LOCATION_HORIZONTAL_ERROR, + GST_TAG_FLAG_META, G_TYPE_DOUBLE, _("geo location horizontal error"), _("expected error of the horizontal positioning measures (in meters)"), NULL); - gst_tag_register (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, GST_TAG_FLAG_META, - G_TYPE_DOUBLE, _("geo location movement speed"), + gst_tag_register_static (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, + GST_TAG_FLAG_META, G_TYPE_DOUBLE, _("geo location movement speed"), _("movement speed of the capturing device while performing the capture " "in m/s"), NULL); - gst_tag_register (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, GST_TAG_FLAG_META, - G_TYPE_DOUBLE, _("geo location movement direction"), + gst_tag_register_static (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, + GST_TAG_FLAG_META, G_TYPE_DOUBLE, _("geo location movement direction"), _("indicates the movement direction of the device performing the capture" " of a media. It is represented as degrees in floating point " "representation, 0 means the geographic north, and increases " "clockwise"), NULL); - gst_tag_register (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, GST_TAG_FLAG_META, - G_TYPE_DOUBLE, _("geo location capture direction"), + gst_tag_register_static (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, + GST_TAG_FLAG_META, G_TYPE_DOUBLE, _("geo location capture direction"), _("indicates the direction the device is pointing to when capturing " " a media. It is represented as degrees in floating point " " representation, 0 means the geographic north, and increases " "clockwise"), NULL); - gst_tag_register (GST_TAG_SHOW_NAME, GST_TAG_FLAG_META, G_TYPE_STRING, + gst_tag_register_static (GST_TAG_SHOW_NAME, GST_TAG_FLAG_META, G_TYPE_STRING, /* TRANSLATORS: 'show name' = 'TV/radio/podcast show name' here */ _("show name"), _("Name of the tv/podcast/series show the media is from"), gst_tag_merge_strings_with_comma); - gst_tag_register (GST_TAG_SHOW_SORTNAME, GST_TAG_FLAG_META, G_TYPE_STRING, + gst_tag_register_static (GST_TAG_SHOW_SORTNAME, GST_TAG_FLAG_META, + G_TYPE_STRING, /* TRANSLATORS: 'show sortname' = 'TV/radio/podcast show name as used for sorting purposes' here */ _("show sortname"), _("Name of the tv/podcast/series show the media is from, for sorting " "purposes"), NULL); - gst_tag_register (GST_TAG_SHOW_EPISODE_NUMBER, GST_TAG_FLAG_META, G_TYPE_UINT, - _("episode number"), + gst_tag_register_static (GST_TAG_SHOW_EPISODE_NUMBER, GST_TAG_FLAG_META, + G_TYPE_UINT, _("episode number"), _("The episode number in the season the media is part of"), gst_tag_merge_use_first); - gst_tag_register (GST_TAG_SHOW_SEASON_NUMBER, GST_TAG_FLAG_META, G_TYPE_UINT, - _("season number"), + gst_tag_register_static (GST_TAG_SHOW_SEASON_NUMBER, GST_TAG_FLAG_META, + G_TYPE_UINT, _("season number"), _("The season number of the show the media is part of"), gst_tag_merge_use_first); - gst_tag_register (GST_TAG_LYRICS, GST_TAG_FLAG_META, G_TYPE_STRING, + gst_tag_register_static (GST_TAG_LYRICS, GST_TAG_FLAG_META, G_TYPE_STRING, _("lyrics"), _("The lyrics of the media, commonly used for songs"), gst_tag_merge_strings_with_comma); - gst_tag_register (GST_TAG_COMPOSER_SORTNAME, GST_TAG_FLAG_META, G_TYPE_STRING, - _("composer sortname"), + gst_tag_register_static (GST_TAG_COMPOSER_SORTNAME, GST_TAG_FLAG_META, + G_TYPE_STRING, _("composer sortname"), _("person(s) who composed the recording, for sorting purposes"), NULL); - gst_tag_register (GST_TAG_GROUPING, GST_TAG_FLAG_META, G_TYPE_STRING, + gst_tag_register_static (GST_TAG_GROUPING, GST_TAG_FLAG_META, G_TYPE_STRING, _("grouping"), _("Groups related media that spans multiple tracks, like the different " "pieces of a concerto. It is a higher level than a track, " "but lower than an album"), NULL); - gst_tag_register (GST_TAG_USER_RATING, GST_TAG_FLAG_META, G_TYPE_UINT, + gst_tag_register_static (GST_TAG_USER_RATING, GST_TAG_FLAG_META, G_TYPE_UINT, _("user rating"), _("Rating attributed by a user. The higher the rank, " "the more the user likes this media"), NULL); - gst_tag_register (GST_TAG_DEVICE_MANUFACTURER, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_DEVICE_MANUFACTURER, GST_TAG_FLAG_META, G_TYPE_STRING, _("device manufacturer"), _("Manufacturer of the device used to create this media"), NULL); - gst_tag_register (GST_TAG_DEVICE_MODEL, GST_TAG_FLAG_META, G_TYPE_STRING, - _("device model"), + gst_tag_register_static (GST_TAG_DEVICE_MODEL, GST_TAG_FLAG_META, + G_TYPE_STRING, _("device model"), _("Model of the device used to create this media"), NULL); - gst_tag_register (GST_TAG_APPLICATION_NAME, GST_TAG_FLAG_META, G_TYPE_STRING, - _("application name"), _("Application used to create the media"), NULL); - gst_tag_register (GST_TAG_APPLICATION_DATA, GST_TAG_FLAG_META, + gst_tag_register_static (GST_TAG_APPLICATION_NAME, GST_TAG_FLAG_META, + G_TYPE_STRING, _("application name"), + _("Application used to create the media"), NULL); + gst_tag_register_static (GST_TAG_APPLICATION_DATA, GST_TAG_FLAG_META, GST_TYPE_BUFFER, _("application data"), _("Arbitrary application data to be serialized into the media"), NULL); - gst_tag_register (GST_TAG_IMAGE_ORIENTATION, GST_TAG_FLAG_META, G_TYPE_STRING, - _("image orientation"), + gst_tag_register_static (GST_TAG_IMAGE_ORIENTATION, GST_TAG_FLAG_META, + G_TYPE_STRING, _("image orientation"), _("How the image should be rotated or flipped before display"), NULL); } @@ -470,8 +487,36 @@ void gst_tag_register (const gchar * name, GstTagFlag flag, GType type, const gchar * nick, const gchar * blurb, GstTagMergeFunc func) { + g_return_if_fail (name != NULL); + g_return_if_fail (nick != NULL); + g_return_if_fail (blurb != NULL); + g_return_if_fail (type != 0 && type != GST_TYPE_LIST); + + return gst_tag_register_static (g_intern_string (name), flag, type, + g_intern_string (nick), g_intern_string (blurb), func); +} + +/** + * gst_tag_register_static: + * @name: the name or identifier string (string constant) + * @flag: a flag describing the type of tag info + * @type: the type this data is in + * @nick: human-readable name or short description (string constant) + * @blurb: a human-readable description for this tag (string constant) + * @func: function for merging multiple values of this tag, or NULL + * + * Registers a new tag type for the use with GStreamer's type system. + * + * Same as gst_tag_register(), but @name, @nick, and @blurb must be + * static strings or inlined strings, as they will not be copied. (GStreamer + * plugins will be made resident once loaded, so this function can be used + * even from dynamically loaded plugins.) + */ +void +gst_tag_register_static (const gchar * name, GstTagFlag flag, GType type, + const gchar * nick, const gchar * blurb, GstTagMergeFunc func) +{ GstTagInfo *info; - gchar *name_dup; g_return_if_fail (name != NULL); g_return_if_fail (nick != NULL); @@ -488,17 +533,13 @@ gst_tag_register (const gchar * name, GstTagFlag flag, GType type, info = g_slice_new (GstTagInfo); info->flag = flag; info->type = type; - info->nick = g_strdup (nick); - info->blurb = g_strdup (blurb); + info->name_quark = g_quark_from_static_string (name); + info->nick = nick; + info->blurb = blurb; info->merge_func = func; - /* we make a copy for the hash table anyway, which will stay around, so - * can use that for the quark table too */ - name_dup = g_strdup (name); - info->name_quark = g_quark_from_static_string (name_dup); - TAG_LOCK; - g_hash_table_insert (__tags, (gpointer) name_dup, info); + g_hash_table_insert (__tags, (gpointer) name, info); TAG_UNLOCK; } @@ -621,19 +662,82 @@ gst_tag_is_fixed (const gchar * tag) return info->merge_func == NULL; } +static void +gst_tag_list_init (GstTagList * taglist, gsize size) +{ + gst_mini_object_init (GST_MINI_OBJECT_CAST (taglist), + gst_tag_list_get_type (), size); + + taglist->mini_object.copy = (GstMiniObjectCopyFunction) __gst_tag_list_copy; + taglist->mini_object.dispose = NULL; + taglist->mini_object.free = (GstMiniObjectFreeFunction) __gst_tag_list_free; +} + +/* takes ownership of the structure */ +static GstTagList * +gst_tag_list_new_internal (GstStructure * s) +{ + GstTagList *tag_list; + + g_assert (s != NULL); + + tag_list = (GstTagList *) g_slice_new (GstTagListImpl); + + gst_tag_list_init (tag_list, sizeof (GstTagListImpl)); + + GST_TAG_LIST_STRUCTURE (tag_list) = s; + +#ifdef DEBUG_REFCOUNT + GST_CAT_TRACE (GST_CAT_TAGS, "created taglist %p", tag_list); +#endif + + return tag_list; +} + +static void +__gst_tag_list_free (GstTagList * list) +{ + g_return_if_fail (GST_IS_TAG_LIST (list)); + +#ifdef DEBUG_REFCOUNT + GST_CAT_TRACE (GST_CAT_TAGS, "freeing caps %p", list); +#endif + + gst_structure_free (GST_TAG_LIST_STRUCTURE (list)); + + /* why not just pass sizeof (GstTagListImpl) here? */ + g_slice_free1 (GST_MINI_OBJECT_SIZE (list), list); +} + +static GstTagList * +__gst_tag_list_copy (const GstTagList * list) +{ + const GstStructure *s; + + g_return_val_if_fail (GST_IS_TAG_LIST (list), NULL); + + s = GST_TAG_LIST_STRUCTURE (list); + return gst_tag_list_new_internal (gst_structure_copy (s)); +} + /** * gst_tag_list_new_empty: * * Creates a new empty GstTagList. * - * Free-function: gst_tag_list_free + * Free-function: gst_tag_list_unref * * Returns: (transfer full): An empty tag list */ GstTagList * gst_tag_list_new_empty (void) { - return GST_TAG_LIST (gst_structure_new_id_empty (GST_QUARK (TAGLIST))); + GstStructure *s; + GstTagList *tag_list; + + s = gst_structure_new_id_empty (GST_QUARK (TAGLIST)); + tag_list = gst_tag_list_new_internal (s); + return tag_list; } /** @@ -649,9 +753,9 @@ gst_tag_list_new_empty (void) * function. The tag list will make copies of any arguments passed * (e.g. strings, buffers). * - * Free-function: gst_tag_list_free + * Free-function: gst_tag_list_unref * - * Returns: (transfer full): a new #GstTagList. Free with gst_tag_list_free() + * Returns: (transfer full): a new #GstTagList. Free with gst_tag_list_unref() * when no longer needed. * * Since: 0.10.24 @@ -679,9 +783,9 @@ gst_tag_list_new (const gchar * tag, ...) * Just like gst_tag_list_new(), only that it takes a va_list argument. * Useful mostly for language bindings. * - * Free-function: gst_tag_list_free + * Free-function: gst_tag_list_unref * - * Returns: (transfer full): a new #GstTagList. Free with gst_tag_list_free() + * Returns: (transfer full): a new #GstTagList. Free with gst_tag_list_unref() * when no longer needed. * * Since: 0.10.24 @@ -716,7 +820,7 @@ gst_tag_list_to_string (const GstTagList * list) { g_return_val_if_fail (GST_IS_TAG_LIST (list), NULL); - return gst_structure_to_string (GST_STRUCTURE (list)); + return gst_structure_to_string (GST_TAG_LIST_STRUCTURE (list)); } /** @@ -732,10 +836,13 @@ gst_tag_list_to_string (const GstTagList * list) GstTagList * gst_tag_list_new_from_string (const gchar * str) { + GstTagList *tag_list; + g_return_val_if_fail (str != NULL, NULL); g_return_val_if_fail (g_str_has_prefix (str, "taglist"), NULL); - return GST_TAG_LIST (gst_structure_from_string (str, NULL)); + tag_list = gst_tag_list_new_internal (gst_structure_from_string (str, NULL)); + return tag_list; } /** @@ -752,7 +859,7 @@ gst_tag_list_n_tags (const GstTagList * list) g_return_val_if_fail (list != NULL, 0); g_return_val_if_fail (GST_IS_TAG_LIST (list), 0); - return gst_structure_n_fields ((GstStructure *) list); + return gst_structure_n_fields (GST_TAG_LIST_STRUCTURE (list)); } /** @@ -770,7 +877,7 @@ gst_tag_list_nth_tag_name (const GstTagList * list, guint index) g_return_val_if_fail (list != NULL, 0); g_return_val_if_fail (GST_IS_TAG_LIST (list), 0); - return gst_structure_nth_field_name ((GstStructure *) list, index); + return gst_structure_nth_field_name (GST_TAG_LIST_STRUCTURE (list), index); } /** @@ -789,7 +896,7 @@ gst_tag_list_is_empty (const GstTagList * list) g_return_val_if_fail (list != NULL, FALSE); g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE); - return (gst_structure_n_fields ((GstStructure *) list) == 0); + return (gst_structure_n_fields (GST_TAG_LIST_STRUCTURE (list)) == 0); } static gboolean @@ -836,8 +943,8 @@ gst_tag_list_is_equal (const GstTagList * list1, const GstTagList * list2) /* we don't just use gst_structure_is_equal() here so we can add some * tolerance for doubles, though maybe we should just add that to * gst_value_compare_double() as well? */ - s1 = (const GstStructure *) list1; - s2 = (const GstStructure *) list2; + s1 = GST_TAG_LIST_STRUCTURE (list1); + s2 = GST_TAG_LIST_STRUCTURE (list2); num_fields1 = gst_structure_n_fields (s1); num_fields2 = gst_structure_n_fields (s2); @@ -863,24 +970,6 @@ gst_tag_list_is_equal (const GstTagList * list1, const GstTagList * list2) return TRUE; } -/** - * gst_is_tag_list: - * @p: Object that might be a taglist - * - * Checks if the given pointer is a taglist. - * - * Returns: TRUE, if the given pointer is a taglist - */ -gboolean -gst_is_tag_list (gconstpointer p) -{ - GstStructure *s = (GstStructure *) p; - - g_return_val_if_fail (p != NULL, FALSE); - - return (GST_IS_STRUCTURE (s) && s->name == GST_QUARK (TAGLIST)); -} - typedef struct { GstTagList *list; @@ -892,7 +981,7 @@ static void gst_tag_list_add_value_internal (GstTagList * tag_list, GstTagMergeMode mode, const gchar * tag, const GValue * value, GstTagInfo * info) { - GstStructure *list = GST_STRUCTURE (tag_list); + GstStructure *list = GST_TAG_LIST_STRUCTURE (tag_list); const GValue *value2; GQuark tag_quark; @@ -981,34 +1070,17 @@ gst_tag_list_insert (GstTagList * into, const GstTagList * from, GstTagCopyData data; g_return_if_fail (GST_IS_TAG_LIST (into)); + g_return_if_fail (gst_tag_list_is_writable (into)); g_return_if_fail (GST_IS_TAG_LIST (from)); g_return_if_fail (GST_TAG_MODE_IS_VALID (mode)); data.list = into; data.mode = mode; if (mode == GST_TAG_MERGE_REPLACE_ALL) { - gst_structure_remove_all_fields (GST_STRUCTURE (data.list)); + gst_structure_remove_all_fields (GST_TAG_LIST_STRUCTURE (into)); } - gst_structure_foreach ((GstStructure *) from, gst_tag_list_copy_foreach, - &data); -} - -/** - * gst_tag_list_copy: - * @list: list to copy - * - * Copies a given #GstTagList. - * - * Free-function: gst_tag_list_free - * - * Returns: (transfer full): copy of the given list - */ -GstTagList * -gst_tag_list_copy (const GstTagList * list) -{ - g_return_val_if_fail (GST_IS_TAG_LIST (list), NULL); - - return GST_TAG_LIST (gst_structure_copy ((GstStructure *) list)); + gst_structure_foreach (GST_TAG_LIST_STRUCTURE (from), + gst_tag_list_copy_foreach, &data); } /** @@ -1020,7 +1092,7 @@ gst_tag_list_copy (const GstTagList * list) * Merges the two given lists into a new list. If one of the lists is NULL, a * copy of the other is returned. If both lists are NULL, NULL is returned. * - * Free-function: gst_tag_list_free + * Free-function: gst_tag_list_unref * * Returns: (transfer full): the new list */ @@ -1047,25 +1119,12 @@ gst_tag_list_merge (const GstTagList * list1, const GstTagList * list2, gst_tag_list_insert (list1_cp, list2_cp, mode); if (!list2) - gst_tag_list_free ((GstTagList *) list2_cp); + gst_tag_list_unref ((GstTagList *) list2_cp); return list1_cp; } /** - * gst_tag_list_free: - * @list: (in) (transfer full): the list to free - * - * Frees the given list and all associated values. - */ -void -gst_tag_list_free (GstTagList * list) -{ - g_return_if_fail (GST_IS_TAG_LIST (list)); - gst_structure_free ((GstStructure *) list); -} - -/** * gst_tag_list_get_tag_size: * @list: a taglist * @tag: the tag to query @@ -1081,7 +1140,7 @@ gst_tag_list_get_tag_size (const GstTagList * list, const gchar * tag) g_return_val_if_fail (GST_IS_TAG_LIST (list), 0); - value = gst_structure_get_value ((GstStructure *) list, tag); + value = gst_structure_get_value (GST_TAG_LIST_STRUCTURE (list), tag); if (value == NULL) return 0; if (G_VALUE_TYPE (value) != GST_TYPE_LIST) @@ -1106,6 +1165,7 @@ gst_tag_list_add (GstTagList * list, GstTagMergeMode mode, const gchar * tag, va_list args; g_return_if_fail (GST_IS_TAG_LIST (list)); + g_return_if_fail (gst_tag_list_is_writable (list)); g_return_if_fail (GST_TAG_MODE_IS_VALID (mode)); g_return_if_fail (tag != NULL); @@ -1130,6 +1190,7 @@ gst_tag_list_add_values (GstTagList * list, GstTagMergeMode mode, va_list args; g_return_if_fail (GST_IS_TAG_LIST (list)); + g_return_if_fail (gst_tag_list_is_writable (list)); g_return_if_fail (GST_TAG_MODE_IS_VALID (mode)); g_return_if_fail (tag != NULL); @@ -1155,11 +1216,12 @@ gst_tag_list_add_valist (GstTagList * list, GstTagMergeMode mode, gchar *error = NULL; g_return_if_fail (GST_IS_TAG_LIST (list)); + g_return_if_fail (gst_tag_list_is_writable (list)); g_return_if_fail (GST_TAG_MODE_IS_VALID (mode)); g_return_if_fail (tag != NULL); if (mode == GST_TAG_MERGE_REPLACE_ALL) { - gst_structure_remove_all_fields (GST_STRUCTURE (list)); + gst_structure_remove_all_fields (GST_TAG_LIST_STRUCTURE (list)); } while (tag != NULL) { @@ -1199,11 +1261,12 @@ gst_tag_list_add_valist_values (GstTagList * list, GstTagMergeMode mode, const gchar * tag, va_list var_args) { g_return_if_fail (GST_IS_TAG_LIST (list)); + g_return_if_fail (gst_tag_list_is_writable (list)); g_return_if_fail (GST_TAG_MODE_IS_VALID (mode)); g_return_if_fail (tag != NULL); if (mode == GST_TAG_MERGE_REPLACE_ALL) { - gst_structure_remove_all_fields (GST_STRUCTURE (list)); + gst_structure_remove_all_fields (GST_TAG_LIST_STRUCTURE (list)); } while (tag != NULL) { @@ -1236,6 +1299,7 @@ gst_tag_list_add_value (GstTagList * list, GstTagMergeMode mode, const gchar * tag, const GValue * value) { g_return_if_fail (GST_IS_TAG_LIST (list)); + g_return_if_fail (gst_tag_list_is_writable (list)); g_return_if_fail (GST_TAG_MODE_IS_VALID (mode)); g_return_if_fail (tag != NULL); @@ -1255,7 +1319,7 @@ gst_tag_list_remove_tag (GstTagList * list, const gchar * tag) g_return_if_fail (GST_IS_TAG_LIST (list)); g_return_if_fail (tag != NULL); - gst_structure_remove_field ((GstStructure *) list, tag); + gst_structure_remove_field (GST_TAG_LIST_STRUCTURE (list), tag); } typedef struct @@ -1297,8 +1361,8 @@ gst_tag_list_foreach (const GstTagList * list, GstTagForeachFunc func, data.func = func; data.tag_list = list; data.data = user_data; - gst_structure_foreach ((GstStructure *) list, structure_foreach_wrapper, - &data); + gst_structure_foreach (GST_TAG_LIST_STRUCTURE (list), + structure_foreach_wrapper, &data); } /** @@ -1322,7 +1386,7 @@ gst_tag_list_get_value_index (const GstTagList * list, const gchar * tag, g_return_val_if_fail (GST_IS_TAG_LIST (list), NULL); g_return_val_if_fail (tag != NULL, NULL); - value = gst_structure_get_value ((GstStructure *) list, tag); + value = gst_structure_get_value (GST_TAG_LIST_STRUCTURE (list), tag); if (value == NULL) return NULL; @@ -1362,7 +1426,7 @@ gst_tag_list_copy_value (GValue * dest, const GstTagList * list, g_return_val_if_fail (dest != NULL, FALSE); g_return_val_if_fail (G_VALUE_TYPE (dest) == 0, FALSE); - src = gst_structure_get_value ((GstStructure *) list, tag); + src = gst_structure_get_value (GST_TAG_LIST_STRUCTURE (list), tag); if (!src) return FALSE; diff --git a/gst/gsttaglist.h b/gst/gsttaglist.h index 00a2770..7940a31 100644 --- a/gst/gsttaglist.h +++ b/gst/gsttaglist.h @@ -132,6 +132,7 @@ typedef enum { * * Extra tag flags used when registering tags. */ +/* FIXME: these are not really flags .. */ typedef enum { GST_TAG_FLAG_UNDEFINED, GST_TAG_FLAG_META, @@ -144,14 +145,18 @@ typedef enum { /** * GstTagList: + * @mini_object: the parent type * - * Opaque #GstTagList data structure. + * Object describing tags / metadata. */ typedef struct _GstTagList GstTagList; +struct _GstTagList { + GstMiniObject mini_object; +}; #define GST_TAG_LIST(x) ((GstTagList *) (x)) -#define GST_IS_TAG_LIST(x) ((x) != NULL && gst_is_tag_list (GST_TAG_LIST (x))) #define GST_TYPE_TAG_LIST (gst_tag_list_get_type ()) +#define GST_IS_TAG_LIST(obj) (GST_IS_MINI_OBJECT_TYPE((obj), GST_TYPE_TAG_LIST)) /** * GstTagForeachFunc: @@ -186,6 +191,13 @@ void gst_tag_register (const gchar * name, const gchar * blurb, GstTagMergeFunc func); +void gst_tag_register_static (const gchar * name, + GstTagFlag flag, + GType type, + const gchar * nick, + const gchar * blurb, + GstTagMergeFunc func); + /* some default merging functions */ void gst_tag_merge_use_first (GValue * dest, const GValue * src); void gst_tag_merge_strings_with_comma (GValue * dest, const GValue * src); @@ -206,8 +218,6 @@ GstTagList * gst_tag_list_new_valist (va_list var_args) G_GNUC_MALLOC; 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; -gboolean gst_is_tag_list (gconstpointer p); -GstTagList * gst_tag_list_copy (const GstTagList * list) G_GNUC_MALLOC; gint gst_tag_list_n_tags (const GstTagList * list); const gchar* gst_tag_list_nth_tag_name (const GstTagList * list, guint index); gboolean gst_tag_list_is_empty (const GstTagList * list); @@ -219,7 +229,6 @@ void gst_tag_list_insert (GstTagList * into, GstTagList * gst_tag_list_merge (const GstTagList * list1, const GstTagList * list2, GstTagMergeMode mode) G_GNUC_MALLOC; -void gst_tag_list_free (GstTagList * list); guint gst_tag_list_get_tag_size (const GstTagList * list, const gchar * tag); void gst_tag_list_add (GstTagList * list, @@ -346,6 +355,104 @@ gboolean gst_tag_list_get_buffer_index (const GstTagList * list, guint index, GstBuffer ** value); +/* refcounting */ +/** + * gst_tag_list_ref: + * @taglist: the #GstTagList to reference + * + * Add a reference to a #GstTagList mini object. + * + * From this point on, until the caller calls gst_tag_list_unref() or + * gst_tag_list_make_writable(), it is guaranteed that the taglist object will + * not change. To use a #GstTagList object, you must always have a refcount on + * it -- either the one made implicitly by e.g. gst_tag_list_new(), or via + * taking one explicitly with this function. + * + * Returns: the same #GstTagList mini object. + */ +#ifdef _FOOL_GTK_DOC_ +G_INLINE_FUNC GstTagList * gst_tag_list_ref (GstTagList * taglist); +#endif + +static inline GstTagList * +gst_tag_list_ref (GstTagList * taglist) +{ + return (GstTagList *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (taglist)); +} + +/** + * gst_tag_list_unref: + * @taglist: a #GstTagList. + * + * Unref a #GstTagList, and and free all its memory when the refcount reaches 0. + */ +#ifdef _FOOL_GTK_DOC_ +G_INLINE_FUNC void gst_tag_list_unref (GstTagList * taglist); +#endif + +static inline void +gst_tag_list_unref (GstTagList * taglist) +{ + gst_mini_object_unref (GST_MINI_OBJECT_CAST (taglist)); +} + +/** + * gst_tag_list_copy: + * @taglist: a #GstTagList. + * + * Creates a new #GstTagList as a copy of the old @taglist. The new taglist + * will have a refcount of 1, owned by the caller, and will be writable as + * a result. + * + * Note that this function is the semantic equivalent of a gst_tag_list_ref() + * followed by a gst_tag_list_make_writable(). If you only want to hold on to a + * reference to the data, you should use gst_tag_list_ref(). + * + * When you are finished with the taglist, call gst_tag_list_unref() on it. + * + * Returns: the new #GstTagList + */ +#ifdef _FOOL_GTK_DOC_ +G_INLINE_FUNC GstTagList * gst_tag_list_copy (const GstTagList * taglist); +#endif + +static inline GstTagList * +gst_tag_list_copy (const GstTagList * taglist) +{ + return GST_TAG_LIST (gst_mini_object_copy (GST_MINI_OBJECT_CAST (taglist))); +} + +/** + * gst_tag_list_is_writable: + * @taglist: a #GstTagList + * + * Tests if you can safely modify @taglist. It is only safe to modify taglist + * when there is only one owner of the taglist - ie, the refcount is 1. + */ +#define gst_tag_list_is_writable(taglist) gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (taglist)) + +/** + * gst_tag_list_make_writable: + * @taglist: (transfer full): a #GstTagList + * + * Returns a writable copy of @taglist. + * + * If there is only one reference count on @taglist, the caller must be the + * owner, and so this function will return the taglist object unchanged. If on + * the other hand there is more than one reference on the object, a new taglist + * object will be returned (which will be a copy of @taglist). The caller's + * reference on @taglist will be removed, and instead the caller will own a + * reference to the returned object. + * + * In short, this function unrefs the taglist in the argument and refs the + * taglist that it returns. Don't access the argument after calling this + * function. See also: gst_tag_list_ref(). + * + * Returns: (transfer full): a writable taglist which may or may not be the + * same as @taglist + */ +#define gst_tag_list_make_writable(taglist) GST_TAG_LIST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (taglist))) + /* GStreamer core tags */ /** * GST_TAG_TITLE: @@ -723,7 +830,7 @@ gboolean gst_tag_list_get_buffer_index (const GstTagList * list, /** * GST_TAG_IMAGE: * - * image (sample) (sample caps should specify the content type and preferably + * image (sample) (sample taglist should specify the content type and preferably * also set "image-type" field as #GstTagImageType) * * Since: 0.10.6 @@ -733,7 +840,7 @@ gboolean gst_tag_list_get_buffer_index (const GstTagList * list, * GST_TAG_PREVIEW_IMAGE: * * image that is meant for preview purposes, e.g. small icon-sized version - * (sample) (sample caps should specify the content type) + * (sample) (sample taglist should specify the content type) * * Since: 0.10.7 */ @@ -742,7 +849,7 @@ gboolean gst_tag_list_get_buffer_index (const GstTagList * list, /** * GST_TAG_ATTACHMENT: * - * generic file attachment (sample) (sample caps should specify the content + * generic file attachment (sample) (sample taglist should specify the content * type and if possible set "filename" to the file name of the * attachment) * diff --git a/gst/gsttagsetter.c b/gst/gsttagsetter.c index 2ed099d..b538c59 100644 --- a/gst/gsttagsetter.c +++ b/gst/gsttagsetter.c @@ -126,7 +126,7 @@ gst_tag_data_free (gpointer p) GstTagData *data = (GstTagData *) p; if (data->list) - gst_tag_list_free (data->list); + gst_tag_list_unref (data->list); g_mutex_clear (&data->lock); @@ -181,7 +181,7 @@ gst_tag_setter_reset_tags (GstTagSetter * setter) GST_TAG_DATA_LOCK (data); if (data->list) { - gst_tag_list_free (data->list); + gst_tag_list_unref (data->list); data->list = NULL; } GST_TAG_DATA_UNLOCK (data); diff --git a/gst/gsttoc.c b/gst/gsttoc.c index 0ea0f33..b79717b 100644 --- a/gst/gsttoc.c +++ b/gst/gsttoc.c @@ -70,90 +70,12 @@ #include "gstvalue.h" #include "gsttoc.h" #include "gstpad.h" +#include "gstquark.h" -#define GST_TOC_TOC_NAME "toc" -#define GST_TOC_ENTRY_NAME "entry" - -#define GST_TOC_TOC_UPDATED_FIELD "updated" -#define GST_TOC_TOC_EXTENDUID_FIELD "extenduid" -#define GST_TOC_INFO_FIELD "info" - -#define GST_TOC_ENTRY_UID_FIELD "uid" -#define GST_TOC_ENTRY_TYPE_FIELD "type" -#define GST_TOC_ENTRY_TAGS_FIELD "tags" - -#define GST_TOC_TOC_ENTRIES_FIELD "subentries" - -#define GST_TOC_INFO_NAME "info-structure" -#define GST_TOC_INFO_TIME_FIELD "time" - -#define GST_TOC_TIME_NAME "time-structure" -#define GST_TOC_TIME_START_FIELD "start" -#define GST_TOC_TIME_STOP_FIELD "stop" - - -enum -{ - GST_TOC_TOC = 0, - GST_TOC_ENTRY = 1, - GST_TOC_UPDATED = 2, - GST_TOC_EXTENDUID = 3, - GST_TOC_UID = 4, - GST_TOC_TYPE = 5, - GST_TOC_TAGS = 6, - GST_TOC_SUBENTRIES = 7, - GST_TOC_INFO = 8, - GST_TOC_INFONAME = 9, - GST_TOC_TIME = 10, - GST_TOC_TIMENAME = 11, - GST_TOC_TIME_START = 12, - GST_TOC_TIME_STOP = 13, - GST_TOC_LAST = 14 -}; - -static GQuark gst_toc_fields[GST_TOC_LAST] = { 0 }; - -void -_priv_gst_toc_initialize (void) -{ - static gboolean inited = FALSE; - - if (G_LIKELY (!inited)) { - gst_toc_fields[GST_TOC_TOC] = g_quark_from_static_string (GST_TOC_TOC_NAME); - gst_toc_fields[GST_TOC_ENTRY] = - g_quark_from_static_string (GST_TOC_ENTRY_NAME); - - gst_toc_fields[GST_TOC_UPDATED] = - g_quark_from_static_string (GST_TOC_TOC_UPDATED_FIELD); - gst_toc_fields[GST_TOC_EXTENDUID] = - g_quark_from_static_string (GST_TOC_TOC_EXTENDUID_FIELD); - gst_toc_fields[GST_TOC_INFO] = - g_quark_from_static_string (GST_TOC_INFO_FIELD); - - gst_toc_fields[GST_TOC_UID] = - g_quark_from_static_string (GST_TOC_ENTRY_UID_FIELD); - gst_toc_fields[GST_TOC_TYPE] = - g_quark_from_static_string (GST_TOC_ENTRY_TYPE_FIELD); - gst_toc_fields[GST_TOC_TAGS] = - g_quark_from_static_string (GST_TOC_ENTRY_TAGS_FIELD); - - gst_toc_fields[GST_TOC_SUBENTRIES] = - g_quark_from_static_string (GST_TOC_TOC_ENTRIES_FIELD); - - gst_toc_fields[GST_TOC_INFONAME] = - g_quark_from_static_string (GST_TOC_INFO_NAME); - gst_toc_fields[GST_TOC_TIME] = - g_quark_from_static_string (GST_TOC_INFO_TIME_FIELD); - gst_toc_fields[GST_TOC_TIMENAME] = - g_quark_from_static_string (GST_TOC_TIME_NAME); - gst_toc_fields[GST_TOC_TIME_START] = - g_quark_from_static_string (GST_TOC_TIME_START_FIELD); - gst_toc_fields[GST_TOC_TIME_STOP] = - g_quark_from_static_string (GST_TOC_TIME_STOP_FIELD); - - inited = TRUE; - } -} +G_DEFINE_BOXED_TYPE (GstToc, gst_toc, + (GBoxedCopyFunc) gst_toc_copy, (GBoxedFreeFunc) gst_toc_free); +G_DEFINE_BOXED_TYPE (GstTocEntry, gst_toc_entry, + (GBoxedCopyFunc) gst_toc_entry_copy, (GBoxedFreeFunc) gst_toc_entry_free); /** * gst_toc_new: @@ -171,7 +93,7 @@ gst_toc_new (void) toc = g_slice_new0 (GstToc); toc->tags = gst_tag_list_new_empty (); - toc->info = gst_structure_new_id_empty (gst_toc_fields[GST_TOC_INFONAME]); + toc->info = gst_structure_new_id_empty (GST_QUARK (INFO_STRUCTURE)); return toc; } @@ -198,7 +120,7 @@ gst_toc_entry_new (GstTocEntryType type, const gchar * uid) entry->uid = g_strdup (uid); entry->type = type; entry->tags = gst_tag_list_new_empty (); - entry->info = gst_structure_new_id_empty (gst_toc_fields[GST_TOC_INFONAME]); + entry->info = gst_structure_new_id_empty (GST_QUARK (INFO_STRUCTURE)); return entry; } @@ -218,7 +140,7 @@ gst_toc_entry_new (GstTocEntryType type, const gchar * uid) */ GstTocEntry * gst_toc_entry_new_with_pad (GstTocEntryType type, const gchar * uid, - gpointer pad) + GstPad * pad) { GstTocEntry *entry; @@ -228,7 +150,7 @@ gst_toc_entry_new_with_pad (GstTocEntryType type, const gchar * uid, entry->uid = g_strdup (uid); entry->type = type; entry->tags = gst_tag_list_new_empty (); - entry->info = gst_structure_new_id_empty (gst_toc_fields[GST_TOC_INFONAME]); + entry->info = gst_structure_new_id_empty (GST_QUARK (INFO_STRUCTURE)); if (pad != NULL && GST_IS_PAD (pad)) entry->pads = g_list_append (entry->pads, gst_object_ref (pad)); @@ -253,7 +175,7 @@ gst_toc_free (GstToc * toc) g_list_free (toc->entries); if (toc->tags != NULL) - gst_tag_list_free (toc->tags); + gst_tag_list_unref (toc->tags); if (toc->info != NULL) gst_structure_free (toc->info); @@ -284,7 +206,7 @@ gst_toc_entry_free (GstTocEntry * entry) g_free (entry->uid); if (entry->tags != NULL) - gst_tag_list_free (entry->tags); + gst_tag_list_unref (entry->tags); if (entry->info != NULL) gst_structure_free (entry->info); @@ -305,22 +227,16 @@ static GstStructure * gst_toc_structure_new (GstTagList * tags, GstStructure * info) { GstStructure *ret; - GValue val = { 0 }; - ret = gst_structure_new_id_empty (gst_toc_fields[GST_TOC_TOC]); + ret = gst_structure_new_id_empty (GST_QUARK (TOC)); if (tags != NULL) { - g_value_init (&val, GST_TYPE_STRUCTURE); - gst_value_set_structure (&val, GST_STRUCTURE (tags)); - gst_structure_id_set_value (ret, gst_toc_fields[GST_TOC_TAGS], &val); - g_value_unset (&val); + gst_structure_id_set (ret, GST_QUARK (TAGS), GST_TYPE_TAG_LIST, tags, NULL); } if (info != NULL) { - g_value_init (&val, GST_TYPE_STRUCTURE); - gst_value_set_structure (&val, info); - gst_structure_id_set_value (ret, gst_toc_fields[GST_TOC_INFO], &val); - g_value_unset (&val); + gst_structure_id_set (ret, GST_QUARK (INFO), GST_TYPE_STRUCTURE, info, + NULL); } return ret; @@ -330,31 +246,21 @@ static GstStructure * gst_toc_entry_structure_new (GstTocEntryType type, const gchar * uid, GstTagList * tags, GstStructure * info) { - GValue val = { 0 }; GstStructure *ret; - ret = gst_structure_new_id_empty (gst_toc_fields[GST_TOC_ENTRY]); + ret = gst_structure_new_id_empty (GST_QUARK (TOC_ENTRY)); - gst_structure_id_set (ret, gst_toc_fields[GST_TOC_TYPE], - GST_TYPE_TOC_ENTRY_TYPE, type, NULL); - - g_value_init (&val, G_TYPE_STRING); - g_value_set_string (&val, uid); - gst_structure_id_set_value (ret, gst_toc_fields[GST_TOC_UID], &val); - g_value_unset (&val); + gst_structure_id_set (ret, GST_QUARK (TYPE), GST_TYPE_TOC_ENTRY_TYPE, type, + NULL); + gst_structure_id_set (ret, GST_QUARK (UID), G_TYPE_STRING, uid, NULL); if (tags != NULL) { - g_value_init (&val, GST_TYPE_STRUCTURE); - gst_value_set_structure (&val, GST_STRUCTURE (tags)); - gst_structure_id_set_value (ret, gst_toc_fields[GST_TOC_TAGS], &val); - g_value_unset (&val); + gst_structure_id_set (ret, GST_QUARK (TAGS), GST_TYPE_TAG_LIST, tags, NULL); } if (info != NULL) { - g_value_init (&val, GST_TYPE_STRUCTURE); - gst_value_set_structure (&val, info); - gst_structure_id_set_value (ret, gst_toc_fields[GST_TOC_INFO], &val); - g_value_unset (&val); + gst_structure_id_set (ret, GST_QUARK (INFO), GST_TYPE_STRUCTURE, info, + NULL); } return ret; @@ -364,11 +270,11 @@ static guint gst_toc_entry_structure_n_subentries (const GstStructure * entry) { if (G_UNLIKELY (!gst_structure_id_has_field_typed (entry, - gst_toc_fields[GST_TOC_SUBENTRIES], GST_TYPE_ARRAY))) + GST_QUARK (SUB_ENTRIES), GST_TYPE_ARRAY))) return 0; else return gst_value_array_get_size ((gst_structure_id_get_value (entry, - gst_toc_fields[GST_TOC_SUBENTRIES]))); + GST_QUARK (SUB_ENTRIES)))); } static const GstStructure * @@ -383,12 +289,12 @@ gst_toc_entry_structure_nth_subentry (const GstStructure * entry, guint nth) return NULL; if (G_UNLIKELY (!gst_structure_id_has_field_typed (entry, - gst_toc_fields[GST_TOC_SUBENTRIES], GST_TYPE_ARRAY))) + GST_QUARK (SUB_ENTRIES), GST_TYPE_ARRAY))) return NULL; else { array = gst_value_array_get_value (gst_structure_id_get_value (entry, - gst_toc_fields[GST_TOC_SUBENTRIES]), nth); + GST_QUARK (SUB_ENTRIES)), nth); return gst_value_get_structure (array); } } @@ -407,20 +313,20 @@ gst_toc_entry_from_structure (const GstStructure * entry, guint level) g_return_val_if_fail (entry != NULL, NULL); g_return_val_if_fail (gst_structure_id_has_field_typed (entry, - gst_toc_fields[GST_TOC_UID], G_TYPE_STRING), NULL); + GST_QUARK (UID), G_TYPE_STRING), NULL); g_return_val_if_fail (gst_structure_id_has_field_typed (entry, - gst_toc_fields[GST_TOC_TYPE], GST_TYPE_TOC_ENTRY_TYPE), NULL); + GST_QUARK (TYPE), GST_TYPE_TOC_ENTRY_TYPE), NULL); - val = gst_structure_id_get_value (entry, gst_toc_fields[GST_TOC_UID]); + val = gst_structure_id_get_value (entry, GST_QUARK (UID)); uid = g_value_get_string (val); ret = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_CHAPTER, uid); - gst_structure_get_enum (entry, GST_TOC_ENTRY_TYPE_FIELD, + gst_structure_get_enum (entry, g_quark_to_string (GST_QUARK (TYPE)), GST_TYPE_TOC_ENTRY_TYPE, (gint *) & (ret->type)); if (gst_structure_id_has_field_typed (entry, - gst_toc_fields[GST_TOC_SUBENTRIES], GST_TYPE_ARRAY)) { + GST_QUARK (SUB_ENTRIES), GST_TYPE_ARRAY)) { count = gst_toc_entry_structure_n_subentries (entry); for (i = 0; i < count; ++i) { @@ -460,20 +366,20 @@ gst_toc_entry_from_structure (const GstStructure * entry, guint level) ret->subentries = g_list_reverse (ret->subentries); } - if (gst_structure_id_has_field_typed (entry, - gst_toc_fields[GST_TOC_TAGS], GST_TYPE_STRUCTURE)) { - val = gst_structure_id_get_value (entry, gst_toc_fields[GST_TOC_TAGS]); + if (gst_structure_id_has_field_typed (entry, GST_QUARK (TAGS), + GST_TYPE_TAG_LIST)) { + val = gst_structure_id_get_value (entry, GST_QUARK (TAGS)); - if (G_LIKELY (GST_IS_TAG_LIST (gst_value_get_structure (val)))) { - list = gst_tag_list_copy (GST_TAG_LIST (gst_value_get_structure (val))); - gst_tag_list_free (ret->tags); + if (G_LIKELY (GST_IS_TAG_LIST (g_value_get_boxed (val)))) { + list = gst_tag_list_copy (GST_TAG_LIST (g_value_get_boxed (val))); + gst_tag_list_unref (ret->tags); ret->tags = list; } } if (gst_structure_id_has_field_typed (entry, - gst_toc_fields[GST_TOC_INFO], GST_TYPE_STRUCTURE)) { - val = gst_structure_id_get_value (entry, gst_toc_fields[GST_TOC_INFO]); + GST_QUARK (INFO), GST_TYPE_STRUCTURE)) { + val = gst_structure_id_get_value (entry, GST_QUARK (INFO)); if (G_LIKELY (GST_IS_STRUCTURE (gst_value_get_structure (val)))) { st = gst_structure_copy (gst_value_get_structure (val)); @@ -502,7 +408,7 @@ __gst_toc_from_structure (const GstStructure * toc) ret = gst_toc_new (); if (gst_structure_id_has_field_typed (toc, - gst_toc_fields[GST_TOC_SUBENTRIES], GST_TYPE_ARRAY)) { + GST_QUARK (SUB_ENTRIES), GST_TYPE_ARRAY)) { count = gst_toc_entry_structure_n_subentries (toc); for (i = 0; i < count; ++i) { @@ -544,20 +450,20 @@ __gst_toc_from_structure (const GstStructure * toc) ret->entries = g_list_reverse (ret->entries); } - if (gst_structure_id_has_field_typed (toc, - gst_toc_fields[GST_TOC_TAGS], GST_TYPE_STRUCTURE)) { - val = gst_structure_id_get_value (toc, gst_toc_fields[GST_TOC_TAGS]); + if (gst_structure_id_has_field_typed (toc, GST_QUARK (TAGS), + GST_TYPE_TAG_LIST)) { + val = gst_structure_id_get_value (toc, GST_QUARK (TAGS)); - if (G_LIKELY (GST_IS_TAG_LIST (gst_value_get_structure (val)))) { - list = gst_tag_list_copy (GST_TAG_LIST (gst_value_get_structure (val))); - gst_tag_list_free (ret->tags); + if (G_LIKELY (GST_IS_TAG_LIST (g_value_get_boxed (val)))) { + list = gst_tag_list_copy (GST_TAG_LIST (g_value_get_boxed (val))); + gst_tag_list_unref (ret->tags); ret->tags = list; } } if (gst_structure_id_has_field_typed (toc, - gst_toc_fields[GST_TOC_INFO], GST_TYPE_STRUCTURE)) { - val = gst_structure_id_get_value (toc, gst_toc_fields[GST_TOC_INFO]); + GST_QUARK (INFO), GST_TYPE_STRUCTURE)) { + val = gst_structure_id_get_value (toc, GST_QUARK (INFO)); if (G_LIKELY (GST_IS_STRUCTURE (gst_value_get_structure (val)))) { st = gst_structure_copy (gst_value_get_structure (val)); @@ -647,8 +553,7 @@ gst_toc_entry_to_structure (const GstTocEntry * entry, guint level) cur = cur->next; } - gst_structure_id_set_value (ret, gst_toc_fields[GST_TOC_SUBENTRIES], - &subentries_val); + gst_structure_id_set_value (ret, GST_QUARK (SUB_ENTRIES), &subentries_val); g_value_unset (&subentries_val); g_value_unset (&entry_val); @@ -719,8 +624,7 @@ __gst_toc_to_structure (const GstToc * toc) cur = cur->next; } - gst_structure_id_set_value (ret, gst_toc_fields[GST_TOC_SUBENTRIES], - &subentries_val); + gst_structure_id_set_value (ret, GST_QUARK (SUB_ENTRIES), &subentries_val); g_value_unset (&val); g_value_unset (&subentries_val); @@ -808,7 +712,7 @@ gst_toc_entry_copy (const GstTocEntry * entry) if (GST_IS_TAG_LIST (entry->tags)) { list = gst_tag_list_copy (entry->tags); - gst_tag_list_free (ret->tags); + gst_tag_list_unref (ret->tags); ret->tags = list; } @@ -866,7 +770,7 @@ gst_toc_copy (const GstToc * toc) if (GST_IS_TAG_LIST (toc->tags)) { list = gst_tag_list_copy (toc->tags); - gst_tag_list_free (ret->tags); + gst_tag_list_unref (ret->tags); ret->tags = list; } @@ -903,21 +807,19 @@ gst_toc_entry_set_start_stop (GstTocEntry * entry, gint64 start, gint64 stop) g_return_if_fail (entry != NULL); g_return_if_fail (GST_IS_STRUCTURE (entry->info)); - if (gst_structure_id_has_field_typed (entry->info, - gst_toc_fields[GST_TOC_TIME], GST_TYPE_STRUCTURE)) { - val = - gst_structure_id_get_value (entry->info, gst_toc_fields[GST_TOC_TIME]); + if (gst_structure_id_has_field_typed (entry->info, GST_QUARK (TIME), + GST_TYPE_STRUCTURE)) { + val = gst_structure_id_get_value (entry->info, GST_QUARK (TIME)); structure = gst_structure_copy (gst_value_get_structure (val)); } if (structure == NULL) - structure = gst_structure_new_id_empty (gst_toc_fields[GST_TOC_TIMENAME]); + structure = gst_structure_new_id_empty (GST_QUARK (TIME_STRUCTURE)); - gst_structure_id_set (structure, gst_toc_fields[GST_TOC_TIME_START], - G_TYPE_INT64, start, gst_toc_fields[GST_TOC_TIME_STOP], G_TYPE_INT64, - stop, NULL); + gst_structure_id_set (structure, GST_QUARK (START), + G_TYPE_INT64, start, GST_QUARK (STOP), G_TYPE_INT64, stop, NULL); - gst_structure_id_set (entry->info, gst_toc_fields[GST_TOC_TIME], + gst_structure_id_set (entry->info, GST_QUARK (TIME), GST_TYPE_STRUCTURE, structure, NULL); gst_structure_free (structure); @@ -948,28 +850,28 @@ gst_toc_entry_get_start_stop (const GstTocEntry * entry, gint64 * start, g_return_val_if_fail (GST_IS_STRUCTURE (entry->info), FALSE); if (!gst_structure_id_has_field_typed (entry->info, - gst_toc_fields[GST_TOC_TIME], GST_TYPE_STRUCTURE)) + GST_QUARK (TIME), GST_TYPE_STRUCTURE)) return FALSE; - val = gst_structure_id_get_value (entry->info, gst_toc_fields[GST_TOC_TIME]); + val = gst_structure_id_get_value (entry->info, GST_QUARK (TIME)); structure = gst_value_get_structure (val); if (start != NULL) { if (gst_structure_id_has_field_typed (structure, - gst_toc_fields[GST_TOC_TIME_START], G_TYPE_INT64)) + GST_QUARK (START), G_TYPE_INT64)) *start = g_value_get_int64 (gst_structure_id_get_value (structure, - gst_toc_fields[GST_TOC_TIME_START])); + GST_QUARK (START))); else ret = FALSE; } if (stop != NULL) { if (gst_structure_id_has_field_typed (structure, - gst_toc_fields[GST_TOC_TIME_STOP], G_TYPE_INT64)) + GST_QUARK (STOP), G_TYPE_INT64)) *stop = g_value_get_int64 (gst_structure_id_get_value (structure, - gst_toc_fields[GST_TOC_TIME_STOP])); + GST_QUARK (STOP))); else ret = FALSE; } @@ -977,6 +879,25 @@ gst_toc_entry_get_start_stop (const GstTocEntry * entry, gint64 * start, return ret; } +/** + * gst_toc_entry_type_get_nick: + * @type: a #GstTocEntryType. + * + * Converts @type to a string representation. + * + * Returns: Returns the human-readable @type. Can be NULL if an error occurred. + * Since: 0.11.92 + */ +const gchar * +gst_toc_entry_type_get_nick (GstTocEntryType type) +{ + const gchar *entry_types[] = { "chapter", "edition" }; + + g_return_val_if_fail ((gint) type >= 0 + && (gint) type < G_N_ELEMENTS (entry_types), NULL); + return entry_types[type]; +} + gboolean __gst_toc_structure_get_updated (const GstStructure * toc) { @@ -985,8 +906,8 @@ __gst_toc_structure_get_updated (const GstStructure * toc) g_return_val_if_fail (GST_IS_STRUCTURE (toc), FALSE); if (G_LIKELY (gst_structure_id_has_field_typed (toc, - gst_toc_fields[GST_TOC_UPDATED], G_TYPE_BOOLEAN))) { - val = gst_structure_id_get_value (toc, gst_toc_fields[GST_TOC_UPDATED]); + GST_QUARK (UPDATED), G_TYPE_BOOLEAN))) { + val = gst_structure_id_get_value (toc, GST_QUARK (UPDATED)); return g_value_get_boolean (val); } @@ -996,14 +917,10 @@ __gst_toc_structure_get_updated (const GstStructure * toc) void __gst_toc_structure_set_updated (GstStructure * toc, gboolean updated) { - GValue val = { 0 }; - g_return_if_fail (toc != NULL); - g_value_init (&val, G_TYPE_BOOLEAN); - g_value_set_boolean (&val, updated); - gst_structure_id_set_value (toc, gst_toc_fields[GST_TOC_UPDATED], &val); - g_value_unset (&val); + gst_structure_id_set (toc, GST_QUARK (UPDATED), G_TYPE_BOOLEAN, updated, + NULL); } gchar * @@ -1014,8 +931,8 @@ __gst_toc_structure_get_extend_uid (const GstStructure * toc) g_return_val_if_fail (GST_IS_STRUCTURE (toc), NULL); if (G_LIKELY (gst_structure_id_has_field_typed (toc, - gst_toc_fields[GST_TOC_EXTENDUID], G_TYPE_STRING))) { - val = gst_structure_id_get_value (toc, gst_toc_fields[GST_TOC_EXTENDUID]); + GST_QUARK (EXTEND_UID), G_TYPE_STRING))) { + val = gst_structure_id_get_value (toc, GST_QUARK (EXTEND_UID)); return g_strdup (g_value_get_string (val)); } @@ -1026,13 +943,9 @@ void __gst_toc_structure_set_extend_uid (GstStructure * toc, const gchar * extend_uid) { - GValue val = { 0 }; - g_return_if_fail (toc != NULL); g_return_if_fail (extend_uid != NULL); - g_value_init (&val, G_TYPE_STRING); - g_value_set_string (&val, extend_uid); - gst_structure_id_set_value (toc, gst_toc_fields[GST_TOC_EXTENDUID], &val); - g_value_unset (&val); + gst_structure_id_set (toc, GST_QUARK (EXTEND_UID), G_TYPE_STRING, extend_uid, + NULL); } diff --git a/gst/gsttoc.h b/gst/gsttoc.h index a1a7b8c..d59cf84 100644 --- a/gst/gsttoc.h +++ b/gst/gsttoc.h @@ -29,6 +29,9 @@ G_BEGIN_DECLS +#define GST_TYPE_TOC (gst_toc_get_type ()) +#define GST_TYPE_TOC_ENTRY (gst_toc_entry_get_type ()) + typedef struct _GstTocEntry GstTocEntry; typedef struct _GstToc GstToc; @@ -90,10 +93,14 @@ struct _GstToc { gpointer _gst_reserved[GST_PADDING]; }; +/* functions to return type structures */ +GType gst_toc_get_type (void); +GType gst_toc_entry_get_type (void); + /* functions to create new structures */ GstToc * gst_toc_new (void); GstTocEntry * gst_toc_entry_new (GstTocEntryType type, const gchar *uid); -GstTocEntry * gst_toc_entry_new_with_pad (GstTocEntryType type, const gchar *uid, gpointer pad); +GstTocEntry * gst_toc_entry_new_with_pad (GstTocEntryType type, const gchar *uid, GstPad * pad); /* functions to free structures */ void gst_toc_entry_free (GstTocEntry *entry); @@ -105,6 +112,7 @@ GstToc * gst_toc_copy (const GstToc *toc); void gst_toc_entry_set_start_stop (GstTocEntry *entry, gint64 start, gint64 stop); gboolean gst_toc_entry_get_start_stop (const GstTocEntry *entry, gint64 *start, gint64 *stop); +const gchar * gst_toc_entry_type_get_nick (GstTocEntryType type); G_END_DECLS diff --git a/gst/gsturi.c b/gst/gsturi.c index afe2907..90e7461 100644 --- a/gst/gsturi.c +++ b/gst/gsturi.c @@ -578,6 +578,8 @@ gst_element_make_from_uri (const GstURIType type, const gchar * uri, g_return_val_if_fail (GST_URI_TYPE_IS_VALID (type), NULL); g_return_val_if_fail (gst_uri_is_valid (uri), NULL); + GST_DEBUG ("type:%d, uri:%s, elementname:%s", type, uri, elementname); + protocol = gst_uri_get_protocol (uri); possibilities = get_element_factories_from_uri_protocol (type, protocol); g_free (protocol); @@ -598,6 +600,7 @@ gst_element_make_from_uri (const GstURIType type, const gchar * uri, if (gst_uri_handler_set_uri (handler, uri, NULL)) break; + GST_WARNING ("element %s didn't accept the URI", GST_ELEMENT_NAME (ret)); gst_object_unref (ret); ret = NULL; } diff --git a/gst/gstutils.c b/gst/gstutils.c index 7771862..5c15341 100644 --- a/gst/gstutils.c +++ b/gst/gstutils.c @@ -2364,8 +2364,8 @@ gst_element_query_convert (GstElement * element, GstFormat src_format, * PAUSED. If the element supports seek in READY, it will always return %TRUE when * it receives the event in the READY state. * - * Returns: %TRUE if the seek operation succeeded (the seek might not always be - * executed instantly though) + * Returns: %TRUE if the seek operation succeeded. Flushing seeks will trigger a + * preroll, which will emit %GST_MESSAGE_ASYNC_DONE. * * Since: 0.10.7 */ @@ -2931,7 +2931,8 @@ gst_pad_query_accept_caps (GstPad * pad, GstCaps * caps) g_return_val_if_fail (GST_IS_PAD (pad), FALSE); g_return_val_if_fail (GST_IS_CAPS (caps), FALSE); - GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "accept caps of %p", caps); + GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "accept caps of %" + GST_PTR_FORMAT, caps); query = gst_query_new_accept_caps (caps); if (gst_pad_query (pad, query)) { diff --git a/gst/parse/Makefile.in b/gst/parse/Makefile.in index 5915f4d..17fcfe4 100644 --- a/gst/parse/Makefile.in +++ b/gst/parse/Makefile.in @@ -52,6 +52,7 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ +target_triplet = @target@ subdir = gst/parse DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in @@ -257,6 +258,10 @@ GST_VERSION_MICRO = @GST_VERSION_MICRO@ GST_VERSION_MINOR = @GST_VERSION_MINOR@ GST_VERSION_NANO = @GST_VERSION_NANO@ GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ HAVE_DOCBOOK2HTML = @HAVE_DOCBOOK2HTML@ HAVE_DOCBOOK2PS = @HAVE_DOCBOOK2PS@ HAVE_DVIPS = @HAVE_DVIPS@ @@ -409,7 +414,11 @@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ +target = @target@ target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ |