memory: expose the GstAllocation structure

Expose the GstAllocation structure and provide an _init function. This makes it
easier to make 'subclasses' of the allocator that contain more info.
It also allows us to expose the flags on the allocator miniobject.
Make a flag to note that the allocator uses a custom alloc function.
This commit is contained in:
Wim Taymans 2012-07-06 17:19:21 +02:00
parent d2627a158e
commit 408df31a48
4 changed files with 74 additions and 76 deletions

View file

@ -91,16 +91,6 @@ size_t gst_memory_alignment = MEMORY_ALIGNMENT - 1;
size_t gst_memory_alignment = 0; size_t gst_memory_alignment = 0;
#endif #endif
struct _GstAllocator
{
GstMiniObject mini_object;
GstMemoryInfo info;
gpointer user_data;
GDestroyNotify notify;
};
/* default memory implementation */ /* default memory implementation */
typedef struct typedef struct
{ {
@ -390,7 +380,7 @@ static GRWLock lock;
static GHashTable *allocators; static GHashTable *allocators;
static void static void
_priv_sysmem_notify (gpointer user_data) _priv_sysmem_free (GstMiniObject * obj)
{ {
g_warning ("The default memory allocator was freed!"); g_warning ("The default memory allocator was freed!");
} }
@ -421,7 +411,8 @@ _priv_gst_memory_initialize (void)
GST_CAT_DEBUG (GST_CAT_MEMORY, "memory alignment: %" G_GSIZE_FORMAT, GST_CAT_DEBUG (GST_CAT_MEMORY, "memory alignment: %" G_GSIZE_FORMAT,
gst_memory_alignment); gst_memory_alignment);
_default_mem_impl = gst_allocator_new (&_mem_info, NULL, _priv_sysmem_notify); _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); _default_allocator = gst_allocator_ref (_default_mem_impl);
gst_allocator_register (GST_ALLOCATOR_SYSMEM, gst_allocator_register (GST_ALLOCATOR_SYSMEM,
@ -729,15 +720,6 @@ gst_memory_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset)
return TRUE; return TRUE;
} }
static void
_gst_allocator_free (GstAllocator * allocator)
{
if (allocator->notify)
allocator->notify (allocator->user_data);
g_slice_free1 (sizeof (GstAllocator), allocator);
}
static GstAllocator * static GstAllocator *
_gst_allocator_copy (GstAllocator * allocator) _gst_allocator_copy (GstAllocator * allocator)
{ {
@ -745,43 +727,37 @@ _gst_allocator_copy (GstAllocator * allocator)
} }
/** /**
* gst_allocator_new: * gst_allocator_init:
* @allocator: a #GstAllocator
* @flags: #GstAllocatorFlags
* @info: a #GstMemoryInfo * @info: a #GstMemoryInfo
* @user_data: user data * @free_func: a function to free @allocator
* @notify: a #GDestroyNotify for @user_data
* *
* Create a new memory allocator with @info and @user_data. * 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 * All functions in @info are mandatory exept the copy and is_span
* functions, which will have a default implementation when left NULL. * functions, which will have a default implementation when left NULL.
* *
* The @user_data will be passed to all calls of the alloc function. @notify
* will be called with @user_data when the allocator is freed.
*
* Returns: a new #GstAllocator. * Returns: a new #GstAllocator.
*/ */
GstAllocator * void
gst_allocator_new (const GstMemoryInfo * info, gpointer user_data, gst_allocator_init (GstAllocator * allocator, GstAllocatorFlags flags,
GDestroyNotify notify) const GstMemoryInfo * info, GstMiniObjectFreeFunction free_func)
{ {
GstAllocator *allocator; 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);
g_return_val_if_fail (info != NULL, NULL); gst_mini_object_init (GST_MINI_OBJECT_CAST (allocator), flags,
g_return_val_if_fail (info->alloc != NULL, NULL); GST_TYPE_ALLOCATOR, (GstMiniObjectCopyFunction) _gst_allocator_copy, NULL,
g_return_val_if_fail (info->mem_map != NULL, NULL); (GstMiniObjectFreeFunction) free_func);
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_new0 (GstAllocator);
gst_mini_object_init (GST_MINI_OBJECT_CAST (allocator), 0, GST_TYPE_ALLOCATOR,
(GstMiniObjectCopyFunction) _gst_allocator_copy, NULL,
(GstMiniObjectFreeFunction) _gst_allocator_free);
allocator->info = *info; allocator->info = *info;
allocator->user_data = user_data;
allocator->notify = notify;
#define INSTALL_FALLBACK(_t) \ #define INSTALL_FALLBACK(_t) \
if (allocator->info._t == NULL) allocator->info._t = _fallback_ ##_t; if (allocator->info._t == NULL) allocator->info._t = _fallback_ ##_t;
@ -789,25 +765,7 @@ gst_allocator_new (const GstMemoryInfo * info, gpointer user_data,
INSTALL_FALLBACK (mem_is_span); INSTALL_FALLBACK (mem_is_span);
#undef INSTALL_FALLBACK #undef INSTALL_FALLBACK
GST_CAT_DEBUG (GST_CAT_MEMORY, "new allocator %p", allocator); GST_CAT_DEBUG (GST_CAT_MEMORY, "init allocator %p", allocator);
return allocator;
}
/**
* gst_allocator_get_memory_type:
* @allocator: a #GstAllocator
*
* Get the memory type allocated by this allocator
*
* Returns: the memory type provided by @allocator
*/
const gchar *
gst_allocator_get_memory_type (GstAllocator * allocator)
{
g_return_val_if_fail (allocator != NULL, NULL);
return allocator->info.mem_type;
} }
/** /**
@ -971,7 +929,7 @@ gst_allocator_alloc (GstAllocator * allocator, gsize size,
if (allocator == NULL) if (allocator == NULL)
allocator = _default_allocator; allocator = _default_allocator;
mem = allocator->info.alloc (allocator, size, params, allocator->user_data); mem = allocator->info.alloc (allocator, size, params, NULL);
return mem; return mem;
} }

View file

@ -246,8 +246,8 @@ struct _GstAllocationParams {
* #GST_MEMORY_FLAG_ZERO_PADDED respectively. * #GST_MEMORY_FLAG_ZERO_PADDED respectively.
* *
* @user_data is extra data passed to this function. The default * @user_data is extra data passed to this function. The default
* gst_allocator_alloc() passes the user_data that was used when creating * gst_allocator_alloc() passes the NULL but other implementations could pass
* @allocator. * custom data.
* *
* Returns: a newly allocated #GstMemory. Free with gst_memory_unref() * Returns: a newly allocated #GstMemory. Free with gst_memory_unref()
*/ */
@ -331,6 +331,20 @@ typedef GstMemory * (*GstMemoryShareFunction) (GstMemory *mem, gssize offset
*/ */
typedef gboolean (*GstMemoryIsSpanFunction) (GstMemory *mem1, GstMemory *mem2, gsize *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: * GstMemoryInfo:
* @mem_type: the memory type this allocator provides * @mem_type: the memory type this allocator provides
@ -342,7 +356,7 @@ typedef gboolean (*GstMemoryIsSpanFunction) (GstMemory *mem1, GstMemory *m
* @mem_share: the implementation of the GstMemoryShareFunction * @mem_share: the implementation of the GstMemoryShareFunction
* @mem_is_span: the implementation of the GstMemoryIsSpanFunction * @mem_is_span: the implementation of the GstMemoryIsSpanFunction
* *
* The #GstMemoryInfo is used to register new memory allocators and contain * The #GstMemoryInfo is used to initialize new memory allocators and contain
* the implementations for various memory operations. * the implementations for various memory operations.
*/ */
struct _GstMemoryInfo { struct _GstMemoryInfo {
@ -364,15 +378,27 @@ struct _GstMemoryInfo {
/** /**
* GstAllocator: * GstAllocator:
* @mini_object: parent structure
* @info: a #GstMemoryInfo with the implementation
* *
* An opaque type returned from gst_allocator_new() or gst_allocator_find() * The #GstAllocator is used to create new memory and should be
* that can be used to allocator memory. * initialized with gst_allocator_init().
*/ */
struct _GstAllocator
{
GstMiniObject mini_object;
GstMemoryInfo info;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
/* allocators */ /* allocators */
GstAllocator * gst_allocator_new (const GstMemoryInfo * info, void gst_allocator_init (GstAllocator * allocator,
gpointer user_data, GDestroyNotify notify); GstAllocatorFlags flags,
const gchar * gst_allocator_get_memory_type (GstAllocator * allocator); const GstMemoryInfo *info,
GstMiniObjectFreeFunction free_func);
/** /**
* gst_allocator_ref: * gst_allocator_ref:

View file

@ -113,6 +113,12 @@ _my_mem_share (MyMemory * mem, gssize offset, gsize size)
return sub; return sub;
} }
static void
free_allocator (GstMiniObject * obj)
{
g_slice_free (GstAllocator, (GstAllocator *) obj);
}
void void
my_memory_init (void) my_memory_init (void)
{ {
@ -127,7 +133,8 @@ my_memory_init (void)
(GstMemoryIsSpanFunction) NULL, (GstMemoryIsSpanFunction) NULL,
}; };
_my_allocator = gst_allocator_new (&info, NULL, 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)); gst_allocator_register ("MyMemory", gst_allocator_ref (_my_allocator));
} }

View file

@ -106,6 +106,12 @@ _my_vidmem_share (MyVidmem * mem, gssize offset, gsize size)
return sub; return sub;
} }
static void
free_allocator (GstMiniObject * obj)
{
g_slice_free (GstAllocator, (GstAllocator *) obj);
}
void void
my_vidmem_init (void) my_vidmem_init (void)
{ {
@ -120,7 +126,8 @@ my_vidmem_init (void)
(GstMemoryIsSpanFunction) NULL, (GstMemoryIsSpanFunction) NULL,
}; };
_my_allocator = gst_allocator_new (&info, NULL, 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)); gst_allocator_register ("MyVidmem", gst_allocator_ref (_my_allocator));
} }