gstreamer_core/libs/gst/base/gstadapter.c
branchRCL_3
changeset 30 7e817e7e631c
parent 29 567bb019e3e3
--- a/gstreamer_core/libs/gst/base/gstadapter.c	Tue Aug 31 15:30:33 2010 +0300
+++ b/gstreamer_core/libs/gst/base/gstadapter.c	Wed Sep 01 12:16:41 2010 +0100
@@ -36,10 +36,6 @@
  * in chunks of the desired size using gst_adapter_peek(). After the data is
  * processed, it is freed using gst_adapter_flush().
  *
- * Other methods such as gst_adapter_take() and gst_adapter_take_buffer()
- * combine gst_adapter_peek() and gst_adapter_flush() in one method and are
- * potentially more convenient for some use cases. 
- *
  * For example, a sink pad's chain function that needs to pass data to a library
  * in 512-byte chunks could be implemented like this:
  * <programlisting>
@@ -78,22 +74,11 @@
  * Also check the GST_BUFFER_FLAG_DISCONT flag on the buffer. Some elements might
  * need to clear the adapter after a discontinuity.
  *
- * Since 0.10.24, the adapter will keep track of the timestamps of the buffers
- * that were pushed. The last seen timestamp before the current position
- * can be queried with gst_adapter_prev_timestamp(). This function can
- * optionally return the amount of bytes between the start of the buffer that
- * carried the timestamp and the current adapter position. The distance is
- * useful when dealing with, for example, raw audio samples because it allows
- * you to calculate the timestamp of the current adapter position by using the
- * last seen timestamp and the amount of bytes since.
- *
  * A last thing to note is that while GstAdapter is pretty optimized,
- * merging buffers still might be an operation that requires a malloc() and
- * memcpy() operation, and these operations are not the fastest. Because of
- * this, some functions like gst_adapter_available_fast() are provided to help
- * speed up such cases should you want to. To avoid repeated memory allocations,
- * gst_adapter_copy() can be used to copy data into a (statically allocated)
- * user provided buffer.
+ * merging buffers still might be an operation that requires a memcpy()
+ * operation, and this operation is not the fastest. Because of this, some
+ * functions like gst_adapter_available_fast() are provided to help speed up
+ * such cases should you want to.
  *
  * GstAdapter is not MT safe. All operations on an adapter must be serialized by
  * the caller. This is not normally a problem, however, as the normal use case
@@ -105,31 +90,22 @@
  * access the buffer later. The adapter will never modify the data in the
  * buffer pushed in it.
  *
- * Last reviewed on 2009-05-13 (0.10.24).
+ * Last reviewed on 2006-04-04 (0.10.6).
  */
 
-#include <gst/gst_private.h>
 #ifdef __SYMBIAN32__
 #include <gst_global.h>
 #endif
+
 #include "gstadapter.h"
 #include <string.h>
 
 /* default size for the assembled data buffer */
-#define DEFAULT_SIZE 4096
+#define DEFAULT_SIZE 16
 
 GST_DEBUG_CATEGORY_STATIC (gst_adapter_debug);
 #define GST_CAT_DEFAULT gst_adapter_debug
 
