gstreamer_core/libs/gst/base/gstadapter.c
changeset 0 0e761a78d257
child 8 4a7fac7dd34a
equal deleted inserted replaced
-1:000000000000 0:0e761a78d257
       
     1 /* GStreamer
       
     2  * Copyright (C) 2004 Benjamin Otte <otte@gnome.org>
       
     3  *               2005 Wim Taymans <wim@fluendo.com>
       
     4  *
       
     5  * This library is free software; you can redistribute it and/or
       
     6  * modify it under the terms of the GNU Library General Public
       
     7  * License as published by the Free Software Foundation; either
       
     8  * version 2 of the License, or (at your option) any later version.
       
     9  *
       
    10  * This library is distributed in the hope that it will be useful,
       
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    13  * Library General Public License for more details.
       
    14  *
       
    15  * You should have received a copy of the GNU Library General Public
       
    16  * License along with this library; if not, write to the
       
    17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    18  * Boston, MA 02111-1307, USA.
       
    19  */
       
    20 
       
    21 /**
       
    22  * SECTION:gstadapter
       
    23  * @short_description: adapts incoming data on a sink pad into chunks of N bytes
       
    24  *
       
    25  * This class is for elements that receive buffers in an undesired size.
       
    26  * While for example raw video contains one image per buffer, the same is not
       
    27  * true for a lot of other formats, especially those that come directly from
       
    28  * a file. So if you have undefined buffer sizes and require a specific size,
       
    29  * this object is for you.
       
    30  *
       
    31  * An adapter is created with gst_adapter_new(). It can be freed again with
       
    32  * g_object_unref().
       
    33  *
       
    34  * The theory of operation is like this: All buffers received are put
       
    35  * into the adapter using gst_adapter_push() and the data is then read back
       
    36  * in chunks of the desired size using gst_adapter_peek(). After the data is
       
    37  * processed, it is freed using gst_adapter_flush().
       
    38  *
       
    39  * For example, a sink pad's chain function that needs to pass data to a library
       
    40  * in 512-byte chunks could be implemented like this:
       
    41  * <programlisting>
       
    42  * static GstFlowReturn
       
    43  * sink_pad_chain (GstPad *pad, GstBuffer *buffer)
       
    44  * {
       
    45  *   MyElement *this;
       
    46  *   GstAdapter *adapter;
       
    47  *   GstFlowReturn ret = GST_FLOW_OK;
       
    48  *   
       
    49  *   // will give the element an extra ref; remember to drop it 
       
    50  *   this = MY_ELEMENT (gst_pad_get_parent (pad));
       
    51  *   adapter = this->adapter;
       
    52  *   
       
    53  *   // put buffer into adapter
       
    54  *   gst_adapter_push (adapter, buffer);
       
    55  *   // while we can read out 512 bytes, process them
       
    56  *   while (gst_adapter_available (adapter) >= 512 && ret == GST_FLOW_OK) {
       
    57  *     // use flowreturn as an error value
       
    58  *     ret = my_library_foo (gst_adapter_peek (adapter, 512));
       
    59  *     gst_adapter_flush (adapter, 512);
       
    60  *   }
       
    61  *   
       
    62  *   gst_object_unref (this);
       
    63  *   return ret;
       
    64  * }
       
    65  * </programlisting>
       
    66  * For another example, a simple element inside GStreamer that uses GstAdapter
       
    67  * is the libvisual element.
       
    68  *
       
    69  * An element using GstAdapter in its sink pad chain function should ensure that
       
    70  * when the FLUSH_STOP event is received, that any queued data is cleared using
       
    71  * gst_adapter_clear(). Data should also be cleared or processed on EOS and
       
    72  * when changing state from #GST_STATE_PAUSED to #GST_STATE_READY.
       
    73  *
       
    74  * Also check the GST_BUFFER_FLAG_DISCONT flag on the buffer. Some elements might
       
    75  * need to clear the adapter after a discontinuity.
       
    76  *
       
    77  * A last thing to note is that while GstAdapter is pretty optimized,
       
    78  * merging buffers still might be an operation that requires a memcpy()
       
    79  * operation, and this operation is not the fastest. Because of this, some
       
    80  * functions like gst_adapter_available_fast() are provided to help speed up
       
    81  * such cases should you want to.
       
    82  *
       
    83  * GstAdapter is not MT safe. All operations on an adapter must be serialized by
       
    84  * the caller. This is not normally a problem, however, as the normal use case
       
    85  * of GstAdapter is inside one pad's chain function, in which case access is
       
    86  * serialized via the pad's STREAM_LOCK.
       
    87  *
       
    88  * Note that gst_adapter_push() takes ownership of the buffer passed. Use 
       
    89  * gst_buffer_ref() before pushing it into the adapter if you still want to
       
    90  * access the buffer later. The adapter will never modify the data in the
       
    91  * buffer pushed in it.
       
    92  *
       
    93  * Last reviewed on 2006-04-04 (0.10.6).
       
    94  */
       
    95 
       
    96 #ifdef __SYMBIAN32__
       
    97 #include <gst_global.h>
       
    98 #endif
       
    99 
       
   100 #include "gstadapter.h"
       
   101 #include <string.h>
       
   102 
       
   103 /* default size for the assembled data buffer */
       
   104 #define DEFAULT_SIZE 16
       
   105 
       
   106 GST_DEBUG_CATEGORY_STATIC (gst_adapter_debug);
       
   107 #define GST_CAT_DEFAULT gst_adapter_debug
       
   108 
       
   109 #define _do_init(thing) \
       
   110   GST_DEBUG_CATEGORY_INIT (gst_adapter_debug, "adapter", 0, "object to splice and merge buffers to desired size")
       
   111 GST_BOILERPLATE_FULL (GstAdapter, gst_adapter, GObject, G_TYPE_OBJECT,
       
   112     _do_init);
       
   113 
       
   114 static void gst_adapter_dispose (GObject * object);
       
   115 static void gst_adapter_finalize (GObject * object);
       
   116 
       
   117 static void
       
   118 gst_adapter_base_init (gpointer g_class)
       
   119 {
       
   120   /* nop */
       
   121 }
       
   122 
       
   123 static void
       
   124 gst_adapter_class_init (GstAdapterClass * klass)
       
   125 {
       
   126   GObjectClass *object = G_OBJECT_CLASS (klass);
       
   127 
       
   128   object->dispose = gst_adapter_dispose;
       
   129   object->finalize = gst_adapter_finalize;
       
   130 }
       
   131 
       
   132 static void
       
   133 gst_adapter_init (GstAdapter * adapter, GstAdapterClass * g_class)
       
   134 {
       
   135   adapter->assembled_data = g_malloc (DEFAULT_SIZE);
       
   136   adapter->assembled_size = DEFAULT_SIZE;
       
   137 }
       
   138 
       
   139 static void
       
   140 gst_adapter_dispose (GObject * object)
       
   141 {
       
   142   GstAdapter *adapter = GST_ADAPTER (object);
       
   143 
       
   144   gst_adapter_clear (adapter);
       
   145 
       
   146   GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
       
   147 }
       
   148 
       
   149 static void
       
   150 gst_adapter_finalize (GObject * object)
       
   151 {
       
   152   GstAdapter *adapter = GST_ADAPTER (object);
       
   153 
       
   154   g_free (adapter->assembled_data);
       
   155 
       
   156   GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
       
   157 }
       
   158 
       
   159 /**
       
   160  * gst_adapter_new:
       
   161  *
       
   162  * Creates a new #GstAdapter. Free with g_object_unref().
       
   163  *
       
   164  * Returns: a new #GstAdapter
       
   165  */
       
   166 #ifdef __SYMBIAN32__
       
   167 EXPORT_C
       
   168 #endif
       
   169 
       
   170 GstAdapter *
       
   171 gst_adapter_new (void)
       
   172 {
       
   173   return g_object_new (GST_TYPE_ADAPTER, NULL);
       
   174 }
       
   175 
       
   176 /**
       
   177  * gst_adapter_clear:
       
   178  * @adapter: a #GstAdapter
       
   179  *
       
   180  * Removes all buffers from @adapter.
       
   181  */
       
   182 #ifdef __SYMBIAN32__
       
   183 EXPORT_C
       
   184 #endif
       
   185 
       
   186 void
       
   187 gst_adapter_clear (GstAdapter * adapter)
       
   188 {
       
   189   g_return_if_fail (GST_IS_ADAPTER (adapter));
       
   190 
       
   191   g_slist_foreach (adapter->buflist, (GFunc) gst_mini_object_unref, NULL);
       
   192   g_slist_free (adapter->buflist);
       
   193   adapter->buflist = NULL;
       
   194   adapter->buflist_end = NULL;
       
   195   adapter->size = 0;
       
   196   adapter->skip = 0;
       
   197   adapter->assembled_len = 0;
       
   198 }
       
   199 
       
   200 /**
       
   201  * gst_adapter_push:
       
   202  * @adapter: a #GstAdapter
       
   203  * @buf: a #GstBuffer to add to queue in the adapter
       
   204  *
       
   205  * Adds the data from @buf to the data stored inside @adapter and takes
       
   206  * ownership of the buffer.
       
   207  */
       
   208 #ifdef __SYMBIAN32__
       
   209 EXPORT_C
       
   210 #endif
       
   211 
       
   212 void
       
   213 gst_adapter_push (GstAdapter * adapter, GstBuffer * buf)
       
   214 {
       
   215   g_return_if_fail (GST_IS_ADAPTER (adapter));
       
   216   g_return_if_fail (GST_IS_BUFFER (buf));
       
   217 
       
   218   adapter->size += GST_BUFFER_SIZE (buf);
       
   219 
       
   220   /* Note: merging buffers at this point is premature. */
       
   221   if (G_UNLIKELY (adapter->buflist == NULL)) {
       
   222     adapter->buflist = adapter->buflist_end = g_slist_append (NULL, buf);
       
   223   } else {
       
   224     /* Otherwise append to the end, and advance our end pointer */
       
   225     adapter->buflist_end = g_slist_append (adapter->buflist_end, buf);
       
   226     adapter->buflist_end = g_slist_next (adapter->buflist_end);
       
   227   }
       
   228 }
       
   229 
       
   230 /* Internal function that copies data into the given buffer, size must be 
       
   231  * bigger than the first buffer */
       
   232 static void
       
   233 gst_adapter_peek_into (GstAdapter * adapter, guint8 * data, guint size)
       
   234 {
       
   235   GstBuffer *cur;
       
   236   GSList *cur_list;
       
   237   guint copied, to_copy;
       
   238 
       
   239   /* The first buffer might be partly consumed, so need to handle
       
   240    * 'skipped' bytes. */
       
   241   cur = adapter->buflist->data;
       
   242   copied = to_copy = MIN (GST_BUFFER_SIZE (cur) - adapter->skip, size);
       
   243   memcpy (data, GST_BUFFER_DATA (cur) + adapter->skip, copied);
       
   244   data += copied;
       
   245 
       
   246   cur_list = g_slist_next (adapter->buflist);
       
   247   while (copied < size) {
       
   248     g_assert (cur_list);
       
   249     cur = cur_list->data;
       
   250     cur_list = g_slist_next (cur_list);
       
   251     to_copy = MIN (GST_BUFFER_SIZE (cur), size - copied);
       
   252     memcpy (data, GST_BUFFER_DATA (cur), to_copy);
       
   253     data += to_copy;
       
   254     copied += to_copy;
       
   255   }
       
   256 }
       
   257 
       
   258 /* Internal method only. Tries to merge buffers at the head of the queue
       
   259  * to form a single larger buffer of size 'size'. Only merges buffers that
       
   260  * where 'gst_buffer_is_span_fast' returns TRUE.
       
   261  *
       
   262  * Returns TRUE if it managed to merge anything.
       
   263  */
       
   264 static gboolean
       
   265 gst_adapter_try_to_merge_up (GstAdapter * adapter, guint size)
       
   266 {
       
   267   GstBuffer *cur, *head;
       
   268   GSList *g;
       
   269 
       
   270   g = adapter->buflist;
       
   271   if (g == NULL)
       
   272     return FALSE;
       
   273 
       
   274   head = g->data;
       
   275   g = g_slist_next (g);
       
   276 
       
   277   /* How large do we want our head buffer? The requested size, plus whatever's
       
   278    * been skipped already */
       
   279   size += adapter->skip;
       
   280 
       
   281   while (g != NULL && GST_BUFFER_SIZE (head) < size) {
       
   282     cur = g->data;
       
   283     if (!gst_buffer_is_span_fast (head, cur))
       
   284       return TRUE;
       
   285 
       
   286     /* Merge the head buffer and the next in line */
       
   287     GST_LOG_OBJECT (adapter,
       
   288         "Merging buffers of size %u & %u in search of target %u",
       
   289         GST_BUFFER_SIZE (head), GST_BUFFER_SIZE (cur), size);
       
   290 
       
   291     head = gst_buffer_join (head, cur);
       
   292 
       
   293     /* Delete the front list item, and store our new buffer in the 2nd list 
       
   294      * item */
       
   295     adapter->buflist = g_slist_delete_link (adapter->buflist, adapter->buflist);
       
   296     g->data = head;
       
   297   }
       
   298 
       
   299   return FALSE;
       
   300 }
       
   301 
       
   302 /**
       
   303  * gst_adapter_peek:
       
   304  * @adapter: a #GstAdapter
       
   305  * @size: the number of bytes to peek
       
   306  *
       
   307  * Gets the first @size bytes stored in the @adapter. The returned pointer is
       
   308  * valid until the next function is called on the adapter.
       
   309  *
       
   310  * Note that setting the returned pointer as the data of a #GstBuffer is
       
   311  * incorrect for general-purpose plugins. The reason is that if a downstream
       
   312  * element stores the buffer so that it has access to it outside of the bounds
       
   313  * of its chain function, the buffer will have an invalid data pointer after
       
   314  * your element flushes the bytes. In that case you should use
       
   315  * gst_adapter_take(), which returns a freshly-allocated buffer that you can set
       
   316  * as #GstBuffer malloc_data or the potentially more performant 
       
   317  * gst_adapter_take_buffer().
       
   318  *
       
   319  * Returns #NULL if @size bytes are not available.
       
   320  *
       
   321  * Returns: a pointer to the first @size bytes of data, or NULL.
       
   322  */
       
   323 #ifdef __SYMBIAN32__
       
   324 EXPORT_C
       
   325 #endif
       
   326 
       
   327 const guint8 *
       
   328 gst_adapter_peek (GstAdapter * adapter, guint size)
       
   329 {
       
   330   GstBuffer *cur;
       
   331 
       
   332   g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
       
   333   g_return_val_if_fail (size > 0, NULL);
       
   334 
       
   335   /* we don't have enough data, return NULL. This is unlikely
       
   336    * as one usually does an _available() first instead of peeking a
       
   337    * random size. */
       
   338   if (G_UNLIKELY (size > adapter->size))
       
   339     return NULL;
       
   340 
       
   341   /* we have enough assembled data, return it */
       
   342   if (adapter->assembled_len >= size)
       
   343     return adapter->assembled_data;
       
   344 
       
   345   /* our head buffer has enough data left, return it */
       
   346   cur = adapter->buflist->data;
       
   347   if (GST_BUFFER_SIZE (cur) >= size + adapter->skip)
       
   348     return GST_BUFFER_DATA (cur) + adapter->skip;
       
   349 
       
   350   /* We may be able to efficiently merge buffers in our pool to 
       
   351    * gather a big enough chunk to return it from the head buffer directly */
       
   352   if (gst_adapter_try_to_merge_up (adapter, size)) {
       
   353     /* Merged something! Check if there's enough avail now */
       
   354     cur = adapter->buflist->data;
       
   355     if (GST_BUFFER_SIZE (cur) >= size + adapter->skip)
       
   356       return GST_BUFFER_DATA (cur) + adapter->skip;
       
   357   }
       
   358 
       
   359   /* Gonna need to copy stuff out */
       
   360   if (adapter->assembled_size < size) {
       
   361     adapter->assembled_size = (size / DEFAULT_SIZE + 1) * DEFAULT_SIZE;
       
   362     GST_DEBUG_OBJECT (adapter, "setting size of internal buffer to %u",
       
   363         adapter->assembled_size);
       
   364     g_free (adapter->assembled_data);
       
   365     adapter->assembled_data = g_malloc (adapter->assembled_size);
       
   366   }
       
   367   adapter->assembled_len = size;
       
   368 
       
   369   gst_adapter_peek_into (adapter, adapter->assembled_data, size);
       
   370 
       
   371   return adapter->assembled_data;
       
   372 }
       
   373 
       
   374 /**
       
   375  * gst_adapter_copy:
       
   376  * @adapter: a #GstAdapter
       
   377  * @dest: the memory where to copy to
       
   378  * @offset: the bytes offset in the adapter to start from
       
   379  * @size: the number of bytes to copy
       
   380  *
       
   381  * Copies @size bytes of data starting at @offset out of the buffers
       
   382  * contained in @GstAdapter into an array @dest provided by the caller.
       
   383  *
       
   384  * The array @dest should be large enough to contain @size bytes.
       
   385  * The user should check that the adapter has (@offset + @size) bytes
       
   386  * available before calling this function.
       
   387  *
       
   388  * Since: 0.10.12
       
   389  */
       
   390 #ifdef __SYMBIAN32__
       
   391 EXPORT_C
       
   392 #endif
       
   393 
       
   394 void
       
   395 gst_adapter_copy (GstAdapter * adapter, guint8 * dest, guint offset, guint size)
       
   396 {
       
   397   GSList *g;
       
   398   int skip;
       
   399 
       
   400   g_return_if_fail (GST_IS_ADAPTER (adapter));
       
   401   g_return_if_fail (size > 0);
       
   402 
       
   403   /* we don't have enough data, return. This is unlikely
       
   404    * as one usually does an _available() first instead of copying a
       
   405    * random size. */
       
   406   if (G_UNLIKELY (offset + size > adapter->size))
       
   407     return;
       
   408 
       
   409   skip = adapter->skip;
       
   410   for (g = adapter->buflist; g && size > 0; g = g_slist_next (g)) {
       
   411     GstBuffer *buf;
       
   412 
       
   413     buf = g->data;
       
   414     if (offset < GST_BUFFER_SIZE (buf) - skip) {
       
   415       int n;
       
   416 
       
   417       n = MIN (GST_BUFFER_SIZE (buf) - skip - offset, size);
       
   418       memcpy (dest, GST_BUFFER_DATA (buf) + skip + offset, n);
       
   419 
       
   420       dest += n;
       
   421       offset = 0;
       
   422       size -= n;
       
   423     } else {
       
   424       offset -= GST_BUFFER_SIZE (buf) - skip;
       
   425     }
       
   426     skip = 0;
       
   427   }
       
   428 }
       
   429 
       
   430 /**
       
   431  * gst_adapter_flush:
       
   432  * @adapter: a #GstAdapter
       
   433  * @flush: the number of bytes to flush
       
   434  *
       
   435  * Flushes the first @flush bytes in the @adapter. The caller must ensure that
       
   436  * at least this many bytes are available.
       
   437  *
       
   438  * See also: gst_adapter_peek().
       
   439  */
       
   440 #ifdef __SYMBIAN32__
       
   441 EXPORT_C
       
   442 #endif
       
   443 
       
   444 void
       
   445 gst_adapter_flush (GstAdapter * adapter, guint flush)
       
   446 {
       
   447   GstBuffer *cur;
       
   448 
       
   449   g_return_if_fail (GST_IS_ADAPTER (adapter));
       
   450   g_return_if_fail (flush <= adapter->size);
       
   451 
       
   452   GST_LOG_OBJECT (adapter, "flushing %u bytes", flush);
       
   453   adapter->size -= flush;
       
   454   adapter->assembled_len = 0;
       
   455   while (flush > 0) {
       
   456     cur = adapter->buflist->data;
       
   457     if (GST_BUFFER_SIZE (cur) <= flush + adapter->skip) {
       
   458       /* can skip whole buffer */
       
   459       flush -= GST_BUFFER_SIZE (cur) - adapter->skip;
       
   460       adapter->skip = 0;
       
   461       adapter->buflist =
       
   462           g_slist_delete_link (adapter->buflist, adapter->buflist);
       
   463       if (G_UNLIKELY (adapter->buflist == NULL))
       
   464         adapter->buflist_end = NULL;
       
   465       gst_buffer_unref (cur);
       
   466     } else {
       
   467       adapter->skip += flush;
       
   468       break;
       
   469     }
       
   470   }
       
   471 }
       
   472 
       
   473 /**
       
   474  * gst_adapter_take:
       
   475  * @adapter: a #GstAdapter
       
   476  * @nbytes: the number of bytes to take
       
   477  *
       
   478  * Returns a freshly allocated buffer containing the first @nbytes bytes of the
       
   479  * @adapter. The returned bytes will be flushed from the adapter.
       
   480  *
       
   481  * Caller owns returned value. g_free after usage.
       
   482  *
       
   483  * Returns: oven-fresh hot data, or #NULL if @nbytes bytes are not available
       
   484  */
       
   485 #ifdef __SYMBIAN32__
       
   486 EXPORT_C
       
   487 #endif
       
   488 
       
   489 guint8 *
       
   490 gst_adapter_take (GstAdapter * adapter, guint nbytes)
       
   491 {
       
   492   guint8 *data;
       
   493 
       
   494   g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
       
   495   g_return_val_if_fail (nbytes > 0, NULL);
       
   496 
       
   497   /* we don't have enough data, return NULL. This is unlikely
       
   498    * as one usually does an _available() first instead of peeking a
       
   499    * random size. */
       
   500   if (G_UNLIKELY (nbytes > adapter->size))
       
   501     return NULL;
       
   502 
       
   503   data = g_malloc (nbytes);
       
   504 
       
   505   /* we have enough assembled data, copy from there */
       
   506   if (adapter->assembled_len >= nbytes) {
       
   507     GST_LOG_OBJECT (adapter, "taking %u bytes already assembled", nbytes);
       
   508     memcpy (data, adapter->assembled_data, nbytes);
       
   509   } else {
       
   510     GST_LOG_OBJECT (adapter, "taking %u bytes by collection", nbytes);
       
   511     gst_adapter_peek_into (adapter, data, nbytes);
       
   512   }
       
   513 
       
   514   gst_adapter_flush (adapter, nbytes);
       
   515 
       
   516   return data;
       
   517 }
       
   518 
       
   519 /**
       
   520  * gst_adapter_take_buffer:
       
   521  * @adapter: a #GstAdapter
       
   522  * @nbytes: the number of bytes to take
       
   523  *
       
   524  * Returns a #GstBuffer containing the first @nbytes bytes of the
       
   525  * @adapter. The returned bytes will be flushed from the adapter.
       
   526  * This function is potentially more performant than gst_adapter_take() 
       
   527  * since it can reuse the memory in pushed buffers by subbuffering
       
   528  * or merging.
       
   529  *
       
   530  * Caller owns returned value. gst_buffer_unref() after usage.
       
   531  *
       
   532  * Since: 0.10.6
       
   533  *
       
   534  * Returns: a #GstBuffer containing the first @nbytes of the adapter, 
       
   535  * or #NULL if @nbytes bytes are not available
       
   536  */
       
   537 #ifdef __SYMBIAN32__
       
   538 EXPORT_C
       
   539 #endif
       
   540 
       
   541 GstBuffer *
       
   542 gst_adapter_take_buffer (GstAdapter * adapter, guint nbytes)
       
   543 {
       
   544   GstBuffer *buffer;
       
   545   GstBuffer *cur;
       
   546 
       
   547   g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
       
   548   g_return_val_if_fail (nbytes > 0, NULL);
       
   549 
       
   550   GST_LOG_OBJECT (adapter, "taking buffer of %u bytes", nbytes);
       
   551 
       
   552   /* we don't have enough data, return NULL. This is unlikely
       
   553    * as one usually does an _available() first instead of grabbing a
       
   554    * random size. */
       
   555   if (G_UNLIKELY (nbytes > adapter->size))
       
   556     return NULL;
       
   557 
       
   558   /* our head buffer has enough data left, return it */
       
   559   cur = adapter->buflist->data;
       
   560   if (GST_BUFFER_SIZE (cur) >= nbytes + adapter->skip) {
       
   561     GST_LOG_OBJECT (adapter, "providing buffer of %d bytes via sub-buffer",
       
   562         nbytes);
       
   563     buffer = gst_buffer_create_sub (cur, adapter->skip, nbytes);
       
   564 
       
   565     gst_adapter_flush (adapter, nbytes);
       
   566 
       
   567     return buffer;
       
   568   }
       
   569 
       
   570   if (gst_adapter_try_to_merge_up (adapter, nbytes)) {
       
   571     /* Merged something, let's try again for sub-buffering */
       
   572     cur = adapter->buflist->data;
       
   573     if (GST_BUFFER_SIZE (cur) >= nbytes + adapter->skip) {
       
   574       GST_LOG_OBJECT (adapter, "providing buffer of %d bytes via sub-buffer",
       
   575           nbytes);
       
   576       buffer = gst_buffer_create_sub (cur, adapter->skip, nbytes);
       
   577 
       
   578       gst_adapter_flush (adapter, nbytes);
       
   579 
       
   580       return buffer;
       
   581     }
       
   582   }
       
   583 
       
   584   buffer = gst_buffer_new_and_alloc (nbytes);
       
   585 
       
   586   /* we have enough assembled data, copy from there */
       
   587   if (adapter->assembled_len >= nbytes) {
       
   588     GST_LOG_OBJECT (adapter, "taking %u bytes already assembled", nbytes);
       
   589     memcpy (GST_BUFFER_DATA (buffer), adapter->assembled_data, nbytes);
       
   590   } else {
       
   591     GST_LOG_OBJECT (adapter, "taking %u bytes by collection", nbytes);
       
   592     gst_adapter_peek_into (adapter, GST_BUFFER_DATA (buffer), nbytes);
       
   593   }
       
   594 
       
   595   gst_adapter_flush (adapter, nbytes);
       
   596 
       
   597   return buffer;
       
   598 }
       
   599 
       
   600 /**
       
   601  * gst_adapter_available:
       
   602  * @adapter: a #GstAdapter
       
   603  *
       
   604  * Gets the maximum amount of bytes available, that is it returns the maximum
       
   605  * value that can be supplied to gst_adapter_peek() without that function
       
   606  * returning NULL.
       
   607  *
       
   608  * Returns: number of bytes available in @adapter
       
   609  */
       
   610 #ifdef __SYMBIAN32__
       
   611 EXPORT_C
       
   612 #endif
       
   613 
       
   614 guint
       
   615 gst_adapter_available (GstAdapter * adapter)
       
   616 {
       
   617   g_return_val_if_fail (GST_IS_ADAPTER (adapter), 0);
       
   618 
       
   619   return adapter->size;
       
   620 }
       
   621 
       
   622 /**
       
   623  * gst_adapter_available_fast:
       
   624  * @adapter: a #GstAdapter
       
   625  *
       
   626  * Gets the maximum number of bytes that are immediately available without
       
   627  * requiring any expensive operations (like copying the data into a 
       
   628  * temporary buffer).
       
   629  *
       
   630  * Returns: number of bytes that are available in @adapter without expensive 
       
   631  * operations
       
   632  */
       
   633 #ifdef __SYMBIAN32__
       
   634 EXPORT_C
       
   635 #endif
       
   636 
       
   637 guint
       
   638 gst_adapter_available_fast (GstAdapter * adapter)
       
   639 {
       
   640   g_return_val_if_fail (GST_IS_ADAPTER (adapter), 0);
       
   641 
       
   642   /* no buffers, we have no data */
       
   643   if (!adapter->buflist)
       
   644     return 0;
       
   645 
       
   646   /* some stuff we already assembled */
       
   647   if (adapter->assembled_len)
       
   648     return adapter->assembled_len;
       
   649 
       
   650   /* we cannot have skipped more than the first buffer */
       
   651   g_assert (GST_BUFFER_SIZE (adapter->buflist->data) > adapter->skip);
       
   652 
       
   653   /* we can quickly get the data of the first buffer */
       
   654   return GST_BUFFER_SIZE (adapter->buflist->data) - adapter->skip;
       
   655 }