Add GstParentBufferMeta
authorJan Schmidt <jan@centricular.com>
Wed, 6 May 2015 06:44:48 +0000 (16:44 +1000)
committerJan Schmidt <jan@centricular.com>
Thu, 18 Jun 2015 15:15:25 +0000 (01:15 +1000)
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

docs/gst/gstreamer-sections.txt
gst/gstbuffer.c
gst/gstbuffer.h
win32/common/libgstreamer.def

index 27a4035..25bb371 100644 (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>
index ba5120e..025e867 100644 (file)
  * 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;
+}
index 0e026a0..fdf0e19 100644 (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__ */
index 4db73f8..9ba9c77 100644 (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