Merge remote-tracking branch 'origin/master' into 0.11
[platform/upstream/gstreamer.git] / gst / gstbufferlist.c
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: Lists of buffers for data-passing
26  * @see_also: #GstPad, #GstMiniObject
27  *
28  * Buffer lists are an object containing a list of buffers.
29  *
30  * Buffer lists are created with gst_buffer_list_new() and filled with data
31  * using a gst_buffer_list_insert().
32  *
33  */
34 #include "gst_private.h"
35
36 #include "gstbuffer.h"
37 #include "gstbufferlist.h"
38
39 #define GST_CAT_DEFAULT GST_CAT_BUFFER_LIST
40
41 /**
42  * GstBufferList:
43  *
44  * Opaque list of grouped buffers.
45  *
46  * Since: 0.10.24
47  */
48 struct _GstBufferList
49 {
50   GstMiniObject mini_object;
51
52   GArray *array;
53 };
54
55 GType _gst_buffer_list_type = 0;
56
57 GST_DEFINE_MINI_OBJECT_TYPE (GstBufferList, gst_buffer_list);
58
59 void
60 _priv_gst_buffer_list_initialize (void)
61 {
62   _gst_buffer_list_type = gst_buffer_list_get_type ();
63 }
64
65 static GstBufferList *
66 _gst_buffer_list_copy (GstBufferList * list)
67 {
68   GstBufferList *copy;
69   guint i, len;
70
71   len = list->array->len;
72   copy = gst_buffer_list_new_sized (len);
73
74   /* add and ref all buffers in the array */
75   for (i = 0; i < len; i++) {
76     GstBuffer *buf = g_array_index (list->array, GstBuffer *, i);
77     buf = gst_buffer_ref (buf);
78     g_array_append_val (copy->array, buf);
79   }
80   return copy;
81 }
82
83 static void
84 _gst_buffer_list_free (GstBufferList * list)
85 {
86   guint i, len;
87   GST_LOG ("free %p", list);
88
89   /* unrefs all buffers too */
90   len = list->array->len;
91   for (i = 0; i < len; i++)
92     gst_buffer_unref (g_array_index (list->array, GstBuffer *, i));
93   g_array_free (list->array, TRUE);
94
95   g_slice_free1 (GST_MINI_OBJECT_SIZE (list), list);
96 }
97
98 static void
99 gst_buffer_list_init (GstBufferList * list, gsize size, guint asize)
100 {
101   gst_mini_object_init (GST_MINI_OBJECT_CAST (list), _gst_buffer_list_type,
102       size);
103
104   list->mini_object.copy = (GstMiniObjectCopyFunction) _gst_buffer_list_copy;
105   list->mini_object.free = (GstMiniObjectFreeFunction) _gst_buffer_list_free;
106
107   list->array = g_array_sized_new (FALSE, FALSE, sizeof (GstBuffer *), asize);
108
109   GST_LOG ("init %p", list);
110 }
111
112 /**
113  * gst_buffer_list_new_sized:
114  * @size: an initial reserved size
115  *
116  * Creates a new, empty #GstBufferList. The caller is responsible for unreffing
117  * the returned #GstBufferList. The list will have @size space preallocated so
118  * that memory reallocations can be avoided.
119  *
120  * Free-function: gst_buffer_list_unref
121  *
122  * Returns: (transfer full): the new #GstBufferList. gst_buffer_list_unref()
123  *     after usage.
124  *
125  * Since: 0.10.24
126  */
127 GstBufferList *
128 gst_buffer_list_new_sized (guint size)
129 {
130   GstBufferList *list;
131
132   list = g_slice_new0 (GstBufferList);
133
134   GST_LOG ("new %p", list);
135
136   gst_buffer_list_init (list, sizeof (GstBufferList), size);
137
138   return list;
139 }
140
141 /**
142  * gst_buffer_list_new:
143  *
144  * Creates a new, empty #GstBufferList. The caller is responsible for unreffing
145  * the returned #GstBufferList.
146  *
147  * Free-function: gst_buffer_list_unref
148  *
149  * Returns: (transfer full): the new #GstBufferList. gst_buffer_list_unref()
150  *     after usage.
151  *
152  * Since: 0.10.24
153  */
154 GstBufferList *
155 gst_buffer_list_new (void)
156 {
157   return gst_buffer_list_new_sized (8);
158 }
159
160 /**
161  * gst_buffer_list_length:
162  * @list: a #GstBufferList
163  *
164  * Returns the number of buffers in @list.
165  *
166  * Returns: the number of buffers in the buffer list
167  *
168  * Since: 0.10.24
169  */
170 guint
171 gst_buffer_list_length (GstBufferList * list)
172 {
173   g_return_val_if_fail (GST_IS_BUFFER_LIST (list), 0);
174
175   return list->array->len;
176 }
177
178 /**
179  * gst_buffer_list_foreach:
180  * @list: a #GstBufferList
181  * @func: (scope call): a #GstBufferListFunc to call
182  * @user_data: (closure): user data passed to @func
183  *
184  * Call @func with @data for each buffer in @list.
185  *
186  * @func can modify the passed buffer pointer or its contents. The return value
187  * of @func define if this function returns or if the remaining buffers in
188  * the list should be skipped.
189  *
190  * Since: 0.10.24
191  */
192 void
193 gst_buffer_list_foreach (GstBufferList * list, GstBufferListFunc func,
194     gpointer user_data)
195 {
196   guint i, len;
197
198   g_return_if_fail (GST_IS_BUFFER_LIST (list));
199   g_return_if_fail (func != NULL);
200
201   len = list->array->len;
202   for (i = 0; i < len;) {
203     GstBuffer *buf, *buf_ret;
204     gboolean ret;
205
206     buf = buf_ret = g_array_index (list->array, GstBuffer *, i);
207     ret = func (&buf_ret, i, user_data);
208
209     /* Check if the function changed the buffer */
210     if (buf != buf_ret) {
211       if (buf_ret == NULL) {
212         g_array_remove_index (list->array, i);
213         len--;
214       } else {
215         g_array_index (list->array, GstBuffer *, i) = buf_ret;
216       }
217     }
218
219     if (!ret)
220       break;
221
222     /* If the buffer was not removed by func go to the next buffer */
223     if (buf_ret != NULL)
224       i++;
225   }
226 }
227
228 /**
229  * gst_buffer_list_get:
230  * @list: a #GstBufferList
231  * @idx: the index
232  *
233  * Get the buffer at @idx.
234  *
235  * Returns: (transfer none): the buffer at @idx in @group or NULL when there
236  *     is no buffer. The buffer remains valid as long as @list is valid.
237  *
238  * Since: 0.10.24
239  */
240 GstBuffer *
241 gst_buffer_list_get (GstBufferList * list, guint idx)
242 {
243   GstBuffer *buf;
244
245   g_return_val_if_fail (GST_IS_BUFFER_LIST (list), NULL);
246   g_return_val_if_fail (idx < list->array->len, NULL);
247
248   buf = g_array_index (list->array, GstBuffer *, idx);
249
250   return buf;
251 }
252
253 /**
254  * gst_buffer_list_insert:
255  * @list: a #GstBufferList
256  * @idx: the index
257  * @buffer: a #GstBuffer
258  *
259  * Insert @buffer at @idx in @list. Other buffers are moved to make room for
260  * this new buffer.
261  *
262  * A -1 value for @idx will append the buffer at the end.
263  */
264 void
265 gst_buffer_list_insert (GstBufferList * list, guint idx, GstBuffer * buffer)
266 {
267   g_return_if_fail (GST_IS_BUFFER_LIST (list));
268   g_return_if_fail (buffer != NULL);
269
270   if (idx == -1)
271     g_array_append_val (list->array, buffer);
272   else {
273     g_return_if_fail (idx < list->array->len);
274     g_array_insert_val (list->array, idx, buffer);
275   }
276 }
277
278 void
279 gst_buffer_list_remove (GstBufferList * list, guint idx, guint length)
280 {
281   g_return_if_fail (GST_IS_BUFFER_LIST (list));
282   g_return_if_fail (idx < list->array->len);
283
284   g_array_remove_range (list->array, idx, length);
285 }