bufferlist: Various cleanups
authorWim Taymans <wim.taymans@collabora.co.uk>
Fri, 19 Jun 2009 13:29:14 +0000 (15:29 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Fri, 19 Jun 2009 13:31:53 +0000 (15:31 +0200)
Add new method to iterate a bufferlist without having to allocate an iterator.
Add convenience method for getting an item from the list based on the group and
index.
Remove redundant _do_data callback and method.
Update unit-tests and add some more for the new methods.

docs/gst/gstreamer-sections.txt
gst/gstbufferlist.c
gst/gstbufferlist.h
tests/check/gst/gstbufferlist.c
win32/common/libgstreamer.def

index a4de092..8c3e8e4 100644 (file)
@@ -215,14 +215,21 @@ gst_buffer_copy_flags_get_type
 GstBufferList
 GstBufferListIterator
 GstBufferListDoFunction
-GstBufferListDoDataFunction
+
 gst_buffer_list_new
 gst_buffer_list_ref
 gst_buffer_list_unref
 gst_buffer_list_copy
 gst_buffer_list_is_writable
 gst_buffer_list_make_writable
+
 gst_buffer_list_n_groups
+
+GstBufferListItem
+GstBufferListFunc
+gst_buffer_list_foreach
+gst_buffer_list_get
+
 gst_buffer_list_iterate
 gst_buffer_list_iterator_free
 gst_buffer_list_iterator_n_buffers
@@ -234,7 +241,6 @@ gst_buffer_list_iterator_remove
 gst_buffer_list_iterator_steal
 gst_buffer_list_iterator_take
 gst_buffer_list_iterator_do
-gst_buffer_list_iterator_do_data
 gst_buffer_list_iterator_merge_group
 <SUBSECTION Standard>
 GstBufferListClass
@@ -245,7 +251,9 @@ GST_IS_BUFFER_LIST
 GST_IS_BUFFER_LIST_CLASS
 GST_TYPE_BUFFER_LIST
 GST_BUFFER_LIST_CAST
+GST_TYPE_BUFFER_LIST_ITEM
 <SUBSECTION Private>
+gst_buffer_list_item_get_type
 gst_buffer_list_get_type
 </SECTION>
 
index 02863ee..20a2ef8 100644 (file)
@@ -289,6 +289,127 @@ gst_buffer_list_n_groups (GstBufferList * list)
   return n;
 }
 
