summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gst/gstbuffer.c3
-rw-r--r--gst/gstbuffer.h2
-rw-r--r--gst/gstmemory.c168
-rw-r--r--gst/gstmemory.h56
-rw-r--r--libs/gst/base/gstbasesrc.c11
-rw-r--r--libs/gst/base/gstbasetransform.c11
-rw-r--r--win32/common/libgstreamer.def3
7 files changed, 175 insertions, 79 deletions
diff --git a/gst/gstbuffer.c b/gst/gstbuffer.c
index fdfd6a43d8..d4e67a5d77 100644
--- a/gst/gstbuffer.c
+++ b/gst/gstbuffer.c
@@ -479,8 +479,7 @@ gst_buffer_new (void)
* be allocated.
*/
GstBuffer *
-gst_buffer_new_allocate (const GstAllocator * allocator, gsize size,
- gsize align)
+gst_buffer_new_allocate (GstAllocator * allocator, gsize size, gsize align)
{
GstBuffer *newbuf;
GstMemory *mem;
diff --git a/gst/gstbuffer.h b/gst/gstbuffer.h
index 39d8d6f431..2a945d67a8 100644
--- a/gst/gstbuffer.h
+++ b/gst/gstbuffer.h
@@ -266,7 +266,7 @@ GType gst_buffer_get_type (void);
/* allocation */
GstBuffer * gst_buffer_new (void);
-GstBuffer * gst_buffer_new_allocate (const GstAllocator * allocator, gsize size, gsize align);
+GstBuffer * gst_buffer_new_allocate (GstAllocator * allocator, gsize size, gsize align);
GstBuffer * gst_buffer_new_wrapped_full (gpointer data, GFreeFunc free_func, gsize offset, gsize size);
GstBuffer * gst_buffer_new_wrapped (gpointer data, gsize size);
diff --git a/gst/gstmemory.c b/gst/gstmemory.c
index 7f4d298f13..4e822edd2f 100644
--- a/gst/gstmemory.c
+++ b/gst/gstmemory.c
@@ -93,9 +93,12 @@ size_t gst_memory_alignment = 0;
struct _GstAllocator
{
- GQuark name;
+ gint refcount;
GstMemoryInfo info;
+
+ gpointer user_data;
+ GDestroyNotify notify;
};
/* default memory implementation */
@@ -108,10 +111,10 @@ typedef struct
} GstMemoryDefault;
/* the default allocator */
-static const GstAllocator *_default_allocator;
+static GstAllocator *_default_allocator;
/* our predefined allocators */
-static const GstAllocator *_default_mem_impl;
+static GstAllocator *_default_mem_impl;
/* initialize the fields */
static void
@@ -182,7 +185,8 @@ _default_mem_new_block (gsize maxsize, gsize align, gsize offset, gsize size)
}
static GstMemory *
-_default_mem_alloc (const GstAllocator * allocator, gsize maxsize, gsize align)
+_default_alloc_alloc (GstAllocator * allocator, gsize maxsize, gsize align,
+ gpointer user_data)
{
return (GstMemory *) _default_mem_new_block (maxsize, align, 0, maxsize);
}
@@ -268,7 +272,7 @@ _default_mem_is_span (GstMemoryDefault * mem1, GstMemoryDefault * mem2,
}
static GstMemory *
-_fallback_copy (GstMemory * mem, gssize offset, gssize size)
+_fallback_mem_copy (GstMemory * mem, gssize offset, gssize size)
{
GstMemory *copy;
GstMapInfo sinfo, dinfo;
@@ -295,7 +299,7 @@ _fallback_copy (GstMemory * mem, gssize offset, gssize size)
}
static gboolean
-_fallback_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset)
+_fallback_mem_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset)
{
return FALSE;
}
@@ -303,18 +307,23 @@ _fallback_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset)
static GRWLock lock;
static GHashTable *allocators;
+static void
+_priv_sysmem_notify (gpointer user_data)
+{
+ g_warning ("The default memory allocator was freed!");
+}
+
void
_priv_gst_memory_initialize (void)
{
static const GstMemoryInfo _mem_info = {
- (GstMemoryAllocFunction) _default_mem_alloc,
+ (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,
- NULL
};
g_rw_lock_init (&lock);
@@ -328,9 +337,11 @@ _priv_gst_memory_initialize (void)
GST_DEBUG ("memory alignment: %" G_GSIZE_FORMAT, gst_memory_alignment);
- _default_mem_impl = gst_allocator_register (GST_ALLOCATOR_SYSMEM, &_mem_info);
+ _default_mem_impl = gst_allocator_new (&_mem_info, NULL, _priv_sysmem_notify);
- _default_allocator = _default_mem_impl;
+ _default_allocator = gst_allocator_ref (_default_mem_impl);
+ gst_allocator_register (GST_ALLOCATOR_SYSMEM,
+ gst_allocator_ref (_default_mem_impl));
}
/**
@@ -396,7 +407,7 @@ gst_memory_unref (GstMemory * mem)
GST_DEBUG ("memory %p, %d->%d", mem, mem->refcount, mem->refcount - 1);
if (g_atomic_int_dec_and_test (&mem->refcount))
- mem->allocator->info.free (mem);
+ mem->allocator->info.mem_free (mem);
}
/**
@@ -587,7 +598,7 @@ gst_memory_map (GstMemory * mem, GstMapInfo * info, GstMapFlags flags)
if (!gst_memory_lock (mem, flags))
goto lock_failed;
- info->data = mem->allocator->info.map (mem, mem->maxsize, flags);
+ info->data = mem->allocator->info.mem_map (mem, mem->maxsize, flags);
if (G_UNLIKELY (info->data == NULL))
goto error;
@@ -631,7 +642,7 @@ gst_memory_unmap (GstMemory * mem, GstMapInfo * info)
/* there must be a ref */
g_return_if_fail (g_atomic_int_get (&mem->state) >= 4);
- mem->allocator->info.unmap (mem);
+ mem->allocator->info.mem_unmap (mem);
gst_memory_unlock (mem);
}
@@ -655,7 +666,7 @@ gst_memory_copy (GstMemory * mem, gssize offset, gssize size)
g_return_val_if_fail (mem != NULL, NULL);
g_return_val_if_fail (gst_memory_lock (mem, GST_MAP_READ), NULL);
- copy = mem->allocator->info.copy (mem, offset, size);
+ copy = mem->allocator->info.mem_copy (mem, offset, size);
gst_memory_unlock (mem);
@@ -680,7 +691,7 @@ gst_memory_share (GstMemory * mem, gssize offset, gssize size)
{
g_return_val_if_fail (mem != NULL, NULL);
- return mem->allocator->info.share (mem, offset, size);
+ return mem->allocator->info.mem_share (mem, offset, size);
}
/**
@@ -713,7 +724,7 @@ gst_memory_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset)
return FALSE;
/* and memory is contiguous */
- if (!mem1->allocator->info.is_span (mem1, mem2, offset))
+ if (!mem1->allocator->info.mem_is_span (mem1, mem2, offset))
return FALSE;
return TRUE;
@@ -721,50 +732,112 @@ gst_memory_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset)
/**
* gst_allocator_register:
- * @name: the name of the allocator
- * @info: #GstMemoryInfo
+ * @info: a #GstMemoryInfo
+ * @user_data: user data
+ * @notify: a #GDestroyNotify for @user_data
*
- * Registers the memory allocator with @name and implementation functions
- * @info.
+ * Create a new memory allocator with @info and @user_data.
*
* All functions in @info are mandatory exept the copy and is_span
* functions, which will have a default implementation when left NULL.
*
- * The user_data field in @info will be passed to all calls of the alloc
- * function.
+ * The @user_data will be passed to all calls of the alloc function and the
+ * @notify function.
*
* Returns: a new #GstAllocator.
*/
-const GstAllocator *
-gst_allocator_register (const gchar * name, const GstMemoryInfo * info)
+GstAllocator *
+gst_allocator_new (const GstMemoryInfo * info, gpointer user_data,
+ GDestroyNotify notify)
{
GstAllocator *allocator;
#define INSTALL_FALLBACK(_t) \
if (allocator->info._t == NULL) allocator->info._t = _fallback_ ##_t;
- g_return_val_if_fail (name != NULL, NULL);
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (info->alloc != NULL, NULL);
- g_return_val_if_fail (info->map != NULL, NULL);
- g_return_val_if_fail (info->unmap != NULL, NULL);
- g_return_val_if_fail (info->free != NULL, NULL);
- g_return_val_if_fail (info->share != NULL, NULL);
+ g_return_val_if_fail (info->mem_map != NULL, NULL);
+ g_return_val_if_fail (info->mem_unmap != NULL, NULL);
+ g_return_val_if_fail (info->mem_free != NULL, NULL);
+ g_return_val_if_fail (info->mem_share != NULL, NULL);
allocator = g_slice_new (GstAllocator);
- allocator->name = g_quark_from_string (name);
+ allocator->refcount = 1;
allocator->info = *info;
- INSTALL_FALLBACK (copy);
- INSTALL_FALLBACK (is_span);
+ allocator->user_data = user_data;
+ allocator->notify = notify;
+ INSTALL_FALLBACK (mem_copy);
+ INSTALL_FALLBACK (mem_is_span);
#undef INSTALL_FALLBACK
- GST_DEBUG ("registering allocator \"%s\"", name);
+ GST_DEBUG ("new allocator %p", allocator);
+
+ return allocator;
+}
+
+/**
+ * gst_alocator_ref:
+ * @allocator: a #GstAllocator
+ *
+ * Increases the refcount of @allocator.
+ *
+ * Returns: @allocator with increased refcount
+ */
+GstAllocator *
+gst_allocator_ref (GstAllocator * allocator)
+{
+ g_return_val_if_fail (allocator != NULL, NULL);
+
+ GST_DEBUG ("alocator %p, %d->%d", allocator, allocator->refcount,
+ allocator->refcount + 1);
+
+ g_atomic_int_inc (&allocator->refcount);
+
+ return allocator;
+}
+
+/**
+ * gst_allocator_unref:
+ * @allocator: a #GstAllocator
+ *
+ * Decreases the refcount of @allocator. When the refcount reaches 0, the free
+ * function of @allocator will be called.
+ */
+void
+gst_allocator_unref (GstAllocator * allocator)
+{
+ g_return_if_fail (allocator != NULL);
+
+ GST_DEBUG ("allocator %p, %d->%d", allocator, allocator->refcount,
+ allocator->refcount - 1);
+
+ if (g_atomic_int_dec_and_test (&allocator->refcount)) {
+ if (allocator->notify)
+ allocator->notify (allocator->user_data);
+ g_slice_free1 (sizeof (GstAllocator), 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_DEBUG ("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);
-
- return allocator;
}
/**
@@ -774,13 +847,13 @@ gst_allocator_register (const gchar * name, const GstMemoryInfo * info)
* Find a previously registered allocator with @name. When @name is NULL, the
* default allocator will be returned.
*
- * Returns: a #GstAllocator or NULL when the allocator with @name was not
- * registered.
+ * 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.
*/
-const GstAllocator *
+GstAllocator *
gst_allocator_find (const gchar * name)
{
- const GstAllocator *allocator;
+ GstAllocator *allocator;
g_rw_lock_reader_lock (&lock);
if (name) {
@@ -788,6 +861,8 @@ gst_allocator_find (const gchar * name)
} else {
allocator = _default_allocator;
}
+ if (allocator)
+ gst_allocator_ref (allocator);
g_rw_lock_reader_unlock (&lock);
return allocator;
@@ -795,18 +870,23 @@ gst_allocator_find (const gchar * name)
/**
* gst_allocator_set_default:
- * @allocator: a #GstAllocator
+ * @allocator: (transfer full): a #GstAllocator
*
- * Set the default allocator.
+ * Set the default allocator. This function takes ownership of @allocator.
*/
void
-gst_allocator_set_default (const GstAllocator * allocator)
+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);
}
/**
@@ -826,7 +906,7 @@ gst_allocator_set_default (const GstAllocator * allocator)
* Returns: (transfer full): a new #GstMemory.
*/
GstMemory *
-gst_allocator_alloc (const GstAllocator * allocator, gsize maxsize, gsize align)
+gst_allocator_alloc (GstAllocator * allocator, gsize maxsize, gsize align)
{
g_return_val_if_fail (((align + 1) & align) == 0, NULL);
@@ -834,5 +914,5 @@ gst_allocator_alloc (const GstAllocator * allocator, gsize maxsize, gsize align)
allocator = _default_allocator;
return allocator->info.alloc (allocator, maxsize, align,
- allocator->info.user_data);
+ allocator->user_data);
}
diff --git a/gst/gstmemory.h b/gst/gstmemory.h
index 6cebb76a25..f3d3095ef9 100644
--- a/gst/gstmemory.h
+++ b/gst/gstmemory.h
@@ -71,7 +71,7 @@ typedef enum {
* as the first member of their structure.
*/
struct _GstMemory {
- const GstAllocator *allocator;
+ GstAllocator *allocator;
GstMemoryFlags flags;
gint refcount;
@@ -134,7 +134,7 @@ typedef struct {
#define GST_ALLOCATOR_SYSMEM "SystemMemory"
/**
- * GstMemoryAllocFunction:
+ * GstAllocatorAllocFunction:
* @allocator: a #GstAllocator
* @maxsize: the maxsize
* @align: the alignment
@@ -143,13 +143,13 @@ typedef struct {
* Allocate a new #GstMemory from @allocator that can hold at least @maxsize bytes
* and is aligned to (@align + 1) bytes.
*
- * @user_data is the data that was used when registering @allocator.
+ * @user_data is the data that was used when creating @allocator.
*
* Returns: a newly allocated #GstMemory. Free with gst_memory_unref()
*/
-typedef GstMemory * (*GstMemoryAllocFunction) (const GstAllocator *allocator,
- gsize maxsize, gsize align,
- gpointer user_data);
+typedef GstMemory * (*GstAllocatorAllocFunction) (GstAllocator *allocator,
+ gsize maxsize, gsize align,
+ gpointer user_data);
/**
* GstMemoryMapFunction:
@@ -229,42 +229,46 @@ typedef gboolean (*GstMemoryIsSpanFunction) (GstMemory *mem1, GstMemory *m
/**
* GstMemoryInfo:
- * @alloc: the implementation of the GstMemoryAllocFunction
- * @map: the implementation of the GstMemoryMapFunction
- * @unmap: the implementation of the GstMemoryUnmapFunction
- * @free: the implementation of the GstMemoryFreeFunction
- * @copy: the implementation of the GstMemoryCopyFunction
- * @share: the implementation of the GstMemoryShareFunction
- * @is_span: the implementation of the GstMemoryIsSpanFunction
- * @user_data: generic user data for the allocator
+ * @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 register new memory allocators and contain
* the implementations for various memory operations.
*/
struct _GstMemoryInfo {
- GstMemoryAllocFunction alloc;
- GstMemoryMapFunction map;
- GstMemoryUnmapFunction unmap;
- GstMemoryFreeFunction free;
+ GstAllocatorAllocFunction alloc;
- GstMemoryCopyFunction copy;
- GstMemoryShareFunction share;
- GstMemoryIsSpanFunction is_span;
+ GstMemoryMapFunction mem_map;
+ GstMemoryUnmapFunction mem_unmap;
+ GstMemoryFreeFunction mem_free;
- gpointer user_data;
+ GstMemoryCopyFunction mem_copy;
+ GstMemoryShareFunction mem_share;
+ GstMemoryIsSpanFunction mem_is_span;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
/* allocators */
-const GstAllocator * gst_allocator_register (const gchar *name, const GstMemoryInfo *info);
-const GstAllocator * gst_allocator_find (const gchar *name);
+GstAllocator * gst_allocator_new (const GstMemoryInfo * info,
+ gpointer user_data, GDestroyNotify notify);
-void gst_allocator_set_default (const GstAllocator * allocator);
+GstAllocator * gst_allocator_ref (GstAllocator * allocator);
+void gst_allocator_unref (GstAllocator * allocator);
+
+void gst_allocator_register (const gchar *name, GstAllocator *alloc);
+GstAllocator * gst_allocator_find (const gchar *name);
+
+void gst_allocator_set_default (GstAllocator * allocator);
/* allocating memory blocks */
-GstMemory * gst_allocator_alloc (const GstAllocator * allocator,
+GstMemory * gst_allocator_alloc (GstAllocator * allocator,
gsize maxsize, gsize align);
GstMemory * gst_memory_new_wrapped (GstMemoryFlags flags, gpointer data, GFreeFunc free_func,
diff --git a/libs/gst/base/gstbasesrc.c b/libs/gst/base/gstbasesrc.c
index 443002804d..13b0c07657 100644
--- a/libs/gst/base/gstbasesrc.c
+++ b/libs/gst/base/gstbasesrc.c
@@ -246,7 +246,7 @@ struct _GstBaseSrcPrivate
GstClockTime earliest_time;
GstBufferPool *pool;
- const GstAllocator *allocator;
+ GstAllocator *allocator;
guint prefix;
guint alignment;
};
@@ -2701,8 +2701,9 @@ null_buffer:
static gboolean
gst_base_src_set_allocation (GstBaseSrc * basesrc, GstBufferPool * pool,
- const GstAllocator * allocator, guint prefix, guint alignment)
+ GstAllocator * allocator, guint prefix, guint alignment)
{
+ GstAllocator *oldalloc;
GstBufferPool *oldpool;
GstBaseSrcPrivate *priv = basesrc->priv;
@@ -2716,6 +2717,7 @@ gst_base_src_set_allocation (GstBaseSrc * basesrc, GstBufferPool * pool,
oldpool = priv->pool;
priv->pool = pool;
+ oldalloc = priv->allocator;
priv->allocator = allocator;
priv->prefix = prefix;
@@ -2730,6 +2732,9 @@ gst_base_src_set_allocation (GstBaseSrc * basesrc, GstBufferPool * pool,
}
gst_object_unref (oldpool);
}
+ if (oldalloc) {
+ gst_allocator_unref (oldalloc);
+ }
return TRUE;
/* ERRORS */
@@ -2766,7 +2771,7 @@ gst_base_src_prepare_allocation (GstBaseSrc * basesrc, GstCaps * caps)
gboolean result = TRUE;
GstQuery *query;
GstBufferPool *pool = NULL;
- const GstAllocator *allocator = NULL;
+ GstAllocator *allocator = NULL;
guint size, min, max, prefix, alignment;
bclass = GST_BASE_SRC_GET_CLASS (basesrc);
diff --git a/libs/gst/base/gstbasetransform.c b/libs/gst/base/gstbasetransform.c
index 698ce31316..3735a1951e 100644
--- a/libs/gst/base/gstbasetransform.c
+++ b/libs/gst/base/gstbasetransform.c
@@ -254,7 +254,7 @@ struct _GstBaseTransformPrivate
GstClockTime position_out;
GstBufferPool *pool;
- const GstAllocator *allocator;
+ GstAllocator *allocator;
guint prefix;
guint alignment;
};
@@ -747,9 +747,10 @@ done:
static gboolean
gst_base_transform_set_allocation (GstBaseTransform * trans,
- GstBufferPool * pool, const GstAllocator * allocator, guint prefix,
+ GstBufferPool * pool, GstAllocator * allocator, guint prefix,
guint alignment)
{
+ GstAllocator *oldalloc;
GstBufferPool *oldpool;
GstBaseTransformPrivate *priv = trans->priv;
@@ -763,6 +764,7 @@ gst_base_transform_set_allocation (GstBaseTransform * trans,
GST_OBJECT_LOCK (trans);
oldpool = priv->pool;
priv->pool = pool;
+ oldalloc = priv->allocator;
priv->allocator = allocator;
priv->prefix = prefix;
priv->alignment = alignment;
@@ -773,6 +775,9 @@ gst_base_transform_set_allocation (GstBaseTransform * trans,
gst_buffer_pool_set_active (oldpool, FALSE);
gst_object_unref (oldpool);
}
+ if (oldalloc) {
+ gst_allocator_unref (oldalloc);
+ }
return TRUE;
/* ERRORS */
@@ -791,7 +796,7 @@ gst_base_transform_do_bufferpool (GstBaseTransform * trans, GstCaps * outcaps)
GstBufferPool *pool = NULL, *oldpool;
guint size, min, max, prefix, alignment;
GstBaseTransformClass *klass;
- const GstAllocator *allocator = NULL;
+ GstAllocator *allocator = NULL;
/* there are these possibilities:
*
diff --git a/win32/common/libgstreamer.def b/win32/common/libgstreamer.def
index 6fb08f1cb1..68a573385c 100644
--- a/win32/common/libgstreamer.def
+++ b/win32/common/libgstreamer.def
@@ -51,8 +51,11 @@ EXPORTS
_gst_trace_mutex DATA
gst_allocator_alloc
gst_allocator_find
+ gst_allocator_new
+ gst_allocator_ref
gst_allocator_register
gst_allocator_set_default
+ gst_allocator_unref
gst_atomic_queue_length
gst_atomic_queue_new
gst_atomic_queue_peek