Revert "bin: Hold the state lock while removing elements from a bin"
[platform/upstream/gstreamer.git] / gst / gstbuffer.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wtay@chello.be>
4  *
5  * gstbuffer.c: Buffer operations
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., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 /**
24  * SECTION:gstbuffer
25  * @title: GstBuffer
26  * @short_description: Data-passing buffer type
27  * @see_also: #GstPad, #GstMiniObject, #GstMemory, #GstMeta, #GstBufferPool
28  *
29  * Buffers are the basic unit of data transfer in GStreamer. They contain the
30  * timing and offset along with other arbitrary metadata that is associated
31  * with the #GstMemory blocks that the buffer contains.
32  *
33  * Buffers are usually created with gst_buffer_new(). After a buffer has been
34  * created one will typically allocate memory for it and add it to the buffer.
35  * The following example creates a buffer that can hold a given video frame
36  * with a given width, height and bits per plane.
37  * |[<!-- language="C" -->
38  *   GstBuffer *buffer;
39  *   GstMemory *memory;
40  *   gint size, width, height, bpp;
41  *   ...
42  *   size = width * height * bpp;
43  *   buffer = gst_buffer_new ();
44  *   memory = gst_allocator_alloc (NULL, size, NULL);
45  *   gst_buffer_insert_memory (buffer, -1, memory);
46  *   ...
47  * ]|
48  *
49  * Alternatively, use gst_buffer_new_allocate() to create a buffer with
50  * preallocated data of a given size.
51  *
52  * Buffers can contain a list of #GstMemory objects. You can retrieve how many
53  * memory objects with gst_buffer_n_memory() and you can get a pointer
54  * to memory with gst_buffer_peek_memory()
55  *
56  * A buffer will usually have timestamps, and a duration, but neither of these
57  * are guaranteed (they may be set to #GST_CLOCK_TIME_NONE). Whenever a
58  * meaningful value can be given for these, they should be set. The timestamps
59  * and duration are measured in nanoseconds (they are #GstClockTime values).
60  *
61  * The buffer DTS refers to the timestamp when the buffer should be decoded and
62  * is usually monotonically increasing. The buffer PTS refers to the timestamp when
63  * the buffer content should be presented to the user and is not always
64  * monotonically increasing.
65  *
66  * A buffer can also have one or both of a start and an end offset. These are
67  * media-type specific. For video buffers, the start offset will generally be
68  * the frame number. For audio buffers, it will be the number of samples
69  * produced so far. For compressed data, it could be the byte offset in a
70  * source or destination file. Likewise, the end offset will be the offset of
71  * the end of the buffer. These can only be meaningfully interpreted if you
72  * know the media type of the buffer (the preceding CAPS event). Either or both
73  * can be set to #GST_BUFFER_OFFSET_NONE.
74  *
75  * gst_buffer_ref() is used to increase the refcount of a buffer. This must be
76  * done when you want to keep a handle to the buffer after pushing it to the
77  * next element. The buffer refcount determines the writability of the buffer, a
78  * buffer is only writable when the refcount is exactly 1, i.e. when the caller
79  * has the only reference to the buffer.
80  *
81  * To efficiently create a smaller buffer out of an existing one, you can
82  * use gst_buffer_copy_region(). This method tries to share the memory objects
83  * between the two buffers.
84  *
85  * If a plug-in wants to modify the buffer data or metadata in-place, it should
86  * first obtain a buffer that is safe to modify by using
87  * gst_buffer_make_writable().  This function is optimized so that a copy will
88  * only be made when it is necessary.
89  *
90  * Several flags of the buffer can be set and unset with the
91  * GST_BUFFER_FLAG_SET() and GST_BUFFER_FLAG_UNSET() macros. Use
92  * GST_BUFFER_FLAG_IS_SET() to test if a certain #GstBufferFlags flag is set.
93  *
94  * Buffers can be efficiently merged into a larger buffer with
95  * gst_buffer_append(). Copying of memory will only be done when absolutely
96  * needed.
97  *
98  * Arbitrary extra metadata can be set on a buffer with gst_buffer_add_meta().
99  * Metadata can be retrieved with gst_buffer_get_meta(). See also #GstMeta
100  *
101  * An element should either unref the buffer or push it out on a src pad
102  * using gst_pad_push() (see #GstPad).
103  *
104  * Buffers are usually freed by unreffing them with gst_buffer_unref(). When
105  * the refcount drops to 0, any memory and metadata pointed to by the buffer is
106  * unreffed as well. Buffers allocated from a #GstBufferPool will be returned to
107  * the pool when the refcount drops to 0.
108  *
109  * The #GstParentBufferMeta is a meta which can be attached to a #GstBuffer
110  * to hold a reference to another buffer that is only released when the child
111  * #GstBuffer is released.
112  *
113  * Typically, #GstParentBufferMeta is used when the child buffer is directly
114  * using the #GstMemory of the parent buffer, and wants to prevent the parent
115  * buffer from being returned to a buffer pool until the #GstMemory is available
116  * for re-use. (Since 1.6)
117  *
118  */
119 #include "gst_private.h"
120
121 #ifdef HAVE_UNISTD_H
122 #include <unistd.h>
123 #endif
124 #ifdef HAVE_STDLIB_H
125 #include <stdlib.h>
126 #endif
127
128 #include "gstbuffer.h"
129 #include "gstbufferpool.h"
130 #include "gstinfo.h"
131 #include "gstutils.h"
132 #include "gstversion.h"
133
134 GType _gst_buffer_type = 0;
135
136 typedef struct _GstMetaItem GstMetaItem;
137
138 struct _GstMetaItem
139 {
140   GstMetaItem *next;
141   GstMeta meta;
142 };
143
144 /* info->size will be sizeof(FooMeta) which contains a GstMeta at the beginning
145  * too, and then there is again a GstMeta in GstMetaItem, so subtract one. */
146 #define ITEM_SIZE(info) ((info)->size + sizeof (GstMetaItem) - sizeof (GstMeta))
147
148 #define GST_BUFFER_MEM_MAX         16
149
150 #define GST_BUFFER_SLICE_SIZE(b)   (((GstBufferImpl *)(b))->slice_size)
151 #define GST_BUFFER_MEM_LEN(b)      (((GstBufferImpl *)(b))->len)
152 #define GST_BUFFER_MEM_ARRAY(b)    (((GstBufferImpl *)(b))->mem)
153 #define GST_BUFFER_MEM_PTR(b,i)    (((GstBufferImpl *)(b))->mem[i])
154 #define GST_BUFFER_BUFMEM(b)       (((GstBufferImpl *)(b))->bufmem)
155 #define GST_BUFFER_META(b)         (((GstBufferImpl *)(b))->item)
156
157 typedef struct
158 {
159   GstBuffer buffer;
160
161   gsize slice_size;
162
163   /* the memory blocks */
164   guint len;
165   GstMemory *mem[GST_BUFFER_MEM_MAX];
166
167   /* memory of the buffer when allocated from 1 chunk */
168   GstMemory *bufmem;
169
170   /* FIXME, make metadata allocation more efficient by using part of the
171    * GstBufferImpl */
172   GstMetaItem *item;
173 } GstBufferImpl;
174
175
176 static gboolean
177 _is_span (GstMemory ** mem, gsize len, gsize * poffset, GstMemory ** parent)
178 {
179   GstMemory *mcur, *mprv;
180   gboolean have_offset = FALSE;
181   gsize i;
182
183   mcur = mprv = NULL;
184
185   for (i = 0; i < len; i++) {
186     if (mcur)
187       mprv = mcur;
188     mcur = mem[i];
189
190     if (mprv && mcur) {
191       gsize poffs;
192
193       /* check if memory is contiguous */
194       if (!gst_memory_is_span (mprv, mcur, &poffs))
195         return FALSE;
196
197       if (!have_offset) {
198         if (poffset)
199           *poffset = poffs;
200         if (parent)
201           *parent = mprv->parent;
202
203         have_offset = TRUE;
204       }
205     }
206   }
207   return have_offset;
208 }
209
210 static GstMemory *
211 _get_merged_memory (GstBuffer * buffer, guint idx, guint length)
212 {
213   GstMemory **mem, *result = NULL;
214
215   GST_CAT_LOG (GST_CAT_BUFFER, "buffer %p, idx %u, length %u", buffer, idx,
216       length);
217
218   mem = GST_BUFFER_MEM_ARRAY (buffer);
219
220   if (G_UNLIKELY (length == 0)) {
221     result = NULL;
222   } else if (G_LIKELY (length == 1)) {
223     result = gst_memory_ref (mem[idx]);
224   } else {
225     GstMemory *parent = NULL;
226     gsize size, poffset = 0;
227
228     size = gst_buffer_get_sizes_range (buffer, idx, length, NULL, NULL);
229
230     if (G_UNLIKELY (_is_span (mem + idx, length, &poffset, &parent))) {
231       if (!GST_MEMORY_IS_NO_SHARE (parent))
232         result = gst_memory_share (parent, poffset, size);
233       if (!result) {
234         GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "copy for merge %p", parent);
235         result = gst_memory_copy (parent, poffset, size);
236       }
237     } else {
238       gsize i, tocopy, left;
239       GstMapInfo sinfo, dinfo;
240       guint8 *ptr;
241
242       result = gst_allocator_alloc (NULL, size, NULL);
243       if (result == NULL || !gst_memory_map (result, &dinfo, GST_MAP_WRITE)) {
244         GST_CAT_ERROR (GST_CAT_BUFFER, "Failed to map memory writable");
245         if (result)
246           gst_memory_unref (result);
247         return NULL;
248       }
249
250       ptr = dinfo.data;
251       left = size;
252
253       for (i = idx; i < (idx + length) && left > 0; i++) {
254         if (!gst_memory_map (mem[i], &sinfo, GST_MAP_READ)) {
255           GST_CAT_ERROR (GST_CAT_BUFFER,
256               "buffer %p, idx %u, length %u failed to map readable", buffer,
257               idx, length);
258           gst_memory_unmap (result, &dinfo);
259           gst_memory_unref (result);
260           return NULL;
261         }
262         tocopy = MIN (sinfo.size, left);
263         GST_CAT_DEBUG (GST_CAT_PERFORMANCE,
264             "memcpy %" G_GSIZE_FORMAT " bytes for merge %p from memory %p",
265             tocopy, result, mem[i]);
266         memcpy (ptr, (guint8 *) sinfo.data, tocopy);
267         left -= tocopy;
268         ptr += tocopy;
269         gst_memory_unmap (mem[i], &sinfo);
270       }
271       gst_memory_unmap (result, &dinfo);
272     }
273   }
274   return result;
275 }
276
277 static void
278 _replace_memory (GstBuffer * buffer, guint len, guint idx, guint length,
279     GstMemory * mem)
280 {
281   gsize end, i;
282
283   end = idx + length;
284
285   GST_CAT_LOG (GST_CAT_BUFFER,
286       "buffer %p replace %u-%" G_GSIZE_FORMAT " with memory %p", buffer, idx,
287       end, mem);
288
289   /* unref old memory */
290   for (i = idx; i < end; i++) {
291     GstMemory *old = GST_BUFFER_MEM_PTR (buffer, i);
292
293     gst_memory_unlock (old, GST_LOCK_FLAG_EXCLUSIVE);
294     gst_mini_object_remove_parent (GST_MINI_OBJECT_CAST (old),
295         GST_MINI_OBJECT_CAST (buffer));
296     gst_memory_unref (old);
297   }
298
299   if (mem != NULL) {
300     /* replace with single memory */
301     gst_mini_object_add_parent (GST_MINI_OBJECT_CAST (mem),
302         GST_MINI_OBJECT_CAST (buffer));
303     gst_memory_lock (mem, GST_LOCK_FLAG_EXCLUSIVE);
304     GST_BUFFER_MEM_PTR (buffer, idx) = mem;
305     idx++;
306     length--;
307   }
308
309   if (end < len) {
310     memmove (&GST_BUFFER_MEM_PTR (buffer, idx),
311         &GST_BUFFER_MEM_PTR (buffer, end), (len - end) * sizeof (gpointer));
312   }
313   GST_BUFFER_MEM_LEN (buffer) = len - length;
314   GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY);
315 }
316
317 /**
318  * gst_buffer_get_flags:
319  * @buffer: a #GstBuffer
320  *
321  * Get the #GstBufferFlags flags set on this buffer.
322  *
323  * Returns: the flags set on this buffer.
324  *
325  * Since: 1.10
326  */
327 GstBufferFlags
328 gst_buffer_get_flags (GstBuffer * buffer)
329 {
330   return (GstBufferFlags) GST_BUFFER_FLAGS (buffer);
331 }
332
333 /**
334  * gst_buffer_flag_is_set:
335  * @buffer: a #GstBuffer
336  * @flags: the #GstBufferFlags flag to check.
337  *
338  * Gives the status of a specific flag on a buffer.
339  *
340  * Returns: %TRUE if all flags in @flags are found on @buffer.
341  *
342  * Since: 1.10
343  */
344 gboolean
345 gst_buffer_has_flags (GstBuffer * buffer, GstBufferFlags flags)
346 {
347   return GST_BUFFER_FLAG_IS_SET (buffer, flags);
348 }
349
350 /**
351  * gst_buffer_set_flags:
352  * @buffer: a #GstBuffer
353  * @flags: the #GstBufferFlags to set.
354  *
355  * Sets one or more buffer flags on a buffer.
356  *
357  * Returns: %TRUE if @flags were successfully set on buffer.
358  *
359  * Since: 1.10
360  */
361 gboolean
362 gst_buffer_set_flags (GstBuffer * buffer, GstBufferFlags flags)
363 {
364   GST_BUFFER_FLAG_SET (buffer, flags);
365   return TRUE;
366 }
367
368 /**
369  * gst_buffer_unset_flags:
370  * @buffer: a #GstBuffer
371  * @flags: the #GstBufferFlags to clear
372  *
373  * Clears one or more buffer flags.
374  *
375  * Returns: true if @flags is successfully cleared from buffer.
376  *
377  * Since: 1.10
378  */
379 gboolean
380 gst_buffer_unset_flags (GstBuffer * buffer, GstBufferFlags flags)
381 {
382   GST_BUFFER_FLAG_UNSET (buffer, flags);
383   return TRUE;
384 }
385
386
387
388 /* transfer full for return and transfer none for @mem */
389 static inline GstMemory *
390 _memory_get_exclusive_reference (GstMemory * mem)
391 {
392   GstMemory *ret = NULL;
393
394   if (gst_memory_lock (mem, GST_LOCK_FLAG_EXCLUSIVE)) {
395     ret = gst_memory_ref (mem);
396   } else {
397     /* we cannot take another exclusive lock as the memory is already
398      * locked WRITE + EXCLUSIVE according to part-miniobject.txt */
399     ret = gst_memory_copy (mem, 0, -1);
400
401     if (ret) {
402       if (!gst_memory_lock (ret, GST_LOCK_FLAG_EXCLUSIVE)) {
403         gst_memory_unref (ret);
404         ret = NULL;
405       }
406     }
407   }
408
409   if (!ret)
410     GST_CAT_WARNING (GST_CAT_BUFFER, "Failed to acquire an exclusive lock for "
411         "memory %p", mem);
412
413   return ret;
414 }
415
416 static inline void
417 _memory_add (GstBuffer * buffer, gint idx, GstMemory * mem)
418 {
419   guint i, len = GST_BUFFER_MEM_LEN (buffer);
420
421   GST_CAT_LOG (GST_CAT_BUFFER, "buffer %p, idx %d, mem %p", buffer, idx, mem);
422
423   if (G_UNLIKELY (len >= GST_BUFFER_MEM_MAX)) {
424     /* too many buffer, span them. */
425     /* FIXME, there is room for improvement here: We could only try to merge
426      * 2 buffers to make some room. If we can't efficiently merge 2 buffers we
427      * could try to only merge the two smallest buffers to avoid memcpy, etc. */
428     GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "memory array overflow in buffer %p",
429         buffer);
430     _replace_memory (buffer, len, 0, len, _get_merged_memory (buffer, 0, len));
431     /* we now have 1 single spanned buffer */
432     len = 1;
433   }
434
435   if (idx == -1)
436     idx = len;
437
438   for (i = len; i > idx; i--) {
439     /* move buffers to insert, FIXME, we need to insert first and then merge */
440     GST_BUFFER_MEM_PTR (buffer, i) = GST_BUFFER_MEM_PTR (buffer, i - 1);
441   }
442   /* and insert the new buffer */
443   GST_BUFFER_MEM_PTR (buffer, idx) = mem;
444   GST_BUFFER_MEM_LEN (buffer) = len + 1;
445   gst_mini_object_add_parent (GST_MINI_OBJECT_CAST (mem),
446       GST_MINI_OBJECT_CAST (buffer));
447
448   GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY);
449 }
450
451 GST_DEFINE_MINI_OBJECT_TYPE (GstBuffer, gst_buffer);
452
453 void
454 _priv_gst_buffer_initialize (void)
455 {
456   _gst_buffer_type = gst_buffer_get_type ();
457 }
458
459 /**
460  * gst_buffer_get_max_memory:
461  *
462  * Get the maximum amount of memory blocks that a buffer can hold. This is a
463  * compile time constant that can be queried with the function.
464  *
465  * When more memory blocks are added, existing memory blocks will be merged
466  * together to make room for the new block.
467  *
468  * Returns: the maximum amount of memory blocks that a buffer can hold.
469  *
470  * Since: 1.2
471  */
472 guint
473 gst_buffer_get_max_memory (void)
474 {
475   return GST_BUFFER_MEM_MAX;
476 }
477
478 /**
479  * gst_buffer_copy_into:
480  * @dest: a destination #GstBuffer
481  * @src: a source #GstBuffer
482  * @flags: flags indicating what metadata fields should be copied.
483  * @offset: offset to copy from
484  * @size: total size to copy. If -1, all data is copied.
485  *
486  * Copies the information from @src into @dest.
487  *
488  * If @dest already contains memory and @flags contains GST_BUFFER_COPY_MEMORY,
489  * the memory from @src will be appended to @dest.
490  *
491  * @flags indicate which fields will be copied.
492  *
493  * Returns: %TRUE if the copying succeeded, %FALSE otherwise.
494  */
495 gboolean
496 gst_buffer_copy_into (GstBuffer * dest, GstBuffer * src,
497     GstBufferCopyFlags flags, gsize offset, gsize size)
498 {
499   GstMetaItem *walk;
500   gsize bufsize;
501   gboolean region = FALSE;
502
503   g_return_val_if_fail (dest != NULL, FALSE);
504   g_return_val_if_fail (src != NULL, FALSE);
505
506   /* nothing to copy if the buffers are the same */
507   if (G_UNLIKELY (dest == src))
508     return TRUE;
509
510   g_return_val_if_fail (gst_buffer_is_writable (dest), FALSE);
511
512   bufsize = gst_buffer_get_size (src);
513   g_return_val_if_fail (bufsize >= offset, FALSE);
514   if (offset > 0)
515     region = TRUE;
516   if (size == -1)
517     size = bufsize - offset;
518   if (size < bufsize)
519     region = TRUE;
520   g_return_val_if_fail (bufsize >= offset + size, FALSE);
521
522   GST_CAT_LOG (GST_CAT_BUFFER, "copy %p to %p, offset %" G_GSIZE_FORMAT
523       "-%" G_GSIZE_FORMAT "/%" G_GSIZE_FORMAT, src, dest, offset, size,
524       bufsize);
525
526   if (flags & GST_BUFFER_COPY_FLAGS) {
527     /* copy flags */
528     guint flags_mask = ~GST_BUFFER_FLAG_TAG_MEMORY;
529
530     GST_MINI_OBJECT_FLAGS (dest) =
531         (GST_MINI_OBJECT_FLAGS (src) & flags_mask) |
532         (GST_MINI_OBJECT_FLAGS (dest) & ~flags_mask);
533   }
534
535   if (flags & GST_BUFFER_COPY_TIMESTAMPS) {
536     if (offset == 0) {
537       GST_BUFFER_PTS (dest) = GST_BUFFER_PTS (src);
538       GST_BUFFER_DTS (dest) = GST_BUFFER_DTS (src);
539       GST_BUFFER_OFFSET (dest) = GST_BUFFER_OFFSET (src);
540       if (size == bufsize) {
541         GST_BUFFER_DURATION (dest) = GST_BUFFER_DURATION (src);
542         GST_BUFFER_OFFSET_END (dest) = GST_BUFFER_OFFSET_END (src);
543       }
544     } else {
545       GST_BUFFER_PTS (dest) = GST_CLOCK_TIME_NONE;
546       GST_BUFFER_DTS (dest) = GST_CLOCK_TIME_NONE;
547       GST_BUFFER_DURATION (dest) = GST_CLOCK_TIME_NONE;
548       GST_BUFFER_OFFSET (dest) = GST_BUFFER_OFFSET_NONE;
549       GST_BUFFER_OFFSET_END (dest) = GST_BUFFER_OFFSET_NONE;
550     }
551   }
552
553   if (flags & GST_BUFFER_COPY_MEMORY) {
554     gsize skip, left, len, dest_len, i, bsize;
555     gboolean deep;
556
557     deep = flags & GST_BUFFER_COPY_DEEP;
558
559     len = GST_BUFFER_MEM_LEN (src);
560     dest_len = GST_BUFFER_MEM_LEN (dest);
561     left = size;
562     skip = offset;
563
564     /* copy and make regions of the memory */
565     for (i = 0; i < len && left > 0; i++) {
566       GstMemory *mem = GST_BUFFER_MEM_PTR (src, i);
567
568       bsize = gst_memory_get_sizes (mem, NULL, NULL);
569
570       if (bsize <= skip) {
571         /* don't copy buffer */
572         skip -= bsize;
573       } else {
574         GstMemory *newmem = NULL;
575         gsize tocopy;
576
577         tocopy = MIN (bsize - skip, left);
578
579         if (tocopy < bsize && !deep && !GST_MEMORY_IS_NO_SHARE (mem)) {
580           /* we need to clip something */
581           newmem = gst_memory_share (mem, skip, tocopy);
582           if (newmem) {
583             gst_memory_lock (newmem, GST_LOCK_FLAG_EXCLUSIVE);
584             skip = 0;
585           }
586         }
587
588         if (deep || GST_MEMORY_IS_NO_SHARE (mem) || (!newmem && tocopy < bsize)) {
589           /* deep copy or we're not allowed to share this memory
590            * between buffers, always copy then */
591           newmem = gst_memory_copy (mem, skip, tocopy);
592           if (newmem) {
593             gst_memory_lock (newmem, GST_LOCK_FLAG_EXCLUSIVE);
594             skip = 0;
595           }
596         } else if (!newmem) {
597           newmem = _memory_get_exclusive_reference (mem);
598         }
599
600         if (!newmem) {
601           gst_buffer_remove_memory_range (dest, dest_len, -1);
602           return FALSE;
603         }
604
605         _memory_add (dest, -1, newmem);
606         left -= tocopy;
607       }
608     }
609     if (flags & GST_BUFFER_COPY_MERGE) {
610       GstMemory *mem;
611
612       len = GST_BUFFER_MEM_LEN (dest);
613       mem = _get_merged_memory (dest, 0, len);
614       if (!mem) {
615         gst_buffer_remove_memory_range (dest, dest_len, -1);
616         return FALSE;
617       }
618       _replace_memory (dest, len, 0, len, mem);
619     }
620   }
621
622   if (flags & GST_BUFFER_COPY_META) {
623     /* NOTE: GstGLSyncMeta copying relies on the meta
624      *       being copied now, after the buffer data,
625      *       so this has to happen last */
626     for (walk = GST_BUFFER_META (src); walk; walk = walk->next) {
627       GstMeta *meta = &walk->meta;
628       const GstMetaInfo *info = meta->info;
629
630       /* Don't copy memory metas if we only copied part of the buffer, didn't
631        * copy memories or merged memories. In all these cases the memory
632        * structure has changed and the memory meta becomes meaningless.
633        */
634       if ((region || !(flags & GST_BUFFER_COPY_MEMORY)
635               || (flags & GST_BUFFER_COPY_MERGE))
636           && gst_meta_api_type_has_tag (info->api, _gst_meta_tag_memory)) {
637         GST_CAT_DEBUG (GST_CAT_BUFFER,
638             "don't copy memory meta %p of API type %s", meta,
639             g_type_name (info->api));
640       } else if (info->transform_func) {
641         GstMetaTransformCopy copy_data;
642
643         copy_data.region = region;
644         copy_data.offset = offset;
645         copy_data.size = size;
646
647         if (!info->transform_func (dest, meta, src,
648                 _gst_meta_transform_copy, &copy_data)) {
649           GST_CAT_ERROR (GST_CAT_BUFFER,
650               "failed to copy meta %p of API type %s", meta,
651               g_type_name (info->api));
652         }
653       }
654     }
655   }
656
657   return TRUE;
658 }
659
660 static GstBuffer *
661 gst_buffer_copy_with_flags (const GstBuffer * buffer, GstBufferCopyFlags flags)
662 {
663   GstBuffer *copy;
664
665   g_return_val_if_fail (buffer != NULL, NULL);
666
667   /* create a fresh new buffer */
668   copy = gst_buffer_new ();
669
670   /* copy what the 'flags' want from our parent */
671   /* FIXME why we can't pass const to gst_buffer_copy_into() ? */
672   if (!gst_buffer_copy_into (copy, (GstBuffer *) buffer, flags, 0, -1))
673     gst_buffer_replace (&copy, NULL);
674
675   if (copy)
676     GST_BUFFER_FLAG_UNSET (copy, GST_BUFFER_FLAG_TAG_MEMORY);
677
678   return copy;
679 }
680
681 static GstBuffer *
682 _gst_buffer_copy (const GstBuffer * buffer)
683 {
684   return gst_buffer_copy_with_flags (buffer, GST_BUFFER_COPY_ALL);
685 }
686
687 /**
688  * gst_buffer_copy_deep:
689  * @buf: a #GstBuffer.
690  *
691  * Create a copy of the given buffer. This will make a newly allocated
692  * copy of the data the source buffer contains.
693  *
694  * Returns: (transfer full): a new copy of @buf.
695  *
696  * Since: 1.6
697  */
698 GstBuffer *
699 gst_buffer_copy_deep (const GstBuffer * buffer)
700 {
701   return gst_buffer_copy_with_flags (buffer,
702       GST_BUFFER_COPY_ALL | GST_BUFFER_COPY_DEEP);
703 }
704
705 /* the default dispose function revives the buffer and returns it to the
706  * pool when there is a pool */
707 static gboolean
708 _gst_buffer_dispose (GstBuffer * buffer)
709 {
710   GstBufferPool *pool;
711
712   /* no pool, do free */
713   if ((pool = buffer->pool) == NULL)
714     return TRUE;
715
716   /* keep the buffer alive */
717   gst_buffer_ref (buffer);
718   /* return the buffer to the pool */
719   GST_CAT_LOG (GST_CAT_BUFFER, "release %p to pool %p", buffer, pool);
720   gst_buffer_pool_release_buffer (pool, buffer);
721
722   return FALSE;
723 }
724
725 static void
726 _gst_buffer_free (GstBuffer * buffer)
727 {
728   GstMetaItem *walk, *next;
729   guint i, len;
730   gsize msize;
731
732   g_return_if_fail (buffer != NULL);
733
734   GST_CAT_LOG (GST_CAT_BUFFER, "finalize %p", buffer);
735
736   /* free metadata */
737   for (walk = GST_BUFFER_META (buffer); walk; walk = next) {
738     GstMeta *meta = &walk->meta;
739     const GstMetaInfo *info = meta->info;
740
741     /* call free_func if any */
742     if (info->free_func)
743       info->free_func (meta, buffer);
744
745     next = walk->next;
746     /* and free the slice */
747     g_slice_free1 (ITEM_SIZE (info), walk);
748   }
749
750   /* get the size, when unreffing the memory, we could also unref the buffer
751    * itself */
752   msize = GST_BUFFER_SLICE_SIZE (buffer);
753
754   /* free our memory */
755   len = GST_BUFFER_MEM_LEN (buffer);
756   for (i = 0; i < len; i++) {
757     gst_memory_unlock (GST_BUFFER_MEM_PTR (buffer, i), GST_LOCK_FLAG_EXCLUSIVE);
758     gst_mini_object_remove_parent (GST_MINI_OBJECT_CAST (GST_BUFFER_MEM_PTR
759             (buffer, i)), GST_MINI_OBJECT_CAST (buffer));
760     gst_memory_unref (GST_BUFFER_MEM_PTR (buffer, i));
761   }
762
763   /* we set msize to 0 when the buffer is part of the memory block */
764   if (msize) {
765 #ifdef USE_POISONING
766     memset (buffer, 0xff, msize);
767 #endif
768     g_slice_free1 (msize, buffer);
769   } else {
770     gst_memory_unref (GST_BUFFER_BUFMEM (buffer));
771   }
772 }
773
774 static void
775 gst_buffer_init (GstBufferImpl * buffer, gsize size)
776 {
777   gst_mini_object_init (GST_MINI_OBJECT_CAST (buffer), 0, _gst_buffer_type,
778       (GstMiniObjectCopyFunction) _gst_buffer_copy,
779       (GstMiniObjectDisposeFunction) _gst_buffer_dispose,
780       (GstMiniObjectFreeFunction) _gst_buffer_free);
781
782   GST_BUFFER_SLICE_SIZE (buffer) = size;
783
784   GST_BUFFER (buffer)->pool = NULL;
785   GST_BUFFER_PTS (buffer) = GST_CLOCK_TIME_NONE;
786   GST_BUFFER_DTS (buffer) = GST_CLOCK_TIME_NONE;
787   GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
788   GST_BUFFER_OFFSET (buffer) = GST_BUFFER_OFFSET_NONE;
789   GST_BUFFER_OFFSET_END (buffer) = GST_BUFFER_OFFSET_NONE;
790
791   GST_BUFFER_MEM_LEN (buffer) = 0;
792   GST_BUFFER_META (buffer) = NULL;
793 }
794
795 /**
796  * gst_buffer_new:
797  *
798  * Creates a newly allocated buffer without any data.
799  *
800  * MT safe.
801  *
802  * Returns: (transfer full): the new #GstBuffer.
803  */
804 GstBuffer *
805 gst_buffer_new (void)
806 {
807   GstBufferImpl *newbuf;
808
809   newbuf = g_slice_new (GstBufferImpl);
810   GST_CAT_LOG (GST_CAT_BUFFER, "new %p", newbuf);
811
812   gst_buffer_init (newbuf, sizeof (GstBufferImpl));
813
814   return GST_BUFFER_CAST (newbuf);
815 }
816
817 /**
818  * gst_buffer_new_allocate:
819  * @allocator: (transfer none) (allow-none): the #GstAllocator to use, or %NULL to use the
820  *     default allocator
821  * @size: the size in bytes of the new buffer's data.
822  * @params: (transfer none) (allow-none): optional parameters
823  *
824  * Tries to create a newly allocated buffer with data of the given size and
825  * extra parameters from @allocator. If the requested amount of memory can't be
826  * allocated, %NULL will be returned. The allocated buffer memory is not cleared.
827  *
828  * When @allocator is %NULL, the default memory allocator will be used.
829  *
830  * Note that when @size == 0, the buffer will not have memory associated with it.
831  *
832  * MT safe.
833  *
834  * Returns: (transfer full) (nullable): a new #GstBuffer, or %NULL if
835  *     the memory couldn't be allocated.
836  */
837 GstBuffer *
838 gst_buffer_new_allocate (GstAllocator * allocator, gsize size,
839     GstAllocationParams * params)
840 {
841   GstBuffer *newbuf;
842   GstMemory *mem;
843 #if 0
844   guint8 *data;
845   gsize asize;
846 #endif
847
848 #if 1
849   if (size > 0) {
850     mem = gst_allocator_alloc (allocator, size, params);
851     if (G_UNLIKELY (mem == NULL))
852       goto no_memory;
853   } else {
854     mem = NULL;
855   }
856
857   newbuf = gst_buffer_new ();
858
859   if (mem != NULL) {
860     gst_memory_lock (mem, GST_LOCK_FLAG_EXCLUSIVE);
861     _memory_add (newbuf, -1, mem);
862   }
863
864   GST_CAT_LOG (GST_CAT_BUFFER,
865       "new buffer %p of size %" G_GSIZE_FORMAT " from allocator %p", newbuf,
866       size, allocator);
867 #endif
868
869 #if 0
870   asize = sizeof (GstBufferImpl) + size;
871   data = g_slice_alloc (asize);
872   if (G_UNLIKELY (data == NULL))
873     goto no_memory;
874
875   newbuf = GST_BUFFER_CAST (data);
876
877   gst_buffer_init ((GstBufferImpl *) data, asize);
878   if (size > 0) {
879     mem = gst_memory_new_wrapped (0, data + sizeof (GstBufferImpl), NULL,
880         size, 0, size);
881     _memory_add (newbuf, -1, mem, TRUE);
882   }
883 #endif
884
885 #if 0
886   /* allocate memory and buffer, it might be interesting to do this but there
887    * are many complications. We need to keep the memory mapped to access the
888    * buffer fields and the memory for the buffer might be just very slow. We
889    * also need to do some more magic to get the alignment right. */
890   asize = sizeof (GstBufferImpl) + size;
891   mem = gst_allocator_alloc (allocator, asize, align);
892   if (G_UNLIKELY (mem == NULL))
893     goto no_memory;
894
895   /* map the data part and init the buffer in it, set the buffer size to 0 so
896    * that a finalize won't free the buffer */
897   data = gst_memory_map (mem, &asize, NULL, GST_MAP_WRITE);
898   gst_buffer_init ((GstBufferImpl *) data, 0);
899   gst_memory_unmap (mem);
900
901   /* strip off the buffer */
902   gst_memory_resize (mem, sizeof (GstBufferImpl), size);
903
904   newbuf = GST_BUFFER_CAST (data);
905   GST_BUFFER_BUFMEM (newbuf) = mem;
906
907   if (size > 0)
908     _memory_add (newbuf, -1, gst_memory_ref (mem), TRUE);
909 #endif
910   GST_BUFFER_FLAG_UNSET (newbuf, GST_BUFFER_FLAG_TAG_MEMORY);
911
912   return newbuf;
913
914   /* ERRORS */
915 no_memory:
916   {
917     GST_CAT_WARNING (GST_CAT_BUFFER,
918         "failed to allocate %" G_GSIZE_FORMAT " bytes", size);
919     return NULL;
920   }
921 }
922
923 /**
924  * gst_buffer_new_wrapped_full:
925  * @flags: #GstMemoryFlags
926  * @data: (array length=size) (element-type guint8) (transfer none): data to wrap
927  * @maxsize: allocated size of @data
928  * @offset: offset in @data
929  * @size: size of valid data
930  * @user_data: (allow-none): user_data
931  * @notify: (allow-none) (scope async) (closure user_data): called with @user_data when the memory is freed
932  *
933  * Allocate a new buffer that wraps the given memory. @data must point to
934  * @maxsize of memory, the wrapped buffer will have the region from @offset and
935  * @size visible.
936  *
937  * When the buffer is destroyed, @notify will be called with @user_data.
938  *
939  * The prefix/padding must be filled with 0 if @flags contains
940  * #GST_MEMORY_FLAG_ZERO_PREFIXED and #GST_MEMORY_FLAG_ZERO_PADDED respectively.
941  *
942  * Returns: (transfer full): a new #GstBuffer
943  */
944 GstBuffer *
945 gst_buffer_new_wrapped_full (GstMemoryFlags flags, gpointer data,
946     gsize maxsize, gsize offset, gsize size, gpointer user_data,
947     GDestroyNotify notify)
948 {
949   GstMemory *mem;
950   GstBuffer *newbuf;
951
952   newbuf = gst_buffer_new ();
953   mem =
954       gst_memory_new_wrapped (flags, data, maxsize, offset, size, user_data,
955       notify);
956   gst_memory_lock (mem, GST_LOCK_FLAG_EXCLUSIVE);
957   _memory_add (newbuf, -1, mem);
958   GST_BUFFER_FLAG_UNSET (newbuf, GST_BUFFER_FLAG_TAG_MEMORY);
959
960   return newbuf;
961 }
962
963 /**
964  * gst_buffer_new_wrapped:
965  * @data: (array length=size) (element-type guint8) (transfer full): data to wrap
966  * @size: allocated size of @data
967  *
968  * Creates a new buffer that wraps the given @data. The memory will be freed
969  * with g_free and will be marked writable.
970  *
971  * MT safe.
972  *
973  * Returns: (transfer full): a new #GstBuffer
974  */
975 GstBuffer *
976 gst_buffer_new_wrapped (gpointer data, gsize size)
977 {
978   return gst_buffer_new_wrapped_full (0, data, size, 0, size, data, g_free);
979 }
980
981 /**
982  * gst_buffer_new_wrapped_bytes:
983  * @bytes: (transfer none): a #GBytes to wrap
984  *
985  * Creates a new #GstBuffer that wraps the given @bytes. The data inside
986  * @bytes cannot be %NULL and the resulting buffer will be marked as read only.
987  *
988  * MT safe.
989  *
990  * Returns: (transfer full): a new #GstBuffer wrapping @bytes
991  *
992  * Since: 1.16
993  */
994 GstBuffer *
995 gst_buffer_new_wrapped_bytes (GBytes * bytes)
996 {
997   guint8 *bytes_data;
998   gsize size;
999
1000   g_return_val_if_fail (bytes != NULL, NULL);
1001   bytes_data = (guint8 *) g_bytes_get_data (bytes, &size);
1002   g_return_val_if_fail (bytes_data != NULL, NULL);
1003
1004   return gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, bytes_data,
1005       size, 0, size, g_bytes_ref (bytes), (GDestroyNotify) g_bytes_unref);
1006 }
1007
1008 /**
1009  * gst_buffer_n_memory:
1010  * @buffer: a #GstBuffer.
1011  *
1012  * Get the amount of memory blocks that this buffer has. This amount is never
1013  * larger than what gst_buffer_get_max_memory() returns.
1014  *
1015  * Returns: the number of memory blocks this buffer is made of.
1016  */
1017 guint
1018 gst_buffer_n_memory (GstBuffer * buffer)
1019 {
1020   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
1021
1022   return GST_BUFFER_MEM_LEN (buffer);
1023 }
1024
1025 /**
1026  * gst_buffer_prepend_memory:
1027  * @buffer: a #GstBuffer.
1028  * @mem: (transfer full): a #GstMemory.
1029  *
1030  * Prepend the memory block @mem to @buffer. This function takes
1031  * ownership of @mem and thus doesn't increase its refcount.
1032  *
1033  * This function is identical to gst_buffer_insert_memory() with an index of 0.
1034  * See gst_buffer_insert_memory() for more details.
1035  */
1036 void
1037 gst_buffer_prepend_memory (GstBuffer * buffer, GstMemory * mem)
1038 {
1039   gst_buffer_insert_memory (buffer, 0, mem);
1040 }
1041
1042 /**
1043  * gst_buffer_append_memory:
1044  * @buffer: a #GstBuffer.
1045  * @mem: (transfer full): a #GstMemory.
1046  *
1047  * Append the memory block @mem to @buffer. This function takes
1048  * ownership of @mem and thus doesn't increase its refcount.
1049  *
1050  * This function is identical to gst_buffer_insert_memory() with an index of -1.
1051  * See gst_buffer_insert_memory() for more details.
1052  */
1053 void
1054 gst_buffer_append_memory (GstBuffer * buffer, GstMemory * mem)
1055 {
1056   gst_buffer_insert_memory (buffer, -1, mem);
1057 }
1058
1059 /**
1060  * gst_buffer_insert_memory:
1061  * @buffer: a #GstBuffer.
1062  * @idx: the index to add the memory at, or -1 to append it to the end
1063  * @mem: (transfer full): a #GstMemory.
1064  *
1065  * Insert the memory block @mem to @buffer at @idx. This function takes ownership
1066  * of @mem and thus doesn't increase its refcount.
1067  *
1068  * Only gst_buffer_get_max_memory() can be added to a buffer. If more memory is
1069  * added, existing memory blocks will automatically be merged to make room for
1070  * the new memory.
1071  */
1072 void
1073 gst_buffer_insert_memory (GstBuffer * buffer, gint idx, GstMemory * mem)
1074 {
1075   GstMemory *tmp;
1076
1077   g_return_if_fail (GST_IS_BUFFER (buffer));
1078   g_return_if_fail (gst_buffer_is_writable (buffer));
1079   g_return_if_fail (mem != NULL);
1080   g_return_if_fail (idx == -1 ||
1081       (idx >= 0 && idx <= GST_BUFFER_MEM_LEN (buffer)));
1082
1083   tmp = _memory_get_exclusive_reference (mem);
1084   g_return_if_fail (tmp != NULL);
1085   gst_memory_unref (mem);
1086   _memory_add (buffer, idx, tmp);
1087 }
1088
1089 static GstMemory *
1090 _get_mapped (GstBuffer * buffer, guint idx, GstMapInfo * info,
1091     GstMapFlags flags)
1092 {
1093   GstMemory *mem, *mapped;
1094
1095   mem = gst_memory_ref (GST_BUFFER_MEM_PTR (buffer, idx));
1096
1097   mapped = gst_memory_make_mapped (mem, info, flags);
1098
1099   if (mapped != mem) {
1100     /* memory changed, lock new memory */
1101     gst_mini_object_add_parent (GST_MINI_OBJECT_CAST (mapped),
1102         GST_MINI_OBJECT_CAST (buffer));
1103     gst_memory_lock (mapped, GST_LOCK_FLAG_EXCLUSIVE);
1104     GST_BUFFER_MEM_PTR (buffer, idx) = mapped;
1105     /* unlock old memory */
1106     gst_memory_unlock (mem, GST_LOCK_FLAG_EXCLUSIVE);
1107     gst_mini_object_remove_parent (GST_MINI_OBJECT_CAST (mem),
1108         GST_MINI_OBJECT_CAST (buffer));
1109     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY);
1110   }
1111   gst_memory_unref (mem);
1112
1113   return mapped;
1114 }
1115
1116 /**
1117  * gst_buffer_peek_memory:
1118  * @buffer: a #GstBuffer.
1119  * @idx: an index
1120  *
1121  * Get the memory block at @idx in @buffer. The memory block stays valid until
1122  * the memory block in @buffer is removed, replaced or merged, typically with
1123  * any call that modifies the memory in @buffer.
1124  *
1125  * Returns: (transfer none) (nullable): the #GstMemory at @idx.
1126  */
1127 GstMemory *
1128 gst_buffer_peek_memory (GstBuffer * buffer, guint idx)
1129 {
1130   guint len;
1131
1132   g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
1133   len = GST_BUFFER_MEM_LEN (buffer);
1134   g_return_val_if_fail (idx < len, NULL);
1135
1136   return GST_BUFFER_MEM_PTR (buffer, idx);
1137 }
1138
1139 /**
1140  * gst_buffer_get_memory:
1141  * @buffer: a #GstBuffer.
1142  * @idx: an index
1143  *
1144  * Get the memory block at index @idx in @buffer.
1145  *
1146  * Returns: (transfer full) (nullable): a #GstMemory that contains the data of the
1147  * memory block at @idx. Use gst_memory_unref () after usage.
1148  */
1149 GstMemory *
1150 gst_buffer_get_memory (GstBuffer * buffer, guint idx)
1151 {
1152   return gst_buffer_get_memory_range (buffer, idx, 1);
1153 }
1154
1155 /**
1156  * gst_buffer_get_all_memory:
1157  * @buffer: a #GstBuffer.
1158  *
1159  * Get all the memory block in @buffer. The memory blocks will be merged
1160  * into one large #GstMemory.
1161  *
1162  * Returns: (transfer full) (nullable): a #GstMemory that contains the merged memory.
1163  * Use gst_memory_unref () after usage.
1164  */
1165 GstMemory *
1166 gst_buffer_get_all_memory (GstBuffer * buffer)
1167 {
1168   return gst_buffer_get_memory_range (buffer, 0, -1);
1169 }
1170
1171 /**
1172  * gst_buffer_get_memory_range:
1173  * @buffer: a #GstBuffer.
1174  * @idx: an index
1175  * @length: a length
1176  *
1177  * Get @length memory blocks in @buffer starting at @idx. The memory blocks will
1178  * be merged into one large #GstMemory.
1179  *
1180  * If @length is -1, all memory starting from @idx is merged.
1181  *
1182  * Returns: (transfer full) (nullable): a #GstMemory that contains the merged data of @length
1183  *    blocks starting at @idx. Use gst_memory_unref () after usage.
1184  */
1185 GstMemory *
1186 gst_buffer_get_memory_range (GstBuffer * buffer, guint idx, gint length)
1187 {
1188   guint len;
1189
1190   GST_CAT_DEBUG (GST_CAT_BUFFER, "idx %u, length %d", idx, length);
1191
1192   g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
1193   len = GST_BUFFER_MEM_LEN (buffer);
1194   g_return_val_if_fail ((len == 0 && idx == 0 && length == -1) ||
1195       (length == -1 && idx < len) || (length > 0 && length + idx <= len), NULL);
1196
1197   if (length == -1)
1198     length = len - idx;
1199
1200   return _get_merged_memory (buffer, idx, length);
1201 }
1202
1203 /**
1204  * gst_buffer_replace_memory:
1205  * @buffer: a #GstBuffer.
1206  * @idx: an index
1207  * @mem: (transfer full): a #GstMemory
1208  *
1209  * Replaces the memory block at index @idx in @buffer with @mem.
1210  */
1211 void
1212 gst_buffer_replace_memory (GstBuffer * buffer, guint idx, GstMemory * mem)
1213 {
1214   gst_buffer_replace_memory_range (buffer, idx, 1, mem);
1215 }
1216
1217 /**
1218  * gst_buffer_replace_all_memory:
1219  * @buffer: a #GstBuffer.
1220  * @mem: (transfer full): a #GstMemory
1221  *
1222  * Replaces all memory in @buffer with @mem.
1223  */
1224 void
1225 gst_buffer_replace_all_memory (GstBuffer * buffer, GstMemory * mem)
1226 {
1227   gst_buffer_replace_memory_range (buffer, 0, -1, mem);
1228 }
1229
1230 /**
1231  * gst_buffer_replace_memory_range:
1232  * @buffer: a #GstBuffer.
1233  * @idx: an index
1234  * @length: a length should not be 0
1235  * @mem: (transfer full): a #GstMemory
1236  *
1237  * Replaces @length memory blocks in @buffer starting at @idx with @mem.
1238  *
1239  * If @length is -1, all memory starting from @idx will be removed and
1240  * replaced with @mem.
1241  *
1242  * @buffer should be writable.
1243  */
1244 void
1245 gst_buffer_replace_memory_range (GstBuffer * buffer, guint idx, gint length,
1246     GstMemory * mem)
1247 {
1248   guint len;
1249
1250   g_return_if_fail (GST_IS_BUFFER (buffer));
1251   g_return_if_fail (gst_buffer_is_writable (buffer));
1252
1253   GST_CAT_DEBUG (GST_CAT_BUFFER, "idx %u, length %d, %p", idx, length, mem);
1254
1255   len = GST_BUFFER_MEM_LEN (buffer);
1256   g_return_if_fail ((len == 0 && idx == 0 && length == -1) ||
1257       (length == -1 && idx < len) || (length > 0 && length + idx <= len));
1258
1259   if (length == -1)
1260     length = len - idx;
1261
1262   _replace_memory (buffer, len, idx, length, mem);
1263 }
1264
1265 /**
1266  * gst_buffer_remove_memory:
1267  * @buffer: a #GstBuffer.
1268  * @idx: an index
1269  *
1270  * Remove the memory block in @b at index @i.
1271  */
1272 void
1273 gst_buffer_remove_memory (GstBuffer * buffer, guint idx)
1274 {
1275   gst_buffer_remove_memory_range (buffer, idx, 1);
1276 }
1277
1278 /**
1279  * gst_buffer_remove_all_memory:
1280  * @buffer: a #GstBuffer.
1281  *
1282  * Remove all the memory blocks in @buffer.
1283  */
1284 void
1285 gst_buffer_remove_all_memory (GstBuffer * buffer)
1286 {
1287   gst_buffer_remove_memory_range (buffer, 0, -1);
1288 }
1289
1290 /**
1291  * gst_buffer_remove_memory_range:
1292  * @buffer: a #GstBuffer.
1293  * @idx: an index
1294  * @length: a length
1295  *
1296  * Remove @length memory blocks in @buffer starting from @idx.
1297  *
1298  * @length can be -1, in which case all memory starting from @idx is removed.
1299  */
1300 void
1301 gst_buffer_remove_memory_range (GstBuffer * buffer, guint idx, gint length)
1302 {
1303   guint len;
1304
1305   g_return_if_fail (GST_IS_BUFFER (buffer));
1306   g_return_if_fail (gst_buffer_is_writable (buffer));
1307
1308   GST_CAT_DEBUG (GST_CAT_BUFFER, "idx %u, length %d", idx, length);
1309
1310   len = GST_BUFFER_MEM_LEN (buffer);
1311   g_return_if_fail ((len == 0 && idx == 0 && length == -1) ||
1312       (length == -1 && idx < len) || length + idx <= len);
1313
1314   if (length == -1)
1315     length = len - idx;
1316
1317   _replace_memory (buffer, len, idx, length, NULL);
1318 }
1319
1320 /**
1321  * gst_buffer_find_memory:
1322  * @buffer: a #GstBuffer.
1323  * @offset: an offset
1324  * @size: a size
1325  * @idx: (out): pointer to index
1326  * @length: (out): pointer to length
1327  * @skip: (out): pointer to skip
1328  *
1329  * Find the memory blocks that span @size bytes starting from @offset
1330  * in @buffer.
1331  *
1332  * When this function returns %TRUE, @idx will contain the index of the first
1333  * memory block where the byte for @offset can be found and @length contains the
1334  * number of memory blocks containing the @size remaining bytes. @skip contains
1335  * the number of bytes to skip in the memory block at @idx to get to the byte
1336  * for @offset.
1337  *
1338  * @size can be -1 to get all the memory blocks after @idx.
1339  *
1340  * Returns: %TRUE when @size bytes starting from @offset could be found in
1341  * @buffer and @idx, @length and @skip will be filled.
1342  */
1343 gboolean
1344 gst_buffer_find_memory (GstBuffer * buffer, gsize offset, gsize size,
1345     guint * idx, guint * length, gsize * skip)
1346 {
1347   guint i, len, found;
1348
1349   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
1350   g_return_val_if_fail (idx != NULL, FALSE);
1351   g_return_val_if_fail (length != NULL, FALSE);
1352   g_return_val_if_fail (skip != NULL, FALSE);
1353
1354   len = GST_BUFFER_MEM_LEN (buffer);
1355
1356   found = 0;
1357   for (i = 0; i < len; i++) {
1358     GstMemory *mem;
1359     gsize s;
1360
1361     mem = GST_BUFFER_MEM_PTR (buffer, i);
1362     s = gst_memory_get_sizes (mem, NULL, NULL);
1363
1364     if (s <= offset) {
1365       /* block before offset, or empty block, skip */
1366       offset -= s;
1367     } else {
1368       /* block after offset */
1369       if (found == 0) {
1370         /* first block, remember index and offset */
1371         *idx = i;
1372         *skip = offset;
1373         if (size == -1) {
1374           /* return remaining blocks */
1375           *length = len - i;
1376           return TRUE;
1377         }
1378         s -= offset;
1379         offset = 0;
1380       }
1381       /* count the amount of found bytes */
1382       found += s;
1383       if (found >= size) {
1384         /* we have enough bytes */
1385         *length = i - *idx + 1;
1386         return TRUE;
1387       }
1388     }
1389   }
1390   return FALSE;
1391 }
1392
1393 /**
1394  * gst_buffer_is_memory_range_writable:
1395  * @buffer: a #GstBuffer.
1396  * @idx: an index
1397  * @length: a length should not be 0
1398  *
1399  * Check if @length memory blocks in @buffer starting from @idx are writable.
1400  *
1401  * @length can be -1 to check all the memory blocks after @idx.
1402  *
1403  * Note that this function does not check if @buffer is writable, use
1404  * gst_buffer_is_writable() to check that if needed.
1405  *
1406  * Returns: %TRUE if the memory range is writable
1407  *
1408  * Since: 1.4
1409  */
1410 gboolean
1411 gst_buffer_is_memory_range_writable (GstBuffer * buffer, guint idx, gint length)
1412 {
1413   guint i, len;
1414
1415   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
1416
1417   GST_CAT_DEBUG (GST_CAT_BUFFER, "idx %u, length %d", idx, length);
1418
1419   len = GST_BUFFER_MEM_LEN (buffer);
1420   g_return_val_if_fail ((len == 0 && idx == 0 && length == -1) ||
1421       (length == -1 && idx < len) || (length > 0 && length + idx <= len),
1422       FALSE);
1423
1424   if (length == -1)
1425     len -= idx;
1426   else
1427     len = length;
1428
1429   for (i = 0; i < len; i++) {
1430     if (!gst_memory_is_writable (GST_BUFFER_MEM_PTR (buffer, i + idx)))
1431       return FALSE;
1432   }
1433   return TRUE;
1434 }
1435
1436 /**
1437  * gst_buffer_is_all_memory_writable:
1438  * @buffer: a #GstBuffer.
1439  *
1440  * Check if all memory blocks in @buffer are writable.
1441  *
1442  * Note that this function does not check if @buffer is writable, use
1443  * gst_buffer_is_writable() to check that if needed.
1444  *
1445  * Returns: %TRUE if all memory blocks in @buffer are writable
1446  *
1447  * Since: 1.4
1448  */
1449 gboolean
1450 gst_buffer_is_all_memory_writable (GstBuffer * buffer)
1451 {
1452   return gst_buffer_is_memory_range_writable (buffer, 0, -1);
1453 }
1454
1455 /**
1456  * gst_buffer_get_sizes:
1457  * @buffer: a #GstBuffer.
1458  * @offset: (out) (allow-none): a pointer to the offset
1459  * @maxsize: (out) (allow-none): a pointer to the maxsize
1460  *
1461  * Get the total size of the memory blocks in @b.
1462  *
1463  * When not %NULL, @offset will contain the offset of the data in the
1464  * first memory block in @buffer and @maxsize will contain the sum of
1465  * the size and @offset and the amount of extra padding on the last
1466  * memory block.  @offset and @maxsize can be used to resize the
1467  * buffer memory blocks with gst_buffer_resize().
1468  *
1469  * Returns: total size of the memory blocks in @buffer.
1470  */
1471 gsize
1472 gst_buffer_get_sizes (GstBuffer * buffer, gsize * offset, gsize * maxsize)
1473 {
1474   return gst_buffer_get_sizes_range (buffer, 0, -1, offset, maxsize);
1475 }
1476
1477 /**
1478  * gst_buffer_get_size:
1479  * @buffer: a #GstBuffer.
1480  *
1481  * Get the total size of the memory blocks in @buffer.
1482  *
1483  * Returns: total size of the memory blocks in @buffer.
1484  */
1485 gsize
1486 gst_buffer_get_size (GstBuffer * buffer)
1487 {
1488   return gst_buffer_get_sizes_range (buffer, 0, -1, NULL, NULL);
1489 }
1490
1491 /**
1492  * gst_buffer_get_sizes_range:
1493  * @buffer: a #GstBuffer.
1494  * @idx: an index
1495  * @length: a length
1496  * @offset: (out) (allow-none): a pointer to the offset
1497  * @maxsize: (out) (allow-none): a pointer to the maxsize
1498  *
1499  * Get the total size of @length memory blocks stating from @idx in @buffer.
1500  *
1501  * When not %NULL, @offset will contain the offset of the data in the
1502  * memory block in @buffer at @idx and @maxsize will contain the sum of the size
1503  * and @offset and the amount of extra padding on the memory block at @idx +
1504  * @length -1.
1505  * @offset and @maxsize can be used to resize the buffer memory blocks with
1506  * gst_buffer_resize_range().
1507  *
1508  * Returns: total size of @length memory blocks starting at @idx in @buffer.
1509  */
1510 gsize
1511 gst_buffer_get_sizes_range (GstBuffer * buffer, guint idx, gint length,
1512     gsize * offset, gsize * maxsize)
1513 {
1514   guint len;
1515   gsize size;
1516   GstMemory *mem;
1517
1518   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
1519   len = GST_BUFFER_MEM_LEN (buffer);
1520   g_return_val_if_fail ((len == 0 && idx == 0 && length == -1) ||
1521       (length == -1 && idx < len) || (length + idx <= len), 0);
1522
1523   if (length == -1)
1524     length = len - idx;
1525
1526   if (G_LIKELY (length == 1)) {
1527     /* common case */
1528     mem = GST_BUFFER_MEM_PTR (buffer, idx);
1529     size = gst_memory_get_sizes (mem, offset, maxsize);
1530   } else {
1531     guint i, end;
1532     gsize extra, offs;
1533
1534     end = idx + length;
1535     size = offs = extra = 0;
1536     for (i = idx; i < end; i++) {
1537       gsize s, o, ms;
1538
1539       mem = GST_BUFFER_MEM_PTR (buffer, i);
1540       s = gst_memory_get_sizes (mem, &o, &ms);
1541
1542       if (s) {
1543         if (size == 0)
1544           /* first size, take accumulated data before as the offset */
1545           offs = extra + o;
1546         /* add sizes */
1547         size += s;
1548         /* save the amount of data after this block */
1549         extra = ms - (o + s);
1550       } else {
1551         /* empty block, add as extra */
1552         extra += ms;
1553       }
1554     }
1555     if (offset)
1556       *offset = offs;
1557     if (maxsize)
1558       *maxsize = offs + size + extra;
1559   }
1560   return size;
1561 }
1562
1563 /**
1564  * gst_buffer_resize:
1565  * @buffer: a #GstBuffer.
1566  * @offset: the offset adjustment
1567  * @size: the new size or -1 to just adjust the offset
1568  *
1569  * Set the offset and total size of the memory blocks in @buffer.
1570  */
1571 void
1572 gst_buffer_resize (GstBuffer * buffer, gssize offset, gssize size)
1573 {
1574   gst_buffer_resize_range (buffer, 0, -1, offset, size);
1575 }
1576
1577 /**
1578  * gst_buffer_set_size:
1579  * @buffer: a #GstBuffer.
1580  * @size: the new size
1581  *
1582  * Set the total size of the memory blocks in @buffer.
1583  */
1584 void
1585 gst_buffer_set_size (GstBuffer * buffer, gssize size)
1586 {
1587   gst_buffer_resize_range (buffer, 0, -1, 0, size);
1588 }
1589
1590 /**
1591  * gst_buffer_resize_range:
1592  * @buffer: a #GstBuffer.
1593  * @idx: an index
1594  * @length: a length
1595  * @offset: the offset adjustment
1596  * @size: the new size or -1 to just adjust the offset
1597  *
1598  * Set the total size of the @length memory blocks starting at @idx in
1599  * @buffer
1600  *
1601  * Returns: %TRUE if resizing succeeded, %FALSE otherwise.
1602  */
1603 gboolean
1604 gst_buffer_resize_range (GstBuffer * buffer, guint idx, gint length,
1605     gssize offset, gssize size)
1606 {
1607   guint i, len, end;
1608   gsize bsize, bufsize, bufoffs, bufmax;
1609
1610   g_return_val_if_fail (gst_buffer_is_writable (buffer), FALSE);
1611   g_return_val_if_fail (size >= -1, FALSE);
1612
1613   len = GST_BUFFER_MEM_LEN (buffer);
1614   g_return_val_if_fail ((len == 0 && idx == 0 && length == -1) ||
1615       (length == -1 && idx < len) || (length + idx <= len), FALSE);
1616
1617   if (length == -1)
1618     length = len - idx;
1619
1620   bufsize = gst_buffer_get_sizes_range (buffer, idx, length, &bufoffs, &bufmax);
1621
1622   GST_CAT_LOG (GST_CAT_BUFFER, "trim %p %" G_GSSIZE_FORMAT "-%" G_GSSIZE_FORMAT
1623       " size:%" G_GSIZE_FORMAT " offs:%" G_GSIZE_FORMAT " max:%"
1624       G_GSIZE_FORMAT, buffer, offset, size, bufsize, bufoffs, bufmax);
1625
1626   /* we can't go back further than the current offset or past the end of the
1627    * buffer */
1628   g_return_val_if_fail ((offset < 0 && bufoffs >= -offset) || (offset >= 0
1629           && bufoffs + offset <= bufmax), FALSE);
1630   if (size == -1) {
1631     g_return_val_if_fail (bufsize >= offset, FALSE);
1632     size = bufsize - offset;
1633   }
1634   g_return_val_if_fail (bufmax >= bufoffs + offset + size, FALSE);
1635
1636   /* no change */
1637   if (offset == 0 && size == bufsize)
1638     return TRUE;
1639
1640   end = idx + length;
1641   /* copy and trim */
1642   for (i = idx; i < end; i++) {
1643     GstMemory *mem;
1644     gsize left, noffs;
1645
1646     mem = GST_BUFFER_MEM_PTR (buffer, i);
1647     bsize = gst_memory_get_sizes (mem, NULL, NULL);
1648
1649     noffs = 0;
1650     /* last buffer always gets resized to the remaining size */
1651     if (i + 1 == end)
1652       left = size;
1653     /* shrink buffers before the offset */
1654     else if ((gssize) bsize <= offset) {
1655       left = 0;
1656       noffs = offset - bsize;
1657       offset = 0;
1658     }
1659     /* clip other buffers */
1660     else
1661       left = MIN (bsize - offset, size);
1662
1663     if (offset != 0 || left != bsize) {
1664       if (gst_memory_is_writable (mem)) {
1665         gst_memory_resize (mem, offset, left);
1666       } else {
1667         GstMemory *newmem = NULL;
1668
1669         if (!GST_MEMORY_IS_NO_SHARE (mem))
1670           newmem = gst_memory_share (mem, offset, left);
1671
1672         if (!newmem)
1673           newmem = gst_memory_copy (mem, offset, left);
1674
1675         if (newmem == NULL)
1676           return FALSE;
1677
1678         gst_mini_object_add_parent (GST_MINI_OBJECT_CAST (newmem),
1679             GST_MINI_OBJECT_CAST (buffer));
1680         gst_memory_lock (newmem, GST_LOCK_FLAG_EXCLUSIVE);
1681         GST_BUFFER_MEM_PTR (buffer, i) = newmem;
1682         gst_memory_unlock (mem, GST_LOCK_FLAG_EXCLUSIVE);
1683         gst_mini_object_remove_parent (GST_MINI_OBJECT_CAST (mem),
1684             GST_MINI_OBJECT_CAST (buffer));
1685         gst_memory_unref (mem);
1686
1687         GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY);
1688       }
1689     }
1690
1691     offset = noffs;
1692     size -= left;
1693   }
1694
1695   return TRUE;
1696 }
1697
1698 /**
1699  * gst_buffer_map:
1700  * @buffer: a #GstBuffer.
1701  * @info: (out): info about the mapping
1702  * @flags: flags for the mapping
1703  *
1704  * This function fills @info with the #GstMapInfo of all merged memory
1705  * blocks in @buffer.
1706  *
1707  * @flags describe the desired access of the memory. When @flags is
1708  * #GST_MAP_WRITE, @buffer should be writable (as returned from
1709  * gst_buffer_is_writable()).
1710  *
1711  * When @buffer is writable but the memory isn't, a writable copy will
1712  * automatically be created and returned. The readonly copy of the
1713  * buffer memory will then also be replaced with this writable copy.
1714  *
1715  * The memory in @info should be unmapped with gst_buffer_unmap() after
1716  * usage.
1717  *
1718  * Returns: %TRUE if the map succeeded and @info contains valid data.
1719  */
1720 gboolean
1721 gst_buffer_map (GstBuffer * buffer, GstMapInfo * info, GstMapFlags flags)
1722 {
1723   return gst_buffer_map_range (buffer, 0, -1, info, flags);
1724 }
1725
1726 /**
1727  * gst_buffer_map_range:
1728  * @buffer: a #GstBuffer.
1729  * @idx: an index
1730  * @length: a length
1731  * @info: (out): info about the mapping
1732  * @flags: flags for the mapping
1733  *
1734  * This function fills @info with the #GstMapInfo of @length merged memory blocks
1735  * starting at @idx in @buffer. When @length is -1, all memory blocks starting
1736  * from @idx are merged and mapped.
1737  *
1738  * @flags describe the desired access of the memory. When @flags is
1739  * #GST_MAP_WRITE, @buffer should be writable (as returned from
1740  * gst_buffer_is_writable()).
1741  *
1742  * When @buffer is writable but the memory isn't, a writable copy will
1743  * automatically be created and returned. The readonly copy of the buffer memory
1744  * will then also be replaced with this writable copy.
1745  *
1746  * The memory in @info should be unmapped with gst_buffer_unmap() after usage.
1747  *
1748  * Returns: %TRUE if the map succeeded and @info contains valid
1749  * data.
1750  */
1751 gboolean
1752 gst_buffer_map_range (GstBuffer * buffer, guint idx, gint length,
1753     GstMapInfo * info, GstMapFlags flags)
1754 {
1755   GstMemory *mem, *nmem;
1756   gboolean write, writable;
1757   gsize len;
1758
1759   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
1760   g_return_val_if_fail (info != NULL, FALSE);
1761   len = GST_BUFFER_MEM_LEN (buffer);
1762   g_return_val_if_fail ((len == 0 && idx == 0 && length == -1) ||
1763       (length == -1 && idx < len) || (length > 0
1764           && length + idx <= len), FALSE);
1765
1766   GST_CAT_LOG (GST_CAT_BUFFER, "buffer %p, idx %u, length %d, flags %04x",
1767       buffer, idx, length, flags);
1768
1769   write = (flags & GST_MAP_WRITE) != 0;
1770   writable = gst_buffer_is_writable (buffer);
1771
1772   /* check if we can write when asked for write access */
1773   if (G_UNLIKELY (write && !writable))
1774     goto not_writable;
1775
1776   if (length == -1)
1777     length = len - idx;
1778
1779   mem = _get_merged_memory (buffer, idx, length);
1780   if (G_UNLIKELY (mem == NULL))
1781     goto no_memory;
1782
1783   /* now try to map */
1784   nmem = gst_memory_make_mapped (mem, info, flags);
1785   if (G_UNLIKELY (nmem == NULL))
1786     goto cannot_map;
1787
1788   /* if we merged or when the map returned a different memory, we try to replace
1789    * the memory in the buffer */
1790   if (G_UNLIKELY (length > 1 || nmem != mem)) {
1791     /* if the buffer is writable, replace the memory */
1792     if (writable) {
1793       _replace_memory (buffer, len, idx, length, gst_memory_ref (nmem));
1794     } else {
1795       if (len > 1) {
1796         GST_CAT_DEBUG (GST_CAT_PERFORMANCE,
1797             "temporary mapping for memory %p in buffer %p", nmem, buffer);
1798       }
1799     }
1800   }
1801   return TRUE;
1802
1803   /* ERROR */
1804 not_writable:
1805   {
1806     GST_WARNING_OBJECT (buffer, "write map requested on non-writable buffer");
1807     g_critical ("write map requested on non-writable buffer");
1808     memset (info, 0, sizeof (GstMapInfo));
1809     return FALSE;
1810   }
1811 no_memory:
1812   {
1813     /* empty buffer, we need to return NULL */
1814     GST_DEBUG_OBJECT (buffer, "can't get buffer memory");
1815     memset (info, 0, sizeof (GstMapInfo));
1816     return TRUE;
1817   }
1818 cannot_map:
1819   {
1820     GST_DEBUG_OBJECT (buffer, "cannot map memory");
1821     memset (info, 0, sizeof (GstMapInfo));
1822     return FALSE;
1823   }
1824 }
1825
1826 /**
1827  * gst_buffer_unmap:
1828  * @buffer: a #GstBuffer.
1829  * @info: a #GstMapInfo
1830  *
1831  * Release the memory previously mapped with gst_buffer_map().
1832  */
1833 void
1834 gst_buffer_unmap (GstBuffer * buffer, GstMapInfo * info)
1835 {
1836   g_return_if_fail (GST_IS_BUFFER (buffer));
1837   g_return_if_fail (info != NULL);
1838
1839   /* we need to check for NULL, it is possible that we tried to map a buffer
1840    * without memory and we should be able to unmap that fine */
1841   if (G_LIKELY (info->memory)) {
1842     gst_memory_unmap (info->memory, info);
1843     gst_memory_unref (info->memory);
1844   }
1845 }
1846
1847 /**
1848  * gst_buffer_fill:
1849  * @buffer: a #GstBuffer.
1850  * @offset: the offset to fill
1851  * @src: (array length=size) (element-type guint8): the source address
1852  * @size: the size to fill
1853  *
1854  * Copy @size bytes from @src to @buffer at @offset.
1855  *
1856  * Returns: The amount of bytes copied. This value can be lower than @size
1857  *    when @buffer did not contain enough data.
1858  */
1859 gsize
1860 gst_buffer_fill (GstBuffer * buffer, gsize offset, gconstpointer src,
1861     gsize size)
1862 {
1863   gsize i, len, left;
1864   const guint8 *ptr = src;
1865
1866   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
1867   g_return_val_if_fail (gst_buffer_is_writable (buffer), 0);
1868   g_return_val_if_fail (src != NULL || size == 0, 0);
1869
1870   GST_CAT_LOG (GST_CAT_BUFFER,
1871       "buffer %p, offset %" G_GSIZE_FORMAT ", size %" G_GSIZE_FORMAT, buffer,
1872       offset, size);
1873
1874   len = GST_BUFFER_MEM_LEN (buffer);
1875   left = size;
1876
1877   for (i = 0; i < len && left > 0; i++) {
1878     GstMapInfo info;
1879     gsize tocopy;
1880     GstMemory *mem;
1881
1882     mem = _get_mapped (buffer, i, &info, GST_MAP_WRITE);
1883     if (info.size > offset) {
1884       /* we have enough */
1885       tocopy = MIN (info.size - offset, left);
1886       memcpy ((guint8 *) info.data + offset, ptr, tocopy);
1887       left -= tocopy;
1888       ptr += tocopy;
1889       offset = 0;
1890     } else {
1891       /* offset past buffer, skip */
1892       offset -= info.size;
1893     }
1894     gst_memory_unmap (mem, &info);
1895   }
1896   return size - left;
1897 }
1898
1899 /**
1900  * gst_buffer_extract:
1901  * @buffer: a #GstBuffer.
1902  * @offset: the offset to extract
1903  * @dest: (out caller-allocates) (array length=size) (element-type guint8):
1904  *     the destination address
1905  * @size: the size to extract
1906  *
1907  * Copy @size bytes starting from @offset in @buffer to @dest.
1908  *
1909  * Returns: The amount of bytes extracted. This value can be lower than @size
1910  *    when @buffer did not contain enough data.
1911  */
1912 gsize
1913 gst_buffer_extract (GstBuffer * buffer, gsize offset, gpointer dest, gsize size)
1914 {
1915   gsize i, len, left;
1916   guint8 *ptr = dest;
1917
1918   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
1919   g_return_val_if_fail (dest != NULL, 0);
1920
1921   GST_CAT_LOG (GST_CAT_BUFFER,
1922       "buffer %p, offset %" G_GSIZE_FORMAT ", size %" G_GSIZE_FORMAT, buffer,
1923       offset, size);
1924
1925   len = GST_BUFFER_MEM_LEN (buffer);
1926   left = size;
1927
1928   for (i = 0; i < len && left > 0; i++) {
1929     GstMapInfo info;
1930     gsize tocopy;
1931     GstMemory *mem;
1932
1933     mem = _get_mapped (buffer, i, &info, GST_MAP_READ);
1934     if (info.size > offset) {
1935       /* we have enough */
1936       tocopy = MIN (info.size - offset, left);
1937       memcpy (ptr, (guint8 *) info.data + offset, tocopy);
1938       left -= tocopy;
1939       ptr += tocopy;
1940       offset = 0;
1941     } else {
1942       /* offset past buffer, skip */
1943       offset -= info.size;
1944     }
1945     gst_memory_unmap (mem, &info);
1946   }
1947   return size - left;
1948 }
1949
1950 /**
1951  * gst_buffer_memcmp:
1952  * @buffer: a #GstBuffer.
1953  * @offset: the offset in @buffer
1954  * @mem: (array length=size) (element-type guint8): the memory to compare
1955  * @size: the size to compare
1956  *
1957  * Compare @size bytes starting from @offset in @buffer with the memory in @mem.
1958  *
1959  * Returns: 0 if the memory is equal.
1960  */
1961 gint
1962 gst_buffer_memcmp (GstBuffer * buffer, gsize offset, gconstpointer mem,
1963     gsize size)
1964 {
1965   gsize i, len;
1966   const guint8 *ptr = mem;
1967   gint res = 0;
1968
1969   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
1970   g_return_val_if_fail (mem != NULL, 0);
1971
1972   GST_CAT_LOG (GST_CAT_BUFFER,
1973       "buffer %p, offset %" G_GSIZE_FORMAT ", size %" G_GSIZE_FORMAT, buffer,
1974       offset, size);
1975
1976   if (G_UNLIKELY (gst_buffer_get_size (buffer) < offset + size))
1977     return -1;
1978
1979   len = GST_BUFFER_MEM_LEN (buffer);
1980
1981   for (i = 0; i < len && size > 0 && res == 0; i++) {
1982     GstMapInfo info;
1983     gsize tocmp;
1984     GstMemory *mem;
1985
1986     mem = _get_mapped (buffer, i, &info, GST_MAP_READ);
1987     if (info.size > offset) {
1988       /* we have enough */
1989       tocmp = MIN (info.size - offset, size);
1990       res = memcmp (ptr, (guint8 *) info.data + offset, tocmp);
1991       size -= tocmp;
1992       ptr += tocmp;
1993       offset = 0;
1994     } else {
1995       /* offset past buffer, skip */
1996       offset -= info.size;
1997     }
1998     gst_memory_unmap (mem, &info);
1999   }
2000   return res;
2001 }
2002
2003 /**
2004  * gst_buffer_memset:
2005  * @buffer: a #GstBuffer.
2006  * @offset: the offset in @buffer
2007  * @val: the value to set
2008  * @size: the size to set
2009  *
2010  * Fill @buf with @size bytes with @val starting from @offset.
2011  *
2012  * Returns: The amount of bytes filled. This value can be lower than @size
2013  *    when @buffer did not contain enough data.
2014  */
2015 gsize
2016 gst_buffer_memset (GstBuffer * buffer, gsize offset, guint8 val, gsize size)
2017 {
2018   gsize i, len, left;
2019
2020   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
2021   g_return_val_if_fail (gst_buffer_is_writable (buffer), 0);
2022
2023   GST_CAT_LOG (GST_CAT_BUFFER,
2024       "buffer %p, offset %" G_GSIZE_FORMAT ", val %02x, size %" G_GSIZE_FORMAT,
2025       buffer, offset, val, size);
2026
2027   len = GST_BUFFER_MEM_LEN (buffer);
2028   left = size;
2029
2030   for (i = 0; i < len && left > 0; i++) {
2031     GstMapInfo info;
2032     gsize toset;
2033     GstMemory *mem;
2034
2035     mem = _get_mapped (buffer, i, &info, GST_MAP_WRITE);
2036     if (info.size > offset) {
2037       /* we have enough */
2038       toset = MIN (info.size - offset, left);
2039       memset ((guint8 *) info.data + offset, val, toset);
2040       left -= toset;
2041       offset = 0;
2042     } else {
2043       /* offset past buffer, skip */
2044       offset -= info.size;
2045     }
2046     gst_memory_unmap (mem, &info);
2047   }
2048   return size - left;
2049 }
2050
2051 /**
2052  * gst_buffer_copy_region:
2053  * @parent: a #GstBuffer.
2054  * @flags: the #GstBufferCopyFlags
2055  * @offset: the offset into parent #GstBuffer at which the new sub-buffer
2056  *          begins.
2057  * @size: the size of the new #GstBuffer sub-buffer, in bytes. If -1, all
2058  *        data is copied.
2059  *
2060  * Creates a sub-buffer from @parent at @offset and @size.
2061  * This sub-buffer uses the actual memory space of the parent buffer.
2062  * This function will copy the offset and timestamp fields when the
2063  * offset is 0. If not, they will be set to #GST_CLOCK_TIME_NONE and
2064  * #GST_BUFFER_OFFSET_NONE.
2065  * If @offset equals 0 and @size equals the total size of @buffer, the
2066  * duration and offset end fields are also copied. If not they will be set
2067  * to #GST_CLOCK_TIME_NONE and #GST_BUFFER_OFFSET_NONE.
2068  *
2069  * MT safe.
2070  *
2071  * Returns: (transfer full): the new #GstBuffer or %NULL if the arguments were
2072  *     invalid.
2073  */
2074 GstBuffer *
2075 gst_buffer_copy_region (GstBuffer * buffer, GstBufferCopyFlags flags,
2076     gsize offset, gsize size)
2077 {
2078   GstBuffer *copy;
2079
2080   g_return_val_if_fail (buffer != NULL, NULL);
2081
2082   /* create the new buffer */
2083   copy = gst_buffer_new ();
2084
2085   GST_CAT_LOG (GST_CAT_BUFFER, "new region copy %p of %p %" G_GSIZE_FORMAT
2086       "-%" G_GSIZE_FORMAT, copy, buffer, offset, size);
2087
2088   if (!gst_buffer_copy_into (copy, buffer, flags, offset, size))
2089     gst_buffer_replace (&copy, NULL);
2090
2091   return copy;
2092 }
2093
2094 /**
2095  * gst_buffer_append:
2096  * @buf1: (transfer full): the first source #GstBuffer to append.
2097  * @buf2: (transfer full): the second source #GstBuffer to append.
2098  *
2099  * Append all the memory from @buf2 to @buf1. The result buffer will contain a
2100  * concatenation of the memory of @buf1 and @buf2.
2101  *
2102  * Returns: (transfer full): the new #GstBuffer that contains the memory
2103  *     of the two source buffers.
2104  */
2105 GstBuffer *
2106 gst_buffer_append (GstBuffer * buf1, GstBuffer * buf2)
2107 {
2108   return gst_buffer_append_region (buf1, buf2, 0, -1);
2109 }
2110
2111 /**
2112  * gst_buffer_append_region:
2113  * @buf1: (transfer full): the first source #GstBuffer to append.
2114  * @buf2: (transfer full): the second source #GstBuffer to append.
2115  * @offset: the offset in @buf2
2116  * @size: the size or -1 of @buf2
2117  *
2118  * Append @size bytes at @offset from @buf2 to @buf1. The result buffer will
2119  * contain a concatenation of the memory of @buf1 and the requested region of
2120  * @buf2.
2121  *
2122  * Returns: (transfer full): the new #GstBuffer that contains the memory
2123  *     of the two source buffers.
2124  */
2125 GstBuffer *
2126 gst_buffer_append_region (GstBuffer * buf1, GstBuffer * buf2, gssize offset,
2127     gssize size)
2128 {
2129   gsize i, len;
2130
2131   g_return_val_if_fail (GST_IS_BUFFER (buf1), NULL);
2132   g_return_val_if_fail (GST_IS_BUFFER (buf2), NULL);
2133
2134   buf1 = gst_buffer_make_writable (buf1);
2135   buf2 = gst_buffer_make_writable (buf2);
2136
2137   gst_buffer_resize (buf2, offset, size);
2138
2139   len = GST_BUFFER_MEM_LEN (buf2);
2140   for (i = 0; i < len; i++) {
2141     GstMemory *mem;
2142
2143     mem = GST_BUFFER_MEM_PTR (buf2, i);
2144     gst_mini_object_remove_parent (GST_MINI_OBJECT_CAST (mem),
2145         GST_MINI_OBJECT_CAST (buf2));
2146     GST_BUFFER_MEM_PTR (buf2, i) = NULL;
2147     _memory_add (buf1, -1, mem);
2148   }
2149
2150   GST_BUFFER_MEM_LEN (buf2) = 0;
2151   GST_BUFFER_FLAG_SET (buf2, GST_BUFFER_FLAG_TAG_MEMORY);
2152   gst_buffer_unref (buf2);
2153
2154   return buf1;
2155 }
2156
2157 /**
2158  * gst_buffer_get_meta:
2159  * @buffer: a #GstBuffer
2160  * @api: the #GType of an API
2161  *
2162  * Get the metadata for @api on buffer. When there is no such metadata, %NULL is
2163  * returned. If multiple metadata with the given @api are attached to this
2164  * buffer only the first one is returned.  To handle multiple metadata with a
2165  * given API use gst_buffer_iterate_meta() or gst_buffer_foreach_meta() instead
2166  * and check the meta->info.api member for the API type.
2167  *
2168  * Returns: (transfer none) (nullable): the metadata for @api on
2169  * @buffer.
2170  */
2171 GstMeta *
2172 gst_buffer_get_meta (GstBuffer * buffer, GType api)
2173 {
2174   GstMetaItem *item;
2175   GstMeta *result = NULL;
2176
2177   g_return_val_if_fail (buffer != NULL, NULL);
2178   g_return_val_if_fail (api != 0, NULL);
2179
2180   /* find GstMeta of the requested API */
2181   for (item = GST_BUFFER_META (buffer); item; item = item->next) {
2182     GstMeta *meta = &item->meta;
2183     if (meta->info->api == api) {
2184       result = meta;
2185       break;
2186     }
2187   }
2188   return result;
2189 }
2190
2191 /**
2192  * gst_buffer_get_n_meta:
2193  * @buffer: a #GstBuffer
2194  * @api_type: the #GType of an API
2195  *
2196  * Returns: number of metas of type @api_type on @buffer.
2197  *
2198  * Since: 1.14
2199  */
2200 guint
2201 gst_buffer_get_n_meta (GstBuffer * buffer, GType api_type)
2202 {
2203   gpointer state = NULL;
2204   GstMeta *meta;
2205   guint n = 0;
2206
2207   while ((meta = gst_buffer_iterate_meta_filtered (buffer, &state, api_type)))
2208     ++n;
2209
2210   return n;
2211 }
2212
2213 /**
2214  * gst_buffer_add_meta:
2215  * @buffer: a #GstBuffer
2216  * @info: a #GstMetaInfo
2217  * @params: params for @info
2218  *
2219  * Add metadata for @info to @buffer using the parameters in @params.
2220  *
2221  * Returns: (transfer none) (nullable): the metadata for the api in @info on @buffer.
2222  */
2223 GstMeta *
2224 gst_buffer_add_meta (GstBuffer * buffer, const GstMetaInfo * info,
2225     gpointer params)
2226 {
2227   GstMetaItem *item;
2228   GstMeta *result = NULL;
2229   gsize size;
2230
2231   g_return_val_if_fail (buffer != NULL, NULL);
2232   g_return_val_if_fail (info != NULL, NULL);
2233   g_return_val_if_fail (gst_buffer_is_writable (buffer), NULL);
2234
2235   /* create a new slice */
2236   size = ITEM_SIZE (info);
2237   /* We warn in gst_meta_register() about metas without
2238    * init function but let's play safe here and prevent
2239    * uninitialized memory
2240    */
2241   if (!info->init_func)
2242     item = g_slice_alloc0 (size);
2243   else
2244     item = g_slice_alloc (size);
2245   result = &item->meta;
2246   result->info = info;
2247   result->flags = GST_META_FLAG_NONE;
2248   GST_CAT_DEBUG (GST_CAT_BUFFER,
2249       "alloc metadata %p (%s) of size %" G_GSIZE_FORMAT, result,
2250       g_type_name (info->type), info->size);
2251
2252   /* call the init_func when needed */
2253   if (info->init_func)
2254     if (!info->init_func (result, params, buffer))
2255       goto init_failed;
2256
2257   /* and add to the list of metadata */
2258   item->next = GST_BUFFER_META (buffer);
2259   GST_BUFFER_META (buffer) = item;
2260
2261   return result;
2262
2263 init_failed:
2264   {
2265     g_slice_free1 (size, item);
2266     return NULL;
2267   }
2268 }
2269
2270 /**
2271  * gst_buffer_remove_meta:
2272  * @buffer: a #GstBuffer
2273  * @meta: a #GstMeta
2274  *
2275  * Remove the metadata for @meta on @buffer.
2276  *
2277  * Returns: %TRUE if the metadata existed and was removed, %FALSE if no such
2278  * metadata was on @buffer.
2279  */
2280 gboolean
2281 gst_buffer_remove_meta (GstBuffer * buffer, GstMeta * meta)
2282 {
2283   GstMetaItem *walk, *prev;
2284
2285   g_return_val_if_fail (buffer != NULL, FALSE);
2286   g_return_val_if_fail (meta != NULL, FALSE);
2287   g_return_val_if_fail (gst_buffer_is_writable (buffer), FALSE);
2288   g_return_val_if_fail (!GST_META_FLAG_IS_SET (meta, GST_META_FLAG_LOCKED),
2289       FALSE);
2290
2291   /* find the metadata and delete */
2292   prev = GST_BUFFER_META (buffer);
2293   for (walk = prev; walk; walk = walk->next) {
2294     GstMeta *m = &walk->meta;
2295     if (m == meta) {
2296       const GstMetaInfo *info = meta->info;
2297
2298       /* remove from list */
2299       if (GST_BUFFER_META (buffer) == walk)
2300         GST_BUFFER_META (buffer) = walk->next;
2301       else
2302         prev->next = walk->next;
2303       /* call free_func if any */
2304       if (info->free_func)
2305         info->free_func (m, buffer);
2306
2307       /* and free the slice */
2308       g_slice_free1 (ITEM_SIZE (info), walk);
2309       break;
2310     }
2311     prev = walk;
2312   }
2313   return walk != NULL;
2314 }
2315
2316 /**
2317  * gst_buffer_iterate_meta: (skip)
2318  * @buffer: a #GstBuffer
2319  * @state: (out caller-allocates): an opaque state pointer
2320  *
2321  * Retrieve the next #GstMeta after @current. If @state points
2322  * to %NULL, the first metadata is returned.
2323  *
2324  * @state will be updated with an opaque state pointer
2325  *
2326  * Returns: (transfer none) (nullable): The next #GstMeta or %NULL
2327  * when there are no more items.
2328  */
2329 GstMeta *
2330 gst_buffer_iterate_meta (GstBuffer * buffer, gpointer * state)
2331 {
2332   GstMetaItem **meta;
2333
2334   g_return_val_if_fail (buffer != NULL, NULL);
2335   g_return_val_if_fail (state != NULL, NULL);
2336
2337   meta = (GstMetaItem **) state;
2338   if (*meta == NULL)
2339     /* state NULL, move to first item */
2340     *meta = GST_BUFFER_META (buffer);
2341   else
2342     /* state !NULL, move to next item in list */
2343     *meta = (*meta)->next;
2344
2345   if (*meta)
2346     return &(*meta)->meta;
2347   else
2348     return NULL;
2349 }
2350
2351 /**
2352  * gst_buffer_iterate_meta_filtered: (skip)
2353  * @buffer: a #GstBuffer
2354  * @state: (out caller-allocates): an opaque state pointer
2355  * @meta_api_type: only return #GstMeta of this type
2356  *
2357  * Retrieve the next #GstMeta of type @meta_api_type after the current one
2358  * according to @state. If @state points to %NULL, the first metadata of
2359  * type @meta_api_type is returned.
2360  *
2361  * @state will be updated with an opaque state pointer
2362  *
2363  * Returns: (transfer none) (nullable): The next #GstMeta of type
2364  * @meta_api_type or %NULL when there are no more items.
2365  *
2366  * Since: 1.12
2367  */
2368 GstMeta *
2369 gst_buffer_iterate_meta_filtered (GstBuffer * buffer, gpointer * state,
2370     GType meta_api_type)
2371 {
2372   GstMetaItem **meta;
2373
2374   g_return_val_if_fail (buffer != NULL, NULL);
2375   g_return_val_if_fail (state != NULL, NULL);
2376
2377   meta = (GstMetaItem **) state;
2378   if (*meta == NULL)
2379     /* state NULL, move to first item */
2380     *meta = GST_BUFFER_META (buffer);
2381   else
2382     /* state !NULL, move to next item in list */
2383     *meta = (*meta)->next;
2384
2385   while (*meta != NULL && (*meta)->meta.info->api != meta_api_type)
2386     *meta = (*meta)->next;
2387
2388   if (*meta)
2389     return &(*meta)->meta;
2390   else
2391     return NULL;
2392 }
2393
2394 /**
2395  * gst_buffer_foreach_meta:
2396  * @buffer: a #GstBuffer
2397  * @func: (scope call): a #GstBufferForeachMetaFunc to call
2398  * @user_data: (closure): user data passed to @func
2399  *
2400  * Call @func with @user_data for each meta in @buffer.
2401  *
2402  * @func can modify the passed meta pointer or its contents. The return value
2403  * of @func define if this function returns or if the remaining metadata items
2404  * in the buffer should be skipped.
2405  *
2406  * Returns: %FALSE when @func returned %FALSE for one of the metadata.
2407  */
2408 gboolean
2409 gst_buffer_foreach_meta (GstBuffer * buffer, GstBufferForeachMetaFunc func,
2410     gpointer user_data)
2411 {
2412   GstMetaItem *walk, *prev, *next;
2413   gboolean res = TRUE;
2414
2415   g_return_val_if_fail (buffer != NULL, FALSE);
2416   g_return_val_if_fail (func != NULL, FALSE);
2417
2418   /* find the metadata and delete */
2419   prev = GST_BUFFER_META (buffer);
2420   for (walk = prev; walk; walk = next) {
2421     GstMeta *m, *new;
2422
2423     m = new = &walk->meta;
2424     next = walk->next;
2425
2426     res = func (buffer, &new, user_data);
2427
2428     if (new == NULL) {
2429       const GstMetaInfo *info = m->info;
2430
2431       GST_CAT_DEBUG (GST_CAT_BUFFER, "remove metadata %p (%s)", m,
2432           g_type_name (info->type));
2433
2434       g_return_val_if_fail (gst_buffer_is_writable (buffer), FALSE);
2435       g_return_val_if_fail (!GST_META_FLAG_IS_SET (m, GST_META_FLAG_LOCKED),
2436           FALSE);
2437
2438       /* remove from list */
2439       if (GST_BUFFER_META (buffer) == walk)
2440         prev = GST_BUFFER_META (buffer) = next;
2441       else
2442         prev->next = next;
2443
2444       /* call free_func if any */
2445       if (info->free_func)
2446         info->free_func (m, buffer);
2447
2448       /* and free the slice */
2449       g_slice_free1 (ITEM_SIZE (info), walk);
2450     } else {
2451       prev = walk;
2452     }
2453     if (!res)
2454       break;
2455   }
2456   return res;
2457 }
2458
2459 /**
2460  * gst_buffer_extract_dup:
2461  * @buffer: a #GstBuffer
2462  * @offset: the offset to extract
2463  * @size: the size to extract
2464  * @dest: (array length=dest_size) (element-type guint8) (out): A pointer where
2465  *  the destination array will be written. Might be %NULL if the size is 0.
2466  * @dest_size: (out): A location where the size of @dest can be written
2467  *
2468  * Extracts a copy of at most @size bytes the data at @offset into
2469  * newly-allocated memory. @dest must be freed using g_free() when done.
2470  *
2471  * Since: 1.0.10
2472  */
2473
2474 void
2475 gst_buffer_extract_dup (GstBuffer * buffer, gsize offset, gsize size,
2476     gpointer * dest, gsize * dest_size)
2477 {
2478   gsize real_size, alloc_size;
2479
2480   real_size = gst_buffer_get_size (buffer);
2481
2482   alloc_size = MIN (real_size - offset, size);
2483   if (alloc_size == 0) {
2484     *dest = NULL;
2485     *dest_size = 0;
2486   } else {
2487     *dest = g_malloc (alloc_size);
2488     *dest_size = gst_buffer_extract (buffer, offset, *dest, size);
2489   }
2490 }
2491
2492 GST_DEBUG_CATEGORY_STATIC (gst_parent_buffer_meta_debug);
2493
2494 /**
2495  * gst_buffer_add_parent_buffer_meta:
2496  * @buffer: (transfer none): a #GstBuffer
2497  * @ref: (transfer none): a #GstBuffer to ref
2498  *
2499  * Add a #GstParentBufferMeta to @buffer that holds a reference on
2500  * @ref until the buffer is freed.
2501  *
2502  * Returns: (transfer none) (nullable): The #GstParentBufferMeta that was added to the buffer
2503  *
2504  * Since: 1.6
2505  */
2506 GstParentBufferMeta *
2507 gst_buffer_add_parent_buffer_meta (GstBuffer * buffer, GstBuffer * ref)
2508 {
2509   GstParentBufferMeta *meta;
2510
2511   g_return_val_if_fail (GST_IS_BUFFER (ref), NULL);
2512
2513   meta =
2514       (GstParentBufferMeta *) gst_buffer_add_meta (buffer,
2515       GST_PARENT_BUFFER_META_INFO, NULL);
2516
2517   if (!meta)
2518     return NULL;
2519
2520   meta->buffer = gst_buffer_ref (ref);
2521
2522   return meta;
2523 }
2524
2525 static gboolean
2526 _gst_parent_buffer_meta_transform (GstBuffer * dest, GstMeta * meta,
2527     GstBuffer * buffer, GQuark type, gpointer data)
2528 {
2529   GstParentBufferMeta *dmeta, *smeta;
2530
2531   smeta = (GstParentBufferMeta *) meta;
2532
2533   if (GST_META_TRANSFORM_IS_COPY (type)) {
2534     /* copy over the reference to the parent buffer.
2535      * Usually, this meta means we need to keep the parent buffer
2536      * alive because one of the child memories is in use, which
2537      * might not be the case if memory is deep copied or sub-regioned,
2538      * but we can't tell, so keep the meta */
2539     dmeta = gst_buffer_add_parent_buffer_meta (dest, smeta->buffer);
2540     if (!dmeta)
2541       return FALSE;
2542
2543     GST_CAT_DEBUG (gst_parent_buffer_meta_debug,
2544         "copy buffer reference metadata");
2545   } else {
2546     /* return FALSE, if transform type is not supported */
2547     return FALSE;
2548   }
2549   return TRUE;
2550 }
2551
2552 static void
2553 _gst_parent_buffer_meta_free (GstParentBufferMeta * parent_meta,
2554     GstBuffer * buffer)
2555 {
2556   GST_CAT_DEBUG (gst_parent_buffer_meta_debug,
2557       "Dropping reference on buffer %p", parent_meta->buffer);
2558   gst_buffer_unref (parent_meta->buffer);
2559 }
2560
2561 static gboolean
2562 _gst_parent_buffer_meta_init (GstParentBufferMeta * parent_meta,
2563     gpointer params, GstBuffer * buffer)
2564 {
2565   static volatile gsize _init;
2566
2567   if (g_once_init_enter (&_init)) {
2568     GST_DEBUG_CATEGORY_INIT (gst_parent_buffer_meta_debug, "parentbuffermeta",
2569         0, "parentbuffermeta");
2570     g_once_init_leave (&_init, 1);
2571   }
2572
2573   parent_meta->buffer = NULL;
2574
2575   return TRUE;
2576 }
2577
2578 GType
2579 gst_parent_buffer_meta_api_get_type (void)
2580 {
2581   static volatile GType type = 0;
2582   static const gchar *tags[] = { NULL };
2583
2584   if (g_once_init_enter (&type)) {
2585     GType _type = gst_meta_api_type_register ("GstParentBufferMetaAPI", tags);
2586     g_once_init_leave (&type, _type);
2587   }
2588
2589   return type;
2590 }
2591
2592 /**
2593  * gst_parent_buffer_meta_get_info:
2594  *
2595  * Get the global #GstMetaInfo describing  the #GstParentBufferMeta meta.
2596  *
2597  * Returns: (transfer none): The #GstMetaInfo
2598  *
2599  * Since: 1.6
2600  */
2601 const GstMetaInfo *
2602 gst_parent_buffer_meta_get_info (void)
2603 {
2604   static const GstMetaInfo *meta_info = NULL;
2605
2606   if (g_once_init_enter ((GstMetaInfo **) & meta_info)) {
2607     const GstMetaInfo *meta =
2608         gst_meta_register (gst_parent_buffer_meta_api_get_type (),
2609         "GstParentBufferMeta",
2610         sizeof (GstParentBufferMeta),
2611         (GstMetaInitFunction) _gst_parent_buffer_meta_init,
2612         (GstMetaFreeFunction) _gst_parent_buffer_meta_free,
2613         _gst_parent_buffer_meta_transform);
2614     g_once_init_leave ((GstMetaInfo **) & meta_info, (GstMetaInfo *) meta);
2615   }
2616
2617   return meta_info;
2618 }
2619
2620 GST_DEBUG_CATEGORY_STATIC (gst_reference_timestamp_meta_debug);
2621
2622 /**
2623  * gst_buffer_add_reference_timestamp_meta:
2624  * @buffer: (transfer none): a #GstBuffer
2625  * @reference: (transfer none): identifier for the timestamp reference.
2626  * @timestamp: timestamp
2627  * @duration: duration, or %GST_CLOCK_TIME_NONE
2628  *
2629  * Add a #GstReferenceTimestampMeta to @buffer that holds a @timestamp and
2630  * optionally @duration based on a specific timestamp @reference. See the
2631  * documentation of #GstReferenceTimestampMeta for details.
2632  *
2633  * Returns: (transfer none) (nullable): The #GstReferenceTimestampMeta that was added to the buffer
2634  *
2635  * Since: 1.14
2636  */
2637 GstReferenceTimestampMeta *
2638 gst_buffer_add_reference_timestamp_meta (GstBuffer * buffer,
2639     GstCaps * reference, GstClockTime timestamp, GstClockTime duration)
2640 {
2641   GstReferenceTimestampMeta *meta;
2642
2643   g_return_val_if_fail (GST_IS_CAPS (reference), NULL);
2644   g_return_val_if_fail (timestamp != GST_CLOCK_TIME_NONE, NULL);
2645
2646   meta =
2647       (GstReferenceTimestampMeta *) gst_buffer_add_meta (buffer,
2648       GST_REFERENCE_TIMESTAMP_META_INFO, NULL);
2649
2650   if (!meta)
2651     return NULL;
2652
2653   meta->reference = gst_caps_ref (reference);
2654   meta->timestamp = timestamp;
2655   meta->duration = duration;
2656
2657   return meta;
2658 }
2659
2660 /**
2661  * gst_buffer_get_reference_timestamp_meta:
2662  * @buffer: a #GstBuffer
2663  * @reference: (allow-none): a reference #GstCaps
2664  *
2665  * Find the first #GstReferenceTimestampMeta on @buffer that conforms to
2666  * @reference. Conformance is tested by checking if the meta's reference is a
2667  * subset of @reference.
2668  *
2669  * Buffers can contain multiple #GstReferenceTimestampMeta metadata items.
2670  *
2671  * Returns: (transfer none) (nullable): the #GstReferenceTimestampMeta or %NULL when there
2672  * is no such metadata on @buffer.
2673  *
2674  * Since: 1.14
2675  */
2676 GstReferenceTimestampMeta *
2677 gst_buffer_get_reference_timestamp_meta (GstBuffer * buffer,
2678     GstCaps * reference)
2679 {
2680   gpointer state = NULL;
2681   GstMeta *meta;
2682   const GstMetaInfo *info = GST_REFERENCE_TIMESTAMP_META_INFO;
2683
2684   while ((meta = gst_buffer_iterate_meta (buffer, &state))) {
2685     if (meta->info->api == info->api) {
2686       GstReferenceTimestampMeta *rmeta = (GstReferenceTimestampMeta *) meta;
2687
2688       if (!reference)
2689         return rmeta;
2690       if (gst_caps_is_subset (rmeta->reference, reference))
2691         return rmeta;
2692     }
2693   }
2694   return NULL;
2695 }
2696
2697 static gboolean
2698 _gst_reference_timestamp_meta_transform (GstBuffer * dest, GstMeta * meta,
2699     GstBuffer * buffer, GQuark type, gpointer data)
2700 {
2701   GstReferenceTimestampMeta *dmeta, *smeta;
2702
2703   /* we copy over the reference timestamp meta, independent of transformation
2704    * that happens. If it applied to the original buffer, it still applies to
2705    * the new buffer as it refers to the time when the media was captured */
2706   smeta = (GstReferenceTimestampMeta *) meta;
2707   dmeta =
2708       gst_buffer_add_reference_timestamp_meta (dest, smeta->reference,
2709       smeta->timestamp, smeta->duration);
2710   if (!dmeta)
2711     return FALSE;
2712
2713   GST_CAT_DEBUG (gst_reference_timestamp_meta_debug,
2714       "copy reference timestamp metadata from buffer %p to %p", buffer, dest);
2715
2716   return TRUE;
2717 }
2718
2719 static void
2720 _gst_reference_timestamp_meta_free (GstReferenceTimestampMeta * meta,
2721     GstBuffer * buffer)
2722 {
2723   if (meta->reference)
2724     gst_caps_unref (meta->reference);
2725 }
2726
2727 static gboolean
2728 _gst_reference_timestamp_meta_init (GstReferenceTimestampMeta * meta,
2729     gpointer params, GstBuffer * buffer)
2730 {
2731   static volatile gsize _init;
2732
2733   if (g_once_init_enter (&_init)) {
2734     GST_DEBUG_CATEGORY_INIT (gst_reference_timestamp_meta_debug,
2735         "referencetimestampmeta", 0, "referencetimestampmeta");
2736     g_once_init_leave (&_init, 1);
2737   }
2738
2739   meta->reference = NULL;
2740   meta->timestamp = GST_CLOCK_TIME_NONE;
2741   meta->duration = GST_CLOCK_TIME_NONE;
2742
2743   return TRUE;
2744 }
2745
2746 GType
2747 gst_reference_timestamp_meta_api_get_type (void)
2748 {
2749   static volatile GType type = 0;
2750   static const gchar *tags[] = { NULL };
2751
2752   if (g_once_init_enter (&type)) {
2753     GType _type =
2754         gst_meta_api_type_register ("GstReferenceTimestampMetaAPI", tags);
2755     g_once_init_leave (&type, _type);
2756   }
2757
2758   return type;
2759 }
2760
2761 /**
2762  * gst_reference_timestamp_meta_get_info:
2763  *
2764  * Get the global #GstMetaInfo describing  the #GstReferenceTimestampMeta meta.
2765  *
2766  * Returns: (transfer none): The #GstMetaInfo
2767  *
2768  * Since: 1.14
2769  */
2770 const GstMetaInfo *
2771 gst_reference_timestamp_meta_get_info (void)
2772 {
2773   static const GstMetaInfo *meta_info = NULL;
2774
2775   if (g_once_init_enter ((GstMetaInfo **) & meta_info)) {
2776     const GstMetaInfo *meta =
2777         gst_meta_register (gst_reference_timestamp_meta_api_get_type (),
2778         "GstReferenceTimestampMeta",
2779         sizeof (GstReferenceTimestampMeta),
2780         (GstMetaInitFunction) _gst_reference_timestamp_meta_init,
2781         (GstMetaFreeFunction) _gst_reference_timestamp_meta_free,
2782         _gst_reference_timestamp_meta_transform);
2783     g_once_init_leave ((GstMetaInfo **) & meta_info, (GstMetaInfo *) meta);
2784   }
2785
2786   return meta_info;
2787 }