+/**
+ * gst_buffer_list_foreach:
+ * @list: a #GstBufferList
+ * @func: a #GstBufferListFunc to call
+ * @user_data: user data passed to @func
+ *
+ * Call @func with @data for each buffer in @list.
+ *
+ * @func can modify the passed buffer pointer or its contents. The return value
+ * of @func define if this function returns or if the remaining buffers in a
+ * group should be skipped.
+ */
+void
+gst_buffer_list_foreach (GstBufferList * list, GstBufferListFunc func,
+    gpointer user_data)
+{
+  GList *tmp, *next;
+  guint group, idx;
+  GstBufferListItem res;
+
+  g_return_if_fail (list != NULL);
+  g_return_if_fail (func != NULL);
+
+  next = list->buffers;
+  group = idx = 0;
+  while (next) {
+    GstBuffer *buffer;
+
+    tmp = next;
+    next = g_list_next (tmp);
+
+    buffer = tmp->data;
+
+    if (buffer == GROUP_START) {
+      group++;
+      idx = 0;
+      continue;
+    } else if (buffer == STOLEN)
+      continue;
+    else
+      idx++;
+
+    /* need to decrement the indices */
+    res = func (&buffer, group - 1, idx - 1, user_data);
+
+    if (G_UNLIKELY (buffer != tmp->data)) {
+      /* the function changed the buffer */
+      if (buffer == NULL) {
+        /* we were asked to remove the item */
+        list->buffers = g_list_delete_link (list->buffers, tmp);
+        idx--;
+      } else {
+        /* change the buffer */
+        tmp->data = buffer;
+      }
+    }
+
+    switch (res) {
+      case GST_BUFFER_LIST_CONTINUE:
+        break;
+      case GST_BUFFER_LIST_SKIP_GROUP:
+        while (next && next->data != GROUP_START)
+          next = g_list_next (next);
+        break;
+      case GST_BUFFER_LIST_END:
+        return;
+    }
+  }
+}
+
+/**
+ * gst_buffer_list_get:
+ * @list: a #GstBufferList
+ * @group: the group
+ * @idx: the index in @group
+ *
+ * Get the buffer at @idx in @group.
+ *
+ * Note that this function is not efficient for iterating over the entire list.
+ * Use and iterator or gst_buffer_list_foreach() instead.
+ *
+ * Returns: the buffer at @idx in @group or NULL when there is no buffer. The
+ * buffer remaing valid as long as @list is valid.
+ */
+GstBuffer *
+gst_buffer_list_get (GstBufferList * list, guint group, guint idx)
+{
+  GList *tmp;
+  guint cgroup, cidx;
+
+  g_return_val_if_fail (list != NULL, NULL);
+
+  tmp = list->buffers;
+  cgroup = 0;
+  while (tmp) {
+    if (tmp->data == GROUP_START) {
+      if (cgroup == group) {
+        /* we found the group */
+        tmp = g_list_next (tmp);
+        cidx = 0;
+        while (tmp && tmp->data != GROUP_START) {
+          if (tmp->data != STOLEN) {
+            if (cidx == idx)
+              return GST_BUFFER_CAST (tmp->data);
+            else
+              cidx++;
+          }
+          tmp = g_list_next (tmp);
+        }
+        break;
+      } else {
+        cgroup++;
+        if (cgroup > group)
+          break;
+      }
+    }
+    tmp = g_list_next (tmp);
+  }
+  return NULL;
+}
+
 GType
 gst_buffer_list_get_type (void)
 {
@@ -474,9 +595,10 @@ gst_buffer_list_iterator_next (GstBufferListIterator * it)
   return buffer;
 
 no_buffer:
-  it->last_returned = NULL;
-
-  return NULL;
+  {
+    it->last_returned = NULL;
+    return NULL;
+  }
 }
 
 /**
@@ -590,11 +712,10 @@ gst_buffer_list_iterator_steal (GstBufferListIterator * it)
 }
 
 /**
- * gst_buffer_list_iterator_do_data:
+ * gst_buffer_list_iterator_do:
  * @it: a #GstBufferListIterator
  * @do_func: the function to be called
- * @data: the gpointer to optional user data.
- * @data_notify: function to be called when @data is no longer used
+ * @user_data: the gpointer to optional user data.
  *
  * Calls the given function for the last buffer returned by
  * gst_buffer_list_iterator_next(). gst_buffer_list_iterator_next() must have
@@ -604,15 +725,11 @@ gst_buffer_list_iterator_steal (GstBufferListIterator * it)
  *
  * See #GstBufferListDoFunction for more details.
  *
- * The @data_notify function is called after @do_func has returned, before this
- * function returns, usually used to free @data.
- *
  * Returns: the return value from @do_func
  */
 GstBuffer *
