0e1fe4c9f033bc618f6c160fbbde7e5852204123
[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., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 /**
24  * SECTION:gstbuffer
25  * @short_description: Data-passing buffer type, supporting sub-buffers.
26  * @see_also: #GstPad, #GstMiniObject, #GstBufferPool
27  *
28  * Buffers are the basic unit of data transfer in GStreamer.  The #GstBuffer
29  * type provides all the state necessary to define the regions of memory as
30  * part of a stream. Region copies are also supported, allowing a smaller
31  * region of a buffer to become its own buffer, with mechanisms in place to
32  * ensure that neither memory space goes away prematurely.
33  *
34  * Buffers are usually created with gst_buffer_new(). After a buffer has been
35  * created one will typically allocate memory for it and add it to the buffer.
36  * The following example creates a buffer that can hold a given video frame
37  * with a given width, height and bits per plane.
38  * <example>
39  * <title>Creating a buffer for a video frame</title>
40  *   <programlisting>
41  *   GstBuffer *buffer;
42  *   GstMemory *memory;
43  *   gint size, width, height, bpp;
44  *   ...
45  *   size = width * height * bpp;
46  *   buffer = gst_buffer_new ();
47  *   memory = gst_allocator_alloc (NULL, size, NULL);
48  *   gst_buffer_take_memory (buffer, -1, memory);
49  *   ...
50  *   </programlisting>
51  * </example>
52  *
53  * Alternatively, use gst_buffer_new_allocate()
54  * to create a buffer with preallocated data of a given size.
55  *
56  * Buffers can contain a list of #GstMemory objects. You can retrieve how many
57  * memory objects with gst_buffer_n_memory() and you can get a pointer
58  * to memory with gst_buffer_peek_memory()
59  *
60  * A buffer will usually have timestamps, and a duration, but neither of these
61  * are guaranteed (they may be set to #GST_CLOCK_TIME_NONE). Whenever a
62  * meaningful value can be given for these, they should be set. The timestamps
63  * and duration are measured in nanoseconds (they are #GstClockTime values).
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 #GstCaps set on it). 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.
77  *
78  * To efficiently create a smaller buffer out of an existing one, you can
79  * use gst_buffer_copy_region().
80  *
81  * If a plug-in wants to modify the buffer data or metadata in-place, it should
82  * first obtain a buffer that is safe to modify by using
83  * gst_buffer_make_writable().  This function is optimized so that a copy will
84  * only be made when it is necessary.
85  *
86  * Several flags of the buffer can be set and unset with the
87  * GST_BUFFER_FLAG_SET() and GST_BUFFER_FLAG_UNSET() macros. Use
88  * GST_BUFFER_FLAG_IS_SET() to test if a certain #GstBufferFlag is set.
89  *
90  * Buffers can be efficiently merged into a larger buffer with
91  * gst_buffer_append(). Copying of memory will only be done when absolutely
92  * needed.
93  *
94  * An element should either unref the buffer or push it out on a src pad
95  * using gst_pad_push() (see #GstPad).
96  *
97  * Buffers are usually freed by unreffing them with gst_buffer_unref(). When
98  * the refcount drops to 0, any data pointed to by the buffer is unreffed as
99  * well.
100  *
101  * Last reviewed on November 8, 2011 (0.11.2)
102  */
103 #include "gst_private.h"
104
105 #ifdef HAVE_UNISTD_H
106 #include <unistd.h>
107 #endif
108 #ifdef HAVE_STDLIB_H
109 #include <stdlib.h>
110 #endif
111
112 #include "gstbuffer.h"
113 #include "gstbufferpool.h"
114 #include "gstinfo.h"
115 #include "gstutils.h"
116 #include "gstminiobject.h"
117 #include "gstversion.h"
118
119 GType _gst_buffer_type = 0;
120
121 typedef struct _GstMetaItem GstMetaItem;
122
123 struct _GstMetaItem
124 {
125   GstMetaItem *next;
126   GstMeta meta;
127 };
128 #define ITEM_SIZE(info) ((info)->size + sizeof (GstMetaItem))
129
130 #define GST_BUFFER_MEM_MAX         16
131
132 #define GST_BUFFER_MEM_LEN(b)      (((GstBufferImpl *)(b))->len)
133 #define GST_BUFFER_MEM_ARRAY(b)    (((GstBufferImpl *)(b))->mem)
134 #define GST_BUFFER_MEM_PTR(b,i)    (((GstBufferImpl *)(b))->mem[i])
135 #define GST_BUFFER_BUFMEM(b)       (((GstBufferImpl *)(b))->bufmem)
136 #define GST_BUFFER_META(b)         (((GstBufferImpl *)(b))->item)
137
138 typedef struct
139 {
140   GstBuffer buffer;
141
142   /* the memory blocks */
143   guint len;
144   GstMemory *mem[GST_BUFFER_MEM_MAX];
145
146   /* memory of the buffer when allocated from 1 chunk */
147   GstMemory *bufmem;
148
149   /* FIXME, make metadata allocation more efficient by using part of the
150    * GstBufferImpl */
151   GstMetaItem *item;
152 } GstBufferImpl;
153
154
155 static gboolean
156 _is_span (GstMemory ** mem, gsize len, gsize * poffset, GstMemory ** parent)
157 {
158   GstMemory *mcur, *mprv;
159   gboolean have_offset = FALSE;
160   gsize i;
161
162   mcur = mprv = NULL;
163
164   for (i = 0; i < len; i++) {
165     if (mcur)
166       mprv = mcur;
167     mcur = mem[i];
168
169     if (mprv && mcur) {
170       gsize poffs;
171
172       /* check if memory is contiguous */
173       if (!gst_memory_is_span (mprv, mcur, &poffs))
174         return FALSE;
175
176       if (!have_offset) {
177         if (poffset)
178           *poffset = poffs;
179         if (parent)
180           *parent = mprv->parent;
181
182         have_offset = TRUE;
183       }
184     }
185   }
186   return have_offset;
187 }
188
189 static GstMemory *
190 _get_merged_memory (GstBuffer * buffer, gboolean * merged)
191 {
192   GstMemory **mem, *result;
193   gsize len;
194
195   mem = GST_BUFFER_MEM_ARRAY (buffer);
196   len = GST_BUFFER_MEM_LEN (buffer);
197
198   if (G_UNLIKELY (len == 0)) {
199     result = NULL;
200     *merged = FALSE;
201   } else if (G_LIKELY (len == 1)) {
202     result = gst_memory_ref (mem[0]);
203     *merged = FALSE;
204   } else {
205     GstMemory *parent = NULL;
206     gsize size, poffset;
207
208     size = gst_buffer_get_size (buffer);
209
210     if (G_UNLIKELY (_is_span (mem, len, &poffset, &parent))) {
211
212       if (parent->flags & GST_MEMORY_FLAG_NO_SHARE) {
213         GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "copy for merge %p", parent);
214         result = gst_memory_copy (parent, poffset, size);
215       } else {
216         result = gst_memory_share (parent, poffset, size);
217       }
218     } else {
219       gsize i, tocopy, left;
220       GstMapInfo sinfo, dinfo;
221       guint8 *ptr;
222
223       result = gst_allocator_alloc (NULL, size, NULL);
224       gst_memory_map (result, &dinfo, GST_MAP_WRITE);
225
226       ptr = dinfo.data;
227       left = size;
228
229       for (i = 0; i < len && left > 0; i++) {
230         gst_memory_map (mem[i], &sinfo, GST_MAP_READ);
231         tocopy = MIN (sinfo.size, left);
232         GST_CAT_DEBUG (GST_CAT_PERFORMANCE,
233             "memcpy for merge %p from memory %p", result, mem[i]);
234         memcpy (ptr, (guint8 *) sinfo.data, tocopy);
235         left -= tocopy;
236         ptr += tocopy;
237         gst_memory_unmap (mem[i], &sinfo);
238       }
239       gst_memory_unmap (result, &dinfo);
240     }
241     *merged = TRUE;
242   }
243   return result;
244 }
245
246 static void
247 _replace_all_memory (GstBuffer * buffer, GstMemory * mem)
248 {
249   gsize len, i;
250
251   GST_LOG ("buffer %p replace with memory %p", buffer, mem);
252
253   len = GST_BUFFER_MEM_LEN (buffer);
254
255   /* unref old memory */
256   for (i = 0; i < len; i++)
257     gst_memory_unref (GST_BUFFER_MEM_PTR (buffer, i));
258   /* replace with single memory */
259   GST_BUFFER_MEM_PTR (buffer, 0) = mem;
260   GST_BUFFER_MEM_LEN (buffer) = 1;
261 }
262
263 static inline void
264 _memory_add (GstBuffer * buffer, guint idx, GstMemory * mem)
265 {
266   guint i, len = GST_BUFFER_MEM_LEN (buffer);
267
268   if (G_UNLIKELY (len >= GST_BUFFER_MEM_MAX)) {
269     gboolean merged;
270     /* too many buffer, span them. */
271     /* FIXME, there is room for improvement here: We could only try to merge
272      * 2 buffers to make some room. If we can't efficiently merge 2 buffers we
273      * could try to only merge the two smallest buffers to avoid memcpy, etc. */
274     GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "memory array overflow in buffer %p",
275         buffer);
276     _replace_all_memory (buffer, _get_merged_memory (buffer, &merged));
277     /* we now have 1 single spanned buffer */
278     len = 1;
279   }
280
281   if (idx == -1)
282     idx = len;
283
284   for (i = len; i > idx; i--) {
285     /* move buffers to insert, FIXME, we need to insert first and then merge */
286     GST_BUFFER_MEM_PTR (buffer, i) = GST_BUFFER_MEM_PTR (buffer, i - 1);
287   }
288   /* and insert the new buffer */
289   GST_BUFFER_MEM_PTR (buffer, idx) = mem;
290   GST_BUFFER_MEM_LEN (buffer) = len + 1;
291 }
292
293 GST_DEFINE_MINI_OBJECT_TYPE (GstBuffer, gst_buffer);
294
295 void
296 _priv_gst_buffer_initialize (void)
297 {
298   _gst_buffer_type = gst_buffer_get_type ();
299 }
300
301 /**
302  * gst_buffer_copy_into:
303  * @dest: a destination #GstBuffer
304  * @src: a source #GstBuffer
305  * @flags: flags indicating what metadata fields should be copied.
306  * @offset: offset to copy from
307  * @size: total size to copy. If -1, all data is copied.
308  *
309  * Copies the information from @src into @dest.
310  *
311  * If @dest already contains memory and @flags contains GST_BUFFER_COPY_MEMORY,
312  * the memory from @src will be appended to @dest.
313  *
314  * @flags indicate which fields will be copied.
315  */
316 void
317 gst_buffer_copy_into (GstBuffer * dest, GstBuffer * src,
318     GstBufferCopyFlags flags, gsize offset, gsize size)
319 {
320   GstMetaItem *walk;
321   gsize bufsize;
322   gboolean region = FALSE;
323
324   g_return_if_fail (dest != NULL);
325   g_return_if_fail (src != NULL);
326
327   /* nothing to copy if the buffers are the same */
328   if (G_UNLIKELY (dest == src))
329     return;
330
331   g_return_if_fail (gst_buffer_is_writable (dest));
332
333   bufsize = gst_buffer_get_size (src);
334   g_return_if_fail (bufsize >= offset);
335   if (offset > 0)
336     region = TRUE;
337   if (size == -1)
338     size = bufsize - offset;
339   if (size < bufsize)
340     region = TRUE;
341   g_return_if_fail (bufsize >= offset + size);
342
343   GST_CAT_LOG (GST_CAT_BUFFER, "copy %p to %p, offset %" G_GSIZE_FORMAT
344       "-%" G_GSIZE_FORMAT "/%" G_GSIZE_FORMAT, src, dest, offset, size,
345       bufsize);
346
347   if (flags & GST_BUFFER_COPY_FLAGS) {
348     /* copy flags */
349     GST_MINI_OBJECT_FLAGS (dest) = GST_MINI_OBJECT_FLAGS (src);
350   }
351
352   if (flags & GST_BUFFER_COPY_TIMESTAMPS) {
353     if (offset == 0) {
354       GST_BUFFER_PTS (dest) = GST_BUFFER_PTS (src);
355       GST_BUFFER_DTS (dest) = GST_BUFFER_DTS (src);
356       GST_BUFFER_OFFSET (dest) = GST_BUFFER_OFFSET (src);
357       if (size == bufsize) {
358         GST_BUFFER_DURATION (dest) = GST_BUFFER_DURATION (src);
359         GST_BUFFER_OFFSET_END (dest) = GST_BUFFER_OFFSET_END (src);
360       }
361     } else {
362       GST_BUFFER_PTS (dest) = GST_CLOCK_TIME_NONE;
363       GST_BUFFER_DTS (dest) = GST_CLOCK_TIME_NONE;
364       GST_BUFFER_DURATION (dest) = GST_CLOCK_TIME_NONE;
365       GST_BUFFER_OFFSET (dest) = GST_BUFFER_OFFSET_NONE;
366       GST_BUFFER_OFFSET_END (dest) = GST_BUFFER_OFFSET_NONE;
367     }
368   }
369
370   if (flags & GST_BUFFER_COPY_MEMORY) {
371     GstMemory *mem;
372     gsize skip, left, len, i, bsize;
373
374     len = GST_BUFFER_MEM_LEN (src);
375     left = size;
376     skip = offset;
377
378     /* copy and make regions of the memory */
379     for (i = 0; i < len && left > 0; i++) {
380       mem = GST_BUFFER_MEM_PTR (src, i);
381       bsize = gst_memory_get_sizes (mem, NULL, NULL);
382
383       if (bsize <= skip) {
384         /* don't copy buffer */
385         skip -= bsize;
386       } else {
387         gsize tocopy;
388
389         tocopy = MIN (bsize - skip, left);
390         if (mem->flags & GST_MEMORY_FLAG_NO_SHARE) {
391           /* no share, always copy then */
392           mem = gst_memory_copy (mem, skip, tocopy);
393           skip = 0;
394         } else if (tocopy < bsize) {
395           /* we need to clip something */
396           mem = gst_memory_share (mem, skip, tocopy);
397           skip = 0;
398         } else {
399           mem = gst_memory_ref (mem);
400         }
401         _memory_add (dest, -1, mem);
402         left -= tocopy;
403       }
404     }
405     if (flags & GST_BUFFER_COPY_MERGE) {
406       gboolean merged;
407       _replace_all_memory (dest, _get_merged_memory (dest, &merged));
408     }
409   }
410
411   if (flags & GST_BUFFER_COPY_META) {
412     for (walk = GST_BUFFER_META (src); walk; walk = walk->next) {
413       GstMeta *meta = &walk->meta;
414       const GstMetaInfo *info = meta->info;
415
416       if (info->transform_func) {
417         GstMetaTransformCopy copy_data;
418
419         copy_data.region = region;
420         copy_data.offset = offset;
421         copy_data.size = size;
422
423         info->transform_func (dest, meta, src,
424             _gst_meta_transform_copy, &copy_data);
425       }
426     }
427   }
428 }
429
430 static GstBuffer *
431 _gst_buffer_copy (GstBuffer * buffer)
432 {
433   GstBuffer *copy;
434
435   g_return_val_if_fail (buffer != NULL, NULL);
436
437   /* create a fresh new buffer */
438   copy = gst_buffer_new ();
439
440   /* we simply copy everything from our parent */
441   gst_buffer_copy_into (copy, buffer, GST_BUFFER_COPY_ALL, 0, -1);
442
443   return copy;
444 }
445
446 /* the default dispose function revives the buffer and returns it to the
447  * pool when there is a pool */
448 static gboolean
449 _gst_buffer_dispose (GstBuffer * buffer)
450 {
451   GstBufferPool *pool;
452
453   /* no pool, do free */
454   if ((pool = buffer->pool) == NULL)
455     return TRUE;
456
457   /* keep the buffer alive */
458   gst_buffer_ref (buffer);
459   /* return the buffer to the pool */
460   GST_CAT_LOG (GST_CAT_BUFFER, "release %p to pool %p", buffer, pool);
461   gst_buffer_pool_release_buffer (pool, buffer);
462
463   return FALSE;
464 }
465
466 static void
467 _gst_buffer_free (GstBuffer * buffer)
468 {
469   GstMetaItem *walk, *next;
470   guint i, len;
471   gsize msize;
472
473   g_return_if_fail (buffer != NULL);
474
475   GST_CAT_LOG (GST_CAT_BUFFER, "finalize %p", buffer);
476
477   /* free metadata */
478   for (walk = GST_BUFFER_META (buffer); walk; walk = next) {
479     GstMeta *meta = &walk->meta;
480     const GstMetaInfo *info = meta->info;
481
482     /* call free_func if any */
483     if (info->free_func)
484       info->free_func (meta, buffer);
485
486     next = walk->next;
487     /* and free the slice */
488     g_slice_free1 (ITEM_SIZE (info), walk);
489   }
490
491   /* get the size, when unreffing the memory, we could also unref the buffer
492    * itself */
493   msize = GST_MINI_OBJECT_SIZE (buffer);
494
495   /* free our memory */
496   len = GST_BUFFER_MEM_LEN (buffer);
497   for (i = 0; i < len; i++)
498     gst_memory_unref (GST_BUFFER_MEM_PTR (buffer, i));
499
500   /* we set msize to 0 when the buffer is part of the memory block */
501   if (msize)
502     g_slice_free1 (msize, buffer);
503   else
504     gst_memory_unref (GST_BUFFER_BUFMEM (buffer));
505 }
506
507 static void
508 gst_buffer_init (GstBufferImpl * buffer, gsize size)
509 {
510   gst_mini_object_init (GST_MINI_OBJECT_CAST (buffer), _gst_buffer_type, size);
511
512   buffer->buffer.mini_object.copy =
513       (GstMiniObjectCopyFunction) _gst_buffer_copy;
514   buffer->buffer.mini_object.dispose =
515       (GstMiniObjectDisposeFunction) _gst_buffer_dispose;
516   buffer->buffer.mini_object.free =
517       (GstMiniObjectFreeFunction) _gst_buffer_free;
518
519   GST_BUFFER (buffer)->pool = NULL;
520   GST_BUFFER_PTS (buffer) = GST_CLOCK_TIME_NONE;
521   GST_BUFFER_DTS (buffer) = GST_CLOCK_TIME_NONE;
522   GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
523   GST_BUFFER_OFFSET (buffer) = GST_BUFFER_OFFSET_NONE;
524   GST_BUFFER_OFFSET_END (buffer) = GST_BUFFER_OFFSET_NONE;
525
526   GST_BUFFER_MEM_LEN (buffer) = 0;
527   GST_BUFFER_META (buffer) = NULL;
528 }
529
530 /**
531  * gst_buffer_new:
532  *
533  * Creates a newly allocated buffer without any data.
534  *
535  * MT safe.
536  *
537  * Returns: (transfer full): the new #GstBuffer.
538  */
539 GstBuffer *
540 gst_buffer_new (void)
541 {
542   GstBufferImpl *newbuf;
543
544   newbuf = g_slice_new (GstBufferImpl);
545   GST_CAT_LOG (GST_CAT_BUFFER, "new %p", newbuf);
546
547   gst_buffer_init (newbuf, sizeof (GstBufferImpl));
548
549   return GST_BUFFER_CAST (newbuf);
550 }
551
552 /**
553  * gst_buffer_new_allocate:
554  * @allocator: (transfer none) (allow-none): the #GstAllocator to use, or NULL to use the
555  *     default allocator
556  * @size: the size in bytes of the new buffer's data.
557  * @params: (transfer none) (allow-none): optional parameters
558  *
559  * Tries to create a newly allocated buffer with data of the given size and
560  * extra parameters from @allocator. If the requested amount of memory can't be
561  * allocated, NULL will be returned. The allocated buffer memory is not cleared.
562  *
563  * When @allocator is NULL, the default memory allocator will be used.
564  *
565  * Note that when @size == 0, the buffer will not have memory associated with it.
566  *
567  * MT safe.
568  *
569  * Returns: (transfer full): a new #GstBuffer, or NULL if the memory couldn't
570  *     be allocated.
571  */
572 GstBuffer *
573 gst_buffer_new_allocate (GstAllocator * allocator, gsize size,
574     GstAllocationParams * params)
575 {
576   GstBuffer *newbuf;
577   GstMemory *mem;
578 #if 0
579   guint8 *data;
580   gsize asize;
581 #endif
582
583 #if 1
584   if (size > 0) {
585     mem = gst_allocator_alloc (allocator, size, params);
586     if (G_UNLIKELY (mem == NULL))
587       goto no_memory;
588   } else {
589     mem = NULL;
590   }
591
592   newbuf = gst_buffer_new ();
593
594   if (mem != NULL)
595     _memory_add (newbuf, -1, mem);
596
597   GST_CAT_LOG (GST_CAT_BUFFER,
598       "new buffer %p of size %" G_GSIZE_FORMAT " from allocator %p", newbuf,
599       size, allocator);
600 #endif
601
602 #if 0
603   asize = sizeof (GstBufferImpl) + size;
604   data = g_slice_alloc (asize);
605   if (G_UNLIKELY (data == NULL))
606     goto no_memory;
607
608   newbuf = GST_BUFFER_CAST (data);
609
610   gst_buffer_init ((GstBufferImpl *) data, asize);
611   if (size > 0) {
612     mem = gst_memory_new_wrapped (0, data + sizeof (GstBufferImpl), NULL,
613         size, 0, size);
614     _memory_add (newbuf, -1, mem);
615   }
616 #endif
617
618 #if 0
619   /* allocate memory and buffer, it might be interesting to do this but there
620    * are many complications. We need to keep the memory mapped to access the
621    * buffer fields and the memory for the buffer might be just very slow. We
622    * also need to do some more magic to get the alignment right. */
623   asize = sizeof (GstBufferImpl) + size;
624   mem = gst_allocator_alloc (allocator, asize, align);
625   if (G_UNLIKELY (mem == NULL))
626     goto no_memory;
627
628   /* map the data part and init the buffer in it, set the buffer size to 0 so
629    * that a finalize won't free the buffer */
630   data = gst_memory_map (mem, &asize, NULL, GST_MAP_WRITE);
631   gst_buffer_init ((GstBufferImpl *) data, 0);
632   gst_memory_unmap (mem);
633
634   /* strip off the buffer */
635   gst_memory_resize (mem, sizeof (GstBufferImpl), size);
636
637   newbuf = GST_BUFFER_CAST (data);
638   GST_BUFFER_BUFMEM (newbuf) = mem;
639
640   if (size > 0)
641     _memory_add (newbuf, -1, gst_memory_ref (mem));
642 #endif
643
644   return newbuf;
645
646   /* ERRORS */
647 no_memory:
648   {
649     GST_CAT_WARNING (GST_CAT_BUFFER,
650         "failed to allocate %" G_GSIZE_FORMAT " bytes", size);
651     return NULL;
652   }
653 }
654
655 /**
656  * gst_buffer_new_wrapped_full:
657  * @flags: #GstMemoryFlags
658  * @data: data to wrap
659  * @maxsize: allocated size of @data
660  * @offset: offset in @data
661  * @size: size of valid data
662  * @user_data: user_data
663  * @notify: called with @user_data when the memory is freed
664  *
665  * Allocate a new buffer that wraps the given memory. @data must point to
666  * @maxsize of memory, the wrapped buffer will have the region from @offset and
667  * @size visible.
668  *
669  * When the buffer is destroyed, @notify will be called with @user_data.
670  *
671  * The prefix/padding must be filled with 0 if @flags contains
672  * #GST_MEMORY_FLAG_ZERO_PREFIXED and #GST_MEMORY_FLAG_ZERO_PADDED respectively.
673  *
674  * Returns: (transfer full): a new #GstBuffer
675  */
676 GstBuffer *
677 gst_buffer_new_wrapped_full (GstMemoryFlags flags, gpointer data,
678     gsize maxsize, gsize offset, gsize size, gpointer user_data,
679     GDestroyNotify notify)
680 {
681   GstBuffer *newbuf;
682
683   newbuf = gst_buffer_new ();
684   gst_buffer_append_memory (newbuf,
685       gst_memory_new_wrapped (flags, data, maxsize, offset, size,
686           user_data, notify));
687
688   return newbuf;
689 }
690
691 /**
692  * gst_buffer_new_wrapped:
693  * @data: data to wrap
694  * @size: allocated size of @data
695  *
696  * Creates a new buffer that wraps the given @data. The memory will be freed
697  * with g_free and will be marked writable.
698  *
699  * MT safe.
700  *
701  * Returns: (transfer full): a new #GstBuffer
702  */
703 GstBuffer *
704 gst_buffer_new_wrapped (gpointer data, gsize size)
705 {
706   return gst_buffer_new_wrapped_full (0, data, size, 0, size, data, g_free);
707 }
708
709 /**
710  * gst_buffer_n_memory:
711  * @buffer: a #GstBuffer.
712  *
713  * Get the amount of memory blocks that this buffer has.
714  *
715  * Returns: (transfer full): the amount of memory block in this buffer.
716  */
717 guint
718 gst_buffer_n_memory (GstBuffer * buffer)
719 {
720   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
721
722   return GST_BUFFER_MEM_LEN (buffer);
723 }
724
725 /**
726  * gst_buffer_take_memory:
727  * @buffer: a #GstBuffer.
728  * @idx: the index to add the memory at, or -1 to append it to the end
729  * @mem: (transfer full): a #GstMemory.
730  *
731  * Add the memory block @mem to @buffer at @idx. This function takes ownership
732  * of @mem and thus doesn't increase its refcount.
733  */
734 void
735 gst_buffer_take_memory (GstBuffer * buffer, gint idx, GstMemory * mem)
736 {
737   g_return_if_fail (GST_IS_BUFFER (buffer));
738   g_return_if_fail (gst_buffer_is_writable (buffer));
739   g_return_if_fail (mem != NULL);
740   g_return_if_fail (idx == -1 ||
741       (idx >= 0 && idx <= GST_BUFFER_MEM_LEN (buffer)));
742
743   _memory_add (buffer, idx, mem);
744 }
745
746 static GstMemory *
747 _get_mapped (GstBuffer * buffer, guint idx, GstMapInfo * info,
748     GstMapFlags flags)
749 {
750   GstMemory *mem, *mapped;
751
752   mem = GST_BUFFER_MEM_PTR (buffer, idx);
753
754   mapped = gst_memory_make_mapped (mem, info, flags);
755   if (!mapped)
756     return NULL;
757
758   if (mapped != mem) {
759     GST_BUFFER_MEM_PTR (buffer, idx) = mapped;
760     gst_memory_unref (mem);
761     mem = mapped;
762   }
763   return mem;
764 }
765
766 /**
767  * gst_buffer_get_memory:
768  * @buffer: a #GstBuffer.
769  * @idx: an index
770  *
771  * Get the memory block in @buffer at @idx. If @idx is -1, all memory is merged
772  * into one large #GstMemory object that is then returned.
773  *
774  * Returns: (transfer full): a #GstMemory at @idx. Use gst_memory_unref () after usage.
775  */
776 GstMemory *
777 gst_buffer_get_memory (GstBuffer * buffer, gint idx)
778 {
779   GstMemory *mem;
780
781   g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
782   g_return_val_if_fail (idx == -1 ||
783       (idx >= 0 && idx <= GST_BUFFER_MEM_LEN (buffer)), NULL);
784
785   if (idx == -1) {
786     gboolean merged;
787     mem = _get_merged_memory (buffer, &merged);
788   } else if ((mem = GST_BUFFER_MEM_PTR (buffer, idx))) {
789     gst_memory_ref (mem);
790   }
791   return mem;
792 }
793
794 /**
795  * gst_buffer_replace_memory:
796  * @buffer: a #GstBuffer.
797  * @idx: an index
798  * @mem: (transfer full): a #GstMemory
799  *
800  * Replaces the memory block in @buffer at @idx with @mem. If @idx is -1, all
801  * memory will be removed and replaced with @mem.
802  *
803  * @buffer should be writable.
804  */
805 void
806 gst_buffer_replace_memory (GstBuffer * buffer, gint idx, GstMemory * mem)
807 {
808   g_return_if_fail (GST_IS_BUFFER (buffer));
809   g_return_if_fail (gst_buffer_is_writable (buffer));
810   g_return_if_fail (idx == -1 ||
811       (idx >= 0 && idx < GST_BUFFER_MEM_LEN (buffer)));
812
813   if (idx == -1) {
814     _replace_all_memory (buffer, mem);
815   } else {
816     GstMemory *old;
817
818     if ((old = GST_BUFFER_MEM_PTR (buffer, idx)))
819       gst_memory_unref (old);
820     GST_BUFFER_MEM_PTR (buffer, idx) = mem;
821   }
822 }
823
824 /**
825  * gst_buffer_remove_memory_range:
826  * @buffer: a #GstBuffer.
827  * @idx: an index
828  * @length: a length
829  *
830  * Remove @len memory blocks in @buffer starting from @idx.
831  *
832  * @length can be -1, in which case all memory starting from @idx is removed.
833  */
834 void
835 gst_buffer_remove_memory_range (GstBuffer * buffer, guint idx, gint length)
836 {
837   guint len, i, end;
838
839   g_return_if_fail (GST_IS_BUFFER (buffer));
840   g_return_if_fail (gst_buffer_is_writable (buffer));
841
842   len = GST_BUFFER_MEM_LEN (buffer);
843   g_return_if_fail ((length == -1 && idx < len) || length + idx < len);
844
845   if (length == -1)
846     length = len - idx;
847
848   end = idx + length;
849   for (i = idx; i < end; i++)
850     gst_memory_unref (GST_BUFFER_MEM_PTR (buffer, i));
851
852   if (end != len) {
853     g_memmove (&GST_BUFFER_MEM_PTR (buffer, idx),
854         &GST_BUFFER_MEM_PTR (buffer, end), (len - end) * sizeof (gpointer));
855   }
856   GST_BUFFER_MEM_LEN (buffer) = len - length;
857 }
858
859 /**
860  * gst_buffer_get_sizes:
861  * @buffer: a #GstBuffer.
862  * @offset: a pointer to the offset
863  * @maxsize: a pointer to the maxsize
864  *
865  * Get the total size of all memory blocks in @buffer.
866  *
867  * When not %NULL, @offset will contain the offset of the data in the first
868  * memory block in @buffer and @maxsize will contain the sum of the size
869  * and @offset and the amount of extra padding on the last memory block.
870  * @offset and @maxsize can be used to resize the buffer with
871  * gst_buffer_resize().
872  *
873  * Returns: the total size of the memory in @buffer.
874  */
875 gsize
876 gst_buffer_get_sizes (GstBuffer * buffer, gsize * offset, gsize * maxsize)
877 {
878   guint len;
879   gsize size;
880   GstMemory *mem;
881
882   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
883
884   len = GST_BUFFER_MEM_LEN (buffer);
885
886   if (G_LIKELY (len == 1)) {
887     /* common case */
888     mem = GST_BUFFER_MEM_PTR (buffer, 0);
889     size = gst_memory_get_sizes (mem, offset, maxsize);
890   } else {
891     guint i;
892     gsize extra, offs;
893
894     size = offs = extra = 0;
895     for (i = 0; i < len; i++) {
896       gsize s, o, ms;
897
898       mem = GST_BUFFER_MEM_PTR (buffer, i);
899       s = gst_memory_get_sizes (mem, &o, &ms);
900
901       if (s) {
902         if (size == 0)
903           /* first size, take accumulated data before as the offset */
904           offs = extra + o;
905         /* add sizes */
906         size += s;
907         /* save the amount of data after this block */
908         extra = ms - (o + s);
909       } else {
910         /* empty block, add as extra */
911         extra += ms;
912       }
913     }
914     if (offset)
915       *offset = offs;
916     if (maxsize)
917       *maxsize = offs + size + extra;
918   }
919   return size;
920 }
921
922 /**
923  * gst_buffer_resize:
924  * @buffer: a #GstBuffer.
925  * @offset: the offset adjustement
926  * @size: the new size or -1 to just adjust the offset
927  *
928  * Set the total size of the buffer
929  */
930 void
931 gst_buffer_resize (GstBuffer * buffer, gssize offset, gssize size)
932 {
933   guint len;
934   guint i;
935   gsize bsize, bufsize, bufoffs, bufmax;
936   GstMemory *mem;
937
938   g_return_if_fail (gst_buffer_is_writable (buffer));
939   g_return_if_fail (size >= -1);
940
941   bufsize = gst_buffer_get_sizes (buffer, &bufoffs, &bufmax);
942
943   GST_CAT_LOG (GST_CAT_BUFFER, "trim %p %" G_GSSIZE_FORMAT "-%" G_GSSIZE_FORMAT
944       " size:%" G_GSIZE_FORMAT " offs:%" G_GSIZE_FORMAT " max:%"
945       G_GSIZE_FORMAT, buffer, offset, size, bufsize, bufoffs, bufmax);
946
947   /* we can't go back further than the current offset or past the end of the
948    * buffer */
949   g_return_if_fail ((offset < 0 && bufoffs >= -offset) || (offset >= 0
950           && bufoffs + offset <= bufmax));
951   if (size == -1) {
952     g_return_if_fail (bufsize >= offset);
953     size = bufsize - offset;
954   }
955   g_return_if_fail (bufmax >= bufoffs + offset + size);
956
957   /* no change */
958   if (offset == 0 && size == bufsize)
959     return;
960
961   len = GST_BUFFER_MEM_LEN (buffer);
962
963   /* copy and trim */
964   for (i = 0; i < len; i++) {
965     gsize left, noffs;
966
967     mem = GST_BUFFER_MEM_PTR (buffer, i);
968     bsize = gst_memory_get_sizes (mem, NULL, NULL);
969
970     noffs = 0;
971     /* last buffer always gets resized to the remaining size */
972     if (i + 1 == len)
973       left = size;
974     /* shrink buffers before the offset */
975     else if ((gssize) bsize <= offset) {
976       left = 0;
977       noffs = offset - bsize;
978       offset = 0;
979     }
980     /* clip other buffers */
981     else
982       left = MIN (bsize - offset, size);
983
984     if (offset != 0 || left != bsize) {
985       if (gst_memory_is_exclusive (mem)) {
986         gst_memory_resize (mem, offset, left);
987       } else {
988         GstMemory *tmp;
989
990         if (mem->flags & GST_MEMORY_FLAG_NO_SHARE)
991           tmp = gst_memory_copy (mem, offset, left);
992         else
993           tmp = gst_memory_share (mem, offset, left);
994
995         gst_memory_unref (mem);
996         mem = tmp;
997       }
998     }
999     offset = noffs;
1000     size -= left;
1001
1002     GST_BUFFER_MEM_PTR (buffer, i) = mem;
1003   }
1004 }
1005
1006 /**
1007  * gst_buffer_map:
1008  * @buffer: a #GstBuffer.
1009  * @info: (out): info about the mapping
1010  * @flags: flags for the mapping
1011  *
1012  * This function fills @info with a pointer to the merged memory in @buffer.
1013  * @flags describe the desired access of the memory. When @flags is
1014  * #GST_MAP_WRITE, @buffer should be writable (as returned from
1015  * gst_buffer_is_writable()).
1016  *
1017  * When @buffer is writable but the memory isn't, a writable copy will
1018  * automatically be created and returned. The readonly copy of the buffer memory
1019  * will then also be replaced with this writable copy.
1020  *
1021  * When the buffer contains multiple memory blocks, the returned pointer will be
1022  * a concatenation of the memory blocks.
1023  *
1024  * The memory in @info should be unmapped with gst_buffer_unmap() after usage.
1025  *
1026  * Returns: (transfer full): %TRUE if the map succeeded and @info contains valid
1027  * data.
1028  */
1029 gboolean
1030 gst_buffer_map (GstBuffer * buffer, GstMapInfo * info, GstMapFlags flags)
1031 {
1032   GstMemory *mem, *nmem;
1033   gboolean write, writable, merged;
1034
1035   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
1036   g_return_val_if_fail (info != NULL, FALSE);
1037
1038   write = (flags & GST_MAP_WRITE) != 0;
1039   writable = gst_buffer_is_writable (buffer);
1040
1041   /* check if we can write when asked for write access */
1042   if (G_UNLIKELY (write && !writable))
1043     goto not_writable;
1044
1045   mem = _get_merged_memory (buffer, &merged);
1046   if (G_UNLIKELY (mem == NULL))
1047     goto no_memory;
1048
1049   /* now try to map */
1050   nmem = gst_memory_make_mapped (mem, info, flags);
1051   if (G_UNLIKELY (nmem == NULL))
1052     goto cannot_map;
1053
1054   /* if we merged or when the map returned a different memory, we try to replace
1055    * the memory in the buffer */
1056   if (G_UNLIKELY (merged || nmem != mem)) {
1057     /* if the buffer is writable, replace the memory */
1058     if (writable) {
1059       _replace_all_memory (buffer, gst_memory_ref (nmem));
1060     } else {
1061       if (GST_BUFFER_MEM_LEN (buffer) > 1) {
1062         GST_CAT_DEBUG (GST_CAT_PERFORMANCE,
1063             "temporary mapping for memory %p in buffer %p", nmem, buffer);
1064       }
1065     }
1066   }
1067   return TRUE;
1068
1069   /* ERROR */
1070 not_writable:
1071   {
1072     GST_WARNING_OBJECT (buffer, "write map requested on non-writable buffer");
1073     g_critical ("write map requested on non-writable buffer");
1074     return FALSE;
1075   }
1076 no_memory:
1077   {
1078     /* empty buffer, we need to return NULL */
1079     GST_DEBUG_OBJECT (buffer, "can't get buffer memory");
1080     info->memory = NULL;
1081     info->data = NULL;
1082     info->size = 0;
1083     info->maxsize = 0;
1084     return TRUE;
1085   }
1086 cannot_map:
1087   {
1088     GST_DEBUG_OBJECT (buffer, "cannot map memory");
1089     return FALSE;
1090   }
1091 }
1092
1093 /**
1094  * gst_buffer_unmap:
1095  * @buffer: a #GstBuffer.
1096  * @info: a #GstMapInfo
1097  *
1098  * Release the memory previously mapped with gst_buffer_map().
1099  */
1100 void
1101 gst_buffer_unmap (GstBuffer * buffer, GstMapInfo * info)
1102 {
1103   g_return_if_fail (GST_IS_BUFFER (buffer));
1104   g_return_if_fail (info != NULL);
1105
1106   /* we need to check for NULL, it is possible that we tried to map a buffer
1107    * without memory and we should be able to unmap that fine */
1108   if (G_LIKELY (info->memory)) {
1109     gst_memory_unmap (info->memory, info);
1110     gst_memory_unref (info->memory);
1111   }
1112 }
1113
1114 /**
1115  * gst_buffer_fill:
1116  * @buffer: a #GstBuffer.
1117  * @offset: the offset to fill
1118  * @src: the source address
1119  * @size: the size to fill
1120  *
1121  * Copy @size bytes from @src to @buffer at @offset.
1122  *
1123  * Returns: The amount of bytes copied. This value can be lower than @size
1124  *    when @buffer did not contain enough data.
1125  */
1126 gsize
1127 gst_buffer_fill (GstBuffer * buffer, gsize offset, gconstpointer src,
1128     gsize size)
1129 {
1130   gsize i, len, left;
1131   const guint8 *ptr = src;
1132
1133   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
1134   g_return_val_if_fail (gst_buffer_is_writable (buffer), 0);
1135   g_return_val_if_fail (src != NULL, 0);
1136
1137   len = GST_BUFFER_MEM_LEN (buffer);
1138   left = size;
1139
1140   for (i = 0; i < len && left > 0; i++) {
1141     GstMapInfo info;
1142     gsize tocopy;
1143     GstMemory *mem;
1144
1145     mem = _get_mapped (buffer, i, &info, GST_MAP_WRITE);
1146     if (info.size > offset) {
1147       /* we have enough */
1148       tocopy = MIN (info.size - offset, left);
1149       memcpy ((guint8 *) info.data + offset, ptr, tocopy);
1150       left -= tocopy;
1151       ptr += tocopy;
1152       offset = 0;
1153     } else {
1154       /* offset past buffer, skip */
1155       offset -= info.size;
1156     }
1157     gst_memory_unmap (mem, &info);
1158   }
1159   return size - left;
1160 }
1161
1162 /**
1163  * gst_buffer_extract:
1164  * @buffer: a #GstBuffer.
1165  * @offset: the offset to extract
1166  * @dest: the destination address
1167  * @size: the size to extract
1168  *
1169  * Copy @size bytes starting from @offset in @buffer to @dest.
1170  *
1171  * Returns: The amount of bytes extracted. This value can be lower than @size
1172  *    when @buffer did not contain enough data.
1173  */
1174 gsize
1175 gst_buffer_extract (GstBuffer * buffer, gsize offset, gpointer dest, gsize size)
1176 {
1177   gsize i, len, left;
1178   guint8 *ptr = dest;
1179
1180   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
1181   g_return_val_if_fail (dest != NULL, 0);
1182
1183   len = GST_BUFFER_MEM_LEN (buffer);
1184   left = size;
1185
1186   for (i = 0; i < len && left > 0; i++) {
1187     GstMapInfo info;
1188     gsize tocopy;
1189     GstMemory *mem;
1190
1191     mem = _get_mapped (buffer, i, &info, GST_MAP_READ);
1192     if (info.size > offset) {
1193       /* we have enough */
1194       tocopy = MIN (info.size - offset, left);
1195       memcpy (ptr, (guint8 *) info.data + offset, tocopy);
1196       left -= tocopy;
1197       ptr += tocopy;
1198       offset = 0;
1199     } else {
1200       /* offset past buffer, skip */
1201       offset -= info.size;
1202     }
1203     gst_memory_unmap (mem, &info);
1204   }
1205   return size - left;
1206 }
1207
1208 /**
1209  * gst_buffer_memcmp:
1210  * @buffer: a #GstBuffer.
1211  * @offset: the offset in @buffer
1212  * @mem: the memory to compare
1213  * @size: the size to compare
1214  *
1215  * Compare @size bytes starting from @offset in @buffer with the memory in @mem.
1216  *
1217  * Returns: 0 if the memory is equal.
1218  */
1219 gint
1220 gst_buffer_memcmp (GstBuffer * buffer, gsize offset, gconstpointer mem,
1221     gsize size)
1222 {
1223   gsize i, len;
1224   const guint8 *ptr = mem;
1225   gint res = 0;
1226
1227   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
1228   g_return_val_if_fail (mem != NULL, 0);
1229
1230   len = GST_BUFFER_MEM_LEN (buffer);
1231
1232   for (i = 0; i < len && size > 0 && res == 0; i++) {
1233     GstMapInfo info;
1234     gsize tocmp;
1235     GstMemory *mem;
1236
1237     mem = _get_mapped (buffer, i, &info, GST_MAP_READ);
1238     if (info.size > offset) {
1239       /* we have enough */
1240       tocmp = MIN (info.size - offset, size);
1241       res = memcmp (ptr, (guint8 *) info.data + offset, tocmp);
1242       size -= tocmp;
1243       ptr += tocmp;
1244       offset = 0;
1245     } else {
1246       /* offset past buffer, skip */
1247       offset -= info.size;
1248     }
1249     gst_memory_unmap (mem, &info);
1250   }
1251   return res;
1252 }
1253
1254 /**
1255  * gst_buffer_memset:
1256  * @buffer: a #GstBuffer.
1257  * @offset: the offset in @buffer
1258  * @val: the value to set
1259  * @size: the size to set
1260  *
1261  * Fill @buf with @size bytes with @val starting from @offset.
1262  *
1263  * Returns: The amount of bytes filled. This value can be lower than @size
1264  *    when @buffer did not contain enough data.
1265  */
1266 gsize
1267 gst_buffer_memset (GstBuffer * buffer, gsize offset, guint8 val, gsize size)
1268 {
1269   gsize i, len, left;
1270
1271   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
1272   g_return_val_if_fail (gst_buffer_is_writable (buffer), 0);
1273
1274   len = GST_BUFFER_MEM_LEN (buffer);
1275   left = size;
1276
1277   for (i = 0; i < len && left > 0; i++) {
1278     GstMapInfo info;
1279     gsize toset;
1280     GstMemory *mem;
1281
1282     mem = _get_mapped (buffer, i, &info, GST_MAP_WRITE);
1283     if (info.size > offset) {
1284       /* we have enough */
1285       toset = MIN (info.size - offset, left);
1286       memset ((guint8 *) info.data + offset, val, toset);
1287       left -= toset;
1288       offset = 0;
1289     } else {
1290       /* offset past buffer, skip */
1291       offset -= info.size;
1292     }
1293     gst_memory_unmap (mem, &info);
1294   }
1295   return size - left;
1296 }
1297
1298 /**
1299  * gst_buffer_copy_region:
1300  * @parent: a #GstBuffer.
1301  * @flags: the #GstBufferCopyFlags
1302  * @offset: the offset into parent #GstBuffer at which the new sub-buffer 
1303  *          begins.
1304  * @size: the size of the new #GstBuffer sub-buffer, in bytes.
1305  *
1306  * Creates a sub-buffer from @parent at @offset and @size.
1307  * This sub-buffer uses the actual memory space of the parent buffer.
1308  * This function will copy the offset and timestamp fields when the
1309  * offset is 0. If not, they will be set to #GST_CLOCK_TIME_NONE and 
1310  * #GST_BUFFER_OFFSET_NONE.
1311  * If @offset equals 0 and @size equals the total size of @buffer, the
1312  * duration and offset end fields are also copied. If not they will be set
1313  * to #GST_CLOCK_TIME_NONE and #GST_BUFFER_OFFSET_NONE.
1314  *
1315  * MT safe.
1316  *
1317  * Returns: (transfer full): the new #GstBuffer or NULL if the arguments were
1318  *     invalid.
1319  */
1320 GstBuffer *
1321 gst_buffer_copy_region (GstBuffer * buffer, GstBufferCopyFlags flags,
1322     gsize offset, gsize size)
1323 {
1324   GstBuffer *copy;
1325
1326   g_return_val_if_fail (buffer != NULL, NULL);
1327
1328   /* create the new buffer */
1329   copy = gst_buffer_new ();
1330
1331   GST_CAT_LOG (GST_CAT_BUFFER, "new region copy %p of %p %" G_GSIZE_FORMAT
1332       "-%" G_GSIZE_FORMAT, copy, buffer, offset, size);
1333
1334   gst_buffer_copy_into (copy, buffer, flags, offset, size);
1335
1336   return copy;
1337 }
1338
1339 /**
1340  * gst_buffer_append:
1341  * @buf1: (transfer full): the first source #GstBuffer to append.
1342  * @buf2: (transfer full): the second source #GstBuffer to append.
1343  *
1344  * Append all the memory from @buf2 to @buf1. The result buffer will contain a
1345  * concatenation of the memory of @buf1 and @buf2.
1346  *
1347  * Returns: (transfer full): the new #GstBuffer that contains the memory
1348  *     of the two source buffers.
1349  */
1350 GstBuffer *
1351 gst_buffer_append (GstBuffer * buf1, GstBuffer * buf2)
1352 {
1353   gsize i, len;
1354
1355   g_return_val_if_fail (GST_IS_BUFFER (buf1), NULL);
1356   g_return_val_if_fail (GST_IS_BUFFER (buf2), NULL);
1357
1358   buf1 = gst_buffer_make_writable (buf1);
1359   buf2 = gst_buffer_make_writable (buf2);
1360
1361   len = GST_BUFFER_MEM_LEN (buf2);
1362   for (i = 0; i < len; i++) {
1363     GstMemory *mem;
1364
1365     mem = GST_BUFFER_MEM_PTR (buf2, i);
1366     GST_BUFFER_MEM_PTR (buf2, i) = NULL;
1367     _memory_add (buf1, -1, mem);
1368   }
1369
1370   /* we can calculate the duration too. Also make sure we're not messing
1371    * with invalid DURATIONS */
1372   if (GST_BUFFER_DURATION_IS_VALID (buf1) &&
1373       GST_BUFFER_DURATION_IS_VALID (buf2)) {
1374     /* add duration */
1375     GST_BUFFER_DURATION (buf1) += GST_BUFFER_DURATION (buf2);
1376   }
1377   if (GST_BUFFER_OFFSET_END_IS_VALID (buf2)) {
1378     /* set offset_end */
1379     GST_BUFFER_OFFSET_END (buf1) = GST_BUFFER_OFFSET_END (buf2);
1380   }
1381
1382   GST_BUFFER_MEM_LEN (buf2) = 0;
1383   gst_buffer_unref (buf2);
1384
1385   return buf1;
1386 }
1387
1388 /**
1389  * gst_buffer_get_meta:
1390  * @buffer: a #GstBuffer
1391  * @api: the #GType of an API
1392  *
1393  * Get the metadata for @api on buffer. When there is no such
1394  * metadata, NULL is returned.
1395  *
1396  * Returns: the metadata for @api on @buffer.
1397  */
1398 GstMeta *
1399 gst_buffer_get_meta (GstBuffer * buffer, GType api)
1400 {
1401   GstMetaItem *item;
1402   GstMeta *result = NULL;
1403
1404   g_return_val_if_fail (buffer != NULL, NULL);
1405   g_return_val_if_fail (api != 0, NULL);
1406
1407   /* find GstMeta of the requested API */
1408   for (item = GST_BUFFER_META (buffer); item; item = item->next) {
1409     GstMeta *meta = &item->meta;
1410     if (meta->info->api == api) {
1411       result = meta;
1412       break;
1413     }
1414   }
1415   return result;
1416 }
1417
1418 /**
1419  * gst_buffer_add_meta:
1420  * @buffer: a #GstBuffer
1421  * @info: a #GstMetaInfo
1422  * @params: params for @info
1423  *
1424  * Add metadata for @info to @buffer using the parameters in @params.
1425  *
1426  * Returns: (transfer none): the metadata for the api in @info on @buffer.
1427  */
1428 GstMeta *
1429 gst_buffer_add_meta (GstBuffer * buffer, const GstMetaInfo * info,
1430     gpointer params)
1431 {
1432   GstMetaItem *item;
1433   GstMeta *result = NULL;
1434   gsize size;
1435
1436   g_return_val_if_fail (buffer != NULL, NULL);
1437   g_return_val_if_fail (info != NULL, NULL);
1438   g_return_val_if_fail (gst_buffer_is_writable (buffer), NULL);
1439
1440   /* create a new slice */
1441   size = ITEM_SIZE (info);
1442   item = g_slice_alloc (size);
1443   result = &item->meta;
1444   result->info = info;
1445   result->flags = GST_META_FLAG_NONE;
1446
1447   GST_CAT_DEBUG (GST_CAT_BUFFER,
1448       "alloc metadata %p (%s) of size %" G_GSIZE_FORMAT, result,
1449       g_type_name (info->type), info->size);
1450
1451   /* call the init_func when needed */
1452   if (info->init_func)
1453     if (!info->init_func (result, params, buffer))
1454       goto init_failed;
1455
1456   /* and add to the list of metadata */
1457   item->next = GST_BUFFER_META (buffer);
1458   GST_BUFFER_META (buffer) = item;
1459
1460   return result;
1461
1462 init_failed:
1463   {
1464     g_slice_free1 (size, item);
1465     return NULL;
1466   }
1467 }
1468
1469 /**
1470  * gst_buffer_remove_meta:
1471  * @buffer: a #GstBuffer
1472  * @meta: a #GstMeta
1473  *
1474  * Remove the metadata for @meta on @buffer.
1475  *
1476  * Returns: %TRUE if the metadata existed and was removed, %FALSE if no such
1477  * metadata was on @buffer.
1478  */
1479 gboolean
1480 gst_buffer_remove_meta (GstBuffer * buffer, GstMeta * meta)
1481 {
1482   GstMetaItem *walk, *prev;
1483
1484   g_return_val_if_fail (buffer != NULL, FALSE);
1485   g_return_val_if_fail (meta != NULL, FALSE);
1486   g_return_val_if_fail (gst_buffer_is_writable (buffer), FALSE);
1487
1488   /* find the metadata and delete */
1489   prev = GST_BUFFER_META (buffer);
1490   for (walk = prev; walk; walk = walk->next) {
1491     GstMeta *m = &walk->meta;
1492     if (m == meta) {
1493       const GstMetaInfo *info = meta->info;
1494
1495       /* remove from list */
1496       if (GST_BUFFER_META (buffer) == walk)
1497         GST_BUFFER_META (buffer) = walk->next;
1498       else
1499         prev->next = walk->next;
1500       /* call free_func if any */
1501       if (info->free_func)
1502         info->free_func (m, buffer);
1503
1504       /* and free the slice */
1505       g_slice_free1 (ITEM_SIZE (info), walk);
1506       break;
1507     }
1508     prev = walk;
1509   }
1510   return walk != NULL;
1511 }
1512
1513 /**
1514  * gst_buffer_iterate_meta:
1515  * @buffer: a #GstBuffer
1516  * @state: an opaque state pointer
1517  *
1518  * Retrieve the next #GstMeta after @current. If @state points
1519  * to %NULL, the first metadata is returned.
1520  *
1521  * @state will be updated with an opage state pointer 
1522  *
1523  * Returns: The next #GstMeta or %NULL when there are no more items.
1524  */
1525 GstMeta *
1526 gst_buffer_iterate_meta (GstBuffer * buffer, gpointer * state)
1527 {
1528   GstMetaItem **meta;
1529
1530   g_return_val_if_fail (buffer != NULL, NULL);
1531   g_return_val_if_fail (state != NULL, NULL);
1532
1533   meta = (GstMetaItem **) state;
1534   if (*meta == NULL)
1535     /* state NULL, move to first item */
1536     *meta = GST_BUFFER_META (buffer);
1537   else
1538     /* state !NULL, move to next item in list */
1539     *meta = (*meta)->next;
1540
1541   if (*meta)
1542     return &(*meta)->meta;
1543   else
1544     return NULL;
1545 }
1546
1547 /**
1548  * gst_buffer_foreach_meta:
1549  * @buffer: a #GstBuffer
1550  * @func: (scope call): a #GstBufferForeachMetaFunc to call
1551  * @user_data: (closure): user data passed to @func
1552  *
1553  * Call @func with @user_data for each meta in @buffer.
1554  *
1555  * @func can modify the passed meta pointer or its contents. The return value
1556  * of @func define if this function returns or if the remaining metadata items
1557  * in the buffer should be skipped.
1558  */
1559 void
1560 gst_buffer_foreach_meta (GstBuffer * buffer, GstBufferForeachMetaFunc func,
1561     gpointer user_data)
1562 {
1563   GstMetaItem *walk, *prev, *next;
1564
1565   g_return_if_fail (buffer != NULL);
1566   g_return_if_fail (func != NULL);
1567
1568   /* find the metadata and delete */
1569   prev = GST_BUFFER_META (buffer);
1570   for (walk = prev; walk; walk = next) {
1571     GstMeta *m, *new;
1572     gboolean res;
1573
1574     m = new = &walk->meta;
1575     next = walk->next;
1576
1577     res = func (buffer, &new, user_data);
1578
1579     if (new == NULL) {
1580       const GstMetaInfo *info = m->info;
1581
1582       GST_CAT_DEBUG (GST_CAT_BUFFER, "remove metadata %p (%s)", m,
1583           g_type_name (info->type));
1584
1585       g_return_if_fail (gst_buffer_is_writable (buffer));
1586
1587       /* remove from list */
1588       if (GST_BUFFER_META (buffer) == walk)
1589         GST_BUFFER_META (buffer) = next;
1590       else
1591         prev->next = next;
1592
1593       /* call free_func if any */
1594       if (info->free_func)
1595         info->free_func (m, buffer);
1596
1597       /* and free the slice */
1598       g_slice_free1 (ITEM_SIZE (info), walk);
1599     }
1600     if (!res)
1601       break;
1602   }
1603 }