gstreamer_core/gst/gstbufferlist.c
branchRCL_3
changeset 30 7e817e7e631c
parent 29 567bb019e3e3
equal deleted inserted replaced
29:567bb019e3e3 30:7e817e7e631c
     1 /* GStreamer
       
     2  * Copyright (C) 2009 Axis Communications <dev-gstreamer at axis dot com>
       
     3  * @author Jonas Holmberg <jonas dot holmberg at axis dot com>
       
     4  *
       
     5  * gstbufferlist.c: Buffer list
       
     6  *
       
     7  * This library is free software; you can redistribute it and/or
       
     8  * modify it under the terms of the GNU Library General Public
       
     9  * License as published by the Free Software Foundation; either
       
    10  * version 2 of the License, or (at your option) any later version.
       
    11  *
       
    12  * This library is distributed in the hope that it will be useful,
       
    13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    15  * Library General Public License for more details.
       
    16  *
       
    17  * You should have received a copy of the GNU Library General Public
       
    18  * License along with this library; if not, write to the
       
    19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    20  * Boston, MA 02111-1307, USA.
       
    21  */
       
    22 
       
    23 /**
       
    24  * SECTION:gstbufferlist
       
    25  * @short_description: Grouped scatter data buffer type for data-passing
       
    26  * @see_also: #GstPad, #GstMiniObject
       
    27  *
       
    28  * Buffer lists are units of grouped scatter/gather data transfer in
       
    29  * GStreamer.
       
    30  *
       
    31  * Buffer lists are created with gst_buffer_list_new() and filled with data
       
    32  * using a #GstBufferListIterator. The iterator has no current buffer; its
       
    33  * cursor position lies between buffers, immediately before the buffer that
       
    34  * would be returned by gst_buffer_list_iterator_next(). After iterating to the
       
    35  * end of a group the iterator must be advanced to the next group by a call to
       
    36  * gst_buffer_list_iterator_next_group() before any further calls to
       
    37  * gst_buffer_list_iterator_next() can return buffers again. The cursor position
       
    38  * of a newly created iterator lies before the first group; a call to
       
    39  * gst_buffer_list_iterator_next_group() is necessary before calls to
       
    40  * gst_buffer_list_iterator_next() can return buffers.
       
    41  *
       
    42  * <informalexample>
       
    43  *   <programlisting>
       
    44  *      +--- group0 ----------------------+--- group1 ------------+
       
    45  *      |   buffer0   buffer1   buffer2   |   buffer3   buffer4   |
       
    46  *    ^   ^         ^         ^         ^   ^         ^         ^
       
    47  *    Iterator positions
       
    48  *   </programlisting>
       
    49  * </informalexample>
       
    50  *
       
    51  * The gst_buffer_list_iterator_remove(), gst_buffer_list_iterator_steal(),
       
    52  * gst_buffer_list_iterator_take(), gst_buffer_list_iterator_do() and
       
    53  * gst_buffer_list_iterator_do_data() functions are not defined in terms of the
       
    54  * cursor position; they operate on the last element returned from
       
    55  * gst_buffer_list_iterator_next().
       
    56  *
       
    57  * The basic use pattern of creating a buffer list with an iterator is as
       
    58  * follows:
       
    59  *
       
    60  * <example>
       
    61  * <title>Creating a buffer list</title>
       
    62  *   <programlisting>
       
    63  *    GstBufferList *list;
       
    64  *    GstBufferListIterator *it;
       
    65  *
       
    66  *    list = gst_buffer_list_new ();
       
    67  *    it = gst_buffer_list_iterate (list);
       
    68  *    gst_buffer_list_iterator_add_group (it);
       
    69  *    gst_buffer_list_iterator_add (it, header1);
       
    70  *    gst_buffer_list_iterator_add (it, data1);
       
    71  *    gst_buffer_list_iterator_add_group (it);
       
    72  *    gst_buffer_list_iterator_add (it, header2);
       
    73  *    gst_buffer_list_iterator_add (it, data2);
       
    74  *    gst_buffer_list_iterator_add_group (it);
       
    75  *    gst_buffer_list_iterator_add (it, header3);
       
    76  *    gst_buffer_list_iterator_add (it, data3);
       
    77  *    ...
       
    78  *    gst_buffer_list_iterator_free (it);
       
    79  *   </programlisting>
       
    80  * </example>
       
    81  *
       
    82  * The basic use pattern of iterating over a buffer list is as follows:
       
    83  *
       
    84  * <example>
       
    85  * <title>Iterating a buffer list</title>
       
    86  *   <programlisting>
       
    87  *    GstBufferListIterator *it;
       
    88  *
       
    89  *    it = gst_buffer_list_iterate (list);
       
    90  *    while (gst_buffer_list_iterator_next_group (it)) {
       
    91  *      while ((buffer = gst_buffer_list_iterator_next (it)) != NULL) {
       
    92  *        do_something_with_buffer (buffer);
       
    93  *      }
       
    94  *    }
       
    95  *    gst_buffer_list_iterator_free (it);
       
    96  *   </programlisting>
       
    97  * </example>
       
    98  *
       
    99  * The basic use pattern of modifying a buffer in a list is as follows:
       
   100  *
       
   101  * <example>
       
   102  * <title>Modifying the data of the first buffer in a list</title>
       
   103  *   <programlisting>
       
   104  *    GstBufferListIterator *it;
       
   105  *
       
   106  *    list = gst_buffer_list_make_writable (list);
       
   107  *    it = gst_buffer_list_iterate (list);
       
   108  *    if (gst_buffer_list_iterator_next_group (it)) {
       
   109  *      GstBuffer *buf
       
   110  *
       
   111  *      buf = gst_buffer_list_iterator_next (it);
       
   112  *      if (buf != NULL) {
       
   113  *        buf = gst_buffer_list_iterator_do (it,
       
   114  *            (GstBufferListDoFunction) gst_mini_object_make_writable, NULL);
       
   115  *        modify_data (GST_BUFFER_DATA (buf));
       
   116  *      }
       
   117  *    }
       
   118  *    gst_buffer_list_iterator_free (it);
       
   119  *   </programlisting>
       
   120  * </example>
       
   121  *
       
   122  * Since: 0.10.24
       
   123  */
       
   124 #include "gst_private.h"
       
   125 
       
   126 #include "gstbuffer.h"
       
   127 #include "gstbufferlist.h"
       
   128 #ifdef __SYMBIAN32__
       
   129 #include <glib_global.h>
       
   130 #endif
       
   131 
       
   132 #define GST_CAT_DEFAULT GST_CAT_BUFFER_LIST
       
   133 
       
   134 #define GROUP_START NULL
       
   135 static const gpointer STOLEN = "";
       
   136 
       
   137 /**
       
   138  * GstBufferList:
       
   139  * @mini_object: the parent structure
       
   140  *
       
   141  * Opaque list of grouped buffers.
       
   142  */
       
   143 struct _GstBufferList
       
   144 {
       
   145   GstMiniObject mini_object;
       
   146 
       
   147   GList *buffers;
       
   148 };
       
   149 
       
   150 struct _GstBufferListClass
       
   151 {
       
   152   GstMiniObjectClass mini_object_class;
       
   153 };
       
   154 
       
   155 /**
       
   156  * GstBufferListIterator:
       
   157  *
       
   158  * Opaque iterator for a #GstBufferList.
       
   159  */
       
   160 struct _GstBufferListIterator
       
   161 {
       
   162   GstBufferList *list;
       
   163   GList *next;
       
   164   GList *last_returned;
       
   165 };
       
   166 
       
   167 static GType _gst_buffer_list_type = 0;
       
   168 static GstMiniObjectClass *parent_class = NULL;
       
   169 #ifdef __SYMBIAN32__
       
   170 EXPORT_C
       
   171 #endif
       
   172 
       
   173 
       
   174 void
       
   175 _gst_buffer_list_initialize (void)
       
   176 {
       
   177   g_type_class_ref (gst_buffer_list_get_type ());
       
   178 }
       
   179 
       
   180 static void
       
   181 gst_buffer_list_init (GTypeInstance * instance, gpointer g_class)
       
   182 {
       
   183   GstBufferList *list;
       
   184 
       
   185   list = (GstBufferList *) instance;
       
   186   list->buffers = NULL;
       
   187 
       
   188   GST_LOG ("init %p", list);
       
   189 }
       
   190 
       
   191 static void
       
   192 gst_buffer_list_finalize (GstBufferList * list)
       
   193 {
       
   194   GList *tmp;
       
   195 
       
   196   g_return_if_fail (list != NULL);
       
   197 
       
   198   GST_LOG ("finalize %p", list);
       
   199 
       
   200   tmp = list->buffers;
       
   201   while (tmp) {
       
   202     if (tmp->data != GROUP_START && tmp->data != STOLEN) {
       
   203       gst_buffer_unref (GST_BUFFER_CAST (tmp->data));
       
   204     }
       
   205     tmp = tmp->next;
       
   206   }
       
   207   g_list_free (list->buffers);
       
   208 
       
   209   parent_class->finalize (GST_MINI_OBJECT_CAST (list));
       
   210 }
       
   211 
       
   212 static GstBufferList *
       
   213 _gst_buffer_list_copy (GstBufferList * list)
       
   214 {
       
   215   GstBufferList *list_copy;
       
   216   GList *tmp;
       
   217 
       
   218   g_return_val_if_fail (list != NULL, NULL);
       
   219 
       
   220   list_copy = gst_buffer_list_new ();
       
   221 
       
   222   /* shallow copy of list and pointers */
       
   223   list_copy->buffers = g_list_copy (list->buffers);
       
   224 
       
   225   /* ref all buffers in the list */
       
   226   tmp = list_copy->buffers;
       
   227   while (tmp) {
       
   228     if (tmp->data != GROUP_START && tmp->data != STOLEN) {
       
   229       tmp->data = gst_buffer_ref (GST_BUFFER_CAST (tmp->data));
       
   230     }
       
   231     tmp = g_list_next (tmp);
       
   232   }
       
   233 
       
   234   return list_copy;
       
   235 }
       
   236 
       
   237 static void
       
   238 gst_buffer_list_class_init (gpointer g_class, gpointer class_data)
       
   239 {
       
   240   GstBufferListClass *list_class = GST_BUFFER_LIST_CLASS (g_class);
       
   241 
       
   242   parent_class = g_type_class_peek_parent (g_class);
       
   243 
       
   244   list_class->mini_object_class.copy =
       
   245       (GstMiniObjectCopyFunction) _gst_buffer_list_copy;
       
   246   list_class->mini_object_class.finalize =
       
   247       (GstMiniObjectFinalizeFunction) gst_buffer_list_finalize;
       
   248 }
       
   249 
       
   250 /**
       
   251  * gst_buffer_list_new:
       
   252  *
       
   253  * Creates a new, empty #GstBufferList. The caller is responsible for unreffing
       
   254  * the returned #GstBufferList.
       
   255  *
       
   256  * Returns: the new #GstBufferList. gst_buffer_list_unref() after usage.
       
   257  */
       
   258 #ifdef __SYMBIAN32__
       
   259 EXPORT_C
       
   260 #endif
       
   261 
       
   262 GstBufferList *
       
   263 gst_buffer_list_new (void)
       
   264 {
       
   265   GstBufferList *list;
       
   266 
       
   267   list = (GstBufferList *) gst_mini_object_new (_gst_buffer_list_type);
       
   268 
       
   269   GST_LOG ("new %p", list);
       
   270 
       
   271   return list;
       
   272 }
       
   273 
       
   274 /**
       
   275  * gst_buffer_list_n_groups:
       
   276  * @list: a #GstBufferList
       
   277  *
       
   278  * Returns the number of groups in @list.
       
   279  *
       
   280  * Returns: the number of groups in the buffer list
       
   281  */
       
   282 #ifdef __SYMBIAN32__
       
   283 EXPORT_C
       
   284 #endif
       
   285 
       
   286 guint
       
   287 gst_buffer_list_n_groups (GstBufferList * list)
       
   288 {
       
   289   GList *tmp;
       
   290   guint n;
       
   291 
       
   292   g_return_val_if_fail (list != NULL, 0);
       
   293 
       
   294   tmp = list->buffers;
       
   295   n = 0;
       
   296   while (tmp) {
       
   297     if (tmp->data == GROUP_START) {
       
   298       n++;
       
   299     }
       
   300     tmp = g_list_next (tmp);
       
   301   }
       
   302 
       
   303   return n;
       
   304 }
       
   305 
       
   306 /**
       
   307  * gst_buffer_list_foreach:
       
   308  * @list: a #GstBufferList
       
   309  * @func: a #GstBufferListFunc to call
       
   310  * @user_data: user data passed to @func
       
   311  *
       
   312  * Call @func with @data for each buffer in @list.
       
   313  *
       
   314  * @func can modify the passed buffer pointer or its contents. The return value
       
   315  * of @func define if this function returns or if the remaining buffers in a
       
   316  * group should be skipped.
       
   317  */
       
   318 #ifdef __SYMBIAN32__
       
   319 EXPORT_C
       
   320 #endif
       
   321 
       
   322 void
       
   323 gst_buffer_list_foreach (GstBufferList * list, GstBufferListFunc func,
       
   324     gpointer user_data)
       
   325 {
       
   326   GList *tmp, *next;
       
   327   guint group, idx;
       
   328   GstBufferListItem res;
       
   329 
       
   330   g_return_if_fail (list != NULL);
       
   331   g_return_if_fail (func != NULL);
       
   332 
       
   333   next = list->buffers;
       
   334   group = idx = 0;
       
   335   while (next) {
       
   336     GstBuffer *buffer;
       
   337 
       
   338     tmp = next;
       
   339     next = g_list_next (tmp);
       
   340 
       
   341     buffer = tmp->data;
       
   342 
       
   343     if (buffer == GROUP_START) {
       
   344       group++;
       
   345       idx = 0;
       
   346       continue;
       
   347     } else if (buffer == STOLEN)
       
   348       continue;
       
   349     else
       
   350       idx++;
       
   351 
       
   352     /* need to decrement the indices */
       
   353     res = func (&buffer, group - 1, idx - 1, user_data);
       
   354 
       
   355     if (G_UNLIKELY (buffer != tmp->data)) {
       
   356       /* the function changed the buffer */
       
   357       if (buffer == NULL) {
       
   358         /* we were asked to remove the item */
       
   359         list->buffers = g_list_delete_link (list->buffers, tmp);
       
   360         idx--;
       
   361       } else {
       
   362         /* change the buffer */
       
   363         tmp->data = buffer;
       
   364       }
       
   365     }
       
   366 
       
   367     switch (res) {
       
   368       case GST_BUFFER_LIST_CONTINUE:
       
   369         break;
       
   370       case GST_BUFFER_LIST_SKIP_GROUP:
       
   371         while (next && next->data != GROUP_START)
       
   372           next = g_list_next (next);
       
   373         break;
       
   374       case GST_BUFFER_LIST_END:
       
   375         return;
       
   376     }
       
   377   }
       
   378 }
       
   379 
       
   380 /**
       
   381  * gst_buffer_list_get:
       
   382  * @list: a #GstBufferList
       
   383  * @group: the group
       
   384  * @idx: the index in @group
       
   385  *
       
   386  * Get the buffer at @idx in @group.
       
   387  *
       
   388  * Note that this function is not efficient for iterating over the entire list.
       
   389  * Use an iterator or gst_buffer_list_foreach() instead.
       
   390  *
       
   391  * Returns: the buffer at @idx in @group or NULL when there is no buffer. The
       
   392  * buffer remains valid as long as @list is valid.
       
   393  */
       
   394 #ifdef __SYMBIAN32__
       
   395 EXPORT_C
       
   396 #endif
       
   397 
       
   398 GstBuffer *
       
   399 gst_buffer_list_get (GstBufferList * list, guint group, guint idx)
       
   400 {
       
   401   GList *tmp;
       
   402   guint cgroup, cidx;
       
   403 
       
   404   g_return_val_if_fail (list != NULL, NULL);
       
   405 
       
   406   tmp = list->buffers;
       
   407   cgroup = 0;
       
   408   while (tmp) {
       
   409     if (tmp->data == GROUP_START) {
       
   410       if (cgroup == group) {
       
   411         /* we found the group */
       
   412         tmp = g_list_next (tmp);
       
   413         cidx = 0;
       
   414         while (tmp && tmp->data != GROUP_START) {
       
   415           if (tmp->data != STOLEN) {
       
   416             if (cidx == idx)
       
   417               return GST_BUFFER_CAST (tmp->data);
       
   418             else
       
   419               cidx++;
       
   420           }
       
   421           tmp = g_list_next (tmp);
       
   422         }
       
   423         break;
       
   424       } else {
       
   425         cgroup++;
       
   426         if (cgroup > group)
       
   427           break;
       
   428       }
       
   429     }
       
   430     tmp = g_list_next (tmp);
       
   431   }
       
   432   return NULL;
       
   433 }
       
   434 #ifdef __SYMBIAN32__
       
   435 EXPORT_C
       
   436 #endif
       
   437 
       
   438 
       
   439 GType
       
   440 gst_buffer_list_get_type (void)
       
   441 {
       
   442   if (G_UNLIKELY (_gst_buffer_list_type == 0)) {
       
   443     static const GTypeInfo buffer_list_info = {
       
   444       sizeof (GstBufferListClass),
       
   445       NULL,
       
   446       NULL,
       
   447       gst_buffer_list_class_init,
       
   448       NULL,
       
   449       NULL,
       
   450       sizeof (GstBufferList),
       
   451       0,
       
   452       gst_buffer_list_init,
       
   453       NULL
       
   454     };
       
   455 
       
   456     _gst_buffer_list_type = g_type_register_static (GST_TYPE_MINI_OBJECT,
       
   457         "GstBufferList", &buffer_list_info, 0);
       
   458   }
       
   459 
       
   460   return _gst_buffer_list_type;
       
   461 }
       
   462 
       
   463 /**
       
   464  * gst_buffer_list_iterate:
       
   465  * @list: a #GstBufferList
       
   466  *
       
   467  * Iterate the buffers in @list. The owner of the iterator must also be the
       
   468  * owner of a reference to @list while the returned iterator is in use.
       
   469  *
       
   470  * Returns: a new #GstBufferListIterator of the buffers in @list.
       
   471  * gst_buffer_list_iterator_free() after usage
       
   472  */
       
   473 #ifdef __SYMBIAN32__
       
   474 EXPORT_C
       
   475 #endif
       
   476 
       
   477 GstBufferListIterator *
       
   478 gst_buffer_list_iterate (GstBufferList * list)
       
   479 {
       
   480   GstBufferListIterator *it;
       
   481 
       
   482   g_return_val_if_fail (list != NULL, NULL);
       
   483 
       
   484   it = g_slice_new (GstBufferListIterator);
       
   485   it->list = list;
       
   486   it->next = list->buffers;
       
   487   it->last_returned = NULL;
       
   488 
       
   489   return it;
       
   490 }
       
   491 
       
   492 /**
       
   493  * gst_buffer_list_iterator_free:
       
   494  * @it: the #GstBufferListIterator to free
       
   495  *
       
   496  * Free the iterator.
       
   497  */
       
   498 #ifdef __SYMBIAN32__
       
   499 EXPORT_C
       
   500 #endif
       
   501 
       
   502 void
       
   503 gst_buffer_list_iterator_free (GstBufferListIterator * it)
       
   504 {
       
   505   g_return_if_fail (it != NULL);
       
   506 
       
   507   g_slice_free (GstBufferListIterator, it);
       
   508 }
       
   509 
       
   510 /**
       
   511  * gst_buffer_list_iterator_n_buffers:
       
   512  * @it: a #GstBufferListIterator
       
   513  *
       
   514  * Returns the number of buffers left to iterate in the current group. I.e. the
       
   515  * number of calls that can be made to gst_buffer_list_iterator_next() before
       
   516  * it returns NULL.
       
   517  *
       
   518  * This function will not move the implicit cursor or in any other way affect
       
   519  * the state of the iterator @it.
       
   520  *
       
   521  * Returns: the number of buffers left to iterate in the current group
       
   522  */
       
   523 #ifdef __SYMBIAN32__
       
   524 EXPORT_C
       
   525 #endif
       
   526 
       
   527 guint
       
   528 gst_buffer_list_iterator_n_buffers (const GstBufferListIterator * it)
       
   529 {
       
   530   GList *tmp;
       
   531   guint n;
       
   532 
       
   533   g_return_val_if_fail (it != NULL, 0);
       
   534 
       
   535   tmp = it->next;
       
   536   n = 0;
       
   537   while (tmp && tmp->data != GROUP_START) {
       
   538     if (tmp->data != STOLEN) {
       
   539       n++;
       
   540     }
       
   541     tmp = g_list_next (tmp);
       
   542   }
       
   543 
       
   544   return n;
       
   545 }
       
   546 
       
   547 /**
       
   548  * gst_buffer_list_iterator_add:
       
   549  * @it: a #GstBufferListIterator
       
   550  * @buffer: a #GstBuffer
       
   551  *
       
   552  * Inserts @buffer into the #GstBufferList iterated with @it. The buffer is
       
   553  * inserted into the current group, immediately before the buffer that would be
       
   554  * returned by gst_buffer_list_iterator_next(). The buffer is inserted before
       
   555  * the implicit cursor, a subsequent call to gst_buffer_list_iterator_next()
       
   556  * will return the buffer after the inserted buffer, if any.
       
   557  *
       
   558  * This function takes ownership of @buffer.
       
   559  */
       
   560 #ifdef __SYMBIAN32__
       
   561 EXPORT_C
       
   562 #endif
       
   563 
       
   564 void
       
   565 gst_buffer_list_iterator_add (GstBufferListIterator * it, GstBuffer * buffer)
       
   566 {
       
   567   g_return_if_fail (it != NULL);
       
   568   g_return_if_fail (buffer != NULL);
       
   569 
       
   570   /* adding before the first group start is not allowed */
       
   571   g_return_if_fail (it->next != it->list->buffers);
       
   572 
       
   573   /* cheap insert into the GList */
       
   574   it->list->buffers = g_list_insert_before (it->list->buffers, it->next,
       
   575       buffer);
       
   576 }
       
   577 
       
   578 /**
       
   579  * gst_buffer_list_iterator_add_group:
       
   580  * @it: a #GstBufferListIterator
       
   581  *
       
   582  * Inserts a new, empty group into the #GstBufferList iterated with @it. The
       
   583  * group is inserted immediately before the group that would be returned by
       
   584  * gst_buffer_list_iterator_next_group(). A subsequent call to
       
   585  * gst_buffer_list_iterator_next_group() will advance the iterator to the group
       
   586  * after the inserted group, if any.
       
   587  */
       
   588 #ifdef __SYMBIAN32__
       
   589 EXPORT_C
       
   590 #endif
       
   591 
       
   592 void
       
   593 gst_buffer_list_iterator_add_group (GstBufferListIterator * it)
       
   594 {
       
   595   g_return_if_fail (it != NULL);
       
   596 
       
   597   /* advance iterator to next group start */
       
   598   while (it->next != NULL && it->next->data != GROUP_START) {
       
   599     it->next = g_list_next (it->next);
       
   600   }
       
   601 
       
   602   /* cheap insert of a group start into the GList */
       
   603   it->list->buffers = g_list_insert_before (it->list->buffers, it->next,
       
   604       GROUP_START);
       
   605 }
       
   606 
       
   607 /**
       
   608  * gst_buffer_list_iterator_next:
       
   609  * @it: a #GstBufferListIterator
       
   610  *
       
   611  * Returns the next buffer in the list iterated with @it. If the iterator is at
       
   612  * the end of a group, NULL will be returned. This function may be called
       
   613  * repeatedly to iterate through the current group.
       
   614  *
       
   615  * The caller will not get a new ref to the returned #GstBuffer and must not
       
   616  * unref it.
       
   617  *
       
   618  * Returns: the next buffer in the current group of the buffer list, or NULL
       
   619  */
       
   620 #ifdef __SYMBIAN32__
       
   621 EXPORT_C
       
   622 #endif
       
   623 
       
   624 GstBuffer *
       
   625 gst_buffer_list_iterator_next (GstBufferListIterator * it)
       
   626 {
       
   627   GstBuffer *buffer;
       
   628 
       
   629   g_return_val_if_fail (it != NULL, NULL);
       
   630 
       
   631   while (it->next != NULL && it->next->data != GROUP_START &&
       
   632       it->next->data == STOLEN) {
       
   633     it->next = g_list_next (it->next);
       
   634   }
       
   635 
       
   636   if (it->next == NULL || it->next->data == GROUP_START) {
       
   637     goto no_buffer;
       
   638   }
       
   639 
       
   640   buffer = GST_BUFFER_CAST (it->next->data);
       
   641 
       
   642   it->last_returned = it->next;
       
   643   it->next = g_list_next (it->next);
       
   644 
       
   645   return buffer;
       
   646 
       
   647 no_buffer:
       
   648   {
       
   649     it->last_returned = NULL;
       
   650     return NULL;
       
   651   }
       
   652 }
       
   653 
       
   654 /**
       
   655  * gst_buffer_list_iterator_next_group:
       
   656  * @it: a #GstBufferListIterator
       
   657  *
       
   658  * Advance the iterator @it to the first buffer in the next group. If the
       
   659  * iterator is at the last group, FALSE will be returned. This function may be
       
   660  * called repeatedly to iterate through the groups in a buffer list.
       
   661  *
       
   662  * Returns: TRUE if the iterator could be advanced to the next group, FALSE if
       
   663  * the iterator was already at the last group
       
   664  */
       
   665 #ifdef __SYMBIAN32__
       
   666 EXPORT_C
       
   667 #endif
       
   668 
       
   669 gboolean
       
   670 gst_buffer_list_iterator_next_group (GstBufferListIterator * it)
       
   671 {
       
   672   g_return_val_if_fail (it != NULL, FALSE);
       
   673 
       
   674   /* advance iterator to next group start */
       
   675   while (it->next != NULL && it->next->data != GROUP_START) {
       
   676     it->next = g_list_next (it->next);
       
   677   }
       
   678 
       
   679   if (it->next) {
       
   680     /* move one step beyond the group start */
       
   681     it->next = g_list_next (it->next);
       
   682   }
       
   683 
       
   684   it->last_returned = NULL;
       
   685 
       
   686   return (it->next != NULL);
       
   687 }
       
   688 
       
   689 /**
       
   690  * gst_buffer_list_iterator_remove:
       
   691  * @it: a #GstBufferListIterator
       
   692  *
       
   693  * Removes the last buffer returned by gst_buffer_list_iterator_next() from
       
   694  * the #GstBufferList iterated with @it. gst_buffer_list_iterator_next() must
       
   695  * have been called on @it before this function is called. This function can
       
   696  * only be called once per call to gst_buffer_list_iterator_next().
       
   697  *
       
   698  * The removed buffer is unreffed.
       
   699  */
       
   700 #ifdef __SYMBIAN32__
       
   701 EXPORT_C
       
   702 #endif
       
   703 
       
   704 void
       
   705 gst_buffer_list_iterator_remove (GstBufferListIterator * it)
       
   706 {
       
   707   g_return_if_fail (it != NULL);
       
   708   g_return_if_fail (it->last_returned != NULL);
       
   709   g_assert (it->last_returned->data != GROUP_START);
       
   710 
       
   711   if (it->last_returned->data != STOLEN) {
       
   712     gst_buffer_unref (it->last_returned->data);
       
   713   }
       
   714   it->list->buffers = g_list_delete_link (it->list->buffers, it->last_returned);
       
   715   it->last_returned = NULL;
       
   716 }
       
   717 
       
   718 /**
       
   719  * gst_buffer_list_iterator_take:
       
   720  * @it: a #GstBufferListIterator
       
   721  * @buffer: a #GstBuffer
       
   722  *
       
   723  * Replaces the last buffer returned by gst_buffer_list_iterator_next() with
       
   724  * @buffer in the #GstBufferList iterated with @it and takes ownership of
       
   725  * @buffer. gst_buffer_list_iterator_next() must have been called on @it before
       
   726  * this function is called. gst_buffer_list_iterator_remove() must not have been
       
   727  * called since the last call to gst_buffer_list_iterator_next().
       
   728  *
       
   729  * This function unrefs the replaced buffer if it has not been stolen with
       
   730  * gst_buffer_list_iterator_steal() and takes ownership of @buffer (i.e. the
       
   731  * refcount of @buffer is not increased).
       
   732  */
       
   733 #ifdef __SYMBIAN32__
       
   734 EXPORT_C
       
   735 #endif
       
   736 
       
   737 void
       
   738 gst_buffer_list_iterator_take (GstBufferListIterator * it, GstBuffer * buffer)
       
   739 {
       
   740   g_return_if_fail (it != NULL);
       
   741   g_return_if_fail (it->last_returned != NULL);
       
   742   g_return_if_fail (buffer != NULL);
       
   743   g_assert (it->last_returned->data != GROUP_START);
       
   744 
       
   745   if (it->last_returned->data != STOLEN) {
       
   746     gst_buffer_unref (it->last_returned->data);
       
   747   }
       
   748   it->last_returned->data = buffer;
       
   749 }
       
   750 
       
   751 /**
       
   752  * gst_buffer_list_iterator_steal:
       
   753  * @it: a #GstBufferListIterator
       
   754  *
       
   755  * Returns the last buffer returned by gst_buffer_list_iterator_next() without
       
   756  * modifying the refcount of the buffer.
       
   757  *
       
   758  * Returns: the last buffer returned by gst_buffer_list_iterator_next()
       
   759  */
       
   760 #ifdef __SYMBIAN32__
       
   761 EXPORT_C
       
   762 #endif
       
   763 
       
   764 GstBuffer *
       
   765 gst_buffer_list_iterator_steal (GstBufferListIterator * it)
       
   766 {
       
   767   GstBuffer *buffer;
       
   768 
       
   769   g_return_val_if_fail (it != NULL, NULL);
       
   770   g_return_val_if_fail (it->last_returned != NULL, NULL);
       
   771   g_return_val_if_fail (it->last_returned->data != STOLEN, NULL);
       
   772   g_assert (it->last_returned->data != GROUP_START);
       
   773 
       
   774   buffer = it->last_returned->data;
       
   775   it->last_returned->data = STOLEN;
       
   776 
       
   777   return buffer;
       
   778 }
       
   779 
       
   780 /**
       
   781  * gst_buffer_list_iterator_do:
       
   782  * @it: a #GstBufferListIterator
       
   783  * @do_func: the function to be called
       
   784  * @user_data: the gpointer to optional user data.
       
   785  *
       
   786  * Calls the given function for the last buffer returned by
       
   787  * gst_buffer_list_iterator_next(). gst_buffer_list_iterator_next() must have
       
   788  * been called on @it before this function is called.
       
   789  * gst_buffer_list_iterator_remove() and gst_buffer_list_iterator_steal() must
       
   790  * not have been called since the last call to gst_buffer_list_iterator_next().
       
   791  *
       
   792  * See #GstBufferListDoFunction for more details.
       
   793  *
       
   794  * Returns: the return value from @do_func
       
   795  */
       
   796 #ifdef __SYMBIAN32__
       
   797 EXPORT_C
       
   798 #endif
       
   799 
       
   800 GstBuffer *
       
   801 gst_buffer_list_iterator_do (GstBufferListIterator * it,
       
   802     GstBufferListDoFunction do_func, gpointer user_data)
       
   803 {
       
   804   GstBuffer *buffer;
       
   805 
       
   806   g_return_val_if_fail (it != NULL, NULL);
       
   807   g_return_val_if_fail (it->last_returned != NULL, NULL);
       
   808   g_return_val_if_fail (it->last_returned->data != STOLEN, NULL);
       
   809   g_return_val_if_fail (do_func != NULL, NULL);
       
   810   g_return_val_if_fail (gst_buffer_list_is_writable (it->list), NULL);
       
   811   g_assert (it->last_returned->data != GROUP_START);
       
   812 
       
   813   buffer = gst_buffer_list_iterator_steal (it);
       
   814   buffer = do_func (buffer, user_data);
       
   815   if (buffer == NULL) {
       
   816     gst_buffer_list_iterator_remove (it);
       
   817   } else {
       
   818     gst_buffer_list_iterator_take (it, buffer);
       
   819   }
       
   820 
       
   821   return buffer;
       
   822 }
       
   823 
       
   824 /**
       
   825  * gst_buffer_list_iterator_merge_group:
       
   826  * @it: a #GstBufferListIterator
       
   827  *
       
   828  * Merge a buffer list group into a normal #GstBuffer by copying its metadata
       
   829  * and memcpying its data into consecutive memory. All buffers in the current
       
   830  * group after the implicit cursor will be merged into one new buffer. The
       
   831  * metadata of the new buffer will be a copy of the metadata of the buffer that
       
   832  * would be returned by gst_buffer_list_iterator_next(). If there is no buffer
       
   833  * in the current group after the implicit cursor, NULL will be returned.
       
   834  *
       
   835  * This function will not move the implicit cursor or in any other way affect
       
   836  * the state of the iterator @it or the list.
       
   837  *
       
   838  * Returns: a new #GstBuffer, gst_buffer_unref() after usage, or NULL
       
   839  */
       
   840 #ifdef __SYMBIAN32__
       
   841 EXPORT_C
       
   842 #endif
       
   843 
       
   844 GstBuffer *
       
   845 gst_buffer_list_iterator_merge_group (const GstBufferListIterator * it)
       
   846 {
       
   847   GList *tmp;
       
   848   guint size;
       
   849   GstBuffer *buf;
       
   850   guint8 *ptr;
       
   851 
       
   852   g_return_val_if_fail (it != NULL, NULL);
       
   853 
       
   854   /* calculate size of merged buffer */
       
   855   size = 0;
       
   856   tmp = it->next;
       
   857   while (tmp && tmp->data != GROUP_START) {
       
   858     if (tmp->data != STOLEN) {
       
   859       size += GST_BUFFER_SIZE (tmp->data);
       
   860     }
       
   861     tmp = g_list_next (tmp);
       
   862   }
       
   863 
       
   864   if (size == 0) {
       
   865     return NULL;
       
   866   }
       
   867 
       
   868   /* allocate a new buffer */
       
   869   buf = gst_buffer_new_and_alloc (size);
       
   870 
       
   871   /* copy metadata from the next buffer after the implicit cursor */
       
   872   gst_buffer_copy_metadata (buf, GST_BUFFER_CAST (it->next->data),
       
   873       GST_BUFFER_COPY_ALL);
       
   874 
       
   875   /* copy data of all buffers before the next group start into the new buffer */
       
   876   ptr = GST_BUFFER_DATA (buf);
       
   877   tmp = it->next;
       
   878   do {
       
   879     if (tmp->data != STOLEN) {
       
   880       memcpy (ptr, GST_BUFFER_DATA (tmp->data), GST_BUFFER_SIZE (tmp->data));
       
   881       ptr += GST_BUFFER_SIZE (tmp->data);
       
   882     }
       
   883     tmp = g_list_next (tmp);
       
   884   } while (tmp && tmp->data != GROUP_START);
       
   885 
       
   886   return buf;
       
   887 }