mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 18:21:04 +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
|
||||
gst_buffer_get_sizes (GstBuffer * buffer, gsize * offset, gsize * maxsize)
|
||||
{
|
||||
guint i, len;
|
||||
gsize extra, size, offs;
|
||||
guint len;
|
||||
gsize size;
|
||||
GstMemory *mem;
|
||||
|
||||
g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
|
||||
|
||||
len = GST_BUFFER_MEM_LEN (buffer);
|
||||
|
||||
size = offs = extra = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
gsize s, o, ms;
|
||||
if (G_LIKELY (len == 1)) {
|
||||
/* common case */
|
||||
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 */
|
||||
size += s;
|
||||
mem = GST_BUFFER_MEM_PTR (buffer, i);
|
||||
s = gst_memory_get_sizes (mem, &o, &ms);
|
||||
|
||||
/* keep offset of first memory block */
|
||||
if (i == 0)
|
||||
offs = o;
|
||||
/* this is the amount of extra bytes in this block, we only keep this for
|
||||
* the last block */
|
||||
else if (i + 1 == len)
|
||||
extra = ms - (o + s);
|
||||
/* add sizes */
|
||||
size += s;
|
||||
|
||||
/* keep offset of first memory block */
|
||||
if (i == 0)
|
||||
offs = o;
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
@ -810,7 +820,7 @@ gst_buffer_resize (GstBuffer * buffer, gssize offset, gsize size)
|
|||
gsize bsize, bufsize, bufoffs, bufmax;
|
||||
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);
|
||||
|
||||
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);
|
||||
bsize = gst_memory_get_sizes (mem, NULL, NULL);
|
||||
|
||||
if (bsize <= offset) {
|
||||
if ((gssize) bsize <= offset) {
|
||||
/* remove buffer */
|
||||
gst_memory_unref (mem);
|
||||
offset -= bsize;
|
||||
} else {
|
||||
gsize left;
|
||||
|
||||
left = MIN (bsize - offset, size);
|
||||
if (left < bsize) {
|
||||
/* last buffer always gets resized to the remaining size */
|
||||
if (si + 1 == len)
|
||||
left = size;
|
||||
else
|
||||
left = MIN (bsize - offset, size);
|
||||
|
||||
if (left) {
|
||||
/* we need to clip something */
|
||||
if (GST_MEMORY_IS_WRITABLE (mem)) {
|
||||
gst_memory_resize (mem, offset, left);
|
||||
|
|
|
@ -228,7 +228,7 @@ _default_mem_free (GstMemoryDefault * mem)
|
|||
}
|
||||
|
||||
static GstMemoryDefault *
|
||||
_default_mem_copy (GstMemoryDefault * mem, gsize offset, gsize size)
|
||||
_default_mem_copy (GstMemoryDefault * mem, gssize offset, gsize size)
|
||||
{
|
||||
GstMemoryDefault *copy;
|
||||
|
||||
|
@ -242,7 +242,7 @@ _default_mem_copy (GstMemoryDefault * mem, gsize offset, gsize size)
|
|||
}
|
||||
|
||||
static GstMemoryDefault *
|
||||
_default_mem_share (GstMemoryDefault * mem, gsize offset, gsize size)
|
||||
_default_mem_share (GstMemoryDefault * mem, gssize offset, gsize size)
|
||||
{
|
||||
GstMemoryDefault *sub;
|
||||
GstMemory *parent;
|
||||
|
@ -278,7 +278,7 @@ _default_mem_is_span (GstMemoryDefault * mem1, GstMemoryDefault * mem2,
|
|||
}
|
||||
|
||||
static GstMemory *
|
||||
_fallback_copy (GstMemory * mem, gsize offset, gsize size)
|
||||
_fallback_copy (GstMemory * mem, gssize offset, gsize size)
|
||||
{
|
||||
GstMemory *copy;
|
||||
guint8 *data, *dest;
|
||||
|
@ -492,7 +492,7 @@ gst_memory_unmap (GstMemory * mem, gpointer data, gsize size)
|
|||
* Returns: a new #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);
|
||||
|
||||
|
@ -513,7 +513,7 @@ gst_memory_copy (GstMemory * mem, gsize offset, gsize size)
|
|||
* Returns: a new #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);
|
||||
|
||||
|
|
|
@ -204,7 +204,7 @@ typedef void (*GstMemoryFreeFunction) (GstMemory *mem);
|
|||
* Returns: a new #GstMemory object wrapping a copy of the requested region in
|
||||
* @mem.
|
||||
*/
|
||||
typedef GstMemory * (*GstMemoryCopyFunction) (GstMemory *mem, gsize offset, gsize size);
|
||||
typedef GstMemory * (*GstMemoryCopyFunction) (GstMemory *mem, gssize offset, gsize size);
|
||||
|
||||
/**
|
||||
* GstMemoryShareFunction:
|
||||
|
@ -218,7 +218,7 @@ typedef GstMemory * (*GstMemoryCopyFunction) (GstMemory *mem, gsize offset,
|
|||
*
|
||||
* 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:
|
||||
|
@ -293,8 +293,8 @@ gpointer gst_memory_map (GstMemory *mem, gsize *size, gsize *maxsize,
|
|||
gboolean gst_memory_unmap (GstMemory *mem, gpointer data, gsize size);
|
||||
|
||||
/* copy and subregions */
|
||||
GstMemory * gst_memory_copy (GstMemory *mem, gsize offset, gsize size);
|
||||
GstMemory * gst_memory_share (GstMemory *mem, gsize offset, gsize size);
|
||||
GstMemory * gst_memory_copy (GstMemory *mem, gssize offset, gsize size);
|
||||
GstMemory * gst_memory_share (GstMemory *mem, gssize offset, gsize size);
|
||||
|
||||
/* span memory */
|
||||
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_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 *
|
||||
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_copy);
|
||||
tcase_add_test (tc_chain, test_try_new_and_alloc);
|
||||
tcase_add_test (tc_chain, test_resize);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue