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