Add GstParentBufferMeta

A core meta which helps implement the old concept
of sub-buffering in some situations, by making it
possible for a buffer to keep a ref on a different
parent buffer. The parent buffer is unreffed when
the Meta is freed.

This meta is used to ensure that a buffer whose
memory is being shared to a child buffer isn't freed
and returned to a buffer pool until the memory
is.

https://bugzilla.gnome.org/show_bug.cgi?id=750039
This commit is contained in:
Jan Schmidt 2015-05-06 16:44:48 +10:00
parent 632431aecb
commit 4d4e436376
4 changed files with 195 additions and 2 deletions

View file

@ -255,6 +255,10 @@ gst_buffer_iterate_meta
GstBufferForeachMetaFunc
gst_buffer_foreach_meta
GstParentBufferMeta
gst_buffer_add_parent_buffer_meta
gst_buffer_get_parent_buffer_meta
<SUBSECTION Standard>
GstBufferClass
GST_BUFFER
@ -263,10 +267,14 @@ GST_TYPE_BUFFER
GST_TYPE_BUFFER_FLAGS
GST_TYPE_BUFFER_COPY_FLAGS
GST_BUFFER_CAST
GST_PARENT_BUFFER_META_INFO
GST_TYPE_PARENT_BUFFER_META_API_TYPE
gst_parent_buffer_meta_get_info
<SUBSECTION Private>
gst_buffer_get_type
gst_buffer_flags_get_type
gst_buffer_copy_flags_get_type
gst_parent_buffer_meta_api_get_type
GST_BUFFER_TIMESTAMP
GST_BUFFER_TIMESTAMP_IS_VALID
</SECTION>

View file

@ -104,6 +104,16 @@
* the refcount drops to 0, any memory and metadata pointed to by the buffer is
* unreffed as well. Buffers allocated from a #GstBufferPool will be returned to
* the pool when the refcount drops to 0.
*
* The #GstParentBufferMeta is a meta which can be attached to a #GstBuffer
* to hold a reference to another buffer that is only released when the child
* #GstBuffer is released.
*
* Typically, #GstParentBufferMeta is used when the child buffer is directly
* using the #GstMemory of the parent buffer, and wants to prevent the parent
* buffer from being returned to a buffer pool until the #GstMemory is available
* for re-use. (Since: 1.6)
*
*/
#include "gst_private.h"
@ -1901,7 +1911,7 @@ gst_buffer_memset (GstBuffer * buffer, gsize offset, guint8 val, gsize size)
* gst_buffer_copy_region:
* @parent: a #GstBuffer.
* @flags: the #GstBufferCopyFlags
* @offset: the offset into parent #GstBuffer at which the new sub-buffer
* @offset: the offset into parent #GstBuffer at which the new sub-buffer
* begins.
* @size: the size of the new #GstBuffer sub-buffer, in bytes. If -1, all
* data is copied.
@ -1909,7 +1919,7 @@ gst_buffer_memset (GstBuffer * buffer, gsize offset, guint8 val, gsize size)
* Creates a sub-buffer from @parent at @offset and @size.
* This sub-buffer uses the actual memory space of the parent buffer.
* This function will copy the offset and timestamp fields when the
* offset is 0. If not, they will be set to #GST_CLOCK_TIME_NONE and
* offset is 0. If not, they will be set to #GST_CLOCK_TIME_NONE and
* #GST_BUFFER_OFFSET_NONE.
* If @offset equals 0 and @size equals the total size of @buffer, the
* duration and offset end fields are also copied. If not they will be set
@ -2257,3 +2267,128 @@ gst_buffer_extract_dup (GstBuffer * buffer, gsize offset, gsize size,
*dest_size = gst_buffer_extract (buffer, offset, *dest, size);
}
GST_DEBUG_CATEGORY (gst_parent_buffer_meta_debug);
/**
* gst_buffer_add_parent_buffer_meta:
* @buffer: (transfer none): a #GstBuffer
* @ref: (transfer none): a #GstBuffer to ref
*
* Add a #GstParentBufferMeta to @buffer that holds a reference on
* @ref until the buffer is freed.
*
* Returns: (transfer none): The #GstParentBufferMeta that was added to the buffer
*
* Since: 1.6
*/
GstParentBufferMeta *
gst_buffer_add_parent_buffer_meta (GstBuffer * buffer, GstBuffer * ref)
{
GstParentBufferMeta *meta;
g_return_val_if_fail (GST_IS_BUFFER (ref), NULL);
meta =
(GstParentBufferMeta *) gst_buffer_add_meta (buffer,
GST_PARENT_BUFFER_META_INFO, NULL);
if (!meta)
return NULL;
meta->buffer = gst_buffer_ref (ref);
return meta;
}
static gboolean
_gst_parent_buffer_meta_transform (GstBuffer * dest, GstMeta * meta,
GstBuffer * buffer, GQuark type, gpointer data)
{
GstParentBufferMeta *dmeta, *smeta;
smeta = (GstParentBufferMeta *) meta;
if (GST_META_TRANSFORM_IS_COPY (type)) {
/* copy over the reference to the parent buffer.
* Usually, this meta means we need to keep the parent buffer
* alive because one of the child memories is in use, which
* might not be the case if memory is deep copied or sub-regioned,
* but we can't tell, so keep the meta */
dmeta = gst_buffer_add_parent_buffer_meta (dest, smeta->buffer);
if (!dmeta)
return FALSE;
GST_CAT_DEBUG (gst_parent_buffer_meta_debug,
"copy buffer reference metadata");
}
return TRUE;
}
static void
_gst_parent_buffer_meta_free (GstParentBufferMeta * parent_meta,
GstBuffer * buffer)
{
GST_CAT_DEBUG (gst_parent_buffer_meta_debug,
"Dropping reference on buffer %p", parent_meta->buffer);
gst_buffer_unref (parent_meta->buffer);
}
static gboolean
_gst_parent_buffer_meta_init (GstParentBufferMeta * parent_meta,
gpointer params, GstBuffer * buffer)
{
static volatile gsize _init;
if (g_once_init_enter (&_init)) {
GST_DEBUG_CATEGORY_INIT (gst_parent_buffer_meta_debug, "glbufferrefmeta", 0,
"glbufferrefmeta");
g_once_init_leave (&_init, 1);
}
parent_meta->buffer = NULL;
return TRUE;
}
GType
gst_parent_buffer_meta_api_get_type (void)
{
static volatile GType type = 0;
static const gchar *tags[] = { NULL };
if (g_once_init_enter (&type)) {
GType _type = gst_meta_api_type_register ("GstParentBufferMetaAPI", tags);
g_once_init_leave (&type, _type);
}
return type;
}
/**
* gst_parent_buffer_meta_get_info:
*
* Get the global #GstMetaInfo describing the #GstParentBufferMeta meta.
*
* Returns: (transfer none): The #GstMetaInfo
*
* Since: 1.6
*/
const GstMetaInfo *
gst_parent_buffer_meta_get_info (void)
{
static const GstMetaInfo *meta_info = NULL;
if (g_once_init_enter (&meta_info)) {
const GstMetaInfo *meta =
gst_meta_register (gst_parent_buffer_meta_api_get_type (),
"GstParentBufferMeta",
sizeof (GstParentBufferMeta),
(GstMetaInitFunction) _gst_parent_buffer_meta_init,
(GstMetaFreeFunction) _gst_parent_buffer_meta_free,
_gst_parent_buffer_meta_transform);
g_once_init_leave (&meta_info, meta);
}
return meta_info;
}