-#define GST_ADAPTER_GET_PRIVATE(obj)  \
-   (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_ADAPTER, GstAdapterPrivate))
-
-struct _GstAdapterPrivate
-{
-  GstClockTime timestamp;
-  guint64 distance;
-};
-
 #define _do_init(thing) \
   GST_DEBUG_CATEGORY_INIT (gst_adapter_debug, "adapter", 0, "object to splice and merge buffers to desired size")
 GST_BOILERPLATE_FULL (GstAdapter, gst_adapter, GObject, G_TYPE_OBJECT,
@@ -149,8 +125,6 @@
 {
   GObjectClass *object = G_OBJECT_CLASS (klass);
 
-  g_type_class_add_private (klass, sizeof (GstAdapterPrivate));
-
   object->dispose = gst_adapter_dispose;
   object->finalize = gst_adapter_finalize;
 }
@@ -158,11 +132,8 @@
 static void
 gst_adapter_init (GstAdapter * adapter, GstAdapterClass * g_class)
 {
-  adapter->priv = GST_ADAPTER_GET_PRIVATE (adapter);
   adapter->assembled_data = g_malloc (DEFAULT_SIZE);
   adapter->assembled_size = DEFAULT_SIZE;
-  adapter->priv->timestamp = GST_CLOCK_TIME_NONE;
-  adapter->priv->distance = 0;
 }
 
 static void
@@ -224,58 +195,6 @@
   adapter->size = 0;
   adapter->skip = 0;
   adapter->assembled_len = 0;
-  adapter->priv->timestamp = GST_CLOCK_TIME_NONE;
-  adapter->priv->distance = 0;
-}
-
-static inline void
-update_timestamp (GstAdapter * adapter, GstBuffer * buf)
-{
-  GstClockTime timestamp;
-
-  timestamp = GST_BUFFER_TIMESTAMP (buf);
-  if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
-    GST_LOG_OBJECT (adapter, "new timestamp %" GST_TIME_FORMAT,
-        GST_TIME_ARGS (timestamp));
-    adapter->priv->timestamp = timestamp;
-    adapter->priv->distance = 0;
-  }
-}
-
-/* copy data into @dest, skipping @skip bytes from the head buffers */
-static void
-copy_into_unchecked (GstAdapter * adapter, guint8 * dest, guint skip,
-    guint size)
-{
-  GSList *g;
-  GstBuffer *buf;
-  guint bsize, csize;
-
-  /* first step, do skipping */
-  g = adapter->buflist;
-  buf = g->data;
-  bsize = GST_BUFFER_SIZE (buf);
-  while (G_UNLIKELY (skip >= bsize)) {
-    skip -= bsize;
-    g = g_slist_next (g);
-    buf = g->data;
-    bsize = GST_BUFFER_SIZE (buf);
-  }
-  /* copy partial buffer */
-  csize = MIN (bsize - skip, size);
-  memcpy (dest, GST_BUFFER_DATA (buf) + skip, csize);
-  size -= csize;
-  dest += csize;
-
-  /* second step, copy remainder */
-  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;
-  }
 }
 
 /**
@@ -285,8 +204,6 @@
  *
  * 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.
  */
 #ifdef __SYMBIAN32__
 EXPORT_C
@@ -295,33 +212,46 @@
 void
 gst_adapter_push (GstAdapter * adapter, GstBuffer * buf)
 {
-  guint size;
-
   g_return_if_fail (GST_IS_ADAPTER (adapter));
   g_return_if_fail (GST_IS_BUFFER (buf));
 
-  size = GST_BUFFER_SIZE (buf);
+  adapter->size += GST_BUFFER_SIZE (buf);
 
-  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)) {
+    adapter->buflist = adapter->buflist_end = g_slist_append (NULL, buf);
   } else {
-    adapter->size += size;
+    /* Otherwise append to the end, and advance our end pointer */
+    adapter->buflist_end = g_slist_append (adapter->buflist_end, buf);
+    adapter->buflist_end = g_slist_next (adapter->buflist_end);
+  }
+}
 
-    /* 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);
-    }
+/* Internal function that copies data into the given buffer, size must be 
+ * bigger than the first buffer */
+static void
+gst_adapter_peek_into (GstAdapter * adapter, guint8 * data, guint size)
+{
+  GstBuffer *cur;
+  GSList *cur_list;
+  guint copied, to_copy;
+
+  /* The first buffer might be partly consumed, so need to handle
+   * 'skipped' bytes. */
+  cur = adapter->buflist->data;
+  copied = to_copy = MIN (GST_BUFFER_SIZE (cur) - adapter->skip, size);
+  memcpy (data, GST_BUFFER_DATA (cur) + adapter->skip, copied);
+  data += copied;
+
+  cur_list = g_slist_next (adapter->buflist);
+  while (copied < size) {
+    g_assert (cur_list);
+    cur = cur_list->data;
+    cur_list = g_slist_next (cur_list);
+    to_copy = MIN (GST_BUFFER_SIZE (cur), size - copied);
+    memcpy (data, GST_BUFFER_DATA (cur), to_copy);
+    data += to_copy;
+    copied += to_copy;
   }
 }
 
