diff --git a/gst/gstmemory.c b/gst/gstmemory.c index 2a15dd157f..53c034b729 100644 --- a/gst/gstmemory.c +++ b/gst/gstmemory.c @@ -35,119 +35,209 @@ struct _GstMemoryImpl typedef struct { GstMemory mem; - + gsize slice_size; guint8 *data; GFreeFunc free_func; - gpointer free_data; gsize maxsize; gsize offset; gsize size; } GstMemoryDefault; -static const GstMemoryImpl *_default_memory_impl; +static const GstMemoryImpl *_default_mem_impl; +static const GstMemoryImpl *_default_sub_impl; + +static void +_default_mem_init (GstMemoryDefault * mem, GstMemory * parent, + gsize slice_size, gpointer data, GFreeFunc free_func, + gsize maxsize, gsize offset, gsize size) +{ + mem->mem.refcount = 1; + mem->mem.impl = data ? _default_mem_impl : _default_sub_impl; + mem->mem.parent = parent ? gst_memory_ref (parent) : NULL; + mem->slice_size = slice_size; + mem->data = data; + mem->free_func = free_func; + mem->maxsize = maxsize; + mem->offset = offset; + mem->size = size; +} + +static GstMemoryDefault * +_default_mem_new (GstMemory * parent, gpointer data, + GFreeFunc free_func, gsize maxsize, gsize offset, gsize size) +{ + GstMemoryDefault *mem; + + mem = g_slice_new (GstMemoryDefault); + _default_mem_init (mem, parent, sizeof (GstMemoryDefault), + data, free_func, maxsize, offset, size); + + return mem; +} static gsize -_default_get_sizes (GstMemory * mem, gsize * maxsize) +_default_mem_get_sizes (GstMemoryDefault * mem, gsize * maxsize) { - GstMemoryDefault *def = (GstMemoryDefault *) mem; - if (maxsize) - *maxsize = def->maxsize; + *maxsize = mem->maxsize; - return def->size; + return mem->size; +} + +static void +_default_mem_trim (GstMemoryDefault * mem, gsize offset, gsize size) +{ + g_return_if_fail (size + mem->offset + offset > mem->maxsize); + + mem->offset += offset; + mem->size = size; } static gpointer -_default_map (GstMemory * mem, gsize * size, gsize * maxsize, GstMapFlags flags) +_default_mem_map (GstMemoryDefault * mem, gsize * size, gsize * maxsize, + GstMapFlags flags) { - GstMemoryDefault *def = (GstMemoryDefault *) mem; + if (size) + *size = mem->size; + if (maxsize) + *maxsize = mem->maxsize; + + return mem->data + mem->offset; +} + +static gpointer +_default_sub_map (GstMemoryDefault * mem, gsize * size, gsize * maxsize, + GstMapFlags flags) +{ + guint8 *data; + + data = gst_memory_map (mem->mem.parent, size, maxsize, flags); if (size) - *size = def->size; + *size = mem->size; if (maxsize) - *maxsize = def->maxsize; + *maxsize -= mem->offset; - return def->data + def->offset; + return data + mem->offset; } static gboolean -_default_unmap (GstMemory * mem, gpointer data, gsize size) +_default_mem_unmap (GstMemoryDefault * mem, gpointer data, gsize size) { - GstMemoryDefault *def = (GstMemoryDefault *) mem; + mem->size = size; + return TRUE; +} - def->size = size; +static gboolean +_default_sub_unmap (GstMemoryDefault * mem, gpointer data, gsize size) +{ + gboolean res; + guint8 *ptr = data; + + mem->size = size; + + res = + gst_memory_unmap (mem->mem.parent, ptr - mem->offset, size + mem->offset); + + return res; +} + +static void +_default_mem_free (GstMemoryDefault * mem) +{ + if (mem->mem.parent) + gst_memory_unref (mem->mem.parent); + + if (mem->free_func) + mem->free_func (mem->data); + + g_slice_free1 (mem->slice_size, mem); +} + +static GstMemoryDefault * +_default_mem_copy (GstMemoryDefault * mem) +{ + GstMemoryDefault *copy; + gpointer data; + + data = g_memdup (mem->data, mem->maxsize); + copy = _default_mem_new (NULL, data, g_free, mem->maxsize, + mem->offset, mem->size); + + return copy; +} + +static void +_default_mem_extract (GstMemoryDefault * mem, gsize offset, gpointer dest, + gsize size) +{ + g_return_if_fail (size + mem->offset + offset > mem->maxsize); + + memcpy (dest, mem->data + mem->offset + offset, size); +} + +static GstMemoryDefault * +_default_mem_sub (GstMemoryDefault * mem, gsize offset, gsize size) +{ + GstMemoryDefault *sub; + GstMemory *parent; + + /* find the real parent */ + if ((parent = mem->mem.parent) == NULL) + parent = (GstMemory *) mem; + + sub = _default_mem_new (parent, mem->data, NULL, mem->maxsize, + mem->offset + offset, size); + + return sub; +} + +static gboolean +_default_mem_is_span (GstMemoryDefault * mem1, GstMemoryDefault * mem2) +{ + /* need to have the same implementation */ + if (mem1->mem.impl != mem2->mem.impl) + return FALSE; + + /* need to have the same parent */ + if (mem1->mem.parent == NULL || mem1->mem.parent != mem2->mem.parent) + return FALSE; + + /* and memory is contiguous */ + if (mem1->data + mem1->offset + mem1->size != mem2->data + mem2->offset) + return FALSE; return TRUE; } -static void -_default_free (GstMemory * mem) +static GstMemoryDefault * +_default_mem_span (GstMemoryDefault * mem1, gsize offset, + GstMemoryDefault * mem2, gsize size) { - GstMemoryDefault *def = (GstMemoryDefault *) mem; + GstMemoryDefault *span; - if (def->free_func) - def->free_func (def->free_data); -} + if (_default_mem_is_span (mem1, mem2)) { + GstMemoryDefault *parent = (GstMemoryDefault *) mem1->mem.parent; -static GstMemory * -_default_copy (GstMemory * mem) -{ - GstMemoryDefault *def = (GstMemoryDefault *) mem; - GstMemoryDefault *copy; + span = + _default_mem_sub (parent, mem1->offset - parent->offset + offset, size); + } else { + guint8 *data; + gsize len1; - copy = g_slice_new (GstMemoryDefault); - copy->mem.impl = _default_memory_impl; - copy->data = g_memdup (def->data, def->maxsize); - copy->free_data = copy->data; - copy->free_func = g_free; - copy->maxsize = def->maxsize; - copy->offset = def->offset; - copy->size = def->size; + data = g_malloc (size); + len1 = mem1->size - offset; - return (GstMemory *) copy; + memcpy (data, mem1->data + mem1->offset + offset, len1); + memcpy (data + len1, mem2->data + mem2->offset, size - len1); + + span = _default_mem_new (NULL, data, g_free, size, 0, size); + } + return span; } static void -_default_copy_into (GstMemory * mem, gsize offset, gpointer dest, gsize size) -{ - GstMemoryDefault *def = (GstMemoryDefault *) mem; - - g_return_if_fail (size + def->offset + offset > def->maxsize); - - memcpy (dest, def->data + def->offset + offset, size); -} - -static void -_default_trim (GstMemory * mem, gsize offset, gsize size) -{ - GstMemoryDefault *def = (GstMemoryDefault *) mem; - - g_return_if_fail (size + def->offset + offset > def->maxsize); - - def->offset += offset; - def->size = size; -} - -static GstMemory * -_default_sub (GstMemory * mem, gsize offset, gsize size) -{ - GstMemoryDefault *def = (GstMemoryDefault *) mem; - GstMemoryDefault *sub; - - sub = g_slice_new (GstMemoryDefault); - sub->mem.impl = _default_memory_impl; - sub->data = def->data; - sub->free_data = gst_memory_ref (mem); - sub->free_func = (GFreeFunc) gst_memory_unref; - sub->maxsize = def->maxsize; - sub->offset = def->offset + offset; - sub->size = size; - - return (GstMemory *) sub; -} - -static void -_fallback_copy_into (GstMemory * mem, gsize offset, gpointer dest, gsize size) +_fallback_extract (GstMemory * mem, gsize offset, gpointer dest, gsize size) { guint8 *data; gsize msize; @@ -160,7 +250,7 @@ _fallback_copy_into (GstMemory * mem, gsize offset, gpointer dest, gsize size) static GstMemory * _fallback_copy (GstMemory * mem) { - GstMemory *copy; + GstMemoryDefault *copy; gpointer data, cdata; gsize size; @@ -168,25 +258,21 @@ _fallback_copy (GstMemory * mem) cdata = g_memdup (data, size); gst_memory_unmap (mem, data, size); - copy = gst_memory_new_wrapped (cdata, g_free, size, 0, size); + copy = _default_mem_new (NULL, cdata, g_free, size, 0, size); - return copy; + return (GstMemory *) copy; } static GstMemory * _fallback_sub (GstMemory * mem, gsize offset, gsize size) { - GstMemoryDefault *def = (GstMemoryDefault *) mem; GstMemoryDefault *sub; + GstMemory *parent; - sub = g_slice_new (GstMemoryDefault); - sub->mem.impl = _default_memory_impl; - sub->data = def->data; - sub->free_data = sub->data; - sub->free_func = NULL; - sub->maxsize = def->maxsize; - sub->offset = def->offset + offset; - sub->size = size; + /* find the real parent */ + parent = mem->parent ? mem->parent : mem; + + sub = _default_mem_new (parent, NULL, NULL, size, offset, size); return (GstMemory *) sub; } @@ -200,7 +286,24 @@ _fallback_is_span (GstMemory * mem1, GstMemory * mem2) static GstMemory * _fallback_span (GstMemory * mem1, gsize offset, GstMemory * mem2, gsize size) { - return FALSE; + GstMemoryDefault *span; + guint8 *data, *dest; + gsize ssize, len1; + + dest = g_malloc (size); + + data = gst_memory_map (mem1, &ssize, NULL, GST_MAP_READ); + len1 = ssize - offset; + memcpy (dest, data + offset, len1); + gst_memory_unmap (mem1, data, size); + + data = gst_memory_map (mem2, &ssize, NULL, GST_MAP_READ); + memcpy (dest + len1, data, ssize - len1); + gst_memory_unmap (mem2, data, size); + + span = _default_mem_new (NULL, dest, g_free, size, 0, size); + + return (GstMemory *) span; } const GstMemoryImpl * @@ -223,7 +326,7 @@ gst_memory_register (const gchar * name, const GstMemoryInfo * info) impl->name = g_quark_from_string (name); impl->info = *info; INSTALL_FALLBACK (copy); - INSTALL_FALLBACK (copy_into); + INSTALL_FALLBACK (extract); INSTALL_FALLBACK (sub); INSTALL_FALLBACK (is_span); INSTALL_FALLBACK (span); @@ -243,17 +346,33 @@ gst_memory_register (const gchar * name, const GstMemoryInfo * info) void _gst_memory_init (void) { - static const GstMemoryInfo info = { - _default_get_sizes, - _default_trim, - _default_map, - _default_unmap, - _default_free, - _default_copy, - _default_copy_into, - _default_sub + static const GstMemoryInfo _mem_info = { + (GstMemoryGetSizesFunction) _default_mem_get_sizes, + (GstMemoryTrimFunction) _default_mem_trim, + (GstMemoryMapFunction) _default_mem_map, + (GstMemoryUnmapFunction) _default_mem_unmap, + (GstMemoryFreeFunction) _default_mem_free, + (GstMemoryCopyFunction) _default_mem_copy, + (GstMemoryExtractFunction) _default_mem_extract, + (GstMemorySubFunction) _default_mem_sub, + (GstMemoryIsSpanFunction) _default_mem_is_span, + (GstMemorySpanFunction) _default_mem_span }; - _default_memory_impl = gst_memory_register ("GstMemoryDefault", &info); + static const GstMemoryInfo _sub_info = { + (GstMemoryGetSizesFunction) _default_mem_get_sizes, + (GstMemoryTrimFunction) _default_mem_trim, + (GstMemoryMapFunction) _default_sub_map, + (GstMemoryUnmapFunction) _default_sub_unmap, + (GstMemoryFreeFunction) _default_mem_free, + NULL, + NULL, + NULL, + NULL, + NULL + }; + + _default_mem_impl = gst_memory_register ("GstMemoryDefault", &_mem_info); + _default_sub_impl = gst_memory_register ("GstMemorySubbuffer", &_sub_info); } GstMemory * @@ -309,12 +428,12 @@ gst_memory_copy (GstMemory * mem) } void -gst_memory_copy_into (GstMemory * mem, gsize offset, gpointer dest, gsize size) +gst_memory_extract (GstMemory * mem, gsize offset, gpointer dest, gsize size) { g_return_if_fail (mem != NULL); g_return_if_fail (dest != NULL); - return mem->impl->info.copy_into (mem, offset, dest, size); + return mem->impl->info.extract (mem, offset, dest, size); } void @@ -333,20 +452,31 @@ gst_memory_sub (GstMemory * mem, gsize offset, gsize size) return mem->impl->info.sub (mem, offset, size); } +gboolean +gst_memory_is_span (GstMemory * mem1, GstMemory * mem2) +{ + g_return_val_if_fail (mem1 != NULL, FALSE); + g_return_val_if_fail (mem2 != NULL, FALSE); + + return mem1->impl->info.is_span (mem1, mem2); +} + +GstMemory * +gst_memory_span (GstMemory * mem1, gsize offset, GstMemory * mem2, gsize size) +{ + g_return_val_if_fail (mem1 != NULL, NULL); + g_return_val_if_fail (mem2 != NULL, NULL); + + return mem1->impl->info.span (mem1, offset, mem2, size); +} + GstMemory * gst_memory_new_wrapped (gpointer data, GFreeFunc free_func, gsize maxsize, gsize offset, gsize size) { GstMemoryDefault *mem; - mem = g_slice_new (GstMemoryDefault); - mem->mem.impl = _default_memory_impl; - mem->data = data; - mem->free_data = data; - mem->free_func = free_func; - mem->maxsize = maxsize; - mem->offset = offset; - mem->size = size; + mem = _default_mem_new (NULL, data, free_func, maxsize, offset, size); return (GstMemory *) mem; } @@ -354,18 +484,24 @@ gst_memory_new_wrapped (gpointer data, GFreeFunc free_func, GstMemory * gst_memory_new_alloc (gsize maxsize, gsize align) { - GstMemory *mem; - gpointer data; - gsize offset; + GstMemoryDefault *mem; + guint8 *data; + gsize offset, size; - data = g_try_malloc (maxsize + align); - if (data == NULL) + /* alloc header and data in one block */ + size = sizeof (GstMemoryDefault) + maxsize + align; + + mem = g_slice_alloc (size); + if (mem == NULL) return NULL; + data = (guint8 *) mem + sizeof (GstMemoryDefault); + if ((offset = ((guintptr) data & align))) offset = align - offset; - mem = gst_memory_new_wrapped (data, g_free, maxsize + align, offset, maxsize); + _default_mem_init (mem, NULL, size, data, NULL, maxsize + align, offset, + maxsize); - return mem; + return (GstMemory *) mem; } diff --git a/gst/gstmemory.h b/gst/gstmemory.h index 11a57fef10..627b1778de 100644 --- a/gst/gstmemory.h +++ b/gst/gstmemory.h @@ -31,9 +31,16 @@ typedef struct _GstMemory GstMemory; typedef struct _GstMemoryInfo GstMemoryInfo; typedef struct _GstMemoryImpl GstMemoryImpl; +typedef enum { + GST_MEMORY_FLAG_READONLY = (1 << 0), + GST_MEMORY_FLAG_MUTABLE = (1 << 1), +} GstMemoryFlags; + /** * GstMemory: - * @info: pointer to the #GstMemoryInfo + * @impl: pointer to the #GstMemoryImpl + * @refcount: refcount + * @paret: parent memory block * * Base structure for memory implementations. Custom memory will put this structure * as the first member of their structure. @@ -41,7 +48,9 @@ typedef struct _GstMemoryImpl GstMemoryImpl; struct _GstMemory { const GstMemoryImpl *impl; - gint refcount; + GstMemoryFlags flags; + gint refcount; + GstMemory *parent; }; typedef enum { @@ -64,7 +73,7 @@ typedef gboolean (*GstMemoryUnmapFunction) (GstMemory *mem, gpointer data, gsiz typedef void (*GstMemoryFreeFunction) (GstMemory *mem); typedef GstMemory * (*GstMemoryCopyFunction) (GstMemory *mem); -typedef void (*GstMemoryCopyIntoFunction) (GstMemory *mem, gsize offset, +typedef void (*GstMemoryExtractFunction) (GstMemory *mem, gsize offset, gpointer dest, gsize size); typedef void (*GstMemoryTrimFunction) (GstMemory *mem, gsize offset, gsize size); typedef GstMemory * (*GstMemorySubFunction) (GstMemory *mem, gsize offset, gsize size); @@ -74,11 +83,9 @@ typedef GstMemory * (*GstMemorySpanFunction) (GstMemory *mem1, gsize offset, /** * GstMemoryInfo: - * @impl: tag indentifying the implementor of the api - * @size: size of the memory structure + * @get_sizes: * - * The #GstMemoryInfo provides information about a specific metadata - * structure. + * The #GstMemoryInfo is used to register new memory implementations. */ struct _GstMemoryInfo { GstMemoryGetSizesFunction get_sizes; @@ -88,7 +95,7 @@ struct _GstMemoryInfo { GstMemoryFreeFunction free; GstMemoryCopyFunction copy; - GstMemoryCopyIntoFunction copy_into; + GstMemoryExtractFunction extract; GstMemorySubFunction sub; GstMemoryIsSpanFunction is_span; GstMemorySpanFunction span; @@ -107,7 +114,7 @@ gpointer gst_memory_map (GstMemory *mem, gsize *size, gsize *maxsize, gboolean gst_memory_unmap (GstMemory *mem, gpointer data, gsize size); GstMemory * gst_memory_copy (GstMemory *mem); -void gst_memory_copy_into (GstMemory *mem, gsize offset, gpointer dest, +void gst_memory_extract (GstMemory *mem, gsize offset, gpointer dest, gsize size); GstMemory * gst_memory_sub (GstMemory *mem, gsize offset, gsize size);