buffer: clean up _span and add more g_return_if..
authorWim Taymans <wim.taymans@collabora.co.uk>
Tue, 29 Mar 2011 14:52:21 +0000 (16:52 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Tue, 29 Mar 2011 14:52:21 +0000 (16:52 +0200)
gst/gstbuffer.c
gst/gstmemory.c
gst/gstmemory.h
win32/common/libgstreamer.def

index 75687a6..e3ce594 100644 (file)
 
 GType _gst_buffer_type = 0;
 
+static GstMemory *_gst_buffer_arr_span (GstMemory ** mem[], gsize len[],
+    guint n, gsize offset, gsize size);
+
 typedef struct _GstMetaItem GstMetaItem;
 
 struct _GstMetaItem
@@ -157,12 +160,38 @@ typedef struct
   GstMetaItem *item;
 } GstBufferImpl;
 
+static void
+_span_memory (GstBuffer * buffer, gsize offset, gsize size)
+{
+  GstMemory *span, **mem[1];
+  gsize len[1], i;
+
+  /* not enough room, span buffers */
+  mem[0] = GST_BUFFER_MEM_ARRAY (buffer);
+  len[0] = GST_BUFFER_MEM_LEN (buffer);
+  span = _gst_buffer_arr_span (mem, len, 1, offset, size);
+
+  /* unref old buffers */
+  for (i = 0; i < len[0]; i++)
+    gst_memory_unref (mem[0][i]);
+
+  /* replace with single spanned buffer */
+  GST_BUFFER_MEM_PTR (buffer, 0) = span;
+  GST_BUFFER_MEM_LEN (buffer) = 1;
+}
+
 static inline void
 _memory_add (GstBuffer * buffer, GstMemory * mem)
 {
   guint len = GST_BUFFER_MEM_LEN (buffer);
-  /* FIXME, span buffers when we run out of places */
-  g_return_if_fail (len < GST_BUFFER_MEM_MAX);
+
+  if (G_UNLIKELY (len >= GST_BUFFER_MEM_MAX)) {
+    gsize size = gst_buffer_get_size (buffer);
+    /* to many buffer, span them */
+    _span_memory (buffer, 0, size);
+    /* we now have 1 single spanned buffer */
+    len = 1;
+  }
   GST_BUFFER_MEM_PTR (buffer, len) = mem;
   GST_BUFFER_MEM_LEN (buffer) = len + 1;
 }
