From: Jan Schmidt Date: Wed, 6 May 2015 06:44:48 +0000 (+1000) Subject: Add GstParentBufferMeta X-Git-Tag: 1.6.1~188 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4d4e4363764d2693f7f15d95d90405b7cb4587b3;p=platform%2Fupstream%2Fgstreamer.git 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 --- diff --git a/docs/gst/gstreamer-sections.txt b/docs/gst/gstreamer-sections.txt index 27a4035..25bb371 100644 --- a/docs/gst/gstreamer-sections.txt +++ b/docs/gst/gstreamer-sections.txt @@ -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 + 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 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 diff --git a/gst/gstbuffer.c b/gst/gstbuffer.c index ba5120e..025e867 100644 --- a/gst/gstbuffer.c +++ b/gst/gstbuffer.c @@ -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; +} diff --git a/gst/gstbuffer.h b/gst/gstbuffer.h index 0e026a0..fdf0e19 100644 --- a/gst/gstbuffer.h +++ b/gst/gstbuffer.h @@ -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__ */ diff --git a/win32/common/libgstreamer.def b/win32/common/libgstreamer.def index 4db73f8..9ba9c77 100644 --- a/win32/common/libgstreamer.def +++ b/win32/common/libgstreamer.def @@ -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