element: Enforce that elements created by gst_element_factory_create/make() are floating
[platform/upstream/gstreamer.git] / gst / gstmemory.c
index 9e97d1e..a68aa47 100644 (file)
@@ -21,6 +21,7 @@
 
 /**
  * SECTION:gstmemory
+ * @title: GstMemory
  * @short_description: refcounted wrapper for memory blocks
  * @see_also: #GstBuffer
  *
@@ -94,6 +95,7 @@ _gst_memory_free (GstMemory * mem)
   allocator = mem->allocator;
 
   gst_allocator_free (allocator, mem);
+
   gst_object_unref (allocator);
 }
 
@@ -123,6 +125,7 @@ gst_memory_init (GstMemory * mem, GstMemoryFlags flags,
 
   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);
   }
@@ -161,8 +164,8 @@ gst_memory_is_type (GstMemory * mem, const gchar * mem_type)
 /**
  * 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.
  *
@@ -197,6 +200,7 @@ void
 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);
 
@@ -292,15 +296,19 @@ gst_memory_map (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;
@@ -314,8 +322,9 @@ lock_failed:
   }
 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;
@@ -336,19 +345,22 @@ gst_memory_unmap (GstMemory * mem, GstMapInfo * info)
   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.
  */
@@ -367,13 +379,13 @@ gst_memory_copy (GstMemory * mem, gssize offset, gssize size)
 /**
  * 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.
  */
@@ -386,8 +398,28 @@ gst_memory_share (GstMemory * mem, gssize offset, gssize size)
   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;
 }
 
@@ -395,7 +427,7 @@ gst_memory_share (GstMemory * mem, gssize offset, gssize size)
  * 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.