gstbuffer: add gst_buffer_copy_deep
authorThiago Santos <thiagoss@osg.samsung.com>
Fri, 13 Mar 2015 18:35:01 +0000 (18:35 +0000)
committerThiago Santos <thiagoss@osg.samsung.com>
Fri, 13 Mar 2015 18:37:04 +0000 (18:37 +0000)
A variant of gst_buffer_copy that forces the underlying memory
to be copied.

This is added to avoid adding an extra reference to a GstMemory
that might belong to a bufferpool that is trying to be drained.
The use case is when the buffer copying is done to release the
old buffer and all its resources.

https://bugzilla.gnome.org/show_bug.cgi?id=745287

gst/gstbuffer.c
gst/gstbuffer.h
tests/check/gst/gstbuffer.c
win32/common/libgstreamer.def

index 06a55b9..f364572 100644 (file)
@@ -508,7 +508,7 @@ gst_buffer_copy_into (GstBuffer * dest, GstBuffer * src,
 }
 
 static GstBuffer *
-_gst_buffer_copy (GstBuffer * buffer)
+gst_buffer_copy_with_flags (const GstBuffer * buffer, GstBufferFlags flags)
 {
   GstBuffer *copy;
 
@@ -517,8 +517,9 @@ _gst_buffer_copy (GstBuffer * buffer)
   /* create a fresh new buffer */
   copy = gst_buffer_new ();
 
-  /* we simply copy everything from our parent */
-  if (!gst_buffer_copy_into (copy, buffer, GST_BUFFER_COPY_ALL, 0, -1))
+  /* copy what the 'flags' want from our parent */
+  /* FIXME why we can't pass const to gst_buffer_copy_into() ? */
+  if (!gst_buffer_copy_into (copy, (GstBuffer *) buffer, flags, 0, -1))
     gst_buffer_replace (&copy, NULL);
 
   if (copy)
@@ -527,6 +528,28 @@ _gst_buffer_copy (GstBuffer * buffer)
   return copy;
 }
 
+static GstBuffer *
+_gst_buffer_copy (const GstBuffer * buffer)
+{
+  return gst_buffer_copy_with_flags (buffer, GST_BUFFER_COPY_ALL);
+}
+
+/**
+ * gst_buffer_copy_deep:
+ * @buf: a #GstBuffer.
+ *
+ * Create a copy of the given buffer. This will make a newly allocated
+ * copy of the data the source buffer contains.
+ *
+ * Returns: (transfer full): a new copy of @buf.
+ */
+GstBuffer *
+gst_buffer_copy_deep (const GstBuffer * buffer)
+{
+  return gst_buffer_copy_with_flags (buffer,
+      GST_BUFFER_COPY_ALL | GST_BUFFER_COPY_DEEP);
+}
+
 /* the default dispose function revives the buffer and returns it to the
  * pool when there is a pool */
 static gboolean
index 643db7d..dd7f237 100644 (file)
@@ -365,8 +365,11 @@ gst_buffer_unref (GstBuffer * buf)
  * gst_buffer_copy:
  * @buf: a #GstBuffer.
  *
- * Create a copy of the given buffer. This will also make a newly allocated
- * copy of the data the source buffer contains.
+ * Create a copy of the given buffer. This will only copy the buffer's
+ * data to a newly allocated memory if needed (if the type of memory
+ * requires it), otherwise the underlying data is just referenced.
+ * Check gst_buffer_copy_deep() if you want to force the data
+ * to be copied to newly allocated memory.
  *
  * Returns: (transfer full): a new copy of @buf.
  */
@@ -380,6 +383,7 @@ gst_buffer_copy (const GstBuffer * buf)
   return GST_BUFFER (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST (buf)));
 }
 
+GstBuffer * gst_buffer_copy_deep (const GstBuffer * buf);
 
 /**
  * GstBufferCopyFlags:
index e52175f..70cb191 100644 (file)
@@ -340,6 +340,8 @@ GST_START_TEST (test_copy)
 
   /* NOTE that data is refcounted */
   fail_unless (info.size == sinfo.size);
+  /* GstBuffer was copied but the underlying GstMemory should be the same */
+  fail_unless (info.data == sinfo.data);
 
   gst_buffer_unmap (copy, &sinfo);
   gst_buffer_unmap (buffer, &info);
@@ -408,6 +410,37 @@ GST_START_TEST (test_copy)
 
 GST_END_TEST;
 
+GST_START_TEST (test_copy_deep)
+{
+  GstBuffer *buffer, *copy;
+  GstMapInfo info, sinfo;
+
+  buffer = gst_buffer_new_and_alloc (4);
+  ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 1);
+
+  copy = gst_buffer_copy_deep (buffer);
+  ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 1);
+  ASSERT_BUFFER_REFCOUNT (copy, "copy", 1);
+  /* buffers are copied and must point to different memory */
+  fail_if (buffer == copy);
+
+  fail_unless (gst_buffer_map (buffer, &info, GST_MAP_READ));
+  fail_unless (gst_buffer_map (copy, &sinfo, GST_MAP_READ));
+
+  /* NOTE that data is refcounted */
+  fail_unless (info.size == sinfo.size);
+  /* copy_deep() forces new GstMemory to be used */
+  fail_unless (info.data != sinfo.data);
+
+  gst_buffer_unmap (copy, &sinfo);
+  gst_buffer_unmap (buffer, &info);
+
+  gst_buffer_unref (copy);
+  gst_buffer_unref (buffer);
+}
+
+GST_END_TEST;
+
 GST_START_TEST (test_try_new_and_alloc)
 {
   GstBuffer *buf;
@@ -871,6 +904,7 @@ gst_buffer_suite (void)
   tcase_add_test (tc_chain, test_metadata_writable);
   tcase_add_test (tc_chain, test_memcmp);
   tcase_add_test (tc_chain, test_copy);
+  tcase_add_test (tc_chain, test_copy_deep);
   tcase_add_test (tc_chain, test_try_new_and_alloc);
   tcase_add_test (tc_chain, test_size);
   tcase_add_test (tc_chain, test_resize);
index 675661d..22acb9d 100644 (file)
@@ -115,6 +115,7 @@ EXPORTS
        gst_buffer_append
        gst_buffer_append_memory
        gst_buffer_append_region
+       gst_buffer_copy_deep
        gst_buffer_copy_flags_get_type
        gst_buffer_copy_into
        gst_buffer_copy_region