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