* Boston, MA 02111-1307, USA.
*/
-#include "config.h"
+/**
+ * SECTION:gstmemory
+ * @short_description: refcounted wrapper for memory blocks
+ * @see_also: #GstBuffer
+ *
+ * GstMemory is a lightweight refcounted object that wraps a region of memory.
+ * They are typically used to manage the data of a #GstBuffer.
+ *
+ * New memory can be created with gst_memory_new_wrapped() that wraps the memory
+ * allocated elsewhere and gst_memory_new_alloc() that creates a new GstMemory
+ * and the memory inside it.
+ *
+ * Refcounting of the memory block is performed with gst_memory_ref() and
+ * gst_memory_unref().
+ *
+ * The size of the memory can be retrieved and changed with
+ * gst_memory_get_sizes() and gst_memory_resize() respectively.
+ *
+ * Getting access to the data of the memory is performed with gst_memory_map().
+ * After the memory access is completed, gst_memory_unmap() should be called.
+ *
+ * Memory can be copied with gst_memory_copy(), which will returnn a writable
+ * copy. gst_memory_share() will create a new memory block that shares the
+ * memory with an existing memory block at a custom offset and with a custom
+ * size.
+ *
+ * Memory can be efficiently merged when gst_memory_is_span() returns TRUE and
+ * with the function gst_memory_span().
+ *
+ * Last reviewed on 2011-03-30 (0.11.0)
+ */
+#include "config.h"
#include "gst_private.h"
-
#include "gstmemory.h"
+
struct _GstMemoryImpl
{
GQuark name;
GstMemoryInfo info;
};
+/* default memory implementation */
typedef struct
{
GstMemory mem;
static const GstMemoryImpl *_default_mem_impl;
static const GstMemoryImpl *_default_share_impl;
+/* initialize the fields */
static void
_default_mem_init (GstMemoryDefault * mem, GstMemoryFlags flags,
GstMemory * parent, gsize slice_size, gpointer data,
mem->size = size;
}
+/* create a new memory block that manages the given memory */
static GstMemoryDefault *
_default_mem_new (GstMemoryFlags flags, GstMemory * parent, gpointer data,
GFreeFunc free_func, gsize maxsize, gsize offset, gsize size)
return mem;
}
+/* allocate the memory and structure in one block */
static GstMemoryDefault *
_default_mem_new_block (gsize maxsize, gsize align, gsize offset, gsize size)
{
static gboolean
_default_mem_unmap (GstMemoryDefault * mem, gpointer data, gsize size)
{
- mem->size = size;
+ if (size != -1)
+ mem->size = size;
return TRUE;
}
gboolean res;
guint8 *ptr = data;
- mem->size = size;
+ if (size != -1)
+ mem->size = size;
+ else
+ size = mem->size - mem->offset;
res =
gst_memory_unmap (mem->mem.parent, ptr - mem->offset, size + mem->offset);
if (size == -1)
size = mem->size > offset ? mem->size - offset : 0;
+
copy = _default_mem_new_block (mem->maxsize, 0, mem->offset + offset, size);
memcpy (copy->data, mem->data, mem->maxsize);
/**
* gst_memory_register:
- * @name:
- * @info:
+ * @name: the name of the implementation
+ * @info: #GstMemoryInfo
+ *
+ * Registers the memory implementation with @name and implementation functions
+ * @info.
*
- * Returns:
+ * Returns: a new #GstMemoryImpl.
*/
const GstMemoryImpl *
gst_memory_register (const gchar * name, const GstMemoryInfo * info)
return impl;
}
+/**
+ * gst_memory_new_wrapped:
+ * @flags: #GstMemoryFlags
+ * @data: data to wrap
+ * @free_func: function to free @data
+ * @maxsize: allocated size of @data
+ * @offset: offset in @data
+ * @size: size of valid data
+ *
+ * Allocate a new memory block that wraps the given @data.
+ *
+ * Returns: a new #GstMemory.
+ */
GstMemory *
gst_memory_new_wrapped (GstMemoryFlags flags, gpointer data,
GFreeFunc free_func, gsize maxsize, gsize offset, gsize size)
{
GstMemoryDefault *mem;
+ g_return_val_if_fail (data != NULL, NULL);
+ g_return_val_if_fail (offset + size <= maxsize, NULL);
+
mem = _default_mem_new (flags, NULL, data, free_func, maxsize, offset, size);
return (GstMemory *) mem;
}
+/**
+ * gst_memory_new_alloc:
+ * @maxsize: allocated size of @data
+ * @align: alignment for the data
+ *
+ * Allocate a new memory block with memory that is at least @maxsize big and las
+ * the given alignment.
+ *
+ * Returns: a new #GstMemory.
+ */
GstMemory *
gst_memory_new_alloc (gsize maxsize, gsize align)
{
return (GstMemory *) mem;
}
-GstMemory *
-gst_memory_new_copy (gsize maxsize, gsize align, gpointer data,
- gsize offset, gsize size)
-{
- GstMemoryDefault *mem;
-
- mem = _default_mem_new_block (maxsize, align, offset, size);
- memcpy (mem->data, data, maxsize);
-
- return (GstMemory *) mem;
-}
-
/**
* gst_memory_ref:
* @mem: a #GstMemory
*
+ * Increases the refcount of @mem.
+ *
* Returns: @mem with increased refcount
*/
GstMemory *
/**
* gst_memory_unref:
* @mem: a #GstMemory
+ *
+ * Decreases the refcount of @mem. When the refcount reaches 0, the free
+ * function of @mem will be called.
*/
void
gst_memory_unref (GstMemory * mem)
* @mem: a #GstMemory
* @maxsize: pointer to maxsize
*
- * Returns: the current size of @mem
+ * Get the current @size and @maxsize of @mem.
+ *
+ * Returns: the current sizes of @mem
*/
gsize
gst_memory_get_sizes (GstMemory * mem, gsize * maxsize)
return mem->impl->info.get_sizes (mem, maxsize);
}
+/**
+ * gst_memory_resize:
+ * @mem: a #GstMemory
+ * @offset: a new offset
+ * @size: a new size
+ *
+ * Resize the memory region. @mem should be writable and offset + size should be
+ * less than the maxsize of @mem.
+ */
+void
+gst_memory_resize (GstMemory * mem, gsize offset, gsize size)
+{
+ g_return_if_fail (mem != NULL);
+ g_return_if_fail (GST_MEMORY_IS_WRITABLE (mem));
+
+ mem->impl->info.resize (mem, offset, size);
+}
+
+/**
+ * gst_memory_map:
+ * @mem: a #GstMemory
+ * @size: pointer for size
+ * @maxsize: pointer for maxsize
+ * @flags: mapping flags
+ *
+ * Get a pointer to the memory of @mem that can be accessed according to @flags.
+ *
+ * @size and @maxsize will contain the size of the memory and the maximum
+ * allocated memory of @mem respectively. They can be set to NULL.
+ *
+ * Returns: a pointer to the memory of @mem.
+ */
gpointer
gst_memory_map (GstMemory * mem, gsize * size, gsize * maxsize,
GstMapFlags flags)
{
g_return_val_if_fail (mem != NULL, NULL);
+ g_return_val_if_fail (!(flags & GST_MAP_WRITE) ||
+ GST_MEMORY_IS_WRITABLE (mem), NULL);
return mem->impl->info.map (mem, size, maxsize, flags);
}
+/**
+ * gst_memory_unmap:
+ * @mem: a #GstMemory
+ * @data: data to unmap
+ * @size: new size of @mem
+ *
+ * Release the memory pointer obtained with gst_memory_map() and set the size of
+ * the memory to @size. @size can be set to -1 when the size should not be
+ * updated.
+ *
+ * Returns: TRUE when the memory was release successfully.
+ */
gboolean
gst_memory_unmap (GstMemory * mem, gpointer data, gsize size)
{
return mem->impl->info.unmap (mem, data, size);
}
+/**
+ * gst_memory_copy:
+ * @mem: a #GstMemory
+ * @offset: an offset to copy
+ * @size: size to copy
+ *
+ * Return a copy of @size bytes from @mem starting from @offset. This copy is
+ * guaranteed to be writable. @size can be set to -1 to return a copy all bytes
+ * from @offset.
+ *
+ * Returns: a new #GstMemory.
+ */
GstMemory *
gst_memory_copy (GstMemory * mem, gsize offset, gsize size)
{
return mem->impl->info.copy (mem, offset, size);
}
-void
-gst_memory_resize (GstMemory * mem, gsize offset, gsize size)
-{
- g_return_if_fail (mem != NULL);
-
- mem->impl->info.resize (mem, offset, size);
-}
-
+/**
+ * gst_memory_share:
+ * @mem: a #GstMemory
+ * @offset: an offset to share
+ * @size: size to share
+ *
+ * Return a shared copy of @size bytes from @mem starting from @offset. No memory
+ * copy is performed and the memory region is simply shared. The result is
+ * guaranteed to be not-writable. @size can be set to -1 to return a share all bytes
+ * from @offset.
+ *
+ * Returns: a new #GstMemory.
+ */
GstMemory *
gst_memory_share (GstMemory * mem, gsize offset, gsize size)
{
return mem->impl->info.share (mem, offset, size);
}
+/**
+ * gst_memory_is_span:
+ * @mem1: a #GstMemory
+ * @mem2: a #GstMemory
+ * @offset: a pointer to a result offset
+ *
+ * Check if @mem1 and mem2 share the memory with a common parent memory object
+ * and that the memory is contiguous.
+ *
+ * If this is the case, the memory of @mem1 and @mem2 can be merged
+ * efficiently by performing gst_memory_share() on the parent object from
+ * the returned @offset.
+ *
+ * Returns: %TRUE if the memory is contiguous and of a common parent.
+ */
gboolean
gst_memory_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset)
{
typedef struct _GstMemoryInfo GstMemoryInfo;
typedef struct _GstMemoryImpl GstMemoryImpl;
+/**
+ * GstMemoryFlags:
+ * @GST_MEMORY_FLAG_READONLY: memory is readonly
+ *
+ * Flags for wrapped memory.
+ */
typedef enum {
GST_MEMORY_FLAG_READONLY = (1 << 0)
} GstMemoryFlags;
-
+/**
+ * GST_MEMORY_IS_WRITABLE:
+ * @mem: a #GstMemory
+ *
+ * Check if @mem is writable.
+ */
#define GST_MEMORY_IS_WRITABLE(mem) (((mem)->refcount == 1) && \
(((mem)->parent == NULL) || ((mem)->parent->refcount == 1)) && \
(((mem)->flags & GST_MEMORY_FLAG_READONLY) == 0))
/**
* GstMemory:
* @impl: pointer to the #GstMemoryImpl
+ * @flags: memory flags
* @refcount: refcount
* @parent: parent memory block
*
GstMemory *parent;
};
+/**
+ * GstMapFlags:
+ * @GST_MAP_READ: map for read access
+ * @GST_MAP_WRITE: map for write access
+ *
+ * Flags used when mapping memory
+ */
typedef enum {
GST_MAP_READ = (1 << 0),
GST_MAP_WRITE = (1 << 1),
} GstMapFlags;
+/**
+ * GST_MAP_READWRITE:
+ *
+ * Map for readwrite access
+ */
#define GST_MAP_READWRITE (GST_MAP_READ | GST_MAP_WRITE)
/**
*/
#define GST_MEMORY_TRACE_NAME "GstMemory"
+/**
+ * GstMemoryGetSizesFunction:
+ * @mem: a #GstMemory
+ * @maxsize: result pointer for maxsize
+ *
+ * Retrieve the size and maxsize of @mem.
+ *
+ * Returns: the size of @mem and the maximum allocated size in @maxsize.
+ */
typedef gsize (*GstMemoryGetSizesFunction) (GstMemory *mem, gsize *maxsize);
+
+/**
+ * GstMemoryResizeFunction:
+ * @mem: a #GstMemory
+ * @offset: the new offset
+ * @size: the new size
+ *
+ * Adjust the size and offset of @mem. @offset bytes will be skipped from the
+ * current first byte in @mem as retrieved with gst_memory_map() and the new
+ * size will be set to @size.
+ *
+ * @size can be set to -1, which will only adjust the offset.
+ */
typedef void (*GstMemoryResizeFunction) (GstMemory *mem, gsize offset, gsize size);
+/**
+ * GstMemoryMapFunction:
+ * @mem: a #GstMemory
+ * @size: pointer for the size
+ * @maxsize: pointer for the maxsize
+ * @flags: access mode for the memory
+ *
+ * Get the memory of @mem that can be accessed according to the mode specified
+ * in @flags. @size and @maxsize will respectively contain the current amount of
+ * valid bytes in the returned memory and the maximum allocated memory.
+ * @size and @maxsize can optionally be set to NULL.
+ *
+ * Returns: a pointer to memory. @size bytes are currently used from the
+ * returned pointer and @maxsize bytes can potentially be used.
+ */
typedef gpointer (*GstMemoryMapFunction) (GstMemory *mem, gsize *size, gsize *maxsize,
GstMapFlags flags);
+
+/**
+ * GstMemoryUnmapFunction:
+ * @mem: a #GstMemory
+ * @data: the data pointer
+ * @size: the new size
+ *
+ * Return the pointer previously retrieved with gst_memory_map() and adjust the
+ * size of the memory with @size. @size can optionally be set to -1 to not
+ * modify the size.
+ *
+ * Returns: %TRUE on success.
+ */
typedef gboolean (*GstMemoryUnmapFunction) (GstMemory *mem, gpointer data, gsize size);
+
+/**
+ * GstMemoryFreeFunction:
+ * @mem: a #GstMemory
+ *
+ * Free the memory used by @mem. This function is usually called when the
+ * refcount of the @mem has reached 0.
+ */
typedef void (*GstMemoryFreeFunction) (GstMemory *mem);
+/**
+ * GstMemoryCopyFunction:
+ * @mem: a #GstMemory
+ * @offset: an offset
+ * @size: a size
+ *
+ * Copy @size bytes from @mem starting at @offset and return them wrapped in a
+ * new GstMemory object.
+ * If @size is set to -1, all bytes starting at @offset are copied.
+ *
+ * Returns: a new #GstMemory object wrapping a copy of the requested region in
+ * @mem.
+ */
typedef GstMemory * (*GstMemoryCopyFunction) (GstMemory *mem, gsize offset, gsize size);
+
+/**
+ * GstMemoryShareFunction:
+ * @mem: a #GstMemory
+ * @offset: an offset
+ * @size: a size
+ *
+ * Share @size bytes from @mem starting at @offset and return them wrapped in a
+ * new GstMemory object. If @size is set to -1, all bytes starting at @offset are
+ * shared. This function does not make a copy of the bytes in @mem.
+ *
+ * Returns: a new #GstMemory object sharing the requested region in @mem.
+ */
typedef GstMemory * (*GstMemoryShareFunction) (GstMemory *mem, gsize offset, gsize size);
+
+/**
+ * GstMemoryIsSpanFunction:
+ * @mem1: a #GstMemory
+ * @mem1: a #GstMemory
+ * @offset: a result offset
+ *
+ * Check if @mem1 and @mem2 occupy contiguous memory and return the offset of
+ * @mem1 in the parent buffer in @offset.
+ *
+ * Returns: %TRUE if @mem1 and @mem2 are in contiguous memory.
+ */
typedef gboolean (*GstMemoryIsSpanFunction) (GstMemory *mem1, GstMemory *mem2, gsize *offset);
/**
* GstMemoryInfo:
- * @get_sizes:
+ * @get_sizes: the implementation of the GstMemoryGetSizesFunction
+ * @resize: the implementation of the GstMemoryResizeFunction
+ * @map: the implementation of the GstMemoryMapFunction
+ * @unmap: the implementation of the GstMemoryUnmapFunction
+ * @free: the implementation of the GstMemoryFreeFunction
+ * @copy: the implementation of the GstMemoryCopyFunction
+ * @share: the implementation of the GstMemoryShareFunction
+ * @is_span: the implementation of the GstMemoryIsSpanFunction
*
- * The #GstMemoryInfo is used to register new memory implementations.
+ * The #GstMemoryInfo is used to register new memory implementations and contain
+ * the implementations for various memory operations.
*/
struct _GstMemoryInfo {
GstMemoryGetSizesFunction get_sizes;
GstMemory * gst_memory_new_wrapped (GstMemoryFlags flags, gpointer data, GFreeFunc free_func,
gsize maxsize, gsize offset, gsize size);
GstMemory * gst_memory_new_alloc (gsize maxsize, gsize align);
-GstMemory * gst_memory_new_copy (gsize maxsize, gsize align, gpointer data,
- gsize offset, gsize size);
/* refcounting */
GstMemory * gst_memory_ref (GstMemory *mem);
GstMemory **mem2, gsize len2, gsize size);
-const GstMemoryImpl * gst_memory_register (const gchar *impl, const GstMemoryInfo *info);
+const GstMemoryImpl * gst_memory_register (const gchar *name, const GstMemoryInfo *info);
#if 0
const GstMemoryInfo * gst_memory_get_info (const gchar * impl);