From e80296cf4617ff59f235da156d6508736fdeeb13 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 29 Feb 2012 17:20:23 +0100 Subject: [PATCH] meta: split registration of API and implementation Split out the registration of the metadata API and its implementation. Make a GType for each metadata API. This allows us to store extra information with the API type such as the tags. Change the buffer API so that we can get the metadata using the API GType. Change the query API so that we use the metadata API GType in the allocation query instead of a string. Update netaddress and unit tests --- gst/gstbuffer.c | 14 +++-- gst/gstbuffer.h | 2 +- gst/gstmeta.c | 91 +++++++++++++++++++------------- gst/gstmeta.h | 22 ++++---- gst/gstquery.c | 33 +++++------- gst/gstquery.h | 6 +-- libs/gst/net/gstnetaddressmeta.c | 19 +++++-- libs/gst/net/gstnetaddressmeta.h | 9 +++- tests/check/gst/gstmeta.c | 24 +++++++-- win32/common/libgstnet.def | 1 + win32/common/libgstreamer.def | 3 +- 11 files changed, 134 insertions(+), 90 deletions(-) diff --git a/gst/gstbuffer.c b/gst/gstbuffer.c index b3d4efdc54..1b1db7e081 100644 --- a/gst/gstbuffer.c +++ b/gst/gstbuffer.c @@ -1474,28 +1474,26 @@ gst_buffer_span (GstBuffer * buf1, gsize offset, GstBuffer * buf2, gsize size) /** * gst_buffer_get_meta: * @buffer: a #GstBuffer - * @info: a #GstMetaInfo + * @api: the #GType of an API * - * Get the metadata for the api in @info on buffer. When there is no such + * Get the metadata for @api on buffer. When there is no such * metadata, NULL is returned. * - * Note that the result metadata might not be of the implementation @info. - * - * Returns: the metadata for the api in @info on @buffer. + * Returns: the metadata for @api on @buffer. */ GstMeta * -gst_buffer_get_meta (GstBuffer * buffer, const GstMetaInfo * info) +gst_buffer_get_meta (GstBuffer * buffer, GType api) { GstMetaItem *item; GstMeta *result = NULL; g_return_val_if_fail (buffer != NULL, NULL); - g_return_val_if_fail (info != NULL, NULL); + g_return_val_if_fail (api != 0, NULL); /* find GstMeta of the requested API */ for (item = GST_BUFFER_META (buffer); item; item = item->next) { GstMeta *meta = &item->meta; - if (meta->info->api == info->api) { + if (meta->info->api == api) { result = meta; break; } diff --git a/gst/gstbuffer.h b/gst/gstbuffer.h index 87ff09007e..57052d5073 100644 --- a/gst/gstbuffer.h +++ b/gst/gstbuffer.h @@ -506,7 +506,7 @@ GstBuffer* gst_buffer_span (GstBuffer *buf1, gsize offset, typedef gboolean (*GstBufferForeachMetaFunc) (GstBuffer *buffer, GstMeta **meta, gpointer user_data); -GstMeta * gst_buffer_get_meta (GstBuffer *buffer, const GstMetaInfo *info); +GstMeta * gst_buffer_get_meta (GstBuffer *buffer, GType api); GstMeta * gst_buffer_add_meta (GstBuffer *buffer, const GstMetaInfo *info, gpointer params); gboolean gst_buffer_remove_meta (GstBuffer *buffer, GstMeta *meta); diff --git a/gst/gstmeta.c b/gst/gstmeta.c index db699336ca..7865030d3f 100644 --- a/gst/gstmeta.c +++ b/gst/gstmeta.c @@ -46,9 +46,57 @@ _priv_gst_meta_initialize (void) _gst_meta_transform_copy = g_quark_from_static_string ("copy"); } +/** + * gst_meta_api_type_register: + * @api: an API to register + * @tags: 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); + + type = g_pointer_type_register_static (api); + + if (type != 0) { + gint i; + + for (i = 0; tags[i]; i++) + g_type_set_qdata (type, g_quark_from_string (tags[i]), + GINT_TO_POINTER (TRUE)); + } + 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_register: - * @api: the name of the #GstMeta API + * @api: the type of the #GstMeta API * @impl: the name of the #GstMeta implementation * @size: the size of the #GstMeta structure * @init_func: a #GstMetaInitFunction @@ -66,33 +114,24 @@ _priv_gst_meta_initialize (void) */ 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, - GstMetaTransformFunction transform_func, const gchar ** tags) + GstMetaTransformFunction transform_func) { GstMetaInfo *info; - guint len, i; - GQuark *qtags; - 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); - g_return_val_if_fail (tags != NULL, NULL); info = g_slice_new (GstMetaInfo); - info->api = g_quark_from_string (api); + info->api = api; info->type = g_pointer_type_register_static (impl); info->size = size; info->init_func = init_func; info->free_func = free_func; info->transform_func = transform_func; - len = g_strv_length ((gchar **) tags); - qtags = g_new0 (GQuark, len); - for (i = 0; i < len; i++) - qtags[i] = g_quark_from_static_string (tags[i]); - info->tags = qtags; - GST_DEBUG ("register \"%s\" implementing \"%s\" of size %" G_GSIZE_FORMAT, api, impl, size); @@ -126,27 +165,3 @@ gst_meta_get_info (const gchar * impl) return info; } - -/* - * gst_meta_info_has_tag: - * @info: a #GstMetaInfo - * @tag: a #GQuark - * - * Check if @info contains @tag. - * - * Returns: %TRUE when @info contains @tag. - */ -gboolean -gst_meta_info_has_tag (const GstMetaInfo * info, GQuark tag) -{ - gint i; - - g_return_val_if_fail (info != NULL, FALSE); - g_return_val_if_fail (tag != 0, FALSE); - - for (i = 0; info->tags[i]; i++) - if (info->tags[i] == tag) - return TRUE; - - return FALSE; -} diff --git a/gst/gstmeta.h b/gst/gstmeta.h index 9d820c21bd..55035344b7 100644 --- a/gst/gstmeta.h +++ b/gst/gstmeta.h @@ -170,7 +170,7 @@ typedef gboolean (*GstMetaTransformFunction) (GstBuffer *transbuf, * structure. */ struct _GstMetaInfo { - GQuark api; + GType api; GType type; gsize size; @@ -178,21 +178,21 @@ struct _GstMetaInfo { GstMetaFreeFunction free_func; GstMetaTransformFunction transform_func; - const GQuark *tags; - /*< private >*/ gpointer _gst_reserved[GST_PADDING]; }; -const GstMetaInfo * gst_meta_register (const gchar *api, const gchar *impl, - gsize size, - GstMetaInitFunction init_func, - GstMetaFreeFunction free_func, - GstMetaTransformFunction transform_func, - const gchar **tags); -const GstMetaInfo * gst_meta_get_info (const gchar * impl); +GType gst_meta_api_type_register (const gchar *api, + const gchar **tags); +gboolean gst_meta_api_type_has_tag (GType api, GQuark tag); + +const GstMetaInfo * gst_meta_register (GType api, const gchar *impl, + gsize size, + GstMetaInitFunction init_func, + GstMetaFreeFunction free_func, + GstMetaTransformFunction transform_func); +const GstMetaInfo * gst_meta_get_info (const gchar * impl); -gboolean gst_meta_info_has_tag (const GstMetaInfo *info, GQuark tag); G_END_DECLS diff --git a/gst/gstquery.c b/gst/gstquery.c index f076361f6b..a3d4daed27 100644 --- a/gst/gstquery.c +++ b/gst/gstquery.c @@ -1713,20 +1713,18 @@ gst_query_parse_allocation_params (GstQuery * query, guint * size, * Add @api as aone of the supported metadata API to @query. */ void -gst_query_add_allocation_meta (GstQuery * query, const gchar * api) +gst_query_add_allocation_meta (GstQuery * query, GType api) { GArray *array; GstStructure *structure; g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION); - g_return_if_fail (api != NULL); + g_return_if_fail (api != 0); g_return_if_fail (gst_query_is_writable (query)); structure = GST_QUERY_STRUCTURE (query); - array = - ensure_array (structure, GST_QUARK (META), sizeof (const gchar *), NULL); + array = ensure_array (structure, GST_QUARK (META), sizeof (GType), NULL); - api = g_intern_string (api); g_array_append_val (array, api); } @@ -1748,8 +1746,7 @@ gst_query_get_n_allocation_metas (GstQuery * query) g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, 0); structure = GST_QUERY_STRUCTURE (query); - array = - ensure_array (structure, GST_QUARK (META), sizeof (const gchar *), NULL); + array = ensure_array (structure, GST_QUARK (META), sizeof (GType), NULL); return array->len; } @@ -1762,23 +1759,22 @@ gst_query_get_n_allocation_metas (GstQuery * query) * Parse an available query and get the metadata API * at @index of the metadata API array. * - * Returns: a #gchar of the metadata API at @index. + * Returns: a #GType of the metadata API at @index. */ -const gchar * +GType gst_query_parse_nth_allocation_meta (GstQuery * query, guint index) { GArray *array; - const gchar *ret = NULL; + GType ret = 0; GstStructure *structure; - g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, NULL); + g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, 0); structure = GST_QUERY_STRUCTURE (query); - array = - ensure_array (structure, GST_QUARK (META), sizeof (const gchar *), NULL); + array = ensure_array (structure, GST_QUARK (META), sizeof (GType), NULL); if (index < array->len) - ret = g_array_index (array, const gchar *, index); + ret = g_array_index (array, GType, index); return ret; } @@ -1793,22 +1789,21 @@ gst_query_parse_nth_allocation_meta (GstQuery * query, guint index) * Returns: TRUE when @api is in the list of metadata. */ gboolean -gst_query_has_allocation_meta (GstQuery * query, const gchar * api) +gst_query_has_allocation_meta (GstQuery * query, GType api) { GArray *array; GstStructure *structure; guint i, len; g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, FALSE); - g_return_val_if_fail (api != NULL, FALSE); + g_return_val_if_fail (api != 0, FALSE); structure = GST_QUERY_STRUCTURE (query); - array = - ensure_array (structure, GST_QUARK (META), sizeof (const gchar *), NULL); + array = ensure_array (structure, GST_QUARK (META), sizeof (GType), NULL); len = array->len; for (i = 0; i < len; i++) { - if (strcmp (api, g_array_index (array, const gchar *, i)) == 0) + if (g_array_index (array, GType, i) == api) return TRUE; } return FALSE; diff --git a/gst/gstquery.h b/gst/gstquery.h index 1f162121f6..38ef3fecbb 100644 --- a/gst/gstquery.h +++ b/gst/gstquery.h @@ -372,10 +372,10 @@ void gst_query_parse_allocation_params (GstQuery *query, guint *size, guint *max_buffers, guint *prefix, guint *alignment, GstBufferPool **pool); -void gst_query_add_allocation_meta (GstQuery *query, const gchar *api); +void gst_query_add_allocation_meta (GstQuery *query, GType api); guint gst_query_get_n_allocation_metas (GstQuery *query); -const gchar * gst_query_parse_nth_allocation_meta (GstQuery *query, guint index); -gboolean gst_query_has_allocation_meta (GstQuery *query, const gchar *api); +GType gst_query_parse_nth_allocation_meta (GstQuery *query, guint index); +gboolean gst_query_has_allocation_meta (GstQuery *query, GType api); void gst_query_add_allocation_memory (GstQuery *query, GstAllocator *allocator); guint gst_query_get_n_allocation_memories (GstQuery *query); diff --git a/libs/gst/net/gstnetaddressmeta.c b/libs/gst/net/gstnetaddressmeta.c index 12028deb66..af869aea40 100644 --- a/libs/gst/net/gstnetaddressmeta.c +++ b/libs/gst/net/gstnetaddressmeta.c @@ -64,17 +64,30 @@ net_address_meta_free (GstMeta * meta, GstBuffer * buffer) nmeta->addr = NULL; } +GType +gst_net_address_meta_api_get_type (void) +{ + static volatile GType type; + static const gchar *tags[] = { "origin", NULL }; + + if (g_once_init_enter (&type)) { + GType _type = gst_meta_api_type_register ("GstNetAddressMetaAPI", tags); + g_once_init_leave (&type, _type); + } + return type; +} + const GstMetaInfo * gst_net_address_meta_get_info (void) { static const GstMetaInfo *meta_info = NULL; - static const gchar *tags[] = { "origin", NULL }; if (meta_info == NULL) { - meta_info = gst_meta_register ("GstNetAddressMeta", "GstNetAddressMeta", + meta_info = gst_meta_register (GST_NET_ADDRESS_META_API_TYPE, + "GstNetAddressMeta", sizeof (GstNetAddressMeta), net_address_meta_init, - net_address_meta_free, net_address_meta_transform, tags); + net_address_meta_free, net_address_meta_transform); } return meta_info; } diff --git a/libs/gst/net/gstnetaddressmeta.h b/libs/gst/net/gstnetaddressmeta.h index c40cf480f1..0173d874a6 100644 --- a/libs/gst/net/gstnetaddressmeta.h +++ b/libs/gst/net/gstnetaddressmeta.h @@ -38,11 +38,16 @@ struct _GstNetAddressMeta { GSocketAddress *addr; }; +GType gst_net_address_meta_api_get_type (void); +#define GST_NET_ADDRESS_META_API_TYPE (gst_net_address_meta_api_get_type()) + +#define gst_buffer_get_net_address_meta(b) \ + ((GstNetAddressMeta*)gst_buffer_get_meta((b),GST_NET_ADDRESS_META_API_TYPE)) + +/* implementation */ const GstMetaInfo *gst_net_address_meta_get_info (void); #define GST_NET_ADDRESS_META_INFO (gst_net_address_meta_get_info()) -#define gst_buffer_get_net_address_meta(b) \ - ((GstNetAddressMeta*)gst_buffer_get_meta((b),GST_NET_ADDRESS_META_INFO)) GstNetAddressMeta * gst_buffer_add_net_address_meta (GstBuffer *buffer, GSocketAddress *addr); diff --git a/tests/check/gst/gstmeta.c b/tests/check/gst/gstmeta.c index 392b123524..b3ea3d7ce2 100644 --- a/tests/check/gst/gstmeta.c +++ b/tests/check/gst/gstmeta.c @@ -43,10 +43,13 @@ typedef struct GstClockTime clock_rate; } GstMetaTest; +static GType gst_meta_test_api_get_type (void); +#define GST_META_TEST_API_TYPE (gst_meta_test_api_get_type()) + static const GstMetaInfo *gst_meta_test_get_info (void); #define GST_META_TEST_INFO (gst_meta_test_get_info()) -#define GST_META_TEST_GET(buf) ((GstMetaTest *)gst_buffer_get_meta(buf,GST_META_TEST_INFO)) +#define GST_META_TEST_GET(buf) ((GstMetaTest *)gst_buffer_get_meta(buf,GST_META_TEST_API_TYPE)) #define GST_META_TEST_ADD(buf) ((GstMetaTest *)gst_buffer_add_meta(buf,GST_META_TEST_INFO,NULL)) #if 0 @@ -114,16 +117,29 @@ test_transform_func (GstBuffer * transbuf, GstMeta * meta, return TRUE; } +static GType +gst_meta_test_api_get_type (void) +{ + static volatile GType type; + static const gchar *tags[] = { "timing", NULL }; + + if (g_once_init_enter (&type)) { + GType _type = gst_meta_api_type_register ("GstMetaTestAPI", tags); + g_once_init_leave (&type, _type); + } + return type; +} + static const GstMetaInfo * gst_meta_test_get_info (void) { static const GstMetaInfo *meta_test_info = NULL; - static const gchar *tags[] = { "timing", NULL }; if (meta_test_info == NULL) { - meta_test_info = gst_meta_register ("GstMetaTest", "GstMetaTest", + meta_test_info = gst_meta_register (GST_META_TEST_API_TYPE, + "GstMetaTest", sizeof (GstMetaTest), - test_init_func, test_free_func, test_transform_func, tags); + test_init_func, test_free_func, test_transform_func); } return meta_test_info; } diff --git a/win32/common/libgstnet.def b/win32/common/libgstnet.def index 14685a2789..42c28ba6b5 100644 --- a/win32/common/libgstnet.def +++ b/win32/common/libgstnet.def @@ -1,5 +1,6 @@ EXPORTS gst_buffer_add_net_address_meta + gst_net_address_meta_api_get_type gst_net_address_meta_get_info gst_net_client_clock_get_type gst_net_client_clock_new diff --git a/win32/common/libgstreamer.def b/win32/common/libgstreamer.def index ce0c5158b7..4bafc0fd0d 100644 --- a/win32/common/libgstreamer.def +++ b/win32/common/libgstreamer.def @@ -584,9 +584,10 @@ EXPORTS gst_message_type_get_name gst_message_type_get_type gst_message_type_to_quark + gst_meta_api_type_has_tag + gst_meta_api_type_register gst_meta_flags_get_type gst_meta_get_info - gst_meta_info_has_tag gst_meta_register gst_mini_object_copy gst_mini_object_flags_get_type