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 } |
|