mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 12:11:13 +00:00
buffermeta: add beginnings of buffer metadata
Add first implementation of arbitrary buffer metadata. We use a simple linked linked of slice allocated metadata chunks. Future implementations could use something more performant. Add get, remove, iterate methods to handle the metadata.
This commit is contained in:
parent
a27da6a919
commit
8468dadc77
10 changed files with 651 additions and 3 deletions
|
@ -209,6 +209,24 @@ gst_buffer_span
|
||||||
gst_buffer_join
|
gst_buffer_join
|
||||||
gst_buffer_merge
|
gst_buffer_merge
|
||||||
|
|
||||||
|
GstBufferMeta
|
||||||
|
|
||||||
|
gst_buffer_get_meta
|
||||||
|
gst_buffer_remove_meta
|
||||||
|
gst_buffer_iterate_meta
|
||||||
|
|
||||||
|
GstBufferMetaInfo
|
||||||
|
|
||||||
|
GstMetaInitFunction
|
||||||
|
GstMetaFreeFunction
|
||||||
|
GstMetaCopyFunction
|
||||||
|
GstMetaSubFunction
|
||||||
|
GstMetaSerializeFunction
|
||||||
|
GstMetaDeserializeFunction
|
||||||
|
|
||||||
|
gst_buffer_meta_get_info
|
||||||
|
gst_buffer_meta_register_info
|
||||||
|
|
||||||
<SUBSECTION Standard>
|
<SUBSECTION Standard>
|
||||||
GstBufferClass
|
GstBufferClass
|
||||||
GST_BUFFER
|
GST_BUFFER
|
||||||
|
|
|
@ -51,6 +51,7 @@ libgstreamer_@GST_MAJORMINOR@_la_SOURCES = \
|
||||||
gstbin.c \
|
gstbin.c \
|
||||||
gstbuffer.c \
|
gstbuffer.c \
|
||||||
gstbufferlist.c \
|
gstbufferlist.c \
|
||||||
|
gstbuffermeta.c \
|
||||||
gstbus.c \
|
gstbus.c \
|
||||||
gstcaps.c \
|
gstcaps.c \
|
||||||
gstchildproxy.c \
|
gstchildproxy.c \
|
||||||
|
@ -142,6 +143,7 @@ gst_headers = \
|
||||||
gstbin.h \
|
gstbin.h \
|
||||||
gstbuffer.h \
|
gstbuffer.h \
|
||||||
gstbufferlist.h \
|
gstbufferlist.h \
|
||||||
|
gstbuffermeta.h \
|
||||||
gstbus.h \
|
gstbus.h \
|
||||||
gstcaps.h \
|
gstcaps.h \
|
||||||
gstchildproxy.h \
|
gstchildproxy.h \
|
||||||
|
|
|
@ -668,6 +668,7 @@ init_post (GOptionContext * context, GOptionGroup * group, gpointer data,
|
||||||
_gst_format_initialize ();
|
_gst_format_initialize ();
|
||||||
_gst_query_initialize ();
|
_gst_query_initialize ();
|
||||||
_gst_caps_initialize ();
|
_gst_caps_initialize ();
|
||||||
|
_gst_buffer_meta_init ();
|
||||||
|
|
||||||
g_type_class_ref (gst_object_get_type ());
|
g_type_class_ref (gst_object_get_type ());
|
||||||
g_type_class_ref (gst_pad_get_type ());
|
g_type_class_ref (gst_pad_get_type ());
|
||||||
|
|
168
gst/gstbuffer.c
168
gst/gstbuffer.c
|
@ -130,6 +130,16 @@
|
||||||
|
|
||||||
GType _gst_buffer_type = 0;
|
GType _gst_buffer_type = 0;
|
||||||
|
|
||||||
|
typedef struct _GstBufferMetaItem GstBufferMetaItem;
|
||||||
|
|
||||||
|
struct _GstBufferMetaItem
|
||||||
|
{
|
||||||
|
GstBufferMetaItem *next;
|
||||||
|
GstBufferMeta meta;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ITEM_SIZE(info) ((info)->size + sizeof (GstBufferMetaItem))
|
||||||
|
|
||||||
/* buffer alignment in bytes
|
/* buffer alignment in bytes
|
||||||
* an alignment of 8 would be the same as malloc() guarantees
|
* an alignment of 8 would be the same as malloc() guarantees
|
||||||
*/
|
*/
|
||||||
|
@ -189,6 +199,8 @@ void
|
||||||
gst_buffer_copy_metadata (GstBuffer * dest, const GstBuffer * src,
|
gst_buffer_copy_metadata (GstBuffer * dest, const GstBuffer * src,
|
||||||
GstBufferCopyFlags flags)
|
GstBufferCopyFlags flags)
|
||||||
{
|
{
|
||||||
|
GstBufferMetaItem *walk;
|
||||||
|
|
||||||
g_return_if_fail (dest != NULL);
|
g_return_if_fail (dest != NULL);
|
||||||
g_return_if_fail (src != NULL);
|
g_return_if_fail (src != NULL);
|
||||||
|
|
||||||
|
@ -224,6 +236,14 @@ gst_buffer_copy_metadata (GstBuffer * dest, const GstBuffer * src,
|
||||||
if (flags & GST_BUFFER_COPY_CAPS) {
|
if (flags & GST_BUFFER_COPY_CAPS) {
|
||||||
gst_caps_replace (&GST_BUFFER_CAPS (dest), GST_BUFFER_CAPS (src));
|
gst_caps_replace (&GST_BUFFER_CAPS (dest), GST_BUFFER_CAPS (src));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (walk = src->priv; walk; walk = walk->next) {
|
||||||
|
GstBufferMeta *meta = &walk->meta;
|
||||||
|
const GstBufferMetaInfo *info = meta->info;
|
||||||
|
|
||||||
|
if (info->copy_func)
|
||||||
|
info->copy_func (dest, meta, src);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstBuffer *
|
static GstBuffer *
|
||||||
|
@ -269,6 +289,8 @@ _gst_buffer_copy (GstBuffer * buffer)
|
||||||
static void
|
static void
|
||||||
_gst_buffer_free (GstBuffer * buffer)
|
_gst_buffer_free (GstBuffer * buffer)
|
||||||
{
|
{
|
||||||
|
GList *walk;
|
||||||
|
|
||||||
g_return_if_fail (buffer != NULL);
|
g_return_if_fail (buffer != NULL);
|
||||||
|
|
||||||
GST_CAT_LOG (GST_CAT_BUFFER, "finalize %p", buffer);
|
GST_CAT_LOG (GST_CAT_BUFFER, "finalize %p", buffer);
|
||||||
|
@ -282,6 +304,18 @@ _gst_buffer_free (GstBuffer * buffer)
|
||||||
if (buffer->parent)
|
if (buffer->parent)
|
||||||
gst_buffer_unref (buffer->parent);
|
gst_buffer_unref (buffer->parent);
|
||||||
|
|
||||||
|
/* free metadata */
|
||||||
|
for (walk = buffer->priv; walk; walk = walk->next) {
|
||||||
|
GstBufferMeta *meta = &walk->meta;
|
||||||
|
const GstBufferMetaInfo *info = meta->info;
|
||||||
|
|
||||||
|
/* call free_func if any */
|
||||||
|
if (info->free_func)
|
||||||
|
info->free_func (meta, buffer);
|
||||||
|
/* and free the slice */
|
||||||
|
g_slice_free1 (ITEM_SIZE (info), meta);
|
||||||
|
}
|
||||||
|
|
||||||
g_slice_free1 (GST_MINI_OBJECT_SIZE (buffer), buffer);
|
g_slice_free1 (GST_MINI_OBJECT_SIZE (buffer), buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -558,6 +592,7 @@ gst_buffer_create_sub (GstBuffer * buffer, guint offset, guint size)
|
||||||
GstBuffer *subbuffer;
|
GstBuffer *subbuffer;
|
||||||
GstBuffer *parent;
|
GstBuffer *parent;
|
||||||
gboolean complete;
|
gboolean complete;
|
||||||
|
GstBufferMetaItem *walk;
|
||||||
|
|
||||||
g_return_val_if_fail (buffer != NULL, NULL);
|
g_return_val_if_fail (buffer != NULL, NULL);
|
||||||
g_return_val_if_fail (buffer->mini_object.refcount > 0, NULL);
|
g_return_val_if_fail (buffer->mini_object.refcount > 0, NULL);
|
||||||
|
@ -620,6 +655,14 @@ gst_buffer_create_sub (GstBuffer * buffer, guint offset, guint size)
|
||||||
GST_BUFFER_OFFSET_END (subbuffer) = GST_BUFFER_OFFSET_NONE;
|
GST_BUFFER_OFFSET_END (subbuffer) = GST_BUFFER_OFFSET_NONE;
|
||||||
GST_BUFFER_CAPS (subbuffer) = NULL;
|
GST_BUFFER_CAPS (subbuffer) = NULL;
|
||||||
}
|
}
|
||||||
|
/* call subbuffer functions for metadata */
|
||||||
|
for (walk = buffer->priv; walk; walk = walk->next) {
|
||||||
|
GstBufferMeta *meta = &walk->meta;
|
||||||
|
const GstBufferMetaInfo *info = meta->info;
|
||||||
|
|
||||||
|
if (info->sub_func)
|
||||||
|
info->sub_func (subbuffer, meta, buffer, offset, size);
|
||||||
|
}
|
||||||
return subbuffer;
|
return subbuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -727,3 +770,128 @@ gst_buffer_span (GstBuffer * buf1, guint32 offset, GstBuffer * buf2,
|
||||||
|
|
||||||
return newbuf;
|
return newbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_buffer_get_meta:
|
||||||
|
* @buffer: a #GstBuffer
|
||||||
|
* @info: a #GstBufferMetaInfo
|
||||||
|
*
|
||||||
|
* Retrieve the metadata for @info on @buffer.
|
||||||
|
*
|
||||||
|
* If there is no metadata for @info on @buffer, this function will return
|
||||||
|
* %NULL unless the @create flags is set to %TRUE, in which case a new
|
||||||
|
* metadata for @info will be created.
|
||||||
|
*
|
||||||
|
* Returns: the metadata for @info on @buffer or %NULL when there is no such
|
||||||
|
* metadata on @buffer and @create is %FALSE.
|
||||||
|
*/
|
||||||
|
GstBufferMeta *
|
||||||
|
gst_buffer_get_meta (GstBuffer * buffer, const GstBufferMetaInfo * info,
|
||||||
|
gboolean create)
|
||||||
|
{
|
||||||
|
GstBufferMetaItem *walk;
|
||||||
|
GstBufferMeta *result = NULL;
|
||||||
|
|
||||||
|
g_return_val_if_fail (buffer != NULL, NULL);
|
||||||
|
g_return_val_if_fail (info != NULL, NULL);
|
||||||
|
|
||||||
|
/* loop over the metadata items until we find the one with the
|
||||||
|
* requested info. FIXME, naive implementation using a list */
|
||||||
|
for (walk = buffer->priv; walk; walk = walk->next) {
|
||||||
|
GstBufferMeta *meta = &walk->meta;
|
||||||
|
if (meta->info == info) {
|
||||||
|
result = meta;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* not found, check if we need to create */
|
||||||
|
if (!result && create) {
|
||||||
|
/* create a new slice */
|
||||||
|
GST_DEBUG ("alloc metadata of size %" G_GSIZE_FORMAT, info->size);
|
||||||
|
walk = g_slice_alloc (ITEM_SIZE (info));
|
||||||
|
result = &walk->meta;
|
||||||
|
result->info = info;
|
||||||
|
/* call the init_func when needed */
|
||||||
|
if (info->init_func)
|
||||||
|
info->init_func (result, buffer);
|
||||||
|
/* and add to the list of metadata */
|
||||||
|
walk->next = buffer->priv;
|
||||||
|
buffer->priv = walk;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_buffer_remove_meta:
|
||||||
|
* @buffer: a #GstBuffer
|
||||||
|
* @info: a #GstBufferMetaInfo
|
||||||
|
*
|
||||||
|
* Remove the metadata for @info on @buffer.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if the metadata existed and was removed, %FALSE if no such
|
||||||
|
* metadata was on @buffer.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gst_buffer_remove_meta (GstBuffer * buffer, const GstBufferMetaInfo * info)
|
||||||
|
{
|
||||||
|
GstBufferMetaItem *walk, *prev;
|
||||||
|
|
||||||
|
g_return_val_if_fail (buffer != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (info != NULL, FALSE);
|
||||||
|
|
||||||
|
/* find the metadata and delete */
|
||||||
|
prev = buffer->priv;
|
||||||
|
for (walk = prev; walk; walk = walk->next) {
|
||||||
|
GstBufferMeta *meta = &walk->meta;
|
||||||
|
if (meta->info == info) {
|
||||||
|
/* remove from list */
|
||||||
|
if (buffer->priv == walk)
|
||||||
|
buffer->priv = walk->next;
|
||||||
|
else
|
||||||
|
prev->next = walk->next;
|
||||||
|
/* call free_func if any */
|
||||||
|
if (info->free_func)
|
||||||
|
info->free_func (meta, buffer);
|
||||||
|
/* and free the slice */
|
||||||
|
g_slice_free1 (ITEM_SIZE (info), meta);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
prev = walk;
|
||||||
|
}
|
||||||
|
return walk != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_buffer_iterate_meta:
|
||||||
|
* @buffer: a #GstBuffer
|
||||||
|
* @state: an opaque state pointer
|
||||||
|
*
|
||||||
|
* Retrieve the next #GstBufferMeta after @current. If @state points
|
||||||
|
* to %NULL, the first metadata is returned.
|
||||||
|
*
|
||||||
|
* @state will be updated with an opage state pointer
|
||||||
|
*
|
||||||
|
* Returns: The next #GstBufferMeta or %NULL when there are no more items.
|
||||||
|
*/
|
||||||
|
GstBufferMeta *
|
||||||
|
gst_buffer_iterate_meta (GstBuffer * buffer, gpointer * state)
|
||||||
|
{
|
||||||
|
GstBufferMetaItem **meta;
|
||||||
|
|
||||||
|
g_return_val_if_fail (buffer != NULL, NULL);
|
||||||
|
g_return_val_if_fail (state != NULL, NULL);
|
||||||
|
|
||||||
|
meta = (GstBufferMetaItem **) state;
|
||||||
|
if (*meta == NULL)
|
||||||
|
/* state NULL, move to first item */
|
||||||
|
*meta = buffer->priv;
|
||||||
|
else
|
||||||
|
/* state !NULL, move to next item in list */
|
||||||
|
*meta = (*meta)->next;
|
||||||
|
|
||||||
|
if (*meta)
|
||||||
|
return &(*meta)->meta;
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
|
@ -284,11 +284,9 @@ struct _GstBuffer {
|
||||||
/* ABI Added */
|
/* ABI Added */
|
||||||
GFreeFunc free_func;
|
GFreeFunc free_func;
|
||||||
GstBuffer *parent;
|
GstBuffer *parent;
|
||||||
|
gpointer priv;
|
||||||
|
|
||||||
gpointer owner_priv;
|
gpointer owner_priv;
|
||||||
|
|
||||||
/*< private >*/
|
|
||||||
gpointer _gst_reserved[GST_PADDING];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* allocation */
|
/* allocation */
|
||||||
|
@ -471,6 +469,15 @@ GstBuffer* gst_buffer_create_sub (GstBuffer *parent, guint offset
|
||||||
gboolean gst_buffer_is_span_fast (GstBuffer *buf1, GstBuffer *buf2);
|
gboolean gst_buffer_is_span_fast (GstBuffer *buf1, GstBuffer *buf2);
|
||||||
GstBuffer* gst_buffer_span (GstBuffer *buf1, guint32 offset, GstBuffer *buf2, guint32 len);
|
GstBuffer* gst_buffer_span (GstBuffer *buf1, guint32 offset, GstBuffer *buf2, guint32 len);
|
||||||
|
|
||||||
|
/* metadata */
|
||||||
|
#include <gst/gstbuffermeta.h>
|
||||||
|
|
||||||
|
GstBufferMeta * gst_buffer_get_meta (GstBuffer *buffer, const GstBufferMetaInfo *info,
|
||||||
|
gboolean create);
|
||||||
|
gboolean gst_buffer_remove_meta (GstBuffer *buffer, const GstBufferMetaInfo *info);
|
||||||
|
|
||||||
|
GstBufferMeta * gst_buffer_iterate_meta (GstBuffer *buffer, gpointer *state);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_value_set_buffer:
|
* gst_value_set_buffer:
|
||||||
* @v: a #GValue to receive the data
|
* @v: a #GValue to receive the data
|
||||||
|
|
91
gst/gstbuffermeta.c
Normal file
91
gst/gstbuffermeta.c
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) 2009 Wim Taymans <wim.taymans@gmail.com>
|
||||||
|
*
|
||||||
|
* gstbuffermeta.c: Buffer metadata operations
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:gstbuffermeta
|
||||||
|
* @short_description: Buffer metadata
|
||||||
|
*
|
||||||
|
* Last reviewed on December 17th, 2009 (0.10.26)
|
||||||
|
*/
|
||||||
|
#include "gst_private.h"
|
||||||
|
|
||||||
|
#include "gstbuffermeta.h"
|
||||||
|
#include "gstbuffer.h"
|
||||||
|
#include "gstinfo.h"
|
||||||
|
#include "gstutils.h"
|
||||||
|
|
||||||
|
static GHashTable *metainfo = NULL;
|
||||||
|
static GStaticRWLock lock = G_STATIC_RW_LOCK_INIT;
|
||||||
|
|
||||||
|
void
|
||||||
|
_gst_buffer_meta_init (void)
|
||||||
|
{
|
||||||
|
metainfo = g_hash_table_new (g_str_hash, g_str_equal);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_buffer_meta_register_info:
|
||||||
|
* @info: a #GstBufferMetaInfo
|
||||||
|
*
|
||||||
|
* Register a #GstBufferMetaInfo. The same @info can be retrieved later with
|
||||||
|
* gst_buffer_meta_get_info() by using the name as the key.
|
||||||
|
*
|
||||||
|
* Returns: a #GstBufferMetaInfo that can be used to access buffer metadata.
|
||||||
|
*/
|
||||||
|
const GstBufferMetaInfo *
|
||||||
|
gst_buffer_meta_register_info (const GstBufferMetaInfo * info)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (info != NULL, NULL);
|
||||||
|
g_return_val_if_fail (info->name != NULL, NULL);
|
||||||
|
g_return_val_if_fail (info->size != 0, NULL);
|
||||||
|
|
||||||
|
GST_DEBUG ("register \"%s\" of size %" G_GSIZE_FORMAT, info->name,
|
||||||
|
info->size);
|
||||||
|
|
||||||
|
g_static_rw_lock_writer_lock (&lock);
|
||||||
|
g_hash_table_insert (metainfo, (gpointer) info->name, (gpointer) info);
|
||||||
|
g_static_rw_lock_writer_unlock (&lock);
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_buffer_meta_get_info:
|
||||||
|
* @name: the name
|
||||||
|
*
|
||||||
|
* Lookup a previously registered meta info structure by its @name.
|
||||||
|
*
|
||||||
|
* Returns: a #GstBufferMetaInfo with @name or #NULL when no such metainfo
|
||||||
|
* exists.
|
||||||
|
*/
|
||||||
|
const GstBufferMetaInfo *
|
||||||
|
gst_buffer_meta_get_info (const gchar * name)
|
||||||
|
{
|
||||||
|
GstBufferMetaInfo *info;
|
||||||
|
|
||||||
|
g_return_val_if_fail (name != NULL, NULL);
|
||||||
|
|
||||||
|
g_static_rw_lock_reader_lock (&lock);
|
||||||
|
info = g_hash_table_lookup (metainfo, name);
|
||||||
|
g_static_rw_lock_reader_unlock (&lock);
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
139
gst/gstbuffermeta.h
Normal file
139
gst/gstbuffermeta.h
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) 2009 Wim Taymans <wim.taymans@gmail.be>
|
||||||
|
*
|
||||||
|
* gstbuffermeta.h: Header for Buffer Metadata structures
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __GST_BUFFER_META_H__
|
||||||
|
#define __GST_BUFFER_META_H__
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef struct _GstBufferMeta GstBufferMeta;
|
||||||
|
typedef struct _GstBufferMetaInfo GstBufferMetaInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstBufferMeta:
|
||||||
|
* @info: pointer to the #GstBufferMetaInfo
|
||||||
|
*
|
||||||
|
* Base structure for buffer metadata. Custom metadata will put this structure
|
||||||
|
* as the first member of their structure.
|
||||||
|
*/
|
||||||
|
struct _GstBufferMeta {
|
||||||
|
const GstBufferMetaInfo *info;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GST_BUFFER_META_TRACE_NAME:
|
||||||
|
*
|
||||||
|
* The name used for tracing memory allocations.
|
||||||
|
*/
|
||||||
|
#define GST_BUFFER_META_TRACE_NAME "GstBufferMeta"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstMetaInitFunction:
|
||||||
|
* @meta: a #GstMeta
|
||||||
|
* @buffer: a #GstBuffer
|
||||||
|
*
|
||||||
|
* Function called when @meta is initialized in @buffer.
|
||||||
|
*/
|
||||||
|
typedef void (*GstMetaInitFunction) (GstBufferMeta *meta, GstBuffer *buffer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstMetaFreeFunction:
|
||||||
|
* @meta: a #GstMeta
|
||||||
|
* @buffer: a #GstBuffer
|
||||||
|
*
|
||||||
|
* Function called when @meta is freed in @buffer.
|
||||||
|
*/
|
||||||
|
typedef void (*GstMetaFreeFunction) (GstBufferMeta *meta, GstBuffer *buffer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstMetaCopyFunction:
|
||||||
|
* @copy: a #GstBuffer
|
||||||
|
* @meta: a #GstMeta
|
||||||
|
* @buffer: a #GstBuffer
|
||||||
|
*
|
||||||
|
* Function called when a copy of @buffer is made and @meta should be copied to
|
||||||
|
* @copy.
|
||||||
|
*/
|
||||||
|
typedef void (*GstMetaCopyFunction) (GstBuffer *copy, GstBufferMeta *meta,
|
||||||
|
const GstBuffer *buffer);
|
||||||
|
/**
|
||||||
|
* GstMetaSubFunction:
|
||||||
|
* @subbuf: a #GstBuffer
|
||||||
|
* @meta: a #GstMeta
|
||||||
|
* @buffer: a #GstBuffer
|
||||||
|
* @offset: subbuffer offset
|
||||||
|
* @size: subbuffer size
|
||||||
|
*
|
||||||
|
* Function called for each @meta in @buffer as a result from creating a
|
||||||
|
* subbuffer @subbuf from @buffer at @offset and with @size. An
|
||||||
|
* implementation could decide to copy and update the metadata on @subbuf.
|
||||||
|
*/
|
||||||
|
typedef void (*GstMetaSubFunction) (GstBuffer *subbuf, GstBufferMeta *meta,
|
||||||
|
GstBuffer *buffer, guint offset, guint size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstMetaSerializeFunction:
|
||||||
|
* @meta: a #GstMeta
|
||||||
|
*/
|
||||||
|
typedef gchar * (*GstMetaSerializeFunction) (GstBufferMeta *meta);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstMetaDeserializeFunction:
|
||||||
|
* @meta: a #GstMeta
|
||||||
|
*/
|
||||||
|
typedef gboolean (*GstMetaDeserializeFunction) (GstBufferMeta *meta,
|
||||||
|
const gchar *s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstBufferMetaInfo:
|
||||||
|
* @name: tag indentifying the metadata
|
||||||
|
* @size: size of the metadata
|
||||||
|
* @init_func: function for initializing the metadata
|
||||||
|
* @free_func: function for freeing the metadata
|
||||||
|
* @copy_func: function for copying the metadata
|
||||||
|
* @sub_func: function for when a subbuffer is taken
|
||||||
|
* @serialize_func: function for serializing
|
||||||
|
* @deserialize_func: function for deserializing
|
||||||
|
*
|
||||||
|
* The #GstBufferMetaInfo provides infomation about a specific metadata
|
||||||
|
* structure.
|
||||||
|
*/
|
||||||
|
struct _GstBufferMetaInfo {
|
||||||
|
const gchar *name;
|
||||||
|
gsize size;
|
||||||
|
|
||||||
|
GstMetaInitFunction init_func;
|
||||||
|
GstMetaFreeFunction free_func;
|
||||||
|
GstMetaCopyFunction copy_func;
|
||||||
|
GstMetaSubFunction sub_func;
|
||||||
|
GstMetaSerializeFunction serialize_func;
|
||||||
|
GstMetaDeserializeFunction deserialize_func;
|
||||||
|
};
|
||||||
|
|
||||||
|
void _gst_buffer_meta_init (void);
|
||||||
|
|
||||||
|
const GstBufferMetaInfo * gst_buffer_meta_register_info (const GstBufferMetaInfo *info);
|
||||||
|
const GstBufferMetaInfo * gst_buffer_meta_get_info (const gchar * name);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GST_BUFFER_META_H__ */
|
|
@ -100,6 +100,7 @@ check_PROGRAMS = \
|
||||||
$(ABI_CHECKS) \
|
$(ABI_CHECKS) \
|
||||||
gst/gstbuffer \
|
gst/gstbuffer \
|
||||||
gst/gstbufferlist \
|
gst/gstbufferlist \
|
||||||
|
gst/gstbuffermeta \
|
||||||
gst/gstbus \
|
gst/gstbus \
|
||||||
gst/gstcaps \
|
gst/gstcaps \
|
||||||
$(CXX_CHECKS) \
|
$(CXX_CHECKS) \
|
||||||
|
|
211
tests/check/gst/gstbuffermeta.c
Normal file
211
tests/check/gst/gstbuffermeta.c
Normal file
|
@ -0,0 +1,211 @@
|
||||||
|
/* GStreamer
|
||||||
|
*
|
||||||
|
* unit test for GstBufferMeta
|
||||||
|
*
|
||||||
|
* Copyright (C) <2009> Wim Taymans <wim.taymans@gmail.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_VALGRIND_H
|
||||||
|
# include <valgrind/valgrind.h>
|
||||||
|
#else
|
||||||
|
# define RUNNING_ON_VALGRIND FALSE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <gst/check/gstcheck.h>
|
||||||
|
|
||||||
|
static const GstBufferMetaInfo *test_meta_info = NULL;
|
||||||
|
|
||||||
|
/* test metadata for PTS/DTS and duration */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GstBufferMeta meta;
|
||||||
|
|
||||||
|
GstClockTime pts;
|
||||||
|
GstClockTime dts;
|
||||||
|
GstClockTime duration;
|
||||||
|
GstClockTime clock_rate;
|
||||||
|
} GstTestMeta;
|
||||||
|
|
||||||
|
static const GstBufferMetaInfo *gst_test_meta_get_info (void);
|
||||||
|
|
||||||
|
#define GST_TEST_META_GET(buf,create) ((GstTestMeta *)gst_buffer_get_meta(buf,gst_test_meta_get_info(),create));
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* unused currently. This is a user function to fill the metadata with default
|
||||||
|
* values. We don't call this from the init function because the user is mostly
|
||||||
|
* likely going to override the values immediately after */
|
||||||
|
static void
|
||||||
|
gst_test_meta_init (GstTestMeta * meta)
|
||||||
|
{
|
||||||
|
meta->pts = GST_CLOCK_TIME_NONE;
|
||||||
|
meta->dts = GST_CLOCK_TIME_NONE;
|
||||||
|
meta->duration = GST_CLOCK_TIME_NONE;
|
||||||
|
meta->clock_rate = GST_SECOND;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_init_func (GstTestMeta * meta, GstBuffer * buffer)
|
||||||
|
{
|
||||||
|
GST_DEBUG ("init called on buffer %p, meta %p", buffer, meta);
|
||||||
|
/* nothing to init really, the init function is mostly for allocating
|
||||||
|
* additional memory or doing special setup as part of adding the metadata to
|
||||||
|
* the buffer*/
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_free_func (GstTestMeta * meta, GstBuffer * buffer)
|
||||||
|
{
|
||||||
|
GST_DEBUG ("free called on buffer %p, meta %p", buffer, meta);
|
||||||
|
/* nothing to free really */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_copy_func (GstBuffer * copy, GstTestMeta * meta, GstBuffer * buffer)
|
||||||
|
{
|
||||||
|
GstTestMeta *test;
|
||||||
|
|
||||||
|
GST_DEBUG ("copy called from buffer %p to %p, meta %p", buffer, copy, meta);
|
||||||
|
|
||||||
|
test = GST_TEST_META_GET (copy, TRUE);
|
||||||
|
test->pts = meta->pts;
|
||||||
|
test->dts = meta->dts;
|
||||||
|
test->duration = meta->duration;
|
||||||
|
test->clock_rate = meta->clock_rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_sub_func (GstBuffer * sub, GstTestMeta * meta, GstBuffer * buffer,
|
||||||
|
guint offset, guint size)
|
||||||
|
{
|
||||||
|
GstTestMeta *test;
|
||||||
|
|
||||||
|
GST_DEBUG ("sub called from buffer %p to %p, meta %p, %u-%u", buffer, sub,
|
||||||
|
meta, offset, size);
|
||||||
|
|
||||||
|
test = GST_TEST_META_GET (sub, TRUE);
|
||||||
|
if (offset == 0) {
|
||||||
|
/* same offset, copy timestamps */
|
||||||
|
test->pts = meta->pts;
|
||||||
|
test->dts = meta->dts;
|
||||||
|
if (size == GST_BUFFER_SIZE (buffer)) {
|
||||||
|
/* same size, copy duration */
|
||||||
|
test->duration = meta->duration;
|
||||||
|
} else {
|
||||||
|
/* else clear */
|
||||||
|
test->duration = GST_CLOCK_TIME_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
test->clock_rate = meta->clock_rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
register_metadata (void)
|
||||||
|
{
|
||||||
|
if (test_meta_info == NULL) {
|
||||||
|
static const GstBufferMetaInfo info = {
|
||||||
|
"GstTestMeta",
|
||||||
|
sizeof (GstTestMeta),
|
||||||
|
(GstMetaInitFunction) test_init_func,
|
||||||
|
(GstMetaFreeFunction) test_free_func,
|
||||||
|
(GstMetaCopyFunction) test_copy_func,
|
||||||
|
(GstMetaSubFunction) test_sub_func,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
test_meta_info = gst_buffer_meta_register_info (&info);
|
||||||
|
}
|
||||||
|
return test_meta_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_START_TEST (test_metadata)
|
||||||
|
{
|
||||||
|
GstBuffer *buffer, *copy, *subbuf;
|
||||||
|
GstTestMeta *meta;
|
||||||
|
|
||||||
|
register_metadata ();
|
||||||
|
|
||||||
|
buffer = gst_buffer_new_and_alloc (4);
|
||||||
|
memset (GST_BUFFER_DATA (buffer), 0, 4);
|
||||||
|
|
||||||
|
/* add some metadata */
|
||||||
|
meta = GST_TEST_META_GET (buffer, TRUE);
|
||||||
|
fail_if (meta == NULL);
|
||||||
|
/* fill some values */
|
||||||
|
meta->pts = 1000;
|
||||||
|
meta->dts = 2000;
|
||||||
|
meta->duration = 1000;
|
||||||
|
meta->clock_rate = 1000;
|
||||||
|
|
||||||
|
/* copy of the buffer */
|
||||||
|
copy = gst_buffer_copy (buffer);
|
||||||
|
/* get metadata of the buffer */
|
||||||
|
meta = GST_TEST_META_GET (copy, FALSE);
|
||||||
|
fail_if (meta == NULL);
|
||||||
|
fail_if (meta->pts != 1000);
|
||||||
|
fail_if (meta->dts != 2000);
|
||||||
|
fail_if (meta->duration != 1000);
|
||||||
|
fail_if (meta->clock_rate != 1000);
|
||||||
|
gst_buffer_unref (copy);
|
||||||
|
|
||||||
|
/* make subbuffer */
|
||||||
|
subbuf = gst_buffer_create_sub (buffer, 0, 1);
|
||||||
|
/* get metadata of the buffer */
|
||||||
|
meta = GST_TEST_META_GET (subbuf, FALSE);
|
||||||
|
fail_if (meta == NULL);
|
||||||
|
fail_if (meta->pts != 1000);
|
||||||
|
fail_if (meta->dts != 2000);
|
||||||
|
fail_if (meta->duration != -1);
|
||||||
|
fail_if (meta->clock_rate != 1000);
|
||||||
|
gst_buffer_unref (subbuf);
|
||||||
|
|
||||||
|
/* make another subbuffer */
|
||||||
|
subbuf = gst_buffer_create_sub (buffer, 1, 3);
|
||||||
|
/* get metadata of the buffer */
|
||||||
|
meta = GST_TEST_META_GET (subbuf, FALSE);
|
||||||
|
fail_if (meta == NULL);
|
||||||
|
fail_if (meta->pts != -1);
|
||||||
|
fail_if (meta->dts != -1);
|
||||||
|
fail_if (meta->duration != -1);
|
||||||
|
fail_if (meta->clock_rate != 1000);
|
||||||
|
gst_buffer_unref (subbuf);
|
||||||
|
|
||||||
|
/* clean up */
|
||||||
|
gst_buffer_unref (buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
|
||||||
|
static Suite *
|
||||||
|
gst_buffermeta_suite (void)
|
||||||
|
{
|
||||||
|
Suite *s = suite_create ("GstBufferMeta");
|
||||||
|
TCase *tc_chain = tcase_create ("general");
|
||||||
|
|
||||||
|
suite_add_tcase (s, tc_chain);
|
||||||
|
tcase_add_test (tc_chain, test_metadata);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_CHECK_MAIN (gst_buffermeta);
|
|
@ -38,6 +38,7 @@ EXPORTS
|
||||||
_gst_buffer_list_type DATA
|
_gst_buffer_list_type DATA
|
||||||
_gst_buffer_type DATA
|
_gst_buffer_type DATA
|
||||||
_gst_caps_type DATA
|
_gst_caps_type DATA
|
||||||
|
_gst_buffer_meta_init
|
||||||
_gst_debug_bin_to_dot_file
|
_gst_debug_bin_to_dot_file
|
||||||
_gst_debug_bin_to_dot_file_with_ts
|
_gst_debug_bin_to_dot_file_with_ts
|
||||||
_gst_debug_category_new
|
_gst_debug_category_new
|
||||||
|
@ -94,8 +95,14 @@ EXPORTS
|
||||||
gst_buffer_create_sub
|
gst_buffer_create_sub
|
||||||
gst_buffer_flag_get_type
|
gst_buffer_flag_get_type
|
||||||
gst_buffer_get_caps
|
gst_buffer_get_caps
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
gst_buffer_get_meta
|
||||||
|
gst_buffer_get_type
|
||||||
|
>>>>>>> buffermeta: implement arbitrary buffer metadata
|
||||||
gst_buffer_is_metadata_writable
|
gst_buffer_is_metadata_writable
|
||||||
gst_buffer_is_span_fast
|
gst_buffer_is_span_fast
|
||||||
|
gst_buffer_iterate_meta
|
||||||
gst_buffer_join
|
gst_buffer_join
|
||||||
gst_buffer_list_foreach
|
gst_buffer_list_foreach
|
||||||
gst_buffer_list_get
|
gst_buffer_list_get
|
||||||
|
@ -117,8 +124,11 @@ EXPORTS
|
||||||
gst_buffer_list_new
|
gst_buffer_list_new
|
||||||
gst_buffer_make_metadata_writable
|
gst_buffer_make_metadata_writable
|
||||||
gst_buffer_merge
|
gst_buffer_merge
|
||||||
|
gst_buffer_meta_get_info
|
||||||
|
gst_buffer_meta_register_info
|
||||||
gst_buffer_new
|
gst_buffer_new
|
||||||
gst_buffer_new_and_alloc
|
gst_buffer_new_and_alloc
|
||||||
|
gst_buffer_remove_meta
|
||||||
gst_buffer_set_caps
|
gst_buffer_set_caps
|
||||||
gst_buffer_span
|
gst_buffer_span
|
||||||
gst_buffer_try_new_and_alloc
|
gst_buffer_try_new_and_alloc
|
||||||
|
|
Loading…
Reference in a new issue