memory: further memory tweaking

Allow for automatic merging of memory block in the _map function and automatic
freeing of the temporary memory.
Remove some unneeded functions.
Add possibility to force writable spanned memory.
This commit is contained in:
Wim Taymans 2011-03-29 19:17:55 +02:00
parent edbfc492bb
commit 030fcde837
5 changed files with 104 additions and 81 deletions

View file

@ -132,7 +132,7 @@
GType _gst_buffer_type = 0;
static GstMemory *_gst_buffer_arr_span (GstMemory ** mem[], gsize len[],
guint n, gsize offset, gsize size);
guint n, gsize offset, gsize size, gboolean writable);
typedef struct _GstMetaItem GstMetaItem;
@ -160,26 +160,36 @@ typedef struct
GstMetaItem *item;
} GstBufferImpl;
static void
_span_memory (GstBuffer * buffer, gsize offset, gsize size)
static GstMemory *
_span_memory (GstBuffer * buffer, gsize offset, gsize size, gboolean writable)
{
GstMemory *span, **mem[1];
gsize len[1], i;
gsize len[1];
/* not enough room, span buffers */
mem[0] = GST_BUFFER_MEM_ARRAY (buffer);
len[0] = GST_BUFFER_MEM_LEN (buffer);
if (len[0] == 1)
return;
span = _gst_buffer_arr_span (mem, len, 1, offset, size);
if (size == -1)
size = gst_buffer_get_size (buffer);
span = _gst_buffer_arr_span (mem, len, 1, offset, size, writable);
return span;
}
static void
_replace_memory (GstBuffer * buffer, GstMemory * mem)
{
gsize len, i;
/* unref old buffers */
for (i = 0; i < len[0]; i++)
gst_memory_unref (mem[0][i]);
len = GST_BUFFER_MEM_LEN (buffer);
for (i = 0; i < len; i++)
gst_memory_unref (GST_BUFFER_MEM_PTR (buffer, i));
/* replace with single spanned buffer */
GST_BUFFER_MEM_PTR (buffer, 0) = span;
GST_BUFFER_MEM_PTR (buffer, 0) = mem;
GST_BUFFER_MEM_LEN (buffer) = 1;
}
@ -189,12 +199,12 @@ _memory_add (GstBuffer * buffer, GstMemory * mem)
guint len = GST_BUFFER_MEM_LEN (buffer);
if (G_UNLIKELY (len >= GST_BUFFER_MEM_MAX)) {
gsize size = gst_buffer_get_size (buffer);
/* to many buffer, span them */
_span_memory (buffer, 0, size);
_replace_memory (buffer, _span_memory (buffer, 0, -1, FALSE));
/* we now have 1 single spanned buffer */
len = 1;
}
/* and append the new buffer */
GST_BUFFER_MEM_PTR (buffer, len) = mem;
GST_BUFFER_MEM_LEN (buffer) = len + 1;
}
@ -328,7 +338,7 @@ gst_buffer_copy_into (GstBuffer * dest, GstBuffer * src,
}
}
if (flags & GST_BUFFER_COPY_MERGE) {
_span_memory (dest, 0, size);
_replace_memory (dest, _span_memory (dest, 0, size, FALSE));
}
}
@ -598,16 +608,30 @@ gst_buffer_take_memory (GstBuffer * buffer, GstMemory * mem)
* Returns: a #GstMemory at @idx.
*/
GstMemory *
gst_buffer_peek_memory (GstBuffer * buffer, guint idx)
gst_buffer_peek_memory (GstBuffer * buffer, guint idx, GstMapFlags flags)
{
GstMemory *mem;
gboolean write;
write = (flags & GST_MAP_WRITE) != 0;
g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
g_return_val_if_fail (idx < GST_BUFFER_MEM_LEN (buffer), NULL);
/* check if we can write when asked for write access */
if (G_UNLIKELY (write && !gst_buffer_is_writable (buffer)))
goto not_writable;
mem = GST_BUFFER_MEM_PTR (buffer, idx);
return mem;
/* ERRORS */
not_writable:
{
g_return_val_if_fail (gst_buffer_is_writable (buffer), NULL);
return NULL;
}
}
/**
@ -759,38 +783,66 @@ gst_buffer_map (GstBuffer * buffer, gsize * size, gsize * maxsize,
{
guint len;
gpointer data;
GstMemory *mem;
gboolean write, writable;
g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
len = GST_BUFFER_MEM_LEN (buffer);
write = (flags & GST_MAP_WRITE) != 0;
writable = gst_buffer_is_writable (buffer);
if (G_UNLIKELY ((flags & GST_MAP_WRITE) && !gst_buffer_is_writable (buffer)))
/* check if we can write when asked for write access */
if (G_UNLIKELY (write && !writable))
goto not_writable;
if (G_LIKELY (len == 1)) {
GstMemory *mem;
len = GST_BUFFER_MEM_LEN (buffer);
mem = GST_BUFFER_MEM_PTR (buffer, 0);
if (flags & GST_MAP_WRITE) {
if (G_UNLIKELY (!GST_MEMORY_IS_WRITABLE (mem))) {
GstMemory *copy;
/* replace with a writable copy */
copy = gst_memory_copy (mem, 0, gst_memory_get_sizes (mem, NULL));
GST_BUFFER_MEM_PTR (buffer, 0) = copy;
gst_memory_unref (mem);
mem = copy;
}
}
data = gst_memory_map (mem, size, maxsize, flags);
} else {
/* FIXME, implement me */
data = NULL;
if (G_UNLIKELY (len == 0)) {
/* no memory, return immediately */
if (size)
*size = 0;
if (maxsize)
*maxsize = 0;
return NULL;
}
if (G_LIKELY (len == 1)) {
/* we can take the first one */
mem = GST_BUFFER_MEM_PTR (buffer, 0);
} else {
/* we need to span memory */
if (writable) {
/* if we can write, we can change the memory with the spanned
* memory */
mem = _span_memory (buffer, 0, -1, write);
_replace_memory (buffer, mem);
} else {
gsize bsize;
/* extract all data in new memory, FIXME slow!! */
bsize = gst_buffer_get_size (buffer);
data = g_malloc (bsize);
gst_buffer_extract (buffer, 0, data, bsize);
if (size)
*size = bsize;
if (maxsize)
*maxsize = bsize;
return data;
}
}
if (G_UNLIKELY (write && !GST_MEMORY_IS_WRITABLE (mem))) {
GstMemory *copy;
/* replace with a writable copy */
copy = gst_memory_copy (mem, 0, -1);
GST_BUFFER_MEM_PTR (buffer, 0) = copy;
gst_memory_unref (mem);
mem = copy;
}
data = gst_memory_map (mem, size, maxsize, flags);
return data;
/* ERROR */
@ -827,8 +879,11 @@ gst_buffer_unmap (GstBuffer * buffer, gpointer data, gsize size)
result = gst_memory_unmap (mem, data, size);
} else {
/* FIXME, implement me */
result = FALSE;
/* 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
* blocks. It's not allowed to add buffers between _map and _unmap. */
g_free (data);
result = TRUE;
}
return result;
}
@ -1064,12 +1119,13 @@ _gst_buffer_arr_is_span_fast (GstMemory ** mem[], gsize len[], guint n,
static GstMemory *
_gst_buffer_arr_span (GstMemory ** mem[], gsize len[], guint n, gsize offset,
gsize size)
gsize size, gboolean writable)
{
GstMemory *span, *parent;
gsize poffset;
if (_gst_buffer_arr_is_span_fast (mem, len, n, &poffset, &parent)) {
if (!writable
&& _gst_buffer_arr_is_span_fast (mem, len, n, &poffset, &parent)) {
span = gst_memory_sub (parent, offset + poffset, size);
} else {
gsize count, left;
@ -1188,7 +1244,7 @@ gst_buffer_span (GstBuffer * buf1, gsize offset, GstBuffer * buf2, gsize size)
mem[1] = GST_BUFFER_MEM_ARRAY (buf2);
len[1] = GST_BUFFER_MEM_LEN (buf2);
span = _gst_buffer_arr_span (mem, len, 2, offset, size);
span = _gst_buffer_arr_span (mem, len, 2, offset, size, FALSE);
newbuf = gst_buffer_new ();
_memory_add (newbuf, span);

View file

@ -284,7 +284,7 @@ GstBuffer * gst_buffer_new_and_alloc (guint size);
/* memory blocks */
guint gst_buffer_n_memory (GstBuffer *buffer);
void gst_buffer_take_memory (GstBuffer *buffer, GstMemory *mem);
GstMemory * gst_buffer_peek_memory (GstBuffer *buffer, guint idx);
GstMemory * gst_buffer_peek_memory (GstBuffer *buffer, guint idx, GstMapFlags flags);
void gst_buffer_remove_memory_range (GstBuffer *buffer, guint idx, guint length);
/**

View file

@ -188,21 +188,14 @@ _default_mem_copy (GstMemoryDefault * mem, gsize offset, gsize size)
{
GstMemoryDefault *copy;
if (size == -1)
size = mem->size > offset ? mem->size - offset : 0;
copy = _default_mem_new_block (mem->maxsize, 0, mem->offset + offset, size);
memcpy (copy->data, mem->data, mem->maxsize);
return copy;
}
static void
_default_mem_extract (GstMemoryDefault * mem, gsize offset, gpointer dest,
gsize size)
{
g_return_if_fail (size + mem->offset + offset <= mem->maxsize);
memcpy (dest, mem->data + mem->offset + offset, size);
}
static GstMemoryDefault *
_default_mem_sub (GstMemoryDefault * mem, gsize offset, gsize size)
{
@ -233,17 +226,6 @@ _default_mem_is_span (GstMemoryDefault * mem1, GstMemoryDefault * mem2,
return mem1->data + mem1->offset + mem1->size == mem2->data + mem2->offset;
}
static void
_fallback_extract (GstMemory * mem, gsize offset, gpointer dest, gsize size)
{
guint8 *data;
gsize msize;
data = gst_memory_map (mem, &msize, NULL, GST_MAP_READ);
memcpy (dest, data + offset, size);
gst_memory_unmap (mem, data, msize);
}
static GstMemory *
_fallback_copy (GstMemory * mem, gsize offset, gsize size)
{
@ -252,6 +234,8 @@ _fallback_copy (GstMemory * mem, gsize offset, gsize size)
gsize msize;
data = gst_memory_map (mem, &msize, NULL, GST_MAP_READ);
if (size == -1)
size = msize > offset ? msize - offset : 0;
copy = _default_mem_new_block (size, 0, 0, size);
memcpy (copy->data, data + offset, size);
gst_memory_unmap (mem, data, msize);
@ -289,7 +273,6 @@ _gst_memory_init (void)
(GstMemoryUnmapFunction) _default_mem_unmap,
(GstMemoryFreeFunction) _default_mem_free,
(GstMemoryCopyFunction) _default_mem_copy,
(GstMemoryExtractFunction) _default_mem_extract,
(GstMemorySubFunction) _default_mem_sub,
(GstMemoryIsSpanFunction) _default_mem_is_span
};
@ -301,7 +284,6 @@ _gst_memory_init (void)
(GstMemoryFreeFunction) _default_mem_free,
NULL,
NULL,
NULL,
NULL
};
@ -336,7 +318,6 @@ gst_memory_register (const gchar * name, const GstMemoryInfo * info)
impl->name = g_quark_from_string (name);
impl->info = *info;
INSTALL_FALLBACK (copy);
INSTALL_FALLBACK (extract);
INSTALL_FALLBACK (sub);
INSTALL_FALLBACK (is_span);
@ -455,15 +436,6 @@ gst_memory_copy (GstMemory * mem, gsize offset, gsize size)
return mem->impl->info.copy (mem, offset, size);
}
void
gst_memory_extract (GstMemory * mem, gsize offset, gpointer dest, gsize size)
{
g_return_if_fail (mem != NULL);
g_return_if_fail (dest != NULL);
return mem->impl->info.extract (mem, offset, dest, size);
}
void
gst_memory_trim (GstMemory * mem, gsize offset, gsize size)
{

View file

@ -81,8 +81,6 @@ typedef gboolean (*GstMemoryUnmapFunction) (GstMemory *mem, gpointer data, gsiz
typedef void (*GstMemoryFreeFunction) (GstMemory *mem);
typedef GstMemory * (*GstMemoryCopyFunction) (GstMemory *mem, gsize offset, gsize size);
typedef void (*GstMemoryExtractFunction) (GstMemory *mem, gsize offset,
gpointer dest, gsize size);
typedef void (*GstMemoryTrimFunction) (GstMemory *mem, gsize offset, gsize size);
typedef GstMemory * (*GstMemorySubFunction) (GstMemory *mem, gsize offset, gsize size);
typedef gboolean (*GstMemoryIsSpanFunction) (GstMemory *mem1, GstMemory *mem2,
@ -102,7 +100,6 @@ struct _GstMemoryInfo {
GstMemoryFreeFunction free;
GstMemoryCopyFunction copy;
GstMemoryExtractFunction extract;
GstMemorySubFunction sub;
GstMemoryIsSpanFunction is_span;
};
@ -128,13 +125,12 @@ void gst_memory_trim (GstMemory *mem, gsize offset, gsize size);
gpointer gst_memory_map (GstMemory *mem, gsize *size, gsize *maxsize,
GstMapFlags flags);
gboolean gst_memory_unmap (GstMemory *mem, gpointer data, gsize size);
void gst_memory_extract (GstMemory *mem, gsize offset, gpointer dest,
gsize size);
/* copy and subregions */
GstMemory * gst_memory_copy (GstMemory *mem, gsize offset, gsize size);
GstMemory * gst_memory_sub (GstMemory *mem, gsize offset, gsize size);
/* memory arrays */
/* span memory */
gboolean gst_memory_is_span (GstMemory *mem1, GstMemory *mem2, gsize *offset);
GstMemory * gst_memory_span (GstMemory **mem1, gsize len1, gsize offset,
GstMemory **mem2, gsize len2, gsize size);

View file

@ -531,7 +531,6 @@ EXPORTS
gst_marshal_VOID__POINTER_OBJECT
gst_marshal_VOID__UINT_BOXED
gst_memory_copy
gst_memory_extract
gst_memory_flags_get_type
gst_memory_get_sizes
gst_memory_is_span