memory: more memory improvements

This commit is contained in:
Wim Taymans 2011-03-19 10:45:37 +01:00
parent 1a7e600f39
commit b35c0df940
2 changed files with 269 additions and 126 deletions

View file

@ -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;
}

View file

@ -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);