/src/gstreamer/subprojects/gstreamer/gst/gstbufferlist.c
Line | Count | Source |
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 | | * Copyright (C) 2014 Tim-Philipp Müller <tim at centricular dot com> |
5 | | * |
6 | | * gstbufferlist.c: Buffer list |
7 | | * |
8 | | * This library is free software; you can redistribute it and/or |
9 | | * modify it under the terms of the GNU Library General Public |
10 | | * License as published by the Free Software Foundation; either |
11 | | * version 2 of the License, or (at your option) any later version. |
12 | | * |
13 | | * This library is distributed in the hope that it will be useful, |
14 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 | | * Library General Public License for more details. |
17 | | * |
18 | | * You should have received a copy of the GNU Library General Public |
19 | | * License along with this library; if not, write to the |
20 | | * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, |
21 | | * Boston, MA 02110-1301, USA. |
22 | | */ |
23 | | |
24 | | /** |
25 | | * SECTION:gstbufferlist |
26 | | * @title: GstBufferList |
27 | | * @short_description: Lists of buffers for data-passing |
28 | | * @see_also: #GstPad, #GstMiniObject |
29 | | * |
30 | | * Buffer lists are an object containing a list of buffers. |
31 | | * |
32 | | * Buffer lists are created with gst_buffer_list_new() and filled with data |
33 | | * using gst_buffer_list_insert(). |
34 | | * |
35 | | * Buffer lists can be pushed on a srcpad with gst_pad_push_list(). This is |
36 | | * interesting when multiple buffers need to be pushed in one go because it |
37 | | * can reduce the amount of overhead for pushing each buffer individually. |
38 | | */ |
39 | | #define GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS |
40 | | #include "gst_private.h" |
41 | | |
42 | | #include "gstbuffer.h" |
43 | | #include "gstbufferlist.h" |
44 | | #include "gstutils.h" |
45 | | |
46 | | #define GST_CAT_DEFAULT GST_CAT_BUFFER_LIST |
47 | | |
48 | | #define GST_BUFFER_LIST_IS_USING_DYNAMIC_ARRAY(list) \ |
49 | 0 | ((list)->buffers != &(list)->arr[0]) |
50 | | |
51 | | /** |
52 | | * GstBufferList: |
53 | | * |
54 | | * Opaque list of grouped buffers. |
55 | | */ |
56 | | struct _GstBufferList |
57 | | { |
58 | | GstMiniObject mini_object; |
59 | | |
60 | | GstBuffer **buffers; |
61 | | guint n_buffers; |
62 | | guint n_allocated; |
63 | | |
64 | | /* one-item array, in reality more items are pre-allocated |
65 | | * as part of the GstBufferList structure, and that |
66 | | * pre-allocated array extends beyond the declared struct */ |
67 | | GstBuffer *arr[1]; |
68 | | }; |
69 | | |
70 | | GType _gst_buffer_list_type = 0; |
71 | | |
72 | 5 | GST_DEFINE_MINI_OBJECT_TYPE (GstBufferList, gst_buffer_list); |
73 | 5 | |
74 | 5 | void |
75 | 5 | _priv_gst_buffer_list_initialize (void) |
76 | 5 | { |
77 | 5 | _gst_buffer_list_type = gst_buffer_list_get_type (); |
78 | 5 | } |
79 | | |
80 | | static GstBufferList * |
81 | | _gst_buffer_list_copy (GstBufferList * list) |
82 | 0 | { |
83 | 0 | GstBufferList *copy; |
84 | 0 | guint i, len; |
85 | |
|
86 | 0 | len = list->n_buffers; |
87 | 0 | copy = gst_buffer_list_new_sized (list->n_allocated); |
88 | | |
89 | | /* add and ref all buffers in the array */ |
90 | 0 | for (i = 0; i < len; i++) { |
91 | 0 | copy->buffers[i] = gst_buffer_ref (list->buffers[i]); |
92 | 0 | gst_mini_object_add_parent (GST_MINI_OBJECT_CAST (copy->buffers[i]), |
93 | 0 | GST_MINI_OBJECT_CAST (copy)); |
94 | 0 | } |
95 | |
|
96 | 0 | copy->n_buffers = len; |
97 | |
|
98 | 0 | return copy; |
99 | 0 | } |
100 | | |
101 | | static void |
102 | | _gst_buffer_list_free (GstBufferList * list) |
103 | 0 | { |
104 | 0 | guint i, len; |
105 | |
|
106 | 0 | GST_LOG ("free %p", list); |
107 | | |
108 | | /* unrefs all buffers too */ |
109 | 0 | len = list->n_buffers; |
110 | 0 | for (i = 0; i < len; i++) { |
111 | 0 | gst_mini_object_remove_parent (GST_MINI_OBJECT_CAST (list->buffers[i]), |
112 | 0 | GST_MINI_OBJECT_CAST (list)); |
113 | 0 | gst_buffer_unref (list->buffers[i]); |
114 | 0 | } |
115 | |
|
116 | 0 | if (GST_BUFFER_LIST_IS_USING_DYNAMIC_ARRAY (list)) |
117 | 0 | g_free (list->buffers); |
118 | |
|
119 | | #ifdef USE_POISONING |
120 | | memset (list, 0xff, sizeof (GstBufferList)); |
121 | | #endif |
122 | |
|
123 | 0 | g_free (list); |
124 | 0 | } |
125 | | |
126 | | static void |
127 | | gst_buffer_list_init (GstBufferList * list, guint n_allocated) |
128 | 0 | { |
129 | 0 | gst_mini_object_init (GST_MINI_OBJECT_CAST (list), 0, _gst_buffer_list_type, |
130 | 0 | (GstMiniObjectCopyFunction) _gst_buffer_list_copy, NULL, |
131 | 0 | (GstMiniObjectFreeFunction) _gst_buffer_list_free); |
132 | |
|
133 | 0 | list->buffers = &list->arr[0]; |
134 | 0 | list->n_buffers = 0; |
135 | 0 | list->n_allocated = n_allocated; |
136 | |
|
137 | 0 | GST_LOG ("init %p", list); |
138 | 0 | } |
139 | | |
140 | | /** |
141 | | * gst_buffer_list_new_sized: |
142 | | * @size: an initial reserved size |
143 | | * |
144 | | * Creates a new, empty #GstBufferList. The list will have @size space |
145 | | * preallocated so that memory reallocations can be avoided. |
146 | | * |
147 | | * Returns: (transfer full): the new #GstBufferList. |
148 | | */ |
149 | | GstBufferList * |
150 | | gst_buffer_list_new_sized (guint size) |
151 | 0 | { |
152 | 0 | GstBufferList *list; |
153 | 0 | gsize slice_size; |
154 | 0 | guint n_allocated; |
155 | |
|
156 | 0 | if (size == 0) |
157 | 0 | size = 1; |
158 | |
|
159 | 0 | n_allocated = GST_ROUND_UP_16 (size); |
160 | |
|
161 | 0 | slice_size = sizeof (GstBufferList) + (n_allocated - 1) * sizeof (gpointer); |
162 | |
|
163 | 0 | list = g_malloc0 (slice_size); |
164 | |
|
165 | 0 | GST_LOG ("new %p", list); |
166 | |
|
167 | 0 | gst_buffer_list_init (list, n_allocated); |
168 | |
|
169 | 0 | return list; |
170 | 0 | } |
171 | | |
172 | | /** |
173 | | * gst_buffer_list_new: |
174 | | * |
175 | | * Creates a new, empty #GstBufferList. |
176 | | * |
177 | | * Returns: (transfer full): the new #GstBufferList. |
178 | | */ |
179 | | GstBufferList * |
180 | | gst_buffer_list_new (void) |
181 | 0 | { |
182 | 0 | return gst_buffer_list_new_sized (8); |
183 | 0 | } |
184 | | |
185 | | /** |
186 | | * gst_buffer_list_length: |
187 | | * @list: a #GstBufferList |
188 | | * |
189 | | * Returns the number of buffers in @list. |
190 | | * |
191 | | * Returns: the number of buffers in the buffer list |
192 | | */ |
193 | | guint |
194 | | gst_buffer_list_length (GstBufferList * list) |
195 | 0 | { |
196 | 0 | g_return_val_if_fail (GST_IS_BUFFER_LIST (list), 0); |
197 | | |
198 | 0 | return list->n_buffers; |
199 | 0 | } |
200 | | |
201 | | static inline void |
202 | | gst_buffer_list_remove_range_internal (GstBufferList * list, guint idx, |
203 | | guint length, gboolean unref_old) |
204 | 0 | { |
205 | 0 | guint i; |
206 | |
|
207 | 0 | if (unref_old) { |
208 | 0 | for (i = idx; i < idx + length; ++i) { |
209 | 0 | gst_mini_object_remove_parent (GST_MINI_OBJECT_CAST (list->buffers[i]), |
210 | 0 | GST_MINI_OBJECT_CAST (list)); |
211 | 0 | gst_buffer_unref (list->buffers[i]); |
212 | 0 | } |
213 | 0 | } |
214 | |
|
215 | 0 | if (idx + length != list->n_buffers) { |
216 | 0 | memmove (&list->buffers[idx], &list->buffers[idx + length], |
217 | 0 | (list->n_buffers - (idx + length)) * sizeof (void *)); |
218 | 0 | } |
219 | |
|
220 | 0 | list->n_buffers -= length; |
221 | 0 | } |
222 | | |
223 | | /** |
224 | | * gst_buffer_list_foreach: |
225 | | * @list: a #GstBufferList |
226 | | * @func: (scope call) (closure user_data): a #GstBufferListFunc to call |
227 | | * @user_data: user data passed to @func |
228 | | * |
229 | | * Calls @func with @data for each buffer in @list. |
230 | | * |
231 | | * @func can modify the passed buffer pointer or its contents. The return value |
232 | | * of @func defines if this function returns or if the remaining buffers in |
233 | | * the list should be skipped. |
234 | | * |
235 | | * Returns: %TRUE when @func returned %TRUE for each buffer in @list or when |
236 | | * @list is empty. |
237 | | */ |
238 | | gboolean |
239 | | gst_buffer_list_foreach (GstBufferList * list, GstBufferListFunc func, |
240 | | gpointer user_data) |
241 | 0 | { |
242 | 0 | guint i, len; |
243 | 0 | gboolean ret = TRUE; |
244 | 0 | gboolean list_was_writable, first_warning = TRUE; |
245 | |
|
246 | 0 | g_return_val_if_fail (GST_IS_BUFFER_LIST (list), FALSE); |
247 | 0 | g_return_val_if_fail (func != NULL, FALSE); |
248 | | |
249 | 0 | list_was_writable = gst_buffer_list_is_writable (list); |
250 | |
|
251 | 0 | len = list->n_buffers; |
252 | 0 | for (i = 0; i < len;) { |
253 | 0 | GstBuffer *buf, *buf_ret; |
254 | 0 | gboolean was_writable; |
255 | |
|
256 | 0 | buf = buf_ret = list->buffers[i]; |
257 | | |
258 | | /* If the buffer is writable, we remove us as parent for now to |
259 | | * allow the callback to destroy the buffer. If we get the buffer |
260 | | * back, we add ourselves as parent again. |
261 | | * |
262 | | * Non-writable buffers just get another reference as they were not |
263 | | * writable to begin with, and they would possibly become writable |
264 | | * by removing ourselves as parent |
265 | | */ |
266 | 0 | was_writable = list_was_writable && gst_buffer_is_writable (buf); |
267 | |
|
268 | 0 | if (was_writable) |
269 | 0 | gst_mini_object_remove_parent (GST_MINI_OBJECT_CAST (buf), |
270 | 0 | GST_MINI_OBJECT_CAST (list)); |
271 | 0 | else |
272 | 0 | gst_buffer_ref (buf); |
273 | |
|
274 | 0 | ret = func (&buf_ret, i, user_data); |
275 | | |
276 | | /* Check if the function changed the buffer */ |
277 | 0 | if (buf != buf_ret) { |
278 | | /* If the list was not writable but the callback was actually changing |
279 | | * our buffer, then it wouldn't have been allowed to do so. |
280 | | * |
281 | | * Fortunately we still have a reference to the old buffer in that case |
282 | | * and just not modify the list, unref the new buffer (if any) and warn |
283 | | * about this */ |
284 | 0 | if (!list_was_writable) { |
285 | 0 | if (first_warning) { |
286 | 0 | g_critical |
287 | 0 | ("gst_buffer_list_foreach: non-writable list %p was changed from callback", |
288 | 0 | list); |
289 | 0 | first_warning = FALSE; |
290 | 0 | } |
291 | 0 | if (buf_ret) |
292 | 0 | gst_buffer_unref (buf_ret); |
293 | 0 | } else if (buf_ret == NULL) { |
294 | 0 | gst_buffer_list_remove_range_internal (list, i, 1, !was_writable); |
295 | 0 | --len; |
296 | 0 | } else { |
297 | 0 | if (!was_writable) { |
298 | 0 | gst_mini_object_remove_parent (GST_MINI_OBJECT_CAST (buf), |
299 | 0 | GST_MINI_OBJECT_CAST (list)); |
300 | 0 | gst_buffer_unref (buf); |
301 | 0 | } |
302 | |
|
303 | 0 | list->buffers[i] = buf_ret; |
304 | 0 | gst_mini_object_add_parent (GST_MINI_OBJECT_CAST (buf_ret), |
305 | 0 | GST_MINI_OBJECT_CAST (list)); |
306 | 0 | } |
307 | 0 | } else { |
308 | 0 | if (was_writable) |
309 | 0 | gst_mini_object_add_parent (GST_MINI_OBJECT_CAST (buf), |
310 | 0 | GST_MINI_OBJECT_CAST (list)); |
311 | 0 | else |
312 | 0 | gst_buffer_unref (buf); |
313 | 0 | } |
314 | |
|
315 | 0 | if (!ret) |
316 | 0 | break; |
317 | | |
318 | | /* If the buffer was not removed by func go to the next buffer */ |
319 | 0 | if (buf_ret != NULL) |
320 | 0 | i++; |
321 | 0 | } |
322 | 0 | return ret; |
323 | 0 | } |
324 | | |
325 | | /** |
326 | | * gst_buffer_list_get: |
327 | | * @list: a #GstBufferList |
328 | | * @idx: the index |
329 | | * |
330 | | * Gets the buffer at @idx. |
331 | | * |
332 | | * You must make sure that @idx does not exceed the number of |
333 | | * buffers available. |
334 | | * |
335 | | * Returns: (transfer none): the buffer at @idx in @group. |
336 | | * The returned buffer remains valid as long as @list is valid and |
337 | | * buffer is not removed from the list. |
338 | | */ |
339 | | GstBuffer * |
340 | | gst_buffer_list_get (GstBufferList * list, guint idx) |
341 | 0 | { |
342 | 0 | g_return_val_if_fail (GST_IS_BUFFER_LIST (list), NULL); |
343 | 0 | g_return_val_if_fail (idx < list->n_buffers, NULL); |
344 | | |
345 | 0 | return list->buffers[idx]; |
346 | 0 | } |
347 | | |
348 | | /** |
349 | | * gst_buffer_list_get_writable: |
350 | | * @list: a (writable) #GstBufferList |
351 | | * @idx: the index |
352 | | * |
353 | | * Gets the buffer at @idx, ensuring it is a writable buffer. |
354 | | * |
355 | | * You must make sure that @idx does not exceed the number of |
356 | | * buffers available. |
357 | | * |
358 | | * Returns: (transfer none): the buffer at @idx in @group. |
359 | | * The returned buffer remains valid as long as @list is valid and |
360 | | * the buffer is not removed from the list. |
361 | | * |
362 | | * Since: 1.14 |
363 | | */ |
364 | | GstBuffer * |
365 | | gst_buffer_list_get_writable (GstBufferList * list, guint idx) |
366 | 0 | { |
367 | 0 | GstBuffer *new_buf; |
368 | |
|
369 | 0 | g_return_val_if_fail (GST_IS_BUFFER_LIST (list), NULL); |
370 | 0 | g_return_val_if_fail (gst_buffer_list_is_writable (list), NULL); |
371 | 0 | g_return_val_if_fail (idx < list->n_buffers, NULL); |
372 | | |
373 | | /* We have to implement this manually here to correctly add/remove the |
374 | | * parent */ |
375 | 0 | if (gst_buffer_is_writable (list->buffers[idx])) |
376 | 0 | return list->buffers[idx]; |
377 | | |
378 | 0 | gst_mini_object_remove_parent (GST_MINI_OBJECT_CAST (list->buffers[idx]), |
379 | 0 | GST_MINI_OBJECT_CAST (list)); |
380 | 0 | new_buf = gst_buffer_copy (list->buffers[idx]); |
381 | 0 | gst_mini_object_add_parent (GST_MINI_OBJECT_CAST (new_buf), |
382 | 0 | GST_MINI_OBJECT_CAST (list)); |
383 | 0 | gst_buffer_unref (list->buffers[idx]); |
384 | 0 | list->buffers[idx] = new_buf; |
385 | |
|
386 | 0 | return new_buf; |
387 | 0 | } |
388 | | |
389 | | /** |
390 | | * gst_buffer_list_add: |
391 | | * @l: a #GstBufferList |
392 | | * @b: a #GstBuffer |
393 | | * |
394 | | * Append @b at the end of @l. |
395 | | */ |
396 | | /** |
397 | | * gst_buffer_list_insert: |
398 | | * @list: a #GstBufferList |
399 | | * @idx: the index |
400 | | * @buffer: (transfer full): a #GstBuffer |
401 | | * |
402 | | * Inserts @buffer at @idx in @list. Other buffers are moved to make room for |
403 | | * this new buffer. |
404 | | * |
405 | | * A -1 value for @idx will append the buffer at the end. |
406 | | */ |
407 | | void |
408 | | gst_buffer_list_insert (GstBufferList * list, gint idx, GstBuffer * buffer) |
409 | 0 | { |
410 | 0 | guint want_alloc; |
411 | |
|
412 | 0 | g_return_if_fail (GST_IS_BUFFER_LIST (list)); |
413 | 0 | g_return_if_fail (buffer != NULL); |
414 | 0 | g_return_if_fail (gst_buffer_list_is_writable (list)); |
415 | | |
416 | 0 | if (idx == -1 && list->n_buffers < list->n_allocated) { |
417 | 0 | gst_mini_object_add_parent (GST_MINI_OBJECT_CAST (buffer), |
418 | 0 | GST_MINI_OBJECT_CAST (list)); |
419 | 0 | list->buffers[list->n_buffers++] = buffer; |
420 | 0 | return; |
421 | 0 | } |
422 | | |
423 | 0 | if (idx == -1 || idx > list->n_buffers) |
424 | 0 | idx = list->n_buffers; |
425 | |
|
426 | 0 | want_alloc = list->n_buffers + 1; |
427 | |
|
428 | 0 | if (want_alloc > list->n_allocated) { |
429 | 0 | if (G_UNLIKELY (list->n_allocated > (G_MAXUINT / 2))) |
430 | 0 | g_error ("Growing GstBufferList would result in overflow"); |
431 | |
|
432 | 0 | want_alloc = MAX (GST_ROUND_UP_16 (want_alloc), list->n_allocated * 2); |
433 | |
|
434 | 0 | if (GST_BUFFER_LIST_IS_USING_DYNAMIC_ARRAY (list)) { |
435 | 0 | list->buffers = g_renew (GstBuffer *, list->buffers, want_alloc); |
436 | 0 | } else { |
437 | 0 | list->buffers = g_new0 (GstBuffer *, want_alloc); |
438 | 0 | memcpy (list->buffers, &list->arr[0], list->n_buffers * sizeof (void *)); |
439 | 0 | GST_CAT_LOG (GST_CAT_PERFORMANCE, "exceeding pre-alloced array"); |
440 | 0 | } |
441 | |
|
442 | 0 | list->n_allocated = want_alloc; |
443 | 0 | } |
444 | |
|
445 | 0 | if (idx < list->n_buffers) { |
446 | 0 | memmove (&list->buffers[idx + 1], &list->buffers[idx], |
447 | 0 | (list->n_buffers - idx) * sizeof (void *)); |
448 | 0 | } |
449 | |
|
450 | 0 | ++list->n_buffers; |
451 | 0 | list->buffers[idx] = buffer; |
452 | 0 | gst_mini_object_add_parent (GST_MINI_OBJECT_CAST (buffer), |
453 | 0 | GST_MINI_OBJECT_CAST (list)); |
454 | 0 | } |
455 | | |
456 | | /** |
457 | | * gst_buffer_list_remove: |
458 | | * @list: a #GstBufferList |
459 | | * @idx: the index |
460 | | * @length: the amount to remove |
461 | | * |
462 | | * Removes @length buffers starting from @idx in @list. The following buffers |
463 | | * are moved to close the gap. |
464 | | */ |
465 | | void |
466 | | gst_buffer_list_remove (GstBufferList * list, guint idx, guint length) |
467 | 0 | { |
468 | 0 | g_return_if_fail (GST_IS_BUFFER_LIST (list)); |
469 | 0 | g_return_if_fail (idx < list->n_buffers); |
470 | 0 | g_return_if_fail (idx + length <= list->n_buffers); |
471 | 0 | g_return_if_fail (gst_buffer_list_is_writable (list)); |
472 | | |
473 | 0 | gst_buffer_list_remove_range_internal (list, idx, length, TRUE); |
474 | 0 | } |
475 | | |
476 | | /** |
477 | | * gst_buffer_list_copy_deep: |
478 | | * @list: a #GstBufferList |
479 | | * |
480 | | * Creates a copy of the given buffer list. This will make a newly allocated |
481 | | * copy of the buffers that the source buffer list contains. |
482 | | * |
483 | | * Returns: (transfer full): a new copy of @list. |
484 | | * |
485 | | * Since: 1.6 |
486 | | */ |
487 | | GstBufferList * |
488 | | gst_buffer_list_copy_deep (const GstBufferList * list) |
489 | 0 | { |
490 | 0 | guint i, len; |
491 | 0 | GstBufferList *result = NULL; |
492 | |
|
493 | 0 | g_return_val_if_fail (GST_IS_BUFFER_LIST (list), NULL); |
494 | | |
495 | 0 | result = gst_buffer_list_new (); |
496 | |
|
497 | 0 | len = list->n_buffers; |
498 | 0 | for (i = 0; i < len; i++) { |
499 | 0 | GstBuffer *old = list->buffers[i]; |
500 | 0 | GstBuffer *new = gst_buffer_copy_deep (old); |
501 | |
|
502 | 0 | if (G_LIKELY (new)) { |
503 | 0 | gst_buffer_list_insert (result, i, new); |
504 | 0 | } else { |
505 | 0 | g_warning |
506 | 0 | ("Failed to deep copy buffer %p while deep " |
507 | 0 | "copying buffer list %p. Buffer list copy " |
508 | 0 | "will be incomplete", old, list); |
509 | 0 | } |
510 | 0 | } |
511 | |
|
512 | 0 | return result; |
513 | 0 | } |
514 | | |
515 | | /** |
516 | | * gst_buffer_list_calculate_size: |
517 | | * @list: a #GstBufferList |
518 | | * |
519 | | * Calculates the size of the data contained in @list by adding the |
520 | | * size of all buffers. |
521 | | * |
522 | | * Returns: the size of the data contained in @list in bytes. |
523 | | * |
524 | | * Since: 1.14 |
525 | | */ |
526 | | gsize |
527 | | gst_buffer_list_calculate_size (GstBufferList * list) |
528 | 0 | { |
529 | 0 | GstBuffer **buffers; |
530 | 0 | gsize size = 0; |
531 | 0 | guint i, n; |
532 | |
|
533 | 0 | g_return_val_if_fail (GST_IS_BUFFER_LIST (list), 0); |
534 | | |
535 | 0 | n = list->n_buffers; |
536 | 0 | buffers = list->buffers; |
537 | |
|
538 | 0 | for (i = 0; i < n; ++i) |
539 | 0 | size += gst_buffer_get_size (buffers[i]); |
540 | |
|
541 | 0 | return size; |
542 | 0 | } |
543 | | |
544 | | /** |
545 | | * gst_buffer_list_ref: (skip) |
546 | | * @list: a #GstBufferList |
547 | | * |
548 | | * Increases the refcount of the given buffer list by one. |
549 | | * |
550 | | * Note that the refcount affects the writability of @list and its data, see |
551 | | * gst_buffer_list_make_writable(). It is important to note that keeping |
552 | | * additional references to GstBufferList instances can potentially increase |
553 | | * the number of memcpy operations in a pipeline. |
554 | | * |
555 | | * Returns: (transfer full): @list |
556 | | */ |
557 | | GstBufferList * |
558 | | gst_buffer_list_ref (GstBufferList * list) |
559 | 0 | { |
560 | 0 | return |
561 | 0 | GST_BUFFER_LIST_CAST (gst_mini_object_ref (GST_MINI_OBJECT_CAST (list))); |
562 | 0 | } |
563 | | |
564 | | /** |
565 | | * gst_buffer_list_unref: (skip) |
566 | | * @list: (transfer full): a #GstBufferList |
567 | | * |
568 | | * Decreases the refcount of the buffer list. If the refcount reaches 0, the |
569 | | * buffer list will be freed. |
570 | | */ |
571 | | void |
572 | | gst_buffer_list_unref (GstBufferList * list) |
573 | 0 | { |
574 | 0 | gst_mini_object_unref (GST_MINI_OBJECT_CAST (list)); |
575 | 0 | } |
576 | | |
577 | | /** |
578 | | * gst_clear_buffer_list: (skip) |
579 | | * @list_ptr: a pointer to a #GstBufferList reference |
580 | | * |
581 | | * Clears a reference to a #GstBufferList. |
582 | | * |
583 | | * @list_ptr must not be %NULL. |
584 | | * |
585 | | * If the reference is %NULL then this function does nothing. Otherwise, the |
586 | | * reference count of the list is decreased and the pointer is set to %NULL. |
587 | | * |
588 | | * Since: 1.16 |
589 | | */ |
590 | | void |
591 | | gst_clear_buffer_list (GstBufferList ** list_ptr) |
592 | 0 | { |
593 | 0 | gst_clear_mini_object ((GstMiniObject **) list_ptr); |
594 | 0 | } |
595 | | |
596 | | /** |
597 | | * gst_buffer_list_copy: (skip) |
598 | | * @list: a #GstBufferList |
599 | | * |
600 | | * Creates a shallow copy of the given buffer list. This will make a newly |
601 | | * allocated copy of the source list with copies of buffer pointers. The |
602 | | * refcount of buffers pointed to will be increased by one. |
603 | | * |
604 | | * Returns: (transfer full): a new copy of @list. |
605 | | */ |
606 | | GstBufferList * |
607 | | gst_buffer_list_copy (const GstBufferList * list) |
608 | 0 | { |
609 | 0 | return |
610 | 0 | GST_BUFFER_LIST_CAST (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST |
611 | 0 | (list))); |
612 | 0 | } |
613 | | |
614 | | /** |
615 | | * gst_buffer_list_replace: |
616 | | * @old_list: (inout) (transfer full) (nullable): pointer to a pointer to a |
617 | | * #GstBufferList to be replaced. |
618 | | * @new_list: (transfer none) (allow-none): pointer to a #GstBufferList that |
619 | | * will replace the buffer list pointed to by @old_list. |
620 | | * |
621 | | * Modifies a pointer to a #GstBufferList to point to a different |
622 | | * #GstBufferList. The modification is done atomically (so this is useful for |
623 | | * ensuring thread safety in some cases), and the reference counts are updated |
624 | | * appropriately (the old buffer list is unreffed, the new is reffed). |
625 | | * |
626 | | * Either @new_list or the #GstBufferList pointed to by @old_list may be %NULL. |
627 | | * |
628 | | * Returns: %TRUE if @new_list was different from @old_list |
629 | | * |
630 | | * Since: 1.16 |
631 | | */ |
632 | | gboolean |
633 | | gst_buffer_list_replace (GstBufferList ** old_list, GstBufferList * new_list) |
634 | 0 | { |
635 | 0 | return gst_mini_object_replace ((GstMiniObject **) old_list, |
636 | 0 | (GstMiniObject *) new_list); |
637 | 0 | } |
638 | | |
639 | | /** |
640 | | * gst_buffer_list_take: |
641 | | * @old_list: (inout) (transfer full): pointer to a pointer to a #GstBufferList |
642 | | * to be replaced. |
643 | | * @new_list: (transfer full) (allow-none): pointer to a #GstBufferList |
644 | | * that will replace the bufferlist pointed to by @old_list. |
645 | | * |
646 | | * Modifies a pointer to a #GstBufferList to point to a different |
647 | | * #GstBufferList. This function is similar to gst_buffer_list_replace() except |
648 | | * that it takes ownership of @new_list. |
649 | | * |
650 | | * Returns: %TRUE if @new_list was different from @old_list |
651 | | * |
652 | | * Since: 1.16 |
653 | | */ |
654 | | gboolean |
655 | | gst_buffer_list_take (GstBufferList ** old_list, GstBufferList * new_list) |
656 | 0 | { |
657 | 0 | return gst_mini_object_take ((GstMiniObject **) old_list, |
658 | 0 | (GstMiniObject *) new_list); |
659 | 0 | } |
660 | | |
661 | | /** |
662 | | * gst_buffer_list_steal: (skip) |
663 | | * @old_list: (inout) (transfer full) (nullable): pointer to a |
664 | | * pointer to a #GstBufferList to be stolen. |
665 | | * |
666 | | * Atomically replace the #GstBufferList pointed to by @old_list with %NULL and |
667 | | * return the original buffer list. |
668 | | * Since: 1.28 |
669 | | */ |
670 | | GstBufferList * |
671 | | gst_buffer_list_steal (GstBufferList ** old_list) |
672 | 0 | { |
673 | 0 | return GST_BUFFER_LIST_CAST (gst_mini_object_steal ((GstMiniObject **) |
674 | 0 | old_list)); |
675 | 0 | } |
676 | | |
677 | | /** |
678 | | * gst_buffer_list_is_writable: |
679 | | * @list: a #GstEvent |
680 | | * |
681 | | * Tests if you can safely modify @list. It is only safe to modify buffer list when |
682 | | * there is only one owner of the buffer list - ie, the object is writable. |
683 | | */ |
684 | | gboolean |
685 | | gst_buffer_list_is_writable (const GstBufferList * list) |
686 | 0 | { |
687 | 0 | return gst_mini_object_is_writable (GST_MINI_OBJECT_CONST_CAST (list)); |
688 | 0 | } |
689 | | |
690 | | /** |
691 | | * gst_buffer_list_make_writable: |
692 | | * @list: (transfer full): a #GstBufferList |
693 | | * |
694 | | * Returns a writable copy of @list. |
695 | | * |
696 | | * If there is only one reference count on @list, the caller must be the owner, |
697 | | * and so this function will return the buffer list object unchanged. If on the other |
698 | | * hand there is more than one reference on the object, a new buffer list object will |
699 | | * be returned. The caller's reference on @list will be removed, and instead the |
700 | | * caller will own a reference to the returned object. |
701 | | * |
702 | | * In short, this function unrefs the buffer_list in the argument and refs the buffer list |
703 | | * that it returns. Don't access the argument after calling this function. See |
704 | | * also: gst_buffer_list_ref(). |
705 | | * |
706 | | * Returns: (transfer full): a writable buffer list which may or may not be the |
707 | | * same as @buffer list |
708 | | */ |
709 | | GstBufferList * |
710 | | gst_buffer_list_make_writable (GstBufferList * list) |
711 | 0 | { |
712 | 0 | return |
713 | 0 | GST_BUFFER_LIST_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST |
714 | 0 | (list))); |
715 | 0 | } |