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