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