summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2010-09-17 12:40:12 +0200
committerWim Taymans <wim.taymans@collabora.co.uk>2010-09-17 12:40:12 +0200
commit1dde3cb4407ce28db88688fc8690fdc1f147cee7 (patch)
treeb21704845ed185d02c9c59458dafb0fa95bc7590
parent47743aa7ac7d980017d4f3cbd83b926dd543d71a (diff)
adapter: add support for 0 sized buffers
Add support for 0 sized buffers. This is interesting in combination with the timestamp functions. Fixes #629553
-rw-r--r--libs/gst/base/gstadapter.c62
-rw-r--r--tests/check/libs/adapter.c81
2 files changed, 112 insertions, 31 deletions
diff --git a/libs/gst/base/gstadapter.c b/libs/gst/base/gstadapter.c
index 33574981bf..e956948e28 100644
--- a/libs/gst/base/gstadapter.c
+++ b/libs/gst/base/gstadapter.c
@@ -271,10 +271,13 @@ copy_into_unchecked (GstAdapter * adapter, guint8 * dest, guint skip,
while (size > 0) {
g = g_slist_next (g);
buf = g->data;
- csize = MIN (GST_BUFFER_SIZE (buf), size);
- memcpy (dest, GST_BUFFER_DATA (buf), csize);
- size -= csize;
- dest += csize;
+ bsize = GST_BUFFER_SIZE (buf);
+ if (G_LIKELY (bsize > 0)) {
+ csize = MIN (bsize, size);
+ memcpy (dest, GST_BUFFER_DATA (buf), csize);
+ size -= csize;
+ dest += csize;
+ }
}
}
@@ -285,8 +288,6 @@ copy_into_unchecked (GstAdapter * adapter, guint8 * dest, guint skip,
*
* Adds the data from @buf to the data stored inside @adapter and takes
* ownership of the buffer.
- * Empty buffers will be automatically dereferenced and not stored in the
- * @adapter.
*/
void
gst_adapter_push (GstAdapter * adapter, GstBuffer * buf)
@@ -297,27 +298,19 @@ gst_adapter_push (GstAdapter * adapter, GstBuffer * buf)
g_return_if_fail (GST_IS_BUFFER (buf));
size = GST_BUFFER_SIZE (buf);
+ adapter->size += size;
- if (G_UNLIKELY (size == 0)) {
- /* we can't have empty buffers, several parts in this file rely on it, this
- * has some problems for the timestamp tracking. */
- GST_LOG_OBJECT (adapter, "discarding empty buffer");
- gst_buffer_unref (buf);
+ /* Note: merging buffers at this point is premature. */
+ if (G_UNLIKELY (adapter->buflist == NULL)) {
+ GST_LOG_OBJECT (adapter, "pushing first %u bytes", size);
+ adapter->buflist = adapter->buflist_end = g_slist_append (NULL, buf);
+ update_timestamp (adapter, buf);
} else {
- adapter->size += size;
-
- /* Note: merging buffers at this point is premature. */
- if (G_UNLIKELY (adapter->buflist == NULL)) {
- GST_LOG_OBJECT (adapter, "pushing first %u bytes", size);
- adapter->buflist = adapter->buflist_end = g_slist_append (NULL, buf);
- update_timestamp (adapter, buf);
- } else {
- /* Otherwise append to the end, and advance our end pointer */
- GST_LOG_OBJECT (adapter, "pushing %u bytes at end, size now %u", size,
- adapter->size);
- adapter->buflist_end = g_slist_append (adapter->buflist_end, buf);
- adapter->buflist_end = g_slist_next (adapter->buflist_end);
- }
+ /* Otherwise append to the end, and advance our end pointer */
+ GST_LOG_OBJECT (adapter, "pushing %u bytes at end, size now %u", size,
+ adapter->size);
+ adapter->buflist_end = g_slist_append (adapter->buflist_end, buf);
+ adapter->buflist_end = g_slist_next (adapter->buflist_end);
}
}
@@ -711,22 +704,29 @@ gst_adapter_available (GstAdapter * adapter)
guint
gst_adapter_available_fast (GstAdapter * adapter)
{
- GstBuffer *first;
+ GstBuffer *cur;
guint size;
+ GSList *g;
g_return_val_if_fail (GST_IS_ADAPTER (adapter), 0);
- /* no buffers, we have no data */
- if (!adapter->buflist)
+ /* no data */
+ if (adapter->size == 0)
return 0;
/* some stuff we already assembled */
if (adapter->assembled_len)
return adapter->assembled_len;
- /* take the first buffer and its size */
- first = GST_BUFFER_CAST (adapter->buflist->data);
- size = GST_BUFFER_SIZE (first);
+ /* take the first non-zero buffer */
+ g = adapter->buflist;
+ while (TRUE) {
+ cur = g->data;
+ size = GST_BUFFER_SIZE (cur);
+ if (size != 0)
+ break;
+ g = g_slist_next (g);
+ }
/* we can quickly get the (remaining) data of the first buffer */
return size - adapter->skip;
diff --git a/tests/check/libs/adapter.c b/tests/check/libs/adapter.c
index e5a371ead8..0c3ebd3b5e 100644
--- a/tests/check/libs/adapter.c
+++ b/tests/check/libs/adapter.c
@@ -335,6 +335,8 @@ GST_START_TEST (test_timestamp)
guint avail;
GstClockTime timestamp;
guint64 dist;
+ guint8 *data;
+ const guint8 *cdata;
adapter = gst_adapter_new ();
fail_unless (adapter != NULL);
@@ -448,6 +450,85 @@ GST_START_TEST (test_timestamp)
fail_unless (timestamp == GST_CLOCK_TIME_NONE);
fail_unless (dist == 0);
+ /* push an empty buffer with timestamp in the adapter */
+ buffer = gst_buffer_new ();
+ GST_BUFFER_TIMESTAMP (buffer) = 2 * GST_SECOND;
+ gst_adapter_push (adapter, buffer);
+ avail = gst_adapter_available (adapter);
+ fail_unless (avail == 0);
+ timestamp = gst_adapter_prev_timestamp (adapter, &dist);
+ fail_unless (timestamp == 2 * GST_SECOND);
+ fail_unless (dist == 0);
+
+ /* push another empty buffer */
+ buffer = gst_buffer_new ();
+ GST_BUFFER_TIMESTAMP (buffer) = 3 * GST_SECOND;
+ gst_adapter_push (adapter, buffer);
+ avail = gst_adapter_available (adapter);
+ fail_unless (avail == 0);
+ timestamp = gst_adapter_prev_timestamp (adapter, &dist);
+ fail_unless (timestamp == 2 * GST_SECOND);
+ fail_unless (dist == 0);
+
+ /* push a buffer with timestamp in the adapter */
+ buffer = gst_buffer_new_and_alloc (100);
+ GST_BUFFER_TIMESTAMP (buffer) = 4 * GST_SECOND;
+ gst_adapter_push (adapter, buffer);
+ avail = gst_adapter_available (adapter);
+ fail_unless (avail == 100);
+ timestamp = gst_adapter_prev_timestamp (adapter, &dist);
+ fail_unless (timestamp == 2 * GST_SECOND);
+ fail_unless (dist == 0);
+
+ gst_adapter_flush (adapter, 1);
+ avail = gst_adapter_available (adapter);
+ fail_unless (avail == 99);
+ timestamp = gst_adapter_prev_timestamp (adapter, &dist);
+ fail_unless (timestamp == 4 * GST_SECOND);
+ fail_unless (dist == 1);
+
+ /* push an empty buffer with timestamp in the adapter */
+ buffer = gst_buffer_new ();
+ GST_BUFFER_TIMESTAMP (buffer) = 5 * GST_SECOND;
+ gst_adapter_push (adapter, buffer);
+ avail = gst_adapter_available (adapter);
+ fail_unless (avail == 99);
+ timestamp = gst_adapter_prev_timestamp (adapter, &dist);
+ fail_unless (timestamp == 4 * GST_SECOND);
+ fail_unless (dist == 1);
+
+ /* push buffer without timestamp */
+ buffer = gst_buffer_new_and_alloc (100);
+ gst_adapter_push (adapter, buffer);
+ avail = gst_adapter_available (adapter);
+ fail_unless (avail == 199);
+ timestamp = gst_adapter_prev_timestamp (adapter, &dist);
+ fail_unless (timestamp == 4 * GST_SECOND);
+ fail_unless (dist == 1);
+
+ /* remove first buffer, timestamp of empty buffer is visible */
+ buffer = gst_adapter_take_buffer (adapter, 99);
+ fail_unless (buffer != NULL);
+ fail_unless (GST_BUFFER_SIZE (buffer) == 99);
+ gst_buffer_unref (buffer);
+ avail = gst_adapter_available (adapter);
+ fail_unless (avail == 100);
+ timestamp = gst_adapter_prev_timestamp (adapter, &dist);
+ fail_unless (timestamp == 5 * GST_SECOND);
+ fail_unless (dist == 0);
+
+ /* remove empty buffer, timestamp still visible */
+ cdata = gst_adapter_peek (adapter, 50);
+ fail_unless (cdata != NULL);
+ data = gst_adapter_take (adapter, 50);
+ fail_unless (data != NULL);
+ g_free (data);
+ avail = gst_adapter_available (adapter);
+ fail_unless (avail == 50);
+ timestamp = gst_adapter_prev_timestamp (adapter, &dist);
+ fail_unless (timestamp == 5 * GST_SECOND);
+ fail_unless (dist == 50);
+
g_object_unref (adapter);
}