X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gst%2Fgstmeta.c;h=4bcaa7aa512ba83d06b20936c5fa5cd846ac6542;hb=e6bd5b41935f125bf43e030dcb909c3537d33b31;hp=078aef14aa3da41d5390c7bcdb02b40965bfcaf8;hpb=52cb649834fbd57f110475f85281d3c0ac7e008f;p=platform%2Fupstream%2Fgstreamer.git diff --git a/gst/gstmeta.c b/gst/gstmeta.c index 078aef1..4bcaa7a 100644 --- a/gst/gstmeta.c +++ b/gst/gstmeta.c @@ -15,15 +15,34 @@ * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. */ /** * SECTION:gstmeta + * @title: GstMeta * @short_description: Buffer metadata * - * Last reviewed on December 17th, 2009 (0.10.26) + * The #GstMeta structure should be included as the first member of a #GstBuffer + * metadata structure. The structure defines the API of the metadata and should + * be accessible to all elements using the metadata. + * + * A metadata API is registered with gst_meta_api_type_register() which takes a + * name for the metadata API and some tags associated with the metadata. + * With gst_meta_api_type_has_tag() one can check if a certain metadata API + * contains a given tag. + * + * Multiple implementations of a metadata API can be registered. + * To implement a metadata API, gst_meta_register() should be used. This + * function takes all parameters needed to create, free and transform metadata + * along with the size of the metadata. The function returns a #GstMetaInfo + * structure that contains the information for the implementation of the API. + * + * A specific implementation can be retrieved by name with gst_meta_get_info(). + * + * See #GstBuffer for how the metadata can be added, retrieved and removed from + * buffers. */ #include "gst_private.h" @@ -33,50 +52,154 @@ #include "gstutils.h" static GHashTable *metainfo = NULL; -static GStaticRWLock lock = G_STATIC_RW_LOCK_INIT; +static GRWLock lock; + +GQuark _gst_meta_transform_copy; +GQuark _gst_meta_tag_memory; void _priv_gst_meta_initialize (void) { + g_rw_lock_init (&lock); metainfo = g_hash_table_new (g_str_hash, g_str_equal); + + _gst_meta_transform_copy = g_quark_from_static_string ("gst-copy"); + _gst_meta_tag_memory = g_quark_from_static_string ("memory"); +} + +/** + * gst_meta_api_type_register: + * @api: an API to register + * @tags: (array zero-terminated=1): tags for @api + * + * Register and return a GType for the @api and associate it with + * @tags. + * + * Returns: a unique GType for @api. + */ +GType +gst_meta_api_type_register (const gchar * api, const gchar ** tags) +{ + GType type; + + g_return_val_if_fail (api != NULL, 0); + g_return_val_if_fail (tags != NULL, 0); + + GST_CAT_DEBUG (GST_CAT_META, "register API \"%s\"", api); + type = g_pointer_type_register_static (api); + + if (type != 0) { + gint i; + + for (i = 0; tags[i]; i++) { + GST_CAT_DEBUG (GST_CAT_META, " adding tag \"%s\"", tags[i]); + g_type_set_qdata (type, g_quark_from_string (tags[i]), + GINT_TO_POINTER (TRUE)); + } + } + + g_type_set_qdata (type, g_quark_from_string ("tags"), + g_strdupv ((gchar **) tags)); + + return type; } /** - * gst_meta_register_info: - * @info: a #GstMetaInfo + * gst_meta_api_type_has_tag: + * @api: an API + * @tag: the tag to check * - * Register a #GstMetaInfo. The same @info can be retrieved later with - * gst_meta_get_info() by using @impl as the key. + * Check if @api was registered with @tag. * - * Returns: a #GstMetaInfo that can be used to access metadata. + * Returns: %TRUE if @api was registered with @tag. + */ +gboolean +gst_meta_api_type_has_tag (GType api, GQuark tag) +{ + g_return_val_if_fail (api != 0, FALSE); + g_return_val_if_fail (tag != 0, FALSE); + + return g_type_get_qdata (api, tag) != NULL; +} + +/** + * gst_meta_api_type_get_tags: + * @api: an API + * + * Returns: (transfer none) (array zero-terminated=1) (element-type utf8): an array of tags as strings. + * + * Since: 1.2 + */ +const gchar *const * +gst_meta_api_type_get_tags (GType api) +{ + const gchar **tags; + g_return_val_if_fail (api != 0, FALSE); + + tags = g_type_get_qdata (api, g_quark_from_string ("tags")); + + if (!tags[0]) + return NULL; + + return (const gchar * const *) tags; +} + +/** + * gst_meta_register: + * @api: the type of the #GstMeta API + * @impl: the name of the #GstMeta implementation + * @size: the size of the #GstMeta structure + * @init_func: (scope async): a #GstMetaInitFunction + * @free_func: (scope async): a #GstMetaFreeFunction + * @transform_func: (scope async): a #GstMetaTransformFunction + * + * Register a new #GstMeta implementation. + * + * The same @info can be retrieved later with gst_meta_get_info() by using + * @impl as the key. + * + * Returns: (transfer none) (nullable): a #GstMetaInfo that can be used to + * access metadata. */ const GstMetaInfo * -gst_meta_register (const gchar * api, const gchar * impl, gsize size, +gst_meta_register (GType api, const gchar * impl, gsize size, GstMetaInitFunction init_func, GstMetaFreeFunction free_func, - GstMetaCopyFunction copy_func, GstMetaTransformFunction transform_func) + GstMetaTransformFunction transform_func) { GstMetaInfo *info; + GType type; - g_return_val_if_fail (api != NULL, NULL); + g_return_val_if_fail (api != 0, NULL); g_return_val_if_fail (impl != NULL, NULL); g_return_val_if_fail (size != 0, NULL); + if (init_func == NULL) + g_critical ("Registering meta implementation '%s' without init function", + impl); + + /* first try to register the implementation name. It's possible + * that this fails because it was already registered. Don't warn, + * glib did this for us already. */ + type = g_pointer_type_register_static (impl); + if (type == 0) + return NULL; + info = g_slice_new (GstMetaInfo); - info->api = g_quark_from_string (api); - info->type = g_pointer_type_register_static (impl); + info->api = api; + info->type = type; info->size = size; info->init_func = init_func; info->free_func = free_func; - info->copy_func = copy_func; info->transform_func = transform_func; - GST_DEBUG ("register \"%s\" implementing \"%s\" of size %" G_GSIZE_FORMAT, - api, impl, size); + GST_CAT_DEBUG (GST_CAT_META, + "register \"%s\" implementing \"%s\" of size %" G_GSIZE_FORMAT, impl, + g_type_name (api), size); - g_static_rw_lock_writer_lock (&lock); + g_rw_lock_writer_lock (&lock); g_hash_table_insert (metainfo, (gpointer) impl, (gpointer) info); - g_static_rw_lock_writer_unlock (&lock); + g_rw_lock_writer_unlock (&lock); return info; } @@ -85,11 +208,11 @@ gst_meta_register (const gchar * api, const gchar * impl, gsize size, * gst_meta_get_info: * @impl: the name * - * Lookup a previously registered meta info structure by its implementor name + * Lookup a previously registered meta info structure by its implementation name * @impl. * - * Returns: a #GstMetaInfo with @impl or #NULL when no such metainfo - * exists. + * Returns: (transfer none) (nullable): a #GstMetaInfo with @impl, or + * %NULL when no such metainfo exists. */ const GstMetaInfo * gst_meta_get_info (const gchar * impl) @@ -98,56 +221,57 @@ gst_meta_get_info (const gchar * impl) g_return_val_if_fail (impl != NULL, NULL); - g_static_rw_lock_reader_lock (&lock); + g_rw_lock_reader_lock (&lock); info = g_hash_table_lookup (metainfo, impl); - g_static_rw_lock_reader_unlock (&lock); + g_rw_lock_reader_unlock (&lock); return info; } -/* Timing metadata */ -static void -meta_timing_copy (GstBuffer * copybuf, GstMetaTiming * meta, - GstBuffer * buffer, gsize offset, gsize size) +/** + * gst_meta_get_seqnum: + * @meta: a #GstMeta + * + * Gets seqnum for this meta. + * + * Since: 1.16 + */ +guint64 +gst_meta_get_seqnum (const GstMeta * meta) { - GstMetaTiming *timing; - - GST_DEBUG ("trans called from buffer %p to %p, meta %p," - "offset %" G_GSIZE_FORMAT ", size %" G_GSIZE_FORMAT, buffer, - copybuf, meta, offset, size); - - timing = gst_buffer_add_meta_timing (copybuf); - if (offset == 0) { - /* same offset, copy timestamps */ - timing->pts = meta->pts; - timing->dts = meta->dts; - if (size == gst_buffer_get_size (buffer)) { - /* same size, copy duration */ - timing->duration = meta->duration; - } else { - /* else clear */ - timing->duration = GST_CLOCK_TIME_NONE; - } - } else { - timing->pts = -1; - timing->dts = -1; - timing->duration = -1; - } - timing->clock_rate = meta->clock_rate; + GstMetaItem *meta_item; + guint8 *p; + + g_return_val_if_fail (meta != NULL, 0); + + p = (guint8 *) meta; + p -= G_STRUCT_OFFSET (GstMetaItem, meta); + meta_item = (GstMetaItem *) p; + return meta_item->seq_num; } -const GstMetaInfo * -gst_meta_timing_get_info (void) +/** + * gst_meta_compare_seqnum: + * @meta1: a #GstMeta + * @meta2: a #GstMeta + * + * Meta sequence number compare function. Can be used as #GCompareFunc + * or a #GCompareDataFunc. + * + * Returns: a negative number if @meta1 comes before @meta2, 0 if both metas + * have an equal sequence number, or a positive integer if @meta1 comes + * after @meta2. + * + * Since: 1.16 + */ +gint +gst_meta_compare_seqnum (const GstMeta * meta1, const GstMeta * meta2) { - static const GstMetaInfo *meta_info = NULL; - - if (meta_info == NULL) { - meta_info = gst_meta_register ("GstMetaTiming", "GstMetaTiming", - sizeof (GstMetaTiming), - (GstMetaInitFunction) NULL, - (GstMetaFreeFunction) NULL, - (GstMetaCopyFunction) meta_timing_copy, - (GstMetaTransformFunction) NULL); - } - return meta_info; + guint64 seqnum1 = gst_meta_get_seqnum (meta1); + guint64 seqnum2 = gst_meta_get_seqnum (meta2); + + if (seqnum1 == seqnum2) + return 0; + + return (seqnum1 < seqnum2) ? -1 : 1; }