memory improvements

Make the memory object simply manage the data pointer and the maxsize and move
the offset and size handling to common functionality.
Use the READONLY flag to set a readonly lock.
Remove the data and size fields from the unmap method. We need an explicit
resize operation instead of using the unmap function.
Make internal helper lock and unlock functions.
Update unit test and users of the old API.
This commit is contained in:
Wim Taymans 2012-01-19 09:12:05 +01:00
parent e349e57154
commit a1d7bd02e4
5 changed files with 199 additions and 324 deletions

View file

@ -1237,13 +1237,10 @@ gst_iterator_result_get_type
GstMemory GstMemory
GstMemoryInfo GstMemoryInfo
GstAllocator GstAllocator
GST_MEMORY_IS_WRITABLE
GstMemoryFlags GstMemoryFlags
GstMapFlags GstMapFlags
GST_MAP_READWRITE GST_MAP_READWRITE
GstMemoryAllocFunction GstMemoryAllocFunction
GstMemoryGetSizesFunction
GstMemoryResizeFunction
GstMemoryMapFunction GstMemoryMapFunction
GstMemoryUnmapFunction GstMemoryUnmapFunction
GstMemoryFreeFunction GstMemoryFreeFunction
@ -1262,6 +1259,8 @@ gst_memory_unref
gst_memory_get_sizes gst_memory_get_sizes
gst_memory_resize gst_memory_resize
gst_memory_is_writable
gst_memory_map gst_memory_map
gst_memory_unmap gst_memory_unmap

View file

@ -538,7 +538,7 @@ gst_buffer_new_allocate (const GstAllocator * allocator, gsize size,
* that a finalize won't free the buffer */ * that a finalize won't free the buffer */
data = gst_memory_map (mem, &asize, NULL, GST_MAP_WRITE); data = gst_memory_map (mem, &asize, NULL, GST_MAP_WRITE);
gst_buffer_init ((GstBufferImpl *) data, 0); gst_buffer_init ((GstBufferImpl *) data, 0);
gst_memory_unmap (mem, data, asize); gst_memory_unmap (mem);
/* strip off the buffer */ /* strip off the buffer */
gst_memory_resize (mem, sizeof (GstBufferImpl), size); gst_memory_resize (mem, sizeof (GstBufferImpl), size);
@ -1004,7 +1004,6 @@ not_writable:
gboolean gboolean
gst_buffer_unmap (GstBuffer * buffer, gpointer data, gssize size) gst_buffer_unmap (GstBuffer * buffer, gpointer data, gssize size)
{ {
gboolean result;
guint len; guint len;
g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE); g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
@ -1015,15 +1014,14 @@ gst_buffer_unmap (GstBuffer * buffer, gpointer data, gssize size)
if (G_LIKELY (len == 1)) { if (G_LIKELY (len == 1)) {
GstMemory *mem = GST_BUFFER_MEM_PTR (buffer, 0); GstMemory *mem = GST_BUFFER_MEM_PTR (buffer, 0);
result = gst_memory_unmap (mem, data, size); gst_memory_unmap (mem);
} else { } else {
/* this must have been from read-only access. After _map, the buffer either /* this must have been from read-only access. After _map, the buffer either
* only contains 1 memory block or it allocated memory to join memory * only contains 1 memory block or it allocated memory to join memory
* blocks. It's not allowed to add buffers between _map and _unmap. */ * blocks. It's not allowed to add buffers between _map and _unmap. */
g_free (data); g_free (data);
result = TRUE;
} }
return result; return TRUE;
} }
/** /**
@ -1071,7 +1069,7 @@ gst_buffer_fill (GstBuffer * buffer, gsize offset, gconstpointer src,
/* offset past buffer, skip */ /* offset past buffer, skip */
offset -= ssize; offset -= ssize;
} }
gst_memory_unmap (mem, data, ssize); gst_memory_unmap (mem);
} }
return size - left; return size - left;
} }
@ -1119,7 +1117,7 @@ gst_buffer_extract (GstBuffer * buffer, gsize offset, gpointer dest, gsize size)
/* offset past buffer, skip */ /* offset past buffer, skip */
offset -= ssize; offset -= ssize;
} }
gst_memory_unmap (mem, data, ssize); gst_memory_unmap (mem);
} }
return size - left; return size - left;
} }
@ -1167,7 +1165,7 @@ gst_buffer_memcmp (GstBuffer * buffer, gsize offset, gconstpointer mem,
/* offset past buffer, skip */ /* offset past buffer, skip */
offset -= ssize; offset -= ssize;
} }
gst_memory_unmap (mem, data, ssize); gst_memory_unmap (mem);
} }
return res; return res;
} }
@ -1213,7 +1211,7 @@ gst_buffer_memset (GstBuffer * buffer, gsize offset, guint8 val, gsize size)
/* offset past buffer, skip */ /* offset past buffer, skip */
offset -= ssize; offset -= ssize;
} }
gst_memory_unmap (mem, data, ssize); gst_memory_unmap (mem);
} }
return size - left; return size - left;
} }
@ -1341,10 +1339,10 @@ _gst_buffer_arr_span (GstMemory ** mem[], gsize len[], guint n, gsize offset,
} else { } else {
offset -= tocopy; offset -= tocopy;
} }
gst_memory_unmap (cmem[i], src, ssize); gst_memory_unmap (cmem[i]);
} }
} }
gst_memory_unmap (span, dest, size); gst_memory_unmap (span);
} }
return span; return span;
} }

