adapter: add function to get a list of buffers
authorWim Taymans <wim.taymans@collabora.co.uk>
Fri, 17 Sep 2010 13:51:08 +0000 (15:51 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Fri, 17 Sep 2010 15:35:41 +0000 (17:35 +0200)
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.

docs/libs/gstreamer-libs-sections.txt
libs/gst/base/gstadapter.c
libs/gst/base/gstadapter.h
tests/check/libs/adapter.c
win32/common/libgstbase.def

index 7f29ecb..09d75f3 100644 (file)
@@ -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
 gst_adapter_masked_scan_uint32_peek
index 6db0ad8..d76290c 100644 (file)
@@ -709,6 +709,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
  *
index 8a79543..a4b65e3 100644 (file)
@@ -90,6 +90,7 @@ void                    gst_adapter_copy                (GstAdapter *adapter, gu
 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);
 
index 0c3ebd3..e9db72a 100644 (file)
@@ -728,6 +728,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)
 {
@@ -745,6 +785,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;
 }
index c23b4bb..6676afe 100644 (file)
@@ -13,6 +13,7 @@ EXPORTS
        gst_adapter_push
        gst_adapter_take
        gst_adapter_take_buffer
+       gst_adapter_take_list
        gst_base_sink_do_preroll
        gst_base_sink_get_blocksize
        gst_base_sink_get_last_buffer