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:
Wim Taymans 2011-07-11 18:00:52 +02:00
parent 0849cae4a8
commit 8461249f22
4 changed files with 129 additions and 34 deletions

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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;
} }