mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 12:11:13 +00:00
buffer: fix negative offsets some more
Allow for negative offsets when doing memory copy and share. Add fast path in the _get_sizes() function. Fix resize for negative offset and expanding the buffer. Add some unit tests.
This commit is contained in:
parent
0849cae4a8
commit
8461249f22
4 changed files with 129 additions and 34 deletions
|
@ -761,36 +761,46 @@ gst_buffer_remove_memory_range (GstBuffer * buffer, guint idx, guint length)
|
||||||
gsize
|
gsize
|
||||||
gst_buffer_get_sizes (GstBuffer * buffer, gsize * offset, gsize * maxsize)
|
gst_buffer_get_sizes (GstBuffer * buffer, gsize * offset, gsize * maxsize)
|
||||||
{
|
{
|
||||||
guint i, len;
|
guint len;
|
||||||
gsize extra, size, offs;
|
gsize size;
|
||||||
|
GstMemory *mem;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
|
g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
|
||||||
|
|
||||||
len = GST_BUFFER_MEM_LEN (buffer);
|
len = GST_BUFFER_MEM_LEN (buffer);
|
||||||
|
|
||||||
size = offs = extra = 0;
|
if (G_LIKELY (len == 1)) {
|
||||||
for (i = 0; i < len; i++) {
|
/* common case */
|
||||||
gsize s, o, ms;
|
mem = GST_BUFFER_MEM_PTR (buffer, 0);
|
||||||
|
size = gst_memory_get_sizes (mem, offset, maxsize);
|
||||||
|
} else {
|
||||||
|
guint i;
|
||||||
|
gsize extra, offs;
|
||||||
|
|
||||||
s = gst_memory_get_sizes (GST_BUFFER_MEM_PTR (buffer, i), &o, &ms);
|
size = offs = extra = 0;
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
gsize s, o, ms;
|
||||||
|
|
||||||
/* add sizes */
|
mem = GST_BUFFER_MEM_PTR (buffer, i);
|
||||||
size += s;
|
s = gst_memory_get_sizes (mem, &o, &ms);
|
||||||
|
|
||||||
/* keep offset of first memory block */
|
/* add sizes */
|
||||||
if (i == 0)
|
size += s;
|
||||||
offs = o;
|
|
||||||
/* this is the amount of extra bytes in this block, we only keep this for
|
/* keep offset of first memory block */
|
||||||
* the last block */
|
if (i == 0)
|
||||||
else if (i + 1 == len)
|
offs = o;
|
||||||
extra = ms - (o + s);
|
/* this is the amount of extra bytes in this block, we only keep this for
|
||||||
|
* the last block */
|
||||||
|
if (i + 1 == len)
|
||||||
|
extra = ms - (o + s);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset)
|
||||||
|
*offset = offs;
|
||||||
|
if (maxsize)
|
||||||
|
*maxsize = offs + size + extra;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset)
|
|
||||||
*offset = offs;
|
|
||||||
if (maxsize)
|
|
||||||
*maxsize = offs + size + extra;
|
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -810,7 +820,7 @@ gst_buffer_resize (GstBuffer * buffer, gssize offset, gsize size)
|
||||||
gsize bsize, bufsize, bufoffs, bufmax;
|
gsize bsize, bufsize, bufoffs, bufmax;
|
||||||
GstMemory *mem;
|
GstMemory *mem;
|
||||||
|
|
||||||
GST_CAT_LOG (GST_CAT_BUFFER, "trim %p %" G_GSIZE_FORMAT "-%" G_GSIZE_FORMAT,
|
GST_CAT_LOG (GST_CAT_BUFFER, "trim %p %" G_GSSIZE_FORMAT "-%" G_GSIZE_FORMAT,
|
||||||
buffer, offset, size);
|
buffer, offset, size);
|
||||||
|
|
||||||
g_return_if_fail (gst_buffer_is_writable (buffer));
|
g_return_if_fail (gst_buffer_is_writable (buffer));
|
||||||
|
@ -834,15 +844,20 @@ gst_buffer_resize (GstBuffer * buffer, gssize offset, gsize size)
|
||||||
mem = GST_BUFFER_MEM_PTR (buffer, si);
|
mem = GST_BUFFER_MEM_PTR (buffer, si);
|
||||||
bsize = gst_memory_get_sizes (mem, NULL, NULL);
|
bsize = gst_memory_get_sizes (mem, NULL, NULL);
|
||||||
|
|
||||||
if (bsize <= offset) {
|
if ((gssize) bsize <= offset) {
|
||||||
/* remove buffer */
|
/* remove buffer */
|
||||||
gst_memory_unref (mem);
|
gst_memory_unref (mem);
|
||||||
offset -= bsize;
|
offset -= bsize;
|
||||||
} else {
|
} else {
|
||||||
gsize left;
|
gsize left;
|
||||||
|
|
||||||
left = MIN (bsize - offset, size);
|
/* last buffer always gets resized to the remaining size */
|
||||||
if (left < bsize) {
|
if (si + 1 == len)
|
||||||
|
left = size;
|
||||||
|
else
|
||||||
|
left = MIN (bsize - offset, size);
|
||||||
|
|
||||||
|
if (left) {
|
||||||
/* we need to clip something */
|
/* we need to clip something */
|
||||||
if (GST_MEMORY_IS_WRITABLE (mem)) {
|
if (GST_MEMORY_IS_WRITABLE (mem)) {
|
||||||
gst_memory_resize (mem, offset, left);
|
gst_memory_resize (mem, offset, left);
|
||||||
|
|
|
@ -228,7 +228,7 @@ _default_mem_free (GstMemoryDefault * mem)
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstMemoryDefault *
|
static GstMemoryDefault *
|
||||||
_default_mem_copy (GstMemoryDefault * mem, gsize offset, gsize size)
|
_default_mem_copy (GstMemoryDefault * mem, gssize offset, gsize size)
|
||||||
{
|
{
|
||||||
GstMemoryDefault *copy;
|
GstMemoryDefault *copy;
|
||||||
|
|
||||||
|
@ -242,7 +242,7 @@ _default_mem_copy (GstMemoryDefault * mem, gsize offset, gsize size)
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstMemoryDefault *
|
static GstMemoryDefault *
|
||||||
_default_mem_share (GstMemoryDefault * mem, gsize offset, gsize size)
|
_default_mem_share (GstMemoryDefault * mem, gssize offset, gsize size)
|
||||||
{
|
{
|
||||||
GstMemoryDefault *sub;
|
GstMemoryDefault *sub;
|
||||||
GstMemory *parent;
|
GstMemory *parent;
|
||||||
|
@ -278,7 +278,7 @@ _default_mem_is_span (GstMemoryDefault * mem1, GstMemoryDefault * mem2,
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstMemory *
|
static GstMemory *
|
||||||
_fallback_copy (GstMemory * mem, gsize offset, gsize size)
|
_fallback_copy (GstMemory * mem, gssize offset, gsize size)
|
||||||
{
|
{
|
||||||
GstMemory *copy;
|
GstMemory *copy;
|
||||||
guint8 *data, *dest;
|
guint8 *data, *dest;
|
||||||
|
@ -492,7 +492,7 @@ gst_memory_unmap (GstMemory * mem, gpointer data, gsize size)
|
||||||
* Returns: a new #GstMemory.
|
* Returns: a new #GstMemory.
|
||||||
*/
|
*/
|
||||||
GstMemory *
|
GstMemory *
|
||||||
gst_memory_copy (GstMemory * mem, gsize offset, gsize size)
|
gst_memory_copy (GstMemory * mem, gssize offset, gsize size)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (mem != NULL, NULL);
|
g_return_val_if_fail (mem != NULL, NULL);
|
||||||
|
|
||||||
|
@ -513,7 +513,7 @@ gst_memory_copy (GstMemory * mem, gsize offset, gsize size)
|
||||||
* Returns: a new #GstMemory.
|
* Returns: a new #GstMemory.
|
||||||
*/
|
*/
|
||||||
GstMemory *
|
GstMemory *
|
||||||
gst_memory_share (GstMemory * mem, gsize offset, gsize size)
|
gst_memory_share (GstMemory * mem, gssize offset, gsize size)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (mem != NULL, NULL);
|
g_return_val_if_fail (mem != NULL, NULL);
|
||||||
|
|
||||||
|
|
|
@ -204,7 +204,7 @@ typedef void (*GstMemoryFreeFunction) (GstMemory *mem);
|
||||||
* Returns: a new #GstMemory object wrapping a copy of the requested region in
|
* Returns: a new #GstMemory object wrapping a copy of the requested region in
|
||||||
* @mem.
|
* @mem.
|
||||||
*/
|
*/
|
||||||
typedef GstMemory * (*GstMemoryCopyFunction) (GstMemory *mem, gsize offset, gsize size);
|
typedef GstMemory * (*GstMemoryCopyFunction) (GstMemory *mem, gssize offset, gsize size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstMemoryShareFunction:
|
* GstMemoryShareFunction:
|
||||||
|
@ -218,7 +218,7 @@ typedef GstMemory * (*GstMemoryCopyFunction) (GstMemory *mem, gsize offset,
|
||||||
*
|
*
|
||||||
* Returns: a new #GstMemory object sharing the requested region in @mem.
|
* Returns: a new #GstMemory object sharing the requested region in @mem.
|
||||||
*/
|
*/
|
||||||
typedef GstMemory * (*GstMemoryShareFunction) (GstMemory *mem, gsize offset, gsize size);
|
typedef GstMemory * (*GstMemoryShareFunction) (GstMemory *mem, gssize offset, gsize size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstMemoryIsSpanFunction:
|
* GstMemoryIsSpanFunction:
|
||||||
|
@ -293,8 +293,8 @@ gpointer gst_memory_map (GstMemory *mem, gsize *size, gsize *maxsize,
|
||||||
gboolean gst_memory_unmap (GstMemory *mem, gpointer data, gsize size);
|
gboolean gst_memory_unmap (GstMemory *mem, gpointer data, gsize size);
|
||||||
|
|
||||||
/* copy and subregions */
|
/* copy and subregions */
|
||||||
GstMemory * gst_memory_copy (GstMemory *mem, gsize offset, gsize size);
|
GstMemory * gst_memory_copy (GstMemory *mem, gssize offset, gsize size);
|
||||||
GstMemory * gst_memory_share (GstMemory *mem, gsize offset, gsize size);
|
GstMemory * gst_memory_share (GstMemory *mem, gssize offset, gsize 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);
|
||||||
|
|
|
@ -441,6 +441,85 @@ GST_START_TEST (test_try_new_and_alloc)
|
||||||
|
|
||||||
GST_END_TEST;
|
GST_END_TEST;
|
||||||
|
|
||||||
|
GST_START_TEST (test_resize)
|
||||||
|
{
|
||||||
|
GstBuffer *buf;
|
||||||
|
gsize maxalloc;
|
||||||
|
gsize size, maxsize, offset;
|
||||||
|
|
||||||
|
/* one memory block */
|
||||||
|
buf = gst_buffer_new_allocate (NULL, 100, 0);
|
||||||
|
|
||||||
|
size = gst_buffer_get_sizes (buf, &offset, &maxalloc);
|
||||||
|
fail_unless (size == 100);
|
||||||
|
fail_unless (offset == 0);
|
||||||
|
fail_unless (maxalloc >= 100);
|
||||||
|
|
||||||
|
ASSERT_CRITICAL (gst_buffer_resize (buf, 200, 50));
|
||||||
|
ASSERT_CRITICAL (gst_buffer_resize (buf, 0, 150));
|
||||||
|
ASSERT_CRITICAL (gst_buffer_resize (buf, 1, maxalloc));
|
||||||
|
ASSERT_CRITICAL (gst_buffer_resize (buf, maxalloc, 1));
|
||||||
|
|
||||||
|
/* this does nothing */
|
||||||
|
gst_buffer_resize (buf, 0, 100);
|
||||||
|
|
||||||
|
/* nothing should have changed */
|
||||||
|
size = gst_buffer_get_sizes (buf, &offset, &maxsize);
|
||||||
|
fail_unless (size == 100);
|
||||||
|
fail_unless (offset == 0);
|
||||||
|
fail_unless (maxsize == maxalloc);
|
||||||
|
|
||||||
|
gst_buffer_resize (buf, 0, 50);
|
||||||
|
size = gst_buffer_get_sizes (buf, &offset, &maxsize);
|
||||||
|
fail_unless (size == 50);
|
||||||
|
fail_unless (offset == 0);
|
||||||
|
fail_unless (maxsize == maxalloc);
|
||||||
|
|
||||||
|
gst_buffer_resize (buf, 0, 100);
|
||||||
|
size = gst_buffer_get_sizes (buf, &offset, &maxsize);
|
||||||
|
fail_unless (size == 100);
|
||||||
|
fail_unless (offset == 0);
|
||||||
|
fail_unless (maxsize == maxalloc);
|
||||||
|
|
||||||
|
gst_buffer_resize (buf, 1, 99);
|
||||||
|
size = gst_buffer_get_sizes (buf, &offset, &maxsize);
|
||||||
|
fail_unless (size == 99);
|
||||||
|
fail_unless (offset == 1);
|
||||||
|
fail_unless (maxsize == maxalloc);
|
||||||
|
|
||||||
|
ASSERT_CRITICAL (gst_buffer_resize (buf, 1, maxalloc - 1));
|
||||||
|
|
||||||
|
gst_buffer_resize (buf, 0, 99);
|
||||||
|
size = gst_buffer_get_sizes (buf, &offset, &maxsize);
|
||||||
|
fail_unless (size == 99);
|
||||||
|
fail_unless (offset == 1);
|
||||||
|
fail_unless (maxsize == maxalloc);
|
||||||
|
|
||||||
|
gst_buffer_resize (buf, -1, 100);
|
||||||
|
size = gst_buffer_get_sizes (buf, &offset, &maxsize);
|
||||||
|
fail_unless (size == 100);
|
||||||
|
fail_unless (offset == 0);
|
||||||
|
fail_unless (maxsize == maxalloc);
|
||||||
|
|
||||||
|
ASSERT_CRITICAL (gst_buffer_resize (buf, -1, 100));
|
||||||
|
|
||||||
|
gst_buffer_resize (buf, 50, 40);
|
||||||
|
size = gst_buffer_get_sizes (buf, &offset, &maxsize);
|
||||||
|
fail_unless (size == 40);
|
||||||
|
fail_unless (offset == 50);
|
||||||
|
fail_unless (maxsize == maxalloc);
|
||||||
|
|
||||||
|
gst_buffer_resize (buf, -50, 100);
|
||||||
|
size = gst_buffer_get_sizes (buf, &offset, &maxsize);
|
||||||
|
fail_unless (size == 100);
|
||||||
|
fail_unless (offset == 0);
|
||||||
|
fail_unless (maxsize == maxalloc);
|
||||||
|
|
||||||
|
gst_buffer_unref (buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
static Suite *
|
static Suite *
|
||||||
gst_buffer_suite (void)
|
gst_buffer_suite (void)
|
||||||
{
|
{
|
||||||
|
@ -456,6 +535,7 @@ gst_buffer_suite (void)
|
||||||
tcase_add_test (tc_chain, test_metadata_writable);
|
tcase_add_test (tc_chain, test_metadata_writable);
|
||||||
tcase_add_test (tc_chain, test_copy);
|
tcase_add_test (tc_chain, test_copy);
|
||||||
tcase_add_test (tc_chain, test_try_new_and_alloc);
|
tcase_add_test (tc_chain, test_try_new_and_alloc);
|
||||||
|
tcase_add_test (tc_chain, test_resize);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue