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