@@ -223,12 +252,13 @@ gst_buffer_copy_into (GstBuffer * dest, GstBuffer * src,
   if (G_UNLIKELY (dest == src))
     return;
 
+  g_return_if_fail (gst_buffer_is_writable (dest));
+
   bufsize = gst_buffer_get_size (src);
+  g_return_if_fail (bufsize >= offset);
   if (size == -1)
     size = bufsize - offset;
-
   g_return_if_fail (bufsize >= offset + size);
-  g_return_if_fail (gst_buffer_is_writable (dest));
 
   GST_CAT_LOG (GST_CAT_BUFFER, "copy %p to %p, offset %" G_GSIZE_FORMAT
       "-%" G_GSIZE_FORMAT "/%" G_GSIZE_FORMAT, src, dest, offset, size,
@@ -646,7 +676,7 @@ gst_buffer_trim (GstBuffer * buffer, gsize offset, gsize size)
 {
   guint len;
   guint si, di;
-  gsize bsize;
+  gsize bsize, bufsize;
   GstMemory *mem;
 
   GST_CAT_LOG (GST_CAT_BUFFER, "trim %p %" G_GSIZE_FORMAT "-%" G_GSIZE_FORMAT,
@@ -654,6 +684,12 @@ gst_buffer_trim (GstBuffer * buffer, gsize offset, gsize size)
 
   g_return_if_fail (gst_buffer_is_writable (buffer));
 
+  bufsize = gst_buffer_get_size (buffer);
+  g_return_if_fail (bufsize >= offset);
+  if (size == -1)
+    size = bufsize - offset;
+  g_return_if_fail (bufsize >= offset + size);
+
   len = GST_BUFFER_MEM_LEN (buffer);
 
   /* copy and trim */
@@ -963,8 +999,10 @@ gst_buffer_create_sub (GstBuffer * buffer, gsize offset, gsize size)
 
   g_return_val_if_fail (buffer != NULL, NULL);
   g_return_val_if_fail (buffer->mini_object.refcount > 0, NULL);
-
   bufsize = gst_buffer_get_size (buffer);
+  g_return_val_if_fail (bufsize >= offset, NULL);
+  if (size == -1)
+    size = bufsize - offset;
   g_return_val_if_fail (bufsize >= offset + size, NULL);
 
   /* create the new buffer */
@@ -978,6 +1016,92 @@ gst_buffer_create_sub (GstBuffer * buffer, gsize offset, gsize size)
   return subbuffer;
 }
 
+static gboolean
+_gst_buffer_arr_is_span_fast (GstMemory ** mem[], gsize len[], guint n,
+    gsize * offset, GstMemory ** parent)
+{
+  GstMemory *mcur, *mprv;
+  gboolean have_offset = FALSE;
+  guint count, i;
+
+  mcur = mprv = NULL;
+  for (count = 0; count < n; count++) {
+    gsize offs, clen;
+    GstMemory **cmem;
+
+    cmem = mem[count];
+    clen = len[count];
+
+    for (i = 0; i < clen; i++) {
+      if (mcur)
+        mprv = mcur;
+      mcur = cmem[i];
+
+      if (mprv && mcur) {
+        /* check is memory is contiguous */
+        if (!gst_memory_is_span (mprv, mcur, &offs))
+          return FALSE;
+
+        if (!have_offset) {
+          if (offset)
+            *offset = offs;
+          if (parent)
+            *parent = mprv->parent;
+
+          have_offset = TRUE;
+        }
+      }
+    }
+  }
+  return have_offset;
+}
+
+static GstMemory *
+_gst_buffer_arr_span (GstMemory ** mem[], gsize len[], guint n, gsize offset,
+    gsize size)
+{
+  GstMemory *span, *parent;
+  gsize poffset;
+
+  if (_gst_buffer_arr_is_span_fast (mem, len, n, &poffset, &parent)) {
+    span = gst_memory_sub (parent, offset + poffset, size);
+  } else {
+    gsize count, left;
+    guint8 *dest, *ptr;
+
+    span = gst_memory_new_alloc (size, 0);
+    dest = gst_memory_map (span, NULL, NULL, GST_MAP_WRITE);
+
+    ptr = dest;
+    left = size;
+
+    for (count = 0; count < n; count++) {
+      gsize i, tocopy, clen, ssize;
+      guint8 *src;
+      GstMemory **cmem;
+
+      cmem = mem[count];
+      clen = len[count];
+
+      for (i = 0; i < clen && left > 0; i++) {
+        src = gst_memory_map (cmem[i], &ssize, NULL, GST_MAP_READ);
+        tocopy = MIN (ssize, left);
+        if (tocopy > offset) {
+          memcpy (ptr, src + offset, tocopy - offset);
+          left -= tocopy;
+          ptr += tocopy;
+          offset = 0;
+        } else {
+          offset -= tocopy;
+        }
+        gst_memory_unmap (cmem[i], src, ssize);
+      }
+    }
+    gst_memory_unmap (span, dest, size);
+  }
+  return span;
+}
+
 /**
  * gst_buffer_is_span_fast:
  * @buf1: the first #GstBuffer.
@@ -994,20 +1118,20 @@ gst_buffer_create_sub (GstBuffer * buffer, gsize offset, gsize size)
 gboolean
 gst_buffer_is_span_fast (GstBuffer * buf1, GstBuffer * buf2)
 {
-  GstMemory **arr1, **arr2;
-  gsize len1, len2;
+  GstMemory **mem[2];
+  gsize len[2];
 
   g_return_val_if_fail (GST_IS_BUFFER (buf1), FALSE);
   g_return_val_if_fail (GST_IS_BUFFER (buf2), FALSE);
   g_return_val_if_fail (buf1->mini_object.refcount > 0, FALSE);
   g_return_val_if_fail (buf2->mini_object.refcount > 0, FALSE);
 
-  arr1 = GST_BUFFER_MEM_ARRAY (buf1);
-  len1 = GST_BUFFER_MEM_LEN (buf1);
-  arr2 = GST_BUFFER_MEM_ARRAY (buf2);
-  len2 = GST_BUFFER_MEM_LEN (buf2);
+  mem[0] = GST_BUFFER_MEM_ARRAY (buf1);
+  len[0] = GST_BUFFER_MEM_LEN (buf1);
+  mem[1] = GST_BUFFER_MEM_ARRAY (buf2);
+  len[1] = GST_BUFFER_MEM_LEN (buf2);
 
-  return gst_memory_is_span (arr1, len1, arr2, len2, NULL, NULL);
+  return _gst_buffer_arr_is_span_fast (mem, len, 2, NULL, NULL);
 }
 
 /**
@@ -1016,7 +1140,7 @@ gst_buffer_is_span_fast (GstBuffer * buf1, GstBuffer * buf2)
  * @offset: the offset in the first buffer from where the new
  * buffer should start.
  * @buf2: the second source #GstBuffer to merge.
- * @len: the total length of the new buffer.
+ * @size: the total size of the new buffer.
  *
  * Creates a new buffer that consists of part of buf1 and buf2.
  * Logically, buf1 and buf2 are concatenated into a single larger
@@ -1034,30 +1158,34 @@ gst_buffer_is_span_fast (GstBuffer * buf1, GstBuffer * buf2)
  *     buffers, or NULL if the arguments are invalid.
  */
 GstBuffer *
-gst_buffer_span (GstBuffer * buf1, gsize offset, GstBuffer * buf2, gsize len)
+gst_buffer_span (GstBuffer * buf1, gsize offset, GstBuffer * buf2, gsize size)
 {
   GstBuffer *newbuf;
-  GstMemory **arr1, **arr2;
-  gsize len1, len2;
-  GstMemory *mem;
+  GstMemory *span;
+  GstMemory **mem[2];
+  gsize len[2], len1, len2;
 
   g_return_val_if_fail (GST_IS_BUFFER (buf1), NULL);
   g_return_val_if_fail (GST_IS_BUFFER (buf2), NULL);
   g_return_val_if_fail (buf1->mini_object.refcount > 0, NULL);
   g_return_val_if_fail (buf2->mini_object.refcount > 0, NULL);
-  g_return_val_if_fail (len > 0, NULL);
-  g_return_val_if_fail (len <= gst_buffer_get_size (buf1) +
-      gst_buffer_get_size (buf2) - offset, NULL);
+  len1 = gst_buffer_get_size (buf1);
+  len2 = gst_buffer_get_size (buf2);
+  g_return_val_if_fail (len1 + len2 > offset, NULL);
+  if (size == -1)
+    size = len1 + len2 - offset;
+  else
+    g_return_val_if_fail (size <= len1 + len2 - offset, NULL);
 
-  newbuf = gst_buffer_new ();
+  mem[0] = GST_BUFFER_MEM_ARRAY (buf1);
+  len[0] = GST_BUFFER_MEM_LEN (buf1);
+  mem[1] = GST_BUFFER_MEM_ARRAY (buf2);
+  len[1] = GST_BUFFER_MEM_LEN (buf2);
 
-  arr1 = GST_BUFFER_MEM_ARRAY (buf1);
-  len1 = GST_BUFFER_MEM_LEN (buf1);
-  arr2 = GST_BUFFER_MEM_ARRAY (buf2);
-  len2 = GST_BUFFER_MEM_LEN (buf2);
+  span = _gst_buffer_arr_span (mem, len, 2, offset, size);
 
-  mem = gst_memory_span (arr1, len1, offset, arr2, len2, len);
-  _memory_add (newbuf, mem);
+  newbuf = gst_buffer_new ();
+  _memory_add (newbuf, span);
 
 #if 0
   /* if the offset is 0, the new buffer has the same timestamp as buf1 */
index 5412f22..38df7ed 100644 (file)
@@ -213,6 +213,9 @@ _default_mem_sub (GstMemoryDefault * mem, gsize offset, gsize size)
   if ((parent = mem->mem.parent) == NULL)
     parent = (GstMemory *) mem;
 
+  if (size == -1)
+    size = mem->size - offset;
+
   sub = _default_mem_new (parent->flags, parent, mem->data, NULL, mem->maxsize,
       mem->offset + offset, size);
 
@@ -478,101 +481,22 @@ gst_memory_sub (GstMemory * mem, gsize offset, gsize size)
 }
 
 gboolean
-gst_memory_is_span (GstMemory ** mem1, gsize len1, GstMemory ** mem2,
-    gsize len2, GstMemory ** parent, gsize * offset)
+gst_memory_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset)
 {
-  GstMemory *m1, *m2, **arr;
-  gsize len, i;
-  guint count;
-  gboolean have_offset = FALSE;
-
   g_return_val_if_fail (mem1 != NULL, FALSE);
   g_return_val_if_fail (mem2 != NULL, FALSE);
 
-  arr = mem1;
-  len = len1;
-  m1 = m2 = NULL;
-
-  for (count = 0; count < 2; count++) {
-    gsize offs;
-
-    for (i = 0; i < len; i++) {
-      if (m2)
-        m1 = m2;
-      m2 = arr[i];
-
-      if (m1 && m2) {
-        /* need to have the same implementation */
-        if (m1->impl != m2->impl)
-          return FALSE;
-
-        /* need to have the same parent */
-        if (m1->parent == NULL || m1->parent != m2->parent)
-          return FALSE;
-
-        /* and memory is contiguous */
-        if (!m1->impl->info.is_span (m1, m2, &offs))
-          return FALSE;
-
-        if (!have_offset) {
-          if (offset)
-            *offset = offs;
-          if (parent)
-            *parent = m1->parent;
-
-          have_offset = TRUE;
-        }
-      }
-    }
-    arr = mem2;
-    len = len2;
-  }
-  if (!have_offset)
+  /* need to have the same implementation */
+  if (mem1->impl != mem2->impl)
     return FALSE;
 
-  return TRUE;
-}
+  /* need to have the same parent */
+  if (mem1->parent == NULL || mem1->parent != mem2->parent)
+    return FALSE;
 
-GstMemory *
-gst_memory_span (GstMemory ** mem1, gsize len1, gsize offset, GstMemory ** mem2,
-    gsize len2, gsize size)
-{
-  GstMemory *span, **mem, *parent;
-  guint8 *data, *dest;
-  gsize count, ssize, tocopy, len, poffset, i;
-
-  g_return_val_if_fail (mem1 != NULL, NULL);
-  g_return_val_if_fail (mem2 != NULL, NULL);
-
-  if (gst_memory_is_span (mem1, len1, mem2, len2, &parent, &poffset)) {
-    span = gst_memory_sub (parent, offset + poffset, size);
-  } else {
-    GstMemoryDefault *tspan;
-
-    tspan = _default_mem_new_block (size, 0, 0, size);
-    dest = tspan->data;
-
-    mem = mem1;
-    len = len1;
-
-    for (count = 0; count < 2; count++) {
-      for (i = 0; i < len && size > 0; i++) {
-        data = gst_memory_map (mem[i], &ssize, NULL, GST_MAP_READ);
-        tocopy = MIN (ssize, size);
-        if (tocopy > offset) {
-          memcpy (dest, data + offset, tocopy - offset);
-          size -= tocopy;
-          dest += tocopy;
-          offset = 0;
-        } else {
-          offset -= tocopy;
-        }
-        gst_memory_unmap (mem[i], data, ssize);
-      }
-      mem = mem2;
-      len = len2;
-    }
-    span = (GstMemory *) tspan;
-  }
-  return span;
+  /* and memory is contiguous */
+  if (!mem1->impl->info.is_span (mem1, mem2, offset))
+    return FALSE;
+
+  return TRUE;
 }
index 99b2ee9..517c591 100644 (file)
@@ -135,9 +135,7 @@ GstMemory * gst_memory_copy       (GstMemory *mem, gsize offset, gsize size);
 GstMemory * gst_memory_sub        (GstMemory *mem, gsize offset, gsize size);
 
 /* memory arrays */
-gboolean    gst_memory_is_span    (GstMemory **mem1, gsize len1,
-                                   GstMemory **mem2, gsize len2,
-                                   GstMemory **parent, gsize *offset);
+gboolean    gst_memory_is_span    (GstMemory *mem1, GstMemory *mem2, gsize *offset);
 GstMemory * gst_memory_span       (GstMemory **mem1, gsize len1, gsize offset,
                                    GstMemory **mem2, gsize len2, gsize size);
 
index 2d65d42..207ca55 100644 (file)
@@ -541,7 +541,6 @@ EXPORTS
        gst_memory_new_wrapped
        gst_memory_ref
        gst_memory_register
-       gst_memory_span
        gst_memory_sub
        gst_memory_trim
        gst_memory_unmap