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