View file

@ -561,6 +561,52 @@ gboolean gst_buffer_foreach_meta (GstBuffer *buffer,
*/
#define gst_value_get_buffer(v) GST_BUFFER_CAST (g_value_get_boxed(v))
typedef struct _GstParentBufferMeta GstParentBufferMeta;
/**
* GstParentBufferMeta:
* @parent: the parent #GstMeta structure
* @buffer: the #GstBuffer on which a reference is being held.
*
* The #GstParentBufferMeta is a #GstMeta which can be attached to a #GstBuffer
* to hold a reference to another buffer that is only released when the child
* #GstBuffer is released.
*
* Typically, #GstParentBufferMeta is used when the child buffer is directly
* using the #GstMemory of the parent buffer, and wants to prevent the parent
* buffer from being returned to a buffer pool until the #GstMemory is available
* for re-use.
*
* (Since: 1.6)
*/
struct _GstParentBufferMeta
{
GstMeta parent;
/*< public >*/
GstBuffer *buffer;
};
GType gst_parent_buffer_meta_api_get_type (void);
#define GST_TYPE_PARENT_BUFFER_META_API_TYPE (gst_parent_buffer_meta_api_get_type())
/**
* gst_buffer_get_parent_buffer_meta:
* @b: a #GstBuffer
*
* Find and return a #GstParentBufferMeta if one exists on the
* buffer
*/
#define gst_buffer_get_parent_buffer_meta(b) \
((GstParentBufferMeta*)gst_buffer_get_meta((b),GST_PARENT_BUFFER_META_API_TYPE))
const GstMetaInfo *gst_parent_buffer_meta_get_info (void);
#define GST_PARENT_BUFFER_META_INFO (gst_parent_buffer_meta_get_info())
/* implementation */
GstParentBufferMeta *gst_buffer_add_parent_buffer_meta (GstBuffer *buffer,
GstBuffer *ref);
G_END_DECLS
#endif /* __GST_BUFFER_H__ */

View file

@ -113,6 +113,7 @@ EXPORTS
gst_bin_sync_children_states
gst_bitmask_get_type
gst_buffer_add_meta
gst_buffer_add_parent_buffer_meta
gst_buffer_add_protection_meta
gst_buffer_append
gst_buffer_append_memory
@ -903,6 +904,9 @@ EXPORTS
gst_pad_use_fixed_caps
gst_param_spec_fraction
gst_param_spec_fraction_get_type
gst_parent_buffer_meta_api_get_type
gst_parent_buffer_meta_debug DATA
gst_parent_buffer_meta_get_info
gst_parse_bin_from_description
gst_parse_bin_from_description_full
gst_parse_context_free