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