buffer: Use the correct enum type to fix a compiler warning
[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  * @short_description: Data-passing buffer type
26  * @see_also: #GstPad, #GstMiniObject, #GstMemory, #GstMeta, #GstBufferPool
27  *
28  * Buffers are the basic unit of data transfer in GStreamer. They contain the
29  * timing and offset along with other arbitrary metadata that is associated
30  * with the #GstMemory blocks that the buffer contains.
31  *
32  * Buffers are usually created with gst_buffer_new(). After a buffer has been
33  * created one will typically allocate memory for it and add it to the buffer.
34  * The following example creates a buffer that can hold a given video frame
35  * with a given width, height and bits per plane.
36  * |[
37  *   GstBuffer *buffer;
38  *   GstMemory *memory;
39  *   gint size, width, height, bpp;
40  *   ...
41  *   size = width * height * bpp;
42  *   buffer = gst_buffer_new ();
43  *   memory = gst_allocator_alloc (NULL, size, NULL);
44  *   gst_buffer_insert_memory (buffer, -1, memory);
45  *   ...
46  * ]|
47  *
48  * Alternatively, use gst_buffer_new_allocate() to create a buffer with
49  * preallocated data of a given size.
50  *
51  * Buffers can contain a list of #GstMemory objects. You can retrieve how many
52  * memory objects with gst_buffer_n_memory() and you can get a pointer
53  * to memory with gst_buffer_peek_memory()
54  *
55  * A buffer will usually have timestamps, and a duration, but neither of these
56  * are guaranteed (they may be set to #GST_CLOCK_TIME_NONE). Whenever a
57  * meaningful value can be given for these, they should be set. The timestamps
58  * and duration are measured in nanoseconds (they are #GstClockTime values).
59  *
60  * The buffer DTS refers to the timestamp when the buffer should be decoded and
61  * is usually monotonically increasing. The buffer PTS refers to the timestamp when
62  * the buffer content should be presented to the user and is not always
63  * monotonically increasing.
64  *
65  * A buffer can also have one or both of a start and an end offset. These are
66  * media-type specific. For video buffers, the start offset will generally be
67  * the frame number. For audio buffers, it will be the number of samples
68  * produced so far. For compressed data, it could be the byte offset in a
69  * source or destination file. Likewise, the end offset will be the offset of
70  * the end of the buffer. These can only be meaningfully interpreted if you
71  * know the media type of the buffer (the preceding CAPS event). Either or both
72  * can be set to #GST_BUFFER_OFFSET_NONE.
73  *
74  * gst_buffer_ref() is used to increase the refcount of a buffer. This must be
75  * done when you want to keep a handle to the buffer after pushing it to the
76  * next element. The buffer refcount determines the writability of the buffer, a
77  * buffer is only writable when the refcount is exactly 1, i.e. when the caller
78  * has the only reference to the buffer.
79  *
80  * To efficiently create a smaller buffer out of an existing one, you can
81  * use gst_buffer_copy_region(). This method tries to share the memory objects
82  * between the two buffers.
83  *
84  * If a plug-in wants to modify the buffer data or metadata in-place, it should
85  * first obtain a buffer that is safe to modify by using
86  * gst_buffer_make_writable().  This function is optimized so that a copy will
87  * only be made when it is necessary.
88  *
89  * Several flags of the buffer can be set and unset with the
90  * GST_BUFFER_FLAG_SET() and GST_BUFFER_FLAG_UNSET() macros. Use
91  * GST_BUFFER_FLAG_IS_SET() to test if a certain #GstBufferFlags flag is set.
92  *
93  * Buffers can be efficiently merged into a larger buffer with
94  * gst_buffer_append(). Copying of memory will only be done when absolutely
95  * needed.
96  *
97  * Arbitrary extra metadata can be set on a buffer with gst_buffer_add_meta().
98  * Metadata can be retrieved with gst_buffer_get_meta(). See also #GstMeta
99  *
100  * An element should either unref the buffer or push it out on a src pad
101  * using gst_pad_push() (see #GstPad).
102  *
103  * Buffers are usually freed by unreffing them with gst_buffer_unref(). When
104  * the refcount drops to 0, any memory and metadata pointed to by the buffer is
105  * unreffed as well. Buffers allocated from a #GstBufferPool will be returned to
106  * the pool when the refcount drops to 0.
107  */
108 #include "gst_private.h"
109
110 #ifdef HAVE_UNISTD_H
111 #include <unistd.h>
112 #endif
113 #ifdef HAVE_STDLIB_H
114 #include <stdlib.h>
115 #endif
116
117 #include "gstbuffer.h"
118 #include "gstbufferpool.h"
119 #include "gstinfo.h"
120 #include "gstutils.h"
121 #include "gstversion.h"
122
123 GType _gst_buffer_type = 0;
124
125 typedef struct _GstMetaItem GstMetaItem;
126
127 struct _GstMetaItem
128 {
129   GstMetaItem *next;
130   GstMeta meta;
131 };
132 #define ITEM_SIZE(info) ((info)->size + sizeof (GstMetaItem))
133
134 #define GST_BUFFER_MEM_MAX         16
135
136 #define GST_BUFFER_SLICE_SIZE(b)   (((GstBufferImpl *)(b))->slice_size)
137 #define GST_BUFFER_MEM_LEN(b)      (((GstBufferImpl *)(b))->len)
138 #define GST_BUFFER_MEM_ARRAY(b)    (((GstBufferImpl *)(b))->mem)
139 #define GST_BUFFER_MEM_PTR(b,i)    (((GstBufferImpl *)(b))->mem[i])
140 #define GST_BUFFER_BUFMEM(b)       (((GstBufferImpl *)(b))->bufmem)
141 #define GST_BUFFER_META(b)         (((GstBufferImpl *)(b))->item)
142
143 typedef struct
144 {
145   GstBuffer buffer;
146
147   gsize slice_size;
148
149   /* the memory blocks */
150   guint len;
151   GstMemory *mem[GST_BUFFER_MEM_MAX];
152
153   /* memory of the buffer when allocated from 1 chunk */
154   GstMemory *bufmem;
155
156   /* FIXME, make metadata allocation more efficient by using part of the
157    * GstBufferImpl */
158   GstMetaItem *item;
159 } GstBufferImpl;
160
161
162 static gboolean
163 _is_span (GstMemory ** mem, gsize len, gsize * poffset, GstMemory ** parent)
164 {
165   GstMemory *mcur, *mprv;
166   gboolean have_offset = FALSE;
167   gsize i;
168
169   mcur = mprv = NULL;
170
171   for (i = 0; i < len; i++) {
172     if (mcur)
173       mprv = mcur;
174     mcur = mem[i];
175
176     if (mprv && mcur) {
177       gsize poffs;
178
179       /* check if memory is contiguous */
180       if (!gst_memory_is_span (mprv, mcur, &poffs))
181         return FALSE;
182
183       if (!have_offset) {
184         if (poffset)
185           *poffset = poffs;
186         if (parent)
187           *parent = mprv->parent;
188
189         have_offset = TRUE;
190       }
191     }
192   }
193   return have_offset;
194 }
195
196 static GstMemory *
197 _get_merged_memory (GstBuffer * buffer, guint idx, guint length)
198 {
199   GstMemory **mem, *result = NULL;
200
201   GST_CAT_LOG (GST_CAT_BUFFER, "buffer %p, idx %u, length %u", buffer, idx,
202       length);
203
204   mem = GST_BUFFER_MEM_ARRAY (buffer);
205
206   if (G_UNLIKELY (length == 0)) {
207     result = NULL;
208   } else if (G_LIKELY (length == 1)) {
209     result = gst_memory_ref (mem[idx]);
210   } else {
211     GstMemory *parent = NULL;
212     gsize size, poffset = 0;
213
214     size = gst_buffer_get_sizes_range (buffer, idx, length, NULL, NULL);
215
216     if (G_UNLIKELY (_is_span (mem + idx, length, &poffset, &parent))) {
217       if (!GST_MEMORY_IS_NO_SHARE (parent))
218         result = gst_memory_share (parent, poffset, size);
219       if (!result) {
220         GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "copy for merge %p", parent);
221         result = gst_memory_copy (parent, poffset, size);
222       }
223     } else {
224       gsize i, tocopy, left;
225       GstMapInfo sinfo, dinfo;
226       guint8 *ptr;
227
228       result = gst_allocator_alloc (NULL, size, NULL);
229       gst_memory_map (result, &dinfo, GST_MAP_WRITE);
230
231       ptr = dinfo.data;
232       left = size;
233
234       for (i = idx; i < (idx + length) && left > 0; i++) {
235         gst_memory_map (mem[i], &sinfo, GST_MAP_READ);
236         tocopy = MIN (sinfo.size, left);
237         GST_CAT_DEBUG (GST_CAT_PERFORMANCE,
238             "memcpy %" G_GSIZE_FORMAT " bytes for merge %p from memory %p",
239             tocopy, result, mem[i]);
240         memcpy (ptr, (guint8 *) sinfo.data, tocopy);
241         left -= tocopy;
242         ptr += tocopy;
243         gst_memory_unmap (mem[i], &sinfo);
244       }
245       gst_memory_unmap (result, &dinfo);
246     }
247   }
248   return result;
249 }
250
251 static void
252 _replace_memory (GstBuffer * buffer, guint len, guint idx, guint length,
253     GstMemory * mem)
254 {
255   gsize end, i;
256
257   end = idx + length;
258
259   GST_CAT_LOG (GST_CAT_BUFFER,
260       "buffer %p replace %u-%" G_GSIZE_FORMAT " with memory %p", buffer, idx,
261       end, mem);
262
263   /* unref old memory */
264   for (i = idx; i < end; i++) {
265     GstMemory *old = GST_BUFFER_MEM_PTR (buffer, i);
266
267     gst_memory_unlock (old, GST_LOCK_FLAG_EXCLUSIVE);
268     gst_memory_unref (old);
269   }
270
271   if (mem != NULL) {
272     /* replace with single memory */
273     gst_memory_lock (mem, GST_LOCK_FLAG_EXCLUSIVE);
274     GST_BUFFER_MEM_PTR (buffer, idx) = mem;
275     idx++;
276     length--;
277   }
278
279   if (end < len) {
280     memmove (&GST_BUFFER_MEM_PTR (buffer, idx),
281         &GST_BUFFER_MEM_PTR (buffer, end), (len - end) * sizeof (gpointer));
282   }
283   GST_BUFFER_MEM_LEN (buffer) = len - length;
284   GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY);
285 }
286
287 static inline void
288 _memory_add (GstBuffer * buffer, gint idx, GstMemory * mem, gboolean lock)
289 {
290   guint i, len = GST_BUFFER_MEM_LEN (buffer);
291
292   GST_CAT_LOG (GST_CAT_BUFFER, "buffer %p, idx %d, mem %p, lock %d", buffer,
293       idx, mem, lock);
294
295   if (G_UNLIKELY (len >= GST_BUFFER_MEM_MAX)) {
296     /* too many buffer, span them. */
297     /* FIXME, there is room for improvement here: We could only try to merge
298      * 2 buffers to make some room. If we can't efficiently merge 2 buffers we
299      * could try to only merge the two smallest buffers to avoid memcpy, etc. */
300     GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "memory array overflow in buffer %p",
301         buffer);
302     _replace_memory (buffer, len, 0, len, _get_merged_memory (buffer, 0, len));
303     /* we now have 1 single spanned buffer */
304     len = 1;
305   }
306
307   if (idx == -1)
308     idx = len;
309
310   for (i = len; i > idx; i--) {
311     /* move buffers to insert, FIXME, we need to insert first and then merge */
312     GST_BUFFER_MEM_PTR (buffer, i) = GST_BUFFER_MEM_PTR (buffer, i - 1);
313   }
314   /* and insert the new buffer */
315   if (lock)
316     gst_memory_lock (mem, GST_LOCK_FLAG_EXCLUSIVE);
317   GST_BUFFER_MEM_PTR (buffer, idx) = mem;
318   GST_BUFFER_MEM_LEN (buffer) = len + 1;
319
320   GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY);
321 }
322
323 GST_DEFINE_MINI_OBJECT_TYPE (GstBuffer, gst_buffer);
324
325 void
326 _priv_gst_buffer_initialize (void)
327 {
328   _gst_buffer_type = gst_buffer_get_type ();
329 }
330
331 /**
332  * gst_buffer_get_max_memory:
333  *
334  * Get the maximum amount of memory blocks that a buffer can hold. This is a
335  * compile time constant that can be queried with the function.
336  *
337  * When more memory blocks are added, existing memory blocks will be merged
338  * together to make room for the new block.
339  *
340  * Returns: the maximum amount of memory blocks that a buffer can hold.
341  *
342  * Since: 1.2
343  */
344 guint
345 gst_buffer_get_max_memory (void)
346 {
347   return GST_BUFFER_MEM_MAX;
348 }
349
350 /**
351  * gst_buffer_copy_into:
352  * @dest: a destination #GstBuffer
353  * @src: a source #GstBuffer
354  * @flags: flags indicating what metadata fields should be copied.
355  * @offset: offset to copy from
356  * @size: total size to copy. If -1, all data is copied.
357  *
358  * Copies the information from @src into @dest.
359  *
360  * If @dest already contains memory and @flags contains GST_BUFFER_COPY_MEMORY,
361  * the memory from @src will be appended to @dest.
362  *
363  * @flags indicate which fields will be copied.
364  *
365  * Returns: %TRUE if the copying succeeded, %FALSE otherwise.
366  */
367 gboolean
368 gst_buffer_copy_into (GstBuffer * dest, GstBuffer * src,
369     GstBufferCopyFlags flags, gsize offset, gsize size)
370 {
371   GstMetaItem *walk;
372   gsize bufsize;
373   gboolean region = FALSE;
374
375   g_return_val_if_fail (dest != NULL, FALSE);
376   g_return_val_if_fail (src != NULL, FALSE);
377
378   /* nothing to copy if the buffers are the same */
379   if (G_UNLIKELY (dest == src))
380     return TRUE;
381
382   g_return_val_if_fail (gst_buffer_is_writable (dest), FALSE);
383
384   bufsize = gst_buffer_get_size (src);
385   g_return_val_if_fail (bufsize >= offset, FALSE);
386   if (offset > 0)
387     region = TRUE;
388   if (size == -1)
389     size = bufsize - offset;
390   if (size < bufsize)
391     region = TRUE;
392   g_return_val_if_fail (bufsize >= offset + size, FALSE);
393
394   GST_CAT_LOG (GST_CAT_BUFFER, "copy %p to %p, offset %" G_GSIZE_FORMAT
395       "-%" G_GSIZE_FORMAT "/%" G_GSIZE_FORMAT, src, dest, offset, size,
396       bufsize);
397
398   if (flags & GST_BUFFER_COPY_FLAGS) {
399     /* copy flags */
400     guint flags_mask = ~GST_BUFFER_FLAG_TAG_MEMORY;
401
402     GST_MINI_OBJECT_FLAGS (dest) =
403         (GST_MINI_OBJECT_FLAGS (src) & flags_mask) |
404         (GST_MINI_OBJECT_FLAGS (dest) & ~flags_mask);
405   }
406
407   if (flags & GST_BUFFER_COPY_TIMESTAMPS) {
408     if (offset == 0) {
409       GST_BUFFER_PTS (dest) = GST_BUFFER_PTS (src);
410       GST_BUFFER_DTS (dest) = GST_BUFFER_DTS (src);
411       GST_BUFFER_OFFSET (dest) = GST_BUFFER_OFFSET (src);
412       if (size == bufsize) {
413         GST_BUFFER_DURATION (dest) = GST_BUFFER_DURATION (src);
414         GST_BUFFER_OFFSET_END (dest) = GST_BUFFER_OFFSET_END (src);
415       }
416     } else {
417       GST_BUFFER_PTS (dest) = GST_CLOCK_TIME_NONE;
418       GST_BUFFER_DTS (dest) = GST_CLOCK_TIME_NONE;
419       GST_BUFFER_DURATION (dest) = GST_CLOCK_TIME_NONE;
420       GST_BUFFER_OFFSET (dest) = GST_BUFFER_OFFSET_NONE;
421       GST_BUFFER_OFFSET_END (dest) = GST_BUFFER_OFFSET_NONE;
422     }
423   }
424
425   if (flags & GST_BUFFER_COPY_MEMORY) {
426     gsize skip, left, len, dest_len, i, bsize;
427     gboolean deep;
428
429     deep = flags & GST_BUFFER_COPY_DEEP;
430
431     len = GST_BUFFER_MEM_LEN (src);
432     dest_len = GST_BUFFER_MEM_LEN (dest);
433     left = size;
434     skip = offset;
435
436     /* copy and make regions of the memory */
437     for (i = 0; i < len && left > 0; i++) {
438       GstMemory *mem = GST_BUFFER_MEM_PTR (src, i);
439
440       bsize = gst_memory_get_sizes (mem, NULL, NULL);
441
442       if (bsize <= skip) {
443         /* don't copy buffer */
444         skip -= bsize;
445       } else {
446         GstMemory *newmem = NULL;
447         gsize tocopy;
448
449         tocopy = MIN (bsize - skip, left);
450
451         if (tocopy < bsize && !deep && !GST_MEMORY_IS_NO_SHARE (mem)) {
452           /* we need to clip something */
453           newmem = gst_memory_share (mem, skip, tocopy);
454           if (newmem)
455             skip = 0;
456         }
457
458         if (deep || GST_MEMORY_IS_NO_SHARE (mem) || (!newmem && tocopy < bsize)) {
459           /* deep copy or we're not allowed to share this memory
460            * between buffers, always copy then */
461           newmem = gst_memory_copy (mem, skip, tocopy);
462           skip = 0;
463         } else if (!newmem) {
464           newmem = gst_memory_ref (mem);
465         }
466
467         if (!newmem) {
468           gst_buffer_remove_memory_range (dest, dest_len, -1);
469           return FALSE;
470         }
471
472         _memory_add (dest, -1, newmem, TRUE);
473         left -= tocopy;
474       }
475     }
476     if (flags & GST_BUFFER_COPY_MERGE) {
477       GstMemory *mem;
478
479       len = GST_BUFFER_MEM_LEN (dest);
480       mem = _get_merged_memory (dest, 0, len);
481       if (!mem) {
482         gst_buffer_remove_memory_range (dest, dest_len, -1);
483         return FALSE;
484       }
485       _replace_memory (dest, len, 0, len, mem);
486     }
487   }
488
489   if (flags & GST_BUFFER_COPY_META) {
490     for (walk = GST_BUFFER_META (src); walk; walk = walk->next) {
491       GstMeta *meta = &walk->meta;
492       const GstMetaInfo *info = meta->info;
493
494       if (info->transform_func) {
495         GstMetaTransformCopy copy_data;
496
497         copy_data.region = region;
498         copy_data.offset = offset;
499         copy_data.size = size;
500
501         info->transform_func (dest, meta, src,
502             _gst_meta_transform_copy, &copy_data);
503       }
504     }
505   }
506
507   return TRUE;
508 }
509
510 static GstBuffer *
511 gst_buffer_copy_with_flags (const GstBuffer * buffer, GstBufferCopyFlags flags)
512 {
513   GstBuffer *copy;
514
515   g_return_val_if_fail (buffer != NULL, NULL);
516
517   /* create a fresh new buffer */
518   copy = gst_buffer_new ();
519
520   /* copy what the 'flags' want from our parent */
521   /* FIXME why we can't pass const to gst_buffer_copy_into() ? */
522   if (!gst_buffer_copy_into (copy, (GstBuffer *) buffer, flags, 0, -1))
523     gst_buffer_replace (&copy, NULL);
524
525   if (copy)
526     GST_BUFFER_FLAG_UNSET (copy, GST_BUFFER_FLAG_TAG_MEMORY);
527
528   return copy;
529 }
530
531 static GstBuffer *
532 _gst_buffer_copy (const GstBuffer * buffer)
533 {
534   return gst_buffer_copy_with_flags (buffer, GST_BUFFER_COPY_ALL);
535 }
536
537 /**
538  * gst_buffer_copy_deep:
539  * @buf: a #GstBuffer.
540  *
541  * Create a copy of the given buffer. This will make a newly allocated
542  * copy of the data the source buffer contains.
543  *
544  * Returns: (transfer full): a new copy of @buf.
545  */
546 GstBuffer *
547 gst_buffer_copy_deep (const GstBuffer * buffer)
548 {
549   return gst_buffer_copy_with_flags (buffer,
550       GST_BUFFER_COPY_ALL | GST_BUFFER_COPY_DEEP);
551 }
552
553 /* the default dispose function revives the buffer and returns it to the
554  * pool when there is a pool */
555 static gboolean
556 _gst_buffer_dispose (GstBuffer * buffer)
557 {
558   GstBufferPool *pool;
559
560   /* no pool, do free */
561   if ((pool = buffer->pool) == NULL)
562     return TRUE;
563
564   /* keep the buffer alive */
565   gst_buffer_ref (buffer);
566   /* return the buffer to the pool */
567   GST_CAT_LOG (GST_CAT_BUFFER, "release %p to pool %p", buffer, pool);
568   gst_buffer_pool_release_buffer (pool, buffer);
569
570   return FALSE;
571 }
572
573 static void
574 _gst_buffer_free (GstBuffer * buffer)
575 {
576   GstMetaItem *walk, *next;
577   guint i, len;
578   gsize msize;
579
580   g_return_if_fail (buffer != NULL);
581
582   GST_CAT_LOG (GST_CAT_BUFFER, "finalize %p", buffer);
583
584   /* free metadata */
585   for (walk = GST_BUFFER_META (buffer); walk; walk = next) {
586     GstMeta *meta = &walk->meta;
587     const GstMetaInfo *info = meta->info;
588
589     /* call free_func if any */
590     if (info->free_func)
591       info->free_func (meta, buffer);
592
593     next = walk->next;
594     /* and free the slice */
595     g_slice_free1 (ITEM_SIZE (info), walk);
596   }
597
598   /* get the size, when unreffing the memory, we could also unref the buffer
599    * itself */
600   msize = GST_BUFFER_SLICE_SIZE (buffer);
601
602   /* free our memory */
603   len = GST_BUFFER_MEM_LEN (buffer);
604   for (i = 0; i < len; i++) {
605     gst_memory_unlock (GST_BUFFER_MEM_PTR (buffer, i), GST_LOCK_FLAG_EXCLUSIVE);
606     gst_memory_unref (GST_BUFFER_MEM_PTR (buffer, i));
607   }
608
609   /* we set msize to 0 when the buffer is part of the memory block */
610   if (msize) {
611 #ifdef USE_POISONING
612     memset (buffer, 0xff, msize);
613 #endif
614     g_slice_free1 (msize, buffer);
615   } else {
616     gst_memory_unref (GST_BUFFER_BUFMEM (buffer));
617   }
618 }
619
620 static void
621 gst_buffer_init (GstBufferImpl * buffer, gsize size)
622 {
623   gst_mini_object_init (GST_MINI_OBJECT_CAST (buffer), 0, _gst_buffer_type,
624       (GstMiniObjectCopyFunction) _gst_buffer_copy,
625       (GstMiniObjectDisposeFunction) _gst_buffer_dispose,
626       (GstMiniObjectFreeFunction) _gst_buffer_free);
627
628   GST_BUFFER_SLICE_SIZE (buffer) = size;
629
630   GST_BUFFER (buffer)->pool = NULL;
631   GST_BUFFER_PTS (buffer) = GST_CLOCK_TIME_NONE;
632   GST_BUFFER_DTS (buffer) = GST_CLOCK_TIME_NONE;
633   GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
634   GST_BUFFER_OFFSET (buffer) = GST_BUFFER_OFFSET_NONE;
635   GST_BUFFER_OFFSET_END (buffer) = GST_BUFFER_OFFSET_NONE;
636
637   GST_BUFFER_MEM_LEN (buffer) = 0;
638   GST_BUFFER_META (buffer) = NULL;
639 }
640
641 /**
642  * gst_buffer_new:
643  *
644  * Creates a newly allocated buffer without any data.
645  *
646  * MT safe.
647  *
648  * Returns: (transfer full): the new #GstBuffer.
649  */
650 GstBuffer *
651 gst_buffer_new (void)
652 {
653   GstBufferImpl *newbuf;
654
655   newbuf = g_slice_new (GstBufferImpl);
656   GST_CAT_LOG (GST_CAT_BUFFER, "new %p", newbuf);
657
658   gst_buffer_init (newbuf, sizeof (GstBufferImpl));
659
660   return GST_BUFFER_CAST (newbuf);
661 }
662
663 /**
664  * gst_buffer_new_allocate:
665  * @allocator: (transfer none) (allow-none): the #GstAllocator to use, or %NULL to use the
666  *     default allocator
667  * @size: the size in bytes of the new buffer's data.
668  * @params: (transfer none) (allow-none): optional parameters
669  *
670  * Tries to create a newly allocated buffer with data of the given size and
671  * extra parameters from @allocator. If the requested amount of memory can't be
672  * allocated, %NULL will be returned. The allocated buffer memory is not cleared.
673  *
674  * When @allocator is %NULL, the default memory allocator will be used.
675  *
676  * Note that when @size == 0, the buffer will not have memory associated with it.
677  *
678  * MT safe.
679  *
680  * Returns: (transfer full) (nullable): a new #GstBuffer, or %NULL if
681  *     the memory couldn't be allocated.
682  */
683 GstBuffer *
684 gst_buffer_new_allocate (GstAllocator * allocator, gsize size,
685     GstAllocationParams * params)
686 {
687   GstBuffer *newbuf;
688   GstMemory *mem;
689 #if 0
690   guint8 *data;
691   gsize asize;
692 #endif
693
694 #if 1
695   if (size > 0) {
696     mem = gst_allocator_alloc (allocator, size, params);
697     if (G_UNLIKELY (mem == NULL))
698       goto no_memory;
699   } else {
700     mem = NULL;
701   }
702
703   newbuf = gst_buffer_new ();
704
705   if (mem != NULL)
706     _memory_add (newbuf, -1, mem, TRUE);
707
708   GST_CAT_LOG (GST_CAT_BUFFER,
709       "new buffer %p of size %" G_GSIZE_FORMAT " from allocator %p", newbuf,
710       size, allocator);
711 #endif
712
713 #if 0
714   asize = sizeof (GstBufferImpl) + size;
715   data = g_slice_alloc (asize);
716   if (G_UNLIKELY (data == NULL))
717     goto no_memory;
718
719   newbuf = GST_BUFFER_CAST (data);
720
721   gst_buffer_init ((GstBufferImpl *) data, asize);
722   if (size > 0) {
723     mem = gst_memory_new_wrapped (0, data + sizeof (GstBufferImpl), NULL,
724         size, 0, size);
725     _memory_add (newbuf, -1, mem, TRUE);
726   }
727 #endif
728
729 #if 0
730   /* allocate memory and buffer, it might be interesting to do this but there
731    * are many complications. We need to keep the memory mapped to access the
732    * buffer fields and the memory for the buffer might be just very slow. We
733    * also need to do some more magic to get the alignment right. */
734   asize = sizeof (GstBufferImpl) + size;
735   mem = gst_allocator_alloc (allocator, asize, align);
736   if (G_UNLIKELY (mem == NULL))
737     goto no_memory;
738
739   /* map the data part and init the buffer in it, set the buffer size to 0 so
740    * that a finalize won't free the buffer */
741   data = gst_memory_map (mem, &asize, NULL, GST_MAP_WRITE);
742   gst_buffer_init ((GstBufferImpl *) data, 0);
743   gst_memory_unmap (mem);
744
745   /* strip off the buffer */
746   gst_memory_resize (mem, sizeof (GstBufferImpl), size);
747
748   newbuf = GST_BUFFER_CAST (data);
749   GST_BUFFER_BUFMEM (newbuf) = mem;
750
751   if (size > 0)
752     _memory_add (newbuf, -1, gst_memory_ref (mem), TRUE);
753 #endif
754   GST_BUFFER_FLAG_UNSET (newbuf, GST_BUFFER_FLAG_TAG_MEMORY);
755
756   return newbuf;
757
758   /* ERRORS */
759 no_memory:
760   {
761     GST_CAT_WARNING (GST_CAT_BUFFER,
762         "failed to allocate %" G_GSIZE_FORMAT " bytes", size);
763     return NULL;
764   }
765 }
766
767 /**
768  * gst_buffer_new_wrapped_full:
769  * @flags: #GstMemoryFlags
770  * @data: (array length=size) (element-type guint8) (transfer none): data to wrap
771  * @maxsize: allocated size of @data
772  * @offset: offset in @data
773  * @size: size of valid data
774  * @user_data: (allow-none): user_data
775  * @notify: (allow-none) (scope async) (closure user_data): called with @user_data when the memory is freed
776  *
777  * Allocate a new buffer that wraps the given memory. @data must point to
778  * @maxsize of memory, the wrapped buffer will have the region from @offset and
779  * @size visible.
780  *
781  * When the buffer is destroyed, @notify will be called with @user_data.
782  *
783  * The prefix/padding must be filled with 0 if @flags contains
784  * #GST_MEMORY_FLAG_ZERO_PREFIXED and #GST_MEMORY_FLAG_ZERO_PADDED respectively.
785  *
786  * Returns: (transfer full): a new #GstBuffer
787  */
788 GstBuffer *
789 gst_buffer_new_wrapped_full (GstMemoryFlags flags, gpointer data,
790     gsize maxsize, gsize offset, gsize size, gpointer user_data,
791     GDestroyNotify notify)
792 {
793   GstMemory *mem;
794   GstBuffer *newbuf;
795
796   newbuf = gst_buffer_new ();
797   mem =
798       gst_memory_new_wrapped (flags, data, maxsize, offset, size, user_data,
799       notify);
800   _memory_add (newbuf, -1, mem, TRUE);
801   GST_BUFFER_FLAG_UNSET (newbuf, GST_BUFFER_FLAG_TAG_MEMORY);
802
803   return newbuf;
804 }
805
806 /**
807  * gst_buffer_new_wrapped:
808  * @data: (array length=size) (element-type guint8) (transfer full): data to wrap
809  * @size: allocated size of @data
810  *
811  * Creates a new buffer that wraps the given @data. The memory will be freed
812  * with g_free and will be marked writable.
813  *
814  * MT safe.
815  *
816  * Returns: (transfer full): a new #GstBuffer
817  */
818 GstBuffer *
819 gst_buffer_new_wrapped (gpointer data, gsize size)
820 {
821   return gst_buffer_new_wrapped_full (0, data, size, 0, size, data, g_free);
822 }
823
824 /**
825  * gst_buffer_n_memory:
826  * @buffer: a #GstBuffer.
827  *
828  * Get the amount of memory blocks that this buffer has. This amount is never
829  * larger than what gst_buffer_get_max_memory() returns.
830  *
831  * Returns: (transfer full): the amount of memory block in this buffer.
832  */
833 guint
834 gst_buffer_n_memory (GstBuffer * buffer)
835 {
836   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
837
838   return GST_BUFFER_MEM_LEN (buffer);
839 }
840
841 /**
842  * gst_buffer_prepend_memory:
843  * @buffer: a #GstBuffer.
844  * @mem: (transfer full): a #GstMemory.
845  *
846  * Prepend the memory block @mem to @buffer. This function takes
847  * ownership of @mem and thus doesn't increase its refcount.
848  *
849  * This function is identical to gst_buffer_insert_memory() with an index of 0.
850  * See gst_buffer_insert_memory() for more details.
851  */
852 void
853 gst_buffer_prepend_memory (GstBuffer * buffer, GstMemory * mem)
854 {
855   gst_buffer_insert_memory (buffer, 0, mem);
856 }
857
858 /**
859  * gst_buffer_append_memory:
860  * @buffer: a #GstBuffer.
861  * @mem: (transfer full): a #GstMemory.
862  *
863  * Append the memory block @mem to @buffer. This function takes
864  * ownership of @mem and thus doesn't increase its refcount.
865  *
866  * This function is identical to gst_buffer_insert_memory() with an index of -1.
867  * See gst_buffer_insert_memory() for more details.
868  */
869 void
870 gst_buffer_append_memory (GstBuffer * buffer, GstMemory * mem)
871 {
872   gst_buffer_insert_memory (buffer, -1, mem);
873 }
874
875 /**
876  * gst_buffer_insert_memory:
877  * @buffer: a #GstBuffer.
878  * @idx: the index to add the memory at, or -1 to append it to the end
879  * @mem: (transfer full): a #GstMemory.
880  *
881  * Insert the memory block @mem to @buffer at @idx. This function takes ownership
882  * of @mem and thus doesn't increase its refcount.
883  *
884  * Only gst_buffer_get_max_memory() can be added to a buffer. If more memory is
885  * added, existing memory blocks will automatically be merged to make room for
886  * the new memory.
887  */
888 void
889 gst_buffer_insert_memory (GstBuffer * buffer, gint idx, GstMemory * mem)
890 {
891   g_return_if_fail (GST_IS_BUFFER (buffer));
892   g_return_if_fail (gst_buffer_is_writable (buffer));
893   g_return_if_fail (mem != NULL);
894   g_return_if_fail (idx == -1 ||
895       (idx >= 0 && idx <= GST_BUFFER_MEM_LEN (buffer)));
896
897   _memory_add (buffer, idx, mem, TRUE);
898 }
899
900 static GstMemory *
901 _get_mapped (GstBuffer * buffer, guint idx, GstMapInfo * info,
902     GstMapFlags flags)
903 {
904   GstMemory *mem, *mapped;
905
906   mem = gst_memory_ref (GST_BUFFER_MEM_PTR (buffer, idx));
907
908   mapped = gst_memory_make_mapped (mem, info, flags);
909
910   if (mapped != mem) {
911     /* memory changed, lock new memory */
912     gst_memory_lock (mapped, GST_LOCK_FLAG_EXCLUSIVE);
913     GST_BUFFER_MEM_PTR (buffer, idx) = mapped;
914     /* unlock old memory */
915     gst_memory_unlock (mem, GST_LOCK_FLAG_EXCLUSIVE);
916     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY);
917   }
918   gst_memory_unref (mem);
919
920   return mapped;
921 }
922
923 /**
924  * gst_buffer_peek_memory:
925  * @buffer: a #GstBuffer.
926  * @idx: an index
927  *
928  * Get the memory block at @idx in @buffer. The memory block stays valid until
929  * the memory block in @buffer is removed, replaced or merged, typically with
930  * any call that modifies the memory in @buffer.
931  *
932  * Returns: (transfer none): the #GstMemory at @idx.
933  */
934 GstMemory *
935 gst_buffer_peek_memory (GstBuffer * buffer, guint idx)
936 {
937   guint len;
938
939   g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
940   len = GST_BUFFER_MEM_LEN (buffer);
941   g_return_val_if_fail (idx < len, NULL);
942
943   return GST_BUFFER_MEM_PTR (buffer, idx);
944 }
945
946 /**
947  * gst_buffer_get_memory:
948  * @buffer: a #GstBuffer.
949  * @idx: an index
950  *
951  * Get the memory block at index @idx in @buffer.
952  *
953  * Returns: (transfer full): a #GstMemory that contains the data of the
954  * memory block at @idx. Use gst_memory_unref () after usage.
955  */
956 GstMemory *
957 gst_buffer_get_memory (GstBuffer * buffer, guint idx)
958 {
959   return gst_buffer_get_memory_range (buffer, idx, 1);
960 }
961
962 /**
963  * gst_buffer_get_all_memory:
964  * @buffer: a #GstBuffer.
965  *
966  * Get all the memory block in @buffer. The memory blocks will be merged
967  * into one large #GstMemory.
968  *
969  * Returns: (transfer full): a #GstMemory that contains the merged memory.
970  * Use gst_memory_unref () after usage.
971  */
972 GstMemory *
973 gst_buffer_get_all_memory (GstBuffer * buffer)
974 {
975   return gst_buffer_get_memory_range (buffer, 0, -1);
976 }
977
978 /**
979  * gst_buffer_get_memory_range:
980  * @buffer: a #GstBuffer.
981  * @idx: an index
982  * @length: a length
983  *
984  * Get @length memory blocks in @buffer starting at @idx. The memory blocks will
985  * be merged into one large #GstMemory.
986  *
987  * If @length is -1, all memory starting from @idx is merged.
988  *
989  * Returns: (transfer full): a #GstMemory that contains the merged data of @length
990  *    blocks starting at @idx. Use gst_memory_unref () after usage.
991  */
992 GstMemory *
993 gst_buffer_get_memory_range (GstBuffer * buffer, guint idx, gint length)
994 {
995   guint len;
996
997   GST_CAT_DEBUG (GST_CAT_BUFFER, "idx %u, length %d", idx, length);
998
999   g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
1000   len = GST_BUFFER_MEM_LEN (buffer);
1001   g_return_val_if_fail ((len == 0 && idx == 0 && length == -1) ||
1002       (length == -1 && idx < len) || (length > 0 && length + idx <= len), NULL);
1003
1004   if (length == -1)
1005     length = len - idx;
1006
1007   return _get_merged_memory (buffer, idx, length);
1008 }
1009
1010 /**
1011  * gst_buffer_replace_memory:
1012  * @buffer: a #GstBuffer.
1013  * @idx: an index
1014  * @mem: (transfer full): a #GstMemory
1015  *
1016  * Replaces the memory block at index @idx in @buffer with @mem.
1017  */
1018 void
1019 gst_buffer_replace_memory (GstBuffer * buffer, guint idx, GstMemory * mem)
1020 {
1021   gst_buffer_replace_memory_range (buffer, idx, 1, mem);
1022 }
1023
1024 /**
1025  * gst_buffer_replace_all_memory:
1026  * @buffer: a #GstBuffer.
1027  * @mem: (transfer full): a #GstMemory
1028  *
1029  * Replaces all memory in @buffer with @mem.
1030  */
1031 void
1032 gst_buffer_replace_all_memory (GstBuffer * buffer, GstMemory * mem)
1033 {
1034   gst_buffer_replace_memory_range (buffer, 0, -1, mem);
1035 }
1036
1037 /**
1038  * gst_buffer_replace_memory_range:
1039  * @buffer: a #GstBuffer.
1040  * @idx: an index
1041  * @length: a length should not be 0
1042  * @mem: (transfer full): a #GstMemory
1043  *
1044  * Replaces @length memory blocks in @buffer starting at @idx with @mem.
1045  *
1046  * If @length is -1, all memory starting from @idx will be removed and
1047  * replaced with @mem.
1048  *
1049  * @buffer should be writable.
1050  */
1051 void
1052 gst_buffer_replace_memory_range (GstBuffer * buffer, guint idx, gint length,
1053     GstMemory * mem)
1054 {
1055   guint len;
1056
1057   g_return_if_fail (GST_IS_BUFFER (buffer));
1058   g_return_if_fail (gst_buffer_is_writable (buffer));
1059
1060   GST_CAT_DEBUG (GST_CAT_BUFFER, "idx %u, length %d, %p", idx, length, mem);
1061
1062   len = GST_BUFFER_MEM_LEN (buffer);
1063   g_return_if_fail ((len == 0 && idx == 0 && length == -1) ||
1064       (length == -1 && idx < len) || (length > 0 && length + idx <= len));
1065
1066   if (length == -1)
1067     length = len - idx;
1068
1069   _replace_memory (buffer, len, idx, length, mem);
1070 }
1071
1072 /**
1073  * gst_buffer_remove_memory:
1074  * @buffer: a #GstBuffer.
1075  * @idx: an index
1076  *
1077  * Remove the memory block in @b at index @i.
1078  */
1079 void
1080 gst_buffer_remove_memory (GstBuffer * buffer, guint idx)
1081 {
1082   gst_buffer_remove_memory_range (buffer, idx, 1);
1083 }
1084
1085 /**
1086  * gst_buffer_remove_all_memory:
1087  * @buffer: a #GstBuffer.
1088  *
1089  * Remove all the memory blocks in @buffer.
1090  */
1091 void
1092 gst_buffer_remove_all_memory (GstBuffer * buffer)
1093 {
1094   gst_buffer_remove_memory_range (buffer, 0, -1);
1095 }
1096
1097 /**
1098  * gst_buffer_remove_memory_range:
1099  * @buffer: a #GstBuffer.
1100  * @idx: an index
1101  * @length: a length
1102  *
1103  * Remove @length memory blocks in @buffer starting from @idx.
1104  *
1105  * @length can be -1, in which case all memory starting from @idx is removed.
1106  */
1107 void
1108 gst_buffer_remove_memory_range (GstBuffer * buffer, guint idx, gint length)
1109 {
1110   guint len;
1111
1112   g_return_if_fail (GST_IS_BUFFER (buffer));
1113   g_return_if_fail (gst_buffer_is_writable (buffer));
1114
1115   GST_CAT_DEBUG (GST_CAT_BUFFER, "idx %u, length %d", idx, length);
1116
1117   len = GST_BUFFER_MEM_LEN (buffer);
1118   g_return_if_fail ((len == 0 && idx == 0 && length == -1) ||
1119       (length == -1 && idx < len) || length + idx <= len);
1120
1121   if (length == -1)
1122     length = len - idx;
1123
1124   _replace_memory (buffer, len, idx, length, NULL);
1125 }
1126
1127 /**
1128  * gst_buffer_find_memory:
1129  * @buffer: a #GstBuffer.
1130  * @offset: an offset
1131  * @size: a size
1132  * @idx: (out): pointer to index
1133  * @length: (out): pointer to length
1134  * @skip: (out): pointer to skip
1135  *
1136  * Find the memory blocks that span @size bytes starting from @offset
1137  * in @buffer.
1138  *
1139  * When this function returns %TRUE, @idx will contain the index of the first
1140  * memory block where the byte for @offset can be found and @length contains the
1141  * number of memory blocks containing the @size remaining bytes. @skip contains
1142  * the number of bytes to skip in the memory block at @idx to get to the byte
1143  * for @offset.
1144  *
1145  * @size can be -1 to get all the memory blocks after @idx.
1146  *
1147  * Returns: %TRUE when @size bytes starting from @offset could be found in
1148  * @buffer and @idx, @length and @skip will be filled.
1149  */
1150 gboolean
1151 gst_buffer_find_memory (GstBuffer * buffer, gsize offset, gsize size,
1152     guint * idx, guint * length, gsize * skip)
1153 {
1154   guint i, len, found;
1155
1156   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
1157   g_return_val_if_fail (idx != NULL, FALSE);
1158   g_return_val_if_fail (length != NULL, FALSE);
1159   g_return_val_if_fail (skip != NULL, FALSE);
1160
1161   len = GST_BUFFER_MEM_LEN (buffer);
1162
1163   found = 0;
1164   for (i = 0; i < len; i++) {
1165     GstMemory *mem;
1166     gsize s;
1167
1168     mem = GST_BUFFER_MEM_PTR (buffer, i);
1169     s = gst_memory_get_sizes (mem, NULL, NULL);
1170
1171     if (s <= offset) {
1172       /* block before offset, or empty block, skip */
1173       offset -= s;
1174     } else {
1175       /* block after offset */
1176       if (found == 0) {
1177         /* first block, remember index and offset */
1178         *idx = i;
1179         *skip = offset;
1180         if (size == -1) {
1181           /* return remaining blocks */
1182           *length = len - i;
1183           return TRUE;
1184         }
1185         s -= offset;
1186         offset = 0;
1187       }
1188       /* count the amount of found bytes */
1189       found += s;
1190       if (found >= size) {
1191         /* we have enough bytes */
1192         *length = i - *idx + 1;
1193         return TRUE;
1194       }
1195     }
1196   }
1197   return FALSE;
1198 }
1199
1200 /**
1201  * gst_buffer_is_memory_range_writable:
1202  * @buffer: a #GstBuffer.
1203  * @idx: an index
1204  * @length: a length should not be 0
1205  *
1206  * Check if @length memory blocks in @buffer starting from @idx are writable.
1207  *
1208  * @length can be -1 to check all the memory blocks after @idx.
1209  *
1210  * Note that this function does not check if @buffer is writable, use
1211  * gst_buffer_is_writable() to check that if needed.
1212  *
1213  * Returns: %TRUE if the memory range is writable
1214  *
1215  * Since: 1.4
1216  */
1217 gboolean
1218 gst_buffer_is_memory_range_writable (GstBuffer * buffer, guint idx, gint length)
1219 {
1220   guint i, len;
1221
1222   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
1223
1224   GST_CAT_DEBUG (GST_CAT_BUFFER, "idx %u, length %d", idx, length);
1225
1226   len = GST_BUFFER_MEM_LEN (buffer);
1227   g_return_val_if_fail ((len == 0 && idx == 0 && length == -1) ||
1228       (length == -1 && idx < len) || (length > 0 && length + idx <= len),
1229       FALSE);
1230
1231   if (length == -1)
1232     len -= idx;
1233   else
1234     len = length;
1235
1236   for (i = 0; i < len; i++) {
1237     if (!gst_memory_is_writable (GST_BUFFER_MEM_PTR (buffer, i + idx)))
1238       return FALSE;
1239   }
1240   return TRUE;
1241 }
1242
1243 /**
1244  * gst_buffer_is_all_memory_writable:
1245  * @buffer: a #GstBuffer.
1246  *
1247  * Check if all memory blocks in @buffer are writable.
1248  *
1249  * Note that this function does not check if @buffer is writable, use
1250  * gst_buffer_is_writable() to check that if needed.
1251  *
1252  * Returns: %TRUE if all memory blocks in @buffer are writable
1253  *
1254  * Since: 1.4
1255  */
1256 gboolean
1257 gst_buffer_is_all_memory_writable (GstBuffer * buffer)
1258 {
1259   return gst_buffer_is_memory_range_writable (buffer, 0, -1);
1260 }
1261
1262 /**
1263  * gst_buffer_get_sizes:
1264  * @buffer: a #GstBuffer.
1265  * @offset: (out) (allow-none): a pointer to the offset
1266  * @maxsize: (out) (allow-none): a pointer to the maxsize
1267  *
1268  * Get the total size of the memory blocks in @b.
1269  *
1270  * When not %NULL, @offset will contain the offset of the data in the
1271  * first memory block in @buffer and @maxsize will contain the sum of
1272  * the size and @offset and the amount of extra padding on the last
1273  * memory block.  @offset and @maxsize can be used to resize the
1274  * buffer memory blocks with gst_buffer_resize().
1275  *
1276  * Returns: total size of the memory blocks in @buffer.
1277  */
1278 gsize
1279 gst_buffer_get_sizes (GstBuffer * buffer, gsize * offset, gsize * maxsize)
1280 {
1281   return gst_buffer_get_sizes_range (buffer, 0, -1, offset, maxsize);
1282 }
1283
1284 /**
1285  * gst_buffer_get_size:
1286  * @buffer: a #GstBuffer.
1287  *
1288  * Get the total size of the memory blocks in @buffer.
1289  *
1290  * Returns: total size of the memory blocks in @buffer.
1291  */
1292 gsize
1293 gst_buffer_get_size (GstBuffer * buffer)
1294 {
1295   return gst_buffer_get_sizes_range (buffer, 0, -1, NULL, NULL);
1296 }
1297
1298 /**
1299  * gst_buffer_get_sizes_range:
1300  * @buffer: a #GstBuffer.
1301  * @idx: an index
1302  * @length: a length
1303  * @offset: (out) (allow-none): a pointer to the offset
1304  * @maxsize: (out) (allow-none): a pointer to the maxsize
1305  *
1306  * Get the total size of @length memory blocks stating from @idx in @buffer.
1307  *
1308  * When not %NULL, @offset will contain the offset of the data in the
1309  * memory block in @buffer at @idx and @maxsize will contain the sum of the size
1310  * and @offset and the amount of extra padding on the memory block at @idx +
1311  * @length -1.
1312  * @offset and @maxsize can be used to resize the buffer memory blocks with
1313  * gst_buffer_resize_range().
1314  *
1315  * Returns: total size of @length memory blocks starting at @idx in @buffer.
1316  */
1317 gsize
1318 gst_buffer_get_sizes_range (GstBuffer * buffer, guint idx, gint length,
1319     gsize * offset, gsize * maxsize)
1320 {
1321   guint len;
1322   gsize size;
1323   GstMemory *mem;
1324
1325   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
1326   len = GST_BUFFER_MEM_LEN (buffer);
1327   g_return_val_if_fail ((len == 0 && idx == 0 && length == -1) ||
1328       (length == -1 && idx < len) || (length + idx <= len), 0);
1329
1330   if (length == -1)
1331     length = len - idx;
1332
1333   if (G_LIKELY (length == 1)) {
1334     /* common case */
1335     mem = GST_BUFFER_MEM_PTR (buffer, idx);
1336     size = gst_memory_get_sizes (mem, offset, maxsize);
1337   } else {
1338     guint i, end;
1339     gsize extra, offs;
1340
1341     end = idx + length;
1342     size = offs = extra = 0;
1343     for (i = idx; i < end; i++) {
1344       gsize s, o, ms;
1345
1346       mem = GST_BUFFER_MEM_PTR (buffer, i);
1347       s = gst_memory_get_sizes (mem, &o, &ms);
1348
1349       if (s) {
1350         if (size == 0)
1351           /* first size, take accumulated data before as the offset */
1352           offs = extra + o;
1353         /* add sizes */
1354         size += s;
1355         /* save the amount of data after this block */
1356         extra = ms - (o + s);
1357       } else {
1358         /* empty block, add as extra */
1359         extra += ms;
1360       }
1361     }
1362     if (offset)
1363       *offset = offs;
1364     if (maxsize)
1365       *maxsize = offs + size + extra;
1366   }
1367   return size;
1368 }
1369
1370 /**
1371  * gst_buffer_resize:
1372  * @buffer: a #GstBuffer.
1373  * @offset: the offset adjustment
1374  * @size: the new size or -1 to just adjust the offset
1375  *
1376  * Set the offset and total size of the memory blocks in @buffer.
1377  */
1378 void
1379 gst_buffer_resize (GstBuffer * buffer, gssize offset, gssize size)
1380 {
1381   gst_buffer_resize_range (buffer, 0, -1, offset, size);
1382 }
1383
1384 /**
1385  * gst_buffer_set_size:
1386  * @buffer: a #GstBuffer.
1387  * @size: the new size
1388  *
1389  * Set the total size of the memory blocks in @buffer.
1390  */
1391 void
1392 gst_buffer_set_size (GstBuffer * buffer, gssize size)
1393 {
1394   gst_buffer_resize_range (buffer, 0, -1, 0, size);
1395 }
1396
1397 /**
1398  * gst_buffer_resize_range:
1399  * @buffer: a #GstBuffer.
1400  * @idx: an index
1401  * @length: a length
1402  * @offset: the offset adjustment
1403  * @size: the new size or -1 to just adjust the offset
1404  *
1405  * Set the total size of the @length memory blocks starting at @idx in
1406  * @buffer
1407  *
1408  * Returns: %TRUE if resizing succeeded, %FALSE otherwise.
1409  */
1410 gboolean
1411 gst_buffer_resize_range (GstBuffer * buffer, guint idx, gint length,
1412     gssize offset, gssize size)
1413 {
1414   guint i, len, end;
1415   gsize bsize, bufsize, bufoffs, bufmax;
1416
1417   g_return_val_if_fail (gst_buffer_is_writable (buffer), FALSE);
1418   g_return_val_if_fail (size >= -1, FALSE);
1419
1420   len = GST_BUFFER_MEM_LEN (buffer);
1421   g_return_val_if_fail ((len == 0 && idx == 0 && length == -1) ||
1422       (length == -1 && idx < len) || (length + idx <= len), FALSE);
1423
1424   if (length == -1)
1425     length = len - idx;
1426
1427   bufsize = gst_buffer_get_sizes_range (buffer, idx, length, &bufoffs, &bufmax);
1428
1429   GST_CAT_LOG (GST_CAT_BUFFER, "trim %p %" G_GSSIZE_FORMAT "-%" G_GSSIZE_FORMAT
1430       " size:%" G_GSIZE_FORMAT " offs:%" G_GSIZE_FORMAT " max:%"
1431       G_GSIZE_FORMAT, buffer, offset, size, bufsize, bufoffs, bufmax);
1432
1433   /* we can't go back further than the current offset or past the end of the
1434    * buffer */
1435   g_return_val_if_fail ((offset < 0 && bufoffs >= -offset) || (offset >= 0
1436           && bufoffs + offset <= bufmax), FALSE);
1437   if (size == -1) {
1438     g_return_val_if_fail (bufsize >= offset, FALSE);
1439     size = bufsize - offset;
1440   }
1441   g_return_val_if_fail (bufmax >= bufoffs + offset + size, FALSE);
1442
1443   /* no change */
1444   if (offset == 0 && size == bufsize)
1445     return TRUE;
1446
1447   end = idx + length;
1448   /* copy and trim */
1449   for (i = idx; i < end; i++) {
1450     GstMemory *mem;
1451     gsize left, noffs;
1452
1453     mem = GST_BUFFER_MEM_PTR (buffer, i);
1454     bsize = gst_memory_get_sizes (mem, NULL, NULL);
1455
1456     noffs = 0;
1457     /* last buffer always gets resized to the remaining size */
1458     if (i + 1 == end)
1459       left = size;
1460     /* shrink buffers before the offset */
1461     else if ((gssize) bsize <= offset) {
1462       left = 0;
1463       noffs = offset - bsize;
1464       offset = 0;
1465     }
1466     /* clip other buffers */
1467     else
1468       left = MIN (bsize - offset, size);
1469
1470     if (offset != 0 || left != bsize) {
1471       if (gst_memory_is_writable (mem)) {
1472         gst_memory_resize (mem, offset, left);
1473       } else {
1474         GstMemory *newmem = NULL;
1475
1476         if (!GST_MEMORY_IS_NO_SHARE (mem))
1477           newmem = gst_memory_share (mem, offset, left);
1478
1479         if (!newmem)
1480           newmem = gst_memory_copy (mem, offset, left);
1481
1482         if (newmem == NULL)
1483           return FALSE;
1484
1485         gst_memory_lock (newmem, GST_LOCK_FLAG_EXCLUSIVE);
1486         GST_BUFFER_MEM_PTR (buffer, i) = newmem;
1487         gst_memory_unlock (mem, GST_LOCK_FLAG_EXCLUSIVE);
1488         gst_memory_unref (mem);
1489
1490         GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY);
1491       }
1492     }
1493
1494     offset = noffs;
1495     size -= left;
1496   }
1497
1498   return TRUE;
1499 }
1500
1501 /**
1502  * gst_buffer_map:
1503  * @buffer: a #GstBuffer.
1504  * @info: (out): info about the mapping
1505  * @flags: flags for the mapping
1506  *
1507  * This function fills @info with the #GstMapInfo of all merged memory
1508  * blocks in @buffer.
1509  *
1510  * @flags describe the desired access of the memory. When @flags is
1511  * #GST_MAP_WRITE, @buffer should be writable (as returned from
1512  * gst_buffer_is_writable()).
1513  *
1514  * When @buffer is writable but the memory isn't, a writable copy will
1515  * automatically be created and returned. The readonly copy of the
1516  * buffer memory will then also be replaced with this writable copy.
1517  *
1518  * The memory in @info should be unmapped with gst_buffer_unmap() after
1519  * usage.
1520  *
1521  * Returns: %TRUE if the map succeeded and @info contains valid data.
1522  */
1523 gboolean
1524 gst_buffer_map (GstBuffer * buffer, GstMapInfo * info, GstMapFlags flags)
1525 {
1526   return gst_buffer_map_range (buffer, 0, -1, info, flags);
1527 }
1528
1529 /**
1530  * gst_buffer_map_range:
1531  * @buffer: a #GstBuffer.
1532  * @idx: an index
1533  * @length: a length
1534  * @info: (out): info about the mapping
1535  * @flags: flags for the mapping
1536  *
1537  * This function fills @info with the #GstMapInfo of @length merged memory blocks
1538  * starting at @idx in @buffer. When @length is -1, all memory blocks starting
1539  * from @idx are merged and mapped.
1540  *
1541  * @flags describe the desired access of the memory. When @flags is
1542  * #GST_MAP_WRITE, @buffer should be writable (as returned from
1543  * gst_buffer_is_writable()).
1544  *
1545  * When @buffer is writable but the memory isn't, a writable copy will
1546  * automatically be created and returned. The readonly copy of the buffer memory
1547  * will then also be replaced with this writable copy.
1548  *
1549  * The memory in @info should be unmapped with gst_buffer_unmap() after usage.
1550  *
1551  * Returns: %TRUE if the map succeeded and @info contains valid
1552  * data.
1553  */
1554 gboolean
1555 gst_buffer_map_range (GstBuffer * buffer, guint idx, gint length,
1556     GstMapInfo * info, GstMapFlags flags)
1557 {
1558   GstMemory *mem, *nmem;
1559   gboolean write, writable;
1560   gsize len;
1561
1562   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
1563   g_return_val_if_fail (info != NULL, FALSE);
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 > 0
1567           && length + idx <= len), FALSE);
1568
1569   GST_CAT_LOG (GST_CAT_BUFFER, "buffer %p, idx %u, length %d, flags %04x",
1570       buffer, idx, length, flags);
1571
1572   write = (flags & GST_MAP_WRITE) != 0;
1573   writable = gst_buffer_is_writable (buffer);
1574
1575   /* check if we can write when asked for write access */
1576   if (G_UNLIKELY (write && !writable))
1577     goto not_writable;
1578
1579   if (length == -1)
1580     length = len - idx;
1581
1582   mem = _get_merged_memory (buffer, idx, length);
1583   if (G_UNLIKELY (mem == NULL))
1584     goto no_memory;
1585
1586   /* now try to map */
1587   nmem = gst_memory_make_mapped (mem, info, flags);
1588   if (G_UNLIKELY (nmem == NULL))
1589     goto cannot_map;
1590
1591   /* if we merged or when the map returned a different memory, we try to replace
1592    * the memory in the buffer */
1593   if (G_UNLIKELY (length > 1 || nmem != mem)) {
1594     /* if the buffer is writable, replace the memory */
1595     if (writable) {
1596       _replace_memory (buffer, len, idx, length, gst_memory_ref (nmem));
1597     } else {
1598       if (len > 1) {
1599         GST_CAT_DEBUG (GST_CAT_PERFORMANCE,
1600             "temporary mapping for memory %p in buffer %p", nmem, buffer);
1601       }
1602     }
1603   }
1604   return TRUE;
1605
1606   /* ERROR */
1607 not_writable:
1608   {
1609     GST_WARNING_OBJECT (buffer, "write map requested on non-writable buffer");
1610     g_critical ("write map requested on non-writable buffer");
1611     memset (info, 0, sizeof (GstMapInfo));
1612     return FALSE;
1613   }
1614 no_memory:
1615   {
1616     /* empty buffer, we need to return NULL */
1617     GST_DEBUG_OBJECT (buffer, "can't get buffer memory");
1618     memset (info, 0, sizeof (GstMapInfo));
1619     return TRUE;
1620   }
1621 cannot_map:
1622   {
1623     GST_DEBUG_OBJECT (buffer, "cannot map memory");
1624     memset (info, 0, sizeof (GstMapInfo));
1625     return FALSE;
1626   }
1627 }
1628
1629 /**
1630  * gst_buffer_unmap:
1631  * @buffer: a #GstBuffer.
1632  * @info: a #GstMapInfo
1633  *
1634  * Release the memory previously mapped with gst_buffer_map().
1635  */
1636 void
1637 gst_buffer_unmap (GstBuffer * buffer, GstMapInfo * info)
1638 {
1639   g_return_if_fail (GST_IS_BUFFER (buffer));
1640   g_return_if_fail (info != NULL);
1641
1642   /* we need to check for NULL, it is possible that we tried to map a buffer
1643    * without memory and we should be able to unmap that fine */
1644   if (G_LIKELY (info->memory)) {
1645     gst_memory_unmap (info->memory, info);
1646     gst_memory_unref (info->memory);
1647   }
1648 }
1649
1650 /**
1651  * gst_buffer_fill:
1652  * @buffer: a #GstBuffer.
1653  * @offset: the offset to fill
1654  * @src: (array length=size) (element-type guint8): the source address
1655  * @size: the size to fill
1656  *
1657  * Copy @size bytes from @src to @buffer at @offset.
1658  *
1659  * Returns: The amount of bytes copied. This value can be lower than @size
1660  *    when @buffer did not contain enough data.
1661  */
1662 gsize
1663 gst_buffer_fill (GstBuffer * buffer, gsize offset, gconstpointer src,
1664     gsize size)
1665 {
1666   gsize i, len, left;
1667   const guint8 *ptr = src;
1668
1669   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
1670   g_return_val_if_fail (gst_buffer_is_writable (buffer), 0);
1671   g_return_val_if_fail (src != NULL || size == 0, 0);
1672
1673   GST_CAT_LOG (GST_CAT_BUFFER,
1674       "buffer %p, offset %" G_GSIZE_FORMAT ", size %" G_GSIZE_FORMAT, buffer,
1675       offset, size);
1676
1677   len = GST_BUFFER_MEM_LEN (buffer);
1678   left = size;
1679
1680   for (i = 0; i < len && left > 0; i++) {
1681     GstMapInfo info;
1682     gsize tocopy;
1683     GstMemory *mem;
1684
1685     mem = _get_mapped (buffer, i, &info, GST_MAP_WRITE);
1686     if (info.size > offset) {
1687       /* we have enough */
1688       tocopy = MIN (info.size - offset, left);
1689       memcpy ((guint8 *) info.data + offset, ptr, tocopy);
1690       left -= tocopy;
1691       ptr += tocopy;
1692       offset = 0;
1693     } else {
1694       /* offset past buffer, skip */
1695       offset -= info.size;
1696     }
1697     gst_memory_unmap (mem, &info);
1698   }
1699   return size - left;
1700 }
1701
1702 /**
1703  * gst_buffer_extract:
1704  * @buffer: a #GstBuffer.
1705  * @offset: the offset to extract
1706  * @dest: the destination address
1707  * @size: the size to extract
1708  *
1709  * Copy @size bytes starting from @offset in @buffer to @dest.
1710  *
1711  * Returns: The amount of bytes extracted. This value can be lower than @size
1712  *    when @buffer did not contain enough data.
1713  */
1714 gsize
1715 gst_buffer_extract (GstBuffer * buffer, gsize offset, gpointer dest, gsize size)
1716 {
1717   gsize i, len, left;
1718   guint8 *ptr = dest;
1719
1720   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
1721   g_return_val_if_fail (dest != NULL, 0);
1722
1723   GST_CAT_LOG (GST_CAT_BUFFER,
1724       "buffer %p, offset %" G_GSIZE_FORMAT ", size %" G_GSIZE_FORMAT, buffer,
1725       offset, size);
1726
1727   len = GST_BUFFER_MEM_LEN (buffer);
1728   left = size;
1729
1730   for (i = 0; i < len && left > 0; i++) {
1731     GstMapInfo info;
1732     gsize tocopy;
1733     GstMemory *mem;
1734
1735     mem = _get_mapped (buffer, i, &info, GST_MAP_READ);
1736     if (info.size > offset) {
1737       /* we have enough */
1738       tocopy = MIN (info.size - offset, left);
1739       memcpy (ptr, (guint8 *) info.data + offset, tocopy);
1740       left -= tocopy;
1741       ptr += tocopy;
1742       offset = 0;
1743     } else {
1744       /* offset past buffer, skip */
1745       offset -= info.size;
1746     }
1747     gst_memory_unmap (mem, &info);
1748   }
1749   return size - left;
1750 }
1751
1752 /**
1753  * gst_buffer_memcmp:
1754  * @buffer: a #GstBuffer.
1755  * @offset: the offset in @buffer
1756  * @mem: (array length=size) (element-type guint8): the memory to compare
1757  * @size: the size to compare
1758  *
1759  * Compare @size bytes starting from @offset in @buffer with the memory in @mem.
1760  *
1761  * Returns: 0 if the memory is equal.
1762  */
1763 gint
1764 gst_buffer_memcmp (GstBuffer * buffer, gsize offset, gconstpointer mem,
1765     gsize size)
1766 {
1767   gsize i, len;
1768   const guint8 *ptr = mem;
1769   gint res = 0;
1770
1771   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
1772   g_return_val_if_fail (mem != NULL, 0);
1773
1774   GST_CAT_LOG (GST_CAT_BUFFER,
1775       "buffer %p, offset %" G_GSIZE_FORMAT ", size %" G_GSIZE_FORMAT, buffer,
1776       offset, size);
1777
1778   if (G_UNLIKELY (gst_buffer_get_size (buffer) < offset + size))
1779     return -1;
1780
1781   len = GST_BUFFER_MEM_LEN (buffer);
1782
1783   for (i = 0; i < len && size > 0 && res == 0; i++) {
1784     GstMapInfo info;
1785     gsize tocmp;
1786     GstMemory *mem;
1787
1788     mem = _get_mapped (buffer, i, &info, GST_MAP_READ);
1789     if (info.size > offset) {
1790       /* we have enough */
1791       tocmp = MIN (info.size - offset, size);
1792       res = memcmp (ptr, (guint8 *) info.data + offset, tocmp);
1793       size -= tocmp;
1794       ptr += tocmp;
1795       offset = 0;
1796     } else {
1797       /* offset past buffer, skip */
1798       offset -= info.size;
1799     }
1800     gst_memory_unmap (mem, &info);
1801   }
1802   return res;
1803 }
1804
1805 /**
1806  * gst_buffer_memset:
1807  * @buffer: a #GstBuffer.
1808  * @offset: the offset in @buffer
1809  * @val: the value to set
1810  * @size: the size to set
1811  *
1812  * Fill @buf with @size bytes with @val starting from @offset.
1813  *
1814  * Returns: The amount of bytes filled. This value can be lower than @size
1815  *    when @buffer did not contain enough data.
1816  */
1817 gsize
1818 gst_buffer_memset (GstBuffer * buffer, gsize offset, guint8 val, gsize size)
1819 {
1820   gsize i, len, left;
1821
1822   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
1823   g_return_val_if_fail (gst_buffer_is_writable (buffer), 0);
1824
1825   GST_CAT_LOG (GST_CAT_BUFFER,
1826       "buffer %p, offset %" G_GSIZE_FORMAT ", val %02x, size %" G_GSIZE_FORMAT,
1827       buffer, offset, val, size);
1828
1829   len = GST_BUFFER_MEM_LEN (buffer);
1830   left = size;
1831
1832   for (i = 0; i < len && left > 0; i++) {
1833     GstMapInfo info;
1834     gsize toset;
1835     GstMemory *mem;
1836
1837     mem = _get_mapped (buffer, i, &info, GST_MAP_WRITE);
1838     if (info.size > offset) {
1839       /* we have enough */
1840       toset = MIN (info.size - offset, left);
1841       memset ((guint8 *) info.data + offset, val, toset);
1842       left -= toset;
1843       offset = 0;
1844     } else {
1845       /* offset past buffer, skip */
1846       offset -= info.size;
1847     }
1848     gst_memory_unmap (mem, &info);
1849   }
1850   return size - left;
1851 }
1852
1853 /**
1854  * gst_buffer_copy_region:
1855  * @parent: a #GstBuffer.
1856  * @flags: the #GstBufferCopyFlags
1857  * @offset: the offset into parent #GstBuffer at which the new sub-buffer 
1858  *          begins.
1859  * @size: the size of the new #GstBuffer sub-buffer, in bytes. If -1, all
1860  *        data is copied.
1861  *
1862  * Creates a sub-buffer from @parent at @offset and @size.
1863  * This sub-buffer uses the actual memory space of the parent buffer.
1864  * This function will copy the offset and timestamp fields when the
1865  * offset is 0. If not, they will be set to #GST_CLOCK_TIME_NONE and 
1866  * #GST_BUFFER_OFFSET_NONE.
1867  * If @offset equals 0 and @size equals the total size of @buffer, the
1868  * duration and offset end fields are also copied. If not they will be set
1869  * to #GST_CLOCK_TIME_NONE and #GST_BUFFER_OFFSET_NONE.
1870  *
1871  * MT safe.
1872  *
1873  * Returns: (transfer full): the new #GstBuffer or %NULL if the arguments were
1874  *     invalid.
1875  */
1876 GstBuffer *
1877 gst_buffer_copy_region (GstBuffer * buffer, GstBufferCopyFlags flags,
1878     gsize offset, gsize size)
1879 {
1880   GstBuffer *copy;
1881
1882   g_return_val_if_fail (buffer != NULL, NULL);
1883
1884   /* create the new buffer */
1885   copy = gst_buffer_new ();
1886
1887   GST_CAT_LOG (GST_CAT_BUFFER, "new region copy %p of %p %" G_GSIZE_FORMAT
1888       "-%" G_GSIZE_FORMAT, copy, buffer, offset, size);
1889
1890   if (!gst_buffer_copy_into (copy, buffer, flags, offset, size))
1891     gst_buffer_replace (&copy, NULL);
1892
1893   return copy;
1894 }
1895
1896 /**
1897  * gst_buffer_append:
1898  * @buf1: (transfer full): the first source #GstBuffer to append.
1899  * @buf2: (transfer full): the second source #GstBuffer to append.
1900  *
1901  * Append all the memory from @buf2 to @buf1. The result buffer will contain a
1902  * concatenation of the memory of @buf1 and @buf2.
1903  *
1904  * Returns: (transfer full): the new #GstBuffer that contains the memory
1905  *     of the two source buffers.
1906  */
1907 GstBuffer *
1908 gst_buffer_append (GstBuffer * buf1, GstBuffer * buf2)
1909 {
1910   return gst_buffer_append_region (buf1, buf2, 0, -1);
1911 }
1912
1913 /**
1914  * gst_buffer_append_region:
1915  * @buf1: (transfer full): the first source #GstBuffer to append.
1916  * @buf2: (transfer full): the second source #GstBuffer to append.
1917  * @offset: the offset in @buf2
1918  * @size: the size or -1 of @buf2
1919  *
1920  * Append @size bytes at @offset from @buf2 to @buf1. The result buffer will
1921  * contain a concatenation of the memory of @buf1 and the requested region of
1922  * @buf2.
1923  *
1924  * Returns: (transfer full): the new #GstBuffer that contains the memory
1925  *     of the two source buffers.
1926  */
1927 GstBuffer *
1928 gst_buffer_append_region (GstBuffer * buf1, GstBuffer * buf2, gssize offset,
1929     gssize size)
1930 {
1931   gsize i, len;
1932
1933   g_return_val_if_fail (GST_IS_BUFFER (buf1), NULL);
1934   g_return_val_if_fail (GST_IS_BUFFER (buf2), NULL);
1935
1936   buf1 = gst_buffer_make_writable (buf1);
1937   buf2 = gst_buffer_make_writable (buf2);
1938
1939   gst_buffer_resize (buf2, offset, size);
1940
1941   len = GST_BUFFER_MEM_LEN (buf2);
1942   for (i = 0; i < len; i++) {
1943     GstMemory *mem;
1944
1945     mem = GST_BUFFER_MEM_PTR (buf2, i);
1946     GST_BUFFER_MEM_PTR (buf2, i) = NULL;
1947     _memory_add (buf1, -1, mem, FALSE);
1948   }
1949
1950   GST_BUFFER_MEM_LEN (buf2) = 0;
1951   GST_BUFFER_FLAG_SET (buf2, GST_BUFFER_FLAG_TAG_MEMORY);
1952   gst_buffer_unref (buf2);
1953
1954   return buf1;
1955 }
1956
1957 /**
1958  * gst_buffer_get_meta:
1959  * @buffer: a #GstBuffer
1960  * @api: the #GType of an API
1961  *
1962  * Get the metadata for @api on buffer. When there is no such metadata, %NULL is
1963  * returned. If multiple metadata with the given @api are attached to this
1964  * buffer only the first one is returned.  To handle multiple metadata with a
1965  * given API use gst_buffer_iterate_meta() or gst_buffer_foreach_meta() instead
1966  * and check the meta->info.api member for the API type.
1967  *
1968  * Returns: (transfer none) (nullable): the metadata for @api on
1969  * @buffer.
1970  */
1971 GstMeta *
1972 gst_buffer_get_meta (GstBuffer * buffer, GType api)
1973 {
1974   GstMetaItem *item;
1975   GstMeta *result = NULL;
1976
1977   g_return_val_if_fail (buffer != NULL, NULL);
1978   g_return_val_if_fail (api != 0, NULL);
1979
1980   /* find GstMeta of the requested API */
1981   for (item = GST_BUFFER_META (buffer); item; item = item->next) {
1982     GstMeta *meta = &item->meta;
1983     if (meta->info->api == api) {
1984       result = meta;
1985       break;
1986     }
1987   }
1988   return result;
1989 }
1990
1991 /**
1992  * gst_buffer_add_meta:
1993  * @buffer: a #GstBuffer
1994  * @info: a #GstMetaInfo
1995  * @params: params for @info
1996  *
1997  * Add metadata for @info to @buffer using the parameters in @params.
1998  *
1999  * Returns: (transfer none): the metadata for the api in @info on @buffer.
2000  */
2001 GstMeta *
2002 gst_buffer_add_meta (GstBuffer * buffer, const GstMetaInfo * info,
2003     gpointer params)
2004 {
2005   GstMetaItem *item;
2006   GstMeta *result = NULL;
2007   gsize size;
2008
2009   g_return_val_if_fail (buffer != NULL, NULL);
2010   g_return_val_if_fail (info != NULL, NULL);
2011   g_return_val_if_fail (gst_buffer_is_writable (buffer), NULL);
2012
2013   /* create a new slice */
2014   size = ITEM_SIZE (info);
2015   item = g_slice_alloc (size);
2016   result = &item->meta;
2017   result->info = info;
2018   result->flags = GST_META_FLAG_NONE;
2019
2020   GST_CAT_DEBUG (GST_CAT_BUFFER,
2021       "alloc metadata %p (%s) of size %" G_GSIZE_FORMAT, result,
2022       g_type_name (info->type), info->size);
2023
2024   /* call the init_func when needed */
2025   if (info->init_func)
2026     if (!info->init_func (result, params, buffer))
2027       goto init_failed;
2028
2029   /* and add to the list of metadata */
2030   item->next = GST_BUFFER_META (buffer);
2031   GST_BUFFER_META (buffer) = item;
2032
2033   return result;
2034
2035 init_failed:
2036   {
2037     g_slice_free1 (size, item);
2038     return NULL;
2039   }
2040 }
2041
2042 /**
2043  * gst_buffer_remove_meta:
2044  * @buffer: a #GstBuffer
2045  * @meta: a #GstMeta
2046  *
2047  * Remove the metadata for @meta on @buffer.
2048  *
2049  * Returns: %TRUE if the metadata existed and was removed, %FALSE if no such
2050  * metadata was on @buffer.
2051  */
2052 gboolean
2053 gst_buffer_remove_meta (GstBuffer * buffer, GstMeta * meta)
2054 {
2055   GstMetaItem *walk, *prev;
2056
2057   g_return_val_if_fail (buffer != NULL, FALSE);
2058   g_return_val_if_fail (meta != NULL, FALSE);
2059   g_return_val_if_fail (gst_buffer_is_writable (buffer), FALSE);
2060   g_return_val_if_fail (!GST_META_FLAG_IS_SET (meta, GST_META_FLAG_LOCKED),
2061       FALSE);
2062
2063   /* find the metadata and delete */
2064   prev = GST_BUFFER_META (buffer);
2065   for (walk = prev; walk; walk = walk->next) {
2066     GstMeta *m = &walk->meta;
2067     if (m == meta) {
2068       const GstMetaInfo *info = meta->info;
2069
2070       /* remove from list */
2071       if (GST_BUFFER_META (buffer) == walk)
2072         GST_BUFFER_META (buffer) = walk->next;
2073       else
2074         prev->next = walk->next;
2075       /* call free_func if any */
2076       if (info->free_func)
2077         info->free_func (m, buffer);
2078
2079       /* and free the slice */
2080       g_slice_free1 (ITEM_SIZE (info), walk);
2081       break;
2082     }
2083     prev = walk;
2084   }
2085   return walk != NULL;
2086 }
2087
2088 /**
2089  * gst_buffer_iterate_meta:
2090  * @buffer: a #GstBuffer
2091  * @state: an opaque state pointer
2092  *
2093  * Retrieve the next #GstMeta after @current. If @state points
2094  * to %NULL, the first metadata is returned.
2095  *
2096  * @state will be updated with an opaque state pointer
2097  *
2098  * Returns: (transfer none) (nullable): The next #GstMeta or %NULL
2099  * when there are no more items.
2100  */
2101 GstMeta *
2102 gst_buffer_iterate_meta (GstBuffer * buffer, gpointer * state)
2103 {
2104   GstMetaItem **meta;
2105
2106   g_return_val_if_fail (buffer != NULL, NULL);
2107   g_return_val_if_fail (state != NULL, NULL);
2108
2109   meta = (GstMetaItem **) state;
2110   if (*meta == NULL)
2111     /* state NULL, move to first item */
2112     *meta = GST_BUFFER_META (buffer);
2113   else
2114     /* state !NULL, move to next item in list */
2115     *meta = (*meta)->next;
2116
2117   if (*meta)
2118     return &(*meta)->meta;
2119   else
2120     return NULL;
2121 }
2122
2123 /**
2124  * gst_buffer_foreach_meta:
2125  * @buffer: a #GstBuffer
2126  * @func: (scope call): a #GstBufferForeachMetaFunc to call
2127  * @user_data: (closure): user data passed to @func
2128  *
2129  * Call @func with @user_data for each meta in @buffer.
2130  *
2131  * @func can modify the passed meta pointer or its contents. The return value
2132  * of @func define if this function returns or if the remaining metadata items
2133  * in the buffer should be skipped.
2134  *
2135  * Returns: %FALSE when @func returned %FALSE for one of the metadata.
2136  */
2137 gboolean
2138 gst_buffer_foreach_meta (GstBuffer * buffer, GstBufferForeachMetaFunc func,
2139     gpointer user_data)
2140 {
2141   GstMetaItem *walk, *prev, *next;
2142   gboolean res = TRUE;
2143
2144   g_return_val_if_fail (buffer != NULL, FALSE);
2145   g_return_val_if_fail (func != NULL, FALSE);
2146
2147   /* find the metadata and delete */
2148   prev = GST_BUFFER_META (buffer);
2149   for (walk = prev; walk; walk = next) {
2150     GstMeta *m, *new;
2151
2152     m = new = &walk->meta;
2153     next = walk->next;
2154
2155     res = func (buffer, &new, user_data);
2156
2157     if (new == NULL) {
2158       const GstMetaInfo *info = m->info;
2159
2160       GST_CAT_DEBUG (GST_CAT_BUFFER, "remove metadata %p (%s)", m,
2161           g_type_name (info->type));
2162
2163       g_return_val_if_fail (gst_buffer_is_writable (buffer), FALSE);
2164       g_return_val_if_fail (!GST_META_FLAG_IS_SET (m, GST_META_FLAG_LOCKED),
2165           FALSE);
2166
2167       /* remove from list */
2168       if (GST_BUFFER_META (buffer) == walk)
2169         GST_BUFFER_META (buffer) = next;
2170       else
2171         prev->next = next;
2172
2173       /* call free_func if any */
2174       if (info->free_func)
2175         info->free_func (m, buffer);
2176
2177       /* and free the slice */
2178       g_slice_free1 (ITEM_SIZE (info), walk);
2179     }
2180     if (!res)
2181       break;
2182   }
2183   return res;
2184 }
2185
2186 /**
2187  * gst_buffer_extract_dup:
2188  * @buffer: a #GstBuffer
2189  * @offset: the offset to extract
2190  * @size: the size to extract
2191  * @dest: (array length=dest_size) (element-type guint8) (out): A pointer where
2192  *  the destination array will be written.
2193  * @dest_size: (out): A location where the size of @dest can be written
2194  *
2195  * Extracts a copy of at most @size bytes the data at @offset into a #GBytes.
2196  * @dest must be freed using g_free() when done.
2197  *
2198  * Since: 1.0.10
2199  */
2200
2201 void
2202 gst_buffer_extract_dup (GstBuffer * buffer, gsize offset, gsize size,
2203     gpointer * dest, gsize * dest_size)
2204 {
2205   gsize real_size;
2206
2207   real_size = gst_buffer_get_size (buffer);
2208
2209   *dest = g_malloc (MIN (real_size - offset, size));
2210
2211   *dest_size = gst_buffer_extract (buffer, offset, *dest, size);
2212 }