From 96eaeadc0f3cbad3cf35d26f542b8359d27e316d Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Fri, 13 Mar 2015 18:35:01 +0000 Subject: [PATCH] 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 --- gst/gstbuffer.c | 29 ++++++++++++++++++++++++++--- gst/gstbuffer.h | 8 ++++++-- tests/check/gst/gstbuffer.c | 34 ++++++++++++++++++++++++++++++++++ win32/common/libgstreamer.def | 1 + 4 files changed, 67 insertions(+), 5 deletions(-) diff --git a/gst/gstbuffer.c b/gst/gstbuffer.c index 06a55b9..f364572 100644 --- a/gst/gstbuffer.c +++ b/gst/gstbuffer.c @@ -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 (©, 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 diff --git a/gst/gstbuffer.h b/gst/gstbuffer.h index 643db7d..dd7f237 100644 --- a/gst/gstbuffer.h +++ b/gst/gstbuffer.h @@ -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: diff --git a/tests/check/gst/gstbuffer.c b/tests/check/gst/gstbuffer.c index e52175f..70cb191 100644 --- a/tests/check/gst/gstbuffer.c +++ b/tests/check/gst/gstbuffer.c @@ -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); diff --git a/win32/common/libgstreamer.def b/win32/common/libgstreamer.def index 675661d..22acb9d 100644 --- a/win32/common/libgstreamer.def +++ b/win32/common/libgstreamer.def @@ -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 -- 2.7.4