miniobject: fix debug
[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  * New memory can be created with gst_memory_new_wrapped() that wraps the memory
31  * allocated elsewhere and gst_memory_new_alloc() that creates a new GstMemory
32  * and the memory inside it.
33  *
34  * Refcounting of the memory block is performed with gst_memory_ref() and
35  * gst_memory_unref().
36  *
37  * The size of the memory can be retrieved and changed with
38  * gst_memory_get_sizes() and gst_memory_resize() respectively.
39  *
40  * Getting access to the data of the memory is performed with gst_memory_map().
41  * After the memory access is completed, gst_memory_unmap() should be called.
42  *
43  * Memory can be copied with gst_memory_copy(), which will returnn a writable
44  * copy. gst_memory_share() will create a new memory block that shares the
45  * memory with an existing memory block at a custom offset and with a custom
46  * size.
47  *
48  * Memory can be efficiently merged when gst_memory_is_span() returns TRUE and
49  * with the function gst_memory_span().
50  *
51  * Last reviewed on 2011-03-30 (0.11.0)
52  */
53
54 #include "config.h"
55 #include "gst_private.h"
56 #include "gstmemory.h"
57
58
59 struct _GstMemoryImpl
60 {
61   GQuark name;
62
63   GstMemoryInfo info;
64 };
65
66 /* default memory implementation */
67 typedef struct
68 {
69   GstMemory mem;
70   gsize slice_size;
71   guint8 *data;
72   GFreeFunc free_func;
73   gsize maxsize;
74   gsize offset;
75   gsize size;
76 } GstMemoryDefault;
77
78 static const GstMemoryImpl *_default_mem_impl;
79 static const GstMemoryImpl *_default_share_impl;
80
81 /* initialize the fields */
82 static void
83 _default_mem_init (GstMemoryDefault * mem, GstMemoryFlags flags,
84     GstMemory * parent, gsize slice_size, gpointer data,
85     GFreeFunc free_func, gsize maxsize, gsize offset, gsize size)
86 {
87   mem->mem.impl = data ? _default_mem_impl : _default_share_impl;
88   mem->mem.flags = flags;
89   mem->mem.refcount = 1;
90   mem->mem.parent = parent ? gst_memory_ref (parent) : NULL;
91   mem->slice_size = slice_size;
92   mem->data = data;
93   mem->free_func = free_func;
94   mem->maxsize = maxsize;
95   mem->offset = offset;
96   mem->size = size;
97 }
98
99 /* create a new memory block that manages the given memory */
100 static GstMemoryDefault *
101 _default_mem_new (GstMemoryFlags flags, GstMemory * parent, gpointer data,
102     GFreeFunc free_func, gsize maxsize, gsize offset, gsize size)
103 {
104   GstMemoryDefault *mem;
105   gsize slice_size;
106
107   slice_size = sizeof (GstMemoryDefault);
108
109   mem = g_slice_alloc (slice_size);
110   _default_mem_init (mem, flags, parent, slice_size,
111       data, free_func, maxsize, offset, size);
112
113   return mem;
114 }
115
116 /* allocate the memory and structure in one block */
117 static GstMemoryDefault *
118 _default_mem_new_block (gsize maxsize, gsize align, gsize offset, gsize size)
119 {
120   GstMemoryDefault *mem;
121   gsize aoffset, slice_size;
122   guint8 *data;
123
124   /* alloc header and data in one block */
125   slice_size = sizeof (GstMemoryDefault) + maxsize + align;
126
127   mem = g_slice_alloc (slice_size);
128   if (mem == NULL)
129     return NULL;
130
131   data = (guint8 *) mem + sizeof (GstMemoryDefault);
132
133   if ((aoffset = ((guintptr) data & align)))
134     aoffset = align - aoffset;
135
136   _default_mem_init (mem, 0, NULL, slice_size, data, NULL, maxsize + align,
137       aoffset + offset, size);
138
139   return mem;
140 }
141
142 static gsize
143 _default_mem_get_sizes (GstMemoryDefault * mem, gsize * maxsize)
144 {
145   if (maxsize)
146     *maxsize = mem->maxsize;
147
148   return mem->size;
149 }
150
151 static void
152 _default_mem_resize (GstMemoryDefault * mem, gsize offset, gsize size)
153 {
154   g_return_if_fail (size + mem->offset + offset <= mem->maxsize);
155
156   mem->offset += offset;
157   mem->size = size;
158 }
159
160 static gpointer
161 _default_mem_map (GstMemoryDefault * mem, gsize * size, gsize * maxsize,
162     GstMapFlags flags)
163 {
164   if (size)
165     *size = mem->size;
166   if (maxsize)
167     *maxsize = mem->maxsize;
168
169   return mem->data + mem->offset;
170 }
171
172 static gpointer
173 _default_share_map (GstMemoryDefault * mem, gsize * size, gsize * maxsize,
174     GstMapFlags flags)
175 {
176   guint8 *data;
177
178   data = gst_memory_map (mem->mem.parent, size, maxsize, flags);
179
180   if (size)
181     *size = mem->size;
182   if (maxsize)
183     *maxsize -= mem->offset;
184
185   return data + mem->offset;
186 }
187
188 static gboolean
189 _default_mem_unmap (GstMemoryDefault * mem, gpointer data, gsize size)
190 {
191   if (size != -1)
192     mem->size = size;
193   return TRUE;
194 }
195
196 static gboolean
197 _default_share_unmap (GstMemoryDefault * mem, gpointer data, gsize size)
198 {
199   gboolean res;
200   guint8 *ptr = data;
201
202   if (size != -1)
203     mem->size = size;
204   else
205     size = mem->size - mem->offset;
206
207   res =
208       gst_memory_unmap (mem->mem.parent, ptr - mem->offset, size + mem->offset);
209
210   return res;
211 }
212
213 static void
214 _default_mem_free (GstMemoryDefault * mem)
215 {
216   if (mem->mem.parent)
217     gst_memory_unref (mem->mem.parent);
218
219   if (mem->free_func)
220     mem->free_func (mem->data);
221
222   g_slice_free1 (mem->slice_size, mem);
223 }
224
225 static GstMemoryDefault *
226 _default_mem_copy (GstMemoryDefault * mem, gsize offset, gsize size)
227 {
228   GstMemoryDefault *copy;
229
230   if (size == -1)
231     size = mem->size > offset ? mem->size - offset : 0;
232
233   copy = _default_mem_new_block (mem->maxsize, 0, mem->offset + offset, size);
234   memcpy (copy->data, mem->data, mem->maxsize);
235
236   return copy;
237 }
238
239 static GstMemoryDefault *
240 _default_mem_share (GstMemoryDefault * mem, gsize offset, gsize size)
241 {
242   GstMemoryDefault *sub;
243   GstMemory *parent;
244
245   /* find the real parent */
246   if ((parent = mem->mem.parent) == NULL)
247     parent = (GstMemory *) mem;
248
249   if (size == -1)
250     size = mem->size - offset;
251
252   sub = _default_mem_new (parent->flags, parent, mem->data, NULL, mem->maxsize,
253       mem->offset + offset, size);
254
255   return sub;
256 }
257
258 static gboolean
259 _default_mem_is_span (GstMemoryDefault * mem1, GstMemoryDefault * mem2,
260     gsize * offset)
261 {
262   if (offset)
263     *offset = mem1->offset;
264
265   /* and memory is contiguous */
266   return mem1->data + mem1->offset + mem1->size == mem2->data + mem2->offset;
267 }
268
269 static GstMemory *
270 _fallback_copy (GstMemory * mem, gsize offset, gsize size)
271 {
272   GstMemoryDefault *copy;
273   guint8 *data;
274   gsize msize;
275
276   data = gst_memory_map (mem, &msize, NULL, GST_MAP_READ);
277   if (size == -1)
278     size = msize > offset ? msize - offset : 0;
279   copy = _default_mem_new_block (size, 0, 0, size);
280   memcpy (copy->data, data + offset, size);
281   gst_memory_unmap (mem, data, msize);
282
283   return (GstMemory *) copy;
284 }
285
286 static GstMemory *
287 _fallback_share (GstMemory * mem, gsize offset, gsize size)
288 {
289   GstMemoryDefault *sub;
290   GstMemory *parent;
291
292   /* find the real parent */
293   parent = mem->parent ? mem->parent : mem;
294
295   sub = _default_mem_new (0, parent, NULL, NULL, size, offset, size);
296
297   return (GstMemory *) sub;
298 }
299
300 static gboolean
301 _fallback_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset)
302 {
303   return FALSE;
304 }
305
306 void
307 _gst_memory_init (void)
308 {
309   static const GstMemoryInfo _mem_info = {
310     (GstMemoryGetSizesFunction) _default_mem_get_sizes,
311     (GstMemoryResizeFunction) _default_mem_resize,
312     (GstMemoryMapFunction) _default_mem_map,
313     (GstMemoryUnmapFunction) _default_mem_unmap,
314     (GstMemoryFreeFunction) _default_mem_free,
315     (GstMemoryCopyFunction) _default_mem_copy,
316     (GstMemoryShareFunction) _default_mem_share,
317     (GstMemoryIsSpanFunction) _default_mem_is_span
318   };
319   static const GstMemoryInfo _share_info = {
320     (GstMemoryGetSizesFunction) _default_mem_get_sizes,
321     (GstMemoryResizeFunction) _default_mem_resize,
322     (GstMemoryMapFunction) _default_share_map,
323     (GstMemoryUnmapFunction) _default_share_unmap,
324     (GstMemoryFreeFunction) _default_mem_free,
325     NULL,
326     NULL,
327     NULL
328   };
329
330   _default_mem_impl = gst_memory_register ("GstMemoryDefault", &_mem_info);
331   _default_share_impl =
332       gst_memory_register ("GstMemorySharebuffer", &_share_info);
333 }
334
335 /**
336  * gst_memory_register:
337  * @name: the name of the implementation
338  * @info: #GstMemoryInfo
339  *
340  * Registers the memory implementation with @name and implementation functions
341  * @info.
342  *
343  * Returns: a new #GstMemoryImpl.
344  */
345 const GstMemoryImpl *
346 gst_memory_register (const gchar * name, const GstMemoryInfo * info)
347 {
348   GstMemoryImpl *impl;
349
350 #define INSTALL_FALLBACK(_t) \
351   if (impl->info._t == NULL) impl->info._t = _fallback_ ##_t;
352
353   g_return_val_if_fail (name != NULL, NULL);
354   g_return_val_if_fail (info != NULL, NULL);
355   g_return_val_if_fail (info->get_sizes != NULL, NULL);
356   g_return_val_if_fail (info->resize != NULL, NULL);
357   g_return_val_if_fail (info->map != NULL, NULL);
358   g_return_val_if_fail (info->unmap != NULL, NULL);
359   g_return_val_if_fail (info->free != NULL, NULL);
360
361   impl = g_slice_new (GstMemoryImpl);
362   impl->name = g_quark_from_string (name);
363   impl->info = *info;
364   INSTALL_FALLBACK (copy);
365   INSTALL_FALLBACK (share);
366   INSTALL_FALLBACK (is_span);
367
368   GST_DEBUG ("register \"%s\" of size %" G_GSIZE_FORMAT, name);
369
370 #if 0
371   g_static_rw_lock_writer_lock (&lock);
372   g_hash_table_insert (memoryimpl, (gpointer) name, (gpointer) impl);
373   g_static_rw_lock_writer_unlock (&lock);
374 #endif
375 #undef INSTALL_FALLBACK
376
377   return impl;
378 }
379
380 /**
381  * gst_memory_new_wrapped:
382  * @flags: #GstMemoryFlags
383  * @data: data to wrap
384  * @free_func: function to free @data
385  * @maxsize: allocated size of @data
386  * @offset: offset in @data
387  * @size: size of valid data
388  *
389  * Allocate a new memory block that wraps the given @data.
390  *
391  * Returns: a new #GstMemory.
392  */
393 GstMemory *
394 gst_memory_new_wrapped (GstMemoryFlags flags, gpointer data,
395     GFreeFunc free_func, gsize maxsize, gsize offset, gsize size)
396 {
397   GstMemoryDefault *mem;
398
399   g_return_val_if_fail (data != NULL, NULL);
400   g_return_val_if_fail (offset + size <= maxsize, NULL);
401
402   mem = _default_mem_new (flags, NULL, data, free_func, maxsize, offset, size);
403
404   return (GstMemory *) mem;
405 }
406
407 /**
408  * gst_memory_new_alloc:
409  * @maxsize: allocated size of @data
410  * @align: alignment for the data
411  *
412  * Allocate a new memory block with memory that is at least @maxsize big and las
413  * the given alignment.
414  *
415  * Returns: a new #GstMemory.
416  */
417 GstMemory *
418 gst_memory_new_alloc (gsize maxsize, gsize align)
419 {
420   GstMemoryDefault *mem;
421
422   mem = _default_mem_new_block (maxsize, align, 0, maxsize);
423
424   return (GstMemory *) mem;
425 }
426
427 /**
428  * gst_memory_ref:
429  * @mem: a #GstMemory
430  *
431  * Increases the refcount of @mem.
432  *
433  * Returns: @mem with increased refcount
434  */
435 GstMemory *
436 gst_memory_ref (GstMemory * mem)
437 {
438   g_return_val_if_fail (mem != NULL, NULL);
439
440   g_atomic_int_inc (&mem->refcount);
441
442   return mem;
443 }
444
445 /**
446  * gst_memory_unref:
447  * @mem: a #GstMemory
448  *
449  * Decreases the refcount of @mem. When the refcount reaches 0, the free
450  * function of @mem will be called.
451  */
452 void
453 gst_memory_unref (GstMemory * mem)
454 {
455   g_return_if_fail (mem != NULL);
456   g_return_if_fail (mem->impl != NULL);
457
458   if (g_atomic_int_dec_and_test (&mem->refcount))
459     mem->impl->info.free (mem);
460 }
461
462 /**
463  * gst_memory_get_sizes:
464  * @mem: a #GstMemory
465  * @maxsize: pointer to maxsize
466  *
467  * Get the current @size and @maxsize of @mem.
468  *
469  * Returns: the current sizes of @mem
470  */
471 gsize
472 gst_memory_get_sizes (GstMemory * mem, gsize * maxsize)
473 {
474   g_return_val_if_fail (mem != NULL, 0);
475
476   return mem->impl->info.get_sizes (mem, maxsize);
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 void
489 gst_memory_resize (GstMemory * mem, gsize offset, gsize size)
490 {
491   g_return_if_fail (mem != NULL);
492   g_return_if_fail (GST_MEMORY_IS_WRITABLE (mem));
493
494   mem->impl->info.resize (mem, offset, size);
495 }
496
497 /**
498  * gst_memory_map:
499  * @mem: a #GstMemory
500  * @size: pointer for size
501  * @maxsize: pointer for maxsize
502  * @flags: mapping flags
503  *
504  * Get a pointer to the memory of @mem that can be accessed according to @flags.
505  *
506  * @size and @maxsize will contain the size of the memory and the maximum
507  * allocated memory of @mem respectively. They can be set to NULL.
508  *
509  * Returns: a pointer to the memory of @mem.
510  */
511 gpointer
512 gst_memory_map (GstMemory * mem, gsize * size, gsize * maxsize,
513     GstMapFlags flags)
514 {
515   g_return_val_if_fail (mem != NULL, NULL);
516   g_return_val_if_fail (!(flags & GST_MAP_WRITE) ||
517       GST_MEMORY_IS_WRITABLE (mem), NULL);
518
519   return mem->impl->info.map (mem, size, maxsize, flags);
520 }
521
522 /**
523  * gst_memory_unmap:
524  * @mem: a #GstMemory
525  * @data: data to unmap
526  * @size: new size of @mem
527  *
528  * Release the memory pointer obtained with gst_memory_map() and set the size of
529  * the memory to @size. @size can be set to -1 when the size should not be
530  * updated.
531  *
532  * Returns: TRUE when the memory was release successfully.
533  */
534 gboolean
535 gst_memory_unmap (GstMemory * mem, gpointer data, gsize size)
536 {
537   g_return_val_if_fail (mem != NULL, FALSE);
538
539   return mem->impl->info.unmap (mem, data, size);
540 }
541
542 /**
543  * gst_memory_copy:
544  * @mem: a #GstMemory
545  * @offset: an offset to copy
546  * @size: size to copy
547  *
548  * Return a copy of @size bytes from @mem starting from @offset. This copy is
549  * guaranteed to be writable. @size can be set to -1 to return a copy all bytes
550  * from @offset.
551  *
552  * Returns: a new #GstMemory.
553  */
554 GstMemory *
555 gst_memory_copy (GstMemory * mem, gsize offset, gsize size)
556 {
557   g_return_val_if_fail (mem != NULL, NULL);
558
559   return mem->impl->info.copy (mem, offset, size);
560 }
561
562 /**
563  * gst_memory_share:
564  * @mem: a #GstMemory
565  * @offset: an offset to share
566  * @size: size to share
567  *
568  * Return a shared copy of @size bytes from @mem starting from @offset. No memory
569  * copy is performed and the memory region is simply shared. The result is
570  * guaranteed to be not-writable. @size can be set to -1 to return a share all bytes
571  * from @offset.
572  *
573  * Returns: a new #GstMemory.
574  */
575 GstMemory *
576 gst_memory_share (GstMemory * mem, gsize offset, gsize size)
577 {
578   g_return_val_if_fail (mem != NULL, NULL);
579
580   return mem->impl->info.share (mem, offset, size);
581 }
582
583 /**
584  * gst_memory_is_span:
585  * @mem1: a #GstMemory
586  * @mem2: a #GstMemory
587  * @offset: a pointer to a result offset
588  *
589  * Check if @mem1 and mem2 share the memory with a common parent memory object
590  * and that the memory is contiguous.
591  *
592  * If this is the case, the memory of @mem1 and @mem2 can be merged
593  * efficiently by performing gst_memory_share() on the parent object from
594  * the returned @offset.
595  *
596  * Returns: %TRUE if the memory is contiguous and of a common parent.
597  */
598 gboolean
599 gst_memory_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset)
600 {
601   g_return_val_if_fail (mem1 != NULL, FALSE);
602   g_return_val_if_fail (mem2 != NULL, FALSE);
603
604   /* need to have the same implementation */
605   if (mem1->impl != mem2->impl)
606     return FALSE;
607
608   /* need to have the same parent */
609   if (mem1->parent == NULL || mem1->parent != mem2->parent)
610     return FALSE;
611
612   /* and memory is contiguous */
613   if (!mem1->impl->info.is_span (mem1, mem2, offset))
614     return FALSE;
615
616   return TRUE;
617 }