summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2009-07-10 18:37:14 +0100
committerWim Taymans <wim@metal.(none)>2009-07-10 18:37:14 +0100
commitcc5cdb1fba71fc8023a8f57f907bb7e7ff40899a (patch)
tree550726c2b68bff9d4225c71e22d4e7a1cb134d0b
parent8ecbf002b8629fc1ac2bca236fc97f38c9b5ef05 (diff)
adapter: add function to get a list of buffersadapter-list
Add a function to retrieve a list of buffers containing the first N bytes from the adapter. This can be done without a memcpy and should make it possible to transfer the list to a GstBufferList later.
-rw-r--r--docs/libs/gstreamer-libs-sections.txt1
-rw-r--r--libs/gst/base/gstadapter.c48
-rw-r--r--libs/gst/base/gstadapter.h1
-rw-r--r--tests/check/libs/adapter.c41
4 files changed, 91 insertions, 0 deletions
diff --git a/docs/libs/gstreamer-libs-sections.txt b/docs/libs/gstreamer-libs-sections.txt
index 44ed3e62d..c1d1a8777 100644
--- a/docs/libs/gstreamer-libs-sections.txt
+++ b/docs/libs/gstreamer-libs-sections.txt
@@ -205,6 +205,7 @@ gst_adapter_available
gst_adapter_available_fast
gst_adapter_take
gst_adapter_take_buffer
+gst_adapter_take_list
gst_adapter_prev_timestamp
gst_adapter_masked_scan_uint32
<SUBSECTION Standard>
diff --git a/libs/gst/base/gstadapter.c b/libs/gst/base/gstadapter.c
index 3c44e8ec2..c8d4feb8c 100644
--- a/libs/gst/base/gstadapter.c
+++ b/libs/gst/base/gstadapter.c
@@ -652,6 +652,54 @@ done:
}
/**
+ * gst_adapter_take_list:
+ * @adapter: a #GstAdapter
+ * @nbytes: the number of bytes to take
+ *
+ * Returns a #GSList of buffers containing the first @nbytes bytes of the
+ * @adapter. The returned bytes will be flushed from the adapter.
+ * When the caller can deal with individual buffers, this function is more
+ * performant because no memory should be coppied.
+ *
+ * Caller owns returned list and contained buffers. gst_buffer_unref() each
+ * buffer in the list before freeng the list after usage.
+ *
+ * Since: 0.10.24
+ *
+ * Returns: a #GSList of buffers containing the first @nbytes of the adapter,
+ * or #NULL if @nbytes bytes are not available
+ */
+GList *
+gst_adapter_take_list (GstAdapter * adapter, guint nbytes)
+{
+ GList *result = NULL, *tail = NULL;
+ GstBuffer *cur;
+ guint hsize, skip;
+
+ g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
+ g_return_val_if_fail (nbytes <= adapter->size, NULL);
+
+ GST_LOG_OBJECT (adapter, "taking %u bytes", nbytes);
+
+ while (nbytes > 0) {
+ cur = adapter->buflist->data;
+ skip = adapter->skip;
+ hsize = MIN (nbytes, GST_BUFFER_SIZE (cur) - skip);
+
+ cur = gst_adapter_take_buffer (adapter, hsize);
+
+ if (result == NULL) {
+ result = tail = g_list_append (result, cur);
+ } else {
+ tail = g_list_append (tail, cur);
+ tail = g_list_next (tail);
+ }
+ nbytes -= hsize;
+ }
+ return result;
+}
+
+/**
* gst_adapter_available:
* @adapter: a #GstAdapter
*
diff --git a/libs/gst/base/gstadapter.h b/libs/gst/base/gstadapter.h
index 49e408e0f..c6a2fefff 100644
--- a/libs/gst/base/gstadapter.h
+++ b/libs/gst/base/gstadapter.h
@@ -90,6 +90,7 @@ void gst_adapter_copy (GstAdapter *adapter, guint8 *dest,
void gst_adapter_flush (GstAdapter *adapter, guint flush);
guint8* gst_adapter_take (GstAdapter *adapter, guint nbytes);
GstBuffer* gst_adapter_take_buffer (GstAdapter *adapter, guint nbytes);
+GList* gst_adapter_take_list (GstAdapter *adapter, guint nbytes);
guint gst_adapter_available (GstAdapter *adapter);
guint gst_adapter_available_fast (GstAdapter *adapter);
diff --git a/tests/check/libs/adapter.c b/tests/check/libs/adapter.c
index 34cef2380..317d2ea6d 100644
--- a/tests/check/libs/adapter.c
+++ b/tests/check/libs/adapter.c
@@ -601,6 +601,46 @@ GST_START_TEST (test_scan)
GST_END_TEST;
+/* Fill a buffer with a sequence of 32 bit ints and read them back out
+ * using take_buffer, checking that they're still in the right order */
+GST_START_TEST (test_take_list)
+{
+ GstAdapter *adapter;
+ int i = 0;
+
+ adapter = create_and_fill_adapter ();
+ while (gst_adapter_available (adapter) >= sizeof (guint32)) {
+ GList *list, *walk;
+ GstBuffer *buf;
+ guint size;
+ guint8 *data;
+
+ list = gst_adapter_take_list (adapter, sizeof (guint32) * 5);
+ fail_unless (list != NULL);
+
+ for (walk = list; walk; walk = g_list_next (walk)) {
+ buf = walk->data;
+ data = GST_BUFFER_DATA (buf);
+ size = GST_BUFFER_SIZE (buf);
+
+ while (size > 0) {
+ fail_unless (GST_READ_UINT32_LE (data) == i);
+ i++;
+ data += sizeof (guint32);
+ size -= sizeof (guint32);
+ }
+ gst_buffer_unref (buf);
+ }
+ g_list_free (list);
+ }
+ fail_unless (gst_adapter_available (adapter) == 0,
+ "Data was left in the adapter");
+
+ g_object_unref (adapter);
+}
+
+GST_END_TEST;
+
static Suite *
gst_adapter_suite (void)
{
@@ -618,6 +658,7 @@ gst_adapter_suite (void)
tcase_add_test (tc_chain, test_take_buf_order);
tcase_add_test (tc_chain, test_timestamp);
tcase_add_test (tc_chain, test_scan);
+ tcase_add_test (tc_chain, test_take_list);
return s;
}