adapter: Add function to return buffer composed of multiple memories
authorOlivier Crête <olivier.crete@collabora.com>
Mon, 15 Jul 2013 19:41:44 +0000 (15:41 -0400)
committerOlivier Crête <olivier.crete@collabora.com>
Tue, 16 Jul 2013 18:07:48 +0000 (14:07 -0400)
API: gst_adapter_take_fast()

libs/gst/base/gstadapter.c
libs/gst/base/gstadapter.h
tests/check/libs/adapter.c
win32/common/libgstbase.def

index 935fa20..a5e7b48 100644 (file)
@@ -709,15 +709,102 @@ gst_adapter_take (GstAdapter * adapter, gsize nbytes)
 }
 
 /**
+ * gst_adapter_take_buffer_fast:
+ * @adapter:  a #GstAdapter
+ * @nbytes: the number of bytes to take
+ *
+ * Returns a #GstBuffer containing the first @nbytes of the @adapter.
+ * The returned bytes will be flushed from the adapter.  This function
+ * is potentially more performant than gst_adapter_take_buffer() since
+ * it can reuse the memory in pushed buffers by subbuffering or
+ * merging. Unlike gst_adapter_take_buffer(), the returned buffer may
+ * be composed of multiple non-contiguous #GstMemory objects, no
+ * copies are made.
+ *
+ * Note that no assumptions should be made as to whether certain buffer
+ * flags such as the DISCONT flag are set on the returned buffer, or not.
+ * The caller needs to explicitly set or unset flags that should be set or
+ * unset.
+ *
+ * This function can return buffer up to the return value of
+ * gst_adapter_available() without making copies if possible.
+ *
+ * Caller owns a reference to the returned buffer. gst_buffer_unref() after
+ * usage.
+ *
+ * Free-function: gst_buffer_unref
+ *
+ * Returns: (transfer full): a #GstBuffer containing the first @nbytes of
+ *     the adapter, or #NULL if @nbytes bytes are not available.
+ *     gst_buffer_unref() when no longer needed.
+ *
+ * Since: 1.2
+ */
+
+GstBuffer *
+gst_adapter_take_buffer_fast (GstAdapter * adapter, gsize nbytes)
+{
+  GstBuffer *buffer = NULL;
+  GstBuffer *cur;
+  GSList *item;
+  gsize skip;
+  gsize left = nbytes;
+
+  g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
+  g_return_val_if_fail (nbytes > 0, NULL);
+
+  GST_LOG_OBJECT (adapter, "taking buffer of %" G_GSIZE_FORMAT " bytes",
+      nbytes);
+
+  /* we don't have enough data, return NULL. This is unlikely
+   * as one usually does an _available() first instead of grabbing a
+   * random size. */
+  if (G_UNLIKELY (nbytes > adapter->size))
+    return NULL;
+
+  skip = adapter->skip;
+  cur = adapter->buflist->data;
+
+  if (skip == 0 && gst_buffer_get_size (cur) == nbytes) {
+    GST_LOG_OBJECT (adapter, "providing buffer of %" G_GSIZE_FORMAT " bytes"
+        " as head buffer", nbytes);
+    buffer = gst_buffer_ref (cur);
+    goto done;
+  }
+
+  for (item = adapter->buflist; item && left > 0; item = item->next) {
+    gsize size;
+
+    cur = item->data;
+    size = MIN (gst_buffer_get_size (cur), left);
+
+    GST_LOG_OBJECT (adapter, "appending %" G_GSIZE_FORMAT " bytes"
+        " via region copy", size);
+    if (buffer)
+      gst_buffer_copy_into (buffer, cur, GST_BUFFER_COPY_MEMORY, 0, size);
+    else
+      buffer = gst_buffer_copy_region (cur, GST_BUFFER_COPY_ALL, skip, size);
+    skip = 0;
+    left -= size;
+  }
+
+done:
+  gst_adapter_flush_unchecked (adapter, nbytes);
+
+  return buffer;
+}
+
+/**
  * gst_adapter_take_buffer:
  * @adapter: a #GstAdapter
  * @nbytes: the number of bytes to take
  *
  * Returns a #GstBuffer containing the first @nbytes bytes of the
  * @adapter. The returned bytes will be flushed from the adapter.
- * This function is potentially more performant than gst_adapter_take()
- * since it can reuse the memory in pushed buffers by subbuffering
- * or merging.
+ * This function is potentially more performant than
+ * gst_adapter_take() since it can reuse the memory in pushed buffers
+ * by subbuffering or merging. This function will always return a
+ * buffer with a single memory region.
  *
  * Note that no assumptions should be made as to whether certain buffer
  * flags such as the DISCONT flag are set on the returned buffer, or not.
index 9625a01..9683f3b 100644 (file)
@@ -60,6 +60,7 @@ void                    gst_adapter_flush               (GstAdapter *adapter, gs
 gpointer                gst_adapter_take                (GstAdapter *adapter, gsize nbytes);
 GstBuffer*              gst_adapter_take_buffer         (GstAdapter *adapter, gsize nbytes);
 GList*                  gst_adapter_take_list           (GstAdapter *adapter, gsize nbytes);
+GstBuffer *             gst_adapter_take_buffer_fast    (GstAdapter *adapter, gsize nbytes);
 gsize                   gst_adapter_available           (GstAdapter *adapter);
 gsize                   gst_adapter_available_fast      (GstAdapter *adapter);
 
index df740f9..dc48385 100644 (file)
@@ -834,6 +834,42 @@ GST_START_TEST (test_merge)
 
 GST_END_TEST;
 
+GST_START_TEST (test_take_buffer_fast)
+{
+  GstAdapter *adapter;
+  GstBuffer *buffer;
+
+  adapter = gst_adapter_new ();
+  fail_if (adapter == NULL);
+
+  buffer = gst_buffer_new_and_alloc (5);
+  fail_if (buffer == NULL);
+  gst_adapter_push (adapter, buffer);
+
+  buffer = gst_buffer_new_and_alloc (10);
+  fail_if (buffer == NULL);
+  gst_adapter_push (adapter, buffer);
+
+  buffer = gst_buffer_new_and_alloc (15);
+  fail_if (buffer == NULL);
+  gst_adapter_push (adapter, buffer);
+
+  fail_unless (gst_adapter_available (adapter) == 30);
+
+  buffer = gst_adapter_take_buffer_fast (adapter, 30);
+  fail_unless (gst_adapter_available (adapter) == 0);
+
+  fail_unless (gst_buffer_n_memory (buffer) == 3);
+  fail_unless (gst_buffer_get_sizes_range (buffer, 0, 1, NULL, NULL) == 5);
+  fail_unless (gst_buffer_get_sizes_range (buffer, 1, 1, NULL, NULL) == 10);
+  fail_unless (gst_buffer_get_sizes_range (buffer, 2, 1, NULL, NULL) == 15);
+
+  gst_buffer_unref (buffer);
+  g_object_unref (adapter);
+}
+
+GST_END_TEST;
+
 static Suite *
 gst_adapter_suite (void)
 {
@@ -853,6 +889,7 @@ gst_adapter_suite (void)
   tcase_add_test (tc_chain, test_scan);
   tcase_add_test (tc_chain, test_take_list);
   tcase_add_test (tc_chain, test_merge);
+  tcase_add_test (tc_chain, test_take_buffer_fast);
 
   return s;
 }
index 7044ad5..09a13ab 100644 (file)
@@ -16,6 +16,7 @@ EXPORTS
        gst_adapter_push
        gst_adapter_take
        gst_adapter_take_buffer
+       gst_adapter_take_buffer_fast
        gst_adapter_take_list
        gst_adapter_unmap
        gst_base_parse_add_index_entry