mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 03:35:21 +00:00
memory: more work on refcount and writability
Rename _is_writable() with _is_exclusive because the writability does not depend on the amount of references to the memory object anymore. Add accessor macros for the memory flags. Rename the GstBuffer _peek_memory() method to _get_memory() and return a reference to the memory now that we can do this without affecting writability of the memory object. Make it possible to also make this function merge the buffer memory. Add methods to replace memory in a buffer. Make some convience macros for the buffer memory functions. Fix unit tests.
This commit is contained in:
parent
88fdeb3ee7
commit
c6a1bed1ad
7 changed files with 181 additions and 152 deletions
208
gst/gstbuffer.c
208
gst/gstbuffer.c
|
@ -172,17 +172,46 @@ _span_memory (GstBuffer * buffer, gsize offset, gsize size, gboolean writable)
|
||||||
return span;
|
return span;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstMemory *
|
||||||
|
_get_merged_memory (GstBuffer * buffer)
|
||||||
|
{
|
||||||
|
guint len;
|
||||||
|
GstMemory *mem;
|
||||||
|
|
||||||
|
len = GST_BUFFER_MEM_LEN (buffer);
|
||||||
|
|
||||||
|
if (G_UNLIKELY (len == 0)) {
|
||||||
|
/* no memory */
|
||||||
|
mem = NULL;
|
||||||
|
} else if (G_LIKELY (len == 1)) {
|
||||||
|
/* we can take the first one */
|
||||||
|
mem = GST_BUFFER_MEM_PTR (buffer, 0);
|
||||||
|
gst_memory_ref (mem);
|
||||||
|
} else {
|
||||||
|
/* we need to span memory */
|
||||||
|
mem = _span_memory (buffer, 0, -1, FALSE);
|
||||||
|
}
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_replace_memory (GstBuffer * buffer, GstMemory * mem)
|
_replace_all_memory (GstBuffer * buffer, GstMemory * mem)
|
||||||
{
|
{
|
||||||
gsize len, i;
|
gsize len, i;
|
||||||
|
|
||||||
len = GST_BUFFER_MEM_LEN (buffer);
|
len = GST_BUFFER_MEM_LEN (buffer);
|
||||||
/* unref old buffers */
|
|
||||||
|
if (G_LIKELY (len == 1 && GST_BUFFER_MEM_PTR (buffer, 0) == mem)) {
|
||||||
|
gst_memory_unref (mem);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_LOG ("buffer %p replace with memory %p", buffer, mem);
|
||||||
|
|
||||||
|
/* unref old memory */
|
||||||
for (i = 0; i < len; i++)
|
for (i = 0; i < len; i++)
|
||||||
gst_memory_unref (GST_BUFFER_MEM_PTR (buffer, i));
|
gst_memory_unref (GST_BUFFER_MEM_PTR (buffer, i));
|
||||||
|
/* replace with single memory */
|
||||||
/* replace with single spanned buffer */
|
|
||||||
GST_BUFFER_MEM_PTR (buffer, 0) = mem;
|
GST_BUFFER_MEM_PTR (buffer, 0) = mem;
|
||||||
GST_BUFFER_MEM_LEN (buffer) = 1;
|
GST_BUFFER_MEM_LEN (buffer) = 1;
|
||||||
}
|
}
|
||||||
|
@ -199,7 +228,7 @@ _memory_add (GstBuffer * buffer, guint idx, GstMemory * mem)
|
||||||
* could try to only merge the two smallest buffers to avoid memcpy, etc. */
|
* could try to only merge the two smallest buffers to avoid memcpy, etc. */
|
||||||
GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "memory array overflow in buffer %p",
|
GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "memory array overflow in buffer %p",
|
||||||
buffer);
|
buffer);
|
||||||
_replace_memory (buffer, _span_memory (buffer, 0, -1, FALSE));
|
_replace_all_memory (buffer, _span_memory (buffer, 0, -1, FALSE));
|
||||||
/* we now have 1 single spanned buffer */
|
/* we now have 1 single spanned buffer */
|
||||||
len = 1;
|
len = 1;
|
||||||
}
|
}
|
||||||
|
@ -321,7 +350,7 @@ gst_buffer_copy_into (GstBuffer * dest, GstBuffer * src,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (flags & GST_BUFFER_COPY_MERGE) {
|
if (flags & GST_BUFFER_COPY_MERGE) {
|
||||||
_replace_memory (dest, _span_memory (dest, 0, size, FALSE));
|
_replace_all_memory (dest, _span_memory (dest, 0, size, FALSE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -584,7 +613,7 @@ gst_buffer_new_wrapped_full (gpointer data, GFreeFunc free_func, gsize offset,
|
||||||
GstBuffer *newbuf;
|
GstBuffer *newbuf;
|
||||||
|
|
||||||
newbuf = gst_buffer_new ();
|
newbuf = gst_buffer_new ();
|
||||||
gst_buffer_take_memory (newbuf, -1,
|
gst_buffer_append_memory (newbuf,
|
||||||
gst_memory_new_wrapped (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
|
gst_memory_new_wrapped (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
|
||||||
data, free_func, offset + size, offset, size));
|
data, free_func, offset + size, offset, size));
|
||||||
|
|
||||||
|
@ -647,67 +676,79 @@ gst_buffer_take_memory (GstBuffer * buffer, gint idx, GstMemory * mem)
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstMemory *
|
static GstMemory *
|
||||||
_get_memory (GstBuffer * buffer, guint idx, gboolean write)
|
_get_mapped (GstBuffer * buffer, guint idx, GstMapInfo * info,
|
||||||
|
GstMapFlags flags)
|
||||||
{
|
{
|
||||||
GstMemory *mem;
|
GstMemory *mem, *mapped;
|
||||||
|
|
||||||
mem = GST_BUFFER_MEM_PTR (buffer, idx);
|
mem = GST_BUFFER_MEM_PTR (buffer, idx);
|
||||||
|
|
||||||
if (G_UNLIKELY (write && !gst_memory_is_writable (mem))) {
|
mapped = gst_memory_make_mapped (mem, info, flags);
|
||||||
GstMemory *copy;
|
if (!mapped)
|
||||||
GST_CAT_LOG (GST_CAT_BUFFER,
|
return NULL;
|
||||||
"making writable copy of memory %p in buffer %p", mem, buffer);
|
|
||||||
/* replace with a writable copy */
|
if (mapped != mem) {
|
||||||
copy = gst_memory_copy (mem, 0, -1);
|
GST_BUFFER_MEM_PTR (buffer, idx) = mapped;
|
||||||
GST_BUFFER_MEM_PTR (buffer, idx) = copy;
|
|
||||||
gst_memory_unref (mem);
|
gst_memory_unref (mem);
|
||||||
mem = copy;
|
mem = mapped;
|
||||||
}
|
}
|
||||||
return mem;
|
return mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_buffer_peek_memory:
|
* gst_buffer_get_memory:
|
||||||
* @buffer: a #GstBuffer.
|
* @buffer: a #GstBuffer.
|
||||||
* @idx: an index
|
* @idx: an index
|
||||||
* @flags: #GstMapFlags
|
|
||||||
*
|
*
|
||||||
* Get the memory block in @buffer at @idx for memory access in @flags.
|
* Get the memory block in @buffer at @idx. If @idx is -1, all memory is merged
|
||||||
* This function does not return a refcount to the memory block. The memory
|
* into one large #GstMemory object that is then returned.
|
||||||
* block stays valid for as long as the caller has a valid reference to @buffer
|
|
||||||
* and as long as no operations that modify the memory blocks are called, such
|
|
||||||
* as gst_buffer_remove_memory_range(), gst_buffer_take_memory() and gst_buffer_resize().
|
|
||||||
*
|
*
|
||||||
* @buffer should be writable when @flags contains #GST_MAP_WRITE. If the memory
|
* Returns: (transfer full): a #GstMemory at @idx. Use gst_memory_unref () after usage.
|
||||||
* at @idx is not writable, a new writable copy will be installed in @buffer and
|
|
||||||
* returned.
|
|
||||||
*
|
|
||||||
* Returns: a #GstMemory at @idx.
|
|
||||||
*/
|
*/
|
||||||
GstMemory *
|
GstMemory *
|
||||||
gst_buffer_peek_memory (GstBuffer * buffer, guint idx, GstMapFlags flags)
|
gst_buffer_get_memory (GstBuffer * buffer, gint idx)
|
||||||
{
|
{
|
||||||
GstMemory *mem;
|
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 (GST_IS_BUFFER (buffer), NULL);
|
||||||
g_return_val_if_fail (idx < GST_BUFFER_MEM_LEN (buffer), NULL);
|
g_return_val_if_fail (idx == -1 ||
|
||||||
|
(idx >= 0 && 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 = _get_memory (buffer, idx, write);
|
|
||||||
|
|
||||||
|
if (idx == -1) {
|
||||||
|
mem = _get_merged_memory (buffer);
|
||||||
|
} else if ((mem = GST_BUFFER_MEM_PTR (buffer, idx))) {
|
||||||
|
gst_memory_ref (mem);
|
||||||
|
}
|
||||||
return mem;
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
/* ERRORS */
|
/**
|
||||||
not_writable:
|
* gst_buffer_replace_memory:
|
||||||
{
|
* @buffer: a #GstBuffer.
|
||||||
g_return_val_if_fail (gst_buffer_is_writable (buffer), NULL);
|
* @idx: an index
|
||||||
return NULL;
|
* @mem: (transfer full): a #GstMemory
|
||||||
|
*
|
||||||
|
* Replaces the memory block in @buffer at @idx with @mem. If @idx is -1, all
|
||||||
|
* memory will be removed and replaced with @mem.
|
||||||
|
*
|
||||||
|
* @buffer should be writable.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gst_buffer_replace_memory (GstBuffer * buffer, gint idx, GstMemory * mem)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GST_IS_BUFFER (buffer));
|
||||||
|
g_return_if_fail (gst_buffer_is_writable (buffer));
|
||||||
|
g_return_if_fail (idx == -1 ||
|
||||||
|
(idx >= 0 && idx < GST_BUFFER_MEM_LEN (buffer)));
|
||||||
|
|
||||||
|
if (idx == -1) {
|
||||||
|
_replace_all_memory (buffer, mem);
|
||||||
|
} else {
|
||||||
|
GstMemory *old;
|
||||||
|
|
||||||
|
if ((old = GST_BUFFER_MEM_PTR (buffer, idx)))
|
||||||
|
gst_memory_unref (old);
|
||||||
|
GST_BUFFER_MEM_PTR (buffer, idx) = mem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -722,7 +763,7 @@ not_writable:
|
||||||
* @length can be -1, in which case all memory starting from @idx is removed.
|
* @length can be -1, in which case all memory starting from @idx is removed.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
gst_buffer_remove_memory_range (GstBuffer * buffer, guint idx, guint length)
|
gst_buffer_remove_memory_range (GstBuffer * buffer, guint idx, gint length)
|
||||||
{
|
{
|
||||||
guint len, i, end;
|
guint len, i, end;
|
||||||
|
|
||||||
|
@ -730,10 +771,10 @@ gst_buffer_remove_memory_range (GstBuffer * buffer, guint idx, guint length)
|
||||||
g_return_if_fail (gst_buffer_is_writable (buffer));
|
g_return_if_fail (gst_buffer_is_writable (buffer));
|
||||||
|
|
||||||
len = GST_BUFFER_MEM_LEN (buffer);
|
len = GST_BUFFER_MEM_LEN (buffer);
|
||||||
if (length == -1) {
|
g_return_if_fail ((length == -1 && idx < len) || length + idx < len);
|
||||||
g_return_if_fail (idx < len);
|
|
||||||
|
if (length == -1)
|
||||||
length = len - idx;
|
length = len - idx;
|
||||||
}
|
|
||||||
|
|
||||||
end = idx + length;
|
end = idx + length;
|
||||||
for (i = idx; i < end; i++)
|
for (i = idx; i < end; i++)
|
||||||
|
@ -746,42 +787,6 @@ gst_buffer_remove_memory_range (GstBuffer * buffer, guint idx, guint length)
|
||||||
GST_BUFFER_MEM_LEN (buffer) = len - length;
|
GST_BUFFER_MEM_LEN (buffer) = len - length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* gst_buffer_get_merged_memory:
|
|
||||||
* @buffer: a #GstBuffer.
|
|
||||||
*
|
|
||||||
* Return a #GstMemory object that contains all the memory in @buffer. If there
|
|
||||||
* was only one memory in @buffer, it will be returned directly, otherwise all
|
|
||||||
* memory objects will be merged into one object that will be returned.
|
|
||||||
*
|
|
||||||
* Returns: a #GstMemory with the merged memory in @buffer. This function can
|
|
||||||
* return %NULL if there is no memory in @buffer. Use gst_memory_unref() after
|
|
||||||
* usage.
|
|
||||||
*/
|
|
||||||
static GstMemory *
|
|
||||||
gst_buffer_get_merged_memory (GstBuffer * buffer)
|
|
||||||
{
|
|
||||||
guint len;
|
|
||||||
GstMemory *mem;
|
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
|
|
||||||
|
|
||||||
len = GST_BUFFER_MEM_LEN (buffer);
|
|
||||||
|
|
||||||
if (G_UNLIKELY (len == 0)) {
|
|
||||||
/* no memory */
|
|
||||||
mem = NULL;
|
|
||||||
} else if (G_LIKELY (len == 1)) {
|
|
||||||
/* we can take the first one */
|
|
||||||
mem = GST_BUFFER_MEM_PTR (buffer, 0);
|
|
||||||
gst_memory_ref (mem);
|
|
||||||
} else {
|
|
||||||
/* we need to span memory */
|
|
||||||
mem = _span_memory (buffer, 0, -1, FALSE);
|
|
||||||
}
|
|
||||||
return mem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_buffer_get_sizes:
|
* gst_buffer_get_sizes:
|
||||||
* @buffer: a #GstBuffer.
|
* @buffer: a #GstBuffer.
|
||||||
|
@ -904,8 +909,7 @@ gst_buffer_resize (GstBuffer * buffer, gssize offset, gssize size)
|
||||||
left = MIN (bsize - offset, size);
|
left = MIN (bsize - offset, size);
|
||||||
|
|
||||||
if (offset != 0 || left != bsize) {
|
if (offset != 0 || left != bsize) {
|
||||||
/* we need to clip something */
|
if (gst_memory_is_exclusive (mem)) {
|
||||||
if (gst_memory_is_writable (mem)) {
|
|
||||||
gst_memory_resize (mem, offset, left);
|
gst_memory_resize (mem, offset, left);
|
||||||
} else {
|
} else {
|
||||||
GstMemory *tmp;
|
GstMemory *tmp;
|
||||||
|
@ -963,7 +967,7 @@ gst_buffer_map (GstBuffer * buffer, GstMapInfo * info, GstMapFlags flags)
|
||||||
if (G_UNLIKELY (write && !writable))
|
if (G_UNLIKELY (write && !writable))
|
||||||
goto not_writable;
|
goto not_writable;
|
||||||
|
|
||||||
mem = gst_buffer_get_merged_memory (buffer);
|
mem = _get_merged_memory (buffer);
|
||||||
if (G_UNLIKELY (mem == NULL))
|
if (G_UNLIKELY (mem == NULL))
|
||||||
goto no_memory;
|
goto no_memory;
|
||||||
|
|
||||||
|
@ -973,11 +977,13 @@ gst_buffer_map (GstBuffer * buffer, GstMapInfo * info, GstMapFlags flags)
|
||||||
goto cannot_map;
|
goto cannot_map;
|
||||||
|
|
||||||
/* if the buffer is writable, replace the memory */
|
/* if the buffer is writable, replace the memory */
|
||||||
if (writable)
|
if (writable) {
|
||||||
_replace_memory (buffer, gst_memory_ref (mem));
|
_replace_all_memory (buffer, gst_memory_ref (mem));
|
||||||
else if (GST_BUFFER_MEM_LEN (buffer) > 1) {
|
} else {
|
||||||
GST_CAT_DEBUG (GST_CAT_PERFORMANCE,
|
if (GST_BUFFER_MEM_LEN (buffer) > 1) {
|
||||||
"temporary mapping for memory %p in buffer %p", mem, buffer);
|
GST_CAT_DEBUG (GST_CAT_PERFORMANCE,
|
||||||
|
"temporary mapping for memory %p in buffer %p", mem, buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -1056,9 +1062,7 @@ gst_buffer_fill (GstBuffer * buffer, gsize offset, gconstpointer src,
|
||||||
gsize tocopy;
|
gsize tocopy;
|
||||||
GstMemory *mem;
|
GstMemory *mem;
|
||||||
|
|
||||||
mem = _get_memory (buffer, i, TRUE);
|
mem = _get_mapped (buffer, i, &info, GST_MAP_WRITE);
|
||||||
|
|
||||||
gst_memory_map (mem, &info, GST_MAP_WRITE);
|
|
||||||
if (info.size > offset) {
|
if (info.size > offset) {
|
||||||
/* we have enough */
|
/* we have enough */
|
||||||
tocopy = MIN (info.size - offset, left);
|
tocopy = MIN (info.size - offset, left);
|
||||||
|
@ -1104,9 +1108,7 @@ gst_buffer_extract (GstBuffer * buffer, gsize offset, gpointer dest, gsize size)
|
||||||
gsize tocopy;
|
gsize tocopy;
|
||||||
GstMemory *mem;
|
GstMemory *mem;
|
||||||
|
|
||||||
mem = GST_BUFFER_MEM_PTR (buffer, i);
|
mem = _get_mapped (buffer, i, &info, GST_MAP_READ);
|
||||||
|
|
||||||
gst_memory_map (mem, &info, GST_MAP_READ);
|
|
||||||
if (info.size > offset) {
|
if (info.size > offset) {
|
||||||
/* we have enough */
|
/* we have enough */
|
||||||
tocopy = MIN (info.size - offset, left);
|
tocopy = MIN (info.size - offset, left);
|
||||||
|
@ -1152,9 +1154,7 @@ gst_buffer_memcmp (GstBuffer * buffer, gsize offset, gconstpointer mem,
|
||||||
gsize tocmp;
|
gsize tocmp;
|
||||||
GstMemory *mem;
|
GstMemory *mem;
|
||||||
|
|
||||||
mem = GST_BUFFER_MEM_PTR (buffer, i);
|
mem = _get_mapped (buffer, i, &info, GST_MAP_READ);
|
||||||
|
|
||||||
gst_memory_map (mem, &info, GST_MAP_READ);
|
|
||||||
if (info.size > offset) {
|
if (info.size > offset) {
|
||||||
/* we have enough */
|
/* we have enough */
|
||||||
tocmp = MIN (info.size - offset, size);
|
tocmp = MIN (info.size - offset, size);
|
||||||
|
@ -1199,9 +1199,7 @@ gst_buffer_memset (GstBuffer * buffer, gsize offset, guint8 val, gsize size)
|
||||||
gsize toset;
|
gsize toset;
|
||||||
GstMemory *mem;
|
GstMemory *mem;
|
||||||
|
|
||||||
mem = _get_memory (buffer, i, TRUE);
|
mem = _get_mapped (buffer, i, &info, GST_MAP_WRITE);
|
||||||
|
|
||||||
gst_memory_map (mem, &info, GST_MAP_WRITE);
|
|
||||||
if (info.size > offset) {
|
if (info.size > offset) {
|
||||||
/* we have enough */
|
/* we have enough */
|
||||||
toset = MIN (info.size - offset, left);
|
toset = MIN (info.size - offset, left);
|
||||||
|
|
|
@ -265,9 +265,13 @@ GstBuffer * gst_buffer_new_wrapped (gpointer data, gsize size);
|
||||||
/* memory blocks */
|
/* memory blocks */
|
||||||
guint gst_buffer_n_memory (GstBuffer *buffer);
|
guint gst_buffer_n_memory (GstBuffer *buffer);
|
||||||
void gst_buffer_take_memory (GstBuffer *buffer, gint idx, GstMemory *mem);
|
void gst_buffer_take_memory (GstBuffer *buffer, gint idx, GstMemory *mem);
|
||||||
GstMemory * gst_buffer_peek_memory (GstBuffer *buffer, guint idx, GstMapFlags flags);
|
void gst_buffer_replace_memory (GstBuffer *buffer, gint idx, GstMemory *mem);
|
||||||
void gst_buffer_remove_memory_range (GstBuffer *buffer, guint idx, guint length);
|
GstMemory * gst_buffer_get_memory (GstBuffer *buffer, gint idx);
|
||||||
|
void gst_buffer_remove_memory_range (GstBuffer *buffer, guint idx, gint length);
|
||||||
|
|
||||||
|
#define gst_buffer_append_memory(b,m) gst_buffer_take_memory ((b), -1, (m))
|
||||||
|
#define gst_buffer_replace_all_memory(b,m) gst_buffer_replace_memory ((b), -1, (m))
|
||||||
|
#define gst_buffer_get_merged_memory(b) gst_buffer_get_memory ((b), -1)
|
||||||
/**
|
/**
|
||||||
* gst_buffer_remove_memory:
|
* gst_buffer_remove_memory:
|
||||||
* @b: a #GstBuffer.
|
* @b: a #GstBuffer.
|
||||||
|
@ -275,7 +279,8 @@ void gst_buffer_remove_memory_range (GstBuffer *buffer, guint idx, guint
|
||||||
*
|
*
|
||||||
* Remove the memory block in @b at @i.
|
* Remove the memory block in @b at @i.
|
||||||
*/
|
*/
|
||||||
#define gst_buffer_remove_memory(b,i) gst_buffer_remove_memory_range ((b), (i), 1)
|
#define gst_buffer_remove_memory(b,i) gst_buffer_remove_memory_range ((b), (i), 1)
|
||||||
|
#define gst_buffer_remove_all_memory(b) gst_buffer_remove_memory_range ((b), 0, -1)
|
||||||
|
|
||||||
gsize gst_buffer_fill (GstBuffer *buffer, gsize offset,
|
gsize gst_buffer_fill (GstBuffer *buffer, gsize offset,
|
||||||
gconstpointer src, gsize size);
|
gconstpointer src, gsize size);
|
||||||
|
|
|
@ -135,7 +135,7 @@ _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 = (flags & GST_MEMORY_FLAG_READONLY ? 0x5 : 0);
|
mem->mem.state = (flags & GST_MEMORY_FLAG_READONLY ? 0x1 : 0);
|
||||||
mem->mem.maxsize = maxsize;
|
mem->mem.maxsize = maxsize;
|
||||||
mem->mem.offset = offset;
|
mem->mem.offset = offset;
|
||||||
mem->mem.size = size;
|
mem->mem.size = size;
|
||||||
|
@ -431,6 +431,7 @@ gst_memory_unref (GstMemory * mem)
|
||||||
mem->refcount - 1);
|
mem->refcount - 1);
|
||||||
|
|
||||||
if (g_atomic_int_dec_and_test (&mem->refcount)) {
|
if (g_atomic_int_dec_and_test (&mem->refcount)) {
|
||||||
|
g_return_if_fail (g_atomic_int_get (&mem->state) < 4);
|
||||||
#ifndef GST_DISABLE_TRACE
|
#ifndef GST_DISABLE_TRACE
|
||||||
_gst_alloc_trace_free (_gst_memory_trace, mem);
|
_gst_alloc_trace_free (_gst_memory_trace, mem);
|
||||||
#endif
|
#endif
|
||||||
|
@ -438,6 +439,21 @@ gst_memory_unref (GstMemory * mem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_memory_is_exclusive:
|
||||||
|
* @mem: a #GstMemory
|
||||||
|
*
|
||||||
|
* Check if the current ref to @mem is exclusive, this means that no other
|
||||||
|
* references exist other than @mem.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gst_memory_is_exclusive (GstMemory * mem)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (mem != NULL, FALSE);
|
||||||
|
|
||||||
|
return (g_atomic_int_get (&mem->refcount) == 1);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_memory_get_sizes:
|
* gst_memory_get_sizes:
|
||||||
* @mem: a #GstMemory
|
* @mem: a #GstMemory
|
||||||
|
@ -474,7 +490,6 @@ void
|
||||||
gst_memory_resize (GstMemory * mem, gssize offset, gsize size)
|
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 (offset >= 0 || mem->offset >= -offset);
|
g_return_if_fail (offset >= 0 || mem->offset >= -offset);
|
||||||
g_return_if_fail (size + mem->offset + offset <= mem->maxsize);
|
g_return_if_fail (size + mem->offset + offset <= mem->maxsize);
|
||||||
|
|
||||||
|
@ -482,24 +497,6 @@ gst_memory_resize (GstMemory * mem, gssize offset, gsize size)
|
||||||
mem->size = size;
|
mem->size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* gst_memory_is_writable:
|
|
||||||
* @mem: a #GstMemory
|
|
||||||
*
|
|
||||||
* Check if @mem is writable.
|
|
||||||
*
|
|
||||||
* Returns: %TRUE is @mem is writable.
|
|
||||||
*/
|
|
||||||
gboolean
|
|
||||||
gst_memory_is_writable (GstMemory * mem)
|
|
||||||
{
|
|
||||||
g_return_val_if_fail (mem != NULL, FALSE);
|
|
||||||
|
|
||||||
return (mem->refcount == 1) &&
|
|
||||||
((mem->parent == NULL) || (mem->parent->refcount == 1)) &&
|
|
||||||
((mem->flags & GST_MEMORY_FLAG_READONLY) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_memory_lock (GstMemory * mem, GstMapFlags flags)
|
gst_memory_lock (GstMemory * mem, GstMapFlags flags)
|
||||||
{
|
{
|
||||||
|
@ -610,8 +607,8 @@ cannot_map:
|
||||||
* - the memory backed by @mem is not accessible with the given @flags.
|
* - the memory backed by @mem is not accessible with the given @flags.
|
||||||
* - the memory was already mapped with a different mapping.
|
* - the memory was already mapped with a different mapping.
|
||||||
*
|
*
|
||||||
* @info and its contents remains valid for as long as @mem is alive and until
|
* @info and its contents remain valid for as long as @mem is valid and
|
||||||
* gst_memory_unmap() is called.
|
* until gst_memory_unmap() is called.
|
||||||
*
|
*
|
||||||
* For each gst_memory_map() call, a corresponding gst_memory_unmap() call
|
* For each gst_memory_map() call, a corresponding gst_memory_unmap() call
|
||||||
* should be done.
|
* should be done.
|
||||||
|
@ -722,6 +719,8 @@ gst_memory_share (GstMemory * mem, gssize offset, gssize size)
|
||||||
GstMemory *shared;
|
GstMemory *shared;
|
||||||
|
|
||||||
g_return_val_if_fail (mem != NULL, NULL);
|
g_return_val_if_fail (mem != NULL, NULL);
|
||||||
|
g_return_val_if_fail (!GST_MEMORY_FLAG_IS_SET (mem, GST_MEMORY_FLAG_NO_SHARE),
|
||||||
|
NULL);
|
||||||
|
|
||||||
shared = mem->allocator->info.mem_share (mem, offset, size);
|
shared = mem->allocator->info.mem_share (mem, offset, size);
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,8 @@ typedef struct _GstAllocator GstAllocator;
|
||||||
|
|
||||||
GST_EXPORT gsize gst_memory_alignment;
|
GST_EXPORT gsize gst_memory_alignment;
|
||||||
|
|
||||||
|
#define GST_MEMORY_CAST(mem) ((GstMemory *)(mem))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstMemoryFlags:
|
* GstMemoryFlags:
|
||||||
* @GST_MEMORY_FLAG_READONLY: memory is readonly. It is not allowed to map the
|
* @GST_MEMORY_FLAG_READONLY: memory is readonly. It is not allowed to map the
|
||||||
|
@ -58,6 +60,30 @@ typedef enum {
|
||||||
GST_MEMORY_FLAG_LAST = (1 << 16)
|
GST_MEMORY_FLAG_LAST = (1 << 16)
|
||||||
} GstMemoryFlags;
|
} GstMemoryFlags;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GST_MEMORY_FLAGS:
|
||||||
|
* @mem: a #GstMemory.
|
||||||
|
*
|
||||||
|
* A flags word containing #GstMemoryFlags flags set on @mem
|
||||||
|
*/
|
||||||
|
#define GST_MEMORY_FLAGS(mem) (GST_MEMORY_CAST (mem)->flags)
|
||||||
|
/**
|
||||||
|
* GST_MEMORY_FLAG_IS_SET:
|
||||||
|
* @mem: a #GstMemory.
|
||||||
|
* @flag: the #GstMemoryFlags to check.
|
||||||
|
*
|
||||||
|
* Gives the status of a specific flag on a @mem.
|
||||||
|
*/
|
||||||
|
#define GST_MEMORY_FLAG_IS_SET(mem,flag) !!(GST_MEMORY_FLAGS (mem) & (flag))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GST_MEMORY_IS_READONLY:
|
||||||
|
* @mem: a #GstMemory.
|
||||||
|
*
|
||||||
|
* Check if @mem is readonly.
|
||||||
|
*/
|
||||||
|
#define GST_MEMORY_IS_READONLY(mem) GST_MEMORY_FLAG_IS_SET(mem,GST_MEMORY_FLAG_READONLY)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstMemory:
|
* GstMemory:
|
||||||
* @allocator: pointer to the #GstAllocator
|
* @allocator: pointer to the #GstAllocator
|
||||||
|
@ -278,30 +304,30 @@ void gst_allocator_set_default (GstAllocator * allocator);
|
||||||
GstMemory * gst_allocator_alloc (GstAllocator * allocator,
|
GstMemory * gst_allocator_alloc (GstAllocator * allocator,
|
||||||
gsize maxsize, gsize align);
|
gsize maxsize, gsize align);
|
||||||
|
|
||||||
GstMemory * gst_memory_new_wrapped (GstMemoryFlags flags, gpointer data, GFreeFunc free_func,
|
GstMemory * gst_memory_new_wrapped (GstMemoryFlags flags, gpointer data, GFreeFunc free_func,
|
||||||
gsize maxsize, gsize offset, gsize size);
|
gsize maxsize, gsize offset, gsize size);
|
||||||
|
|
||||||
/* refcounting */
|
/* refcounting */
|
||||||
GstMemory * gst_memory_ref (GstMemory *mem);
|
GstMemory * gst_memory_ref (GstMemory *mem);
|
||||||
void gst_memory_unref (GstMemory *mem);
|
void gst_memory_unref (GstMemory *mem);
|
||||||
|
|
||||||
|
gboolean gst_memory_is_exclusive (GstMemory *mem);
|
||||||
|
|
||||||
/* getting/setting memory properties */
|
/* getting/setting memory properties */
|
||||||
gsize gst_memory_get_sizes (GstMemory *mem, gsize *offset, gsize *maxsize);
|
gsize gst_memory_get_sizes (GstMemory *mem, gsize *offset, gsize *maxsize);
|
||||||
void gst_memory_resize (GstMemory *mem, gssize offset, gsize size);
|
void gst_memory_resize (GstMemory *mem, gssize offset, gsize size);
|
||||||
|
|
||||||
/* retrieving data */
|
/* retrieving data */
|
||||||
gboolean gst_memory_is_writable (GstMemory *mem);
|
GstMemory * gst_memory_make_mapped (GstMemory *mem, GstMapInfo *info, GstMapFlags flags);
|
||||||
|
gboolean gst_memory_map (GstMemory *mem, GstMapInfo *info, GstMapFlags flags);
|
||||||
GstMemory * gst_memory_make_mapped (GstMemory *mem, GstMapInfo *info, GstMapFlags flags);
|
void gst_memory_unmap (GstMemory *mem, GstMapInfo *info);
|
||||||
gboolean gst_memory_map (GstMemory *mem, GstMapInfo *info, GstMapFlags flags);
|
|
||||||
void gst_memory_unmap (GstMemory *mem, GstMapInfo *info);
|
|
||||||
|
|
||||||
/* 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);
|
||||||
GstMemory * gst_memory_share (GstMemory *mem, gssize offset, gssize size);
|
GstMemory * gst_memory_share (GstMemory *mem, gssize offset, gssize size);
|
||||||
|
|
||||||
/* span memory */
|
/* span memory */
|
||||||
gboolean gst_memory_is_span (GstMemory *mem1, GstMemory *mem2, gsize *offset);
|
gboolean gst_memory_is_span (GstMemory *mem1, GstMemory *mem2, gsize *offset);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
|
|
@ -450,8 +450,9 @@ GST_START_TEST (test_size)
|
||||||
fail_unless (offset == 0);
|
fail_unless (offset == 0);
|
||||||
fail_unless (maxalloc >= 100);
|
fail_unless (maxalloc >= 100);
|
||||||
|
|
||||||
mem = gst_buffer_peek_memory (buf, 0, GST_MAP_WRITE);
|
mem = gst_buffer_get_memory (buf, 0);
|
||||||
gst_memory_resize (mem, 10, 70);
|
gst_memory_resize (mem, 10, 70);
|
||||||
|
gst_memory_unref (mem);
|
||||||
|
|
||||||
size = gst_buffer_get_sizes (buf, &offset, &maxsize);
|
size = gst_buffer_get_sizes (buf, &offset, &maxsize);
|
||||||
fail_unless (size == 70);
|
fail_unless (size == 70);
|
||||||
|
|
|
@ -133,7 +133,7 @@ create_read_only_memory (void)
|
||||||
/* assign some read-only data to the new memory */
|
/* assign some read-only data to the new memory */
|
||||||
mem = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
|
mem = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
|
||||||
(gpointer) ro_memory, NULL, sizeof (ro_memory), 0, sizeof (ro_memory));
|
(gpointer) ro_memory, NULL, sizeof (ro_memory), 0, sizeof (ro_memory));
|
||||||
fail_if (gst_memory_is_writable (mem));
|
fail_unless (GST_MEMORY_IS_READONLY (mem));
|
||||||
|
|
||||||
return mem;
|
return mem;
|
||||||
}
|
}
|
||||||
|
@ -147,11 +147,10 @@ GST_START_TEST (test_writable)
|
||||||
mem = create_read_only_memory ();
|
mem = create_read_only_memory ();
|
||||||
|
|
||||||
fail_if (gst_memory_map (mem, &info, GST_MAP_WRITE));
|
fail_if (gst_memory_map (mem, &info, GST_MAP_WRITE));
|
||||||
fail_if (gst_memory_is_writable (mem));
|
|
||||||
|
|
||||||
mem2 = gst_memory_copy (mem, 0, -1);
|
mem2 = gst_memory_copy (mem, 0, -1);
|
||||||
fail_if (gst_memory_is_writable (mem));
|
fail_unless (GST_MEMORY_IS_READONLY (mem));
|
||||||
fail_unless (gst_memory_is_writable (mem2));
|
fail_if (GST_MEMORY_IS_READONLY (mem2));
|
||||||
|
|
||||||
fail_unless (gst_memory_map (mem2, &info, GST_MAP_WRITE));
|
fail_unless (gst_memory_map (mem2, &info, GST_MAP_WRITE));
|
||||||
info.data[4] = 'a';
|
info.data[4] = 'a';
|
||||||
|
@ -180,7 +179,7 @@ GST_START_TEST (test_submemory_writable)
|
||||||
mem = create_read_only_memory ();
|
mem = create_read_only_memory ();
|
||||||
|
|
||||||
sub_mem = gst_memory_share (mem, 0, 8);
|
sub_mem = gst_memory_share (mem, 0, 8);
|
||||||
fail_if (gst_memory_is_writable (sub_mem));
|
fail_unless (GST_MEMORY_IS_READONLY (sub_mem));
|
||||||
|
|
||||||
fail_if (gst_memory_map (mem, &info, GST_MAP_WRITE));
|
fail_if (gst_memory_map (mem, &info, GST_MAP_WRITE));
|
||||||
fail_if (gst_memory_map (sub_mem, &info, GST_MAP_WRITE));
|
fail_if (gst_memory_map (sub_mem, &info, GST_MAP_WRITE));
|
||||||
|
|
|
@ -90,6 +90,7 @@ EXPORTS
|
||||||
gst_buffer_fill
|
gst_buffer_fill
|
||||||
gst_buffer_flags_get_type
|
gst_buffer_flags_get_type
|
||||||
gst_buffer_foreach_meta
|
gst_buffer_foreach_meta
|
||||||
|
gst_buffer_get_memory
|
||||||
gst_buffer_get_meta
|
gst_buffer_get_meta
|
||||||
gst_buffer_get_sizes
|
gst_buffer_get_sizes
|
||||||
gst_buffer_get_type
|
gst_buffer_get_type
|
||||||
|
@ -113,7 +114,6 @@ EXPORTS
|
||||||
gst_buffer_new_allocate
|
gst_buffer_new_allocate
|
||||||
gst_buffer_new_wrapped
|
gst_buffer_new_wrapped
|
||||||
gst_buffer_new_wrapped_full
|
gst_buffer_new_wrapped_full
|
||||||
gst_buffer_peek_memory
|
|
||||||
gst_buffer_pool_acquire_buffer
|
gst_buffer_pool_acquire_buffer
|
||||||
gst_buffer_pool_config_add_option
|
gst_buffer_pool_config_add_option
|
||||||
gst_buffer_pool_config_get
|
gst_buffer_pool_config_get
|
||||||
|
@ -133,6 +133,7 @@ EXPORTS
|
||||||
gst_buffer_pool_set_config
|
gst_buffer_pool_set_config
|
||||||
gst_buffer_remove_memory_range
|
gst_buffer_remove_memory_range
|
||||||
gst_buffer_remove_meta
|
gst_buffer_remove_meta
|
||||||
|
gst_buffer_replace_memory
|
||||||
gst_buffer_resize
|
gst_buffer_resize
|
||||||
gst_buffer_span
|
gst_buffer_span
|
||||||
gst_buffer_take_memory
|
gst_buffer_take_memory
|
||||||
|
@ -507,8 +508,8 @@ EXPORTS
|
||||||
gst_memory_flags_get_type
|
gst_memory_flags_get_type
|
||||||
gst_memory_get_sizes
|
gst_memory_get_sizes
|
||||||
gst_memory_get_type
|
gst_memory_get_type
|
||||||
|
gst_memory_is_exclusive
|
||||||
gst_memory_is_span
|
gst_memory_is_span
|
||||||
gst_memory_is_writable
|
|
||||||
gst_memory_make_mapped
|
gst_memory_make_mapped
|
||||||
gst_memory_map
|
gst_memory_map
|
||||||
gst_memory_new_wrapped
|
gst_memory_new_wrapped
|
||||||
|
|
Loading…
Reference in a new issue