View file

@ -105,9 +105,6 @@ typedef struct
gsize slice_size; gsize slice_size;
guint8 *data; guint8 *data;
GFreeFunc free_func; GFreeFunc free_func;
gsize maxsize;
gsize offset;
gsize size;
} GstMemoryDefault; } GstMemoryDefault;
/* the default allocator */ /* the default allocator */
@ -126,13 +123,13 @@ _default_mem_init (GstMemoryDefault * mem, GstMemoryFlags flags,
mem->mem.flags = flags; mem->mem.flags = flags;
mem->mem.refcount = 1; mem->mem.refcount = 1;
mem->mem.parent = parent ? gst_memory_ref (parent) : NULL; mem->mem.parent = parent ? gst_memory_ref (parent) : NULL;
mem->mem.state = 0; mem->mem.state = (flags & GST_MEMORY_FLAG_READONLY ? 0x5 : 0);
mem->mem.maxsize = maxsize;
mem->mem.offset = offset;
mem->mem.size = size;
mem->slice_size = slice_size; mem->slice_size = slice_size;
mem->data = data; mem->data = data;
mem->free_func = free_func; mem->free_func = free_func;
mem->maxsize = maxsize;
mem->offset = offset;
mem->size = size;
} }
/* create a new memory block that manages the given memory */ /* create a new memory block that manages the given memory */
@ -188,62 +185,15 @@ _default_mem_alloc (const GstAllocator * allocator, gsize maxsize, gsize align)
return (GstMemory *) _default_mem_new_block (maxsize, align, 0, maxsize); return (GstMemory *) _default_mem_new_block (maxsize, align, 0, maxsize);
} }
static gsize
_default_mem_get_sizes (GstMemoryDefault * mem, gsize * offset, gsize * maxsize)
{
if (offset)
*offset = mem->offset;
if (maxsize)
*maxsize = mem->maxsize;
return mem->size;
}
static void
_default_mem_resize (GstMemoryDefault * mem, gssize offset, gsize size)
{
g_return_if_fail (offset >= 0 || mem->offset >= -offset);
g_return_if_fail (size + mem->offset + offset <= mem->maxsize);
mem->offset += offset;
mem->size = size;
}
static gpointer static gpointer
_default_mem_map (GstMemoryDefault * mem, gsize * size, gsize * maxsize, _default_mem_map (GstMemoryDefault * mem, GstMapFlags flags)
GstMapFlags flags)
{ {
if (size) return mem->data;
*size = mem->size;
if (maxsize)
*maxsize = mem->maxsize - mem->offset;
return mem->data + mem->offset;
} }
static gboolean static gboolean
_default_mem_unmap (GstMemoryDefault * mem, gpointer data, gsize size) _default_mem_unmap (GstMemoryDefault * mem)
{ {
GST_DEBUG ("mem: %p, data %p, size %" G_GSIZE_FORMAT, mem, data, size);
GST_DEBUG ("mem: %p, data %p, offset %" G_GSIZE_FORMAT ", size %"
G_GSIZE_FORMAT ", maxsize %" G_GSIZE_FORMAT, mem, mem->data, mem->offset,
mem->size, mem->maxsize);
g_return_val_if_fail ((guint8 *) data >= mem->data
&& (guint8 *) data < mem->data + mem->maxsize, FALSE);
if (mem->data + mem->offset != data) {
gsize newoffset = (guint8 *) data - mem->data;
if (size == -1)
size = mem->offset + mem->size - newoffset;
mem->offset = newoffset;
}
if (size != -1) {
g_return_val_if_fail (mem->offset + size <= mem->maxsize, FALSE);
mem->size = size;
}
return TRUE; return TRUE;
} }
@ -265,10 +215,12 @@ _default_mem_copy (GstMemoryDefault * mem, gssize offset, gsize size)
GstMemoryDefault *copy; GstMemoryDefault *copy;
if (size == -1) if (size == -1)
size = mem->size > offset ? mem->size - offset : 0; size = mem->mem.size > offset ? mem->mem.size - offset : 0;
copy = _default_mem_new_block (mem->maxsize, 0, mem->offset + offset, size); copy =
memcpy (copy->data, mem->data, mem->maxsize); _default_mem_new_block (mem->mem.maxsize, 0, mem->mem.offset + offset,
size);
memcpy (copy->data, mem->data, mem->mem.maxsize);
return copy; return copy;
} }
@ -284,10 +236,11 @@ _default_mem_share (GstMemoryDefault * mem, gssize offset, gsize size)
parent = (GstMemory *) mem; parent = (GstMemory *) mem;
if (size == -1) if (size == -1)
size = mem->size - offset; size = mem->mem.size - offset;
sub = _default_mem_new (parent->flags, parent, mem->data, NULL, mem->maxsize, sub =
mem->offset + offset, size); _default_mem_new (parent->flags, parent, mem->data, NULL,
mem->mem.maxsize, mem->mem.offset + offset, size);
return sub; return sub;
} }
@ -302,11 +255,12 @@ _default_mem_is_span (GstMemoryDefault * mem1, GstMemoryDefault * mem2,
parent = (GstMemoryDefault *) mem1->mem.parent; parent = (GstMemoryDefault *) mem1->mem.parent;
*offset = mem1->offset - parent->offset; *offset = mem1->mem.offset - parent->mem.offset;
} }
/* and memory is contiguous */ /* and memory is contiguous */
return mem1->data + mem1->offset + mem1->size == mem2->data + mem2->offset; return mem1->data + mem1->mem.offset + mem1->mem.size ==
mem2->data + mem2->mem.offset;
} }
static GstMemory * static GstMemory *
@ -317,15 +271,16 @@ _fallback_copy (GstMemory * mem, gssize offset, gssize size)
gsize msize; gsize msize;
data = gst_memory_map (mem, &msize, NULL, GST_MAP_READ); data = gst_memory_map (mem, &msize, NULL, GST_MAP_READ);
if (data == NULL)
return NULL;
if (size == -1) if (size == -1)
size = msize > offset ? msize - offset : 0; size = msize > offset ? msize - offset : 0;
/* use the same allocator as the memory we copy, FIXME, alignment? */ /* use the same allocator as the memory we copy */
copy = gst_allocator_alloc (mem->allocator, size, 0); copy = gst_allocator_alloc (mem->allocator, size, mem->align);
dest = gst_memory_map (copy, NULL, NULL, GST_MAP_WRITE); dest = gst_memory_map (copy, NULL, NULL, GST_MAP_WRITE);
memcpy (dest, data + offset, size); memcpy (dest, data + offset, size);
gst_memory_unmap (copy, dest, size); gst_memory_unmap (copy);
gst_memory_unmap (mem);
gst_memory_unmap (mem, data, msize);
return (GstMemory *) copy; return (GstMemory *) copy;
} }
@ -344,8 +299,6 @@ _priv_gst_memory_initialize (void)
{ {
static const GstMemoryInfo _mem_info = { static const GstMemoryInfo _mem_info = {
(GstMemoryAllocFunction) _default_mem_alloc, (GstMemoryAllocFunction) _default_mem_alloc,
(GstMemoryGetSizesFunction) _default_mem_get_sizes,
(GstMemoryResizeFunction) _default_mem_resize,
(GstMemoryMapFunction) _default_mem_map, (GstMemoryMapFunction) _default_mem_map,
(GstMemoryUnmapFunction) _default_mem_unmap, (GstMemoryUnmapFunction) _default_mem_unmap,
(GstMemoryFreeFunction) _default_mem_free, (GstMemoryFreeFunction) _default_mem_free,
@ -448,7 +401,12 @@ gst_memory_get_sizes (GstMemory * mem, gsize * offset, gsize * maxsize)
{ {
g_return_val_if_fail (mem != NULL, 0); g_return_val_if_fail (mem != NULL, 0);
return mem->allocator->info.get_sizes (mem, offset, maxsize); if (offset)
*offset = mem->offset;
if (maxsize)
*maxsize = mem->maxsize;
return mem->size;
} }
/** /**
@ -465,8 +423,11 @@ gst_memory_resize (GstMemory * mem, gssize offset, gsize size)
{ {
g_return_if_fail (mem != NULL); g_return_if_fail (mem != NULL);
g_return_if_fail (gst_memory_is_writable (mem)); g_return_if_fail (gst_memory_is_writable (mem));
g_return_if_fail (offset >= 0 || mem->offset >= -offset);
g_return_if_fail (size + mem->offset + offset <= mem->maxsize);
mem->allocator->info.resize (mem, offset, size); mem->offset += offset;
mem->size = size;
} }
/** /**
@ -487,6 +448,52 @@ gst_memory_is_writable (GstMemory * mem)
((mem->flags & GST_MEMORY_FLAG_READONLY) == 0); ((mem->flags & GST_MEMORY_FLAG_READONLY) == 0);
} }
static gboolean
gst_memory_lock (GstMemory * mem, GstMapFlags flags)
{
gint access_mode, state, newstate;
access_mode = flags & 3;
do {
state = g_atomic_int_get (&mem->state);
if (state == 0) {
/* nothing mapped, set access_mode and refcount */
newstate = 4 | access_mode;
} else {
/* access_mode must match */
if ((state & access_mode) != access_mode)
goto lock_failed;
/* increase refcount */
newstate = state + 4;
}
} while (!g_atomic_int_compare_and_exchange (&mem->state, state, newstate));
return TRUE;
lock_failed:
{
GST_DEBUG ("lock failed %p: state %d, access_mode %d", mem, state,
access_mode);
return FALSE;
}
}
static void
gst_memory_unlock (GstMemory * mem)
{
gint state, newstate;
do {
state = g_atomic_int_get (&mem->state);
/* decrease the refcount */
newstate = state - 4;
/* last refcount, unset access_mode */
if (newstate < 4)
newstate = 0;
} while (!g_atomic_int_compare_and_exchange (&mem->state, state, newstate));
}
/** /**
* gst_memory_map: * gst_memory_map:
* @mem: a #GstMemory * @mem: a #GstMemory
@ -499,94 +506,71 @@ gst_memory_is_writable (GstMemory * mem)
* @size and @maxsize will contain the size of the memory and the maximum * @size and @maxsize will contain the size of the memory and the maximum
* allocated memory of @mem respectively. They can be set to NULL. * allocated memory of @mem respectively. They can be set to NULL.
* *
* This function can return NULL for various reasons:
* - the memory backed by @mem is not accessible with the given @flags.
* - the memory was already mapped with a different mapping.
*
* @pointer remains valid for as long as @mem is alive and until
* gst_memory_unmap() is called.
*
* For each gst_memory_map() call, a corresponding gst_memory_unmap() call
* should be done.
*
* Returns: (transfer none): a pointer to the memory of @mem. * Returns: (transfer none): a pointer to the memory of @mem.
*/ */
gpointer gpointer
gst_memory_map (GstMemory * mem, gsize * size, gsize * maxsize, gst_memory_map (GstMemory * mem, gsize * size, gsize * maxsize,
GstMapFlags flags) GstMapFlags flags)
{ {
gpointer res; guint8 *res;
gint access_mode, state, newstate;
g_return_val_if_fail (mem != NULL, NULL); g_return_val_if_fail (mem != NULL, NULL);
access_mode = flags & 3;
g_return_val_if_fail (!(access_mode & GST_MAP_WRITE)
|| gst_memory_is_writable (mem), NULL);
do { if (!gst_memory_lock (mem, flags))
state = g_atomic_int_get (&mem->state); goto lock_failed;
if (state == 0) {
/* nothing mapped, set access_mode and refcount */
newstate = 4 | access_mode;
} else {
/* access_mode must match */
g_return_val_if_fail ((state & access_mode) == access_mode, NULL);
/* increase refcount */
newstate = state + 4;
}
} while (!g_atomic_int_compare_and_exchange (&mem->state, state, newstate));
res = mem->allocator->info.map (mem, size, maxsize, flags); res = mem->allocator->info.map (mem, mem->maxsize, flags);
if (G_UNLIKELY (res == NULL)) { if (G_UNLIKELY (res == NULL))
/* something went wrong, restore the orginal state again */ goto error;
do {
state = g_atomic_int_get (&mem->state); if (size)
/* there must be a ref */ *size = mem->size;
g_return_val_if_fail (state >= 4, NULL); if (maxsize)
/* decrease the refcount */ *maxsize = mem->maxsize - mem->offset;
newstate = state - 4;
/* last refcount, unset access_mode */ return res + mem->offset;
if (newstate < 4)
newstate = 0; /* ERRORS */
} while (!g_atomic_int_compare_and_exchange (&mem->state, state, newstate)); lock_failed:
{
g_critical ("memory %p: failed to lock memory", mem);
return NULL;
}
error:
{
/* something went wrong, restore the orginal state again */
GST_ERROR ("mem %p: map failed", mem);
gst_memory_unlock (mem);
return NULL;
} }
return res;
} }
/** /**
* gst_memory_unmap: * gst_memory_unmap:
* @mem: a #GstMemory * @mem: a #GstMemory
* @data: data to unmap
* @size: new size of @mem, or -1
* *
* Release the memory pointer obtained with gst_memory_map() and set the size of * Release the memory obtained with gst_memory_map()
* the memory to @size. @size can be set to -1 when the size should not be
* updated.
*
* It is possible to pass a different @data than that obtained from
* gst_memory_map() in which case the offset of @mem will be updated.
*
* Returns: TRUE when the memory was release successfully.
*/ */
gboolean void
gst_memory_unmap (GstMemory * mem, gpointer data, gssize size) gst_memory_unmap (GstMemory * mem)
{ {
gboolean need_unmap = TRUE; g_return_if_fail (mem != NULL);
gint state, newstate; /* there must be a ref */
g_return_if_fail (g_atomic_int_get (&mem->state) >= 4);
g_return_val_if_fail (mem != NULL, FALSE); mem->allocator->info.unmap (mem);
gst_memory_unlock (mem);
do {
state = g_atomic_int_get (&mem->state);
/* there must be a ref */
g_return_val_if_fail (state >= 4, FALSE);
if (need_unmap) {
/* try to unmap, only do this once */
if (!mem->allocator->info.unmap (mem, data, size))
return FALSE;
need_unmap = FALSE;
}
/* success, try to decrease the refcount */
newstate = state - 4;
/* last refcount, unset access_mode */
if (newstate < 4)
newstate = 0;
} while (!g_atomic_int_compare_and_exchange (&mem->state, state, newstate));
return TRUE;
} }
/** /**
@ -604,9 +588,16 @@ gst_memory_unmap (GstMemory * mem, gpointer data, gssize size)
GstMemory * GstMemory *
gst_memory_copy (GstMemory * mem, gssize offset, gssize size) gst_memory_copy (GstMemory * mem, gssize offset, gssize size)
{ {
g_return_val_if_fail (mem != NULL, NULL); GstMemory *copy;
return mem->allocator->info.copy (mem, offset, 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);
gst_memory_unlock (mem);
return copy;
} }
/** /**
@ -693,8 +684,6 @@ gst_allocator_register (const gchar * name, const GstMemoryInfo * info)
g_return_val_if_fail (name != NULL, NULL); g_return_val_if_fail (name != NULL, NULL);
g_return_val_if_fail (info != 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->alloc != NULL, NULL);
g_return_val_if_fail (info->get_sizes != NULL, NULL);
g_return_val_if_fail (info->resize != NULL, NULL);
g_return_val_if_fail (info->map != NULL, NULL); g_return_val_if_fail (info->map != NULL, NULL);
g_return_val_if_fail (info->unmap != 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->free != NULL, NULL);

View file

@ -62,6 +62,10 @@ typedef enum {
* @refcount: refcount * @refcount: refcount
* @parent: parent memory block * @parent: parent memory block
* @state: private state * @state: private state
* @maxsize: the maximum size allocated
* @align: the alignment of the memory
* @offset: the offset where valid data starts
* @size: the size of valid data
* *
* Base structure for memory implementations. Custom memory will put this structure * Base structure for memory implementations. Custom memory will put this structure
* as the first member of their structure. * as the first member of their structure.
@ -73,6 +77,10 @@ struct _GstMemory {
gint refcount; gint refcount;
GstMemory *parent; GstMemory *parent;
volatile gint state; volatile gint state;
gsize maxsize;
gsize align;
gsize offset;
gsize size;
}; };
/** /**
@ -122,63 +130,30 @@ typedef GstMemory * (*GstMemoryAllocFunction) (const GstAllocator *allocator,
gsize maxsize, gsize align, gsize maxsize, gsize align,
gpointer user_data); gpointer user_data);
/**
* GstMemoryGetSizesFunction:
* @mem: a #GstMemory
* @offset: result pointer for offset
* @maxsize: result pointer for maxsize
*
* Retrieve the size, offset and maxsize of @mem.
*
* Returns: the size of @mem, the offset and the maximum allocated size in @maxsize.
*/
typedef gsize (*GstMemoryGetSizesFunction) (GstMemory *mem, gsize *offset, gsize *maxsize);
/**
* GstMemoryResizeFunction:
* @mem: a #GstMemory
* @offset: the offset adjustement
* @size: the new size or -1 to just adjust the offset
*
* Adjust the size and offset of @mem. @offset bytes will be adjusted from the
* current first byte in @mem as retrieved with gst_memory_map() and the new
* size will be set to @size.
*
* @size can be set to -1, which will only adjust the offset.
*/
typedef void (*GstMemoryResizeFunction) (GstMemory *mem, gssize offset, gssize size);
/** /**
* GstMemoryMapFunction: * GstMemoryMapFunction:
* @mem: a #GstMemory * @mem: a #GstMemory
* @size: pointer for the size * @maxsize: size to map
* @maxsize: pointer for the maxsize
* @flags: access mode for the memory * @flags: access mode for the memory
* *
* Get the memory of @mem that can be accessed according to the mode specified * Get the memory of @mem that can be accessed according to the mode specified
* in @flags. @size and @maxsize will respectively contain the current amount of * in @flags. The function should return a pointer that contains at least
* valid bytes in the returned memory and the maximum allocated memory. * @maxsize bytes.
* @size and @maxsize can optionally be set to NULL.
* *
* Returns: a pointer to memory. @size bytes are currently used from the * Returns: a pointer to memory of which at least @maxsize bytes can be
* returned pointer and @maxsize bytes can potentially be used. * accessed according to the access pattern in @flags.
*/ */
typedef gpointer (*GstMemoryMapFunction) (GstMemory *mem, gsize *size, gsize *maxsize, typedef gpointer (*GstMemoryMapFunction) (GstMemory *mem, gsize maxsize, GstMapFlags flags);
GstMapFlags flags);
/** /**
* GstMemoryUnmapFunction: * GstMemoryUnmapFunction:
* @mem: a #GstMemory * @mem: a #GstMemory
* @data: the data pointer
* @size: the new size, or -1 to not modify the size
* *
* Return the pointer previously retrieved with gst_memory_map() and adjust the * Return the pointer previously retrieved with gst_memory_map().
* size of the memory with @size. @size can optionally be set to -1 to not
* modify the size.
* *
* Returns: %TRUE on success. * Returns: %TRUE on success.
*/ */
typedef gboolean (*GstMemoryUnmapFunction) (GstMemory *mem, gpointer data, gssize size); typedef void (*GstMemoryUnmapFunction) (GstMemory *mem);
/** /**
* GstMemoryFreeFunction: * GstMemoryFreeFunction:
@ -234,8 +209,6 @@ typedef gboolean (*GstMemoryIsSpanFunction) (GstMemory *mem1, GstMemory *m
/** /**
* GstMemoryInfo: * GstMemoryInfo:
* @alloc: the implementation of the GstMemoryAllocFunction * @alloc: the implementation of the GstMemoryAllocFunction
* @get_sizes: the implementation of the GstMemoryGetSizesFunction
* @resize: the implementation of the GstMemoryResizeFunction
* @map: the implementation of the GstMemoryMapFunction * @map: the implementation of the GstMemoryMapFunction
* @unmap: the implementation of the GstMemoryUnmapFunction * @unmap: the implementation of the GstMemoryUnmapFunction
* @free: the implementation of the GstMemoryFreeFunction * @free: the implementation of the GstMemoryFreeFunction
@ -249,8 +222,6 @@ typedef gboolean (*GstMemoryIsSpanFunction) (GstMemory *mem1, GstMemory *m
*/ */
struct _GstMemoryInfo { struct _GstMemoryInfo {
GstMemoryAllocFunction alloc; GstMemoryAllocFunction alloc;
GstMemoryGetSizesFunction get_sizes;
GstMemoryResizeFunction resize;
GstMemoryMapFunction map; GstMemoryMapFunction map;
GstMemoryUnmapFunction unmap; GstMemoryUnmapFunction unmap;
GstMemoryFreeFunction free; GstMemoryFreeFunction free;
@ -291,7 +262,7 @@ gboolean gst_memory_is_writable (GstMemory *mem);
gpointer gst_memory_map (GstMemory *mem, gsize *size, gsize *maxsize, gpointer gst_memory_map (GstMemory *mem, gsize *size, gsize *maxsize,
GstMapFlags flags); GstMapFlags flags);
gboolean gst_memory_unmap (GstMemory *mem, gpointer data, gssize size); void gst_memory_unmap (GstMemory *mem);
/* copy and subregions */ /* copy and subregions */
GstMemory * gst_memory_copy (GstMemory *mem, gssize offset, gssize size); GstMemory * gst_memory_copy (GstMemory *mem, gssize offset, gssize size);

View file

@ -45,7 +45,7 @@ GST_START_TEST (test_submemory)
fail_unless (size == 4, "memory has wrong size"); fail_unless (size == 4, "memory has wrong size");
fail_unless (maxsize >= 4, "memory has wrong size"); fail_unless (maxsize >= 4, "memory has wrong size");
memset (data, 0, 4); memset (data, 0, 4);
gst_memory_unmap (memory, data, 4); gst_memory_unmap (memory);
data = gst_memory_map (memory, &size, NULL, GST_MAP_READ); data = gst_memory_map (memory, &size, NULL, GST_MAP_READ);
@ -57,7 +57,7 @@ GST_START_TEST (test_submemory)
fail_unless (memcmp (data + 1, sdata, 2) == 0, fail_unless (memcmp (data + 1, sdata, 2) == 0,
"submemory contains the wrong data"); "submemory contains the wrong data");
ASSERT_MEMORY_REFCOUNT (sub, "submemory", 1); ASSERT_MEMORY_REFCOUNT (sub, "submemory", 1);
gst_memory_unmap (sub, sdata, ssize); gst_memory_unmap (sub);
gst_memory_unref (sub); gst_memory_unref (sub);
/* create a submemory of size 0 */ /* create a submemory of size 0 */
@ -68,7 +68,7 @@ GST_START_TEST (test_submemory)
fail_unless (memcmp (data + 1, sdata, 0) == 0, fail_unless (memcmp (data + 1, sdata, 0) == 0,
"submemory contains the wrong data"); "submemory contains the wrong data");
ASSERT_MEMORY_REFCOUNT (sub, "submemory", 1); ASSERT_MEMORY_REFCOUNT (sub, "submemory", 1);
gst_memory_unmap (sub, sdata, ssize); gst_memory_unmap (sub);
gst_memory_unref (sub); gst_memory_unref (sub);
/* test if metadata is coppied, not a complete memory copy so only the /* test if metadata is coppied, not a complete memory copy so only the
@ -89,7 +89,7 @@ GST_START_TEST (test_submemory)
/* clean up */ /* clean up */
gst_memory_unref (sub); gst_memory_unref (sub);
gst_memory_unmap (memory, data, size); gst_memory_unmap (memory);
gst_memory_unref (memory); gst_memory_unref (memory);
} }
@ -157,7 +157,7 @@ GST_START_TEST (test_writable)
data = gst_memory_map (mem2, &size, NULL, GST_MAP_WRITE); data = gst_memory_map (mem2, &size, NULL, GST_MAP_WRITE);
data[4] = 'a'; data[4] = 'a';
gst_memory_unmap (mem2, data, size); gst_memory_unmap (mem2);
gst_memory_ref (mem2); gst_memory_ref (mem2);
ASSERT_CRITICAL (gst_memory_map (mem, &size, NULL, GST_MAP_WRITE)); ASSERT_CRITICAL (gst_memory_map (mem, &size, NULL, GST_MAP_WRITE));
@ -165,8 +165,7 @@ GST_START_TEST (test_writable)
data = gst_memory_map (mem2, &size, NULL, GST_MAP_WRITE); data = gst_memory_map (mem2, &size, NULL, GST_MAP_WRITE);
data[4] = 'a'; data[4] = 'a';
gst_memory_unmap (mem2, data, size); gst_memory_unmap (mem2);
gst_memory_unref (mem2); gst_memory_unref (mem2);
gst_memory_unref (mem); gst_memory_unref (mem);
@ -198,7 +197,6 @@ GST_START_TEST (test_copy)
{ {
GstMemory *memory, *copy; GstMemory *memory, *copy;
gsize size, ssize; gsize size, ssize;
guint8 *data, *sdata;
memory = gst_allocator_alloc (NULL, 4, 0); memory = gst_allocator_alloc (NULL, 4, 0);
ASSERT_MEMORY_REFCOUNT (memory, "memory", 1); ASSERT_MEMORY_REFCOUNT (memory, "memory", 1);
@ -209,28 +207,28 @@ GST_START_TEST (test_copy)
/* memorys are copied and must point to different memory */ /* memorys are copied and must point to different memory */
fail_if (memory == copy); fail_if (memory == copy);
data = gst_memory_map (memory, &size, NULL, GST_MAP_READ); gst_memory_map (memory, &size, NULL, GST_MAP_READ);
sdata = gst_memory_map (copy, &ssize, NULL, GST_MAP_READ); gst_memory_map (copy, &ssize, NULL, GST_MAP_READ);
/* NOTE that data is refcounted */ /* NOTE that data is refcounted */
fail_unless (size == ssize); fail_unless (size == ssize);
gst_memory_unmap (copy, sdata, ssize); gst_memory_unmap (copy);
gst_memory_unmap (memory, data, size); gst_memory_unmap (memory);
gst_memory_unref (copy); gst_memory_unref (copy);
gst_memory_unref (memory); gst_memory_unref (memory);
memory = gst_allocator_alloc (NULL, 0, 0); memory = gst_allocator_alloc (NULL, 0, 0);
data = gst_memory_map (memory, &size, NULL, GST_MAP_READ); gst_memory_map (memory, &size, NULL, GST_MAP_READ);
fail_unless (size == 0); fail_unless (size == 0);
gst_memory_unmap (memory, data, size); gst_memory_unmap (memory);
/* copying a 0-sized memory should not crash */ /* copying a 0-sized memory should not crash */
copy = gst_memory_copy (memory, 0, -1); copy = gst_memory_copy (memory, 0, -1);
data = gst_memory_map (copy, &size, NULL, GST_MAP_READ); gst_memory_map (copy, &size, NULL, GST_MAP_READ);
fail_unless (size == 0); fail_unless (size == 0);
gst_memory_unmap (copy, data, size); gst_memory_unmap (copy);
gst_memory_unref (copy); gst_memory_unref (copy);
gst_memory_unref (memory); gst_memory_unref (memory);
@ -248,7 +246,7 @@ GST_START_TEST (test_try_new_and_alloc)
fail_unless (mem != NULL); fail_unless (mem != NULL);
data = gst_memory_map (mem, &size, NULL, GST_MAP_READ); data = gst_memory_map (mem, &size, NULL, GST_MAP_READ);
fail_unless (size == 0); fail_unless (size == 0);
gst_memory_unmap (mem, data, size); gst_memory_unmap (mem);
gst_memory_unref (mem); gst_memory_unref (mem);
/* normal alloc should still work */ /* normal alloc should still work */
@ -258,7 +256,7 @@ GST_START_TEST (test_try_new_and_alloc)
fail_unless (data != NULL); fail_unless (data != NULL);
fail_unless (size == (640 * 480 * 4)); fail_unless (size == (640 * 480 * 4));
data[640 * 479 * 4 + 479] = 0xff; data[640 * 479 * 4 + 479] = 0xff;
gst_memory_unmap (mem, data, size); gst_memory_unmap (mem);
gst_memory_unref (mem); gst_memory_unref (mem);
@ -397,51 +395,8 @@ GST_START_TEST (test_map)
fail_unless (data != NULL); fail_unless (data != NULL);
fail_unless (size == 100); fail_unless (size == 100);
fail_unless (maxsize == maxalloc); fail_unless (maxsize == maxalloc);
ASSERT_CRITICAL (gst_memory_unmap (mem, (guint8 *) data - 1, maxsize + 1));
gst_memory_unmap (mem, data, size);
/* make smaller by unmapping less */
data = gst_memory_map (mem, &size, &maxsize, GST_MAP_READ);
fail_unless (data != NULL);
fail_unless (size == 100);
fail_unless (maxsize == maxalloc);
gst_memory_unmap (mem, data, size - 1);
size = gst_memory_get_sizes (mem, &offset, &maxalloc);
fail_unless (size == 99);
fail_unless (offset == 0);
fail_unless (maxalloc >= 100);
/* make bigger by unmapping more */
data = gst_memory_map (mem, &size, &maxsize, GST_MAP_READ);
fail_unless (data != NULL);
fail_unless (size == 99);
fail_unless (maxsize == maxalloc);
gst_memory_unmap (mem, data, size + 1);
size = gst_memory_get_sizes (mem, &offset, &maxalloc);
fail_unless (size == 100);
fail_unless (offset == 0);
fail_unless (maxalloc >= 100);
/* resize beyond the maxsize */
data = gst_memory_map (mem, &size, &maxsize, GST_MAP_READ);
fail_unless (data != NULL);
fail_unless (size == 100);
fail_unless (maxsize == maxalloc);
ASSERT_CRITICAL (gst_memory_unmap (mem, data, maxsize + 1));
gst_memory_unmap (mem, data, maxsize);
/* add offset, maxsize should be smaller now */
gst_memory_resize (mem, 1, 99);
data = gst_memory_map (mem, &size, &maxsize, GST_MAP_READ);
fail_unless (data != NULL);
fail_unless (size == 99);
fail_unless (maxsize == maxalloc - 1);
ASSERT_CRITICAL (gst_memory_unmap (mem, data, maxsize + 1));
gst_memory_unmap (mem, data, maxsize);
gst_memory_unmap (mem);
gst_memory_unref (mem); gst_memory_unref (mem);
} }
@ -464,30 +419,17 @@ GST_START_TEST (test_map_nested)
fail_unless (data2 == data1); fail_unless (data2 == data1);
fail_unless (size2 == 100); fail_unless (size2 == 100);
/* unmap in reverse order */ /* unmap */
gst_memory_unmap (mem, data2, size2); gst_memory_unmap (mem);
gst_memory_unmap (mem, data1, size1); gst_memory_unmap (mem);
/* nested mapping */
data1 = gst_memory_map (mem, &size1, &maxsize1, GST_MAP_READ);
fail_unless (data1 != NULL);
fail_unless (size1 == 100);
data2 = gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READ);
fail_unless (data2 == data1);
fail_unless (size2 == 100);
/* unmap in different order */
gst_memory_unmap (mem, data1, size1);
gst_memory_unmap (mem, data2, size2);
data1 = gst_memory_map (mem, &size1, &maxsize1, GST_MAP_READ); data1 = gst_memory_map (mem, &size1, &maxsize1, GST_MAP_READ);
/* not allowed */ /* not allowed */
ASSERT_CRITICAL (gst_memory_map (mem, &size2, &maxsize2, GST_MAP_WRITE)); ASSERT_CRITICAL (gst_memory_map (mem, &size2, &maxsize2, GST_MAP_WRITE));
ASSERT_CRITICAL (gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READWRITE)); ASSERT_CRITICAL (gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READWRITE));
data2 = gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READ); data2 = gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READ);
gst_memory_unmap (mem, data1, size1); gst_memory_unmap (mem);
gst_memory_unmap (mem, data2, size2); gst_memory_unmap (mem);
fail_unless (mem->state == 0); fail_unless (mem->state == 0);
data1 = gst_memory_map (mem, &size1, &maxsize1, GST_MAP_WRITE); data1 = gst_memory_map (mem, &size1, &maxsize1, GST_MAP_WRITE);
@ -495,21 +437,19 @@ GST_START_TEST (test_map_nested)
ASSERT_CRITICAL (gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READ)); ASSERT_CRITICAL (gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READ));
ASSERT_CRITICAL (gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READWRITE)); ASSERT_CRITICAL (gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READWRITE));
data2 = gst_memory_map (mem, &size2, &maxsize2, GST_MAP_WRITE); data2 = gst_memory_map (mem, &size2, &maxsize2, GST_MAP_WRITE);
gst_memory_unmap (mem, data1, size1); gst_memory_unmap (mem);
gst_memory_unmap (mem, data2, size2); gst_memory_unmap (mem);
/* nothing was mapped */ /* nothing was mapped */
ASSERT_CRITICAL (gst_memory_unmap (mem, data2, size2)); ASSERT_CRITICAL (gst_memory_unmap (mem));
data1 = gst_memory_map (mem, &size1, &maxsize1, GST_MAP_READWRITE); data1 = gst_memory_map (mem, &size1, &maxsize1, GST_MAP_READWRITE);
data2 = gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READ); data2 = gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READ);
gst_memory_unmap (mem, data2, size2); gst_memory_unmap (mem);
data2 = gst_memory_map (mem, &size2, &maxsize2, GST_MAP_WRITE); data2 = gst_memory_map (mem, &size2, &maxsize2, GST_MAP_WRITE);
gst_memory_unmap (mem, data2, size2); gst_memory_unmap (mem);
/* ut of range */ gst_memory_unmap (mem);
ASSERT_CRITICAL (gst_memory_unmap (mem, (guint8 *) data1 - 1, size1));
gst_memory_unmap (mem, data1, size1);
/* nothing was mapped */ /* nothing was mapped */
ASSERT_CRITICAL (gst_memory_unmap (mem, data1, size1)); ASSERT_CRITICAL (gst_memory_unmap (mem));
gst_memory_unref (mem); gst_memory_unref (mem);
} }
@ -535,32 +475,24 @@ GST_START_TEST (test_map_resize)
fail_unless (size == 99); fail_unless (size == 99);
fail_unless (offset == 1); fail_unless (offset == 1);
fail_unless (maxalloc >= 100); fail_unless (maxalloc >= 100);
gst_memory_unmap (mem);
/* unmap the buffer with original pointer and size, should restore the offset
* and size */
gst_memory_unmap (mem, data, 100);
size = gst_memory_get_sizes (mem, &offset, &maxalloc); size = gst_memory_get_sizes (mem, &offset, &maxalloc);
fail_unless (size == 100); fail_unless (size == 99);
fail_unless (offset == 0); fail_unless (offset == 1);
fail_unless (maxalloc >= 100); fail_unless (maxalloc >= 100);
data = gst_memory_map (mem, &size, &maxsize, GST_MAP_READ); data = gst_memory_map (mem, &size, &maxsize, GST_MAP_READ);
fail_unless (data != NULL); fail_unless (data != NULL);
fail_unless (size == 100);
fail_unless (maxsize >= 100);
/* resize the buffer with unmap */
gst_memory_unmap (mem, (guint8 *) data + 1, 99);
size = gst_memory_get_sizes (mem, &offset, &maxalloc);
fail_unless (size == 99); fail_unless (size == 99);
fail_unless (offset == 1); fail_unless (offset == 1);
fail_unless (maxalloc >= 100); fail_unless (maxsize >= 100);
gst_memory_unmap (mem);
/* and larger */ /* and larger */
data = gst_memory_map (mem, &size, &maxsize, GST_MAP_READ); data = gst_memory_map (mem, &size, &maxsize, GST_MAP_READ);
gst_memory_unmap (mem, (guint8 *) data - 1, 100); gst_memory_resize (mem, -1, 100);
gst_memory_unmap (mem);
size = gst_memory_get_sizes (mem, &offset, &maxalloc); size = gst_memory_get_sizes (mem, &offset, &maxalloc);
fail_unless (size == 100); fail_unless (size == 100);
@ -568,21 +500,7 @@ GST_START_TEST (test_map_resize)
fail_unless (maxalloc >= 100); fail_unless (maxalloc >= 100);
data = gst_memory_map (mem, &size, &maxsize, GST_MAP_READ); data = gst_memory_map (mem, &size, &maxsize, GST_MAP_READ);
gst_memory_unmap (mem, (guint8 *) data + 1, -1); gst_memory_unmap (mem);
size = gst_memory_get_sizes (mem, &offset, &maxalloc);
fail_unless (size == 99);
fail_unless (offset == 1);
fail_unless (maxalloc >= 100);
data = gst_memory_map (mem, &size, &maxsize, GST_MAP_READ);
gst_memory_unmap (mem, (guint8 *) data - 1, -1);
size = gst_memory_get_sizes (mem, &offset, &maxalloc);
fail_unless (size == 100);
fail_unless (offset == 0);
fail_unless (maxalloc >= 100);
gst_memory_unref (mem); gst_memory_unref (mem);
} }