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.
#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 {
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;
{
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;
/* 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 */
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
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);
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);
*
* 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 *
*
* 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)
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;
}
/**
* 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
* 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;
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
* 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;
/**
* 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:
* 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:
/**
* 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);
/**
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,
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;
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);
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);
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);
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);
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);
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));
{
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");
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);
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);
{
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);
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);
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);
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);
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));
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));