X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gst%2Fgstmeta.c;h=4bcaa7aa512ba83d06b20936c5fa5cd846ac6542;hb=ce43de86902c4e9c8ed4e9682602664cb9bce2ee;hp=ef6f53326c93fcf0e55fbfa4ee4b85f8f8a95563;hpb=10f7e52698ad2ad051c9ca2c261a7433bab5d791;p=platform%2Fupstream%2Fgstreamer.git diff --git a/gst/gstmeta.c b/gst/gstmeta.c index ef6f533..4bcaa7a 100644 --- a/gst/gstmeta.c +++ b/gst/gstmeta.c @@ -1,5 +1,7 @@ -/* Gnome-Streamer - * Copyright (C) <1999> Erik Walthinsen +/* GStreamer + * Copyright (C) 2011 Wim Taymans + * + * gstmeta.c: metadata operations * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -13,45 +15,263 @@ * * 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 + * + * 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" -#include -#include +#include "gstbuffer.h" +#include "gstmeta.h" +#include "gstinfo.h" +#include "gstutils.h" +static GHashTable *metainfo = NULL; +static GRWLock lock; -GstMeta *gst_meta_new_size(gint size) { - GstMeta *meta; +GQuark _gst_meta_transform_copy; +GQuark _gst_meta_tag_memory; - meta = g_malloc(size); - gst_meta_ref(meta); +void +_priv_gst_meta_initialize (void) +{ + g_rw_lock_init (&lock); + metainfo = g_hash_table_new (g_str_hash, g_str_equal); - return meta; + _gst_meta_transform_copy = g_quark_from_static_string ("gst-copy"); + _gst_meta_tag_memory = g_quark_from_static_string ("memory"); } -void gst_meta_ref(GstMeta *meta) { - g_return_if_fail(meta != NULL); +/** + * 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; - gst_trace_add_entry(NULL,0,meta,"ref meta"); - meta->refcount++; -} + g_return_val_if_fail (api != NULL, 0); + g_return_val_if_fail (tags != NULL, 0); -void gst_meta_unref(GstMeta *meta) { - g_return_if_fail(meta != NULL); + GST_CAT_DEBUG (GST_CAT_META, "register API \"%s\"", api); + type = g_pointer_type_register_static (api); - gst_trace_add_entry(NULL,0,meta,"unref meta"); - meta->refcount--; + if (type != 0) { + gint i; - if (meta->refcount == 0) { -// gst_trace_add_entry(NULL,0,meta,"destroy meta"); - g_free(meta); -// g_print("freeing metadata\n"); + 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_api_type_has_tag: + * @api: an API + * @tag: the tag to check + * + * Check if @api was registered with @tag. + * + * 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 (GType api, const gchar * impl, gsize size, + GstMetaInitFunction init_func, GstMetaFreeFunction free_func, + GstMetaTransformFunction transform_func) +{ + GstMetaInfo *info; + GType type; + + 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 = api; + info->type = type; + info->size = size; + info->init_func = init_func; + info->free_func = free_func; + info->transform_func = transform_func; + + GST_CAT_DEBUG (GST_CAT_META, + "register \"%s\" implementing \"%s\" of size %" G_GSIZE_FORMAT, impl, + g_type_name (api), size); + + g_rw_lock_writer_lock (&lock); + g_hash_table_insert (metainfo, (gpointer) impl, (gpointer) info); + g_rw_lock_writer_unlock (&lock); + + return info; +} + +/** + * gst_meta_get_info: + * @impl: the name + * + * Lookup a previously registered meta info structure by its implementation name + * @impl. + * + * Returns: (transfer none) (nullable): a #GstMetaInfo with @impl, or + * %NULL when no such metainfo exists. + */ +const GstMetaInfo * +gst_meta_get_info (const gchar * impl) +{ + GstMetaInfo *info; + + g_return_val_if_fail (impl != NULL, NULL); + + g_rw_lock_reader_lock (&lock); + info = g_hash_table_lookup (metainfo, impl); + g_rw_lock_reader_unlock (&lock); + + return info; +} + +/** + * gst_meta_get_seqnum: + * @meta: a #GstMeta + * + * Gets seqnum for this meta. + * + * Since: 1.16 + */ +guint64 +gst_meta_get_seqnum (const GstMeta * meta) +{ + 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; +} + +/** + * 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) +{ + guint64 seqnum1 = gst_meta_get_seqnum (meta1); + guint64 seqnum2 = gst_meta_get_seqnum (meta2); + + if (seqnum1 == seqnum2) + return 0; -GstMeta *gst_meta_cow(GstMeta *meta) { - g_return_if_fail(meta != NULL); + return (seqnum1 < seqnum2) ? -1 : 1; }