memory: fix is_exclusive
[platform/upstream/gstreamer.git] / gst / gstmemory.c
1 /* GStreamer
2  * Copyright (C) 2011 Wim Taymans <wim.taymans@gmail.be>
3  *
4  * gstmemory.c: memory block handling
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 /**
23  * SECTION:gstmemory
24  * @short_description: refcounted wrapper for memory blocks
25  * @see_also: #GstBuffer
26  *
27  * GstMemory is a lightweight refcounted object that wraps a region of memory.
28  * They are typically used to manage the data of a #GstBuffer.
29  *
30  * A GstMemory object has an allocated region of memory of maxsize. The maximum
31  * size does not change during the lifetime of the memory object. The memory
32  * also has an offset and size property that specifies the valid range of memory
33  * in the allocated region.
34  *
35  * Memory is usually created by allocators with a gst_allocator_alloc()
36  * method call. When NULL is used as the allocator, the default allocator will
37  * be used.
38  *
39  * New allocators can be registered with gst_allocator_register().
40  * Allocators are identified by name and can be retrieved with
41  * gst_allocator_find(). gst_allocator_set_default() can be used to change the
42  * default allocator.
43  *
44  * New memory can be created with gst_memory_new_wrapped() that wraps the memory
45  * allocated elsewhere.
46  *
47  * Refcounting of the memory block is performed with gst_memory_ref() and
48  * gst_memory_unref().
49  *
50  * The size of the memory can be retrieved and changed with
51  * gst_memory_get_sizes() and gst_memory_resize() respectively.
52  *
53  * Getting access to the data of the memory is performed with gst_memory_map().
54  * The call will return a pointer to offset bytes into the region of memory.
55  * After the memory access is completed, gst_memory_unmap() should be called.
56  *
57  * Memory can be copied with gst_memory_copy(), which will return a writable
58  * copy. gst_memory_share() will create a new memory block that shares the
59  * memory with an existing memory block at a custom offset and with a custom
60  * size.
61  *
62  * Memory can be efficiently merged when gst_memory_is_span() returns TRUE.
63  *
64  * Last reviewed on 2012-03-28 (0.11.3)
65  */
66
67 #ifdef HAVE_CONFIG_H
68 #include "config.h"
69 #endif
70
71 #include "gst_private.h"
72 #include "gstmemory.h"
73
74 GST_DEFINE_MINI_OBJECT_TYPE (GstMemory, gst_memory);
75
76 GST_DEFINE_MINI_OBJECT_TYPE (GstAllocator, gst_allocator);
77
78 G_DEFINE_BOXED_TYPE (GstAllocationParams, gst_allocation_params,
79     (GBoxedCopyFunc) gst_allocation_params_copy,
80     (GBoxedFreeFunc) gst_allocation_params_free);
81
82 #if defined(MEMORY_ALIGNMENT_MALLOC)
83 size_t gst_memory_alignment = 7;
84 #elif defined(MEMORY_ALIGNMENT_PAGESIZE)
85 /* we fill this in in the _init method */
86 size_t gst_memory_alignment = 0;
87 #elif defined(MEMORY_ALIGNMENT)
88 size_t gst_memory_alignment = MEMORY_ALIGNMENT - 1;
89 #else
90 #error "No memory alignment configured"
91 size_t gst_memory_alignment = 0;
92 #endif
93
94 struct _GstAllocator
95 {
96   GstMiniObject mini_object;
97
98   GstMemoryInfo info;
99
100   gpointer user_data;
101   GDestroyNotify notify;
102 };
103
104 /* default memory implementation */
105 typedef struct
106 {
107   GstMemory mem;
108   gsize slice_size;
109   guint8 *data;
110   gpointer user_data;
111   GDestroyNotify notify;
112 } GstMemoryDefault;
113
114 /* the default allocator */
115 static GstAllocator *_default_allocator;
116
117 /* our predefined allocators */
118 static GstAllocator *_default_mem_impl;
119
120 #define SHARE_ONE (1 << 16)
121 #define SHARE_MASK (~(SHARE_ONE - 1))
122 #define LOCK_ONE (GST_LOCK_FLAG_LAST)
123 #define FLAG_MASK (GST_LOCK_FLAG_LAST - 1)
124 #define LOCK_MASK ((SHARE_ONE - 1) - FLAG_MASK)
125 #define LOCK_FLAG_MASK (SHARE_ONE - 1)
126
127 static GstMemory *
128 _gst_memory_copy (GstMemory * mem)
129 {
130   return gst_memory_copy (mem, 0, -1);
131 }
132
133 static void
134 _gst_memory_free (GstMemory * mem)
135 {
136   /* there should be no outstanding mappings */
137   g_return_if_fail ((g_atomic_int_get (&mem->state) & LOCK_MASK) < 4);
138   mem->allocator->info.mem_free (mem);
139 }
140
141 /* initialize the fields */
142 static void
143 _default_mem_init (GstMemoryDefault * mem, GstMemoryFlags flags,
144     GstMemory * parent, gsize slice_size, gpointer data,
145     gsize maxsize, gsize offset, gsize size, gsize align,
146     gpointer user_data, GDestroyNotify notify)
147 {
148   gst_mini_object_init (GST_MINI_OBJECT_CAST (mem), GST_TYPE_MEMORY,
149       (GstMiniObjectCopyFunction) _gst_memory_copy, NULL,
150       (GstMiniObjectFreeFunction) _gst_memory_free);
151
152   mem->mem.mini_object.flags = flags;
153
154   mem->mem.allocator = _default_mem_impl;
155   mem->mem.parent = parent ? gst_memory_ref (parent) : NULL;
156   mem->mem.state = (flags & GST_MEMORY_FLAG_READONLY ? GST_LOCK_FLAG_READ : 0);
157   mem->mem.maxsize = maxsize;
158   mem->mem.align = align;
159   mem->mem.offset = offset;
160   mem->mem.size = size;
161   mem->slice_size = slice_size;
162   mem->data = data;
163   mem->user_data = user_data;
164   mem->notify = notify;
165
166   GST_CAT_DEBUG (GST_CAT_MEMORY, "new memory %p, maxsize:%" G_GSIZE_FORMAT
167       " offset:%" G_GSIZE_FORMAT " size:%" G_GSIZE_FORMAT, mem, maxsize,
168       offset, size);
169 }
170
171 /* create a new memory block that manages the given memory */
172 static GstMemoryDefault *
173 _default_mem_new (GstMemoryFlags flags, GstMemory * parent, gpointer data,
174     gsize maxsize, gsize offset, gsize size, gsize align, gpointer user_data,
175     GDestroyNotify notify)
176 {
177   GstMemoryDefault *mem;
178   gsize slice_size;
179
180   slice_size = sizeof (GstMemoryDefault);
181
182   mem = g_slice_alloc (slice_size);
183   _default_mem_init (mem, flags, parent, slice_size,
184       data, maxsize, offset, size, align, user_data, notify);
185
186   return mem;
187 }
188
189 /* allocate the memory and structure in one block */
190 static GstMemoryDefault *
191 _default_mem_new_block (GstMemoryFlags flags, gsize maxsize, gsize align,
192     gsize offset, gsize size)
193 {
194   GstMemoryDefault *mem;
195   gsize aoffset, slice_size, padding;
196   guint8 *data;
197
198   /* ensure configured alignment */
199   align |= gst_memory_alignment;
200   /* allocate more to compensate for alignment */
201   maxsize += align;
202   /* alloc header and data in one block */
203   slice_size = sizeof (GstMemoryDefault) + maxsize;
204
205   mem = g_slice_alloc (slice_size);
206   if (mem == NULL)
207     return NULL;
208
209   data = (guint8 *) mem + sizeof (GstMemoryDefault);
210
211   /* do alignment */
212   if ((aoffset = ((guintptr) data & align))) {
213     aoffset = (align + 1) - aoffset;
214     data += aoffset;
215     maxsize -= aoffset;
216   }
217
218   if (offset && (flags & GST_MEMORY_FLAG_ZERO_PREFIXED))
219     memset (data, 0, offset);
220
221   padding = maxsize - (offset + size);
222   if (padding && (flags & GST_MEMORY_FLAG_ZERO_PADDED))
223     memset (data + offset + size, 0, padding);
224
225   _default_mem_init (mem, flags, NULL, slice_size, data, maxsize,
226       offset, size, align, NULL, NULL);
227
228   return mem;
229 }
230
231 static GstMemory *
232 _default_alloc_alloc (GstAllocator * allocator, gsize size,
233     GstAllocationParams * params, gpointer user_data)
234 {
235   gsize maxsize = size + params->prefix + params->padding;
236
237   return (GstMemory *) _default_mem_new_block (params->flags,
238       maxsize, params->align, params->prefix, size);
239 }
240
241 static gpointer
242 _default_mem_map (GstMemoryDefault * mem, gsize maxsize, GstMapFlags flags)
243 {
244   return mem->data;
245 }
246
247 static gboolean
248 _default_mem_unmap (GstMemoryDefault * mem)
249 {
250   return TRUE;
251 }
252
253 static void
254 _default_mem_free (GstMemoryDefault * mem)
255 {
256   GST_CAT_DEBUG (GST_CAT_MEMORY, "free memory %p", mem);
257
258   if (mem->mem.parent)
259     gst_memory_unref (mem->mem.parent);
260
261   if (mem->notify)
262     mem->notify (mem->user_data);
263
264   g_slice_free1 (mem->slice_size, mem);
265 }
266
267 static GstMemoryDefault *
268 _default_mem_copy (GstMemoryDefault * mem, gssize offset, gsize size)
269 {
270   GstMemoryDefault *copy;
271
272   if (size == -1)
273     size = mem->mem.size > offset ? mem->mem.size - offset : 0;
274
275   copy =
276       _default_mem_new_block (0, mem->mem.maxsize, 0, mem->mem.offset + offset,
277       size);
278   GST_CAT_DEBUG (GST_CAT_PERFORMANCE,
279       "memcpy %" G_GSIZE_FORMAT " memory %p -> %p", mem->mem.maxsize, mem,
280       copy);
281   memcpy (copy->data, mem->data, mem->mem.maxsize);
282
283   return copy;
284 }
285
286 static GstMemoryDefault *
287 _default_mem_share (GstMemoryDefault * mem, gssize offset, gsize size)
288 {
289   GstMemoryDefault *sub;
290   GstMemory *parent;
291
292   /* find the real parent */
293   if ((parent = mem->mem.parent) == NULL)
294     parent = (GstMemory *) mem;
295
296   if (size == -1)
297     size = mem->mem.size - offset;
298
299   sub =
300       _default_mem_new (GST_MINI_OBJECT_FLAGS (parent), parent, mem->data,
301       mem->mem.maxsize, mem->mem.offset + offset, size, mem->mem.align, NULL,
302       NULL);
303
304   return sub;
305 }
306
307 static gboolean
308 _default_mem_is_span (GstMemoryDefault * mem1, GstMemoryDefault * mem2,
309     gsize * offset)
310 {
311
312   if (offset) {
313     GstMemoryDefault *parent;
314
315     parent = (GstMemoryDefault *) mem1->mem.parent;
316
317     *offset = mem1->mem.offset - parent->mem.offset;
318   }
319
320   /* and memory is contiguous */
321   return mem1->data + mem1->mem.offset + mem1->mem.size ==
322       mem2->data + mem2->mem.offset;
323 }
324
325 static GstMemory *
326 _fallback_mem_copy (GstMemory * mem, gssize offset, gssize size)
327 {
328   GstMemory *copy;
329   GstMapInfo sinfo, dinfo;
330   GstAllocationParams params = { 0, 0, 0, mem->align, };
331
332   if (!gst_memory_map (mem, &sinfo, GST_MAP_READ))
333     return NULL;
334
335   if (size == -1)
336     size = sinfo.size > offset ? sinfo.size - offset : 0;
337
338   /* use the same allocator as the memory we copy  */
339   copy = gst_allocator_alloc (mem->allocator, size, &params);
340   if (!gst_memory_map (copy, &dinfo, GST_MAP_WRITE)) {
341     GST_CAT_WARNING (GST_CAT_MEMORY, "could not write map memory %p", copy);
342     gst_memory_unmap (mem, &sinfo);
343     return NULL;
344   }
345
346   GST_CAT_DEBUG (GST_CAT_PERFORMANCE,
347       "memcpy %" G_GSSIZE_FORMAT " memory %p -> %p", size, mem, copy);
348   memcpy (dinfo.data, sinfo.data + offset, size);
349   gst_memory_unmap (copy, &dinfo);
350   gst_memory_unmap (mem, &sinfo);
351
352   return copy;
353 }
354
355 static gboolean
356 _fallback_mem_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset)
357 {
358   return FALSE;
359 }
360
361 static GRWLock lock;
362 static GHashTable *allocators;
363
364 static void
365 _priv_sysmem_notify (gpointer user_data)
366 {
367   g_warning ("The default memory allocator was freed!");
368 }
369
370 void
371 _priv_gst_memory_initialize (void)
372 {
373   static const GstMemoryInfo _mem_info = {
374     GST_ALLOCATOR_SYSMEM,
375     (GstAllocatorAllocFunction) _default_alloc_alloc,
376     (GstMemoryMapFunction) _default_mem_map,
377     (GstMemoryUnmapFunction) _default_mem_unmap,
378     (GstMemoryFreeFunction) _default_mem_free,
379     (GstMemoryCopyFunction) _default_mem_copy,
380     (GstMemoryShareFunction) _default_mem_share,
381     (GstMemoryIsSpanFunction) _default_mem_is_span,
382   };
383
384   g_rw_lock_init (&lock);
385   allocators = g_hash_table_new (g_str_hash, g_str_equal);
386
387 #ifdef HAVE_GETPAGESIZE
388 #ifdef MEMORY_ALIGNMENT_PAGESIZE
389   gst_memory_alignment = getpagesize () - 1;
390 #endif
391 #endif
392
393   GST_CAT_DEBUG (GST_CAT_MEMORY, "memory alignment: %" G_GSIZE_FORMAT,
394       gst_memory_alignment);
395
396   _default_mem_impl = gst_allocator_new (&_mem_info, NULL, _priv_sysmem_notify);
397
398   _default_allocator = gst_allocator_ref (_default_mem_impl);
399   gst_allocator_register (GST_ALLOCATOR_SYSMEM,
400       gst_allocator_ref (_default_mem_impl));
401 }
402
403 /**
404  * gst_memory_new_wrapped:
405  * @flags: #GstMemoryFlags
406  * @data: data to wrap
407  * @maxsize: allocated size of @data
408  * @offset: offset in @data
409  * @size: size of valid data
410  * @user_data: user_data
411  * @notify: called with @user_data when the memory is freed
412  *
413  * Allocate a new memory block that wraps the given @data.
414  *
415  * The prefix/padding must be filled with 0 if @flags contains
416  * #GST_MEMORY_FLAG_ZERO_PREFIXED and #GST_MEMORY_FLAG_ZERO_PADDED respectively.
417  *
418  * Returns: a new #GstMemory.
419  */
420 GstMemory *
421 gst_memory_new_wrapped (GstMemoryFlags flags, gpointer data,
422     gsize maxsize, gsize offset, gsize size, gpointer user_data,
423     GDestroyNotify notify)
424 {
425   GstMemoryDefault *mem;
426
427   g_return_val_if_fail (data != NULL, NULL);
428   g_return_val_if_fail (offset + size <= maxsize, NULL);
429
430   mem =
431       _default_mem_new (flags, NULL, data, maxsize, offset, size, 0, user_data,
432       notify);
433
434   return (GstMemory *) mem;
435 }
436
437 /**
438  * gst_memory_is_exclusive:
439  * @mem: a #GstMemory
440  *
441  * Check if the current EXCLUSIVE lock on @mem is the only one, this means that
442  * changes to the object will not be visible to any other object.
443  */
444 gboolean
445 gst_memory_is_exclusive (GstMemory * mem)
446 {
447   gint state;
448
449   g_return_val_if_fail (mem != NULL, FALSE);
450
451   state = g_atomic_int_get (&mem->state);
452
453   return (state & SHARE_MASK) < 2;
454 }
455
456 /**
457  * gst_memory_get_sizes:
458  * @mem: a #GstMemory
459  * @offset: pointer to offset
460  * @maxsize: pointer to maxsize
461  *
462  * Get the current @size, @offset and @maxsize of @mem.
463  *
464  * Returns: the current sizes of @mem
465  */
466 gsize
467 gst_memory_get_sizes (GstMemory * mem, gsize * offset, gsize * maxsize)
468 {
469   g_return_val_if_fail (mem != NULL, 0);
470
471   if (offset)
472     *offset = mem->offset;
473   if (maxsize)
474     *maxsize = mem->maxsize;
475
476   return mem->size;
477 }
478
479 /**
480  * gst_memory_resize:
481  * @mem: a #GstMemory
482  * @offset: a new offset
483  * @size: a new size
484  *
485  * Resize the memory region. @mem should be writable and offset + size should be
486  * less than the maxsize of @mem.
487  *
488  * #GST_MEMORY_FLAG_ZERO_PREFIXED and #GST_MEMORY_FLAG_ZERO_PADDED will be
489  * cleared when offset or padding is increased respectively.
490  */
491 void
492 gst_memory_resize (GstMemory * mem, gssize offset, gsize size)
493 {
494   g_return_if_fail (mem != NULL);
495   g_return_if_fail (offset >= 0 || mem->offset >= -offset);
496   g_return_if_fail (size + mem->offset + offset <= mem->maxsize);
497
498   /* if we increase the prefix, we can't guarantee it is still 0 filled */
499   if ((offset > 0) && GST_MEMORY_IS_ZERO_PREFIXED (mem))
500     GST_MEMORY_FLAG_UNSET (mem, GST_MEMORY_FLAG_ZERO_PREFIXED);
501
502   /* if we increase the padding, we can't guarantee it is still 0 filled */
503   if ((offset + size < mem->size) && GST_MEMORY_IS_ZERO_PADDED (mem))
504     GST_MEMORY_FLAG_UNSET (mem, GST_MEMORY_FLAG_ZERO_PADDED);
505
506   mem->offset += offset;
507   mem->size = size;
508 }
509
510 /**
511  * gst_memory_lock:
512  * @mem: a #GstMemory
513  * @flags: #GstLockFlags
514  *
515  * Lock the memory with the specified access mode in @flags.
516  *
517  * Returns: %TRUE if the memory could be locked.
518  */
519 gboolean
520 gst_memory_lock (GstMemory * mem, GstLockFlags flags)
521 {
522   gint access_mode, state, newstate;
523
524   access_mode = flags & FLAG_MASK;
525
526   do {
527     newstate = state = g_atomic_int_get (&mem->state);
528
529     GST_CAT_TRACE (GST_CAT_MEMORY, "lock %p: state %08x, access_mode %d",
530         mem, state, access_mode);
531
532     if (access_mode & GST_LOCK_FLAG_EXCLUSIVE) {
533       /* shared ref */
534       newstate += SHARE_ONE;
535       access_mode &= ~GST_LOCK_FLAG_EXCLUSIVE;
536     }
537
538     if (access_mode) {
539       if ((state & LOCK_FLAG_MASK) == 0) {
540         /* shared counter > 1 and write access */
541         if (state > SHARE_ONE && access_mode & GST_LOCK_FLAG_WRITE)
542           goto lock_failed;
543         /* nothing mapped, set access_mode */
544         newstate |= access_mode;
545       } else {
546         /* access_mode must match */
547         if ((state & access_mode) != access_mode)
548           goto lock_failed;
549       }
550       /* increase refcount */
551       newstate += LOCK_ONE;
552     }
553   } while (!g_atomic_int_compare_and_exchange (&mem->state, state, newstate));
554
555   return TRUE;
556
557 lock_failed:
558   {
559     GST_CAT_DEBUG (GST_CAT_MEMORY, "lock failed %p: state %08x, access_mode %d",
560         mem, state, access_mode);
561     return FALSE;
562   }
563 }
564
565 /**
566  * gst_memory_unlock:
567  * @mem: a #GstMemory
568  * @flags: #GstLockFlags
569  *
570  * Unlock the memory with the specified access mode in @flags.
571  */
572 void
573 gst_memory_unlock (GstMemory * mem, GstLockFlags flags)
574 {
575   gint access_mode, state, newstate;
576
577   access_mode = flags & FLAG_MASK;
578
579   do {
580     newstate = state = g_atomic_int_get (&mem->state);
581
582     GST_CAT_TRACE (GST_CAT_MEMORY, "unlock %p: state %08x, access_mode %d",
583         mem, state, access_mode);
584
585     if (access_mode & GST_LOCK_FLAG_EXCLUSIVE) {
586       /* shared counter */
587       g_return_if_fail (state >= SHARE_ONE);
588       newstate -= SHARE_ONE;
589       access_mode &= ~GST_LOCK_FLAG_EXCLUSIVE;
590     }
591
592     if (access_mode) {
593       g_return_if_fail ((state & access_mode) == access_mode);
594       /* decrease the refcount */
595       newstate -= LOCK_ONE;
596       /* last refcount, unset access_mode */
597       if ((newstate & LOCK_FLAG_MASK) == access_mode)
598         newstate &= ~LOCK_FLAG_MASK;
599     }
600   } while (!g_atomic_int_compare_and_exchange (&mem->state, state, newstate));
601 }
602
603 /**
604  * gst_memory_make_mapped:
605  * @mem: (transfer full): a #GstMemory
606  * @info: (out): pointer for info
607  * @flags: mapping flags
608  *
609  * Create a #GstMemory object that is mapped with @flags. If @mem is mappable
610  * with @flags, this function returns the mapped @mem directly. Otherwise a
611  * mapped copy of @mem is returned.
612  *
613  * This function takes ownership of old @mem and returns a reference to a new
614  * #GstMemory.
615  *
616  * Returns: (transfer full): a #GstMemory object mapped with @flags or NULL when
617  * a mapping is not possible.
618  */
619 GstMemory *
620 gst_memory_make_mapped (GstMemory * mem, GstMapInfo * info, GstMapFlags flags)
621 {
622   GstMemory *result;
623
624   if (gst_memory_map (mem, info, flags)) {
625     result = mem;
626   } else {
627     result = gst_memory_copy (mem, 0, -1);
628     gst_memory_unref (mem);
629
630     if (result == NULL)
631       goto cannot_copy;
632
633     if (!gst_memory_map (result, info, flags))
634       goto cannot_map;
635   }
636   return result;
637
638   /* ERRORS */
639 cannot_copy:
640   {
641     GST_CAT_DEBUG (GST_CAT_MEMORY, "cannot copy memory %p", mem);
642     return NULL;
643   }
644 cannot_map:
645   {
646     GST_CAT_DEBUG (GST_CAT_MEMORY, "cannot map memory %p with flags %d", mem,
647         flags);
648     gst_memory_unref (result);
649     return NULL;
650   }
651 }
652
653 /**
654  * gst_memory_map:
655  * @mem: a #GstMemory
656  * @info: (out): pointer for info
657  * @flags: mapping flags
658  *
659  * Fill @info with the pointer and sizes of the memory in @mem that can be
660  * accessed according to @flags.
661  *
662  * This function can return %FALSE for various reasons:
663  * - the memory backed by @mem is not accessible with the given @flags.
664  * - the memory was already mapped with a different mapping.
665  *
666  * @info and its contents remain valid for as long as @mem is valid and
667  * until gst_memory_unmap() is called.
668  *
669  * For each gst_memory_map() call, a corresponding gst_memory_unmap() call
670  * should be done.
671  *
672  * Returns: %TRUE if the map operation was successful.
673  */
674 gboolean
675 gst_memory_map (GstMemory * mem, GstMapInfo * info, GstMapFlags flags)
676 {
677   g_return_val_if_fail (mem != NULL, FALSE);
678   g_return_val_if_fail (info != NULL, FALSE);
679
680   if (!gst_memory_lock (mem, flags))
681     goto lock_failed;
682
683   info->data = mem->allocator->info.mem_map (mem, mem->maxsize, flags);
684
685   if (G_UNLIKELY (info->data == NULL))
686     goto error;
687
688   info->memory = mem;
689   info->flags = flags;
690   info->size = mem->size;
691   info->maxsize = mem->maxsize - mem->offset;
692   info->data = info->data + mem->offset;
693
694   return TRUE;
695
696   /* ERRORS */
697 lock_failed:
698   {
699     GST_CAT_DEBUG (GST_CAT_MEMORY, "mem %p: lock %d failed", mem, flags);
700     return FALSE;
701   }
702 error:
703   {
704     /* something went wrong, restore the orginal state again */
705     GST_CAT_ERROR (GST_CAT_MEMORY, "mem %p: map failed", mem);
706     gst_memory_unlock (mem, flags);
707     return FALSE;
708   }
709 }
710
711 /**
712  * gst_memory_unmap:
713  * @mem: a #GstMemory
714  * @info: a #GstMapInfo
715  *
716  * Release the memory obtained with gst_memory_map()
717  */
718 void
719 gst_memory_unmap (GstMemory * mem, GstMapInfo * info)
720 {
721   g_return_if_fail (mem != NULL);
722   g_return_if_fail (info != NULL);
723   g_return_if_fail (info->memory == mem);
724   /* there must be a ref */
725   g_return_if_fail (g_atomic_int_get (&mem->state) >= 4);
726
727   mem->allocator->info.mem_unmap (mem);
728   gst_memory_unlock (mem, info->flags);
729 }
730
731 /**
732  * gst_memory_copy:
733  * @mem: a #GstMemory
734  * @offset: an offset to copy
735  * @size: size to copy or -1 to copy all bytes from offset
736  *
737  * Return a copy of @size bytes from @mem starting from @offset. This copy is
738  * guaranteed to be writable. @size can be set to -1 to return a copy all bytes
739  * from @offset.
740  *
741  * Returns: a new #GstMemory.
742  */
743 GstMemory *
744 gst_memory_copy (GstMemory * mem, gssize offset, gssize size)
745 {
746   GstMemory *copy;
747
748   g_return_val_if_fail (mem != NULL, NULL);
749
750   copy = mem->allocator->info.mem_copy (mem, offset, size);
751
752   return copy;
753 }
754
755 /**
756  * gst_memory_share:
757  * @mem: a #GstMemory
758  * @offset: an offset to share
759  * @size: size to share or -1 to share bytes from offset
760  *
761  * Return a shared copy of @size bytes from @mem starting from @offset. No
762  * memory copy is performed and the memory region is simply shared. The result
763  * is guaranteed to be not-writable. @size can be set to -1 to return a share
764  * all bytes from @offset.
765  *
766  * Returns: a new #GstMemory.
767  */
768 GstMemory *
769 gst_memory_share (GstMemory * mem, gssize offset, gssize size)
770 {
771   GstMemory *shared;
772
773   g_return_val_if_fail (mem != NULL, NULL);
774   g_return_val_if_fail (!GST_MEMORY_FLAG_IS_SET (mem, GST_MEMORY_FLAG_NO_SHARE),
775       NULL);
776
777   shared = mem->allocator->info.mem_share (mem, offset, size);
778
779   return shared;
780 }
781
782 /**
783  * gst_memory_is_span:
784  * @mem1: a #GstMemory
785  * @mem2: a #GstMemory
786  * @offset: a pointer to a result offset
787  *
788  * Check if @mem1 and mem2 share the memory with a common parent memory object
789  * and that the memory is contiguous.
790  *
791  * If this is the case, the memory of @mem1 and @mem2 can be merged
792  * efficiently by performing gst_memory_share() on the parent object from
793  * the returned @offset.
794  *
795  * Returns: %TRUE if the memory is contiguous and of a common parent.
796  */
797 gboolean
798 gst_memory_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset)
799 {
800   g_return_val_if_fail (mem1 != NULL, FALSE);
801   g_return_val_if_fail (mem2 != NULL, FALSE);
802
803   /* need to have the same allocators */
804   if (mem1->allocator != mem2->allocator)
805     return FALSE;
806
807   /* need to have the same parent */
808   if (mem1->parent == NULL || mem1->parent != mem2->parent)
809     return FALSE;
810
811   /* and memory is contiguous */
812   if (!mem1->allocator->info.mem_is_span (mem1, mem2, offset))
813     return FALSE;
814
815   return TRUE;
816 }
817
818 static void
819 _gst_allocator_free (GstAllocator * allocator)
820 {
821   if (allocator->notify)
822     allocator->notify (allocator->user_data);
823
824   g_slice_free1 (sizeof (GstAllocator), allocator);
825 }
826
827 static GstAllocator *
828 _gst_allocator_copy (GstAllocator * allocator)
829 {
830   return gst_allocator_ref (allocator);
831 }
832
833 /**
834  * gst_allocator_new:
835  * @info: a #GstMemoryInfo
836  * @user_data: user data
837  * @notify: a #GDestroyNotify for @user_data
838  *
839  * Create a new memory allocator with @info and @user_data.
840  *
841  * All functions in @info are mandatory exept the copy and is_span
842  * functions, which will have a default implementation when left NULL.
843  *
844  * The @user_data will be passed to all calls of the alloc function. @notify
845  * will be called with @user_data when the allocator is freed.
846  *
847  * Returns: a new #GstAllocator.
848  */
849 GstAllocator *
850 gst_allocator_new (const GstMemoryInfo * info, gpointer user_data,
851     GDestroyNotify notify)
852 {
853   GstAllocator *allocator;
854
855   g_return_val_if_fail (info != NULL, NULL);
856   g_return_val_if_fail (info->alloc != NULL, NULL);
857   g_return_val_if_fail (info->mem_map != NULL, NULL);
858   g_return_val_if_fail (info->mem_unmap != NULL, NULL);
859   g_return_val_if_fail (info->mem_free != NULL, NULL);
860   g_return_val_if_fail (info->mem_share != NULL, NULL);
861
862   allocator = g_slice_new0 (GstAllocator);
863
864   gst_mini_object_init (GST_MINI_OBJECT_CAST (allocator), GST_TYPE_ALLOCATOR,
865       (GstMiniObjectCopyFunction) _gst_allocator_copy, NULL,
866       (GstMiniObjectFreeFunction) _gst_allocator_free);
867
868   allocator->info = *info;
869   allocator->user_data = user_data;
870   allocator->notify = notify;
871
872 #define INSTALL_FALLBACK(_t) \
873   if (allocator->info._t == NULL) allocator->info._t = _fallback_ ##_t;
874   INSTALL_FALLBACK (mem_copy);
875   INSTALL_FALLBACK (mem_is_span);
876 #undef INSTALL_FALLBACK
877
878   GST_CAT_DEBUG (GST_CAT_MEMORY, "new allocator %p", allocator);
879
880   return allocator;
881 }
882
883 /**
884  * gst_allocator_get_memory_type:
885  * @allocator: a #GstAllocator
886  *
887  * Get the memory type allocated by this allocator
888  *
889  * Returns: the memory type provided by @allocator
890  */
891 const gchar *
892 gst_allocator_get_memory_type (GstAllocator * allocator)
893 {
894   g_return_val_if_fail (allocator != NULL, NULL);
895
896   return allocator->info.mem_type;
897 }
898
899 /**
900  * gst_allocator_register:
901  * @name: the name of the allocator
902  * @allocator: (transfer full): #GstAllocator
903  *
904  * Registers the memory @allocator with @name. This function takes ownership of
905  * @allocator.
906  */
907 void
908 gst_allocator_register (const gchar * name, GstAllocator * allocator)
909 {
910   g_return_if_fail (name != NULL);
911   g_return_if_fail (allocator != NULL);
912
913   GST_CAT_DEBUG (GST_CAT_MEMORY, "registering allocator %p with name \"%s\"",
914       allocator, name);
915
916   g_rw_lock_writer_lock (&lock);
917   g_hash_table_insert (allocators, (gpointer) name, (gpointer) allocator);
918   g_rw_lock_writer_unlock (&lock);
919 }
920
921 /**
922  * gst_allocator_find:
923  * @name: the name of the allocator
924  *
925  * Find a previously registered allocator with @name. When @name is NULL, the
926  * default allocator will be returned.
927  *
928  * Returns: (transfer full): a #GstAllocator or NULL when the allocator with @name was not
929  * registered. Use gst_allocator_unref() to release the allocator after usage.
930  */
931 GstAllocator *
932 gst_allocator_find (const gchar * name)
933 {
934   GstAllocator *allocator;
935
936   g_rw_lock_reader_lock (&lock);
937   if (name) {
938     allocator = g_hash_table_lookup (allocators, (gconstpointer) name);
939   } else {
940     allocator = _default_allocator;
941   }
942   if (allocator)
943     gst_allocator_ref (allocator);
944   g_rw_lock_reader_unlock (&lock);
945
946   return allocator;
947 }
948
949 /**
950  * gst_allocator_set_default:
951  * @allocator: (transfer full): a #GstAllocator
952  *
953  * Set the default allocator. This function takes ownership of @allocator.
954  */
955 void
956 gst_allocator_set_default (GstAllocator * allocator)
957 {
958   GstAllocator *old;
959   g_return_if_fail (allocator != NULL);
960
961   g_rw_lock_writer_lock (&lock);
962   old = _default_allocator;
963   _default_allocator = allocator;
964   g_rw_lock_writer_unlock (&lock);
965
966   if (old)
967     gst_allocator_unref (old);
968 }
969
970 /**
971  * gst_allocation_params_init:
972  * @params: a #GstAllocationParams
973  *
974  * Initialize @params to its default values
975  */
976 void
977 gst_allocation_params_init (GstAllocationParams * params)
978 {
979   g_return_if_fail (params != NULL);
980
981   memset (params, 0, sizeof (GstAllocationParams));
982 }
983
984 /**
985  * gst_allocation_params_copy:
986  * @params: (transfer none): a #GstAllocationParams
987  *
988  * Create a copy of @params.
989  *
990  * Free-function: gst_allocation_params_free
991  *
992  * Returns: (transfer full): a new ##GstAllocationParams, free with
993  * gst_allocation_params_free().
994  */
995 GstAllocationParams *
996 gst_allocation_params_copy (const GstAllocationParams * params)
997 {
998   GstAllocationParams *result = NULL;
999
1000   if (params) {
1001     result =
1002         (GstAllocationParams *) g_slice_copy (sizeof (GstAllocationParams),
1003         params);
1004   }
1005   return result;
1006 }
1007
1008 /**
1009  * gst_allocation_params_free:
1010  * @params: (in) (transfer full): a #GstAllocationParams
1011  *
1012  * Free @params
1013  */
1014 void
1015 gst_allocation_params_free (GstAllocationParams * params)
1016 {
1017   g_slice_free (GstAllocationParams, params);
1018 }
1019
1020 /**
1021  * gst_allocator_alloc:
1022  * @allocator: (transfer none) (allow-none): a #GstAllocator to use
1023  * @size: size of the visible memory area
1024  * @params: (transfer none) (allow-none): optional parameters
1025  *
1026  * Use @allocator to allocate a new memory block with memory that is at least
1027  * @size big.
1028  *
1029  * The optional @params can specify the prefix and padding for the memory. If
1030  * NULL is passed, no flags, no extra prefix/padding and a default alignment is
1031  * used.
1032  *
1033  * The prefix/padding will be filled with 0 if flags contains
1034  * #GST_MEMORY_FLAG_ZERO_PREFIXED and #GST_MEMORY_FLAG_ZERO_PADDED respectively.
1035  *
1036  * When @allocator is NULL, the default allocator will be used.
1037  *
1038  * The alignment in @params is given as a bitmask so that @align + 1 equals
1039  * the amount of bytes to align to. For example, to align to 8 bytes,
1040  * use an alignment of 7.
1041  *
1042  * Returns: (transfer full): a new #GstMemory.
1043  */
1044 GstMemory *
1045 gst_allocator_alloc (GstAllocator * allocator, gsize size,
1046     GstAllocationParams * params)
1047 {
1048   GstMemory *mem;
1049   static GstAllocationParams defparams = { 0, 0, 0, 0, };
1050
1051   if (params) {
1052     g_return_val_if_fail (((params->align + 1) & params->align) == 0, NULL);
1053   } else {
1054     params = &defparams;
1055   }
1056
1057   if (allocator == NULL)
1058     allocator = _default_allocator;
1059
1060   mem = allocator->info.alloc (allocator, size, params, allocator->user_data);
1061
1062   return mem;
1063 }