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