/**
* SECTION:gstmemory
+ * @title: GstMemory
* @short_description: refcounted wrapper for memory blocks
* @see_also: #GstBuffer
*
* in the allocated region.
*
* Memory is usually created by allocators with a gst_allocator_alloc()
- * method call. When NULL is used as the allocator, the default allocator will
+ * method call. When %NULL is used as the allocator, the default allocator will
* be used.
*
* New allocators can be registered with gst_allocator_register().
* 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.
- *
- * Last reviewed on 2012-03-28 (0.11.3)
+ * Memory can be efficiently merged when gst_memory_is_span() returns %TRUE.
*/
#ifdef HAVE_CONFIG_H
#include "gst_private.h"
#include "gstmemory.h"
+GType _gst_memory_type = 0;
GST_DEFINE_MINI_OBJECT_TYPE (GstMemory, gst_memory);
static GstMemory *
allocator = mem->allocator;
gst_allocator_free (allocator, mem);
+
gst_object_unref (allocator);
}
mem->allocator = gst_object_ref (allocator);
if (parent) {
+ /* FIXME 2.0: this can fail if the memory is already write locked */
gst_memory_lock (parent, GST_LOCK_FLAG_EXCLUSIVE);
gst_memory_ref (parent);
}
/**
* gst_memory_get_sizes:
* @mem: a #GstMemory
- * @offset: pointer to offset
- * @maxsize: pointer to maxsize
+ * @offset: (out) (allow-none): pointer to offset
+ * @maxsize: (out) (allow-none): pointer to maxsize
*
* Get the current @size, @offset and @maxsize of @mem.
*
gst_memory_resize (GstMemory * mem, gssize offset, gsize size)
{
g_return_if_fail (mem != NULL);
+ g_return_if_fail (gst_memory_is_writable (mem));
g_return_if_fail (offset >= 0 || mem->offset >= -offset);
g_return_if_fail (size + mem->offset + offset <= mem->maxsize);
* This function takes ownership of old @mem and returns a reference to a new
* #GstMemory.
*
- * Returns: (transfer full): a #GstMemory object mapped with @flags or NULL when
- * a mapping is not possible.
+ * Returns: (transfer full) (nullable): a #GstMemory object mapped
+ * with @flags or %NULL when a mapping is not possible.
*/
GstMemory *
gst_memory_make_mapped (GstMemory * mem, GstMapInfo * info, GstMapFlags flags)
if (!gst_memory_lock (mem, (GstLockFlags) flags))
goto lock_failed;
- info->data = mem->allocator->mem_map (mem, mem->maxsize, flags);
+ info->flags = flags;
+ info->memory = mem;
+ info->size = mem->size;
+ info->maxsize = mem->maxsize - mem->offset;
+
+ if (mem->allocator->mem_map_full)
+ info->data = mem->allocator->mem_map_full (mem, info, mem->maxsize);
+ else
+ info->data = mem->allocator->mem_map (mem, mem->maxsize, flags);
if (G_UNLIKELY (info->data == NULL))
goto error;
- info->memory = mem;
- info->flags = flags;
- info->size = mem->size;
- info->maxsize = mem->maxsize - mem->offset;
info->data = info->data + mem->offset;
return TRUE;
lock_failed:
{
GST_CAT_DEBUG (GST_CAT_MEMORY, "mem %p: lock %d failed", mem, flags);
+ memset (info, 0, sizeof (GstMapInfo));
return FALSE;
}
error:
{
- /* something went wrong, restore the orginal state again */
- GST_CAT_ERROR (GST_CAT_MEMORY, "mem %p: subclass map failed", mem);
+ /* something went wrong, restore the original state again
+ * it is up to the subclass to log an error if needed. */
+ GST_CAT_INFO (GST_CAT_MEMORY, "mem %p: subclass map failed", mem);
gst_memory_unlock (mem, (GstLockFlags) flags);
+ memset (info, 0, sizeof (GstMapInfo));
return FALSE;
}
}
g_return_if_fail (info != NULL);
g_return_if_fail (info->memory == mem);
- mem->allocator->mem_unmap (mem);
+ if (mem->allocator->mem_unmap_full)
+ mem->allocator->mem_unmap_full (mem, info);
+ else
+ mem->allocator->mem_unmap (mem);
gst_memory_unlock (mem, (GstLockFlags) info->flags);
}
/**
* gst_memory_copy:
* @mem: a #GstMemory
- * @offset: an offset to copy
- * @size: size to copy or -1 to copy all bytes from offset
+ * @offset: offset to copy from
+ * @size: size to copy, or -1 to copy to the end of the memory region
*
* 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.
+ * guaranteed to be writable. @size can be set to -1 to return a copy
+ * from @offset to the end of the memory region.
*
* Returns: a new #GstMemory.
*/
/**
* gst_memory_share:
* @mem: a #GstMemory
- * @offset: an offset to share
- * @size: size to share or -1 to share bytes from offset
+ * @offset: offset to share from
+ * @size: size to share, or -1 to share to the end of the memory region
*
* 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.
+ * is guaranteed to be non-writable. @size can be set to -1 to return a shared
+ * copy from @offset to the end of the memory region.
*
* Returns: a new #GstMemory.
*/
g_return_val_if_fail (!GST_MEMORY_FLAG_IS_SET (mem, GST_MEMORY_FLAG_NO_SHARE),
NULL);
+ /* whether we can lock the memory exclusively */
+ /* in order to maintain backwards compatibility by not requiring subclasses
+ * to lock the memory themselves and propagate the possible failure in their
+ * mem_share implementation */
+ /* FIXME 2.0: remove and fix gst_memory_init() and/or all memory subclasses
+ * to propagate this failure case */
+ if (!gst_memory_lock (mem, GST_LOCK_FLAG_EXCLUSIVE))
+ return NULL;
+
+ /* double lock to ensure we are not mapped writable without an
+ * exclusive lock. */
+ if (!gst_memory_lock (mem, GST_LOCK_FLAG_EXCLUSIVE)) {
+ gst_memory_unlock (mem, GST_LOCK_FLAG_EXCLUSIVE);
+ return NULL;
+ }
+
shared = mem->allocator->mem_share (mem, offset, size);
+ /* unlocking before calling the subclass would be racy */
+ gst_memory_unlock (mem, GST_LOCK_FLAG_EXCLUSIVE);
+ gst_memory_unlock (mem, GST_LOCK_FLAG_EXCLUSIVE);
+
return shared;
}
* gst_memory_is_span:
* @mem1: a #GstMemory
* @mem2: a #GstMemory
- * @offset: a pointer to a result offset
+ * @offset: (out): 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.
return TRUE;
}
+
+void
+_priv_gst_memory_initialize (void)
+{
+ _gst_memory_type = gst_memory_get_type ();
+}