bdbd5e4e6e896b2b366ff6e90657dda678850914
[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
291   sub = _default_mem_new (0, mem, NULL, NULL, size, offset, size);
292
293   return (GstMemory *) sub;
294 }
295
296 static gboolean
297 _fallback_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset)
298 {
299   return FALSE;
300 }
301
302 void
303 _gst_memory_init (void)
304 {
305   static const GstMemoryInfo _mem_info = {
306     (GstMemoryGetSizesFunction) _default_mem_get_sizes,
307     (GstMemoryResizeFunction) _default_mem_resize,
308     (GstMemoryMapFunction) _default_mem_map,
309     (GstMemoryUnmapFunction) _default_mem_unmap,
310     (GstMemoryFreeFunction) _default_mem_free,
311     (GstMemoryCopyFunction) _default_mem_copy,
312     (GstMemoryShareFunction) _default_mem_share,
313     (GstMemoryIsSpanFunction) _default_mem_is_span
314   };
315   static const GstMemoryInfo _share_info = {
316     (GstMemoryGetSizesFunction) _default_mem_get_sizes,
317     (GstMemoryResizeFunction) _default_mem_resize,
318     (GstMemoryMapFunction) _default_share_map,
319     (GstMemoryUnmapFunction) _default_share_unmap,
320     (GstMemoryFreeFunction) _default_mem_free,
321     NULL,
322     NULL,
323     NULL
324   };
325
326   _default_mem_impl = gst_memory_register ("GstMemoryDefault", &_mem_info);
327   _default_share_impl =
328       gst_memory_register ("GstMemorySharebuffer", &_share_info);
329 }
330
331 /**
332  * gst_memory_register:
333  * @name: the name of the implementation
334  * @info: #GstMemoryInfo
335  *
336  * Registers the memory implementation with @name and implementation functions
337  * @info.
338  *
339  * Returns: a new #GstMemoryImpl.
340  */
341 const GstMemoryImpl *
342 gst_memory_register (const gchar * name, const GstMemoryInfo * info)
343 {
344   GstMemoryImpl *impl;
345
346 #define INSTALL_FALLBACK(_t) \
347   if (impl->info._t == NULL) impl->info._t = _fallback_ ##_t;
348
349   g_return_val_if_fail (name != NULL, NULL);
350   g_return_val_if_fail (info != NULL, NULL);
351   g_return_val_if_fail (info->get_sizes != NULL, NULL);
352   g_return_val_if_fail (info->resize != NULL, NULL);
353   g_return_val_if_fail (info->map != NULL, NULL);
354   g_return_val_if_fail (info->unmap != NULL, NULL);
355   g_return_val_if_fail (info->free != NULL, NULL);
356
357   impl = g_slice_new (GstMemoryImpl);
358   impl->name = g_quark_from_string (name);
359   impl->info = *info;
360   INSTALL_FALLBACK (copy);
361   INSTALL_FALLBACK (share);
362   INSTALL_FALLBACK (is_span);
363
364   GST_DEBUG ("register \"%s\" of size %" G_GSIZE_FORMAT, name);
365
366 #if 0
367   g_static_rw_lock_writer_lock (&lock);
368   g_hash_table_insert (memoryimpl, (gpointer) name, (gpointer) impl);
369   g_static_rw_lock_writer_unlock (&lock);
370 #endif
371 #undef INSTALL_FALLBACK
372
373   return impl;
374 }
375
376 /**
377  * gst_memory_new_wrapped:
378  * @flags: #GstMemoryFlags
379  * @data: data to wrap
380  * @free_func: function to free @data
381  * @maxsize: allocated size of @data
382  * @offset: offset in @data
383  * @size: size of valid data
384  *
385  * Allocate a new memory block that wraps the given @data.
386  *
387  * Returns: a new #GstMemory.
388  */
389 GstMemory *
390 gst_memory_new_wrapped (GstMemoryFlags flags, gpointer data,
391     GFreeFunc free_func, gsize maxsize, gsize offset, gsize size)
392 {
393   GstMemoryDefault *mem;
394
395   g_return_val_if_fail (data != NULL, NULL);
396   g_return_val_if_fail (offset + size <= maxsize, NULL);
397
398   mem = _default_mem_new (flags, NULL, data, free_func, maxsize, offset, size);
399
400   return (GstMemory *) mem;
401 }
402
403 /**
404  * gst_memory_new_alloc:
405  * @maxsize: allocated size of @data
406  * @align: alignment for the data
407  *
408  * Allocate a new memory block with memory that is at least @maxsize big and las
409  * the given alignment.
410  *
411  * Returns: a new #GstMemory.
412  */
413 GstMemory *
414 gst_memory_new_alloc (gsize maxsize, gsize align)
415 {
416   GstMemoryDefault *mem;
417
418   mem = _default_mem_new_block (maxsize, align, 0, maxsize);
419
420   return (GstMemory *) mem;
421 }
422
423 /**
424  * gst_memory_ref:
425  * @mem: a #GstMemory
426  *
427  * Increases the refcount of @mem.
428  *
429  * Returns: @mem with increased refcount
430  */
431 GstMemory *
432 gst_memory_ref (GstMemory * mem)
433 {
434   g_return_val_if_fail (mem != NULL, NULL);
435
436   g_atomic_int_inc (&mem->refcount);
437
438   return mem;
439 }
440
441 /**
442  * gst_memory_unref:
443  * @mem: a #GstMemory
444  *
445  * Decreases the refcount of @mem. When the refcount reaches 0, the free
446  * function of @mem will be called.
447  */
448 void
449 gst_memory_unref (GstMemory * mem)
450 {
451   g_return_if_fail (mem != NULL);
452   g_return_if_fail (mem->impl != NULL);
453
454   if (g_atomic_int_dec_and_test (&mem->refcount))
455     mem->impl->info.free (mem);
456 }
457
458 /**
459  * gst_memory_get_sizes:
460  * @mem: a #GstMemory
461  * @maxsize: pointer to maxsize
462  *
463  * Get the current @size and @maxsize of @mem.
464  *
465  * Returns: the current sizes of @mem
466  */
467 gsize
468 gst_memory_get_sizes (GstMemory * mem, gsize * maxsize)
469 {
470   g_return_val_if_fail (mem != NULL, 0);
471
472   return mem->impl->info.get_sizes (mem, maxsize);
473 }
474
475 /**
476  * gst_memory_resize:
477  * @mem: a #GstMemory
478  * @offset: a new offset
479  * @size: a new size
480  *
481  * Resize the memory region. @mem should be writable and offset + size should be
482  * less than the maxsize of @mem.
483  */
484 void
485 gst_memory_resize (GstMemory * mem, gsize offset, gsize size)
486 {
487   g_return_if_fail (mem != NULL);
488   g_return_if_fail (GST_MEMORY_IS_WRITABLE (mem));
489
490   mem->impl->info.resize (mem, offset, size);
491 }
492
493 /**
494  * gst_memory_map:
495  * @mem: a #GstMemory
496  * @size: pointer for size
497  * @maxsize: pointer for maxsize
498  * @flags: mapping flags
499  *
500  * Get a pointer to the memory of @mem that can be accessed according to @flags.
501  *
502  * @size and @maxsize will contain the size of the memory and the maximum
503  * allocated memory of @mem respectively. They can be set to NULL.
504  *
505  * Returns: a pointer to the memory of @mem.
506  */
507 gpointer
508 gst_memory_map (GstMemory * mem, gsize * size, gsize * maxsize,
509     GstMapFlags flags)
510 {
511   g_return_val_if_fail (mem != NULL, NULL);
512   g_return_val_if_fail (!(flags & GST_MAP_WRITE) ||
513       GST_MEMORY_IS_WRITABLE (mem), NULL);
514
515   return mem->impl->info.map (mem, size, maxsize, flags);
516 }
517
518 /**
519  * gst_memory_unmap:
520  * @mem: a #GstMemory
521  * @data: data to unmap
522  * @size: new size of @mem
523  *
524  * Release the memory pointer obtained with gst_memory_map() and set the size of
525  * the memory to @size. @size can be set to -1 when the size should not be
526  * updated.
527  *
528  * Returns: TRUE when the memory was release successfully.
529  */
530 gboolean
531 gst_memory_unmap (GstMemory * mem, gpointer data, gsize size)
532 {
533   g_return_val_if_fail (mem != NULL, FALSE);
534
535   return mem->impl->info.unmap (mem, data, size);
536 }
537
538 /**
539  * gst_memory_copy:
540  * @mem: a #GstMemory
541  * @offset: an offset to copy
542  * @size: size to copy
543  *
544  * Return a copy of @size bytes from @mem starting from @offset. This copy is
545  * guaranteed to be writable. @size can be set to -1 to return a copy all bytes
546  * from @offset.
547  *
548  * Returns: a new #GstMemory.
549  */
550 GstMemory *
551 gst_memory_copy (GstMemory * mem, gsize offset, gsize size)
552 {
553   g_return_val_if_fail (mem != NULL, NULL);
554
555   return mem->impl->info.copy (mem, offset, size);
556 }
557
558 /**
559  * gst_memory_share:
560  * @mem: a #GstMemory
561  * @offset: an offset to share
562  * @size: size to share
563  *
564  * Return a shared copy of @size bytes from @mem starting from @offset. No memory
565  * copy is performed and the memory region is simply shared. The result is
566  * guaranteed to be not-writable. @size can be set to -1 to return a share all bytes
567  * from @offset.
568  *
569  * Returns: a new #GstMemory.
570  */
571 GstMemory *
572 gst_memory_share (GstMemory * mem, gsize offset, gsize size)
573 {
574   g_return_val_if_fail (mem != NULL, NULL);
575
576   return mem->impl->info.share (mem, offset, size);
577 }
578
579 /**
580  * gst_memory_is_span:
581  * @mem1: a #GstMemory
582  * @mem2: a #GstMemory
583  * @offset: a pointer to a result offset
584  *
585  * Check if @mem1 and mem2 share the memory with a common parent memory object
586  * and that the memory is contiguous.
587  *
588  * If this is the case, the memory of @mem1 and @mem2 can be merged
589  * efficiently by performing gst_memory_share() on the parent object from
590  * the returned @offset.
591  *
592  * Returns: %TRUE if the memory is contiguous and of a common parent.
593  */
594 gboolean
595 gst_memory_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset)
596 {
597   g_return_val_if_fail (mem1 != NULL, FALSE);
598   g_return_val_if_fail (mem2 != NULL, FALSE);
599
600   /* need to have the same implementation */
601   if (mem1->impl != mem2->impl)
602     return FALSE;
603
604   /* need to have the same parent */
605   if (mem1->parent == NULL || mem1->parent != mem2->parent)
606     return FALSE;
607
608   /* and memory is contiguous */
609   if (!mem1->impl->info.is_span (mem1, mem2, offset))
610     return FALSE;
611
612   return TRUE;
613 }