* GstMemory is a lightweight refcounted object that wraps a region of memory.
* They are typically used to manage the data of a #GstBuffer.
*
+ * Memory is created by allocators.
+ *
* New memory can be created with gst_memory_new_wrapped() that wraps the memory
- * allocated elsewhere and gst_memory_new_alloc() that creates a new GstMemory
- * and the memory inside it.
+ * allocated elsewhere.
*
* Refcounting of the memory block is performed with gst_memory_ref() and
* gst_memory_unref().
#include "gstmemory.h"
-struct _GstMemoryImpl
+struct _GstMemoryAllocator
{
GQuark name;
gsize size;
} GstMemoryDefault;
-static const GstMemoryImpl *_default_mem_impl;
-static const GstMemoryImpl *_default_share_impl;
+/* the default allocator */
+static const GstMemoryAllocator *_default_allocator;
+
+/* our predefined allocators */
+static const GstMemoryAllocator *_default_mem_impl;
+static const GstMemoryAllocator *_default_share_impl;
/* initialize the fields */
static void
GstMemory * parent, gsize slice_size, gpointer data,
GFreeFunc free_func, gsize maxsize, gsize offset, gsize size)
{
- mem->mem.impl = data ? _default_mem_impl : _default_share_impl;
+ mem->mem.allocator = data ? _default_mem_impl : _default_share_impl;
mem->mem.flags = flags;
mem->mem.refcount = 1;
mem->mem.parent = parent ? gst_memory_ref (parent) : NULL;
return mem;
}
+static GstMemory *
+_default_mem_alloc (const GstMemoryAllocator * allocator, gsize maxsize,
+ gsize align)
+{
+ return (GstMemory *) _default_mem_new_block (maxsize, align, 0, maxsize);
+}
+
static gsize
_default_mem_get_sizes (GstMemoryDefault * mem, gsize * maxsize)
{
return FALSE;
}
+static GStaticRWLock lock = G_STATIC_RW_LOCK_INIT;
+static GHashTable *memoryimpl;
+
void
_gst_memory_init (void)
{
static const GstMemoryInfo _mem_info = {
+ (GstMemoryAllocFunction) _default_mem_alloc,
(GstMemoryGetSizesFunction) _default_mem_get_sizes,
(GstMemoryResizeFunction) _default_mem_resize,
(GstMemoryMapFunction) _default_mem_map,
(GstMemoryFreeFunction) _default_mem_free,
(GstMemoryCopyFunction) _default_mem_copy,
(GstMemoryShareFunction) _default_mem_share,
- (GstMemoryIsSpanFunction) _default_mem_is_span
+ (GstMemoryIsSpanFunction) _default_mem_is_span,
+ NULL
};
static const GstMemoryInfo _share_info = {
+ (GstMemoryAllocFunction) _default_mem_alloc,
(GstMemoryGetSizesFunction) _default_mem_get_sizes,
(GstMemoryResizeFunction) _default_mem_resize,
(GstMemoryMapFunction) _default_share_map,
(GstMemoryFreeFunction) _default_mem_free,
NULL,
NULL,
+ NULL,
NULL
};
- _default_mem_impl = gst_memory_register ("GstMemoryDefault", &_mem_info);
- _default_share_impl =
- gst_memory_register ("GstMemorySharebuffer", &_share_info);
-}
-
-/**
- * gst_memory_register:
- * @name: the name of the implementation
- * @info: #GstMemoryInfo
- *
- * Registers the memory implementation with @name and implementation functions
- * @info.
- *
- * Returns: a new #GstMemoryImpl.
- */
-const GstMemoryImpl *
-gst_memory_register (const gchar * name, const GstMemoryInfo * info)
-{
- GstMemoryImpl *impl;
-
-#define INSTALL_FALLBACK(_t) \
- if (impl->info._t == NULL) impl->info._t = _fallback_ ##_t;
+ memoryimpl = g_hash_table_new (g_str_hash, g_str_equal);
- g_return_val_if_fail (name != NULL, NULL);
- g_return_val_if_fail (info != NULL, NULL);
- g_return_val_if_fail (info->get_sizes != NULL, NULL);
- g_return_val_if_fail (info->resize != NULL, NULL);
- g_return_val_if_fail (info->map != NULL, NULL);
- g_return_val_if_fail (info->unmap != NULL, NULL);
- g_return_val_if_fail (info->free != NULL, NULL);
-
- impl = g_slice_new (GstMemoryImpl);
- impl->name = g_quark_from_string (name);
- impl->info = *info;
- INSTALL_FALLBACK (copy);
- INSTALL_FALLBACK (share);
- INSTALL_FALLBACK (is_span);
-
- GST_DEBUG ("register \"%s\" of size %" G_GSIZE_FORMAT, name);
-
-#if 0
- g_static_rw_lock_writer_lock (&lock);
- g_hash_table_insert (memoryimpl, (gpointer) name, (gpointer) impl);
- g_static_rw_lock_writer_unlock (&lock);
-#endif
-#undef INSTALL_FALLBACK
+ _default_mem_impl =
+ gst_memory_allocator_register ("GstMemoryDefault", &_mem_info);
+ _default_share_impl =
+ gst_memory_allocator_register ("GstMemorySharebuffer", &_share_info);
- return impl;
+ _default_allocator = _default_mem_impl;
}
/**
return (GstMemory *) mem;
}
-/**
- * gst_memory_new_alloc:
- * @maxsize: allocated size of @data
- * @align: alignment for the data
- *
- * Allocate a new memory block with memory that is at least @maxsize big and has
- * the given alignment.
- *
- * @align is given as a bitmask so that @align + 1 equals the amount of bytes to
- * align to. For example, to align to 8 bytes, use an alignment of 7.
- *
- * Returns: a new #GstMemory.
- */
-GstMemory *
-gst_memory_new_alloc (gsize maxsize, gsize align)
-{
- GstMemoryDefault *mem;
-
- g_return_val_if_fail (((align + 1) & align) == 0, NULL);
-
- mem = _default_mem_new_block (maxsize, align, 0, maxsize);
-
- return (GstMemory *) mem;
-}
-
/**
* gst_memory_ref:
* @mem: a #GstMemory
gst_memory_unref (GstMemory * mem)
{
g_return_if_fail (mem != NULL);
- g_return_if_fail (mem->impl != NULL);
+ g_return_if_fail (mem->allocator != NULL);
if (g_atomic_int_dec_and_test (&mem->refcount))
- mem->impl->info.free (mem);
+ mem->allocator->info.free (mem);
}
/**
{
g_return_val_if_fail (mem != NULL, 0);
- return mem->impl->info.get_sizes (mem, maxsize);
+ return mem->allocator->info.get_sizes (mem, maxsize);
}
/**
g_return_if_fail (mem != NULL);
g_return_if_fail (GST_MEMORY_IS_WRITABLE (mem));
- mem->impl->info.resize (mem, offset, size);
+ mem->allocator->info.resize (mem, offset, size);
}
/**
g_return_val_if_fail (!(flags & GST_MAP_WRITE) ||
GST_MEMORY_IS_WRITABLE (mem), NULL);
- return mem->impl->info.map (mem, size, maxsize, flags);
+ return mem->allocator->info.map (mem, size, maxsize, flags);
}
/**
{
g_return_val_if_fail (mem != NULL, FALSE);
- return mem->impl->info.unmap (mem, data, size);
+ return mem->allocator->info.unmap (mem, data, size);
}
/**
{
g_return_val_if_fail (mem != NULL, NULL);
- return mem->impl->info.copy (mem, offset, size);
+ return mem->allocator->info.copy (mem, offset, size);
}
/**
{
g_return_val_if_fail (mem != NULL, NULL);
- return mem->impl->info.share (mem, offset, size);
+ return mem->allocator->info.share (mem, offset, size);
}
/**
g_return_val_if_fail (mem1 != NULL, FALSE);
g_return_val_if_fail (mem2 != NULL, FALSE);
- /* need to have the same implementation */
- if (mem1->impl != mem2->impl)
+ /* need to have the same allocators */
+ if (mem1->allocator != mem2->allocator)
return FALSE;
/* need to have the same parent */
return FALSE;
/* and memory is contiguous */
- if (!mem1->impl->info.is_span (mem1, mem2, offset))
+ if (!mem1->allocator->info.is_span (mem1, mem2, offset))
return FALSE;
return TRUE;
}
+
+/**
+ * gst_memory_allocator_register:
+ * @name: the name of the allocator
+ * @info: #GstMemoryInfo
+ *
+ * Registers the memory allocator with @name and implementation functions
+ * @info.
+ *
+ * Returns: a new #GstMemoryAllocator.
+ */
+const GstMemoryAllocator *
+gst_memory_allocator_register (const gchar * name, const GstMemoryInfo * info)
+{
+ GstMemoryAllocator *allocator;
+
+#define INSTALL_FALLBACK(_t) \
+ if (allocator->info._t == NULL) allocator->info._t = _fallback_ ##_t;
+
+ g_return_val_if_fail (name != NULL, NULL);
+ g_return_val_if_fail (info != NULL, NULL);
+ g_return_val_if_fail (info->get_sizes != NULL, NULL);
+ g_return_val_if_fail (info->resize != NULL, NULL);
+ g_return_val_if_fail (info->map != NULL, NULL);
+ g_return_val_if_fail (info->unmap != NULL, NULL);
+ g_return_val_if_fail (info->free != NULL, NULL);
+
+ allocator = g_slice_new (GstMemoryAllocator);
+ allocator->name = g_quark_from_string (name);
+ allocator->info = *info;
+ INSTALL_FALLBACK (copy);
+ INSTALL_FALLBACK (share);
+ INSTALL_FALLBACK (is_span);
+#undef INSTALL_FALLBACK
+
+ GST_DEBUG ("register \"%s\" of size %" G_GSIZE_FORMAT, name);
+
+ g_static_rw_lock_writer_lock (&lock);
+ g_hash_table_insert (memoryimpl, (gpointer) name, (gpointer) allocator);
+ g_static_rw_lock_writer_unlock (&lock);
+
+ return allocator;
+}
+
+/**
+ * gst_memory_allocator_find:
+ * @name: the name of the allocator
+ *
+ * Find a previously registered allocator with @name.
+ *
+ * Returns: a #GstMemoryAllocator or NULL when the allocator with @name was not
+ * registered.
+ */
+const GstMemoryAllocator *
+gst_memory_allocator_find (const gchar * name)
+{
+ GstMemoryAllocator *allocator;
+
+ g_return_val_if_fail (name != NULL, NULL);
+
+ g_static_rw_lock_writer_lock (&lock);
+ allocator = g_hash_table_lookup (memoryimpl, (gconstpointer) name);
+ g_static_rw_lock_writer_unlock (&lock);
+
+ return allocator;
+}
+
+/**
+ * gst_memory_allocator_get_default:
+ *
+ * Get the default allocator.
+ *
+ * Returns: the default #GstMemoryAllocator
+ */
+const GstMemoryAllocator *
+gst_memory_allocator_get_default (void)
+{
+ return _default_allocator;
+}
+
+/**
+ * gst_memory_allocator_set_default:
+ * @allocator: a ##GstMemoryAllocator
+ *
+ * Set the default allocator.
+ */
+void
+gst_memory_allocator_set_default (const GstMemoryAllocator * allocator)
+{
+ g_return_if_fail (allocator != NULL);
+
+ _default_allocator = allocator;
+}
+
+/**
+ * gst_memory_allocator_alloc:
+ * @allocator: a #GstMemoryAllocator to use
+ * @maxsize: allocated size of @data
+ * @align: alignment for the data
+ *
+ * Use @allocator to allocate a new memory block with memory that is at least
+ * @maxsize big and has the given alignment.
+ *
+ * @align is given as a bitmask so that @align + 1 equals the amount of bytes to
+ * align to. For example, to align to 8 bytes, use an alignment of 7.
+ *
+ * Returns: a new #GstMemory.
+ */
+GstMemory *
+gst_memory_allocator_alloc (const GstMemoryAllocator * allocator,
+ gsize maxsize, gsize align)
+{
+ g_return_val_if_fail (allocator == NULL
+ || allocator->info.alloc != NULL, NULL);
+ g_return_val_if_fail (((align + 1) & align) == 0, NULL);
+
+ if (allocator == NULL)
+ allocator = _default_allocator;
+
+ return allocator->info.alloc (allocator, maxsize, align);
+}
typedef struct _GstMemory GstMemory;
typedef struct _GstMemoryInfo GstMemoryInfo;
-typedef struct _GstMemoryImpl GstMemoryImpl;
+typedef struct _GstMemoryAllocator GstMemoryAllocator;
/**
* GstMemoryFlags:
/**
* GstMemory:
- * @impl: pointer to the #GstMemoryImpl
+ * @allocator: pointer to the #GstMemoryAllocator
* @flags: memory flags
* @refcount: refcount
* @parent: parent memory block
* as the first member of their structure.
*/
struct _GstMemory {
- const GstMemoryImpl *impl;
+ const GstMemoryAllocator *allocator;
GstMemoryFlags flags;
gint refcount;
*/
#define GST_MEMORY_TRACE_NAME "GstMemory"
+/**
+ * GstMemoryGetSizesFunction:
+ * @maxsize: the maxsize
+ * @align: the alignment
+ *
+ * Allocate a new #GstMemory that hold at least @maxsize bytes and is aligned to
+ * (@align + 1) bytes.
+ *
+ * Returns: a newly allocated #GstMemory. Free with gst_memory_unref()
+ */
+typedef GstMemory * (*GstMemoryAllocFunction) (const GstMemoryAllocator *allocator, gsize maxsize, gsize align);
+
/**
* GstMemoryGetSizesFunction:
* @mem: a #GstMemory
/**
* GstMemoryInfo:
+ * @alloc: the implementation of the GstMemoryAllocFunction
* @get_sizes: the implementation of the GstMemoryGetSizesFunction
* @resize: the implementation of the GstMemoryResizeFunction
* @map: the implementation of the GstMemoryMapFunction
* @copy: the implementation of the GstMemoryCopyFunction
* @share: the implementation of the GstMemoryShareFunction
* @is_span: the implementation of the GstMemoryIsSpanFunction
+ * @user_data: generic user data for the allocator
*
- * The #GstMemoryInfo is used to register new memory implementations and contain
+ * The #GstMemoryInfo is used to register new memory allocators and contain
* the implementations for various memory operations.
*/
struct _GstMemoryInfo {
+ GstMemoryAllocFunction alloc;
GstMemoryGetSizesFunction get_sizes;
GstMemoryResizeFunction resize;
GstMemoryMapFunction map;
GstMemoryCopyFunction copy;
GstMemoryShareFunction share;
GstMemoryIsSpanFunction is_span;
+
+ gpointer user_data;
};
void _gst_memory_init (void);
+/* allocators */
+const GstMemoryAllocator * gst_memory_allocator_register (const gchar *name, const GstMemoryInfo *info);
+const GstMemoryAllocator * gst_memory_allocator_find (const gchar *name);
+
+const GstMemoryAllocator * gst_memory_allocator_get_default (void);
+void gst_memory_allocator_set_default (const GstMemoryAllocator * allocator);
+
/* allocating memory blocks */
-GstMemory * gst_memory_new_wrapped (GstMemoryFlags flags, gpointer data, GFreeFunc free_func,
- gsize maxsize, gsize offset, gsize size);
-GstMemory * gst_memory_new_alloc (gsize maxsize, gsize align);
+GstMemory * gst_memory_allocator_alloc (const GstMemoryAllocator * allocator,
+ gsize maxsize, gsize align);
+GstMemory * gst_memory_new_wrapped (GstMemoryFlags flags, gpointer data, GFreeFunc free_func,
+ gsize maxsize, gsize offset, gsize size);
/* refcounting */
GstMemory * gst_memory_ref (GstMemory *mem);
GstMemory * gst_memory_span (GstMemory **mem1, gsize len1, gsize offset,
GstMemory **mem2, gsize len2, gsize size);
-
-const GstMemoryImpl * gst_memory_register (const gchar *name, const GstMemoryInfo *info);
-
-#if 0
-const GstMemoryInfo * gst_memory_get_info (const gchar * impl);
-#endif
-
G_END_DECLS
#endif /* __GST_MEMORY_H__ */