memory: more fixes

Automatically make the memory of a buffer writable when the buffer is writable
and the memory is asked to mapped WRITE.
Add docs
This commit is contained in:
Wim Taymans 2011-03-24 11:49:46 +01:00
parent 38ffe30745
commit 6f2af5aa87
3 changed files with 184 additions and 71 deletions

View file

@ -416,14 +416,12 @@ gst_buffer_new_and_alloc (guint size)
* the requested amount of memory can't be allocated, NULL will be returned.
* The buffer memory is not cleared.
*
* Note that when @size == 0, the buffer data pointer will be NULL.
* Note that when @size == 0, the buffer will not have memory associated with it.
*
* MT safe.
*
* Returns: (transfer full): a new #GstBuffer, or NULL if the memory couldn't
* be allocated.
*
* Since: 0.10.13
*/
GstBuffer *
gst_buffer_try_new_and_alloc (guint size)
@ -456,6 +454,14 @@ no_memory:
}
}
/**
* gst_buffer_n_memory:
* @buffer: a #GstBuffer.
*
* Get the amount of memory blocks that this buffer has.
*
* Returns: (transfer full): the amount of memory block in this buffer.
*/
guint
gst_buffer_n_memory (GstBuffer * buffer)
{
@ -468,6 +474,14 @@ gst_buffer_n_memory (GstBuffer * buffer)
return arr->len;
}
/**
* gst_buffer_take_memory:
* @buffer: a #GstBuffer.
* @mem: a #GstMemory.
*
* Add the memory block @mem to @buffer. This function takes ownership of @mem
* and thus doesn't increase its refcount.
*/
void
gst_buffer_take_memory (GstBuffer * buffer, GstMemory * mem)
{
@ -481,6 +495,17 @@ gst_buffer_take_memory (GstBuffer * buffer, GstMemory * mem)
g_ptr_array_add (arr, mem);
}
/**
* gst_buffer_peek_memory:
* @buffer: a #GstBuffer.
* @idx: an index
*
* Get the memory block in @buffer at @idx. This function does not return a
* refcount to the memory block. The memory block stays valid for as long as the
* caller has a valid reference to @buffer.
*
* Returns: a #GstMemory at @idx.
*/
GstMemory *
gst_buffer_peek_memory (GstBuffer * buffer, guint idx)
{
@ -496,6 +521,13 @@ gst_buffer_peek_memory (GstBuffer * buffer, guint idx)
return mem;
}
/**
* gst_buffer_remove_memory:
* @buffer: a #GstBuffer.
* @idx: an index
*
* Remove the memory block in @buffer at @idx.
*/
void
gst_buffer_remove_memory (GstBuffer * buffer, guint idx)
{
@ -509,6 +541,14 @@ gst_buffer_remove_memory (GstBuffer * buffer, guint idx)
g_ptr_array_remove_index (arr, idx);
}
/**
* gst_buffer_get_size:
* @buffer: a #GstBuffer.
*
* Get the total size of all memory blocks in @buffer.
*
* Returns: the total size of the memory in @buffer.
*/
gsize
gst_buffer_get_size (GstBuffer * buffer)
{
@ -526,7 +566,30 @@ gst_buffer_get_size (GstBuffer * buffer)
return size;
}
/* getting memory */
/**
* gst_buffer_map:
* @buffer: a #GstBuffer.
* @size: a location for the size
* @maxsize: a location for the max size
* @flags: flags for the mapping
*
* This function return a pointer to the memory in @buffer. @flags describe the
* desired access of the memory. When @flags is #GST_MAP_WRITE, @buffer should
* be writable (as returned from gst_buffer_is_writable()).
*
* @size and @maxsize will contain the current valid number of bytes in the
* returned memory area and the total maximum mount of bytes available in the
* returned memory area respectively.
*
* When @buffer is writable but the memory isn't, a writable copy will
* automatically be created and returned. The readonly copy of the buffer memory
* will then also be replaced with this writable copy.
*
* When the buffer contains multiple memory blocks, the returned pointer will be
* a concatenation of the memory blocks.
*
* Returns: a pointer to the memory for the buffer.
*/
gpointer
gst_buffer_map (GstBuffer * buffer, gsize * size, gsize * maxsize,
GstMapFlags flags)
@ -544,13 +607,19 @@ gst_buffer_map (GstBuffer * buffer, gsize * size, gsize * maxsize,
goto not_writable;
if (G_LIKELY (len == 1)) {
GstMemory *mem = g_ptr_array_index (arr, 0);
GstMemory *mem;
mem = g_ptr_array_index (arr, 0);
if (flags & GST_MAP_WRITE) {
if (G_UNLIKELY (!GST_MEMORY_IS_WRITABLE (mem))) {
/* try to get a writable copy */
g_return_val_if_fail (GST_MEMORY_IS_WRITABLE (mem), NULL);
return NULL;
GstMemory *copy;
/* replace with a writable copy */
copy = gst_memory_copy (mem, 0, gst_memory_get_sizes (mem, NULL));
g_ptr_array_index (arr, 0) = copy;
gst_memory_unref (mem);
mem = copy;
}
}
@ -568,6 +637,17 @@ not_writable:
}
}
/**
* gst_buffer_unmap:
* @buffer: a #GstBuffer.
* @data: the previously mapped data
* @size: the size of @data
*
* Release the memory previously mapped with gst_buffer_map().
*
* Returns: #TRUE on success. #FALSE can be returned when the new size is larger
* than the maxsize of the memory.
*/
gboolean
gst_buffer_unmap (GstBuffer * buffer, gpointer data, gsize size)
{
@ -590,6 +670,15 @@ gst_buffer_unmap (GstBuffer * buffer, gpointer data, gsize size)
return result;
}
/**
* gst_buffer_extract:
* @buffer: a #GstBuffer.
* @offset: the offset to extract
* @dest: the destination address
* @size: the size to extract
*
* Copy @size bytes starting from @offset in @buffer to @dest.
*/
void
gst_buffer_extract (GstBuffer * buffer, gsize offset, gpointer dest, gsize size)
{

View file

@ -276,6 +276,43 @@ _fallback_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset)
return FALSE;
}
void
_gst_memory_init (void)
{
static const GstMemoryInfo _mem_info = {
(GstMemoryGetSizesFunction) _default_mem_get_sizes,
(GstMemoryTrimFunction) _default_mem_trim,
(GstMemoryMapFunction) _default_mem_map,
(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
};
static const GstMemoryInfo _sub_info = {
(GstMemoryGetSizesFunction) _default_mem_get_sizes,
(GstMemoryTrimFunction) _default_mem_trim,
(GstMemoryMapFunction) _default_sub_map,
(GstMemoryUnmapFunction) _default_sub_unmap,
(GstMemoryFreeFunction) _default_mem_free,
NULL,
NULL,
NULL,
NULL
};
_default_mem_impl = gst_memory_register ("GstMemoryDefault", &_mem_info);
_default_sub_impl = gst_memory_register ("GstMemorySubbuffer", &_sub_info);
}
/**
* gst_memory_register:
* @name:
* @info:
*
* Returns:
*/
const GstMemoryImpl *
gst_memory_register (const gchar * name, const GstMemoryInfo * info)
{
@ -312,36 +349,45 @@ gst_memory_register (const gchar * name, const GstMemoryInfo * info)
return impl;
}
void
_gst_memory_init (void)
GstMemory *
gst_memory_new_wrapped (GstMemoryFlags flags, gpointer data,
GFreeFunc free_func, gsize maxsize, gsize offset, gsize size)
{
static const GstMemoryInfo _mem_info = {
(GstMemoryGetSizesFunction) _default_mem_get_sizes,
(GstMemoryTrimFunction) _default_mem_trim,
(GstMemoryMapFunction) _default_mem_map,
(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
};
static const GstMemoryInfo _sub_info = {
(GstMemoryGetSizesFunction) _default_mem_get_sizes,
(GstMemoryTrimFunction) _default_mem_trim,
(GstMemoryMapFunction) _default_sub_map,
(GstMemoryUnmapFunction) _default_sub_unmap,
(GstMemoryFreeFunction) _default_mem_free,
NULL,
NULL,
NULL,
NULL
};
GstMemoryDefault *mem;
_default_mem_impl = gst_memory_register ("GstMemoryDefault", &_mem_info);
_default_sub_impl = gst_memory_register ("GstMemorySubbuffer", &_sub_info);
mem = _default_mem_new (flags, NULL, data, free_func, maxsize, offset, size);
return (GstMemory *) mem;
}
GstMemory *
gst_memory_new_alloc (gsize maxsize, gsize align)
{
GstMemoryDefault *mem;
mem = _default_mem_new_block (maxsize, align, 0, maxsize);
return (GstMemory *) mem;
}
GstMemory *
gst_memory_new_copy (gsize maxsize, gsize align, gpointer data,
gsize offset, gsize size)
{
GstMemoryDefault *mem;
mem = _default_mem_new_block (maxsize, align, offset, size);
memcpy (mem->data, data, maxsize);
return (GstMemory *) mem;
}
/**
* gst_memory_ref:
* @mem: a #GstMemory
*
* Returns: @mem with increased refcount
*/
GstMemory *
gst_memory_ref (GstMemory * mem)
{
@ -352,6 +398,10 @@ gst_memory_ref (GstMemory * mem)
return mem;
}
/**
* gst_memory_unref:
* @mem: a #GstMemory
*/
void
gst_memory_unref (GstMemory * mem)
{
@ -362,6 +412,13 @@ gst_memory_unref (GstMemory * mem)
mem->impl->info.free (mem);
}
/**
* gst_memory_get_sizes:
* @mem: a #GstMemory
* @maxsize: pointer to maxsize
*
* Returns: the current size of @mem
*/
gsize
gst_memory_get_sizes (GstMemory * mem, gsize * maxsize)
{
@ -519,36 +576,3 @@ gst_memory_span (GstMemory ** mem1, gsize len1, gsize offset, GstMemory ** mem2,
}
return span;
}
GstMemory *
gst_memory_new_wrapped (GstMemoryFlags flags, gpointer data,
GFreeFunc free_func, gsize maxsize, gsize offset, gsize size)
{
GstMemoryDefault *mem;
mem = _default_mem_new (flags, NULL, data, free_func, maxsize, offset, size);
return (GstMemory *) mem;
}
GstMemory *
gst_memory_new_alloc (gsize maxsize, gsize align)
{
GstMemoryDefault *mem;
mem = _default_mem_new_block (maxsize, align, 0, maxsize);
return (GstMemory *) mem;
}
GstMemory *
gst_memory_new_copy (gsize maxsize, gsize align, gpointer data,
gsize offset, gsize size)
{
GstMemoryDefault *mem;
mem = _default_mem_new_block (maxsize, align, offset, size);
memcpy (mem->data, data, maxsize);
return (GstMemory *) mem;
}

View file

@ -280,16 +280,16 @@ create_and_fill_adapter (void)
for (i = 0; i < 10000; i += 4) {
GstBuffer *buf;
guint8 *data;
guint8 *data, *ptr;
buf = gst_buffer_new_and_alloc (sizeof (guint32) * 4);
fail_unless (buf != NULL);
data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE);
ptr = data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE);
for (j = 0; j < 4; j++) {
GST_WRITE_UINT32_LE (data, i + j);
data += sizeof (guint32);
GST_WRITE_UINT32_LE (ptr, i + j);
ptr += sizeof (guint32);
}
gst_buffer_unmap (buf, data, sizeof (guint32) * 4);