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
This commit is contained in:
Wim Taymans 2012-02-29 17:20:23 +01:00
parent fc01e757cf
commit e80296cf46
11 changed files with 134 additions and 90 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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