From edd2ffe4d4caef2247e7f2376c5309f07b26ac02 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 14 Mar 2012 21:32:22 +0100 Subject: [PATCH] memory: Add 0 padding 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 | 4 +-- gst/gstbufferpool.c | 8 +++--- gst/gstmemory.c | 57 +++++++++++++++++++++++++++++++--------- gst/gstmemory.h | 49 +++++++++++++++++++++++++++++----- libs/gst/base/gstbasesrc.c | 6 ++--- libs/gst/base/gstbasetransform.c | 5 ++-- tests/check/gst/gstbuffer.c | 10 +++---- tests/check/gst/gstmemory.c | 22 +++++++++------- 8 files changed, 115 insertions(+), 46 deletions(-) diff --git a/gst/gstbuffer.c b/gst/gstbuffer.c index 9d30a36..0284ac6 100644 --- a/gst/gstbuffer.c +++ b/gst/gstbuffer.c @@ -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; diff --git a/gst/gstbufferpool.c b/gst/gstbufferpool.c index 40521e3..c34e421 100644 --- a/gst/gstbufferpool.c +++ b/gst/gstbufferpool.c @@ -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; diff --git a/gst/gstmemory.c b/gst/gstmemory.c index 8cda557..726c23d 100644 --- a/gst/gstmemory.c +++ b/gst/gstmemory.c @@ -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 diff --git a/gst/gstmemory.h b/gst/gstmemory.h index 7ec50f4..f64aef8 100644 --- a/gst/gstmemory.h +++ b/gst/gstmemory.h @@ -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, diff --git a/libs/gst/base/gstbasesrc.c b/libs/gst/base/gstbasesrc.c index af57bfa..c93a19b 100644 --- a/libs/gst/base/gstbasesrc.c +++ b/libs/gst/base/gstbasesrc.c @@ -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; diff --git a/libs/gst/base/gstbasetransform.c b/libs/gst/base/gstbasetransform.c index c151b7a..8a15fbd 100644 --- a/libs/gst/base/gstbasetransform.c +++ b/libs/gst/base/gstbasetransform.c @@ -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); diff --git a/tests/check/gst/gstbuffer.c b/tests/check/gst/gstbuffer.c index 5a8b9e0..f04bbdc 100644 --- a/tests/check/gst/gstbuffer.c +++ b/tests/check/gst/gstbuffer.c @@ -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); diff --git a/tests/check/gst/gstmemory.c b/tests/check/gst/gstmemory.c index 8bde54a..da4c77c 100644 --- a/tests/check/gst/gstmemory.c +++ b/tests/check/gst/gstmemory.c @@ -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)); -- 2.7.4