b2f6a31a41703bb0f7ac5e5d3a25c72309b593b6
[platform/upstream/gstreamer.git] / gst / gstallocator.c
1 /* GStreamer
2  * Copyright (C) 2011 Wim Taymans <wim.taymans@gmail.be>
3  *
4  * gstallocator.c: memory block allocator
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., 51 Franklin St, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21
22 /**
23  * SECTION:gstallocator
24  * @short_description: allocate memory blocks
25  * @see_also: #GstMemory
26  *
27  * Memory is usually created by allocators with a gst_allocator_alloc()
28  * method call. When NULL is used as the allocator, the default allocator will
29  * be used.
30  *
31  * New allocators can be registered with gst_allocator_register().
32  * Allocators are identified by name and can be retrieved with
33  * gst_allocator_find(). gst_allocator_set_default() can be used to change the
34  * default allocator.
35  *
36  * New memory can be created with gst_memory_new_wrapped() that wraps the memory
37  * allocated elsewhere.
38  *
39  * Last reviewed on 2012-07-09 (0.11.3)
40  */
41
42 #ifdef HAVE_CONFIG_H
43 #include "config.h"
44 #endif
45
46 #include "gst_private.h"
47 #include "gstmemory.h"
48
49 GST_DEBUG_CATEGORY_STATIC (gst_allocator_debug);
50 #define GST_CAT_DEFAULT gst_allocator_debug
51
52 #define GST_ALLOCATOR_GET_PRIVATE(obj)  \
53      (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_ALLOCATOR, GstAllocatorPrivate))
54
55 struct _GstAllocatorPrivate
56 {
57   gpointer dummy;
58 };
59
60 #if defined(MEMORY_ALIGNMENT_MALLOC)
61 size_t gst_memory_alignment = 7;
62 #elif defined(MEMORY_ALIGNMENT_PAGESIZE)
63 /* we fill this in in the _init method */
64 size_t gst_memory_alignment = 0;
65 #elif defined(MEMORY_ALIGNMENT)
66 size_t gst_memory_alignment = MEMORY_ALIGNMENT - 1;
67 #else
68 #error "No memory alignment configured"
69 size_t gst_memory_alignment = 0;
70 #endif
71
72 /* the default allocator */
73 static GstAllocator *_default_allocator;
74
75 static GstAllocator *_sysmem_allocator;
76
77 /* registered allocators */
78 static GRWLock lock;
79 static GHashTable *allocators;
80
81 G_DEFINE_ABSTRACT_TYPE (GstAllocator, gst_allocator, GST_TYPE_OBJECT);
82
83 static void
84 gst_allocator_class_init (GstAllocatorClass * klass)
85 {
86   g_type_class_add_private (klass, sizeof (GstAllocatorPrivate));
87
88   GST_DEBUG_CATEGORY_INIT (gst_allocator_debug, "allocator", 0,
89       "allocator debug");
90 }
91
92 static GstMemory *
93 _fallback_mem_copy (GstMemory * mem, gssize offset, gssize size)
94 {
95   GstMemory *copy;
96   GstMapInfo sinfo, dinfo;
97   GstAllocationParams params = { 0, mem->align, 0, 0, };
98
99   if (!gst_memory_map (mem, &sinfo, GST_MAP_READ))
100     return NULL;
101
102   if (size == -1)
103     size = sinfo.size > offset ? sinfo.size - offset : 0;
104
105   /* use the same allocator as the memory we copy  */
106   copy = gst_allocator_alloc (mem->allocator, size, &params);
107   if (!gst_memory_map (copy, &dinfo, GST_MAP_WRITE)) {
108     GST_CAT_WARNING (GST_CAT_MEMORY, "could not write map memory %p", copy);
109     gst_allocator_free (mem->allocator, copy);
110     gst_memory_unmap (mem, &sinfo);
111     return NULL;
112   }
113
114   GST_CAT_DEBUG (GST_CAT_PERFORMANCE,
115       "memcpy %" G_GSSIZE_FORMAT " memory %p -> %p", size, mem, copy);
116   memcpy (dinfo.data, sinfo.data + offset, size);
117   gst_memory_unmap (copy, &dinfo);
118   gst_memory_unmap (mem, &sinfo);
119
120   return copy;
121 }
122
123 static gboolean
124 _fallback_mem_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset)
125 {
126   return FALSE;
127 }
128
129 static void
130 gst_allocator_init (GstAllocator * allocator)
131 {
132   allocator->priv = GST_ALLOCATOR_GET_PRIVATE (allocator);
133
134   allocator->mem_copy = _fallback_mem_copy;
135   allocator->mem_is_span = _fallback_mem_is_span;
136 }
137
138 G_DEFINE_BOXED_TYPE (GstAllocationParams, gst_allocation_params,
139     (GBoxedCopyFunc) gst_allocation_params_copy,
140     (GBoxedFreeFunc) gst_allocation_params_free);
141
142 /**
143  * gst_allocation_params_init:
144  * @params: a #GstAllocationParams
145  *
146  * Initialize @params to its default values
147  */
148 void
149 gst_allocation_params_init (GstAllocationParams * params)
150 {
151   g_return_if_fail (params != NULL);
152
153   memset (params, 0, sizeof (GstAllocationParams));
154 }
155
156 /**
157  * gst_allocation_params_copy:
158  * @params: (transfer none): a #GstAllocationParams
159  *
160  * Create a copy of @params.
161  *
162  * Free-function: gst_allocation_params_free
163  *
164  * Returns: (transfer full): a new ##GstAllocationParams, free with
165  * gst_allocation_params_free().
166  */
167 GstAllocationParams *
168 gst_allocation_params_copy (const GstAllocationParams * params)
169 {
170   GstAllocationParams *result = NULL;
171
172   if (params) {
173     result =
174         (GstAllocationParams *) g_slice_copy (sizeof (GstAllocationParams),
175         params);
176   }
177   return result;
178 }
179
180 /**
181  * gst_allocation_params_free:
182  * @params: (in) (transfer full): a #GstAllocationParams
183  *
184  * Free @params
185  */
186 void
187 gst_allocation_params_free (GstAllocationParams * params)
188 {
189   g_slice_free (GstAllocationParams, params);
190 }
191
192 /**
193  * gst_allocator_register:
194  * @name: the name of the allocator
195  * @allocator: (transfer full): #GstAllocator
196  *
197  * Registers the memory @allocator with @name. This function takes ownership of
198  * @allocator.
199  */
200 void
201 gst_allocator_register (const gchar * name, GstAllocator * allocator)
202 {
203   g_return_if_fail (name != NULL);
204   g_return_if_fail (allocator != NULL);
205
206   GST_CAT_DEBUG (GST_CAT_MEMORY, "registering allocator %p with name \"%s\"",
207       allocator, name);
208
209   g_rw_lock_writer_lock (&lock);
210   g_hash_table_insert (allocators, (gpointer) name, (gpointer) allocator);
211   g_rw_lock_writer_unlock (&lock);
212 }
213
214 /**
215  * gst_allocator_find:
216  * @name: the name of the allocator
217  *
218  * Find a previously registered allocator with @name. When @name is NULL, the
219  * default allocator will be returned.
220  *
221  * Returns: (transfer full): a #GstAllocator or NULL when the allocator with @name was not
222  * registered. Use gst_object_unref() to release the allocator after usage.
223  */
224 GstAllocator *
225 gst_allocator_find (const gchar * name)
226 {
227   GstAllocator *allocator;
228
229   g_rw_lock_reader_lock (&lock);
230   if (name) {
231     allocator = g_hash_table_lookup (allocators, (gconstpointer) name);
232   } else {
233     allocator = _default_allocator;
234   }
235   if (allocator)
236     gst_object_ref (allocator);
237   g_rw_lock_reader_unlock (&lock);
238
239   return allocator;
240 }
241
242 /**
243  * gst_allocator_set_default:
244  * @allocator: (transfer full): a #GstAllocator
245  *
246  * Set the default allocator. This function takes ownership of @allocator.
247  */
248 void
249 gst_allocator_set_default (GstAllocator * allocator)
250 {
251   GstAllocator *old;
252
253   g_return_if_fail (GST_IS_ALLOCATOR (allocator));
254
255   g_rw_lock_writer_lock (&lock);
256   old = _default_allocator;
257   _default_allocator = allocator;
258   g_rw_lock_writer_unlock (&lock);
259
260   if (old)
261     gst_object_unref (old);
262 }
263
264 /**
265  * gst_allocator_alloc:
266  * @allocator: (transfer none) (allow-none): a #GstAllocator to use
267  * @size: size of the visible memory area
268  * @params: (transfer none) (allow-none): optional parameters
269  *
270  * Use @allocator to allocate a new memory block with memory that is at least
271  * @size big.
272  *
273  * The optional @params can specify the prefix and padding for the memory. If
274  * NULL is passed, no flags, no extra prefix/padding and a default alignment is
275  * used.
276  *
277  * The prefix/padding will be filled with 0 if flags contains
278  * #GST_MEMORY_FLAG_ZERO_PREFIXED and #GST_MEMORY_FLAG_ZERO_PADDED respectively.
279  *
280  * When @allocator is NULL, the default allocator will be used.
281  *
282  * The alignment in @params is given as a bitmask so that @align + 1 equals
283  * the amount of bytes to align to. For example, to align to 8 bytes,
284  * use an alignment of 7.
285  *
286  * Returns: (transfer full): a new #GstMemory.
287  */
288 GstMemory *
289 gst_allocator_alloc (GstAllocator * allocator, gsize size,
290     GstAllocationParams * params)
291 {
292   GstMemory *mem;
293   static GstAllocationParams defparams = { 0, 0, 0, 0, };
294   GstAllocatorClass *aclass;
295
296   if (params) {
297     g_return_val_if_fail (((params->align + 1) & params->align) == 0, NULL);
298   } else {
299     params = &defparams;
300   }
301
302   if (allocator == NULL)
303     allocator = _default_allocator;
304
305   aclass = GST_ALLOCATOR_GET_CLASS (allocator);
306   if (aclass->alloc)
307     mem = aclass->alloc (allocator, size, params);
308   else
309     mem = NULL;
310
311   return mem;
312 }
313
314 /**
315  * gst_allocator_free:
316  * @allocator: (transfer none): a #GstAllocator to use
317  * @memory: (transfer full): the memory to free
318  *
319  * Free @memory that was previously allocated with gst_allocator_alloc().
320  */
321 void
322 gst_allocator_free (GstAllocator * allocator, GstMemory * memory)
323 {
324   GstAllocatorClass *aclass;
325
326   g_return_if_fail (GST_IS_ALLOCATOR (allocator));
327   g_return_if_fail (memory != NULL);
328   g_return_if_fail (memory->allocator == allocator);
329
330   aclass = GST_ALLOCATOR_GET_CLASS (allocator);
331   if (aclass->free)
332     aclass->free (allocator, memory);
333 }
334
335 /* default memory implementation */
336 typedef struct
337 {
338   GstMemory mem;
339
340   gsize slice_size;
341   guint8 *data;
342
343   gpointer user_data;
344   GDestroyNotify notify;
345 } GstMemoryDefault;
346
347 typedef struct
348 {
349   GstAllocator parent;
350 } GstDefaultAllocator;
351
352 typedef struct
353 {
354   GstAllocatorClass parent_class;
355 } GstDefaultAllocatorClass;
356
357 GType gst_default_allocator_get_type (void);
358 G_DEFINE_TYPE (GstDefaultAllocator, gst_default_allocator, GST_TYPE_ALLOCATOR);
359
360 /* initialize the fields */
361 static inline void
362 _default_mem_init (GstMemoryDefault * mem, GstMemoryFlags flags,
363     GstMemory * parent, gsize slice_size,
364     gpointer data, gsize maxsize, gsize align, gsize offset, gsize size,
365     gpointer user_data, GDestroyNotify notify)
366 {
367   gst_memory_init (GST_MEMORY_CAST (mem),
368       flags, _sysmem_allocator, parent, maxsize, align, offset, size);
369
370   mem->slice_size = slice_size;
371   mem->data = data;
372   mem->user_data = user_data;
373   mem->notify = notify;
374 }
375
376 /* create a new memory block that manages the given memory */
377 static inline GstMemoryDefault *
378 _default_mem_new (GstMemoryFlags flags,
379     GstMemory * parent, gpointer data, gsize maxsize, gsize align, gsize offset,
380     gsize size, gpointer user_data, GDestroyNotify notify)
381 {
382   GstMemoryDefault *mem;
383   gsize slice_size;
384
385   slice_size = sizeof (GstMemoryDefault);
386
387   mem = g_slice_alloc (slice_size);
388   _default_mem_init (mem, flags, parent, slice_size,
389       data, maxsize, align, offset, size, user_data, notify);
390
391   return mem;
392 }
393
394 /* allocate the memory and structure in one block */
395 static GstMemoryDefault *
396 _default_mem_new_block (GstMemoryFlags flags,
397     gsize maxsize, gsize align, gsize offset, gsize size)
398 {
399   GstMemoryDefault *mem;
400   gsize aoffset, slice_size, padding;
401   guint8 *data;
402
403   /* ensure configured alignment */
404   align |= gst_memory_alignment;
405   /* allocate more to compensate for alignment */
406   maxsize += align;
407   /* alloc header and data in one block */
408   slice_size = sizeof (GstMemoryDefault) + maxsize;
409
410   mem = g_slice_alloc (slice_size);
411   if (mem == NULL)
412     return NULL;
413
414   data = (guint8 *) mem + sizeof (GstMemoryDefault);
415
416   /* do alignment */
417   if ((aoffset = ((guintptr) data & align))) {
418     aoffset = (align + 1) - aoffset;
419     data += aoffset;
420     maxsize -= aoffset;
421   }
422
423   if (offset && (flags & GST_MEMORY_FLAG_ZERO_PREFIXED))
424     memset (data, 0, offset);
425
426   padding = maxsize - (offset + size);
427   if (padding && (flags & GST_MEMORY_FLAG_ZERO_PADDED))
428     memset (data + offset + size, 0, padding);
429
430   _default_mem_init (mem, flags, NULL, slice_size, data, maxsize,
431       align, offset, size, NULL, NULL);
432
433   return mem;
434 }
435
436 static gpointer
437 _default_mem_map (GstMemoryDefault * mem, gsize maxsize, GstMapFlags flags)
438 {
439   return mem->data;
440 }
441
442 static gboolean
443 _default_mem_unmap (GstMemoryDefault * mem)
444 {
445   return TRUE;
446 }
447
448 static GstMemoryDefault *
449 _default_mem_copy (GstMemoryDefault * mem, gssize offset, gsize size)
450 {
451   GstMemoryDefault *copy;
452
453   if (size == -1)
454     size = mem->mem.size > offset ? mem->mem.size - offset : 0;
455
456   copy =
457       _default_mem_new_block (0, mem->mem.maxsize, mem->mem.align,
458       mem->mem.offset + offset, size);
459   GST_CAT_DEBUG (GST_CAT_PERFORMANCE,
460       "memcpy %" G_GSIZE_FORMAT " memory %p -> %p", mem->mem.maxsize, mem,
461       copy);
462   memcpy (copy->data, mem->data, mem->mem.maxsize);
463
464   return copy;
465 }
466
467 static GstMemoryDefault *
468 _default_mem_share (GstMemoryDefault * mem, gssize offset, gsize size)
469 {
470   GstMemoryDefault *sub;
471   GstMemory *parent;
472
473   /* find the real parent */
474   if ((parent = mem->mem.parent) == NULL)
475     parent = (GstMemory *) mem;
476
477   if (size == -1)
478     size = mem->mem.size - offset;
479
480   /* the shared memory is always readonly */
481   sub =
482       _default_mem_new (GST_MINI_OBJECT_FLAGS (parent) |
483       GST_MINI_OBJECT_FLAG_LOCK_READONLY, parent, mem->data, mem->mem.maxsize,
484       mem->mem.align, mem->mem.offset + offset, size, NULL, NULL);
485
486   return sub;
487 }
488
489 static gboolean
490 _default_mem_is_span (GstMemoryDefault * mem1, GstMemoryDefault * mem2,
491     gsize * offset)
492 {
493
494   if (offset) {
495     GstMemoryDefault *parent;
496
497     parent = (GstMemoryDefault *) mem1->mem.parent;
498
499     *offset = mem1->mem.offset - parent->mem.offset;
500   }
501
502   /* and memory is contiguous */
503   return mem1->data + mem1->mem.offset + mem1->mem.size ==
504       mem2->data + mem2->mem.offset;
505 }
506
507 static GstMemory *
508 default_alloc (GstAllocator * allocator, gsize size,
509     GstAllocationParams * params)
510 {
511   gsize maxsize = size + params->prefix + params->padding;
512
513   return (GstMemory *) _default_mem_new_block (params->flags,
514       maxsize, params->align, params->prefix, size);
515 }
516
517 static void
518 default_free (GstAllocator * allocator, GstMemory * mem)
519 {
520   GstMemoryDefault *dmem = (GstMemoryDefault *) mem;
521   gsize slice_size;
522
523   if (dmem->notify)
524     dmem->notify (dmem->user_data);
525
526   slice_size = dmem->slice_size;
527
528 #ifdef USE_POISONING
529   /* just poison the structs, not all the data */
530   memset (mem, 0xff, sizeof (GstMemoryDefault));
531 #endif
532
533   g_slice_free1 (slice_size, mem);
534 }
535
536 static void
537 gst_default_allocator_finalize (GObject * obj)
538 {
539   g_warning ("The default memory allocator was freed!");
540 }
541
542 static void
543 gst_default_allocator_class_init (GstDefaultAllocatorClass * klass)
544 {
545   GObjectClass *gobject_class;
546   GstAllocatorClass *allocator_class;
547
548   gobject_class = (GObjectClass *) klass;
549   allocator_class = (GstAllocatorClass *) klass;
550
551   gobject_class->finalize = gst_default_allocator_finalize;
552
553   allocator_class->alloc = default_alloc;
554   allocator_class->free = default_free;
555 }
556
557 static void
558 gst_default_allocator_init (GstDefaultAllocator * allocator)
559 {
560   GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
561
562   GST_CAT_DEBUG (GST_CAT_MEMORY, "init allocator %p", allocator);
563
564   alloc->mem_type = GST_ALLOCATOR_SYSMEM;
565   alloc->mem_map = (GstMemoryMapFunction) _default_mem_map;
566   alloc->mem_unmap = (GstMemoryUnmapFunction) _default_mem_unmap;
567   alloc->mem_copy = (GstMemoryCopyFunction) _default_mem_copy;
568   alloc->mem_share = (GstMemoryShareFunction) _default_mem_share;
569   alloc->mem_is_span = (GstMemoryIsSpanFunction) _default_mem_is_span;
570 }
571
572 void
573 _priv_gst_memory_initialize (void)
574 {
575   g_rw_lock_init (&lock);
576   allocators = g_hash_table_new (g_str_hash, g_str_equal);
577
578 #ifdef HAVE_GETPAGESIZE
579 #ifdef MEMORY_ALIGNMENT_PAGESIZE
580   gst_memory_alignment = getpagesize () - 1;
581 #endif
582 #endif
583
584   GST_CAT_DEBUG (GST_CAT_MEMORY, "memory alignment: %" G_GSIZE_FORMAT,
585       gst_memory_alignment);
586
587   _sysmem_allocator = g_object_new (gst_default_allocator_get_type (), NULL);
588
589   gst_allocator_register (GST_ALLOCATOR_SYSMEM,
590       gst_object_ref (_sysmem_allocator));
591
592   _default_allocator = gst_object_ref (_sysmem_allocator);
593 }
594
595 /**
596  * gst_memory_new_wrapped:
597  * @flags: #GstMemoryFlags
598  * @data: data to wrap
599  * @maxsize: allocated size of @data
600  * @offset: offset in @data
601  * @size: size of valid data
602  * @user_data: user_data
603  * @notify: called with @user_data when the memory is freed
604  *
605  * Allocate a new memory block that wraps the given @data.
606  *
607  * The prefix/padding must be filled with 0 if @flags contains
608  * #GST_MEMORY_FLAG_ZERO_PREFIXED and #GST_MEMORY_FLAG_ZERO_PADDED respectively.
609  *
610  * Returns: a new #GstMemory.
611  */
612 GstMemory *
613 gst_memory_new_wrapped (GstMemoryFlags flags, gpointer data,
614     gsize maxsize, gsize offset, gsize size, gpointer user_data,
615     GDestroyNotify notify)
616 {
617   GstMemoryDefault *mem;
618
619   g_return_val_if_fail (data != NULL, NULL);
620   g_return_val_if_fail (offset + size <= maxsize, NULL);
621
622   mem =
623       _default_mem_new (flags, NULL, data, maxsize, 0, offset, size, user_data,
624       notify);
625
626   return (GstMemory *) mem;
627 }