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