adapter: optimize taking the headbuffer
authorWim Taymans <wim.taymans@collabora.co.uk>
Mon, 27 Apr 2009 08:13:01 +0000 (10:13 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Tue, 12 May 2009 08:25:40 +0000 (10:25 +0200)
When a are requested to take a buffer from the adapter that is exactly the
headbuffer, don't make a subbuffer of it but return that head buffer.

Add a unit-test for this new optimisation.

libs/gst/base/gstadapter.c
tests/check/libs/adapter.c

index 58c280d0a1a3cd8ab0689d74763ff2be745a839c..981a2bb0574fbfd9870be359aa03594ba7b01a71 100644 (file)
@@ -523,6 +523,7 @@ gst_adapter_take_buffer (GstAdapter * adapter, guint nbytes)
 {
   GstBuffer *buffer;
   GstBuffer *cur;
+  guint hsize;
 
   g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
   g_return_val_if_fail (nbytes > 0, NULL);
@@ -535,16 +536,20 @@ gst_adapter_take_buffer (GstAdapter * adapter, guint nbytes)
   if (G_UNLIKELY (nbytes > adapter->size))
     return NULL;
 
-  /* our head buffer has enough data left, return it */
   cur = adapter->buflist->data;
-  if (GST_BUFFER_SIZE (cur) >= nbytes + adapter->skip) {
+  hsize = GST_BUFFER_SIZE (cur);
+
+  /* our head buffer has enough data left, return it */
+  if (adapter->skip == 0 && hsize == nbytes) {
+    GST_LOG_OBJECT (adapter, "providing buffer of %d bytes as head buffer",
+        nbytes);
+    buffer = gst_buffer_ref (cur);
+    goto done;
+  } else if (hsize >= nbytes + adapter->skip) {
     GST_LOG_OBJECT (adapter, "providing buffer of %d bytes via sub-buffer",
         nbytes);
     buffer = gst_buffer_create_sub (cur, adapter->skip, nbytes);
-
-    gst_adapter_flush (adapter, nbytes);
-
-    return buffer;
+    goto done;
   }
 
   if (gst_adapter_try_to_merge_up (adapter, nbytes)) {
@@ -554,10 +559,7 @@ gst_adapter_take_buffer (GstAdapter * adapter, guint nbytes)
       GST_LOG_OBJECT (adapter, "providing buffer of %d bytes via sub-buffer",
           nbytes);
       buffer = gst_buffer_create_sub (cur, adapter->skip, nbytes);
-
-      gst_adapter_flush (adapter, nbytes);
-
-      return buffer;
+      goto done;
     }
   }
 
@@ -572,6 +574,7 @@ gst_adapter_take_buffer (GstAdapter * adapter, guint nbytes)
     gst_adapter_peek_into (adapter, GST_BUFFER_DATA (buffer), nbytes);
   }
 
+done:
   gst_adapter_flush (adapter, nbytes);
 
   return buffer;
index e45c210d9cf2b56fe1552e12a5746631c7de9ce8..41924c7fa258aeb73c69073334932f8c230ce37a 100644 (file)
@@ -149,6 +149,44 @@ GST_END_TEST;
  */
 GST_START_TEST (test_take1)
 {
+  GstAdapter *adapter;
+  GstBuffer *buffer, *buffer2;
+  guint avail;
+  guint8 *data, *data2;
+
+  adapter = gst_adapter_new ();
+  fail_unless (adapter != NULL);
+
+  buffer = gst_buffer_new_and_alloc (100);
+  fail_unless (buffer != NULL);
+  fail_unless (GST_BUFFER_DATA (buffer) != NULL);
+  fail_unless (GST_BUFFER_SIZE (buffer) == 100);
+
+  data = GST_BUFFER_DATA (buffer);
+
+  /* push in the adapter */
+  gst_adapter_push (adapter, buffer);
+
+  avail = gst_adapter_available (adapter);
+  fail_unless (avail == 100);
+
+  /* take out buffer */
+  buffer2 = gst_adapter_take_buffer (adapter, 100);
+  fail_unless (buffer2 != NULL);
+  fail_unless (GST_BUFFER_DATA (buffer2) != NULL);
+  fail_unless (GST_BUFFER_SIZE (buffer2) == 100);
+  data2 = GST_BUFFER_DATA (buffer2);
+
+  avail = gst_adapter_available (adapter);
+  fail_unless (avail == 0);
+
+  /* the buffer should be the same */
+  fail_unless (buffer == buffer2);
+  fail_unless (data == data2);
+
+  gst_buffer_unref (buffer2);
+
+  g_object_unref (adapter);
 }
 
 GST_END_TEST;