memory: Make GstAllocator a GstObject
authorWim Taymans <wim.taymans@collabora.co.uk>
Mon, 9 Jul 2012 14:02:50 +0000 (16:02 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Mon, 9 Jul 2012 14:28:22 +0000 (16:28 +0200)
Make GstAllocator a GstObject instead of a GstMiniObject, like bufferpool.
Make a new gstallocator.c file. Make a GstAllocator subclass for the default
allocator.

15 files changed:
gst/Makefile.am
gst/gstallocator.c [new file with mode: 0644]
gst/gstallocator.h [new file with mode: 0644]
gst/gstbuffer.h
gst/gstbufferpool.c
gst/gstmemory.c
gst/gstmemory.h
gst/gstquery.c
gst/gstquery.h
libs/gst/base/gstbasesrc.c
libs/gst/base/gstbasetransform.c
tests/examples/memory/memory_test.c
tests/examples/memory/my-memory.c
tests/examples/memory/my-memory.h
tests/examples/memory/my-vidmem.c

index 542f45d..b6bb664 100644 (file)
@@ -48,6 +48,7 @@ EXTRA_libgstreamer_@GST_API_VERSION@_la_SOURCES = \
 libgstreamer_@GST_API_VERSION@_la_SOURCES = \
        gst.c                   \
        gstobject.c             \
+       gstallocator.c          \
        gstbin.c                \
        gstbuffer.c             \
        gstbufferlist.c         \
@@ -142,6 +143,7 @@ gst_headers =                       \
        gst.h                   \
        glib-compat.h           \
        gstobject.h             \
+       gstallocator.h          \
        gstbin.h                \
        gstbuffer.h             \
        gstbufferlist.h         \
diff --git a/gst/gstallocator.c b/gst/gstallocator.c
new file mode 100644 (file)
index 0000000..7262675
--- /dev/null
@@ -0,0 +1,618 @@
+/* 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, &params);
+  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;
+}
diff --git a/gst/gstallocator.h b/gst/gstallocator.h
new file mode 100644 (file)
index 0000000..1ef471f
--- /dev/null
@@ -0,0 +1,186 @@
+/* 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__ */
index a890e3a..edeae38 100644 (file)
@@ -26,7 +26,7 @@
 
 #include <gst/gstminiobject.h>
 #include <gst/gstclock.h>
-#include <gst/gstmemory.h>
+#include <gst/gstallocator.h>
 
 G_BEGIN_DECLS
 
index 08461b0..2aebd29 100644 (file)
@@ -199,7 +199,7 @@ gst_buffer_pool_finalize (GObject * object)
   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);
 }
@@ -493,9 +493,9 @@ default_set_config (GstBufferPool * pool, GstStructure * config)
   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;
@@ -896,7 +896,7 @@ gst_buffer_pool_config_get_allocator (GstStructure * config,
   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;
index 60e5b90..5796e04 100644 (file)
 
 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)
 {
@@ -124,7 +90,7 @@ _gst_memory_free (GstMemory * mem)
     gst_memory_unref (mem->parent);
   }
 
