gstbuffer: add gst_buffer_copy_deep

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
This commit is contained in:
Thiago Santos 2015-03-13 18:35:01 +00:00
parent d8f572647f
commit 96eaeadc0f
4 changed files with 67 additions and 5 deletions

View 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

View 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:

View 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);

View 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