buffer: fix negative offsets some more
authorWim Taymans <wim.taymans@collabora.co.uk>
Mon, 11 Jul 2011 16:00:52 +0000 (18:00 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Mon, 11 Jul 2011 16:00:52 +0000 (18:00 +0200)
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.

gst/gstbuffer.c
gst/gstmemory.c
gst/gstmemory.h
tests/check/gst/gstbuffer.c

index b190112..2bcfe73 100644 (file)
@@ -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;
-
-    s = gst_memory_get_sizes (GST_BUFFER_MEM_PTR (buffer, i), &o, &ms);
-
-    /* add sizes */
-    size += s;
+  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;
+
+    size = offs = extra = 0;
+    for (i = 0; i < len; i++) {
+      gsize s, o, ms;
+
+      mem = GST_BUFFER_MEM_PTR (buffer, i);
+      s = gst_memory_get_sizes (mem, &o, &ms);
+
+      /* 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);
+    }
 
-    /* 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);
+    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);
index f30d3c9..dfb3697 100644 (file)
@@ -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);
 
index 9bf338e..a4f4112 100644 (file)
@@ -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);
index b37d943..22cbef7 100644 (file)
@@ -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;
 }