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