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