memory: Add 0 padding
authorWim Taymans <wim.taymans@collabora.co.uk>
Wed, 14 Mar 2012 20:32:22 +0000 (21:32 +0100)
committerWim Taymans <wim.taymans@collabora.co.uk>
Wed, 14 Mar 2012 20:32:22 +0000 (21:32 +0100)
Change gst_allocator_alloc() so that we can also spicify flags and padding.
Add 2 new flags to mark the memory 0 prefixed/padded. This allows us to
remove some resizes in the base classes.
When allocating memory, memset prefix and padding with 0 when the flags tell
us to.
On resize, clear the zero padding flags if we can't guarantee the memory is
still 0 filled.
Update tests.

gst/gstbuffer.c
gst/gstbufferpool.c
gst/gstmemory.c
gst/gstmemory.h
libs/gst/base/gstbasesrc.c
libs/gst/base/gstbasetransform.c
tests/check/gst/gstbuffer.c
tests/check/gst/gstmemory.c

index 9d30a36..0284ac6 100644 (file)
@@ -536,7 +536,7 @@ gst_buffer_new_allocate (GstAllocator * allocator, gsize size, gsize align)
 
 #if 1
   if (size > 0) {
-    mem = gst_allocator_alloc (allocator, size, align);
+    mem = gst_allocator_alloc (allocator, 0, size, 0, size, align);
     if (G_UNLIKELY (mem == NULL))
       goto no_memory;
   } else {
@@ -1343,7 +1343,7 @@ _gst_buffer_arr_span (GstMemory ** mem[], gsize len[], guint n, gsize offset,
     GstMapInfo dinfo;
     guint8 *ptr;
 
-    span = gst_allocator_alloc (NULL, size, 0);
+    span = gst_allocator_alloc (NULL, 0, size, 0, size, 0);
     gst_memory_map (span, &dinfo, GST_MAP_WRITE);
 
     ptr = dinfo.data;
index 40521e3..c34e421 100644 (file)
@@ -182,13 +182,13 @@ default_alloc_buffer (GstBufferPool * pool, GstBuffer ** buffer,
 {
   GstBufferPoolPrivate *priv = pool->priv;
   GstMemory *mem;
+  gsize maxsize;
 
   *buffer = gst_buffer_new ();
 
-  mem =
-      gst_allocator_alloc (NULL, priv->size + priv->prefix + priv->padding,
-      priv->align);
-  gst_memory_resize (mem, priv->prefix, priv->size);
+  maxsize = priv->size + priv->prefix + priv->padding;
+  mem = gst_allocator_alloc (NULL, 0, maxsize, priv->prefix,
+      priv->size, priv->align);
   gst_buffer_take_memory (*buffer, -1, mem);
 
   return GST_FLOW_OK;
index 8cda557..726c23d 100644 (file)
@@ -169,10 +169,11 @@ _default_mem_new (GstMemoryFlags flags, GstMemory * parent, gpointer data,
 
 /* allocate the memory and structure in one block */
 static GstMemoryDefault *
-_default_mem_new_block (gsize maxsize, gsize align, gsize offset, gsize size)
+_default_mem_new_block (GstMemoryFlags flags, gsize maxsize, gsize align,
+    gsize offset, gsize size)
 {
   GstMemoryDefault *mem;
-  gsize aoffset, slice_size;
+  gsize aoffset, slice_size, padding;
   guint8 *data;
 
   /* ensure configured alignment */
@@ -189,19 +190,27 @@ _default_mem_new_block (gsize maxsize, gsize align, gsize offset, gsize size)
   data = (guint8 *) mem + sizeof (GstMemoryDefault);
 
   if ((aoffset = ((guintptr) data & align)))
-    aoffset = (align + 1) - aoffset;
+    data += (align + 1) - aoffset;
 
-  _default_mem_init (mem, 0, NULL, slice_size, data, maxsize,
-      aoffset + offset, size, NULL, NULL);
+  if (offset && (flags & GST_MEMORY_FLAG_ZERO_PREFIXED))
+    memset (data, 0, offset);
+
+  padding = maxsize - (offset + size);
+  if (padding && (flags & GST_MEMORY_FLAG_ZERO_PADDED))
+    memset (data + offset + size, 0, padding);
+
+  _default_mem_init (mem, flags, NULL, slice_size, data, maxsize,
+      offset, size, NULL, NULL);
 
   return mem;
 }
 
 static GstMemory *
-_default_alloc_alloc (GstAllocator * allocator, gsize maxsize, gsize align,
-    gpointer user_data)
+_default_alloc_alloc (GstAllocator * allocator, GstMemoryFlags flags,
+    gsize maxsize, gsize offset, gsize size, gsize align, gpointer user_data)
 {
-  return (GstMemory *) _default_mem_new_block (maxsize, align, 0, maxsize);
+  return (GstMemory *) _default_mem_new_block (flags, maxsize, align, offset,
+      size);
 }
 
 static gpointer
@@ -239,7 +248,7 @@ _default_mem_copy (GstMemoryDefault * mem, gssize offset, gsize size)
     size = mem->mem.size > offset ? mem->mem.size - offset : 0;
 
   copy =
-      _default_mem_new_block (mem->mem.maxsize, 0, mem->mem.offset + offset,
+      _default_mem_new_block (0, mem->mem.maxsize, 0, mem->mem.offset + offset,
       size);
   memcpy (copy->data, mem->data, mem->mem.maxsize);
   GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "copy memory %p -> %p", mem, copy);
@@ -298,7 +307,7 @@ _fallback_mem_copy (GstMemory * mem, gssize offset, gssize size)
     size = sinfo.size > offset ? sinfo.size - offset : 0;
 
   /* use the same allocator as the memory we copy  */
-  copy = gst_allocator_alloc (mem->allocator, size, mem->align);
+  copy = gst_allocator_alloc (mem->allocator, 0, size, 0, size, mem->align);
   if (!gst_memory_map (copy, &dinfo, GST_MAP_WRITE)) {
     GST_CAT_WARNING (GST_CAT_MEMORY, "could not write map memory %p", copy);
     gst_memory_unmap (mem, &sinfo);
@@ -378,6 +387,9 @@ _priv_gst_memory_initialize (void)
  *
  * Allocate a new memory block that wraps the given @data.
  *
+ * The prefix/padding must be filled with 0 if @flags contains
+ * #GST_MEMORY_FLAG_ZERO_PREFIXED and #GST_MEMORY_FLAG_ZERO_PADDED respectively.
+ *
  * Returns: a new #GstMemory.
  */
 GstMemory *
@@ -494,6 +506,9 @@ gst_memory_get_sizes (GstMemory * mem, gsize * offset, gsize * maxsize)
  *
  * Resize the memory region. @mem should be writable and offset + size should be
  * less than the maxsize of @mem.
+ *
+ * #GST_MEMORY_FLAG_ZERO_PREFIXED and #GST_MEMORY_FLAG_ZERO_PADDED will be
+ * cleared when offset or padding is increased respectively.
  */
 void
 gst_memory_resize (GstMemory * mem, gssize offset, gsize size)
@@ -502,6 +517,14 @@ gst_memory_resize (GstMemory * mem, gssize offset, gsize size)
   g_return_if_fail (offset >= 0 || mem->offset >= -offset);
   g_return_if_fail (size + mem->offset + offset <= mem->maxsize);
 
+  /* if we increase the prefix, we can't guarantee it is still 0 filled */
+  if ((offset > 0) && GST_MEMORY_IS_ZERO_PREFIXED (mem))
+    GST_MEMORY_FLAG_UNSET (mem, GST_MEMORY_FLAG_ZERO_PREFIXED);
+
+  /* if we increase the padding, we can't guarantee it is still 0 filled */
+  if ((offset + size < mem->size) && GST_MEMORY_IS_ZERO_PADDED (mem))
+    GST_MEMORY_FLAG_UNSET (mem, GST_MEMORY_FLAG_ZERO_PADDED);
+
   mem->offset += offset;
   mem->size = size;
 }
@@ -962,12 +985,20 @@ gst_allocator_set_default (GstAllocator * allocator)
 /**
  * gst_allocator_alloc:
  * @allocator: (transfer none) (allow-none): a #GstAllocator to use
+ * @flags: the flags
  * @maxsize: allocated size of @data
+ * @offset: offset in allocated memory
+ * @size: size of visible
  * @align: alignment for the data
  *
  * Use @allocator to allocate a new memory block with memory that is at least
  * @maxsize big and has the given alignment.
  *
+ * @offset and @size describe the start and size of the accessible memory.
+ *
+ * The prefix/padding will be filled with 0 if @flags contains
+ * #GST_MEMORY_FLAG_ZERO_PREFIXED and #GST_MEMORY_FLAG_ZERO_PADDED respectively.
+ *
  * When @allocator is NULL, the default allocator will be used.
  *
  * @align is given as a bitmask so that @align + 1 equals the amount of bytes to
@@ -976,7 +1007,8 @@ gst_allocator_set_default (GstAllocator * allocator)
  * Returns: (transfer full): a new #GstMemory.
  */
 GstMemory *
-gst_allocator_alloc (GstAllocator * allocator, gsize maxsize, gsize align)
+gst_allocator_alloc (GstAllocator * allocator, GstMemoryFlags flags,
+    gsize maxsize, gsize offset, gsize size, gsize align)
 {
   GstMemory *mem;
 
@@ -985,7 +1017,8 @@ gst_allocator_alloc (GstAllocator * allocator, gsize maxsize, gsize align)
   if (allocator == NULL)
     allocator = _default_allocator;
 
-  mem = allocator->info.alloc (allocator, maxsize, align, allocator->user_data);
+  mem = allocator->info.alloc (allocator, flags, maxsize, offset, size,
+      align, allocator->user_data);
 #ifndef GST_DISABLE_TRACE
   _gst_alloc_trace_new (_gst_memory_trace, mem);
 #endif
index 7ec50f4..f64aef8 100644 (file)
@@ -49,15 +49,19 @@ GST_EXPORT gsize gst_memory_alignment;
  * memory with #GST_MAP_WRITE.
  * @GST_MEMORY_FLAG_NO_SHARE: memory must not be shared. Copies will have to be
  * made when this memory needs to be shared between buffers.
+ * @GST_MEMORY_FLAG_ZERO_PREFIXED: the memory prefix is filled with 0 bytes
+ * @GST_MEMORY_FLAG_ZERO_PADDED: the memory padding is filled with 0 bytes
  * @GST_MEMORY_FLAG_LAST: first flag that can be used for custom purposes
  *
  * Flags for wrapped memory.
  */
 typedef enum {
-  GST_MEMORY_FLAG_READONLY = (1 << 0),
-  GST_MEMORY_FLAG_NO_SHARE = (1 << 1),
+  GST_MEMORY_FLAG_READONLY      = (1 << 0),
+  GST_MEMORY_FLAG_NO_SHARE      = (1 << 1),
+  GST_MEMORY_FLAG_ZERO_PREFIXED = (1 << 2),
+  GST_MEMORY_FLAG_ZERO_PADDED   = (1 << 3),
 
-  GST_MEMORY_FLAG_LAST     = (1 << 16)
+  GST_MEMORY_FLAG_LAST          = (1 << 16)
 } GstMemoryFlags;
 
 /**
@@ -75,6 +79,14 @@ typedef enum {
  * Gives the status of a specific flag on a @mem.
  */
 #define GST_MEMORY_FLAG_IS_SET(mem,flag)   !!(GST_MEMORY_FLAGS (mem) & (flag))
+/**
+ * GST_MEMORY_FLAG_UNSET:
+ * @mem: a #GstMemory.
+ * @flag: the #GstMemoryFlags to clear.
+ *
+ * Clear a specific flag on a @mem.
+ */
+#define GST_MEMORY_FLAG_UNSET(mem,flag)   (GST_MEMORY_FLAGS (mem) &= ~(flag))
 
 /**
  * GST_MEMORY_IS_READONLY:
@@ -83,6 +95,21 @@ typedef enum {
  * Check if @mem is readonly.
  */
 #define GST_MEMORY_IS_READONLY(mem)        GST_MEMORY_FLAG_IS_SET(mem,GST_MEMORY_FLAG_READONLY)
+/**
+ * GST_MEMORY_IS_ZERO_PREFIXED:
+ * @mem: a #GstMemory.
+ *
+ * Check if the prefix in @mem is 0 filled.
+ */
+#define GST_MEMORY_IS_ZERO_PREFIXED(mem)   GST_MEMORY_FLAG_IS_SET(mem,GST_MEMORY_FLAG_ZERO_PREFIXED)
+/**
+ * GST_MEMORY_IS_ZERO_PADDED:
+ * @mem: a #GstMemory.
+ *
+ * Check if the padding in @mem is 0 filled.
+ */
+#define GST_MEMORY_IS_ZERO_PADDED(mem)     GST_MEMORY_FLAG_IS_SET(mem,GST_MEMORY_FLAG_ZERO_PADDED)
+
 
 /**
  * GstMemory:
@@ -169,19 +196,28 @@ typedef struct {
 /**
  * GstAllocatorAllocFunction:
  * @allocator: a #GstAllocator
+ * @flags: the flags
  * @maxsize: the maxsize
+ * @offset: the offset
+ * @size: the size
  * @align: the alignment
  * @user_data: user data
  *
  * Allocate a new #GstMemory from @allocator that can hold at least @maxsize bytes
  * and is aligned to (@align + 1) bytes.
  *
+ * The offset and size of the memory should be set and the prefix/padding must
+ * be filled with 0 if @flags contains #GST_MEMORY_FLAG_ZERO_PREFIXED and
+ * #GST_MEMORY_FLAG_ZERO_PADDED respectively.
+ *
  * @user_data is the data that was used when creating @allocator.
  *
  * Returns: a newly allocated #GstMemory. Free with gst_memory_unref()
  */
 typedef GstMemory *  (*GstAllocatorAllocFunction)  (GstAllocator *allocator,
-                                                    gsize maxsize, gsize align,
+                                                    GstMemoryFlags flags,
+                                                    gsize maxsize, gsize offset,
+                                                    gsize size, gsize align,
                                                     gpointer user_data);
 
 /**
@@ -305,8 +341,9 @@ GstAllocator * gst_allocator_find            (const gchar *name);
 void           gst_allocator_set_default     (GstAllocator * allocator);
 
 /* allocating memory blocks */
-GstMemory *    gst_allocator_alloc           (GstAllocator * allocator,
-                                              gsize maxsize, gsize align);
+GstMemory *    gst_allocator_alloc           (GstAllocator * allocator, GstMemoryFlags flags,
+                                              gsize maxsize, gsize offset, gsize size,
+                                              gsize align);
 
 GstMemory *    gst_memory_new_wrapped  (GstMemoryFlags flags, gpointer data, gsize maxsize,
                                         gsize offset, gsize size, gpointer user_data,
index af57bfa..c93a19b 100644 (file)
@@ -1360,13 +1360,11 @@ gst_base_src_default_alloc (GstBaseSrc * src, guint64 offset,
 
     maxsize = size + priv->prefix + priv->padding;
 
-    mem = gst_allocator_alloc (priv->allocator, maxsize, priv->alignment);
+    mem = gst_allocator_alloc (priv->allocator, 0, maxsize, priv->prefix,
+        size, priv->alignment);
     if (G_UNLIKELY (mem == NULL))
       goto alloc_failed;
 
-    if (priv->prefix != 0 || priv->padding != 0)
-      gst_memory_resize (mem, priv->prefix, size);
-
     *buffer = gst_buffer_new ();
     if (G_UNLIKELY (*buffer == NULL))
       goto buffer_failed;
index c151b7a..8a15fbd 100644 (file)
@@ -1523,9 +1523,8 @@ default_prepare_output_buffer (GstBaseTransform * trans,
 
   GST_DEBUG_OBJECT (trans, "doing alloc of size %" G_GSIZE_FORMAT, outsize);
   maxsize = outsize + priv->prefix + priv->padding;
-  mem = gst_allocator_alloc (priv->allocator, maxsize, priv->alignment);
-  if (priv->prefix != 0 || priv->padding != 0)
-    gst_memory_resize (mem, priv->prefix, outsize);
+  mem = gst_allocator_alloc (priv->allocator, 0, maxsize, priv->prefix,
+      outsize, priv->alignment);
 
   *outbuf = gst_buffer_new ();
   gst_buffer_take_memory (*outbuf, -1, mem);
index 5a8b9e0..f04bbdc 100644 (file)
@@ -460,7 +460,7 @@ GST_START_TEST (test_size)
   fail_unless (maxsize == maxalloc);
 
   /* new memory */
-  mem = gst_allocator_alloc (NULL, 100, 0);
+  mem = gst_allocator_alloc (NULL, 0, 100, 0, 100, 0);
   size = gst_memory_get_sizes (mem, &offset, &maxalloc2);
   fail_unless (size == 100);
   fail_unless (offset == 0);
@@ -483,7 +483,7 @@ GST_START_TEST (test_size)
   fail_unless (maxalloc == 80 + (maxalloc2 - 20));
 
   /* appending an empty block */
-  mem = gst_allocator_alloc (NULL, 100, 0);
+  mem = gst_allocator_alloc (NULL, 0, 100, 0, 100, 0);
   size = gst_memory_get_sizes (mem, &offset, &maxalloc3);
   gst_memory_resize (mem, 0, 0);
   gst_buffer_take_memory (buf, -1, mem);
@@ -496,7 +496,7 @@ GST_START_TEST (test_size)
   fail_unless (maxalloc == 80 + (maxalloc2 - 20) + maxalloc3);
 
   /* prepending an empty block */
-  mem = gst_allocator_alloc (NULL, 100, 0);
+  mem = gst_allocator_alloc (NULL, 0, 100, 0, 100, 0);
   size = gst_memory_get_sizes (mem, &offset, &maxalloc4);
   gst_memory_resize (mem, 0, 0);
   gst_buffer_take_memory (buf, 0, mem);
@@ -619,8 +619,8 @@ GST_START_TEST (test_map)
   gsize size, offset;
 
   buf = gst_buffer_new ();
-  gst_buffer_take_memory (buf, -1, gst_allocator_alloc (NULL, 50, 0));
-  gst_buffer_take_memory (buf, -1, gst_allocator_alloc (NULL, 50, 0));
+  gst_buffer_take_memory (buf, -1, gst_allocator_alloc (NULL, 0, 50, 0, 50, 0));
+  gst_buffer_take_memory (buf, -1, gst_allocator_alloc (NULL, 0, 50, 0, 50, 0));
 
   size = gst_buffer_get_sizes (buf, &offset, &maxalloc);
   fail_unless (size == 100);
index 8bde54a..da4c77c 100644 (file)
@@ -37,7 +37,7 @@ GST_START_TEST (test_submemory)
   GstMemory *memory, *sub;
   GstMapInfo info, sinfo;
 
-  memory = gst_allocator_alloc (NULL, 4, 0);
+  memory = gst_allocator_alloc (NULL, 0, 4, 0, 4, 0);
 
   /* check sizes, memory starts out empty */
   fail_unless (gst_memory_map (memory, &info, GST_MAP_WRITE));
@@ -98,7 +98,7 @@ GST_START_TEST (test_is_span)
 {
   GstMemory *memory, *sub1, *sub2;
 
-  memory = gst_allocator_alloc (NULL, 4, 0);
+  memory = gst_allocator_alloc (NULL, 0, 4, 0, 4, 0);
 
   sub1 = gst_memory_share (memory, 0, 2);
   fail_if (sub1 == NULL, "share of memory returned NULL");
@@ -196,7 +196,7 @@ GST_START_TEST (test_copy)
   GstMemory *memory, *copy;
   GstMapInfo info, sinfo;
 
-  memory = gst_allocator_alloc (NULL, 4, 0);
+  memory = gst_allocator_alloc (NULL, 0, 4, 0, 4, 0);
   ASSERT_MEMORY_REFCOUNT (memory, "memory", 1);
 
   copy = gst_memory_copy (memory, 0, -1);
@@ -217,7 +217,7 @@ GST_START_TEST (test_copy)
   gst_memory_unref (copy);
   gst_memory_unref (memory);
 
-  memory = gst_allocator_alloc (NULL, 0, 0);
+  memory = gst_allocator_alloc (NULL, 0, 0, 0, 0, 0);
   fail_unless (gst_memory_map (memory, &info, GST_MAP_READ));
   fail_unless (info.size == 0);
   gst_memory_unmap (memory, &info);
@@ -238,8 +238,9 @@ GST_START_TEST (test_try_new_and_alloc)
 {
   GstMemory *mem;
   GstMapInfo info;
+  gsize size;
 
-  mem = gst_allocator_alloc (NULL, 0, 0);
+  mem = gst_allocator_alloc (NULL, 0, 0, 0, 0, 0);
   fail_unless (mem != NULL);
   fail_unless (gst_memory_map (mem, &info, GST_MAP_READ));
   fail_unless (info.size == 0);
@@ -247,7 +248,8 @@ GST_START_TEST (test_try_new_and_alloc)
   gst_memory_unref (mem);
 
   /* normal alloc should still work */
-  mem = gst_allocator_alloc (NULL, 640 * 480 * 4, 0);
+  size = 640 * 480 * 4;
+  mem = gst_allocator_alloc (NULL, 0, size, 0, size, 0);
   fail_unless (mem != NULL);
   fail_unless (gst_memory_map (mem, &info, GST_MAP_WRITE));
   fail_unless (info.data != NULL);
@@ -281,7 +283,7 @@ GST_START_TEST (test_resize)
   gsize size, maxsize, offset;
 
   /* one memory block */
-  mem = gst_allocator_alloc (NULL, 100, 0);
+  mem = gst_allocator_alloc (NULL, 0, 100, 0, 100, 0);
 
   size = gst_memory_get_sizes (mem, &offset, &maxalloc);
   fail_unless (size == 100);
@@ -380,7 +382,7 @@ GST_START_TEST (test_map)
   gsize size, offset;
 
   /* one memory block */
-  mem = gst_allocator_alloc (NULL, 100, 0);
+  mem = gst_allocator_alloc (NULL, 0, 100, 0, 100, 0);
 
   size = gst_memory_get_sizes (mem, &offset, &maxalloc);
   fail_unless (size == 100);
@@ -404,7 +406,7 @@ GST_START_TEST (test_map_nested)
   GstMemory *mem;
   GstMapInfo info1, info2;
 
-  mem = gst_allocator_alloc (NULL, 100, 0);
+  mem = gst_allocator_alloc (NULL, 0, 100, 0, 100, 0);
 
   /* nested mapping */
   fail_unless (gst_memory_map (mem, &info1, GST_MAP_READ));
@@ -458,7 +460,7 @@ GST_START_TEST (test_map_resize)
   GstMapInfo info;
   gsize size, maxalloc, offset;
 
-  mem = gst_allocator_alloc (NULL, 100, 0);
+  mem = gst_allocator_alloc (NULL, 0, 100, 0, 100, 0);
 
   /* do mapping */
   fail_unless (gst_memory_map (mem, &info, GST_MAP_READ));