miniobject: fix debug
[platform/upstream/gstreamer.git] / gst / gstbuffer.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wtay@chello.be>
4  *
5  * gstbuffer.c: Buffer operations
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 /**
24  * SECTION:gstbuffer
25  * @short_description: Data-passing buffer type, supporting sub-buffers.
26  * @see_also: #GstPad, #GstMiniObject
27  *
28  * Buffers are the basic unit of data transfer in GStreamer.  The #GstBuffer
29  * type provides all the state necessary to define the regions of memory as
30  * part of a stream. Region copies are also supported, allowing a smaller
31  * region of a buffer to become its own buffer, with mechanisms in place to
32  * ensure that neither memory space goes away prematurely.
33  *
34  * Buffers are usually created with gst_buffer_new(). After a buffer has been
35  * created one will typically allocate memory for it and set the size of the
36  * buffer data.  The following example creates a buffer that can hold a given
37  * video frame with a given width, height and bits per plane.
38  * <example>
39  * <title>Creating a buffer for a video frame</title>
40  *   <programlisting>
41  *   GstBuffer *buffer;
42  *   gint size, width, height, bpp;
43  *   ...
44  *   size = width * height * bpp;
45  *   buffer = gst_buffer_new ();
46  *   GST_BUFFER_SIZE (buffer) = size;
47  *   GST_BUFFER_MALLOCDATA (buffer) = g_malloc (size);
48  *   GST_BUFFER_DATA (buffer) = GST_BUFFER_MALLOCDATA (buffer);
49  *   ...
50  *   </programlisting>
51  * </example>
52  *
53  * Alternatively, use gst_buffer_new_and_alloc()
54  * to create a buffer with preallocated data of a given size.
55  *
56  * The data pointed to by the buffer can be retrieved with the GST_BUFFER_DATA()
57  * macro. The size of the data can be found with GST_BUFFER_SIZE(). For buffers
58  * of size 0, the data pointer is undefined (usually NULL) and should never be used.
59  *
60  * If an element knows what pad you will push the buffer out on, it should use
61  * gst_pad_alloc_buffer() instead to create a buffer.  This allows downstream
62  * elements to provide special buffers to write in, like hardware buffers.
63  *
64  * A buffer has a pointer to a #GstCaps describing the media type of the data
65  * in the buffer. Attach caps to the buffer with gst_buffer_set_caps(); this
66  * is typically done before pushing out a buffer using gst_pad_push() so that
67  * the downstream element knows the type of the buffer.
68  *
69  * A buffer will usually have a timestamp, and a duration, but neither of these
70  * are guaranteed (they may be set to #GST_CLOCK_TIME_NONE). Whenever a
71  * meaningful value can be given for these, they should be set. The timestamp
72  * and duration are measured in nanoseconds (they are #GstClockTime values).
73  *
74  * A buffer can also have one or both of a start and an end offset. These are
75  * media-type specific. For video buffers, the start offset will generally be
76  * the frame number. For audio buffers, it will be the number of samples
77  * produced so far. For compressed data, it could be the byte offset in a
78  * source or destination file. Likewise, the end offset will be the offset of
79  * the end of the buffer. These can only be meaningfully interpreted if you
80  * know the media type of the buffer (the #GstCaps set on it). Either or both
81  * can be set to #GST_BUFFER_OFFSET_NONE.
82  *
83  * gst_buffer_ref() is used to increase the refcount of a buffer. This must be
84  * done when you want to keep a handle to the buffer after pushing it to the
85  * next element.
86  *
87  * To efficiently create a smaller buffer out of an existing one, you can
88  * use gst_buffer_copy_region().
89  *
90  * If a plug-in wants to modify the buffer data or metadata in-place, it should
91  * first obtain a buffer that is safe to modify by using
92  * gst_buffer_make_writable().  This function is optimized so that a copy will
93  * only be made when it is necessary.
94  *
95  * Several flags of the buffer can be set and unset with the
96  * GST_BUFFER_FLAG_SET() and GST_BUFFER_FLAG_UNSET() macros. Use
97  * GST_BUFFER_FLAG_IS_SET() to test if a certain #GstBufferFlag is set.
98  *
99  * Buffers can be efficiently merged into a larger buffer with
100  * gst_buffer_span(), which avoids memory copies when the gst_buffer_is_span_fast()
101  * function returns TRUE.
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 data pointed to by the buffer is unreffed as
108  * well.
109  *
110  * Last reviewed on March 30, 2011 (0.11.0)
111  */
112 #include "gst_private.h"
113
114 #ifdef HAVE_UNISTD_H
115 #include <unistd.h>
116 #endif
117 #ifdef HAVE_STDLIB_H
118 #include <stdlib.h>
119 #endif
120
121 #include "gstbuffer.h"
122 #include "gstbufferpool.h"
123 #include "gstinfo.h"
124 #include "gstutils.h"
125 #include "gstminiobject.h"
126 #include "gstversion.h"
127
128 GType _gst_buffer_type = 0;
129
130 static GstMemory *_gst_buffer_arr_span (GstMemory ** mem[], gsize len[],
131     guint n, gsize offset, gsize size, gboolean writable);
132
133 typedef struct _GstMetaItem GstMetaItem;
134
135 struct _GstMetaItem
136 {
137   GstMetaItem *next;
138   GstMeta meta;
139 };
140 #define ITEM_SIZE(info) ((info)->size + sizeof (GstMetaItem))
141
142 #define GST_BUFFER_MEM_MAX         16
143
144 #define GST_BUFFER_MEM_LEN(b)      (((GstBufferImpl *)(b))->len)
145 #define GST_BUFFER_MEM_ARRAY(b)    (((GstBufferImpl *)(b))->mem)
146 #define GST_BUFFER_MEM_PTR(b,i)    (((GstBufferImpl *)(b))->mem[i])
147 #define GST_BUFFER_META(b)         (((GstBufferImpl *)(b))->item)
148
149 typedef struct
150 {
151   GstBuffer buffer;
152
153   /* the memory blocks */
154   guint len;
155   GstMemory *mem[GST_BUFFER_MEM_MAX];
156
157   /* FIXME, make metadata allocation more efficient by using part of the
158    * GstBufferImpl */
159   GstMetaItem *item;
160 } GstBufferImpl;
161
162 static GstMemory *
163 _span_memory (GstBuffer * buffer, gsize offset, gsize size, gboolean writable)
164 {
165   GstMemory *span, **mem[1];
166   gsize len[1];
167
168   /* not enough room, span buffers */
169   mem[0] = GST_BUFFER_MEM_ARRAY (buffer);
170   len[0] = GST_BUFFER_MEM_LEN (buffer);
171
172   if (size == -1)
173     size = gst_buffer_get_size (buffer);
174
175   span = _gst_buffer_arr_span (mem, len, 1, offset, size, writable);
176
177   return span;
178 }
179
180 static void
181 _replace_memory (GstBuffer * buffer, GstMemory * mem)
182 {
183   gsize len, i;
184
185   /* unref old buffers */
186   len = GST_BUFFER_MEM_LEN (buffer);
187   for (i = 0; i < len; i++)
188     gst_memory_unref (GST_BUFFER_MEM_PTR (buffer, i));
189
190   /* replace with single spanned buffer */
191   GST_BUFFER_MEM_PTR (buffer, 0) = mem;
192   GST_BUFFER_MEM_LEN (buffer) = 1;
193 }
194
195 static inline void
196 _memory_add (GstBuffer * buffer, GstMemory * mem)
197 {
198   guint len = GST_BUFFER_MEM_LEN (buffer);
199
200   if (G_UNLIKELY (len >= GST_BUFFER_MEM_MAX)) {
201     /* to many buffer, span them */
202     _replace_memory (buffer, _span_memory (buffer, 0, -1, FALSE));
203     /* we now have 1 single spanned buffer */
204     len = 1;
205   }
206   /* and append the new buffer */
207   GST_BUFFER_MEM_PTR (buffer, len) = mem;
208   GST_BUFFER_MEM_LEN (buffer) = len + 1;
209 }
210
211 #if 1
212 /* buffer alignment in bytes
213  * an alignment of 8 would be the same as malloc() guarantees
214  */
215 #ifdef HAVE_POSIX_MEMALIGN
216 #if defined(BUFFER_ALIGNMENT_MALLOC)
217 static size_t _gst_buffer_data_alignment = 8;
218 #elif defined(BUFFER_ALIGNMENT_PAGESIZE)
219 static size_t _gst_buffer_data_alignment = 0;
220 #elif defined(BUFFER_ALIGNMENT)
221 static size_t _gst_buffer_data_alignment = BUFFER_ALIGNMENT;
222 #else
223 #error "No buffer alignment configured"
224 #endif
225 #endif /* HAVE_POSIX_MEMALIGN */
226 #endif
227
228 void
229 _gst_buffer_initialize (void)
230 {
231   if (G_LIKELY (_gst_buffer_type == 0)) {
232     _gst_buffer_type = gst_mini_object_register ("GstBuffer");
233 #ifdef HAVE_GETPAGESIZE
234 #ifdef BUFFER_ALIGNMENT_PAGESIZE
235     _gst_buffer_data_alignment = getpagesize ();
236 #endif
237 #endif
238   }
239 }
240
241 /**
242  * gst_buffer_copy_into:
243  * @dest: a destination #GstBuffer
244  * @src: a source #GstBuffer
245  * @flags: flags indicating what metadata fields should be copied.
246  * @offset: offset to copy from
247  * @size: total size to copy
248  *
249  * Copies the information from @src into @dest.
250  *
251  * @flags indicate which fields will be copied.
252  */
253 void
254 gst_buffer_copy_into (GstBuffer * dest, GstBuffer * src,
255     GstBufferCopyFlags flags, gsize offset, gsize size)
256 {
257   GstMetaItem *walk;
258   gsize bufsize;
259
260   g_return_if_fail (dest != NULL);
261   g_return_if_fail (src != NULL);
262
263   /* nothing to copy if the buffers are the same */
264   if (G_UNLIKELY (dest == src))
265     return;
266
267   g_return_if_fail (gst_buffer_is_writable (dest));
268
269   bufsize = gst_buffer_get_size (src);
270   g_return_if_fail (bufsize >= offset);
271   if (size == -1)
272     size = bufsize - offset;
273   g_return_if_fail (bufsize >= offset + size);
274
275   GST_CAT_LOG (GST_CAT_BUFFER, "copy %p to %p, offset %" G_GSIZE_FORMAT
276       "-%" G_GSIZE_FORMAT "/%" G_GSIZE_FORMAT, src, dest, offset, size,
277       bufsize);
278
279   if (flags & GST_BUFFER_COPY_FLAGS) {
280     guint mask;
281
282     /* copy relevant flags */
283     mask = GST_BUFFER_FLAG_PREROLL | GST_BUFFER_FLAG_IN_CAPS |
284         GST_BUFFER_FLAG_DELTA_UNIT | GST_BUFFER_FLAG_DISCONT |
285         GST_BUFFER_FLAG_GAP | GST_BUFFER_FLAG_MEDIA1 |
286         GST_BUFFER_FLAG_MEDIA2 | GST_BUFFER_FLAG_MEDIA3;
287     GST_MINI_OBJECT_FLAGS (dest) |= GST_MINI_OBJECT_FLAGS (src) & mask;
288   }
289
290   if (flags & GST_BUFFER_COPY_TIMESTAMPS) {
291     if (offset == 0) {
292       GST_BUFFER_TIMESTAMP (dest) = GST_BUFFER_TIMESTAMP (src);
293       GST_BUFFER_OFFSET (dest) = GST_BUFFER_OFFSET (src);
294       if (size == bufsize) {
295         GST_BUFFER_DURATION (dest) = GST_BUFFER_DURATION (src);
296         GST_BUFFER_OFFSET_END (dest) = GST_BUFFER_OFFSET_END (src);
297       }
298     } else {
299       GST_BUFFER_TIMESTAMP (dest) = GST_CLOCK_TIME_NONE;
300       GST_BUFFER_DURATION (dest) = GST_CLOCK_TIME_NONE;
301       GST_BUFFER_OFFSET (dest) = GST_BUFFER_OFFSET_NONE;
302       GST_BUFFER_OFFSET_END (dest) = GST_BUFFER_OFFSET_NONE;
303     }
304   }
305
306   if (flags & GST_BUFFER_COPY_CAPS) {
307     gst_caps_replace (&GST_BUFFER_CAPS (dest), GST_BUFFER_CAPS (src));
308   }
309
310   if (flags & GST_BUFFER_COPY_MEMORY) {
311     GstMemory *mem;
312     gsize left, len, i, bsize;
313
314     len = GST_BUFFER_MEM_LEN (src);
315     left = size;
316
317     /* copy and make regions of the memory */
318     for (i = 0; i < len && left > 0; i++) {
319       mem = GST_BUFFER_MEM_PTR (src, i);
320       bsize = gst_memory_get_sizes (mem, NULL);
321
322       if (bsize <= offset) {
323         /* don't copy buffer */
324         offset -= bsize;
325       } else {
326         gsize tocopy;
327
328         tocopy = MIN (bsize - offset, left);
329         if (tocopy < bsize) {
330           /* we need to clip something */
331           mem = gst_memory_share (mem, offset, tocopy);
332         } else {
333           mem = gst_memory_ref (mem);
334         }
335         _memory_add (dest, mem);
336         left -= tocopy;
337       }
338     }
339     if (flags & GST_BUFFER_COPY_MERGE) {
340       _replace_memory (dest, _span_memory (dest, 0, size, FALSE));
341     }
342   }
343
344   for (walk = GST_BUFFER_META (src); walk; walk = walk->next) {
345     GstMeta *meta = &walk->meta;
346     const GstMetaInfo *info = meta->info;
347
348     if (info->copy_func)
349       info->copy_func (dest, meta, src, offset, size);
350   }
351 }
352
353 static GstBuffer *
354 _gst_buffer_copy (GstBuffer * buffer)
355 {
356   GstBuffer *copy;
357
358   g_return_val_if_fail (buffer != NULL, NULL);
359
360   /* create a fresh new buffer */
361   copy = gst_buffer_new ();
362
363   /* we simply copy everything from our parent */
364   gst_buffer_copy_into (copy, buffer, GST_BUFFER_COPY_ALL, 0, -1);
365
366   return copy;
367 }
368
369 /* the default dispose function revives the buffer and returns it to the
370  * pool when there is a pool */
371 static void
372 _gst_buffer_dispose (GstBuffer * buffer)
373 {
374   GstBufferPool *pool;
375
376   if ((pool = buffer->pool) != NULL) {
377     /* keep the buffer alive */
378     gst_buffer_ref (buffer);
379     /* return the buffer to the pool */
380     GST_CAT_LOG (GST_CAT_BUFFER, "release %p to pool %p", buffer, pool);
381     gst_buffer_pool_release_buffer (pool, buffer);
382   }
383 }
384
385 static void
386 _gst_buffer_free (GstBuffer * buffer)
387 {
388   GstMetaItem *walk, *next;
389   guint i, len;
390   gsize msize;
391
392   g_return_if_fail (buffer != NULL);
393
394   GST_CAT_LOG (GST_CAT_BUFFER, "finalize %p", buffer);
395
396   gst_caps_replace (&GST_BUFFER_CAPS (buffer), NULL);
397
398   /* free metadata */
399   for (walk = GST_BUFFER_META (buffer); walk; walk = next) {
400     GstMeta *meta = &walk->meta;
401     const GstMetaInfo *info = meta->info;
402
403     /* call free_func if any */
404     if (info->free_func)
405       info->free_func (meta, buffer);
406
407     next = walk->next;
408     /* and free the slice */
409     g_slice_free1 (ITEM_SIZE (info), walk);
410   }
411
412   /* get the size, when unreffing the memory, we could also unref the buffer
413    * itself */
414   msize = GST_MINI_OBJECT_SIZE (buffer);
415
416   /* free our memory */
417   len = GST_BUFFER_MEM_LEN (buffer);
418   for (i = 0; i < len; i++)
419     gst_memory_unref (GST_BUFFER_MEM_PTR (buffer, i));
420
421   if (msize)
422     g_slice_free1 (msize, buffer);
423 }
424
425 static void
426 gst_buffer_init (GstBufferImpl * buffer, gsize size)
427 {
428   gst_mini_object_init (GST_MINI_OBJECT_CAST (buffer), _gst_buffer_type, size);
429
430   buffer->buffer.mini_object.copy =
431       (GstMiniObjectCopyFunction) _gst_buffer_copy;
432   buffer->buffer.mini_object.dispose =
433       (GstMiniObjectDisposeFunction) _gst_buffer_dispose;
434   buffer->buffer.mini_object.free =
435       (GstMiniObjectFreeFunction) _gst_buffer_free;
436
437   GST_BUFFER (buffer)->pool = NULL;
438   GST_BUFFER_CAPS (buffer) = NULL;
439   GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
440   GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
441   GST_BUFFER_OFFSET (buffer) = GST_BUFFER_OFFSET_NONE;
442   GST_BUFFER_OFFSET_END (buffer) = GST_BUFFER_OFFSET_NONE;
443
444   GST_BUFFER_MEM_LEN (buffer) = 0;
445   GST_BUFFER_META (buffer) = NULL;
446 }
447
448 /**
449  * gst_buffer_new:
450  *
451  * Creates a newly allocated buffer without any data.
452  *
453  * MT safe.
454  *
455  * Returns: (transfer full): the new #GstBuffer.
456  */
457 GstBuffer *
458 gst_buffer_new (void)
459 {
460   GstBufferImpl *newbuf;
461
462   newbuf = g_slice_new (GstBufferImpl);
463   GST_CAT_LOG (GST_CAT_BUFFER, "new %p", newbuf);
464
465   gst_buffer_init (newbuf, sizeof (GstBufferImpl));
466
467   return GST_BUFFER_CAST (newbuf);
468 }
469
470 /**
471  * gst_buffer_new_and_alloc:
472  * @size: the size in bytes of the new buffer's data.
473  *
474  * Tries to create a newly allocated buffer with data of the given size. If
475  * the requested amount of memory can't be allocated, NULL will be returned.
476  * The allocated buffer memory is not cleared.
477  *
478  * Note that when @size == 0, the buffer will not have memory associated with it.
479  *
480  * MT safe.
481  *
482  * Returns: (transfer full): a new #GstBuffer, or NULL if the memory couldn't
483  *     be allocated.
484  */
485 GstBuffer *
486 gst_buffer_new_and_alloc (guint size)
487 {
488   GstBuffer *newbuf;
489   GstMemory *mem;
490 #if 0
491   guint8 *data;
492   gsize asize;
493 #endif
494
495 #if 1
496   if (size > 0) {
497     mem = gst_memory_new_alloc (size, _gst_buffer_data_alignment);
498     if (G_UNLIKELY (mem == NULL))
499       goto no_memory;
500   } else {
501     mem = NULL;
502   }
503
504   newbuf = gst_buffer_new ();
505
506   if (mem != NULL)
507     _memory_add (newbuf, mem);
508
509   GST_CAT_LOG (GST_CAT_BUFFER, "new %p of size %d", newbuf, size);
510
511   return newbuf;
512 #endif
513
514 #if 0
515   asize = sizeof (GstBufferImpl) + size;
516   data = g_slice_alloc (asize);
517   if (G_UNLIKELY (data == NULL))
518     goto no_memory;
519
520   newbuf = GST_BUFFER_CAST (data);
521
522   gst_buffer_init ((GstBufferImpl *) data, asize);
523   if (size > 0) {
524     mem = gst_memory_new_wrapped (0, data + sizeof (GstBufferImpl), NULL,
525         size, 0, size);
526     _memory_add (newbuf, mem);
527   }
528
529   return newbuf;
530 #endif
531
532 #if 0
533   /* allocate memory and buffer */
534   asize = sizeof (GstBufferImpl) + size;
535   mem = gst_memory_new_alloc (asize, 0);
536   if (G_UNLIKELY (mem == NULL))
537     goto no_memory;
538
539   /* map the data part and init the buffer in it, set the buffer size to 0 so
540    * that a finalize won't free the buffer */
541   data = gst_memory_map (mem, &asize, NULL, GST_MAP_WRITE);
542   gst_buffer_init ((GstBufferImpl *) data, 0);
543   gst_memory_unmap (mem, data, asize);
544
545   /* strip off the buffer */
546   gst_memory_resize (mem, sizeof (GstBufferImpl), size);
547
548   newbuf = GST_BUFFER_CAST (data);
549
550   if (size > 0)
551     _memory_add (newbuf, mem);
552 #endif
553
554   return newbuf;
555
556   /* ERRORS */
557 no_memory:
558   {
559     GST_CAT_WARNING (GST_CAT_BUFFER, "failed to allocate %d bytes", size);
560     return NULL;
561   }
562 }
563
564 /**
565  * gst_buffer_n_memory:
566  * @buffer: a #GstBuffer.
567  *
568  * Get the amount of memory blocks that this buffer has.
569  *
570  * Returns: (transfer full): the amount of memory block in this buffer.
571  */
572 guint
573 gst_buffer_n_memory (GstBuffer * buffer)
574 {
575   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
576
577   return GST_BUFFER_MEM_LEN (buffer);
578 }
579
580 /**
581  * gst_buffer_take_memory:
582  * @buffer: a #GstBuffer.
583  * @mem: a #GstMemory.
584  *
585  * Add the memory block @mem to @buffer. This function takes ownership of @mem
586  * and thus doesn't increase its refcount.
587  */
588 void
589 gst_buffer_take_memory (GstBuffer * buffer, GstMemory * mem)
590 {
591   g_return_if_fail (GST_IS_BUFFER (buffer));
592   g_return_if_fail (gst_buffer_is_writable (buffer));
593   g_return_if_fail (mem != NULL);
594
595   _memory_add (buffer, mem);
596 }
597
598 /**
599  * gst_buffer_peek_memory:
600  * @buffer: a #GstBuffer.
601  * @idx: an index
602  *
603  * Get the memory block in @buffer at @idx. This function does not return a
604  * refcount to the memory block. The memory block stays valid for as long as the
605  * caller has a valid reference to @buffer.
606  *
607  * Returns: a #GstMemory at @idx.
608  */
609 GstMemory *
610 gst_buffer_peek_memory (GstBuffer * buffer, guint idx, GstMapFlags flags)
611 {
612   GstMemory *mem;
613   gboolean write;
614
615   write = (flags & GST_MAP_WRITE) != 0;
616
617   g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
618   g_return_val_if_fail (idx < GST_BUFFER_MEM_LEN (buffer), NULL);
619
620   /* check if we can write when asked for write access */
621   if (G_UNLIKELY (write && !gst_buffer_is_writable (buffer)))
622     goto not_writable;
623
624   mem = GST_BUFFER_MEM_PTR (buffer, idx);
625
626   return mem;
627
628   /* ERRORS */
629 not_writable:
630   {
631     g_return_val_if_fail (gst_buffer_is_writable (buffer), NULL);
632     return NULL;
633   }
634 }
635
636 /**
637  * gst_buffer_remove_memory_range:
638  * @buffer: a #GstBuffer.
639  * @idx: an index
640  * @length: a length
641  *
642  * Remove @len memory blocks in @buffer starting from @idx.
643  *
644  * @length can be -1, in which case all memory starting from @idx is removed.
645  */
646 void
647 gst_buffer_remove_memory_range (GstBuffer * buffer, guint idx, guint length)
648 {
649   guint len, i, end;
650
651   g_return_if_fail (GST_IS_BUFFER (buffer));
652   g_return_if_fail (gst_buffer_is_writable (buffer));
653
654   len = GST_BUFFER_MEM_LEN (buffer);
655   if (length == -1) {
656     g_return_if_fail (idx < len);
657     length = len - idx;
658   }
659
660   end = idx + length;
661   for (i = idx; i < end; i++)
662     gst_memory_unref (GST_BUFFER_MEM_PTR (buffer, i));
663
664   if (end != len) {
665     g_memmove (&GST_BUFFER_MEM_PTR (buffer, idx),
666         &GST_BUFFER_MEM_PTR (buffer, end), (len - end) * sizeof (gpointer));
667   }
668   GST_BUFFER_MEM_LEN (buffer) = len - length;
669 }
670
671 /**
672  * gst_buffer_get_size:
673  * @buffer: a #GstBuffer.
674  *
675  * Get the total size of all memory blocks in @buffer.
676  *
677  * Returns: the total size of the memory in @buffer.
678  */
679 gsize
680 gst_buffer_get_size (GstBuffer * buffer)
681 {
682   guint i, size, len;
683
684   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
685
686   len = GST_BUFFER_MEM_LEN (buffer);
687
688   size = 0;
689   for (i = 0; i < len; i++) {
690     size += gst_memory_get_sizes (GST_BUFFER_MEM_PTR (buffer, i), NULL);
691   }
692   return size;
693 }
694
695 /**
696  * gst_buffer_resize:
697  * @buffer: a #GstBuffer.
698  * @offset: the new offset
699  * @size: the new size
700  *
701  * Set the total size of the buffer
702  */
703 void
704 gst_buffer_resize (GstBuffer * buffer, gsize offset, gsize size)
705 {
706   guint len;
707   guint si, di;
708   gsize bsize, bufsize;
709   GstMemory *mem;
710
711   GST_CAT_LOG (GST_CAT_BUFFER, "trim %p %" G_GSIZE_FORMAT "-%" G_GSIZE_FORMAT,
712       buffer, offset, size);
713
714   g_return_if_fail (gst_buffer_is_writable (buffer));
715
716   bufsize = gst_buffer_get_size (buffer);
717   g_return_if_fail (bufsize >= offset);
718   if (size == -1)
719     size = bufsize - offset;
720   g_return_if_fail (bufsize >= offset + size);
721
722   len = GST_BUFFER_MEM_LEN (buffer);
723
724   /* copy and trim */
725   for (di = si = 0; si < len && size > 0; si++) {
726     mem = GST_BUFFER_MEM_PTR (buffer, si);
727     bsize = gst_memory_get_sizes (mem, NULL);
728
729     if (bsize <= offset) {
730       /* remove buffer */
731       gst_memory_unref (mem);
732       offset -= bsize;
733     } else {
734       gsize tocopy;
735
736       tocopy = MIN (bsize - offset, size);
737       if (tocopy < bsize) {
738         /* we need to clip something */
739         if (GST_MEMORY_IS_WRITABLE (mem)) {
740           gst_memory_resize (mem, offset, tocopy);
741         } else {
742           GstMemory *tmp;
743           tmp = gst_memory_share (mem, offset, tocopy);
744           gst_memory_unref (mem);
745           mem = tmp;
746         }
747       }
748       GST_BUFFER_MEM_PTR (buffer, di++) = mem;
749       size -= tocopy;
750     }
751   }
752   GST_BUFFER_MEM_LEN (buffer) = di;
753 }
754
755 /**
756  * gst_buffer_map:
757  * @buffer: a #GstBuffer.
758  * @size: a location for the size
759  * @maxsize: a location for the max size
760  * @flags: flags for the mapping
761  *
762  * This function return a pointer to the memory in @buffer. @flags describe the
763  * desired access of the memory. When @flags is #GST_MAP_WRITE, @buffer should
764  * be writable (as returned from gst_buffer_is_writable()).
765  *
766  * @size and @maxsize will contain the current valid number of bytes in the
767  * returned memory area and the total maximum mount of bytes available in the
768  * returned memory area respectively.
769  *
770  * When @buffer is writable but the memory isn't, a writable copy will
771  * automatically be created and returned. The readonly copy of the buffer memory
772  * will then also be replaced with this writable copy.
773  *
774  * When the buffer contains multiple memory blocks, the returned pointer will be
775  * a concatenation of the memory blocks.
776  *
777  * Returns: a pointer to the memory for the buffer.
778  */
779 gpointer
780 gst_buffer_map (GstBuffer * buffer, gsize * size, gsize * maxsize,
781     GstMapFlags flags)
782 {
783   guint len;
784   gpointer data;
785   GstMemory *mem;
786   gboolean write, writable;
787
788   g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
789
790   write = (flags & GST_MAP_WRITE) != 0;
791   writable = gst_buffer_is_writable (buffer);
792
793   /* check if we can write when asked for write access */
794   if (G_UNLIKELY (write && !writable))
795     goto not_writable;
796
797   len = GST_BUFFER_MEM_LEN (buffer);
798
799   if (G_UNLIKELY (len == 0)) {
800     /* no memory, return immediately */
801     if (size)
802       *size = 0;
803     if (maxsize)
804       *maxsize = 0;
805     return NULL;
806   }
807
808   if (G_LIKELY (len == 1)) {
809     /* we can take the first one */
810     mem = GST_BUFFER_MEM_PTR (buffer, 0);
811   } else {
812     /* we need to span memory */
813     if (writable) {
814       /* if we can write, we can change the memory with the spanned
815        * memory */
816       mem = _span_memory (buffer, 0, -1, write);
817       _replace_memory (buffer, mem);
818     } else {
819       gsize bsize;
820
821       /* extract all data in new memory, FIXME slow!! */
822       bsize = gst_buffer_get_size (buffer);
823
824       data = g_malloc (bsize);
825       gst_buffer_extract (buffer, 0, data, bsize);
826       if (size)
827         *size = bsize;
828       if (maxsize)
829         *maxsize = bsize;
830       return data;
831     }
832   }
833
834   if (G_UNLIKELY (write && !GST_MEMORY_IS_WRITABLE (mem))) {
835     GstMemory *copy;
836     /* replace with a writable copy */
837     copy = gst_memory_copy (mem, 0, -1);
838     GST_BUFFER_MEM_PTR (buffer, 0) = copy;
839     gst_memory_unref (mem);
840     mem = copy;
841   }
842
843   data = gst_memory_map (mem, size, maxsize, flags);
844
845   return data;
846
847   /* ERROR */
848 not_writable:
849   {
850     g_return_val_if_fail (gst_buffer_is_writable (buffer), NULL);
851     return NULL;
852   }
853 }
854
855 /**
856  * gst_buffer_unmap:
857  * @buffer: a #GstBuffer.
858  * @data: the previously mapped data
859  * @size: the size of @data
860  *
861  * Release the memory previously mapped with gst_buffer_map().
862  *
863  * Returns: #TRUE on success. #FALSE can be returned when the new size is larger
864  * than the maxsize of the memory.
865  */
866 gboolean
867 gst_buffer_unmap (GstBuffer * buffer, gpointer data, gsize size)
868 {
869   gboolean result;
870   guint len;
871
872   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
873
874   len = GST_BUFFER_MEM_LEN (buffer);
875
876   if (G_LIKELY (len == 1)) {
877     GstMemory *mem = GST_BUFFER_MEM_PTR (buffer, 0);
878
879     result = gst_memory_unmap (mem, data, size);
880   } else {
881     /* this must have been from read-only access. After _map, the buffer either
882      * only contains 1 memory block or it allocated memory to join memory
883      * blocks. It's not allowed to add buffers between _map and _unmap. */
884     g_free (data);
885     result = TRUE;
886   }
887   return result;
888 }
889
890 /**
891  * gst_buffer_fill:
892  * @buffer: a #GstBuffer.
893  * @offset: the offset to fill
894  * @src: the source address
895  * @size: the size to fill
896  *
897  * Copy @size bytes fro @src to @buffer at @offset.
898  */
899 void
900 gst_buffer_fill (GstBuffer * buffer, gsize offset, gconstpointer src,
901     gsize size)
902 {
903   gsize i, len;
904   const guint8 *ptr = src;
905
906   g_return_if_fail (GST_IS_BUFFER (buffer));
907   g_return_if_fail (gst_buffer_is_writable (buffer));
908   g_return_if_fail (src != NULL);
909
910   len = GST_BUFFER_MEM_LEN (buffer);
911
912   for (i = 0; i < len && size > 0; i++) {
913     guint8 *data;
914     gsize ssize, tocopy;
915     GstMemory *mem;
916
917     mem = GST_BUFFER_MEM_PTR (buffer, i);
918
919     data = gst_memory_map (mem, &ssize, NULL, GST_MAP_WRITE);
920     if (ssize > offset) {
921       /* we have enough */
922       tocopy = MIN (ssize - offset, size);
923       memcpy (data + offset, ptr, tocopy);
924       size -= tocopy;
925       ptr += tocopy;
926       offset = 0;
927     } else {
928       /* offset past buffer, skip */
929       offset -= ssize;
930     }
931     gst_memory_unmap (mem, data, ssize);
932   }
933 }
934
935 /**
936  * gst_buffer_extract:
937  * @buffer: a #GstBuffer.
938  * @offset: the offset to extract
939  * @dest: the destination address
940  * @size: the size to extract
941  *
942  * Copy @size bytes starting from @offset in @buffer to @dest.
943  */
944 void
945 gst_buffer_extract (GstBuffer * buffer, gsize offset, gpointer dest, gsize size)
946 {
947   gsize i, len;
948   guint8 *ptr = dest;
949
950   g_return_if_fail (GST_IS_BUFFER (buffer));
951   g_return_if_fail (dest != NULL);
952
953   len = GST_BUFFER_MEM_LEN (buffer);
954
955   for (i = 0; i < len && size > 0; i++) {
956     guint8 *data;
957     gsize ssize, tocopy;
958     GstMemory *mem;
959
960     mem = GST_BUFFER_MEM_PTR (buffer, i);
961
962     data = gst_memory_map (mem, &ssize, NULL, GST_MAP_READ);
963     if (ssize > offset) {
964       /* we have enough */
965       tocopy = MIN (ssize - offset, size);
966       memcpy (ptr, data + offset, tocopy);
967       size -= tocopy;
968       ptr += tocopy;
969       offset = 0;
970     } else {
971       /* offset past buffer, skip */
972       offset -= ssize;
973     }
974     gst_memory_unmap (mem, data, ssize);
975   }
976 }
977
978 /**
979  * gst_buffer_get_caps:
980  * @buffer: a #GstBuffer.
981  *
982  * Gets the media type of the buffer. This can be NULL if there
983  * is no media type attached to this buffer.
984  *
985  * Returns: (transfer full): a reference to the #GstCaps. unref after usage.
986  * Returns NULL if there were no caps on this buffer.
987  */
988 /* this is not made atomic because if the buffer were reffed from multiple
989  * threads, it would have a refcount > 2 and thus be immutable.
990  */
991 GstCaps *
992 gst_buffer_get_caps (GstBuffer * buffer)
993 {
994   GstCaps *ret;
995
996   g_return_val_if_fail (buffer != NULL, NULL);
997
998   ret = GST_BUFFER_CAPS (buffer);
999
1000   if (ret)
1001     gst_caps_ref (ret);
1002
1003   return ret;
1004 }
1005
1006 /**
1007  * gst_buffer_set_caps:
1008  * @buffer: a #GstBuffer.
1009  * @caps: (transfer none): a #GstCaps.
1010  *
1011  * Sets the media type on the buffer. The refcount of the caps will
1012  * be increased and any previous caps on the buffer will be
1013  * unreffed.
1014  */
1015 /* this is not made atomic because if the buffer were reffed from multiple
1016  * threads, it would have a refcount > 2 and thus be immutable.
1017  */
1018 void
1019 gst_buffer_set_caps (GstBuffer * buffer, GstCaps * caps)
1020 {
1021   g_return_if_fail (buffer != NULL);
1022   g_return_if_fail (caps == NULL || GST_CAPS_IS_SIMPLE (caps));
1023
1024 #if GST_VERSION_NANO == 1
1025   /* we enable this extra debugging in git versions only for now */
1026   g_warn_if_fail (gst_buffer_is_writable (buffer));
1027   /* FIXME: would be nice to also check if caps are fixed here, but expensive */
1028 #endif
1029
1030   gst_caps_replace (&GST_BUFFER_CAPS (buffer), caps);
1031 }
1032
1033 /**
1034  * gst_buffer_copy_region:
1035  * @parent: a #GstBuffer.
1036  * @offset: the offset into parent #GstBuffer at which the new sub-buffer 
1037  *          begins.
1038  * @size: the size of the new #GstBuffer sub-buffer, in bytes.
1039  *
1040  * Creates a sub-buffer from @parent at @offset and @size.
1041  * This sub-buffer uses the actual memory space of the parent buffer.
1042  * This function will copy the offset and timestamp fields when the
1043  * offset is 0. If not, they will be set to #GST_CLOCK_TIME_NONE and 
1044  * #GST_BUFFER_OFFSET_NONE.
1045  * If @offset equals 0 and @size equals the total size of @buffer, the
1046  * duration and offset end fields are also copied. If not they will be set
1047  * to #GST_CLOCK_TIME_NONE and #GST_BUFFER_OFFSET_NONE.
1048  *
1049  * MT safe.
1050  *
1051  * Returns: (transfer full): the new #GstBuffer or NULL if the arguments were
1052  *     invalid.
1053  */
1054 GstBuffer *
1055 gst_buffer_copy_region (GstBuffer * buffer, GstBufferCopyFlags flags,
1056     gsize offset, gsize size)
1057 {
1058   GstBuffer *copy;
1059
1060   g_return_val_if_fail (buffer != NULL, NULL);
1061
1062   /* create the new buffer */
1063   copy = gst_buffer_new ();
1064
1065   GST_CAT_LOG (GST_CAT_BUFFER, "new region copy %p of %p %" G_GSIZE_FORMAT
1066       "-%" G_GSIZE_FORMAT, copy, buffer, offset, size);
1067
1068   gst_buffer_copy_into (copy, buffer, flags, offset, size);
1069
1070   return copy;
1071 }
1072
1073 static gboolean
1074 _gst_buffer_arr_is_span_fast (GstMemory ** mem[], gsize len[], guint n,
1075     gsize * offset, GstMemory ** parent)
1076 {
1077   GstMemory *mcur, *mprv;
1078   gboolean have_offset = FALSE;
1079   guint count, i;
1080
1081   mcur = mprv = NULL;
1082   for (count = 0; count < n; count++) {
1083     gsize offs, clen;
1084     GstMemory **cmem;
1085
1086     cmem = mem[count];
1087     clen = len[count];
1088
1089     for (i = 0; i < clen; i++) {
1090       if (mcur)
1091         mprv = mcur;
1092       mcur = cmem[i];
1093
1094       if (mprv && mcur) {
1095         /* check is memory is contiguous */
1096         if (!gst_memory_is_span (mprv, mcur, &offs))
1097           return FALSE;
1098
1099         if (!have_offset) {
1100           if (offset)
1101             *offset = offs;
1102           if (parent)
1103             *parent = mprv->parent;
1104
1105           have_offset = TRUE;
1106         }
1107       }
1108     }
1109   }
1110   return have_offset;
1111 }
1112
1113 static GstMemory *
1114 _gst_buffer_arr_span (GstMemory ** mem[], gsize len[], guint n, gsize offset,
1115     gsize size, gboolean writable)
1116 {
1117   GstMemory *span, *parent;
1118   gsize poffset;
1119
1120   if (!writable
1121       && _gst_buffer_arr_is_span_fast (mem, len, n, &poffset, &parent)) {
1122     span = gst_memory_share (parent, offset + poffset, size);
1123   } else {
1124     gsize count, left;
1125     guint8 *dest, *ptr;
1126
1127     span = gst_memory_new_alloc (size, 0);
1128     dest = gst_memory_map (span, NULL, NULL, GST_MAP_WRITE);
1129
1130     ptr = dest;
1131     left = size;
1132
1133     for (count = 0; count < n; count++) {
1134       gsize i, tocopy, clen, ssize;
1135       guint8 *src;
1136       GstMemory **cmem;
1137
1138       cmem = mem[count];
1139       clen = len[count];
1140
1141       for (i = 0; i < clen && left > 0; i++) {
1142         src = gst_memory_map (cmem[i], &ssize, NULL, GST_MAP_READ);
1143         tocopy = MIN (ssize, left);
1144         if (tocopy > offset) {
1145           memcpy (ptr, src + offset, tocopy - offset);
1146           left -= tocopy;
1147           ptr += tocopy;
1148           offset = 0;
1149         } else {
1150           offset -= tocopy;
1151         }
1152         gst_memory_unmap (cmem[i], src, ssize);
1153       }
1154     }
1155     gst_memory_unmap (span, dest, size);
1156   }
1157   return span;
1158 }
1159
1160 /**
1161  * gst_buffer_is_span_fast:
1162  * @buf1: the first #GstBuffer.
1163  * @buf2: the second #GstBuffer.
1164  *
1165  * Determines whether a gst_buffer_span() can be done without copying
1166  * the contents, that is, whether the data areas are contiguous sub-buffers of
1167  * the same buffer.
1168  *
1169  * MT safe.
1170  * Returns: TRUE if the buffers are contiguous,
1171  * FALSE if a copy would be required.
1172  */
1173 gboolean
1174 gst_buffer_is_span_fast (GstBuffer * buf1, GstBuffer * buf2)
1175 {
1176   GstMemory **mem[2];
1177   gsize len[2];
1178
1179   g_return_val_if_fail (GST_IS_BUFFER (buf1), FALSE);
1180   g_return_val_if_fail (GST_IS_BUFFER (buf2), FALSE);
1181   g_return_val_if_fail (buf1->mini_object.refcount > 0, FALSE);
1182   g_return_val_if_fail (buf2->mini_object.refcount > 0, FALSE);
1183
1184   mem[0] = GST_BUFFER_MEM_ARRAY (buf1);
1185   len[0] = GST_BUFFER_MEM_LEN (buf1);
1186   mem[1] = GST_BUFFER_MEM_ARRAY (buf2);
1187   len[1] = GST_BUFFER_MEM_LEN (buf2);
1188
1189   return _gst_buffer_arr_is_span_fast (mem, len, 2, NULL, NULL);
1190 }
1191
1192 /**
1193  * gst_buffer_span:
1194  * @buf1: the first source #GstBuffer to merge.
1195  * @offset: the offset in the first buffer from where the new
1196  * buffer should start.
1197  * @buf2: the second source #GstBuffer to merge.
1198  * @size: the total size of the new buffer.
1199  *
1200  * Creates a new buffer that consists of part of buf1 and buf2.
1201  * Logically, buf1 and buf2 are concatenated into a single larger
1202  * buffer, and a new buffer is created at the given offset inside
1203  * this space, with a given length.
1204  *
1205  * If the two source buffers are children of the same larger buffer,
1206  * and are contiguous, the new buffer will be a child of the shared
1207  * parent, and thus no copying is necessary. you can use
1208  * gst_buffer_is_span_fast() to determine if a memcpy will be needed.
1209  *
1210  * MT safe.
1211  *
1212  * Returns: (transfer full): the new #GstBuffer that spans the two source
1213  *     buffers, or NULL if the arguments are invalid.
1214  */
1215 GstBuffer *
1216 gst_buffer_span (GstBuffer * buf1, gsize offset, GstBuffer * buf2, gsize size)
1217 {
1218   GstBuffer *newbuf;
1219   GstMemory *span;
1220   GstMemory **mem[2];
1221   gsize len[2], len1, len2;
1222
1223   g_return_val_if_fail (GST_IS_BUFFER (buf1), NULL);
1224   g_return_val_if_fail (GST_IS_BUFFER (buf2), NULL);
1225   g_return_val_if_fail (buf1->mini_object.refcount > 0, NULL);
1226   g_return_val_if_fail (buf2->mini_object.refcount > 0, NULL);
1227   len1 = gst_buffer_get_size (buf1);
1228   len2 = gst_buffer_get_size (buf2);
1229   g_return_val_if_fail (len1 + len2 > offset, NULL);
1230   if (size == -1)
1231     size = len1 + len2 - offset;
1232   else
1233     g_return_val_if_fail (size <= len1 + len2 - offset, NULL);
1234
1235   mem[0] = GST_BUFFER_MEM_ARRAY (buf1);
1236   len[0] = GST_BUFFER_MEM_LEN (buf1);
1237   mem[1] = GST_BUFFER_MEM_ARRAY (buf2);
1238   len[1] = GST_BUFFER_MEM_LEN (buf2);
1239
1240   span = _gst_buffer_arr_span (mem, len, 2, offset, size, FALSE);
1241
1242   newbuf = gst_buffer_new ();
1243   _memory_add (newbuf, span);
1244
1245 #if 0
1246   /* if the offset is 0, the new buffer has the same timestamp as buf1 */
1247   if (offset == 0) {
1248     GST_BUFFER_OFFSET (newbuf) = GST_BUFFER_OFFSET (buf1);
1249     GST_BUFFER_TIMESTAMP (newbuf) = GST_BUFFER_TIMESTAMP (buf1);
1250
1251     /* if we completely merged the two buffers (appended), we can
1252      * calculate the duration too. Also make sure we's not messing with
1253      * invalid DURATIONS */
1254     if (buf1->size + buf2->size == len) {
1255       if (GST_BUFFER_DURATION_IS_VALID (buf1) &&
1256           GST_BUFFER_DURATION_IS_VALID (buf2)) {
1257         /* add duration */
1258         GST_BUFFER_DURATION (newbuf) = GST_BUFFER_DURATION (buf1) +
1259             GST_BUFFER_DURATION (buf2);
1260       }
1261       if (GST_BUFFER_OFFSET_END_IS_VALID (buf2)) {
1262         /* add offset_end */
1263         GST_BUFFER_OFFSET_END (newbuf) = GST_BUFFER_OFFSET_END (buf2);
1264       }
1265     }
1266   }
1267 #endif
1268
1269   return newbuf;
1270 }
1271
1272 /**
1273  * gst_buffer_get_meta:
1274  * @buffer: a #GstBuffer
1275  * @info: a #GstMetaInfo
1276  *
1277  * Get the metadata for the api in @info on buffer. When there is no such
1278  * metadata, NULL is returned.
1279  *
1280  * Note that the result metadata might not be of the implementation @info.
1281  *
1282  * Returns: the metadata for the api in @info on @buffer.
1283  */
1284 GstMeta *
1285 gst_buffer_get_meta (GstBuffer * buffer, const GstMetaInfo * info)
1286 {
1287   GstMetaItem *item;
1288   GstMeta *result = NULL;
1289
1290   g_return_val_if_fail (buffer != NULL, NULL);
1291   g_return_val_if_fail (info != NULL, NULL);
1292
1293   /* find GstMeta of the requested API */
1294   for (item = GST_BUFFER_META (buffer); item; item = item->next) {
1295     GstMeta *meta = &item->meta;
1296     if (meta->info->api == info->api) {
1297       result = meta;
1298       break;
1299     }
1300   }
1301   return result;
1302 }
1303
1304 /**
1305  * gst_buffer_add_meta:
1306  * @buffer: a #GstBuffer
1307  * @info: a #GstMetaInfo
1308  * @params: params for @info
1309  *
1310  * Add metadata for @info to @buffer using the parameters in @params.
1311  *
1312  * Returns: the metadata for the api in @info on @buffer.
1313  */
1314 GstMeta *
1315 gst_buffer_add_meta (GstBuffer * buffer, const GstMetaInfo * info,
1316     gpointer params)
1317 {
1318   GstMetaItem *item;
1319   GstMeta *result = NULL;
1320   gsize size;
1321
1322   g_return_val_if_fail (buffer != NULL, NULL);
1323   g_return_val_if_fail (info != NULL, NULL);
1324
1325   /* create a new slice */
1326   GST_CAT_DEBUG (GST_CAT_BUFFER, "alloc metadata of size %" G_GSIZE_FORMAT,
1327       info->size);
1328
1329   size = ITEM_SIZE (info);
1330   item = g_slice_alloc (size);
1331   result = &item->meta;
1332   result->info = info;
1333
1334   /* call the init_func when needed */
1335   if (info->init_func)
1336     if (!info->init_func (result, params, buffer))
1337       goto init_failed;
1338
1339   /* and add to the list of metadata */
1340   item->next = GST_BUFFER_META (buffer);
1341   GST_BUFFER_META (buffer) = item;
1342
1343   return result;
1344
1345 init_failed:
1346   {
1347     g_slice_free1 (size, item);
1348     return NULL;
1349   }
1350 }
1351
1352 /**
1353  * gst_buffer_remove_meta:
1354  * @buffer: a #GstBuffer
1355  * @meta: a #GstMeta
1356  *
1357  * Remove the metadata for @meta on @buffer.
1358  *
1359  * Returns: %TRUE if the metadata existed and was removed, %FALSE if no such
1360  * metadata was on @buffer.
1361  */
1362 gboolean
1363 gst_buffer_remove_meta (GstBuffer * buffer, GstMeta * meta)
1364 {
1365   GstMetaItem *walk, *prev;
1366
1367   g_return_val_if_fail (buffer != NULL, FALSE);
1368   g_return_val_if_fail (meta != NULL, FALSE);
1369
1370   /* find the metadata and delete */
1371   prev = GST_BUFFER_META (buffer);
1372   for (walk = prev; walk; walk = walk->next) {
1373     GstMeta *m = &walk->meta;
1374     if (m == meta) {
1375       const GstMetaInfo *info = meta->info;
1376
1377       /* remove from list */
1378       if (GST_BUFFER_META (buffer) == walk)
1379         GST_BUFFER_META (buffer) = walk->next;
1380       else
1381         prev->next = walk->next;
1382       /* call free_func if any */
1383       if (info->free_func)
1384         info->free_func (m, buffer);
1385
1386       /* and free the slice */
1387       g_slice_free1 (ITEM_SIZE (info), walk);
1388       break;
1389     }
1390     prev = walk;
1391   }
1392   return walk != NULL;
1393 }
1394
1395 /**
1396  * gst_buffer_iterate_meta:
1397  * @buffer: a #GstBuffer
1398  * @state: an opaque state pointer
1399  *
1400  * Retrieve the next #GstMeta after @current. If @state points
1401  * to %NULL, the first metadata is returned.
1402  *
1403  * @state will be updated with an opage state pointer 
1404  *
1405  * Returns: The next #GstMeta or %NULL when there are no more items.
1406  */
1407 GstMeta *
1408 gst_buffer_iterate_meta (GstBuffer * buffer, gpointer * state)
1409 {
1410   GstMetaItem **meta;
1411
1412   g_return_val_if_fail (buffer != NULL, NULL);
1413   g_return_val_if_fail (state != NULL, NULL);
1414
1415   meta = (GstMetaItem **) state;
1416   if (*meta == NULL)
1417     /* state NULL, move to first item */
1418     *meta = GST_BUFFER_META (buffer);
1419   else
1420     /* state !NULL, move to next item in list */
1421     *meta = (*meta)->next;
1422
1423   if (*meta)
1424     return &(*meta)->meta;
1425   else
1426     return NULL;
1427 }