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