Make GstAllocator a GstObject instead of a GstMiniObject, like bufferpool.
Make a new gstallocator.c file. Make a GstAllocator subclass for the default
allocator.
libgstreamer_@GST_API_VERSION@_la_SOURCES = \
gst.c \
gstobject.c \
+ gstallocator.c \
gstbin.c \
gstbuffer.c \
gstbufferlist.c \
gst.h \
glib-compat.h \
gstobject.h \
+ gstallocator.h \
gstbin.h \
gstbuffer.h \
gstbufferlist.h \
--- /dev/null
+/* GStreamer
+ * Copyright (C) 2011 Wim Taymans <wim.taymans@gmail.be>
+ *
+ * gstallocator.c: memory block allocator
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:gstallocator
+ * @short_description: allocate memory blocks
+ * @see_also: #GstMemory
+ *
+ * Memory is usually created by allocators with a gst_allocator_alloc()
+ * method call. When NULL is used as the allocator, the default allocator will
+ * be used.
+ *
+ * New allocators can be registered with gst_allocator_register().
+ * Allocators are identified by name and can be retrieved with
+ * gst_allocator_find(). gst_allocator_set_default() can be used to change the
+ * default allocator.
+ *
+ * New memory can be created with gst_memory_new_wrapped() that wraps the memory
+ * allocated elsewhere.
+ *
+ * Last reviewed on 2012-07-09 (0.11.3)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gst_private.h"
+#include "gstmemory.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_allocator_debug);
+#define GST_CAT_DEFAULT gst_allocator_debug
+
+#define GST_ALLOCATOR_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_ALLOCATOR, GstAllocatorPrivate))
+
+struct _GstAllocatorPrivate
+{
+ gpointer dummy;
+};
+
+#if defined(MEMORY_ALIGNMENT_MALLOC)
+size_t gst_memory_alignment = 7;
+#elif defined(MEMORY_ALIGNMENT_PAGESIZE)
+/* we fill this in in the _init method */
+size_t gst_memory_alignment = 0;
+#elif defined(MEMORY_ALIGNMENT)
+size_t gst_memory_alignment = MEMORY_ALIGNMENT - 1;
+#else
+#error "No memory alignment configured"
+size_t gst_memory_alignment = 0;
+#endif
+
+/* the default allocator */
+static GstAllocator *_default_allocator;
+
+static GstAllocator *_sysmem_allocator;
+
+/* registered allocators */
+static GRWLock lock;
+static GHashTable *allocators;
+
+G_DEFINE_ABSTRACT_TYPE (GstAllocator, gst_allocator, GST_TYPE_OBJECT);
+
+static void
+gst_allocator_class_init (GstAllocatorClass * klass)
+{
+ g_type_class_add_private (klass, sizeof (GstAllocatorPrivate));
+
+ GST_DEBUG_CATEGORY_INIT (gst_allocator_debug, "allocator", 0,
+ "allocator debug");
+}
+
+static GstMemory *
+_fallback_mem_copy (GstMemory * mem, gssize offset, gssize size)
+{
+ GstMemory *copy;
+ GstMapInfo sinfo, dinfo;
+ GstAllocationParams params = { 0, 0, 0, mem->align, };
+
+ if (!gst_memory_map (mem, &sinfo, GST_MAP_READ))
+ return NULL;
+
+ if (size == -1)
+ size = sinfo.size > offset ? sinfo.size - offset : 0;
+
+ /* use the same allocator as the memory we copy */
+ copy = gst_allocator_alloc (mem->allocator, size, ¶ms);
+ if (!gst_memory_map (copy, &dinfo, GST_MAP_WRITE)) {
+ GST_CAT_WARNING (GST_CAT_MEMORY, "could not write map memory %p", copy);
+ gst_memory_unmap (mem, &sinfo);
+ return NULL;
+ }
+
+ GST_CAT_DEBUG (GST_CAT_PERFORMANCE,
+ "memcpy %" G_GSSIZE_FORMAT " memory %p -> %p", size, mem, copy);
+ memcpy (dinfo.data, sinfo.data + offset, size);
+ gst_memory_unmap (copy, &dinfo);
+ gst_memory_unmap (mem, &sinfo);
+
+ return copy;
+}
+
+static gboolean
+_fallback_mem_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset)
+{
+ return FALSE;
+}
+
+static void
+gst_allocator_init (GstAllocator * allocator)
+{
+ allocator->priv = GST_ALLOCATOR_GET_PRIVATE (allocator);
+
+ allocator->mem_copy = _fallback_mem_copy;
+ allocator->mem_is_span = _fallback_mem_is_span;
+}
+
+G_DEFINE_BOXED_TYPE (GstAllocationParams, gst_allocation_params,
+ (GBoxedCopyFunc) gst_allocation_params_copy,
+ (GBoxedFreeFunc) gst_allocation_params_free);
+
+/**
+ * gst_allocation_params_init:
+ * @params: a #GstAllocationParams
+ *
+ * Initialize @params to its default values
+ */
+void
+gst_allocation_params_init (GstAllocationParams * params)
+{
+ g_return_if_fail (params != NULL);
+
+ memset (params, 0, sizeof (GstAllocationParams));
+}
+
+/**
+ * gst_allocation_params_copy:
+ * @params: (transfer none): a #GstAllocationParams
+ *
+ * Create a copy of @params.
+ *
+ * Free-function: gst_allocation_params_free
+ *
+ * Returns: (transfer full): a new ##GstAllocationParams, free with
+ * gst_allocation_params_free().
+ */
+GstAllocationParams *
+gst_allocation_params_copy (const GstAllocationParams * params)
+{
+ GstAllocationParams *result = NULL;
+
+ if (params) {
+ result =
+ (GstAllocationParams *) g_slice_copy (sizeof (GstAllocationParams),
+ params);
+ }
+ return result;
+}
+
+/**
+ * gst_allocation_params_free:
+ * @params: (in) (transfer full): a #GstAllocationParams
+ *
+ * Free @params
+ */
+void
+gst_allocation_params_free (GstAllocationParams * params)
+{
+ g_slice_free (GstAllocationParams, params);
+}
+
+/**
+ * gst_allocator_register:
+ * @name: the name of the allocator
+ * @allocator: (transfer full): #GstAllocator
+ *
+ * Registers the memory @allocator with @name. This function takes ownership of
+ * @allocator.
+ */
+void
+gst_allocator_register (const gchar * name, GstAllocator * allocator)
+{
+ g_return_if_fail (name != NULL);
+ g_return_if_fail (allocator != NULL);
+
+ GST_CAT_DEBUG (GST_CAT_MEMORY, "registering allocator %p with name \"%s\"",
+ allocator, name);
+
+ g_rw_lock_writer_lock (&lock);
+ g_hash_table_insert (allocators, (gpointer) name, (gpointer) allocator);
+ g_rw_lock_writer_unlock (&lock);
+}
+
+/**
+ * gst_allocator_find:
+ * @name: the name of the allocator
+ *
+ * Find a previously registered allocator with @name. When @name is NULL, the
+ * default allocator will be returned.
+ *
+ * Returns: (transfer full): a #GstAllocator or NULL when the allocator with @name was not
+ * registered. Use gst_object_unref() to release the allocator after usage.
+ */
+GstAllocator *
+gst_allocator_find (const gchar * name)
+{
+ GstAllocator *allocator;
+
+ g_rw_lock_reader_lock (&lock);
+ if (name) {
+ allocator = g_hash_table_lookup (allocators, (gconstpointer) name);
+ } else {
+ allocator = _default_allocator;
+ }
+ if (allocator)
+ gst_object_ref (allocator);
+ g_rw_lock_reader_unlock (&lock);
+
+ return allocator;
+}
+
+/**
+ * gst_allocator_set_default:
+ * @allocator: (transfer full): a #GstAllocator
+ *
+ * Set the default allocator. This function takes ownership of @allocator.
+ */
+void
+gst_allocator_set_default (GstAllocator * allocator)
+{
+ GstAllocator *old;
+
+ g_return_if_fail (GST_IS_ALLOCATOR (allocator));
+
+ g_rw_lock_writer_lock (&lock);
+ old = _default_allocator;
+ _default_allocator = allocator;
+ g_rw_lock_writer_unlock (&lock);
+
+ if (old)
+ gst_object_unref (old);
+}
+
+/**
+ * gst_allocator_alloc:
+ * @allocator: (transfer none) (allow-none): a #GstAllocator to use
+ * @size: size of the visible memory area
+ * @params: (transfer none) (allow-none): optional parameters
+ *
+ * Use @allocator to allocate a new memory block with memory that is at least
+ * @size big.
+ *
+ * The optional @params can specify the prefix and padding for the memory. If
+ * NULL is passed, no flags, no extra prefix/padding and a default alignment is
+ * used.
+ *
+ * The prefix/padding will be filled with 0 if flags contains
+ * #GST_MEMORY_FLAG_ZERO_PREFIXED and #GST_MEMORY_FLAG_ZERO_PADDED respectively.
+ *
+ * When @allocator is NULL, the default allocator will be used.
+ *
+ * The alignment in @params 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: (transfer full): a new #GstMemory.
+ */
+GstMemory *
+gst_allocator_alloc (GstAllocator * allocator, gsize size,
+ GstAllocationParams * params)
+{
+ GstMemory *mem;
+ static GstAllocationParams defparams = { 0, 0, 0, 0, };
+ GstAllocatorClass *aclass;
+
+ if (params) {
+ g_return_val_if_fail (((params->align + 1) & params->align) == 0, NULL);
+ } else {
+ params = &defparams;
+ }
+
+ if (allocator == NULL)
+ allocator = _default_allocator;
+
+ aclass = GST_ALLOCATOR_GET_CLASS (allocator);
+ if (aclass->alloc)
+ mem = aclass->alloc (allocator, size, params, NULL);
+ else
+ mem = NULL;
+
+ return mem;
+}
+
+/**
+ * gst_allocator_free:
+ * @allocator: (transfer none): a #GstAllocator to use
+ * @memory: (transfer full): the memory to free
+ *
+ * Free @memory that was previously allocated with gst_allocator_alloc().
+ */
+void
+gst_allocator_free (GstAllocator * allocator, GstMemory * memory)
+{
+ GstAllocatorClass *aclass;
+
+ g_return_if_fail (GST_IS_ALLOCATOR (allocator));
+ g_return_if_fail (memory != NULL);
+ g_return_if_fail (memory->allocator == allocator);
+
+ aclass = GST_ALLOCATOR_GET_CLASS (allocator);
+ if (aclass->free)
+ aclass->free (allocator, memory);
+}
+
+/* default memory implementation */
+typedef struct
+{
+ GstMemory mem;
+
+ gsize slice_size;
+ guint8 *data;
+
+ gpointer user_data;
+ GDestroyNotify notify;
+} GstMemoryDefault;
+
+typedef struct
+{
+ GstAllocator parent;
+} GstDefaultAllocator;
+
+typedef struct
+{
+ GstAllocatorClass parent_class;
+} GstDefaultAllocatorClass;
+
+GType gst_default_allocator_get_type (void);
+G_DEFINE_TYPE (GstDefaultAllocator, gst_default_allocator, GST_TYPE_ALLOCATOR);
+
+/* initialize the fields */
+static inline void
+_default_mem_init (GstMemoryDefault * mem, GstMemoryFlags flags,
+ GstMemory * parent, gsize slice_size,
+ gpointer data, gsize maxsize, gsize align, gsize offset, gsize size,
+ gpointer user_data, GDestroyNotify notify)
+{
+ gst_memory_init (GST_MEMORY_CAST (mem),
+ flags, _sysmem_allocator, parent, maxsize, align, offset, size);
+
+ mem->slice_size = slice_size;
+ mem->data = data;
+ mem->user_data = user_data;
+ mem->notify = notify;
+}
+
+/* create a new memory block that manages the given memory */
+static inline GstMemoryDefault *
+_default_mem_new (GstMemoryFlags flags,
+ GstMemory * parent, gpointer data, gsize maxsize, gsize align, gsize offset,
+ gsize size, gpointer user_data, GDestroyNotify notify)
+{
+ GstMemoryDefault *mem;
+ gsize slice_size;
+
+ slice_size = sizeof (GstMemoryDefault);
+
+ mem = g_slice_alloc (slice_size);
+ _default_mem_init (mem, flags, parent, slice_size,
+ data, maxsize, align, offset, size, user_data, notify);
+
+ return mem;
+}
+
+/* allocate the memory and structure in one block */
+static GstMemoryDefault *
+_default_mem_new_block (GstMemoryFlags flags,
+ gsize maxsize, gsize align, gsize offset, gsize size)
+{
+ GstMemoryDefault *mem;
+ gsize aoffset, slice_size, padding;
+ guint8 *data;
+
+ /* ensure configured alignment */
+ align |= gst_memory_alignment;
+ /* allocate more to compensate for alignment */
+ maxsize += align;
+ /* alloc header and data in one block */
+ slice_size = sizeof (GstMemoryDefault) + maxsize;
+
+ mem = g_slice_alloc (slice_size);
+ if (mem == NULL)
+ return NULL;
+
+ data = (guint8 *) mem + sizeof (GstMemoryDefault);
+
+ /* do alignment */
+ if ((aoffset = ((guintptr) data & align))) {
+ aoffset = (align + 1) - aoffset;
+ data += aoffset;
+ maxsize -= aoffset;
+ }
+
+ if (offset && (flags & GST_MEMORY_FLAG_ZERO_PREFIXED))
+ memset (data, 0, offset);
+
+ padding = maxsize - (offset + size);
+ if (padding && (flags & GST_MEMORY_FLAG_ZERO_PADDED))
+ memset (data + offset + size, 0, padding);
+
+ _default_mem_init (mem, flags, NULL, slice_size, data, maxsize,
+ align, offset, size, NULL, NULL);
+
+ return mem;
+}
+
+static gpointer
+_default_mem_map (GstMemoryDefault * mem, gsize maxsize, GstMapFlags flags)
+{
+ return mem->data;
+}
+
+static gboolean
+_default_mem_unmap (GstMemoryDefault * mem)
+{
+ return TRUE;
+}
+
+static GstMemoryDefault *
+_default_mem_copy (GstMemoryDefault * mem, gssize offset, gsize size)
+{
+ GstMemoryDefault *copy;
+
+ if (size == -1)
+ size = mem->mem.size > offset ? mem->mem.size - offset : 0;
+
+ copy =
+ _default_mem_new_block (0, mem->mem.maxsize, 0, mem->mem.offset + offset,
+ size);
+ GST_CAT_DEBUG (GST_CAT_PERFORMANCE,
+ "memcpy %" G_GSIZE_FORMAT " memory %p -> %p", mem->mem.maxsize, mem,
+ copy);
+ memcpy (copy->data, mem->data, mem->mem.maxsize);
+
+ return copy;
+}
+
+static GstMemoryDefault *
+_default_mem_share (GstMemoryDefault * mem, gssize offset, gsize size)
+{
+ GstMemoryDefault *sub;
+ GstMemory *parent;
+
+ /* find the real parent */
+ if ((parent = mem->mem.parent) == NULL)
+ parent = (GstMemory *) mem;
+
+ if (size == -1)
+ size = mem->mem.size - offset;
+
+ /* the shared memory is always readonly */
+ sub =
+ _default_mem_new (GST_MINI_OBJECT_FLAGS (parent) |
+ GST_MINI_OBJECT_FLAG_LOCK_READONLY, parent, mem->data, mem->mem.maxsize,
+ mem->mem.align, mem->mem.offset + offset, size, NULL, NULL);
+
+ return sub;
+}
+
+static gboolean
+_default_mem_is_span (GstMemoryDefault * mem1, GstMemoryDefault * mem2,
+ gsize * offset)
+{
+
+ if (offset) {
+ GstMemoryDefault *parent;
+
+ parent = (GstMemoryDefault *) mem1->mem.parent;
+
+ *offset = mem1->mem.offset - parent->mem.offset;
+ }
+
+ /* and memory is contiguous */
+ return mem1->data + mem1->mem.offset + mem1->mem.size ==
+ mem2->data + mem2->mem.offset;
+}
+
+static GstMemory *
+default_alloc (GstAllocator * allocator, gsize size,
+ GstAllocationParams * params, gpointer user_data)
+{
+ gsize maxsize = size + params->prefix + params->padding;
+
+ return (GstMemory *) _default_mem_new_block (params->flags,
+ maxsize, params->align, params->prefix, size);
+}
+
+static void
+default_free (GstAllocator * allocator, GstMemory * mem)
+{
+ GstMemoryDefault *dmem = (GstMemoryDefault *) mem;
+
+ if (dmem->notify)
+ dmem->notify (dmem->user_data);
+
+ g_slice_free1 (dmem->slice_size, mem);
+}
+
+static void
+gst_default_allocator_finalize (GObject * obj)
+{
+ g_warning ("The default memory allocator was freed!");
+}
+
+static void
+gst_default_allocator_class_init (GstDefaultAllocatorClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstAllocatorClass *allocator_class;
+
+ gobject_class = (GObjectClass *) klass;
+ allocator_class = (GstAllocatorClass *) klass;
+
+ gobject_class->finalize = gst_default_allocator_finalize;
+
+ allocator_class->alloc = default_alloc;
+ allocator_class->free = default_free;
+}
+
+static void
+gst_default_allocator_init (GstDefaultAllocator * allocator)
+{
+ GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
+
+ GST_CAT_DEBUG (GST_CAT_MEMORY, "init allocator %p", allocator);
+
+ alloc->mem_type = GST_ALLOCATOR_SYSMEM;
+ alloc->mem_map = (GstMemoryMapFunction) _default_mem_map;
+ alloc->mem_unmap = (GstMemoryUnmapFunction) _default_mem_unmap;
+ alloc->mem_copy = (GstMemoryCopyFunction) _default_mem_copy;
+ alloc->mem_share = (GstMemoryShareFunction) _default_mem_share;
+ alloc->mem_is_span = (GstMemoryIsSpanFunction) _default_mem_is_span;
+}
+
+void
+_priv_gst_memory_initialize (void)
+{
+ g_rw_lock_init (&lock);
+ allocators = g_hash_table_new (g_str_hash, g_str_equal);
+
+#ifdef HAVE_GETPAGESIZE
+#ifdef MEMORY_ALIGNMENT_PAGESIZE
+ gst_memory_alignment = getpagesize () - 1;
+#endif
+#endif
+
+ GST_CAT_DEBUG (GST_CAT_MEMORY, "memory alignment: %" G_GSIZE_FORMAT,
+ gst_memory_alignment);
+
+ _sysmem_allocator = g_object_new (gst_default_allocator_get_type (), NULL);
+
+ gst_allocator_register (GST_ALLOCATOR_SYSMEM,
+ gst_object_ref (_sysmem_allocator));
+
+ _default_allocator = gst_object_ref (_sysmem_allocator);
+}
+
+/**
+ * gst_memory_new_wrapped:
+ * @flags: #GstMemoryFlags
+ * @data: data to wrap
+ * @maxsize: allocated size of @data
+ * @offset: offset in @data
+ * @size: size of valid data
+ * @user_data: user_data
+ * @notify: called with @user_data when the memory is freed
+ *
+ * Allocate a new memory block that wraps the given @data.
+ *
+ * The prefix/padding must be filled with 0 if @flags contains
+ * #GST_MEMORY_FLAG_ZERO_PREFIXED and #GST_MEMORY_FLAG_ZERO_PADDED respectively.
+ *
+ * Returns: a new #GstMemory.
+ */
+GstMemory *
+gst_memory_new_wrapped (GstMemoryFlags flags, gpointer data,
+ gsize maxsize, gsize offset, gsize size, gpointer user_data,
+ GDestroyNotify notify)
+{
+ GstMemoryDefault *mem;
+
+ g_return_val_if_fail (data != NULL, NULL);
+ g_return_val_if_fail (offset + size <= maxsize, NULL);
+
+ mem =
+ _default_mem_new (flags, NULL, data, maxsize, 0, offset, size, user_data,
+ notify);
+
+ return (GstMemory *) mem;
+}
--- /dev/null
+/* GStreamer
+ * Copyright (C) 2009 Wim Taymans <wim.taymans@gmail.be>
+ *
+ * gstallocator.h: Header for memory allocation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __GST_ALLOCATOR_H__
+#define __GST_ALLOCATOR_H__
+
+#include <gst/gstmemory.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GstAllocatorPrivate GstAllocatorPrivate;
+typedef struct _GstAllocatorClass GstAllocatorClass;
+
+#define GST_TYPE_ALLOCATOR (gst_allocator_get_type())
+#define GST_IS_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_ALLOCATOR))
+#define GST_IS_ALLOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_ALLOCATOR))
+#define GST_ALLOCATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_ALLOCATOR, GstAllocatorClass))
+#define GST_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_ALLOCATOR, GstAllocator))
+#define GST_ALLOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_ALLOCATOR, GstAllocatorClass))
+#define GST_ALLOCATOR_CAST(obj) ((GstAllocator *)(obj))
+
+#define GST_TYPE_ALLOCATION_PARAMS (gst_allocation_params_get_type())
+GType gst_allocation_params_get_type(void);
+
+typedef struct _GstAllocationParams GstAllocationParams;
+
+/**
+ * gst_memory_alignment:
+ *
+ * The default memory alignment in bytes - 1
+ * an alignment of 7 would be the same as what malloc() guarantees.
+ */
+GST_EXPORT gsize gst_memory_alignment;
+
+/**
+ * GST_ALLOCATOR_SYSMEM:
+ *
+ * The allocator name for the default system memory allocator
+ */
+#define GST_ALLOCATOR_SYSMEM "SystemMemory"
+
+/**
+ * GstAllocationParams:
+ * @flags: flags to control allocation
+ * @align: the desired alignment of the memory
+ * @prefix: the desired prefix
+ * @padding: the desired padding
+ *
+ * Parameters to control the allocation of memory
+ */
+struct _GstAllocationParams {
+ GstMemoryFlags flags;
+ gsize align;
+ gsize prefix;
+ gsize padding;
+
+ /*< private >*/
+ gpointer _gst_reserved[GST_PADDING];
+};
+
+#if 0
+/**
+ * GstAllocatorAllocFunction:
+ * @allocator: a #GstAllocator
+ * @size: the size
+ * @params: allocator params
+ * @user_data: user data
+ *
+ * Allocate a new #GstMemory from @allocator that can hold at least @size
+ * bytes (+ padding) and is aligned to (@align + 1) bytes.
+ *
+ * The offset and size of the memory should be set and the prefix/padding must
+ * be filled with 0 if @params flags contains #GST_MEMORY_FLAG_ZERO_PREFIXED and
+ * #GST_MEMORY_FLAG_ZERO_PADDED respectively.
+ *
+ * @user_data is extra data passed to this function. The default
+ * gst_allocator_alloc() passes the NULL but other implementations could pass
+ * custom data.
+ *
+ * Returns: a newly allocated #GstMemory. Free with gst_memory_unref()
+ */
+typedef GstMemory * (*GstAllocatorAllocFunction) (GstAllocator *allocator,
+ gsize size, GstAllocationParams *params,
+ gpointer user_data);
+#endif
+
+/**
+ * GstAllocatorFlags:
+ * @GST_ALLOCATOR_CUSTOM_ALLOC: The allocator has a custom alloc function.
+ * @GST_ALLOCATOR_FLAG_LAST: first flag that can be used for custom purposes
+ *
+ * Flags for allocators.
+ */
+typedef enum {
+ GST_ALLOCATOR_FLAG_CUSTOM_ALLOC = (GST_OBJECT_FLAG_LAST << 0),
+
+ GST_ALLOCATOR_FLAG_LAST = (GST_OBJECT_FLAG_LAST << 16)
+} GstAllocatorFlags;
+
+/**
+ * GstAllocator:
+ * @mini_object: parent structure
+ * @mem_type: the memory type this allocator provides
+ * @mem_map: the implementation of the GstMemoryMapFunction
+ * @mem_unmap: the implementation of the GstMemoryUnmapFunction
+ * @mem_free: the implementation of the GstMemoryFreeFunction
+ * @mem_copy: the implementation of the GstMemoryCopyFunction
+ * @mem_share: the implementation of the GstMemoryShareFunction
+ * @mem_is_span: the implementation of the GstMemoryIsSpanFunction
+ *
+ * The #GstAllocator is used to create new memory.
+ */
+struct _GstAllocator
+{
+ GstObject object;
+
+ const gchar *mem_type;
+
+ GstMemoryMapFunction mem_map;
+ GstMemoryUnmapFunction mem_unmap;
+
+ GstMemoryCopyFunction mem_copy;
+ GstMemoryShareFunction mem_share;
+ GstMemoryIsSpanFunction mem_is_span;
+
+ gpointer _gst_reserved[GST_PADDING];
+
+ /*< private >*/
+ GstAllocatorPrivate *priv;
+};
+
+struct _GstAllocatorClass {
+ GstObjectClass object_class;
+
+ GstMemory * (*alloc) (GstAllocator *allocator, gsize size,
+ GstAllocationParams *params, gpointer user_data);
+ void (*free) (GstAllocator *allocator, GstMemory *memory);
+
+ /*< private >*/
+ gpointer _gst_reserved[GST_PADDING];
+};
+
+GType gst_allocator_get_type(void);
+
+/* allocators */
+void gst_allocator_register (const gchar *name, GstAllocator *allocator);
+GstAllocator * gst_allocator_find (const gchar *name);
+void gst_allocator_set_default (GstAllocator * allocator);
+
+/* allocation parameters */
+void gst_allocation_params_init (GstAllocationParams *params);
+GstAllocationParams *
+ gst_allocation_params_copy (const GstAllocationParams *params) G_GNUC_MALLOC;
+void gst_allocation_params_free (GstAllocationParams *params);
+
+/* allocating memory blocks */
+GstMemory * gst_allocator_alloc (GstAllocator * allocator, gsize size,
+ GstAllocationParams *params);
+void gst_allocator_free (GstAllocator * allocator, GstMemory *mem);
+
+GstMemory * gst_memory_new_wrapped (GstMemoryFlags flags, gpointer data, gsize maxsize,
+ gsize offset, gsize size, gpointer user_data,
+ GDestroyNotify notify);
+
+G_END_DECLS
+
+#endif /* __GST_ALLOCATOR_H__ */
#include <gst/gstminiobject.h>
#include <gst/gstclock.h>
-#include <gst/gstmemory.h>
+#include <gst/gstallocator.h>
G_BEGIN_DECLS
gst_structure_free (priv->config);
g_rec_mutex_clear (&priv->rec_lock);
if (priv->allocator)
- gst_allocator_unref (priv->allocator);
+ gst_object_unref (priv->allocator);
G_OBJECT_CLASS (gst_buffer_pool_parent_class)->finalize (object);
}
priv->max_buffers = max_buffers;
if (priv->allocator)
- gst_allocator_unref (priv->allocator);
+ gst_object_unref (priv->allocator);
if ((priv->allocator = allocator))
- gst_allocator_ref (allocator);
+ gst_object_ref (allocator);
priv->params = params;
return TRUE;
g_return_val_if_fail (config != NULL, FALSE);
if (allocator)
- *allocator = g_value_get_boxed (gst_structure_id_get_value (config,
+ *allocator = g_value_get_object (gst_structure_id_get_value (config,
GST_QUARK (ALLOCATOR)));
if (params) {
GstAllocationParams *p;
GST_DEFINE_MINI_OBJECT_TYPE (GstMemory, gst_memory);
-GST_DEFINE_MINI_OBJECT_TYPE (GstAllocator, gst_allocator);
-
-G_DEFINE_BOXED_TYPE (GstAllocationParams, gst_allocation_params,
- (GBoxedCopyFunc) gst_allocation_params_copy,
- (GBoxedFreeFunc) gst_allocation_params_free);
-
-#if defined(MEMORY_ALIGNMENT_MALLOC)
-size_t gst_memory_alignment = 7;
-#elif defined(MEMORY_ALIGNMENT_PAGESIZE)
-/* we fill this in in the _init method */
-size_t gst_memory_alignment = 0;
-#elif defined(MEMORY_ALIGNMENT)
-size_t gst_memory_alignment = MEMORY_ALIGNMENT - 1;
-#else
-#error "No memory alignment configured"
-size_t gst_memory_alignment = 0;
-#endif
-
-/* default memory implementation */
-typedef struct
-{
- GstMemory mem;
- gsize slice_size;
- guint8 *data;
- gpointer user_data;
- GDestroyNotify notify;
-} GstMemoryDefault;
-
-/* the default allocator */
-static GstAllocator *_default_allocator;
-
-/* our predefined allocators */
-static GstAllocator *_default_mem_impl;
-
static GstMemory *
_gst_memory_copy (GstMemory * mem)
{
gst_memory_unref (mem->parent);
}
- mem->allocator->info.mem_free (mem);
+ gst_allocator_free (mem->allocator, mem);
}
/**
offset, size);
}
-/* initialize the fields */
-static inline void
-_default_mem_init (GstMemoryDefault * mem, GstMemoryFlags flags,
- GstMemory * parent, gsize slice_size, gpointer data,
- gsize maxsize, gsize align, gsize offset, gsize size,
- gpointer user_data, GDestroyNotify notify)
-{
- gst_memory_init (GST_MEMORY_CAST (mem),
- flags, _default_mem_impl, parent, maxsize, align, offset, size);
-
- mem->slice_size = slice_size;
- mem->data = data;
- mem->user_data = user_data;
- mem->notify = notify;
-}
-
-/* create a new memory block that manages the given memory */
-static inline GstMemoryDefault *
-_default_mem_new (GstMemoryFlags flags, GstMemory * parent, gpointer data,
- gsize maxsize, gsize align, gsize offset, gsize size, gpointer user_data,
- GDestroyNotify notify)
-{
- GstMemoryDefault *mem;
- gsize slice_size;
-
- slice_size = sizeof (GstMemoryDefault);
-
- mem = g_slice_alloc (slice_size);
- _default_mem_init (mem, flags, parent, slice_size,
- data, maxsize, align, offset, size, user_data, notify);
-
- return mem;
-}
-
-/* allocate the memory and structure in one block */
-static GstMemoryDefault *
-_default_mem_new_block (GstMemoryFlags flags, gsize maxsize, gsize align,
- gsize offset, gsize size)
-{
- GstMemoryDefault *mem;
- gsize aoffset, slice_size, padding;
- guint8 *data;
-
- /* ensure configured alignment */
- align |= gst_memory_alignment;
- /* allocate more to compensate for alignment */
- maxsize += align;
- /* alloc header and data in one block */
- slice_size = sizeof (GstMemoryDefault) + maxsize;
-
- mem = g_slice_alloc (slice_size);
- if (mem == NULL)
- return NULL;
-
- data = (guint8 *) mem + sizeof (GstMemoryDefault);
-
- /* do alignment */
- if ((aoffset = ((guintptr) data & align))) {
- aoffset = (align + 1) - aoffset;
- data += aoffset;
- maxsize -= aoffset;
- }
-
- if (offset && (flags & GST_MEMORY_FLAG_ZERO_PREFIXED))
- memset (data, 0, offset);
-
- padding = maxsize - (offset + size);
- if (padding && (flags & GST_MEMORY_FLAG_ZERO_PADDED))
- memset (data + offset + size, 0, padding);
-
- _default_mem_init (mem, flags, NULL, slice_size, data, maxsize,
- align, offset, size, NULL, NULL);
-
- return mem;
-}
-
-static GstMemory *
-_default_alloc_alloc (GstAllocator * allocator, gsize size,
- GstAllocationParams * params, gpointer user_data)
-{
- gsize maxsize = size + params->prefix + params->padding;
-
- return (GstMemory *) _default_mem_new_block (params->flags,
- maxsize, params->align, params->prefix, size);
-}
-
-static gpointer
-_default_mem_map (GstMemoryDefault * mem, gsize maxsize, GstMapFlags flags)
-{
- return mem->data;
-}
-
-static gboolean
-_default_mem_unmap (GstMemoryDefault * mem)
-{
- return TRUE;
-}
-
-static void
-_default_mem_free (GstMemoryDefault * mem)
-{
- if (mem->notify)
- mem->notify (mem->user_data);
-
- g_slice_free1 (mem->slice_size, mem);
-}
-
-static GstMemoryDefault *
-_default_mem_copy (GstMemoryDefault * mem, gssize offset, gsize size)
-{
- GstMemoryDefault *copy;
-
- if (size == -1)
- size = mem->mem.size > offset ? mem->mem.size - offset : 0;
-
- copy =
- _default_mem_new_block (0, mem->mem.maxsize, 0, mem->mem.offset + offset,
- size);
- GST_CAT_DEBUG (GST_CAT_PERFORMANCE,
- "memcpy %" G_GSIZE_FORMAT " memory %p -> %p", mem->mem.maxsize, mem,
- copy);
- memcpy (copy->data, mem->data, mem->mem.maxsize);
-
- return copy;
-}
-
-static GstMemoryDefault *
-_default_mem_share (GstMemoryDefault * mem, gssize offset, gsize size)
-{
- GstMemoryDefault *sub;
- GstMemory *parent;
-
- /* find the real parent */
- if ((parent = mem->mem.parent) == NULL)
- parent = (GstMemory *) mem;
-
- if (size == -1)
- size = mem->mem.size - offset;
-
- /* the shared memory is always readonly */
- sub =
- _default_mem_new (GST_MINI_OBJECT_FLAGS (parent) |
- GST_MINI_OBJECT_FLAG_LOCK_READONLY, parent, mem->data, mem->mem.maxsize,
- mem->mem.align, mem->mem.offset + offset, size, NULL, NULL);
-
- return sub;
-}
-
-static gboolean
-_default_mem_is_span (GstMemoryDefault * mem1, GstMemoryDefault * mem2,
- gsize * offset)
-{
-
- if (offset) {
- GstMemoryDefault *parent;
-
- parent = (GstMemoryDefault *) mem1->mem.parent;
-
- *offset = mem1->mem.offset - parent->mem.offset;
- }
-
- /* and memory is contiguous */
- return mem1->data + mem1->mem.offset + mem1->mem.size ==
- mem2->data + mem2->mem.offset;
-}
-
-static GstMemory *
-_fallback_mem_copy (GstMemory * mem, gssize offset, gssize size)
-{
- GstMemory *copy;
- GstMapInfo sinfo, dinfo;
- GstAllocationParams params = { 0, 0, 0, mem->align, };
-
- if (!gst_memory_map (mem, &sinfo, GST_MAP_READ))
- return NULL;
-
- if (size == -1)
- size = sinfo.size > offset ? sinfo.size - offset : 0;
-
- /* use the same allocator as the memory we copy */
- copy = gst_allocator_alloc (mem->allocator, size, ¶ms);
- if (!gst_memory_map (copy, &dinfo, GST_MAP_WRITE)) {
- GST_CAT_WARNING (GST_CAT_MEMORY, "could not write map memory %p", copy);
- gst_memory_unmap (mem, &sinfo);
- return NULL;
- }
-
- GST_CAT_DEBUG (GST_CAT_PERFORMANCE,
- "memcpy %" G_GSSIZE_FORMAT " memory %p -> %p", size, mem, copy);
- memcpy (dinfo.data, sinfo.data + offset, size);
- gst_memory_unmap (copy, &dinfo);
- gst_memory_unmap (mem, &sinfo);
-
- return copy;
-}
-
-static gboolean
-_fallback_mem_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset)
-{
- return FALSE;
-}
-
-static GRWLock lock;
-static GHashTable *allocators;
-
-static void
-_priv_sysmem_free (GstMiniObject * obj)
-{
- g_warning ("The default memory allocator was freed!");
-}
-
-void
-_priv_gst_memory_initialize (void)
-{
- static const GstMemoryInfo _mem_info = {
- GST_ALLOCATOR_SYSMEM,
- (GstAllocatorAllocFunction) _default_alloc_alloc,
- (GstMemoryMapFunction) _default_mem_map,
- (GstMemoryUnmapFunction) _default_mem_unmap,
- (GstMemoryFreeFunction) _default_mem_free,
- (GstMemoryCopyFunction) _default_mem_copy,
- (GstMemoryShareFunction) _default_mem_share,
- (GstMemoryIsSpanFunction) _default_mem_is_span,
- };
-
- g_rw_lock_init (&lock);
- allocators = g_hash_table_new (g_str_hash, g_str_equal);
-
-#ifdef HAVE_GETPAGESIZE
-#ifdef MEMORY_ALIGNMENT_PAGESIZE
- gst_memory_alignment = getpagesize () - 1;
-#endif
-#endif
-
- GST_CAT_DEBUG (GST_CAT_MEMORY, "memory alignment: %" G_GSIZE_FORMAT,
- gst_memory_alignment);
-
- _default_mem_impl = g_slice_new (GstAllocator);
- gst_allocator_init (_default_mem_impl, 0, &_mem_info, _priv_sysmem_free);
-
- _default_allocator = gst_allocator_ref (_default_mem_impl);
- gst_allocator_register (GST_ALLOCATOR_SYSMEM,
- gst_allocator_ref (_default_mem_impl));
-}
-
-/**
- * gst_memory_new_wrapped:
- * @flags: #GstMemoryFlags
- * @data: data to wrap
- * @maxsize: allocated size of @data
- * @offset: offset in @data
- * @size: size of valid data
- * @user_data: user_data
- * @notify: called with @user_data when the memory is freed
- *
- * Allocate a new memory block that wraps the given @data.
- *
- * The prefix/padding must be filled with 0 if @flags contains
- * #GST_MEMORY_FLAG_ZERO_PREFIXED and #GST_MEMORY_FLAG_ZERO_PADDED respectively.
- *
- * Returns: a new #GstMemory.
- */
-GstMemory *
-gst_memory_new_wrapped (GstMemoryFlags flags, gpointer data,
- gsize maxsize, gsize offset, gsize size, gpointer user_data,
- GDestroyNotify notify)
-{
- GstMemoryDefault *mem;
-
- g_return_val_if_fail (data != NULL, NULL);
- g_return_val_if_fail (offset + size <= maxsize, NULL);
-
- mem =
- _default_mem_new (flags, NULL, data, maxsize, 0, offset, size, user_data,
- notify);
-
- return (GstMemory *) mem;
-}
-
/**
* gst_memory_get_sizes:
* @mem: a #GstMemory
if (!gst_memory_lock (mem, flags))
goto lock_failed;
- info->data = mem->allocator->info.mem_map (mem, mem->maxsize, flags);
+ info->data = mem->allocator->mem_map (mem, mem->maxsize, flags);
if (G_UNLIKELY (info->data == NULL))
goto error;
g_return_if_fail (info != NULL);
g_return_if_fail (info->memory == mem);
- mem->allocator->info.mem_unmap (mem);
+ mem->allocator->mem_unmap (mem);
gst_memory_unlock (mem, info->flags);
}
g_return_val_if_fail (mem != NULL, NULL);
- copy = mem->allocator->info.mem_copy (mem, offset, size);
+ copy = mem->allocator->mem_copy (mem, offset, size);
return copy;
}
g_return_val_if_fail (!GST_MEMORY_FLAG_IS_SET (mem, GST_MEMORY_FLAG_NO_SHARE),
NULL);
- shared = mem->allocator->info.mem_share (mem, offset, size);
+ shared = mem->allocator->mem_share (mem, offset, size);
return shared;
}
return FALSE;
/* and memory is contiguous */
- if (!mem1->allocator->info.mem_is_span (mem1, mem2, offset))
+ if (!mem1->allocator->mem_is_span (mem1, mem2, offset))
return FALSE;
return TRUE;
}
-
-static GstAllocator *
-_gst_allocator_copy (GstAllocator * allocator)
-{
- return gst_allocator_ref (allocator);
-}
-
-/**
- * gst_allocator_init:
- * @allocator: a #GstAllocator
- * @flags: #GstAllocatorFlags
- * @info: a #GstMemoryInfo
- * @free_func: a function to free @allocator
- *
- * Initialize a new memory allocator. The caller should have allocated the
- * memory to hold at least sizeof (GstAllocator) bytes.
- *
- * All functions in @info are mandatory exept the copy and is_span
- * functions, which will have a default implementation when left NULL.
- *
- * Returns: a new #GstAllocator.
- */
-void
-gst_allocator_init (GstAllocator * allocator, GstAllocatorFlags flags,
- const GstMemoryInfo * info, GstMiniObjectFreeFunction free_func)
-{
- g_return_if_fail (allocator != NULL);
- g_return_if_fail (info != NULL);
- g_return_if_fail (info->alloc != NULL);
- g_return_if_fail (info->mem_map != NULL);
- g_return_if_fail (info->mem_unmap != NULL);
- g_return_if_fail (info->mem_free != NULL);
- g_return_if_fail (info->mem_share != NULL);
-
- gst_mini_object_init (GST_MINI_OBJECT_CAST (allocator), flags,
- GST_TYPE_ALLOCATOR, (GstMiniObjectCopyFunction) _gst_allocator_copy, NULL,
- (GstMiniObjectFreeFunction) free_func);
-
- allocator->info = *info;
-
-#define INSTALL_FALLBACK(_t) \
- if (allocator->info._t == NULL) allocator->info._t = _fallback_ ##_t;
- INSTALL_FALLBACK (mem_copy);
- INSTALL_FALLBACK (mem_is_span);
-#undef INSTALL_FALLBACK
-
- GST_CAT_DEBUG (GST_CAT_MEMORY, "init allocator %p", allocator);
-}
-
-/**
- * gst_allocator_register:
- * @name: the name of the allocator
- * @allocator: (transfer full): #GstAllocator
- *
- * Registers the memory @allocator with @name. This function takes ownership of
- * @allocator.
- */
-void
-gst_allocator_register (const gchar * name, GstAllocator * allocator)
-{
- g_return_if_fail (name != NULL);
- g_return_if_fail (allocator != NULL);
-
- GST_CAT_DEBUG (GST_CAT_MEMORY, "registering allocator %p with name \"%s\"",
- allocator, name);
-
- g_rw_lock_writer_lock (&lock);
- g_hash_table_insert (allocators, (gpointer) name, (gpointer) allocator);
- g_rw_lock_writer_unlock (&lock);
-}
-
-/**
- * gst_allocator_find:
- * @name: the name of the allocator
- *
- * Find a previously registered allocator with @name. When @name is NULL, the
- * default allocator will be returned.
- *
- * Returns: (transfer full): a #GstAllocator or NULL when the allocator with @name was not
- * registered. Use gst_allocator_unref() to release the allocator after usage.
- */
-GstAllocator *
-gst_allocator_find (const gchar * name)
-{
- GstAllocator *allocator;
-
- g_rw_lock_reader_lock (&lock);
- if (name) {
- allocator = g_hash_table_lookup (allocators, (gconstpointer) name);
- } else {
- allocator = _default_allocator;
- }
- if (allocator)
- gst_allocator_ref (allocator);
- g_rw_lock_reader_unlock (&lock);
-
- return allocator;
-}
-
-/**
- * gst_allocator_set_default:
- * @allocator: (transfer full): a #GstAllocator
- *
- * Set the default allocator. This function takes ownership of @allocator.
- */
-void
-gst_allocator_set_default (GstAllocator * allocator)
-{
- GstAllocator *old;
- g_return_if_fail (allocator != NULL);
-
- g_rw_lock_writer_lock (&lock);
- old = _default_allocator;
- _default_allocator = allocator;
- g_rw_lock_writer_unlock (&lock);
-
- if (old)
- gst_allocator_unref (old);
-}
-
-/**
- * gst_allocation_params_init:
- * @params: a #GstAllocationParams
- *
- * Initialize @params to its default values
- */
-void
-gst_allocation_params_init (GstAllocationParams * params)
-{
- g_return_if_fail (params != NULL);
-
- memset (params, 0, sizeof (GstAllocationParams));
-}
-
-/**
- * gst_allocation_params_copy:
- * @params: (transfer none): a #GstAllocationParams
- *
- * Create a copy of @params.
- *
- * Free-function: gst_allocation_params_free
- *
- * Returns: (transfer full): a new ##GstAllocationParams, free with
- * gst_allocation_params_free().
- */
-GstAllocationParams *
-gst_allocation_params_copy (const GstAllocationParams * params)
-{
- GstAllocationParams *result = NULL;
-
- if (params) {
- result =
- (GstAllocationParams *) g_slice_copy (sizeof (GstAllocationParams),
- params);
- }
- return result;
-}
-
-/**
- * gst_allocation_params_free:
- * @params: (in) (transfer full): a #GstAllocationParams
- *
- * Free @params
- */
-void
-gst_allocation_params_free (GstAllocationParams * params)
-{
- g_slice_free (GstAllocationParams, params);
-}
-
-/**
- * gst_allocator_alloc:
- * @allocator: (transfer none) (allow-none): a #GstAllocator to use
- * @size: size of the visible memory area
- * @params: (transfer none) (allow-none): optional parameters
- *
- * Use @allocator to allocate a new memory block with memory that is at least
- * @size big.
- *
- * The optional @params can specify the prefix and padding for the memory. If
- * NULL is passed, no flags, no extra prefix/padding and a default alignment is
- * used.
- *
- * The prefix/padding will be filled with 0 if flags contains
- * #GST_MEMORY_FLAG_ZERO_PREFIXED and #GST_MEMORY_FLAG_ZERO_PADDED respectively.
- *
- * When @allocator is NULL, the default allocator will be used.
- *
- * The alignment in @params 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: (transfer full): a new #GstMemory.
- */
-GstMemory *
-gst_allocator_alloc (GstAllocator * allocator, gsize size,
- GstAllocationParams * params)
-{
- GstMemory *mem;
- static GstAllocationParams defparams = { 0, 0, 0, 0, };
-
- if (params) {
- g_return_val_if_fail (((params->align + 1) & params->align) == 0, NULL);
- } else {
- params = &defparams;
- }
-
- if (allocator == NULL)
- allocator = _default_allocator;
-
- mem = allocator->info.alloc (allocator, size, params, NULL);
-
- return mem;
-}
#define GST_TYPE_MEMORY (gst_memory_get_type())
GType gst_memory_get_type(void);
-#define GST_TYPE_ALLOCATOR (gst_allocator_get_type())
-GType gst_allocator_get_type(void);
-
-#define GST_TYPE_ALLOCATION_PARAMS (gst_allocation_params_get_type())
-GType gst_allocation_params_get_type(void);
-
typedef struct _GstMemory GstMemory;
-typedef struct _GstMemoryInfo GstMemoryInfo;
typedef struct _GstAllocator GstAllocator;
-typedef struct _GstAllocationParams GstAllocationParams;
-
-/**
- * gst_memory_alignment:
- *
- * The default memory alignment in bytes - 1
- * an alignment of 7 would be the same as what malloc() guarantees.
- */
-GST_EXPORT gsize gst_memory_alignment;
#define GST_MEMORY_CAST(mem) ((GstMemory *)(mem))
GST_MAP_FLAG_LAST = (1 << 16)
} GstMapFlags;
+
/**
* GST_MAP_READWRITE:
*
#define GST_MAP_INFO_INIT { NULL, 0, NULL, 0, 0, }
/**
- * GST_ALLOCATOR_SYSMEM:
- *
- * The allocator name for the default system memory allocator
- */
-#define GST_ALLOCATOR_SYSMEM "SystemMemory"
-
-/**
- * GstAllocationParams:
- * @flags: flags to control allocation
- * @align: the desired alignment of the memory
- * @prefix: the desired prefix
- * @padding: the desired padding
- *
- * Parameters to control the allocation of memory
- */
-struct _GstAllocationParams {
- GstMemoryFlags flags;
- gsize align;
- gsize prefix;
- gsize padding;
-
- /*< private >*/
- gpointer _gst_reserved[GST_PADDING];
-};
-
-/**
- * GstAllocatorAllocFunction:
- * @allocator: a #GstAllocator
- * @size: the size
- * @params: allocator params
- * @user_data: user data
- *
- * Allocate a new #GstMemory from @allocator that can hold at least @size
- * bytes (+ padding) and is aligned to (@align + 1) bytes.
- *
- * The offset and size of the memory should be set and the prefix/padding must
- * be filled with 0 if @params flags contains #GST_MEMORY_FLAG_ZERO_PREFIXED and
- * #GST_MEMORY_FLAG_ZERO_PADDED respectively.
- *
- * @user_data is extra data passed to this function. The default
- * gst_allocator_alloc() passes the NULL but other implementations could pass
- * custom data.
- *
- * Returns: a newly allocated #GstMemory. Free with gst_memory_unref()
- */
-typedef GstMemory * (*GstAllocatorAllocFunction) (GstAllocator *allocator,
- gsize size, GstAllocationParams *params,
- gpointer user_data);
-
-/**
* GstMemoryMapFunction:
* @mem: a #GstMemory
* @maxsize: size to map
typedef void (*GstMemoryUnmapFunction) (GstMemory *mem);
/**
- * GstMemoryFreeFunction:
- * @mem: a #GstMemory
- *
- * Free the memory used by @mem. This function is usually called when the
- * refcount of the @mem has reached 0.
- */
-typedef void (*GstMemoryFreeFunction) (GstMemory *mem);
-
-/**
* GstMemoryCopyFunction:
* @mem: a #GstMemory
* @offset: an offset
*/
typedef gboolean (*GstMemoryIsSpanFunction) (GstMemory *mem1, GstMemory *mem2, gsize *offset);
-/**
- * GstAllocatorFlags:
- * @GST_ALLOCATOR_CUSTOM_ALLOC: The allocator has a custom alloc function.
- * @GST_ALLOCATOR_FLAG_LAST: first flag that can be used for custom purposes
- *
- * Flags for allocators.
- */
-typedef enum {
- GST_ALLOCATOR_FLAG_CUSTOM_ALLOC = (GST_MINI_OBJECT_FLAG_LAST << 0),
-
- GST_ALLOCATOR_FLAG_LAST = (GST_MINI_OBJECT_FLAG_LAST << 16)
-} GstAllocatorFlags;
-
-
-/**
- * GstMemoryInfo:
- * @mem_type: the memory type this allocator provides
- * @alloc: the implementation of the GstAllocatorAllocFunction
- * @mem_map: the implementation of the GstMemoryMapFunction
- * @mem_unmap: the implementation of the GstMemoryUnmapFunction
- * @mem_free: the implementation of the GstMemoryFreeFunction
- * @mem_copy: the implementation of the GstMemoryCopyFunction
- * @mem_share: the implementation of the GstMemoryShareFunction
- * @mem_is_span: the implementation of the GstMemoryIsSpanFunction
- *
- * The #GstMemoryInfo is used to initialize new memory allocators and contain
- * the implementations for various memory operations.
- */
-struct _GstMemoryInfo {
- const gchar *mem_type;
-
- GstAllocatorAllocFunction alloc;
-
- GstMemoryMapFunction mem_map;
- GstMemoryUnmapFunction mem_unmap;
- GstMemoryFreeFunction mem_free;
-
- GstMemoryCopyFunction mem_copy;
- GstMemoryShareFunction mem_share;
- GstMemoryIsSpanFunction mem_is_span;
-
- /*< private >*/
- gpointer _gst_reserved[GST_PADDING];
-};
-
-/**
- * GstAllocator:
- * @mini_object: parent structure
- * @info: a #GstMemoryInfo with the implementation
- *
- * The #GstAllocator is used to create new memory and should be
- * initialized with gst_allocator_init().
- */
-struct _GstAllocator
-{
- GstMiniObject mini_object;
-
- GstMemoryInfo info;
-
- /*< private >*/
- gpointer _gst_reserved[GST_PADDING];
-};
-
-/* allocators */
-void gst_allocator_init (GstAllocator * allocator,
- GstAllocatorFlags flags,
- const GstMemoryInfo *info,
- GstMiniObjectFreeFunction free_func);
-
-/**
- * gst_allocator_ref:
- * @allocator: The allocator to refcount
- *
- * Increase the refcount of this allocator.
- *
- * Returns: (transfer full): @allocator (for convenience when doing assignments)
- */
-#ifdef _FOOL_GTK_DOC_
-G_INLINE_FUNC GstAllocator * gst_allocator_ref (GstAllocator * allocator);
-#endif
-
-static inline GstAllocator *
-gst_allocator_ref (GstAllocator * allocator)
-{
- return (GstAllocator *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (allocator));
-}
-
-/**
- * gst_allocator_unref:
- * @allocator: (transfer full): the allocator to refcount
- *
- * Decrease the refcount of an allocator, freeing it if the refcount reaches 0.
- */
-#ifdef _FOOL_GTK_DOC_
-G_INLINE_FUNC void gst_allocator_unref (GstAllocator * allocator);
-#endif
-
-static inline void
-gst_allocator_unref (GstAllocator * allocator)
-{
- gst_mini_object_unref (GST_MINI_OBJECT_CAST (allocator));
-}
-
-void gst_allocator_register (const gchar *name, GstAllocator *allocator);
-GstAllocator * gst_allocator_find (const gchar *name);
-
-void gst_allocator_set_default (GstAllocator * allocator);
-
-/* allocating memory blocks */
-void gst_allocation_params_init (GstAllocationParams *params);
-GstAllocationParams *
- gst_allocation_params_copy (const GstAllocationParams *params) G_GNUC_MALLOC;
-void gst_allocation_params_free (GstAllocationParams *params);
-
-GstMemory * gst_allocator_alloc (GstAllocator * allocator, gsize size,
- GstAllocationParams *params);
-
-GstMemory * gst_memory_new_wrapped (GstMemoryFlags flags, gpointer data, gsize maxsize,
- gsize offset, gsize size, gpointer user_data,
- GDestroyNotify notify);
-
void gst_memory_init (GstMemory *mem, GstMemoryFlags flags,
GstAllocator *allocator, GstMemory *parent,
gsize maxsize, gsize align,
gsize offset, gsize size);
-
/* refcounting */
/**
* gst_memory_ref:
allocation_param_free (AllocationParam * ap)
{
if (ap->allocator)
- gst_allocator_unref (ap->allocator);
+ gst_object_unref (ap->allocator);
}
/**
sizeof (AllocationParam), (GDestroyNotify) allocation_param_free);
if ((ap.allocator = allocator))
- gst_allocator_ref (allocator);
+ gst_object_ref (allocator);
if (params)
ap.params = *params;
else
if (allocator)
if ((*allocator = ap->allocator))
- gst_allocator_ref (*allocator);
+ gst_object_ref (*allocator);
if (params)
*params = ap->params;
}
allocation_param_free (old);
if ((ap.allocator = allocator))
- gst_allocator_ref (allocator);
+ gst_object_ref (allocator);
if (params)
ap.params = *params;
else
#include <gst/gststructure.h>
#include <gst/gstformat.h>
#include <gst/gstpad.h>
+#include <gst/gstallocator.h>
#include <gst/gsttoc.h>
G_BEGIN_DECLS
gst_object_unref (oldpool);
}
if (oldalloc) {
- gst_allocator_unref (oldalloc);
+ gst_object_unref (oldalloc);
}
return TRUE;
else
gst_query_add_allocation_param (query, allocator, ¶ms);
if (allocator)
- gst_allocator_unref (allocator);
+ gst_object_unref (allocator);
if (pool) {
gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max);
gst_object_unref (oldpool);
}
if (oldalloc) {
- gst_allocator_unref (oldalloc);
+ gst_object_unref (oldalloc);
}
if (oldquery) {
gst_query_unref (oldquery);
else
gst_query_add_allocation_param (query, allocator, ¶ms);
if (allocator)
- gst_allocator_unref (allocator);
+ gst_object_unref (allocator);
if (pool) {
gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max);
gst_memory_unmap (mem, &info);
gst_memory_unref (mem);
- gst_allocator_unref (alloc);
+ gst_object_unref (alloc);
/* allocator with custom alloc API */
my_vidmem_init ();
gst_memory_unmap (mem, &info);
gst_memory_unref (mem);
- gst_allocator_unref (alloc);
+ gst_object_unref (alloc);
return 0;
}
#include "my-memory.h"
-static GstAllocator *_my_allocator;
-
typedef struct
{
GstMemory mem;
static GstMemory *
-_my_alloc_alloc (GstAllocator * allocator, gsize size,
+_my_alloc (GstAllocator * allocator, gsize size,
GstAllocationParams * params, gpointer user_data)
{
MyMemory *mem;
return (GstMemory *) mem;
}
+static void
+_my_free (GstAllocator * allocator, GstMemory * mem)
+{
+ MyMemory *mmem = (MyMemory *) mem;
+
+ g_free (mmem->data);
+ g_slice_free (MyMemory, mmem);
+ GST_DEBUG ("%p: freed", mmem);
+}
+
static gpointer
_my_mem_map (MyMemory * mem, gsize maxsize, GstMapFlags flags)
{
return TRUE;
}
-static void
-_my_mem_free (MyMemory * mem)
-{
- g_free (mem->data);
- g_slice_free (MyMemory, mem);
- GST_DEBUG ("%p: freed", mem);
-}
-
static MyMemory *
_my_mem_share (MyMemory * mem, gssize offset, gsize size)
{
return sub;
}
+typedef struct
+{
+ GstAllocator parent;
+} MyMemoryAllocator;
+
+typedef struct
+{
+ GstAllocatorClass parent_class;
+} MyMemoryAllocatorClass;
+
+GType my_memory_allocator_get_type (void);
+G_DEFINE_TYPE (MyMemoryAllocator, my_memory_allocator, GST_TYPE_ALLOCATOR);
+
+static void
+my_memory_allocator_class_init (MyMemoryAllocatorClass * klass)
+{
+ GstAllocatorClass *allocator_class;
+
+ allocator_class = (GstAllocatorClass *) klass;
+
+ allocator_class->alloc = _my_alloc;
+ allocator_class->free = _my_free;
+}
+
static void
-free_allocator (GstMiniObject * obj)
+my_memory_allocator_init (MyMemoryAllocator * allocator)
{
- g_slice_free (GstAllocator, (GstAllocator *) obj);
+ GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
+
+ alloc->mem_type = "MyMemory";
+ alloc->mem_map = (GstMemoryMapFunction) _my_mem_map;
+ alloc->mem_unmap = (GstMemoryUnmapFunction) _my_mem_unmap;
+ alloc->mem_share = (GstMemoryShareFunction) _my_mem_share;
}
void
my_memory_init (void)
{
- static const GstMemoryInfo info = {
- "MyMemory",
- (GstAllocatorAllocFunction) _my_alloc_alloc,
- (GstMemoryMapFunction) _my_mem_map,
- (GstMemoryUnmapFunction) _my_mem_unmap,
- (GstMemoryFreeFunction) _my_mem_free,
- (GstMemoryCopyFunction) NULL,
- (GstMemoryShareFunction) _my_mem_share,
- (GstMemoryIsSpanFunction) NULL,
- };
-
- _my_allocator = g_slice_new (GstAllocator);
- gst_allocator_init (_my_allocator, 0, &info, free_allocator);
-
- gst_allocator_register ("MyMemory", gst_allocator_ref (_my_allocator));
+ GstAllocator *allocator;
+
+ allocator = g_object_new (my_memory_allocator_get_type (), NULL);
+
+ gst_allocator_register ("MyMemory", allocator);
}
#include <gst/gst.h>
+
/* example of an allocator that delays allocation of the memory
* until the memory is mapped */
void my_memory_init (void);
static GstMemory *
-_my_alloc_alloc (GstAllocator * allocator, gsize size,
+_my_alloc (GstAllocator * allocator, gsize size,
GstAllocationParams * params, gpointer user_data)
{
g_warning ("Use my_vidmem_alloc() to allocate from this allocator");
return NULL;
}
+static void
+_my_free (GstAllocator * allocator, GstMemory * mem)
+{
+ MyVidmem *vmem = (MyVidmem *) mem;
+
+ g_free (vmem->data);
+ g_slice_free (MyVidmem, vmem);
+ GST_DEBUG ("%p: freed", vmem);
+}
+
static gpointer
_my_vidmem_map (MyVidmem * mem, gsize maxsize, GstMapFlags flags)
{
return TRUE;
}
-static void
-_my_vidmem_free (MyVidmem * mem)
-{
- g_free (mem->data);
- g_slice_free (MyVidmem, mem);
- GST_DEBUG ("%p: freed", mem);
-}
-
static MyVidmem *
_my_vidmem_share (MyVidmem * mem, gssize offset, gsize size)
{
return sub;
}
+typedef struct
+{
+ GstAllocator parent;
+} MyVidmemAllocator;
+
+typedef struct
+{
+ GstAllocatorClass parent_class;
+} MyVidmemAllocatorClass;
+
+GType my_vidmem_allocator_get_type (void);
+G_DEFINE_TYPE (MyVidmemAllocator, my_vidmem_allocator, GST_TYPE_ALLOCATOR);
+
+static void
+my_vidmem_allocator_class_init (MyVidmemAllocatorClass * klass)
+{
+ GstAllocatorClass *allocator_class;
+
+ allocator_class = (GstAllocatorClass *) klass;
+
+ allocator_class->alloc = _my_alloc;
+ allocator_class->free = _my_free;
+}
+
static void
-free_allocator (GstMiniObject * obj)
+my_vidmem_allocator_init (MyVidmemAllocator * allocator)
{
- g_slice_free (GstAllocator, (GstAllocator *) obj);
+ GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
+
+ alloc->mem_type = "MyVidmem";
+ alloc->mem_map = (GstMemoryMapFunction) _my_vidmem_map;
+ alloc->mem_unmap = (GstMemoryUnmapFunction) _my_vidmem_unmap;
+ alloc->mem_share = (GstMemoryShareFunction) _my_vidmem_share;
}
void
my_vidmem_init (void)
{
- static const GstMemoryInfo info = {
- "MyVidmem",
- (GstAllocatorAllocFunction) _my_alloc_alloc,
- (GstMemoryMapFunction) _my_vidmem_map,
- (GstMemoryUnmapFunction) _my_vidmem_unmap,
- (GstMemoryFreeFunction) _my_vidmem_free,
- (GstMemoryCopyFunction) NULL,
- (GstMemoryShareFunction) _my_vidmem_share,
- (GstMemoryIsSpanFunction) NULL,
- };
-
- _my_allocator = g_slice_new (GstAllocator);
- gst_allocator_init (_my_allocator, 0, &info, free_allocator);
-
- gst_allocator_register ("MyVidmem", gst_allocator_ref (_my_allocator));
-}
+ _my_allocator = g_object_new (my_vidmem_allocator_get_type (), NULL);
+ gst_allocator_register ("MyVidmem", gst_object_ref (_my_allocator));
+}
GstMemory *
my_vidmem_alloc (guint format, guint width, guint height)