-  mem->allocator->info.mem_free (mem);
+  gst_allocator_free (mem->allocator, mem);
 }
 
 /**
@@ -167,285 +133,6 @@ gst_memory_init (GstMemory * mem, GstMemoryFlags flags,
       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, &params);
-  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
@@ -580,7 +267,7 @@ gst_memory_map (GstMemory * mem, GstMapInfo * info, GstMapFlags flags)
   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;
@@ -622,7 +309,7 @@ gst_memory_unmap (GstMemory * mem, GstMapInfo * info)
   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);
 }
 
@@ -645,7 +332,7 @@ gst_memory_copy (GstMemory * mem, gssize offset, gssize size)
 
   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;
 }
@@ -672,7 +359,7 @@ gst_memory_share (GstMemory * mem, gssize offset, gssize size)
   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;
 }
@@ -707,222 +394,8 @@ gst_memory_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset)
     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;
-}
index fe093e3..e249cb4 100644 (file)
@@ -32,24 +32,8 @@ G_BEGIN_DECLS
 #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))
 
@@ -167,6 +151,7 @@ typedef enum {
 
   GST_MAP_FLAG_LAST = (1 << 16)
 } GstMapFlags;
+
 /**
  * GST_MAP_READWRITE:
  *
@@ -206,56 +191,6 @@ typedef struct {
 #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
@@ -281,15 +216,6 @@ typedef gpointer    (*GstMemoryMapFunction)       (GstMemory *mem, gsize maxsize
 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
@@ -331,132 +257,10 @@ typedef GstMemory * (*GstMemoryShareFunction)     (GstMemory *mem, gssize 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:
index 17d4e6b..9e518a0 100644 (file)
@@ -1837,7 +1837,7 @@ static void
 allocation_param_free (AllocationParam * ap)
 {
   if (ap->allocator)
-    gst_allocator_unref (ap->allocator);
+    gst_object_unref (ap->allocator);
 }
 
 /**
@@ -1865,7 +1865,7 @@ gst_query_add_allocation_param (GstQuery * query, GstAllocator * 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
@@ -1930,7 +1930,7 @@ gst_query_parse_nth_allocation_param (GstQuery * query, guint index,
 
   if (allocator)
     if ((*allocator = ap->allocator))
-      gst_allocator_ref (*allocator);
+      gst_object_ref (*allocator);
   if (params)
     *params = ap->params;
 }
@@ -1964,7 +1964,7 @@ gst_query_set_nth_allocation_param (GstQuery * query, guint index,
   allocation_param_free (old);
 
   if ((ap.allocator = allocator))
-    gst_allocator_ref (allocator);
+    gst_object_ref (allocator);
   if (params)
     ap.params = *params;
   else
index 28e893e..c8fc62a 100644 (file)
@@ -33,6 +33,7 @@
 #include <gst/gststructure.h>
 #include <gst/gstformat.h>
 #include <gst/gstpad.h>
+#include <gst/gstallocator.h>
 #include <gst/gsttoc.h>
 
 G_BEGIN_DECLS
index 2129cc0..bef0f6d 100644 (file)
@@ -2787,7 +2787,7 @@ gst_base_src_set_allocation (GstBaseSrc * basesrc, GstBufferPool * pool,
     gst_object_unref (oldpool);
   }
   if (oldalloc) {
-    gst_allocator_unref (oldalloc);
+    gst_object_unref (oldalloc);
   }
   return TRUE;
 
@@ -2870,7 +2870,7 @@ gst_base_src_decide_allocation_default (GstBaseSrc * basesrc, GstQuery * query)
   else
     gst_query_add_allocation_param (query, allocator, &params);
   if (allocator)
-    gst_allocator_unref (allocator);
+    gst_object_unref (allocator);
 
   if (pool) {
     gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max);
index 391114b..d17b055 100644 (file)
@@ -785,7 +785,7 @@ gst_base_transform_set_allocation (GstBaseTransform * trans,
     gst_object_unref (oldpool);
   }
   if (oldalloc) {
-    gst_allocator_unref (oldalloc);
+    gst_object_unref (oldalloc);
   }
   if (oldquery) {
     gst_query_unref (oldquery);
@@ -883,7 +883,7 @@ gst_base_transform_default_decide_allocation (GstBaseTransform * trans,
   else
     gst_query_add_allocation_param (query, allocator, &params);
   if (allocator)
-    gst_allocator_unref (allocator);
+    gst_object_unref (allocator);
 
   if (pool) {
     gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max);
index fd445fb..96d9afb 100644 (file)
@@ -26,7 +26,7 @@ main (int argc, char **argv)
   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 ();
@@ -48,7 +48,7 @@ main (int argc, char **argv)
   gst_memory_unmap (mem, &info);
 
   gst_memory_unref (mem);
-  gst_allocator_unref (alloc);
+  gst_object_unref (alloc);
 
   return 0;
 }
index 6993a21..1e5ca6d 100644 (file)
@@ -19,8 +19,6 @@
 
 #include "my-memory.h"
 
-static GstAllocator *_my_allocator;
-
 typedef struct
 {
   GstMemory mem;
@@ -31,7 +29,7 @@ typedef struct
 
 
 static GstMemory *
-_my_alloc_alloc (GstAllocator * allocator, gsize size,
+_my_alloc (GstAllocator * allocator, gsize size,
     GstAllocationParams * params, gpointer user_data)
 {
   MyMemory *mem;
@@ -49,6 +47,16 @@ _my_alloc_alloc (GstAllocator * allocator, gsize size,
   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)
 {
@@ -78,14 +86,6 @@ _my_mem_unmap (MyMemory * mem)
   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)
 {
@@ -114,28 +114,47 @@ _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);
 }
index c814003..dad2d24 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <gst/gst.h>
 
+
 /* example of an allocator that delays allocation of the memory
  * until the memory is mapped */
 void my_memory_init (void);
index 768a616..1268639 100644 (file)
@@ -34,7 +34,7 @@ typedef struct
 
 
 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");
@@ -42,6 +42,16 @@ _my_alloc_alloc (GstAllocator * allocator, gsize size,
   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)
 {
@@ -71,14 +81,6 @@ _my_vidmem_unmap (MyVidmem * mem)
   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)
 {
@@ -107,32 +109,48 @@ _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)