diff --git a/ChangeLog b/ChangeLog index 145d6bed4e..dd7aef83c8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2006-08-21 Wim Taymans <wim@fluendo.com> + + * gst/gstbuffer.c: (gst_buffer_make_metadata_writable), + (gst_buffer_create_sub): + Copy duration/offset_end/caps when creating a subbuffer of the + complete parent. + Make the subbuffer read-only when we make the metadata writable for + now. Fixes #351768. + + * tests/check/gst/gstbuffer.c: (GST_START_TEST): + Added check for metadata copy when creating subbuffers. + 2006-08-21 Edward Hervey <edward@fluendo.com> * libs/gst/base/gstbasetransform.c: diff --git a/gst/gstbuffer.c b/gst/gstbuffer.c index ff8c3684f8..2602809e28 100644 --- a/gst/gstbuffer.c +++ b/gst/gstbuffer.c @@ -368,7 +368,8 @@ gst_buffer_is_metadata_writable (GstBuffer * buf) * is solely owned by the caller, by creating a subbuffer of the original * buffer if necessary. * - * After calling this function, @buf should not be referenced anymore. + * After calling this function, @buf should not be referenced anymore. The + * result of this function has guaranteed writable metadata. * * Returns: A new #GstBuffer with writable metadata. */ @@ -381,8 +382,13 @@ gst_buffer_make_metadata_writable (GstBuffer * buf) ret = buf; } else { ret = gst_buffer_create_sub (buf, 0, GST_BUFFER_SIZE (buf)); + + /* copy all the flags except IN_CAPS */ GST_BUFFER_FLAGS (ret) = GST_BUFFER_FLAGS (buf); GST_BUFFER_FLAG_UNSET (ret, GST_BUFFER_FLAG_IN_CAPS); + /* data should always be set to READONLY */ + GST_BUFFER_FLAG_SET (ret, GST_BUFFER_FLAG_READONLY); + gst_buffer_unref (buf); } @@ -472,8 +478,11 @@ gst_subbuffer_init (GTypeInstance * instance, gpointer g_class) * 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, else they are set to #GST_CLOCK_TIME_NONE/#GST_BUFFER_OFFSET_NONE. - * The duration field of the new buffer is set to #GST_CLOCK_TIME_NONE. + * 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 + * to #GST_CLOCK_TIME_NONE and #GST_BUFFER_OFFSET_NONE. * * MT safe. * Returns: the new #GstBuffer. @@ -484,6 +493,7 @@ gst_buffer_create_sub (GstBuffer * buffer, guint offset, guint size) { GstSubBuffer *subbuffer; GstBuffer *parent; + gboolean complete; g_return_val_if_fail (buffer != NULL, NULL); g_return_val_if_fail (buffer->mini_object.refcount > 0, NULL); @@ -513,16 +523,28 @@ gst_buffer_create_sub (GstBuffer * buffer, guint offset, guint size) if (offset == 0) { GST_BUFFER_TIMESTAMP (subbuffer) = GST_BUFFER_TIMESTAMP (buffer); GST_BUFFER_OFFSET (subbuffer) = GST_BUFFER_OFFSET (buffer); + complete = (buffer->size == size); } else { GST_BUFFER_TIMESTAMP (subbuffer) = GST_CLOCK_TIME_NONE; GST_BUFFER_OFFSET (subbuffer) = GST_BUFFER_OFFSET_NONE; + complete = FALSE; } - GST_BUFFER_DURATION (subbuffer) = GST_CLOCK_TIME_NONE; - GST_BUFFER_OFFSET_END (subbuffer) = GST_BUFFER_OFFSET_NONE; - - GST_BUFFER_CAPS (subbuffer) = NULL; + if (complete) { + GstCaps *caps; + /* if we copied the complete buffer we can copy the duration, + * offset_end and caps as well */ + GST_BUFFER_DURATION (subbuffer) = GST_BUFFER_DURATION (buffer); + GST_BUFFER_OFFSET_END (subbuffer) = GST_BUFFER_OFFSET_END (buffer); + if ((caps = GST_BUFFER_CAPS (buffer))) + gst_caps_ref (caps); + GST_BUFFER_CAPS (subbuffer) = caps; + } else { + GST_BUFFER_DURATION (subbuffer) = GST_CLOCK_TIME_NONE; + GST_BUFFER_OFFSET_END (subbuffer) = GST_BUFFER_OFFSET_NONE; + GST_BUFFER_CAPS (subbuffer) = NULL; + } return GST_BUFFER_CAST (subbuffer); } diff --git a/tests/check/gst/gstbuffer.c b/tests/check/gst/gstbuffer.c index 105d0d7e47..7be0c52f75 100644 --- a/tests/check/gst/gstbuffer.c +++ b/tests/check/gst/gstbuffer.c @@ -72,6 +72,11 @@ GST_START_TEST (test_subbuffer) buffer = gst_buffer_new_and_alloc (4); memset (GST_BUFFER_DATA (buffer), 0, 4); + /* set some metadata */ + GST_BUFFER_TIMESTAMP (buffer) = 1; + GST_BUFFER_DURATION (buffer) = 2; + GST_BUFFER_OFFSET (buffer) = 3; + GST_BUFFER_OFFSET_END (buffer) = 4; sub = gst_buffer_create_sub (buffer, 1, 2); fail_if (sub == NULL, "create_sub of buffer returned NULL"); @@ -80,7 +85,12 @@ GST_START_TEST (test_subbuffer) 2) == 0, "subbuffer contains the wrong data"); ASSERT_BUFFER_REFCOUNT (buffer, "parent", 2); ASSERT_BUFFER_REFCOUNT (sub, "subbuffer", 1); - + fail_unless (GST_BUFFER_TIMESTAMP (sub) == -1, + "subbuffer has wrong timestamp"); + fail_unless (GST_BUFFER_DURATION (sub) == -1, "subbuffer has wrong duration"); + fail_unless (GST_BUFFER_OFFSET (sub) == -1, "subbuffer has wrong offset"); + fail_unless (GST_BUFFER_OFFSET_END (sub) == -1, + "subbuffer has wrong offset end"); gst_buffer_unref (sub); /* create a subbuffer of size 0 */ @@ -91,6 +101,32 @@ GST_START_TEST (test_subbuffer) 0) == 0, "subbuffer contains the wrong data"); ASSERT_BUFFER_REFCOUNT (buffer, "parent", 2); ASSERT_BUFFER_REFCOUNT (sub, "subbuffer", 1); + gst_buffer_unref (sub); + + /* test if metadata is coppied, not a complete buffer copy so only the + * timestamp and offset fields are copied. */ + sub = gst_buffer_create_sub (buffer, 0, 1); + fail_if (sub == NULL, "create_sub of buffer returned NULL"); + fail_unless (GST_BUFFER_SIZE (sub) == 1, "subbuffer has wrong size"); + fail_unless (GST_BUFFER_TIMESTAMP (sub) == 1, + "subbuffer has wrong timestamp"); + fail_unless (GST_BUFFER_OFFSET (sub) == 3, "subbuffer has wrong offset"); + fail_unless (GST_BUFFER_DURATION (sub) == -1, "subbuffer has wrong duration"); + fail_unless (GST_BUFFER_OFFSET_END (sub) == -1, + "subbuffer has wrong offset end"); + gst_buffer_unref (sub); + + /* test if metadata is coppied, a complete buffer is copied so all the timing + * fields should be copied. */ + sub = gst_buffer_create_sub (buffer, 0, 4); + fail_if (sub == NULL, "create_sub of buffer returned NULL"); + fail_unless (GST_BUFFER_SIZE (sub) == 4, "subbuffer has wrong size"); + fail_unless (GST_BUFFER_TIMESTAMP (sub) == 1, + "subbuffer has wrong timestamp"); + fail_unless (GST_BUFFER_DURATION (sub) == 2, "subbuffer has wrong duration"); + fail_unless (GST_BUFFER_OFFSET (sub) == 3, "subbuffer has wrong offset"); + fail_unless (GST_BUFFER_OFFSET_END (sub) == 4, + "subbuffer has wrong offset end"); /* clean up */ gst_buffer_unref (sub);