mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-02 08:42:32 +00:00
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:
parent
38ffe30745
commit
6f2af5aa87
3 changed files with 184 additions and 71 deletions
105
gst/gstbuffer.c
105
gst/gstbuffer.c
|
@ -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)
|
||||
{
|
||||
|
|
142
gst/gstmemory.c
142
gst/gstmemory.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue