miniobject: add lock functionality to GstMiniObject
[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   mem->allocator->info.mem_free (mem);
137 }
138
139 /* initialize the fields */
140 static void
141 _default_mem_init (GstMemoryDefault * mem, GstMemoryFlags flags,
142     GstMemory * parent, gsize slice_size, gpointer data,
143     gsize maxsize, gsize offset, gsize size, gsize align,
144     gpointer user_data, GDestroyNotify notify)
145 {
146   gst_mini_object_init (GST_MINI_OBJECT_CAST (mem),
147       flags | GST_MINI_OBJECT_FLAG_LOCKABLE, GST_TYPE_MEMORY,
148       (GstMiniObjectCopyFunction) _gst_memory_copy, NULL,
149       (GstMiniObjectFreeFunction) _gst_memory_free);
150
151   mem->mem.allocator = _default_mem_impl;
152   mem->mem.parent = parent ? gst_memory_ref (parent) : NULL;
153   mem->mem.maxsize = maxsize;
154   mem->mem.align = align;
155   mem->mem.offset = offset;
156   mem->mem.size = size;
157   mem->slice_size = slice_size;
158   mem->data = data;
159   mem->user_data = user_data;
160   mem->notify = notify;
161
162   GST_CAT_DEBUG (GST_CAT_MEMORY, "new memory %p, maxsize:%" G_GSIZE_FORMAT
163       " offset:%" G_GSIZE_FORMAT " size:%" G_GSIZE_FORMAT, mem, maxsize,
164       offset, size);
165 }
166
167 /* create a new memory block that manages the given memory */
168 static GstMemoryDefault *
169 _default_mem_new (GstMemoryFlags flags, GstMemory * parent, gpointer data,
170     gsize maxsize, gsize offset, gsize size, gsize align, gpointer user_data,
171     GDestroyNotify notify)
172 {
173   GstMemoryDefault *mem;
174   gsize slice_size;
175
176   slice_size = sizeof (GstMemoryDefault);
177
178   mem = g_slice_alloc (slice_size);
179   _default_mem_init (mem, flags, parent, slice_size,
180       data, maxsize, offset, size, align, user_data, notify);
181
182   return mem;
183 }
184
185 /* allocate the memory and structure in one block */
186 static GstMemoryDefault *
187 _default_mem_new_block (GstMemoryFlags flags, gsize maxsize, gsize align,
188     gsize offset, gsize size)
189 {
190   GstMemoryDefault *mem;
191   gsize aoffset, slice_size, padding;
192   guint8 *data;
193
194   /* ensure configured alignment */
195   align |= gst_memory_alignment;
196   /* allocate more to compensate for alignment */
197   maxsize += align;
198   /* alloc header and data in one block */
199   slice_size = sizeof (GstMemoryDefault) + maxsize;
200
201   mem = g_slice_alloc (slice_size);
202   if (mem == NULL)
203     return NULL;
204
205   data = (guint8 *) mem + sizeof (GstMemoryDefault);
206
207   /* do alignment */
208   if ((aoffset = ((guintptr) data & align))) {
209     aoffset = (align + 1) - aoffset;
210     data += aoffset;
211     maxsize -= aoffset;
212   }
213
214   if (offset && (flags & GST_MEMORY_FLAG_ZERO_PREFIXED))
215     memset (data, 0, offset);
216
217   padding = maxsize - (offset + size);
218   if (padding && (flags & GST_MEMORY_FLAG_ZERO_PADDED))
219     memset (data + offset + size, 0, padding);
220
221   _default_mem_init (mem, flags, NULL, slice_size, data, maxsize,
222       offset, size, align, NULL, NULL);
223
224   return mem;
225 }
226
227 static GstMemory *
228 _default_alloc_alloc (GstAllocator * allocator, gsize size,
229     GstAllocationParams * params, gpointer user_data)
230 {
231   gsize maxsize = size + params->prefix + params->padding;
232
233   return (GstMemory *) _default_mem_new_block (params->flags,
234       maxsize, params->align, params->prefix, size);
235 }
236
237 static gpointer
238 _default_mem_map (GstMemoryDefault * mem, gsize maxsize, GstMapFlags flags)
239 {
240   return mem->data;
241 }
242
243 static gboolean
244 _default_mem_unmap (GstMemoryDefault * mem)
245 {
246   return TRUE;
247 }
248
249 static void
250 _default_mem_free (GstMemoryDefault * mem)
251 {
252   GST_CAT_DEBUG (GST_CAT_MEMORY, "free memory %p", mem);
253
254   if (mem->mem.parent)
255     gst_memory_unref (mem->mem.parent);
256
257   if (mem->notify)
258     mem->notify (mem->user_data);
259
260   g_slice_free1 (mem->slice_size, mem);
261 }
262
263 static GstMemoryDefault *
264 _default_mem_copy (GstMemoryDefault * mem, gssize offset, gsize size)
265 {
266   GstMemoryDefault *copy;
267
268   if (size == -1)
269     size = mem->mem.size > offset ? mem->mem.size - offset : 0;
270
271   copy =
272       _default_mem_new_block (0, mem->mem.maxsize, 0, mem->mem.offset + offset,
273       size);
274   GST_CAT_DEBUG (GST_CAT_PERFORMANCE,
275       "memcpy %" G_GSIZE_FORMAT " memory %p -> %p", mem->mem.maxsize, mem,
276       copy);
277   memcpy (copy->data, mem->data, mem->mem.maxsize);
278
279   return copy;
280 }
281
282 static GstMemoryDefault *
283 _default_mem_share (GstMemoryDefault * mem, gssize offset, gsize size)
284 {
285   GstMemoryDefault *sub;
286   GstMemory *parent;
287
288   /* find the real parent */
289   if ((parent = mem->mem.parent) == NULL)
290     parent = (GstMemory *) mem;
291
292   if (size == -1)
293     size = mem->mem.size - offset;
294
295   sub =
296       _default_mem_new (GST_MINI_OBJECT_FLAGS (parent), parent, mem->data,
297       mem->mem.maxsize, mem->mem.offset + offset, size, mem->mem.align, NULL,
298       NULL);
299
300   return sub;
301 }
302
303 static gboolean
304 _default_mem_is_span (GstMemoryDefault * mem1, GstMemoryDefault * mem2,
305     gsize * offset)
306 {
307
308   if (offset) {
309     GstMemoryDefault *parent;
310
311     parent = (GstMemoryDefault *) mem1->mem.parent;
312
313     *offset = mem1->mem.offset - parent->mem.offset;
314   }
315
316   /* and memory is contiguous */
317   return mem1->data + mem1->mem.offset + mem1->mem.size ==
318       mem2->data + mem2->mem.offset;
319 }
320
321 static GstMemory *
322 _fallback_mem_copy (GstMemory * mem, gssize offset, gssize size)
323 {
324   GstMemory *copy;
325   GstMapInfo sinfo, dinfo;
326   GstAllocationParams params = { 0, 0, 0, mem->align, };
327
328   if (!gst_memory_map (mem, &sinfo, GST_MAP_READ))
329     return NULL;
330
331   if (size == -1)
332     size = sinfo.size > offset ? sinfo.size - offset : 0;
333
334   /* use the same allocator as the memory we copy  */
335   copy = gst_allocator_alloc (mem->allocator, size, &params);
336   if (!gst_memory_map (copy, &dinfo, GST_MAP_WRITE)) {
337     GST_CAT_WARNING (GST_CAT_MEMORY, "could not write map memory %p", copy);
338     gst_memory_unmap (mem, &sinfo);
339     return NULL;
340   }
341
342   GST_CAT_DEBUG (GST_CAT_PERFORMANCE,
343       "memcpy %" G_GSSIZE_FORMAT " memory %p -> %p", size, mem, copy);
344   memcpy (dinfo.data, sinfo.data + offset, size);
345   gst_memory_unmap (copy, &dinfo);
346   gst_memory_unmap (mem, &sinfo);
347
348   return copy;
349 }
350
351 static gboolean
352 _fallback_mem_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset)
353 {
354   return FALSE;
355 }
356
357 static GRWLock lock;
358 static GHashTable *allocators;
359
360 static void
361 _priv_sysmem_notify (gpointer user_data)
362 {
363   g_warning ("The default memory allocator was freed!");
364 }
365
366 void
367 _priv_gst_memory_initialize (void)
368 {
369   static const GstMemoryInfo _mem_info = {
370     GST_ALLOCATOR_SYSMEM,
371     (GstAllocatorAllocFunction) _default_alloc_alloc,
372     (GstMemoryMapFunction) _default_mem_map,
373     (GstMemoryUnmapFunction) _default_mem_unmap,
374     (GstMemoryFreeFunction) _default_mem_free,
375     (GstMemoryCopyFunction) _default_mem_copy,
376     (GstMemoryShareFunction) _default_mem_share,
377     (GstMemoryIsSpanFunction) _default_mem_is_span,
378   };
379
380   g_rw_lock_init (&lock);
381   allocators = g_hash_table_new (g_str_hash, g_str_equal);
382
383 #ifdef HAVE_GETPAGESIZE
384 #ifdef MEMORY_ALIGNMENT_PAGESIZE
385   gst_memory_alignment = getpagesize () - 1;
386 #endif
387 #endif
388
389   GST_CAT_DEBUG (GST_CAT_MEMORY, "memory alignment: %" G_GSIZE_FORMAT,
390       gst_memory_alignment);
391
392   _default_mem_impl = gst_allocator_new (&_mem_info, NULL, _priv_sysmem_notify);
393
394   _default_allocator = gst_allocator_ref (_default_mem_impl);
395   gst_allocator_register (GST_ALLOCATOR_SYSMEM,
396       gst_allocator_ref (_default_mem_impl));
397 }
398
399 /**
400  * gst_memory_new_wrapped:
401  * @flags: #GstMemoryFlags
402  * @data: data to wrap
403  * @maxsize: allocated size of @data
404  * @offset: offset in @data
405  * @size: size of valid data
406  * @user_data: user_data
407  * @notify: called with @user_data when the memory is freed
408  *
409  * Allocate a new memory block that wraps the given @data.
410  *
411  * The prefix/padding must be filled with 0 if @flags contains
412  * #GST_MEMORY_FLAG_ZERO_PREFIXED and #GST_MEMORY_FLAG_ZERO_PADDED respectively.
413  *
414  * Returns: a new #GstMemory.
415  */
416 GstMemory *
417 gst_memory_new_wrapped (GstMemoryFlags flags, gpointer data,
418     gsize maxsize, gsize offset, gsize size, gpointer user_data,
419     GDestroyNotify notify)
420 {
421   GstMemoryDefault *mem;
422
423   g_return_val_if_fail (data != NULL, NULL);
424   g_return_val_if_fail (offset + size <= maxsize, NULL);
425
426   mem =
427       _default_mem_new (flags, NULL, data, maxsize, offset, size, 0, user_data,
428       notify);
429
430   return (GstMemory *) mem;
431 }
432
433 /**
434  * gst_memory_get_sizes:
435  * @mem: a #GstMemory
436  * @offset: pointer to offset
437  * @maxsize: pointer to maxsize
438  *
439  * Get the current @size, @offset and @maxsize of @mem.
440  *
441  * Returns: the current sizes of @mem
442  */
443 gsize
444 gst_memory_get_sizes (GstMemory * mem, gsize * offset, gsize * maxsize)
445 {
446   g_return_val_if_fail (mem != NULL, 0);
447
448   if (offset)
449     *offset = mem->offset;
450   if (maxsize)
451     *maxsize = mem->maxsize;
452
453   return mem->size;
454 }
455
456 /**
457  * gst_memory_resize:
458  * @mem: a #GstMemory
459  * @offset: a new offset
460  * @size: a new size
461  *
462  * Resize the memory region. @mem should be writable and offset + size should be
463  * less than the maxsize of @mem.
464  *
465  * #GST_MEMORY_FLAG_ZERO_PREFIXED and #GST_MEMORY_FLAG_ZERO_PADDED will be
466  * cleared when offset or padding is increased respectively.
467  */
468 void
469 gst_memory_resize (GstMemory * mem, gssize offset, gsize size)
470 {
471   g_return_if_fail (mem != NULL);
472   g_return_if_fail (offset >= 0 || mem->offset >= -offset);
473   g_return_if_fail (size + mem->offset + offset <= mem->maxsize);
474
475   /* if we increase the prefix, we can't guarantee it is still 0 filled */
476   if ((offset > 0) && GST_MEMORY_IS_ZERO_PREFIXED (mem))
477     GST_MEMORY_FLAG_UNSET (mem, GST_MEMORY_FLAG_ZERO_PREFIXED);
478
479   /* if we increase the padding, we can't guarantee it is still 0 filled */
480   if ((offset + size < mem->size) && GST_MEMORY_IS_ZERO_PADDED (mem))
481     GST_MEMORY_FLAG_UNSET (mem, GST_MEMORY_FLAG_ZERO_PADDED);
482
483   mem->offset += offset;
484   mem->size = size;
485 }
486
487 /**
488  * gst_memory_make_mapped:
489  * @mem: (transfer full): a #GstMemory
490  * @info: (out): pointer for info
491  * @flags: mapping flags
492  *
493  * Create a #GstMemory object that is mapped with @flags. If @mem is mappable
494  * with @flags, this function returns the mapped @mem directly. Otherwise a
495  * mapped copy of @mem is returned.
496  *
497  * This function takes ownership of old @mem and returns a reference to a new
498  * #GstMemory.
499  *
500  * Returns: (transfer full): a #GstMemory object mapped with @flags or NULL when
501  * a mapping is not possible.
502  */
503 GstMemory *
504 gst_memory_make_mapped (GstMemory * mem, GstMapInfo * info, GstMapFlags flags)
505 {
506   GstMemory *result;
507
508   if (gst_memory_map (mem, info, flags)) {
509     result = mem;
510   } else {
511     result = gst_memory_copy (mem, 0, -1);
512     gst_memory_unref (mem);
513
514     if (result == NULL)
515       goto cannot_copy;
516
517     if (!gst_memory_map (result, info, flags))
518       goto cannot_map;
519   }
520   return result;
521
522   /* ERRORS */
523 cannot_copy:
524   {
525     GST_CAT_DEBUG (GST_CAT_MEMORY, "cannot copy memory %p", mem);
526     return NULL;
527   }
528 cannot_map:
529   {
530     GST_CAT_DEBUG (GST_CAT_MEMORY, "cannot map memory %p with flags %d", mem,
531         flags);
532     gst_memory_unref (result);
533     return NULL;
534   }
535 }
536
537 /**
538  * gst_memory_map:
539  * @mem: a #GstMemory
540  * @info: (out): pointer for info
541  * @flags: mapping flags
542  *
543  * Fill @info with the pointer and sizes of the memory in @mem that can be
544  * accessed according to @flags.
545  *
546  * This function can return %FALSE for various reasons:
547  * - the memory backed by @mem is not accessible with the given @flags.
548  * - the memory was already mapped with a different mapping.
549  *
550  * @info and its contents remain valid for as long as @mem is valid and
551  * until gst_memory_unmap() is called.
552  *
553  * For each gst_memory_map() call, a corresponding gst_memory_unmap() call
554  * should be done.
555  *
556  * Returns: %TRUE if the map operation was successful.
557  */
558 gboolean
559 gst_memory_map (GstMemory * mem, GstMapInfo * info, GstMapFlags flags)
560 {
561   g_return_val_if_fail (mem != NULL, FALSE);
562   g_return_val_if_fail (info != NULL, FALSE);
563
564   if (!gst_memory_lock (mem, flags))
565     goto lock_failed;
566
567   info->data = mem->allocator->info.mem_map (mem, mem->maxsize, flags);
568
569   if (G_UNLIKELY (info->data == NULL))
570     goto error;
571
572   info->memory = mem;
573   info->flags = flags;
574   info->size = mem->size;
575   info->maxsize = mem->maxsize - mem->offset;
576   info->data = info->data + mem->offset;
577
578   return TRUE;
579
580   /* ERRORS */
581 lock_failed:
582   {
583     GST_CAT_DEBUG (GST_CAT_MEMORY, "mem %p: lock %d failed", mem, flags);
584     return FALSE;
585   }
586 error:
587   {
588     /* something went wrong, restore the orginal state again */
589     GST_CAT_ERROR (GST_CAT_MEMORY, "mem %p: map failed", mem);
590     gst_memory_unlock (mem, flags);
591     return FALSE;
592   }
593 }
594
595 /**
596  * gst_memory_unmap:
597  * @mem: a #GstMemory
598  * @info: a #GstMapInfo
599  *
600  * Release the memory obtained with gst_memory_map()
601  */
602 void
603 gst_memory_unmap (GstMemory * mem, GstMapInfo * info)
604 {
605   g_return_if_fail (mem != NULL);
606   g_return_if_fail (info != NULL);
607   g_return_if_fail (info->memory == mem);
608
609   mem->allocator->info.mem_unmap (mem);
610   gst_memory_unlock (mem, info->flags);
611 }
612
613 /**
614  * gst_memory_copy:
615  * @mem: a #GstMemory
616  * @offset: an offset to copy
617  * @size: size to copy or -1 to copy all bytes from offset
618  *
619  * Return a copy of @size bytes from @mem starting from @offset. This copy is
620  * guaranteed to be writable. @size can be set to -1 to return a copy all bytes
621  * from @offset.
622  *
623  * Returns: a new #GstMemory.
624  */
625 GstMemory *
626 gst_memory_copy (GstMemory * mem, gssize offset, gssize size)
627 {
628   GstMemory *copy;
629
630   g_return_val_if_fail (mem != NULL, NULL);
631
632   copy = mem->allocator->info.mem_copy (mem, offset, size);
633
634   return copy;
635 }
636
637 /**
638  * gst_memory_share:
639  * @mem: a #GstMemory
640  * @offset: an offset to share
641  * @size: size to share or -1 to share bytes from offset
642  *
643  * Return a shared copy of @size bytes from @mem starting from @offset. No
644  * memory copy is performed and the memory region is simply shared. The result
645  * is guaranteed to be not-writable. @size can be set to -1 to return a share
646  * all bytes from @offset.
647  *
648  * Returns: a new #GstMemory.
649  */
650 GstMemory *
651 gst_memory_share (GstMemory * mem, gssize offset, gssize size)
652 {
653   GstMemory *shared;
654
655   g_return_val_if_fail (mem != NULL, NULL);
656   g_return_val_if_fail (!GST_MEMORY_FLAG_IS_SET (mem, GST_MEMORY_FLAG_NO_SHARE),
657       NULL);
658
659   shared = mem->allocator->info.mem_share (mem, offset, size);
660
661   return shared;
662 }
663
664 /**
665  * gst_memory_is_span:
666  * @mem1: a #GstMemory
667  * @mem2: a #GstMemory
668  * @offset: a pointer to a result offset
669  *
670  * Check if @mem1 and mem2 share the memory with a common parent memory object
671  * and that the memory is contiguous.
672  *
673  * If this is the case, the memory of @mem1 and @mem2 can be merged
674  * efficiently by performing gst_memory_share() on the parent object from
675  * the returned @offset.
676  *
677  * Returns: %TRUE if the memory is contiguous and of a common parent.
678  */
679 gboolean
680 gst_memory_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset)
681 {
682   g_return_val_if_fail (mem1 != NULL, FALSE);
683   g_return_val_if_fail (mem2 != NULL, FALSE);
684
685   /* need to have the same allocators */
686   if (mem1->allocator != mem2->allocator)
687     return FALSE;
688
689   /* need to have the same parent */
690   if (mem1->parent == NULL || mem1->parent != mem2->parent)
691     return FALSE;
692
693   /* and memory is contiguous */
694   if (!mem1->allocator->info.mem_is_span (mem1, mem2, offset))
695     return FALSE;
696
697   return TRUE;
698 }
699
700 static void
701 _gst_allocator_free (GstAllocator * allocator)
702 {
703   if (allocator->notify)
704     allocator->notify (allocator->user_data);
705
706   g_slice_free1 (sizeof (GstAllocator), allocator);
707 }
708
709 static GstAllocator *
710 _gst_allocator_copy (GstAllocator * allocator)
711 {
712   return gst_allocator_ref (allocator);
713 }
714
715 /**
716  * gst_allocator_new:
717  * @info: a #GstMemoryInfo
718  * @user_data: user data
719  * @notify: a #GDestroyNotify for @user_data
720  *
721  * Create a new memory allocator with @info and @user_data.
722  *
723  * All functions in @info are mandatory exept the copy and is_span
724  * functions, which will have a default implementation when left NULL.
725  *
726  * The @user_data will be passed to all calls of the alloc function. @notify
727  * will be called with @user_data when the allocator is freed.
728  *
729  * Returns: a new #GstAllocator.
730  */
731 GstAllocator *
732 gst_allocator_new (const GstMemoryInfo * info, gpointer user_data,
733     GDestroyNotify notify)
734 {
735   GstAllocator *allocator;
736
737   g_return_val_if_fail (info != NULL, NULL);
738   g_return_val_if_fail (info->alloc != NULL, NULL);
739   g_return_val_if_fail (info->mem_map != NULL, NULL);
740   g_return_val_if_fail (info->mem_unmap != NULL, NULL);
741   g_return_val_if_fail (info->mem_free != NULL, NULL);
742   g_return_val_if_fail (info->mem_share != NULL, NULL);
743
744   allocator = g_slice_new0 (GstAllocator);
745
746   gst_mini_object_init (GST_MINI_OBJECT_CAST (allocator), 0, GST_TYPE_ALLOCATOR,
747       (GstMiniObjectCopyFunction) _gst_allocator_copy, NULL,
748       (GstMiniObjectFreeFunction) _gst_allocator_free);
749
750   allocator->info = *info;
751   allocator->user_data = user_data;
752   allocator->notify = notify;
753
754 #define INSTALL_FALLBACK(_t) \
755   if (allocator->info._t == NULL) allocator->info._t = _fallback_ ##_t;
756   INSTALL_FALLBACK (mem_copy);
757   INSTALL_FALLBACK (mem_is_span);
758 #undef INSTALL_FALLBACK
759
760   GST_CAT_DEBUG (GST_CAT_MEMORY, "new allocator %p", allocator);
761
762   return allocator;
763 }
764
765 /**
766  * gst_allocator_get_memory_type:
767  * @allocator: a #GstAllocator
768  *
769  * Get the memory type allocated by this allocator
770  *
771  * Returns: the memory type provided by @allocator
772  */
773 const gchar *
774 gst_allocator_get_memory_type (GstAllocator * allocator)
775 {
776   g_return_val_if_fail (allocator != NULL, NULL);
777
778   return allocator->info.mem_type;
779 }
780
781 /**
782  * gst_allocator_register:
783  * @name: the name of the allocator
784  * @allocator: (transfer full): #GstAllocator
785  *
786  * Registers the memory @allocator with @name. This function takes ownership of
787  * @allocator.
788  */
789 void
790 gst_allocator_register (const gchar * name, GstAllocator * allocator)
791 {
792   g_return_if_fail (name != NULL);
793   g_return_if_fail (allocator != NULL);
794
795   GST_CAT_DEBUG (GST_CAT_MEMORY, "registering allocator %p with name \"%s\"",
796       allocator, name);
797
798   g_rw_lock_writer_lock (&lock);
799   g_hash_table_insert (allocators, (gpointer) name, (gpointer) allocator);
800   g_rw_lock_writer_unlock (&lock);
801 }
802
803 /**
804  * gst_allocator_find:
805  * @name: the name of the allocator
806  *
807  * Find a previously registered allocator with @name. When @name is NULL, the
808  * default allocator will be returned.
809  *
810  * Returns: (transfer full): a #GstAllocator or NULL when the allocator with @name was not
811  * registered. Use gst_allocator_unref() to release the allocator after usage.
812  */
813 GstAllocator *
814 gst_allocator_find (const gchar * name)
815 {
816   GstAllocator *allocator;
817
818   g_rw_lock_reader_lock (&lock);
819   if (name) {
820     allocator = g_hash_table_lookup (allocators, (gconstpointer) name);
821   } else {
822     allocator = _default_allocator;
823   }
824   if (allocator)
825     gst_allocator_ref (allocator);
826   g_rw_lock_reader_unlock (&lock);
827
828   return allocator;
829 }
830
831 /**
832  * gst_allocator_set_default:
833  * @allocator: (transfer full): a #GstAllocator
834  *
835  * Set the default allocator. This function takes ownership of @allocator.
836  */
837 void
838 gst_allocator_set_default (GstAllocator * allocator)
839 {
840   GstAllocator *old;
841   g_return_if_fail (allocator != NULL);
842
843   g_rw_lock_writer_lock (&lock);
844   old = _default_allocator;
845   _default_allocator = allocator;
846   g_rw_lock_writer_unlock (&lock);
847
848   if (old)
849     gst_allocator_unref (old);
850 }
851
852 /**
853  * gst_allocation_params_init:
854  * @params: a #GstAllocationParams
855  *
856  * Initialize @params to its default values
857  */
858 void
859 gst_allocation_params_init (GstAllocationParams * params)
860 {
861   g_return_if_fail (params != NULL);
862
863   memset (params, 0, sizeof (GstAllocationParams));
864 }
865
866 /**
867  * gst_allocation_params_copy:
868  * @params: (transfer none): a #GstAllocationParams
869  *
870  * Create a copy of @params.
871  *
872  * Free-function: gst_allocation_params_free
873  *
874  * Returns: (transfer full): a new ##GstAllocationParams, free with
875  * gst_allocation_params_free().
876  */
877 GstAllocationParams *
878 gst_allocation_params_copy (const GstAllocationParams * params)
879 {
880   GstAllocationParams *result = NULL;
881
882   if (params) {
883     result =
884         (GstAllocationParams *) g_slice_copy (sizeof (GstAllocationParams),
885         params);
886   }
887   return result;
888 }
889
890 /**
891  * gst_allocation_params_free:
892  * @params: (in) (transfer full): a #GstAllocationParams
893  *
894  * Free @params
895  */
896 void
897 gst_allocation_params_free (GstAllocationParams * params)
898 {
899   g_slice_free (GstAllocationParams, params);
900 }
901
902 /**
903  * gst_allocator_alloc:
904  * @allocator: (transfer none) (allow-none): a #GstAllocator to use
905  * @size: size of the visible memory area
906  * @params: (transfer none) (allow-none): optional parameters
907  *
908  * Use @allocator to allocate a new memory block with memory that is at least
909  * @size big.
910  *
911  * The optional @params can specify the prefix and padding for the memory. If
912  * NULL is passed, no flags, no extra prefix/padding and a default alignment is
913  * used.
914  *
915  * The prefix/padding will be filled with 0 if flags contains
916  * #GST_MEMORY_FLAG_ZERO_PREFIXED and #GST_MEMORY_FLAG_ZERO_PADDED respectively.
917  *
918  * When @allocator is NULL, the default allocator will be used.
919  *
920  * The alignment in @params is given as a bitmask so that @align + 1 equals
921  * the amount of bytes to align to. For example, to align to 8 bytes,
922  * use an alignment of 7.
923  *
924  * Returns: (transfer full): a new #GstMemory.
925  */
926 GstMemory *
927 gst_allocator_alloc (GstAllocator * allocator, gsize size,
928     GstAllocationParams * params)
929 {
930   GstMemory *mem;
931   static GstAllocationParams defparams = { 0, 0, 0, 0, };
932
933   if (params) {
934     g_return_val_if_fail (((params->align + 1) & params->align) == 0, NULL);
935   } else {
936     params = &defparams;
937   }
938
939   if (allocator == NULL)
940     allocator = _default_allocator;
941
942   mem = allocator->info.alloc (allocator, size, params, allocator->user_data);
943
944   return mem;
945 }