@@ -398,7 +328,6 @@
 gst_adapter_peek (GstAdapter * adapter, guint size)
 {
   GstBuffer *cur;
-  guint skip;
 
   g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
   g_return_val_if_fail (size > 0, NULL);
@@ -415,33 +344,29 @@
 
   /* our head buffer has enough data left, return it */
   cur = adapter->buflist->data;
-  skip = adapter->skip;
-  if (GST_BUFFER_SIZE (cur) >= size + skip)
-    return GST_BUFFER_DATA (cur) + skip;
+  if (GST_BUFFER_SIZE (cur) >= size + adapter->skip)
+    return GST_BUFFER_DATA (cur) + adapter->skip;
 
   /* We may be able to efficiently merge buffers in our pool to 
    * gather a big enough chunk to return it from the head buffer directly */
   if (gst_adapter_try_to_merge_up (adapter, size)) {
     /* Merged something! Check if there's enough avail now */
     cur = adapter->buflist->data;
-    if (GST_BUFFER_SIZE (cur) >= size + skip)
-      return GST_BUFFER_DATA (cur) + skip;
+    if (GST_BUFFER_SIZE (cur) >= size + adapter->skip)
+      return GST_BUFFER_DATA (cur) + adapter->skip;
   }
 
   /* Gonna need to copy stuff out */
-  if (G_UNLIKELY (adapter->assembled_size < size)) {
+  if (adapter->assembled_size < size) {
     adapter->assembled_size = (size / DEFAULT_SIZE + 1) * DEFAULT_SIZE;
-    GST_DEBUG_OBJECT (adapter, "resizing internal buffer to %u",
+    GST_DEBUG_OBJECT (adapter, "setting size of internal buffer to %u",
         adapter->assembled_size);
-    /* no g_realloc to avoid a memcpy that is not desired here since we are
-     * going to copy new data into the area below */
     g_free (adapter->assembled_data);
     adapter->assembled_data = g_malloc (adapter->assembled_size);
   }
   adapter->assembled_len = size;
 
-  GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "copy data from adapter");
-  copy_into_unchecked (adapter, adapter->assembled_data, skip, size);
+  gst_adapter_peek_into (adapter, adapter->assembled_data, size);
 
   return adapter->assembled_data;
 }
@@ -469,11 +394,37 @@
 void
 gst_adapter_copy (GstAdapter * adapter, guint8 * dest, guint offset, guint size)
 {
+  GSList *g;
+  int skip;
+
   g_return_if_fail (GST_IS_ADAPTER (adapter));
   g_return_if_fail (size > 0);
-  g_return_if_fail (offset + size <= adapter->size);
+
+  /* we don't have enough data, return. This is unlikely
+   * as one usually does an _available() first instead of copying a
+   * random size. */
+  if (G_UNLIKELY (offset + size > adapter->size))
+    return;
+
+  skip = adapter->skip;
+  for (g = adapter->buflist; g && size > 0; g = g_slist_next (g)) {
+    GstBuffer *buf;
 
-  copy_into_unchecked (adapter, dest, offset + adapter->skip, size);
+    buf = g->data;
+    if (offset < GST_BUFFER_SIZE (buf) - skip) {
+      int n;
+
+      n = MIN (GST_BUFFER_SIZE (buf) - skip - offset, size);
+      memcpy (dest, GST_BUFFER_DATA (buf) + skip + offset, n);
+
+      dest += n;
+      offset = 0;
+      size -= n;
+    } else {
+      offset -= GST_BUFFER_SIZE (buf) - skip;
+    }
+    skip = 0;
+  }
 }
 
 /**
@@ -494,56 +445,29 @@
 gst_adapter_flush (GstAdapter * adapter, guint flush)
 {
   GstBuffer *cur;
-  guint size;
-  GstAdapterPrivate *priv;
-  GSList *g;
 
   g_return_if_fail (GST_IS_ADAPTER (adapter));
   g_return_if_fail (flush <= adapter->size);
 
   GST_LOG_OBJECT (adapter, "flushing %u bytes", flush);
-
-  /* flushing out 0 bytes will do nothing */
-  if (G_UNLIKELY (flush == 0))
-    return;
-
-  priv = adapter->priv;
-
-  /* clear state */
   adapter->size -= flush;
   adapter->assembled_len = 0;
-
-  /* take skip into account */
-  flush += adapter->skip;
-  /* distance is always at least the amount of skipped bytes */
-  priv->distance -= adapter->skip;
-
-  g = adapter->buflist;
-  cur = g->data;
-  size = GST_BUFFER_SIZE (cur);
-  while (flush >= size) {
-    /* can skip whole buffer */
-    GST_LOG_OBJECT (adapter, "flushing out head buffer");
-    priv->distance += size;
-    flush -= size;
-
-    gst_buffer_unref (cur);
-    g = g_slist_delete_link (g, g);
-
-    if (G_UNLIKELY (g == NULL)) {
-      GST_LOG_OBJECT (adapter, "adapter empty now");
-      adapter->buflist_end = NULL;
+  while (flush > 0) {
+    cur = adapter->buflist->data;
+    if (GST_BUFFER_SIZE (cur) <= flush + adapter->skip) {
+      /* can skip whole buffer */
+      flush -= GST_BUFFER_SIZE (cur) - adapter->skip;
+      adapter->skip = 0;
+      adapter->buflist =
+          g_slist_delete_link (adapter->buflist, adapter->buflist);
+      if (G_UNLIKELY (adapter->buflist == NULL))
+        adapter->buflist_end = NULL;
+      gst_buffer_unref (cur);
+    } else {
+      adapter->skip += flush;
       break;
     }
-    /* there is a new head buffer, update the timestamp */
-    cur = g->data;
-    update_timestamp (adapter, cur);
-    size = GST_BUFFER_SIZE (cur);
   }
-  adapter->buflist = g;
-  /* account for the remaining bytes */
-  adapter->skip = flush;
-  adapter->priv->distance += flush;
 }
 
 /**
@@ -576,18 +500,15 @@
   if (G_UNLIKELY (nbytes > adapter->size))
     return NULL;
 
-  /* we have enough assembled data, take from there */
+  data = g_malloc (nbytes);
+
+  /* we have enough assembled data, copy from there */
   if (adapter->assembled_len >= nbytes) {
     GST_LOG_OBJECT (adapter, "taking %u bytes already assembled", nbytes);
-    data = adapter->assembled_data;
-    /* allocate new data, assembled_len will be set to 0 in the flush below */
-    adapter->assembled_data = g_malloc (adapter->assembled_size);
+    memcpy (data, adapter->assembled_data, nbytes);
   } else {
-    /* we need to allocate and copy. We could potentially copy bytes from the
-     * assembled data before doing the copy_into */
     GST_LOG_OBJECT (adapter, "taking %u bytes by collection", nbytes);
-    data = g_malloc (nbytes);
-    copy_into_unchecked (adapter, data, adapter->skip, nbytes);
+    gst_adapter_peek_into (adapter, data, nbytes);
   }
 
   gst_adapter_flush (adapter, nbytes);
@@ -622,7 +543,6 @@
 {
   GstBuffer *buffer;
   GstBuffer *cur;
-  guint hsize, skip;
 
   g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
   g_return_val_if_fail (nbytes > 0, NULL);
@@ -635,52 +555,43 @@
   if (G_UNLIKELY (nbytes > adapter->size))
     return NULL;
 
+  /* our head buffer has enough data left, return it */
   cur = adapter->buflist->data;
-  skip = adapter->skip;
-  hsize = GST_BUFFER_SIZE (cur);
-
-  /* our head buffer has enough data left, return it */
-  if (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 + skip) {
+  if (GST_BUFFER_SIZE (cur) >= nbytes + adapter->skip) {
     GST_LOG_OBJECT (adapter, "providing buffer of %d bytes via sub-buffer",
         nbytes);
-    buffer = gst_buffer_create_sub (cur, skip, nbytes);
-    goto done;
+    buffer = gst_buffer_create_sub (cur, adapter->skip, nbytes);
+
+    gst_adapter_flush (adapter, nbytes);
+
+    return buffer;
   }
 
   if (gst_adapter_try_to_merge_up (adapter, nbytes)) {
     /* Merged something, let's try again for sub-buffering */
     cur = adapter->buflist->data;
-    if (GST_BUFFER_SIZE (cur) >= nbytes + skip) {
+    if (GST_BUFFER_SIZE (cur) >= nbytes + adapter->skip) {
       GST_LOG_OBJECT (adapter, "providing buffer of %d bytes via sub-buffer",
           nbytes);
-      buffer = gst_buffer_create_sub (cur, skip, nbytes);
-      goto done;
+      buffer = gst_buffer_create_sub (cur, adapter->skip, nbytes);
+
+      gst_adapter_flush (adapter, nbytes);
+
+      return buffer;
     }
   }
 
+  buffer = gst_buffer_new_and_alloc (nbytes);
+
   /* we have enough assembled data, copy from there */
   if (adapter->assembled_len >= nbytes) {
     GST_LOG_OBJECT (adapter, "taking %u bytes already assembled", nbytes);
-    buffer = gst_buffer_new ();
-    GST_BUFFER_SIZE (buffer) = nbytes;
-    GST_BUFFER_DATA (buffer) = adapter->assembled_data;
-    GST_BUFFER_MALLOCDATA (buffer) = adapter->assembled_data;
-    /* flush will set the assembled_len to 0 */
-    adapter->assembled_data = g_malloc (adapter->assembled_size);
+    memcpy (GST_BUFFER_DATA (buffer), adapter->assembled_data, nbytes);
   } else {
-    /* we need to allocate and copy. We could potentially copy bytes from the
-     * assembled data before doing the copy_into */
-    buffer = gst_buffer_new_and_alloc (nbytes);
     GST_LOG_OBJECT (adapter, "taking %u bytes by collection", nbytes);
-    copy_into_unchecked (adapter, GST_BUFFER_DATA (buffer), skip, nbytes);
+    gst_adapter_peek_into (adapter, GST_BUFFER_DATA (buffer), nbytes);
   }
 
-done:
   gst_adapter_flush (adapter, nbytes);
 
   return buffer;
@@ -726,9 +637,6 @@
 guint
 gst_adapter_available_fast (GstAdapter * adapter)
 {
-  GstBuffer *first;
-  guint size;
-
   g_return_val_if_fail (GST_IS_ADAPTER (adapter), 0);
 
   /* no buffers, we have no data */
@@ -739,153 +647,9 @@
   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);
-
-  /* we can quickly get the (remaining) data of the first buffer */
-  return size - adapter->skip;
-}
-
-/**
- * gst_adapter_prev_timestamp:
- * @adapter: a #GstAdapter
- * @distance: pointer to location for distance or NULL
- *
- * Get the timestamp that was before the current byte in the adapter. When
- * @distance is given, the amount of bytes between the timestamp and the current
- * position is returned.
- *
- * The timestamp is reset to GST_CLOCK_TIME_NONE when the adapter is first
- * created or when it is cleared.
- *
- * Returns: The previously seen timestamp.
- *
- * Since: 0.10.24
- */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-GstClockTime
-gst_adapter_prev_timestamp (GstAdapter * adapter, guint64 * distance)
-{
-  g_return_val_if_fail (GST_IS_ADAPTER (adapter), GST_CLOCK_TIME_NONE);
-
-  if (distance)
-    *distance = adapter->priv->distance;
-
-  return adapter->priv->timestamp;
-}
+  /* we cannot have skipped more than the first buffer */
+  g_assert (GST_BUFFER_SIZE (adapter->buflist->data) > adapter->skip);
 
-/**
- * gst_adapter_masked_scan_uint32:
- * @adapter: a #GstAdapter
- * @mask: mask to apply to data before matching against @pattern
- * @pattern: pattern to match (after mask is applied)
- * @offset: offset into the adapter data from which to start scanning, returns
- *          the last scanned position.
- * @size: number of bytes to scan from offset
- *
- * Scan for pattern @pattern with applied mask @mask in the adapter data,
- * starting from offset @offset. 
- *
- * The bytes in @pattern and @mask are interpreted left-to-right, regardless
- * of endianness.  All four bytes of the pattern must be present in the
- * adapter for it to match, even if the first or last bytes are masked out.
- *
- * It is an error to call this function without making sure that there is
- * enough data (offset+size bytes) in the adapter.
- *
- * Returns: offset of the first match, or -1 if no match was found.
- *
- * Example:
- * <programlisting>
- * // Assume the adapter contains 0x00 0x01 0x02 ... 0xfe 0xff
- * 
- * gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x00010203, 0, 256);
- * // -> returns 0
- * gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x00010203, 1, 255);
- * // -> returns -1
- * gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x01020304, 1, 255);
- * // -> returns 1
- * gst_adapter_masked_scan_uint32 (adapter, 0xffff, 0x0001, 0, 256);
- * // -> returns -1
- * gst_adapter_masked_scan_uint32 (adapter, 0xffff, 0x0203, 0, 256);
- * // -> returns 0
- * gst_adapter_masked_scan_uint32 (adapter, 0xffff0000, 0x02030000, 0, 256);
- * // -> returns 2
- * gst_adapter_masked_scan_uint32 (adapter, 0xffff0000, 0x02030000, 0, 4);
- * // -> returns -1
- * </programlisting>
- *
- * Since: 0.10.24
- */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-guint
-gst_adapter_masked_scan_uint32 (GstAdapter * adapter, guint32 mask,
-    guint32 pattern, guint offset, guint size)
-{
-  GSList *g;
-  guint skip, bsize, i;
-  guint32 state;
-  guint8 *bdata;
-  GstBuffer *buf;
-
-  g_return_val_if_fail (size > 0, -1);
-  g_return_val_if_fail (offset + size <= adapter->size, -1);
-
-  /* we can't find the pattern with less than 4 bytes */
-  if (G_UNLIKELY (size < 4))
-    return -1;
-
-  skip = offset + adapter->skip;
-
-  /* first step, do skipping and position on the first buffer */
-  g = adapter->buflist;
-  buf = g->data;
-  bsize = GST_BUFFER_SIZE (buf);
-  while (G_UNLIKELY (skip >= bsize)) {
-    skip -= bsize;
-    g = g_slist_next (g);
-    buf = g->data;
-    bsize = GST_BUFFER_SIZE (buf);
-  }
-  /* get the data now */
-  bsize -= skip;
-  bdata = GST_BUFFER_DATA (buf) + skip;
-  skip = 0;
-
-  /* set the state to something that does not match */
-  state = ~pattern;
-
-  /* now find data */
-  do {
-    bsize = MIN (bsize, size);
-    for (i = 0; i < bsize; i++) {
-      state = ((state << 8) | bdata[i]);
-      if (G_UNLIKELY ((state & mask) == pattern)) {
-        /* we have a match but we need to have skipped at
-         * least 4 bytes to fill the state. */
-        if (G_LIKELY (skip + i >= 3))
-          return offset + skip + i - 3;
-      }
-    }
-    size -= bsize;
-    if (size == 0)
-      break;
-
-    /* nothing found yet, go to next buffer */
-    skip += bsize;
-    g = g_slist_next (g);
-    buf = g->data;
-    bsize = GST_BUFFER_SIZE (buf);
-    bdata = GST_BUFFER_DATA (buf);
-  } while (TRUE);
-
-  /* nothing found */
-  return -1;
+  /* we can quickly get the data of the first buffer */
+  return GST_BUFFER_SIZE (adapter->buflist->data) - adapter->skip;
 }