-gst_buffer_list_iterator_do_data (GstBufferListIterator * it,
-    GstBufferListDoDataFunction do_func, gpointer data,
-    GDestroyNotify data_notify)
+gst_buffer_list_iterator_do (GstBufferListIterator * it,
+    GstBufferListDoFunction do_func, gpointer user_data)
 {
   GstBuffer *buffer;
 
@@ -624,56 +741,16 @@ gst_buffer_list_iterator_do_data (GstBufferListIterator * it,
   g_assert (it->last_returned->data != GROUP_START);
 
   buffer = gst_buffer_list_iterator_steal (it);
-  buffer = do_func (buffer, data);
+  buffer = do_func (buffer, user_data);
   if (buffer == NULL) {
     gst_buffer_list_iterator_remove (it);
   } else {
     gst_buffer_list_iterator_take (it, buffer);
   }
 
-  if (data_notify != NULL) {
-    data_notify (data);
-  }
-
   return buffer;
 }
 
-static GstBuffer *
-do_func_no_data (GstBuffer * buffer, GstBufferListDoFunction do_func)
-{
-  return do_func (buffer);
-}
-
-/**
- * gst_buffer_list_iterator_do:
- * @it: a #GstBufferListIterator
- * @do_func: the function to be called
- *
- * Calls the given function for the last buffer returned by
- * gst_buffer_list_iterator_next(). gst_buffer_list_iterator_next() must have
- * been called on @it before this function is called.
- * gst_buffer_list_iterator_remove() or gst_buffer_list_iterator_steal() must
- * not have been called since the last call to gst_buffer_list_iterator_next().
- *
- * See #GstBufferListDoFunction for more details.
- *
- * Returns: the return value from @do_func
- */
-GstBuffer *
-gst_buffer_list_iterator_do (GstBufferListIterator * it,
-    GstBufferListDoFunction do_func)
-{
-  g_return_val_if_fail (it != NULL, NULL);
-  g_return_val_if_fail (it->last_returned != NULL, NULL);
-  g_return_val_if_fail (it->last_returned->data != STOLEN, NULL);
-  g_return_val_if_fail (do_func != NULL, NULL);
-  g_return_val_if_fail (gst_buffer_list_is_writable (it->list), NULL);
-  g_assert (it->last_returned->data != GROUP_START);
-
-  return gst_buffer_list_iterator_do_data (it,
-      (GstBufferListDoDataFunction) do_func_no_data, do_func, NULL);
-}
-
 /**
  * gst_buffer_list_iterator_merge_group:
  * @it: a #GstBufferListIterator
index 5e3385e..392b338 100644 (file)
@@ -42,6 +42,7 @@ typedef struct _GstBufferListIterator GstBufferListIterator;
 /**
  * GstBufferListDoFunction:
  * @buffer: the #GstBuffer
+ * @user_data: user data
  *
  * A function for accessing the last buffer returned by
  * gst_buffer_list_iterator_next(). The function can leave @buffer in the list,
@@ -58,29 +59,49 @@ typedef struct _GstBufferListIterator GstBufferListIterator;
  * Returns: the buffer to replace @buffer in the list, or NULL to remove @buffer
  * from the list
  */
-typedef GstBuffer* (*GstBufferListDoFunction) (GstBuffer * buffer);
+typedef GstBuffer* (*GstBufferListDoFunction) (GstBuffer * buffer, gpointer user_data);
 
 /**
- * GstBufferListDoDataFunction:
- * @buffer: the #GstBuffer
- * @data: the gpointer to optional user data.
- *
- * A function for accessing the last buffer returned by
- * gst_buffer_list_iterator_next(). The function can leave @buffer in the list,
- * replace @buffer in the list or remove @buffer from the list, depending on
- * the return value. If the function returns NULL, @buffer will be removed from
- * the list, otherwise @buffer will be replaced with the returned buffer.
- *
- * The last buffer returned by gst_buffer_list_iterator_next() will be replaced
- * with the buffer returned from the function. The function takes ownership of
- * @buffer and if a different value than @buffer is returned, @buffer must be
- * unreffed. If NULL is returned, the buffer will be removed from the list. The
- * list must be writable.
+ * GstBufferListItem:
+ * @GST_BUFFER_LIST_CONTINUE:   Retrieve next buffer
+ * @GST_BUFFER_LIST_SKIP_GROUP: Skip to next group
+ * @GST_BUFFER_LIST_REMOVE:     Remove the current buffer
+ * @GST_BUFFER_LIST_END:        End iteration
  *
- * Returns: the buffer to replace @buffer in the list, or NULL to remove @buffer
- * from the list
+ * The result of the #GstBufferListFunc.
  */
-typedef GstBuffer* (*GstBufferListDoDataFunction) (GstBuffer * buffer, gpointer data);
+typedef enum {
+  GST_BUFFER_LIST_CONTINUE,
+  GST_BUFFER_LIST_SKIP_GROUP,
+  GST_BUFFER_LIST_END
+} GstBufferListItem;
+
+/**
+ * GstBufferListFunc:
+ * @buffer: pointer the buffer
+ * @group: the group index of @buffer
+ * @idx: the index in @group of @buffer
+ * @user_data: user data passed to gst_buffer_list_foreach()
+ *
+ * A function that will be called from gst_buffer_list_foreach(). The @buffer
+ * field will point to a the reference of the buffer at @idx in @group.
+ *
+ * When this function returns #GST_BUFFER_LIST_CONTINUE, the next buffer will be
+ * returned. When #GST_BUFFER_LIST_SKIP_GROUP is returned, all remaining buffers
+ * in the current group will be skipped and the first buffer of the next group
+ * is returned (if any). When GST_BUFFER_LIST_END is returned,
+ * gst_buffer_list_foreach() will return.
+ *
+ * When @buffer is set to NULL, the item will be removed from the bufferlist.
+ * When @buffer has been made writable, the new buffer reference can be assigned
+ * to @buffer. This function is responsible for unreffing the old buffer when
+ * removing or modifying.
+ *
+ * Returns: a #GstBufferListItem
+ */
+typedef GstBufferListItem (*GstBufferListFunc)   (GstBuffer **buffer, guint group, guint idx,
+                                                  gpointer user_data);
+
 
 GType gst_buffer_list_get_type (void);
 
@@ -170,6 +191,11 @@ gst_buffer_list_copy (const GstBufferList * list)
 
 guint                    gst_buffer_list_n_groups              (GstBufferList *list);
 
+void                     gst_buffer_list_foreach               (GstBufferList *list,
+                                                                GstBufferListFunc func,
+                                                               gpointer user_data);
+GstBuffer *              gst_buffer_list_get                   (GstBufferList *list, guint group, guint idx);
+
 /* iterator */
 GstBufferListIterator *  gst_buffer_list_iterate               (GstBufferList *list);
 void                     gst_buffer_list_iterator_free         (GstBufferListIterator *it);
@@ -184,9 +210,8 @@ void                     gst_buffer_list_iterator_remove       (GstBufferListIte
 GstBuffer *              gst_buffer_list_iterator_steal        (GstBufferListIterator *it);
 void                     gst_buffer_list_iterator_take         (GstBufferListIterator *it, GstBuffer *buffer);
 
-GstBuffer *              gst_buffer_list_iterator_do           (GstBufferListIterator *it, GstBufferListDoFunction do_func);
-GstBuffer *              gst_buffer_list_iterator_do_data      (GstBufferListIterator *it, GstBufferListDoDataFunction do_func,
-                                                                gpointer data, GDestroyNotify data_notify);
+GstBuffer *              gst_buffer_list_iterator_do           (GstBufferListIterator *it, GstBufferListDoFunction do_func,
+                                                                gpointer user_data);
 
 /* conversion */
 GstBuffer *              gst_buffer_list_iterator_merge_group  (const GstBufferListIterator *it);
index 6372af2..395309f 100644 (file)
@@ -424,15 +424,6 @@ GST_END_TEST;
 static gpointer do_data_func_data;
 static gboolean notified;
 
-static void
-data_notify (gpointer data)
-{
-  fail_unless (data != NULL);
-  fail_unless (data == do_data_func_data);
-  fail_if (notified);
-  notified = TRUE;
-}
-
 static GstBuffer *
 do_data_func (GstBuffer * buffer, gpointer data)
 {
@@ -458,16 +449,12 @@ GST_START_TEST (test_do)
   gchar *data;
 
   /* error handling */
-  ASSERT_CRITICAL ((buf = gst_buffer_list_iterator_do (NULL, NULL)));
+  ASSERT_CRITICAL ((buf = gst_buffer_list_iterator_do (NULL, NULL, NULL)));
   fail_unless (buf == NULL);
-  ASSERT_CRITICAL ((buf = gst_buffer_list_iterator_do_data (NULL, NULL, NULL,
-              NULL)));
   fail_unless (buf == NULL);
   it = gst_buffer_list_iterate (list);
-  ASSERT_CRITICAL ((buf = gst_buffer_list_iterator_do (it, NULL)));
+  ASSERT_CRITICAL ((buf = gst_buffer_list_iterator_do (it, NULL, NULL)));
   fail_unless (buf == NULL);
-  ASSERT_CRITICAL ((buf = gst_buffer_list_iterator_do_data (it, NULL, NULL,
-              NULL)));
   fail_unless (buf == NULL);
 
   /* add buffers to the list */
@@ -481,28 +468,32 @@ GST_START_TEST (test_do)
   /* call do-function */
   it = gst_buffer_list_iterate (list);
   fail_unless (gst_buffer_list_iterator_next_group (it));
-  ASSERT_CRITICAL ((buf = gst_buffer_list_iterator_do (it, gst_buffer_ref)));
+  ASSERT_CRITICAL ((buf =
+          gst_buffer_list_iterator_do (it,
+              (GstBufferListDoFunction) gst_buffer_ref, NULL)));
   fail_unless (buf == NULL);
   data = "data";
-  ASSERT_CRITICAL ((buf = gst_buffer_list_iterator_do_data (it, do_data_func,
-              data, data_notify)));
+  ASSERT_CRITICAL ((buf = gst_buffer_list_iterator_do (it, do_data_func,
+              data)));
   fail_unless (buf == NULL);
   fail_unless (do_data_func_data != data);
   buf = gst_buffer_list_iterator_next (it);
   fail_unless (buf == buf1);
   ASSERT_BUFFER_REFCOUNT (buf1, "buf1", 2);
-  buf = gst_buffer_list_iterator_do (it, gst_buffer_ref);
+  buf =
+      gst_buffer_list_iterator_do (it, (GstBufferListDoFunction) gst_buffer_ref,
+      NULL);
   fail_unless (buf == buf1);
   ASSERT_BUFFER_REFCOUNT (buf1, "buf1", 3);
   gst_buffer_unref (buf);
-  buf = gst_buffer_list_iterator_do_data (it, do_data_func, data, data_notify);
+  buf = gst_buffer_list_iterator_do (it, do_data_func, data);
   fail_unless (buf == buf1);
   fail_unless (do_data_func_data == data);
 
   /* do-function that return a new buffer replaces the buffer in the list */
   ASSERT_BUFFER_REFCOUNT (buf1, "buf1", 2);
   buf = gst_buffer_list_iterator_do (it,
-      (GstBufferListDoFunction) gst_mini_object_make_writable);
+      (GstBufferListDoFunction) gst_mini_object_make_writable, NULL);
   fail_unless (buf != buf1);
   ASSERT_BUFFER_REFCOUNT (buf, "buf", 1);
   ASSERT_BUFFER_REFCOUNT (buf, "buf1", 1);
@@ -510,9 +501,12 @@ GST_START_TEST (test_do)
 
   /* do-function that return NULL removes the buffer from the list */
   ASSERT_BUFFER_REFCOUNT (buf1, "buf1", 2);
-  fail_unless (gst_buffer_list_iterator_do (it, do_func_null) == NULL);
+  fail_unless (gst_buffer_list_iterator_do (it,
+          (GstBufferListDoFunction) do_func_null, NULL) == NULL);
   ASSERT_BUFFER_REFCOUNT (buf1, "buf1", 1);
-  ASSERT_CRITICAL ((buf = gst_buffer_list_iterator_do (it, gst_buffer_ref)));
+  ASSERT_CRITICAL ((buf =
+          gst_buffer_list_iterator_do (it,
+              (GstBufferListDoFunction) gst_buffer_ref, NULL)));
   fail_unless (buf == NULL);
   fail_unless (gst_buffer_list_iterator_next (it) == NULL);
   gst_buffer_list_iterator_free (it);
@@ -645,6 +639,134 @@ GST_START_TEST (test_merge)
 
 GST_END_TEST;
 
+typedef struct
+{
+  GstBuffer *buf[3][3];
+  guint iter;
+} ForeachData;
+
+static GstBufferListItem
+foreach_func1 (GstBuffer ** buffer, guint group, guint idx, ForeachData * data)
+{
+  fail_unless (buffer != NULL);
+  fail_unless (*buffer == data->buf[group][idx]);
+
+  data->iter++;
+
+  return GST_BUFFER_LIST_CONTINUE;
+}
+
+static GstBufferListItem
+foreach_func2 (GstBuffer ** buffer, guint group, guint idx, ForeachData * data)
+{
+  fail_unless (idx == 0);
+  fail_unless (buffer != NULL);
+  fail_unless (*buffer == data->buf[group][idx]);
+
+  data->iter++;
+
+  return GST_BUFFER_LIST_SKIP_GROUP;
+}
+
+static GstBufferListItem
+foreach_func3 (GstBuffer ** buffer, guint group, guint idx, ForeachData * data)
+{
+  fail_unless (group == 0);
+  fail_unless (idx == 0);
+  fail_unless (buffer != NULL);
+  fail_unless (*buffer == data->buf[group][idx]);
+
+  data->iter++;
+
+  return GST_BUFFER_LIST_END;
+}
+
+static GstBufferListItem
+foreach_func4 (GstBuffer ** buffer, guint group, guint idx, ForeachData * data)
+{
+  fail_unless (idx == 0);
+  fail_unless (buffer != NULL);
+  fail_unless (*buffer == data->buf[group][idx]);
+
+  *buffer = NULL;
+  data->iter++;
+
+  return GST_BUFFER_LIST_SKIP_GROUP;
+}
+
+static GstBufferListItem
+foreach_func5 (GstBuffer ** buffer, guint group, guint idx, ForeachData * data)
+{
+  fail_unless (buffer != NULL);
+
+  data->iter++;
+
+  return GST_BUFFER_LIST_CONTINUE;
+}
+
+GST_START_TEST (test_foreach)
+{
+  GstBufferListIterator *it;
+  ForeachData data;
+
+  /* add buffers to the list */
+  it = gst_buffer_list_iterate (list);
+  gst_buffer_list_iterator_add_group (it);
+  data.buf[0][0] = gst_buffer_new ();
+  gst_buffer_list_iterator_add (it, data.buf[0][0]);
+  gst_buffer_list_iterator_add_group (it);
+  data.buf[1][0] = gst_buffer_new ();
+  gst_buffer_list_iterator_add (it, data.buf[1][0]);
+  data.buf[1][1] = gst_buffer_new ();
+  gst_buffer_list_iterator_add (it, data.buf[1][1]);
+  gst_buffer_list_iterator_free (it);
+  gst_buffer_list_iterator_add_group (it);
+
+  fail_unless (gst_buffer_list_get (list, 0, 0) == data.buf[0][0]);
+  fail_unless (gst_buffer_list_get (list, 0, 1) == NULL);
+  fail_unless (gst_buffer_list_get (list, 1, 0) == data.buf[1][0]);
+  fail_unless (gst_buffer_list_get (list, 1, 1) == data.buf[1][1]);
+  fail_unless (gst_buffer_list_get (list, 1, 2) == NULL);
+  fail_unless (gst_buffer_list_get (list, 2, 0) == NULL);
+  fail_unless (gst_buffer_list_get (list, 2, 1) == NULL);
+  fail_unless (gst_buffer_list_get (list, 3, 3) == NULL);
+
+  /* iterate everything */
+  data.iter = 0;
+  gst_buffer_list_foreach (list, (GstBufferListFunc) foreach_func1, &data);
+  fail_unless (data.iter == 3);
+
+  /* iterate only the first buffer of groups */
+  data.iter = 0;
+  gst_buffer_list_foreach (list, (GstBufferListFunc) foreach_func2, &data);
+  fail_unless (data.iter == 2);
+
+  /* iterate only the first buffer */
+  data.iter = 0;
+  gst_buffer_list_foreach (list, (GstBufferListFunc) foreach_func3, &data);
+  fail_unless (data.iter == 1);
+
+  /* remove the first buffer of each group */
+  data.iter = 0;
+  gst_buffer_list_foreach (list, (GstBufferListFunc) foreach_func4, &data);
+  fail_unless (data.iter == 2);
+
+  fail_unless (gst_buffer_list_get (list, 0, 0) == NULL);
+  fail_unless (gst_buffer_list_get (list, 0, 1) == NULL);
+  fail_unless (gst_buffer_list_get (list, 1, 0) == data.buf[1][1]);
+  fail_unless (gst_buffer_list_get (list, 1, 1) == NULL);
+  fail_unless (gst_buffer_list_get (list, 1, 2) == NULL);
+  fail_unless (gst_buffer_list_get (list, 2, 0) == NULL);
+
+  /* iterate everything, just one more buffer now */
+  data.iter = 0;
+  gst_buffer_list_foreach (list, (GstBufferListFunc) foreach_func5, &data);
+  fail_unless (data.iter == 1);
+}
+
+GST_END_TEST;
+
+
 static Suite *
 gst_buffer_list_suite (void)
 {
@@ -660,6 +782,7 @@ gst_buffer_list_suite (void)
   tcase_add_test (tc_chain, test_take);
   tcase_add_test (tc_chain, test_do);
   tcase_add_test (tc_chain, test_merge);
+  tcase_add_test (tc_chain, test_foreach);
 
   return s;
 }
index fec9c77..ecfd130 100644 (file)
@@ -87,12 +87,14 @@ EXPORTS
        gst_buffer_is_metadata_writable
        gst_buffer_is_span_fast
        gst_buffer_join
+       gst_buffer_list_foreach
+       gst_buffer_list_get
        gst_buffer_list_get_type
+       gst_buffer_list_item_get_type
        gst_buffer_list_iterate
        gst_buffer_list_iterator_add
        gst_buffer_list_iterator_add_group
        gst_buffer_list_iterator_do
-       gst_buffer_list_iterator_do_data
        gst_buffer_list_iterator_free
        gst_buffer_list_iterator_merge_group
        gst_buffer_list_iterator_n_buffers