summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2012-01-18 14:45:28 +0100
committerWim Taymans <wim.taymans@collabora.co.uk>2012-01-18 14:45:28 +0100
commit7fb3ec7a086600411264cae0b21b51540060057d (patch)
tree32f231d0e8182aa85f6138bbc0016df7fe1c1dc0
parent10d901291e7bad1736a5a9792fa20884cde2b2b0 (diff)
WIP: attempt to add locking to miniobjectminiobject-lock
Attempt to decouple the refcounting from writability of the miniobject. For this we need to explicitely mark when the object is in use. Use a try_lock and unlock method for this on the miniobject, we don't actually block when the lock can't be taken but we simply return an error.
-rw-r--r--gst/gstbuffer.c290
-rw-r--r--gst/gstbuffer.h54
-rw-r--r--gst/gstcaps.c6
-rw-r--r--gst/gstcaps.h20
-rw-r--r--gst/gstevent.c2
-rw-r--r--gst/gstevent.h25
-rw-r--r--gst/gstmemory.c274
-rw-r--r--gst/gstmemory.h69
-rw-r--r--gst/gstminiobject.c117
-rw-r--r--gst/gstminiobject.h26
-rw-r--r--gst/gstquery.c143
-rw-r--r--gst/gstquery.h20
-rw-r--r--libs/gst/base/gstbaseparse.c9
-rw-r--r--libs/gst/base/gstbasesink.c4
-rw-r--r--libs/gst/base/gstbasesrc.c9
-rw-r--r--libs/gst/base/gstbasetransform.c12
-rw-r--r--libs/gst/base/gstcollectpads2.c3
-rw-r--r--plugins/elements/gstcapsfilter.c3
-rw-r--r--plugins/elements/gstfunnel.c3
-rw-r--r--plugins/elements/gstidentity.c9
-rw-r--r--plugins/elements/gstinputselector.c4
-rw-r--r--plugins/elements/gstqueue.c6
-rw-r--r--plugins/elements/gstvalve.c3
-rw-r--r--tests/check/gst/gstbuffer.c33
-rw-r--r--tests/check/gst/gstmemory.c177
-rw-r--r--tests/check/gst/gstminiobject.c4
-rw-r--r--tools/gst-inspect.c3
27 files changed, 676 insertions, 652 deletions
diff --git a/gst/gstbuffer.c b/gst/gstbuffer.c
index f333cd66c..bb94fc772 100644
--- a/gst/gstbuffer.c
+++ b/gst/gstbuffer.c
@@ -119,7 +119,7 @@
GType _gst_buffer_type = 0;
static GstMemory *_gst_buffer_arr_span (GstMemory ** mem[], gsize len[],
- guint n, gsize offset, gsize size, gboolean writable);
+ guint n, gsize offset, gsize size);
typedef struct _GstMetaItem GstMetaItem;
@@ -136,6 +136,7 @@ struct _GstMetaItem
#define GST_BUFFER_MEM_ARRAY(b) (((GstBufferImpl *)(b))->mem)
#define GST_BUFFER_MEM_PTR(b,i) (((GstBufferImpl *)(b))->mem[i])
#define GST_BUFFER_BUFMEM(b) (((GstBufferImpl *)(b))->bufmem)
+#define GST_BUFFER_MERGED(b) (((GstBufferImpl *)(b))->merged)
#define GST_BUFFER_META(b) (((GstBufferImpl *)(b))->item)
typedef struct
@@ -149,13 +150,16 @@ typedef struct
/* memory of the buffer when allocated from 1 chunk */
GstMemory *bufmem;
+ /* cache for last merged memory */
+ GstMemory *merged;
+
/* FIXME, make metadata allocation more efficient by using part of the
* GstBufferImpl */
GstMetaItem *item;
} GstBufferImpl;
static GstMemory *
-_span_memory (GstBuffer * buffer, gsize offset, gsize size, gboolean writable)
+_span_memory (GstBuffer * buffer, gsize offset, gsize size)
{
GstMemory *span, **mem[1];
gsize len[1];
@@ -167,7 +171,7 @@ _span_memory (GstBuffer * buffer, gsize offset, gsize size, gboolean writable)
if (size == -1)
size = gst_buffer_get_size (buffer);
- span = _gst_buffer_arr_span (mem, len, 1, offset, size, writable);
+ span = _gst_buffer_arr_span (mem, len, 1, offset, size);
return span;
}
@@ -197,7 +201,7 @@ _memory_add (GstBuffer * buffer, guint idx, GstMemory * mem)
/* FIXME, there is room for improvement here: We could only try to merge
* 2 buffers to make some room. If we can't efficiently merge 2 buffers we
* could try to only merge the two smallest buffers to avoid memcpy, etc. */
- _replace_memory (buffer, _span_memory (buffer, 0, -1, FALSE));
+ _replace_memory (buffer, _span_memory (buffer, 0, -1));
/* we now have 1 single spanned buffer */
len = 1;
}
@@ -248,7 +252,10 @@ gst_buffer_copy_into (GstBuffer * dest, GstBuffer * src,
if (G_UNLIKELY (dest == src))
return;
- g_return_if_fail (gst_buffer_is_writable (dest));
+ if (!gst_buffer_try_lock (src, GST_LOCK_READ)) {
+ g_warning ("failed to lock buffer %p in READ mode", src);
+ return;
+ }
bufsize = gst_buffer_get_size (src);
g_return_if_fail (bufsize >= offset);
@@ -256,6 +263,12 @@ gst_buffer_copy_into (GstBuffer * dest, GstBuffer * src,
size = bufsize - offset;
g_return_if_fail (bufsize >= offset + size);
+ if (!gst_buffer_try_lock (dest, GST_LOCK_WRITE)) {
+ g_warning ("failed to lock buffer %p in WRITE mode", dest);
+ gst_buffer_unlock (src);
+ return;
+ }
+
GST_CAT_LOG (GST_CAT_BUFFER, "copy %p to %p, offset %" G_GSIZE_FORMAT
"-%" G_GSIZE_FORMAT "/%" G_GSIZE_FORMAT, src, dest, offset, size,
bufsize);
@@ -319,7 +332,7 @@ gst_buffer_copy_into (GstBuffer * dest, GstBuffer * src,
}
}
if (flags & GST_BUFFER_COPY_MERGE) {
- _replace_memory (dest, _span_memory (dest, 0, size, FALSE));
+ _replace_memory (dest, _span_memory (dest, 0, size));
}
}
@@ -332,6 +345,8 @@ gst_buffer_copy_into (GstBuffer * dest, GstBuffer * src,
info->copy_func (dest, meta, src, offset, size);
}
}
+ gst_buffer_unlock (dest);
+ gst_buffer_unlock (src);
}
static GstBuffer *
@@ -432,6 +447,7 @@ gst_buffer_init (GstBufferImpl * buffer, gsize size)
GST_BUFFER_MEM_LEN (buffer) = 0;
GST_BUFFER_META (buffer) = NULL;
+ GST_BUFFER_MERGED (buffer) = NULL;
}
/**
@@ -538,7 +554,7 @@ gst_buffer_new_allocate (const GstAllocator * allocator, gsize size,
* that a finalize won't free the buffer */
data = gst_memory_map (mem, &asize, NULL, GST_MAP_WRITE);
gst_buffer_init ((GstBufferImpl *) data, 0);
- gst_memory_unmap (mem, data, asize);
+ gst_memory_unmap (mem);
/* strip off the buffer */
gst_memory_resize (mem, sizeof (GstBufferImpl), size);
@@ -637,77 +653,80 @@ void
gst_buffer_take_memory (GstBuffer * buffer, gint idx, GstMemory * mem)
{
g_return_if_fail (GST_IS_BUFFER (buffer));
- g_return_if_fail (gst_buffer_is_writable (buffer));
g_return_if_fail (mem != NULL);
g_return_if_fail (idx == -1 ||
(idx >= 0 && idx <= GST_BUFFER_MEM_LEN (buffer)));
- _memory_add (buffer, idx, mem);
-}
-
-static GstMemory *
-_get_memory (GstBuffer * buffer, guint idx, gboolean write)
-{
- GstMemory *mem;
+ if (!gst_buffer_try_lock (buffer, GST_LOCK_WRITE)) {
+ g_warning ("failed to lock buffer %p in WRITE mode", buffer);
+ return;
+ }
- mem = GST_BUFFER_MEM_PTR (buffer, idx);
+ _memory_add (buffer, idx, mem);
- if (G_UNLIKELY (write && !gst_memory_is_writable (mem))) {
- GstMemory *copy;
- GST_CAT_LOG (GST_CAT_BUFFER,
- "making writable copy of memory %p in buffer %p", mem, buffer);
- /* replace with a writable copy */
- copy = gst_memory_copy (mem, 0, -1);
- GST_BUFFER_MEM_PTR (buffer, idx) = copy;
- gst_memory_unref (mem);
- mem = copy;
- }
- return mem;
+ gst_buffer_unlock (buffer);
}
/**
* gst_buffer_peek_memory:
* @buffer: a #GstBuffer.
* @idx: an index
- * @flags: #GstMapFlags
*
- * Get the memory block in @buffer at @idx for memory access in @flags.
+ * Get the memory block in @buffer at @idx.
* This function does not return a refcount to the memory block. The memory
* block stays valid for as long as the caller has a valid reference to @buffer
* and as long as no operations that modify the memory blocks are called, such
* as gst_buffer_remove_memory_range(), gst_buffer_take_memory() and gst_buffer_resize().
*
- * @buffer should be writable when @flags contains #GST_MAP_WRITE. If the memory
- * at @idx is not writable, a new writable copy will be installed in @buffer and
- * returned.
- *
* Returns: a #GstMemory at @idx.
*/
GstMemory *
-gst_buffer_peek_memory (GstBuffer * buffer, guint idx, GstMapFlags flags)
+gst_buffer_peek_memory (GstBuffer * buffer, guint idx)
{
GstMemory *mem;
- gboolean write;
-
- write = (flags & GST_MAP_WRITE) != 0;
g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
g_return_val_if_fail (idx < GST_BUFFER_MEM_LEN (buffer), NULL);
- /* check if we can write when asked for write access */
- if (G_UNLIKELY (write && !gst_buffer_is_writable (buffer)))
- goto not_writable;
-
- mem = _get_memory (buffer, idx, write);
+ mem = GST_BUFFER_MEM_PTR (buffer, idx);
return mem;
+}
- /* ERRORS */
-not_writable:
- {
- g_return_val_if_fail (gst_buffer_is_writable (buffer), NULL);
- return NULL;
+/**
+ * gst_buffer_get_merged_memory:
+ * @buffer: a #GstBuffer.
+ *
+ * Return a #GstMemory object that contains all the memory in @buffer. If there
+ * was only one memory in @buffer, it will be returned directly, otherwise all
+ * memory objects will be merged into one object that will be returned.
+ *
+ * Returns: a #GstMemory with the merged memory in @buffer. This function can
+ * return %NULL if there is no memory in @buffer. Use gst_memory_unref() after
+ * usage.
+ */
+GstMemory *
+gst_buffer_get_merged_memory (GstBuffer * buffer)
+{
+ guint len;
+ GstMemory *mem;
+
+ g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
+
+ len = GST_BUFFER_MEM_LEN (buffer);
+
+ if (G_UNLIKELY (len == 0)) {
+ /* no memory */
+ mem = NULL;
+ } else if (G_LIKELY (len == 1)) {
+ /* we can take the first one */
+ mem = GST_BUFFER_MEM_PTR (buffer, 0);
+ gst_memory_ref (mem);
+ } else {
+ /* we need to span memory */
+ mem = _span_memory (buffer, 0, -1);
}
+ return mem;
}
/**
@@ -726,7 +745,11 @@ gst_buffer_remove_memory_range (GstBuffer * buffer, guint idx, guint length)
guint len, i, end;
g_return_if_fail (GST_IS_BUFFER (buffer));
- g_return_if_fail (gst_buffer_is_writable (buffer));
+
+ if (!gst_buffer_try_lock (buffer, GST_LOCK_WRITE)) {
+ g_warning ("failed to lock buffer %p in WRITE mode", buffer);
+ return;
+ }
len = GST_BUFFER_MEM_LEN (buffer);
if (length == -1) {
@@ -743,6 +766,8 @@ gst_buffer_remove_memory_range (GstBuffer * buffer, guint idx, guint length)
&GST_BUFFER_MEM_PTR (buffer, end), (len - end) * sizeof (gpointer));
}
GST_BUFFER_MEM_LEN (buffer) = len - length;
+
+ gst_buffer_unlock (buffer);
}
/**
@@ -824,9 +849,13 @@ gst_buffer_resize (GstBuffer * buffer, gssize offset, gssize size)
gsize bsize, bufsize, bufoffs, bufmax;
GstMemory *mem;
- g_return_if_fail (gst_buffer_is_writable (buffer));
g_return_if_fail (size >= -1);
+ if (!gst_buffer_try_lock (buffer, GST_LOCK_WRITE)) {
+ g_warning ("failed to lock buffer %p in WRITE mode", buffer);
+ return;
+ }
+
bufsize = gst_buffer_get_sizes (buffer, &bufoffs, &bufmax);
GST_CAT_LOG (GST_CAT_BUFFER, "trim %p %" G_GSSIZE_FORMAT "-%" G_GSSIZE_FORMAT
@@ -868,25 +897,14 @@ gst_buffer_resize (GstBuffer * buffer, gssize offset, gssize size)
if (offset != 0 || left != bsize) {
/* we need to clip something */
- if (gst_memory_is_writable (mem)) {
- gst_memory_resize (mem, offset, left);
- } else {
- GstMemory *tmp;
-
- if (mem->flags & GST_MEMORY_FLAG_NO_SHARE)
- tmp = gst_memory_copy (mem, offset, left);
- else
- tmp = gst_memory_share (mem, offset, left);
-
- gst_memory_unref (mem);
- mem = tmp;
- }
+ gst_memory_resize (mem, offset, left);
}
offset = noffs;
size -= left;
GST_BUFFER_MEM_PTR (buffer, i) = mem;
}
+ gst_buffer_unlock (buffer);
}
/**
@@ -917,74 +935,56 @@ gpointer
gst_buffer_map (GstBuffer * buffer, gsize * size, gsize * maxsize,
GstMapFlags flags)
{
- guint len;
- gpointer data;
+ gpointer data = NULL;
GstMemory *mem;
- gboolean write, writable;
g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
- write = (flags & GST_MAP_WRITE) != 0;
- writable = gst_buffer_is_writable (buffer);
-
- /* check if we can write when asked for write access */
- if (G_UNLIKELY (write && !writable))
- goto not_writable;
-
- len = GST_BUFFER_MEM_LEN (buffer);
+ do {
+ mem = g_atomic_pointer_get (&GST_BUFFER_MERGED (buffer));
+ /* if we have a merged copy, use that */
+ if (mem != NULL)
+ break;
- if (G_UNLIKELY (len == 0)) {
+ mem = gst_buffer_get_merged_memory (buffer);
/* no memory, return immediately */
- if (size)
- *size = 0;
- if (maxsize)
- *maxsize = 0;
- return NULL;
- }
+ if (G_UNLIKELY (mem == NULL))
+ goto no_memory;
- if (G_LIKELY (len == 1)) {
- /* we can take the first one */
- mem = GST_BUFFER_MEM_PTR (buffer, 0);
- } else {
- /* we need to span memory */
- if (writable) {
- /* if we can write, we can change the memory with the spanned
- * memory */
- mem = _span_memory (buffer, 0, -1, write);
- _replace_memory (buffer, mem);
- } else {
- gsize bsize;
-
- /* extract all data in new memory, FIXME slow!! */
- bsize = gst_buffer_get_size (buffer);
-
- data = g_malloc (bsize);
- gst_buffer_extract (buffer, 0, data, bsize);
- if (size)
- *size = bsize;
- if (maxsize)
- *maxsize = bsize;
- return data;
+ /* now try to map */
+ data = gst_memory_map (mem, size, maxsize, flags);
+ if (data == NULL && (flags & GST_MAP_WRITE)) {
+ GstMemory *tmp;
+ /* make a (writable) copy */
+ tmp = gst_memory_copy (mem, 0, -1);
+ gst_memory_unref (mem);
+ mem = tmp;
}
- }
- if (G_UNLIKELY (write && !gst_memory_is_writable (mem))) {
- GstMemory *copy;
- /* replace with a writable copy */
- copy = gst_memory_copy (mem, 0, -1);
- GST_BUFFER_MEM_PTR (buffer, 0) = copy;
+ /* try to swap in the new memory */
+ if (g_atomic_pointer_compare_and_exchange (&GST_BUFFER_MERGED (buffer),
+ NULL, mem))
+ break;
+
+ /* something changed, try again */
gst_memory_unref (mem);
- mem = copy;
- }
+ data = NULL;
+ } while (1);
- data = gst_memory_map (mem, size, maxsize, flags);
+ GST_DEBUG_OBJECT (buffer, "map %p", mem);
+ if (data == NULL)
+ data = gst_memory_map (mem, size, maxsize, flags);
return data;
- /* ERROR */
-not_writable:
+ /* ERRORS */
+no_memory:
{
- g_return_val_if_fail (gst_buffer_is_writable (buffer), NULL);
+ GST_ERROR ("buffer has no memory");
+ if (size)
+ *size = 0;
+ if (maxsize)
+ *maxsize = 0;
return NULL;
}
}
@@ -1005,24 +1005,26 @@ gboolean
gst_buffer_unmap (GstBuffer * buffer, gpointer data, gssize size)
{
gboolean result;
- guint len;
+ GstMemory *mem;
g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
g_return_val_if_fail (size >= -1, FALSE);
- len = GST_BUFFER_MEM_LEN (buffer);
-
- if (G_LIKELY (len == 1)) {
- GstMemory *mem = GST_BUFFER_MEM_PTR (buffer, 0);
+ /* replace the merged pointer with NULL */
+ do {
+ mem = g_atomic_pointer_get (&GST_BUFFER_MERGED (buffer));
+ } while (!g_atomic_pointer_compare_and_exchange (&GST_BUFFER_MERGED (buffer),
+ mem, NULL));
- result = gst_memory_unmap (mem, data, size);
+ /* and unmap */
+ GST_DEBUG_OBJECT (buffer, "unmap %p", mem);
+ if (mem) {
+ result = gst_memory_unmap (mem);
+ gst_memory_unref (mem);
} else {
- /* this must have been from read-only access. After _map, the buffer either
- * only contains 1 memory block or it allocated memory to join memory
- * blocks. It's not allowed to add buffers between _map and _unmap. */
- g_free (data);
- result = TRUE;
+ result = FALSE;
}
+
return result;
}
@@ -1046,9 +1048,14 @@ gst_buffer_fill (GstBuffer * buffer, gsize offset, gconstpointer src,
const guint8 *ptr = src;
g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
- g_return_val_if_fail (gst_buffer_is_writable (buffer), 0);
g_return_val_if_fail (src != NULL, 0);
+ if (!gst_buffer_try_lock (buffer, GST_LOCK_WRITE)) {
+ g_warning ("failed to lock buffer %p in WRITE mode", buffer);
+ return 0;
+ }
+
+
len = GST_BUFFER_MEM_LEN (buffer);
left = size;
@@ -1057,7 +1064,7 @@ gst_buffer_fill (GstBuffer * buffer, gsize offset, gconstpointer src,
gsize ssize, tocopy;
GstMemory *mem;
- mem = _get_memory (buffer, i, TRUE);
+ mem = GST_BUFFER_MEM_PTR (buffer, i);
data = gst_memory_map (mem, &ssize, NULL, GST_MAP_WRITE);
if (ssize > offset) {
@@ -1071,7 +1078,7 @@ gst_buffer_fill (GstBuffer * buffer, gsize offset, gconstpointer src,
/* offset past buffer, skip */
offset -= ssize;
}
- gst_memory_unmap (mem, data, ssize);
+ gst_memory_unmap (mem);
}
return size - left;
}
@@ -1119,7 +1126,7 @@ gst_buffer_extract (GstBuffer * buffer, gsize offset, gpointer dest, gsize size)
/* offset past buffer, skip */
offset -= ssize;
}
- gst_memory_unmap (mem, data, ssize);
+ gst_memory_unmap (mem);
}
return size - left;
}
@@ -1167,7 +1174,7 @@ gst_buffer_memcmp (GstBuffer * buffer, gsize offset, gconstpointer mem,
/* offset past buffer, skip */
offset -= ssize;
}
- gst_memory_unmap (mem, data, ssize);
+ gst_memory_unmap (mem);
}
return res;
}
@@ -1190,7 +1197,11 @@ gst_buffer_memset (GstBuffer * buffer, gsize offset, guint8 val, gsize size)
gsize i, len, left;
g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
- g_return_val_if_fail (gst_buffer_is_writable (buffer), 0);
+
+ if (!gst_buffer_try_lock (buffer, GST_LOCK_WRITE)) {
+ g_warning ("failed to lock buffer %p in WRITE mode", buffer);
+ return 0;
+ }
len = GST_BUFFER_MEM_LEN (buffer);
left = size;
@@ -1200,7 +1211,7 @@ gst_buffer_memset (GstBuffer * buffer, gsize offset, guint8 val, gsize size)
gsize ssize, toset;
GstMemory *mem;
- mem = _get_memory (buffer, i, TRUE);
+ mem = GST_BUFFER_MEM_PTR (buffer, i);
data = gst_memory_map (mem, &ssize, NULL, GST_MAP_WRITE);
if (ssize > offset) {
@@ -1213,7 +1224,7 @@ gst_buffer_memset (GstBuffer * buffer, gsize offset, guint8 val, gsize size)
/* offset past buffer, skip */
offset -= ssize;
}
- gst_memory_unmap (mem, data, ssize);
+ gst_memory_unmap (mem);
}
return size - left;
}
@@ -1301,13 +1312,12 @@ _gst_buffer_arr_is_span_fast (GstMemory ** mem[], gsize len[], guint n,
static GstMemory *
_gst_buffer_arr_span (GstMemory ** mem[], gsize len[], guint n, gsize offset,
- gsize size, gboolean writable)
+ gsize size)
{
GstMemory *span, *parent = NULL;
gsize poffset = 0;
- if (!writable
- && _gst_buffer_arr_is_span_fast (mem, len, n, &poffset, &parent)) {
+ if (_gst_buffer_arr_is_span_fast (mem, len, n, &poffset, &parent)) {
if (parent->flags & GST_MEMORY_FLAG_NO_SHARE)
span = gst_memory_copy (parent, offset + poffset, size);
else
@@ -1341,10 +1351,10 @@ _gst_buffer_arr_span (GstMemory ** mem[], gsize len[], guint n, gsize offset,
} else {
offset -= tocopy;
}
- gst_memory_unmap (cmem[i], src, ssize);
+ gst_memory_unmap (cmem[i]);
}
}
- gst_memory_unmap (span, dest, size);
+ gst_memory_unmap (span);
}
return span;
}
@@ -1429,7 +1439,7 @@ gst_buffer_span (GstBuffer * buf1, gsize offset, GstBuffer * buf2, gsize size)
mem[1] = GST_BUFFER_MEM_ARRAY (buf2);
len[1] = GST_BUFFER_MEM_LEN (buf2);
- span = _gst_buffer_arr_span (mem, len, 2, offset, size, FALSE);
+ span = _gst_buffer_arr_span (mem, len, 2, offset, size);
newbuf = gst_buffer_new ();
_memory_add (newbuf, -1, span);
diff --git a/gst/gstbuffer.h b/gst/gstbuffer.h
index d52753292..124ee9225 100644
--- a/gst/gstbuffer.h
+++ b/gst/gstbuffer.h
@@ -273,9 +273,11 @@ GstBuffer * gst_buffer_new_wrapped (gpointer data, gsize size);
/* memory blocks */
guint gst_buffer_n_memory (GstBuffer *buffer);
void gst_buffer_take_memory (GstBuffer *buffer, gint idx, GstMemory *mem);
-GstMemory * gst_buffer_peek_memory (GstBuffer *buffer, guint idx, GstMapFlags flags);
+GstMemory * gst_buffer_peek_memory (GstBuffer *buffer, guint idx);
void gst_buffer_remove_memory_range (GstBuffer *buffer, guint idx, guint length);
+GstMemory * gst_buffer_get_merged_memory (GstBuffer * buffer);
+
/**
* gst_buffer_remove_memory:
* @b: a #GstBuffer.
@@ -319,6 +321,25 @@ gpointer gst_buffer_map (GstBuffer *buffer, gsize *size, gsiz
GstMapFlags flags);
gboolean gst_buffer_unmap (GstBuffer *buffer, gpointer data, gssize size);
+/**
+ * gst_buffer_try_lock:
+ * @buf: a #GstBuffer
+ *
+ * Try to lock @buf in the @mode.
+ *
+ * Returns: %TRUE if @buf could be locked in @mode
+ */
+#define gst_buffer_try_lock(buf,mode) gst_mini_object_try_lock (GST_MINI_OBJECT_CAST (buf),mode)
+/**
+ * gst_buffer_unlock:
+ * @buf: a #GstBuffer
+ *
+ * Unlock @buf.
+ */
+#define gst_buffer_unlock(buf) gst_mini_object_unlock (GST_MINI_OBJECT_CAST (buf))
+
+#define gst_buffer_make_locked(buf,mode) GST_BUFFER_CAST (gst_mini_object_make_locked (GST_MINI_OBJECT_CAST (buf), mode))
+
/* refcounting */
/**
* gst_buffer_ref:
@@ -326,13 +347,6 @@ gboolean gst_buffer_unmap (GstBuffer *buffer, gpointer data, gs
*
* Increases the refcount of the given buffer by one.
*
- * Note that the refcount affects the writeability
- * of @buf and its metadata, see gst_buffer_is_writable() and
- * gst_buffer_is_metadata_writable(). It is
- * important to note that keeping additional references to
- * GstBuffer instances can potentially increase the number
- * of memcpy operations in a pipeline.
- *
* Returns: (transfer full): @buf
*/
#ifdef _FOOL_GTK_DOC_
@@ -429,30 +443,6 @@ typedef enum {
void gst_buffer_copy_into (GstBuffer *dest, GstBuffer *src,
GstBufferCopyFlags flags,
gsize offset, gsize size);
-
-/**
- * gst_buffer_is_writable:
- * @buf: a #GstBuffer
- *
- * Tests if you can safely write data into a buffer's data array or validly
- * modify the caps and timestamp metadata. Metadata in a GstBuffer is always
- * writable, but it is only safe to change it when there is only one owner
- * of the buffer - ie, the refcount is 1.
- */
-#define gst_buffer_is_writable(buf) gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (buf))
-/**
- * gst_buffer_make_writable:
- * @buf: (transfer full): a #GstBuffer
- *
- * Makes a writable buffer from the given buffer. If the source buffer is
- * already writable, this will simply return the same buffer. A copy will
- * otherwise be made using gst_buffer_copy().
- *
- * Returns: (transfer full): a writable buffer which may or may not be the
- * same as @buf
- */
-#define gst_buffer_make_writable(buf) GST_BUFFER_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (buf)))
-
/**
* gst_buffer_replace:
* @obuf: (inout) (transfer full): pointer to a pointer to a #GstBuffer to be
diff --git a/gst/gstcaps.c b/gst/gstcaps.c
index 3bfe62bde..d89fbce64 100644
--- a/gst/gstcaps.c
+++ b/gst/gstcaps.c
@@ -509,7 +509,7 @@ gst_caps_append (GstCaps * caps1, GstCaps * caps2)
g_return_if_fail (GST_IS_CAPS (caps2));
g_return_if_fail (IS_WRITABLE (caps1));
- caps2 = gst_caps_make_writable (caps2);
+ caps2 = gst_caps_make_locked (caps2, GST_LOCK_WRITE);
if (G_UNLIKELY (CAPS_IS_ANY (caps1) || CAPS_IS_ANY (caps2))) {
/* FIXME: this leaks */
@@ -524,6 +524,7 @@ gst_caps_append (GstCaps * caps1, GstCaps * caps2)
gst_caps_append_structure_unchecked (caps1, structure);
}
}
+ gst_caps_unlock (caps2);
gst_caps_unref (caps2); /* guaranteed to free it */
}
@@ -549,7 +550,7 @@ gst_caps_merge (GstCaps * caps1, GstCaps * caps2)
g_return_if_fail (GST_IS_CAPS (caps2));
g_return_if_fail (IS_WRITABLE (caps1));
- caps2 = gst_caps_make_writable (caps2);
+ caps2 = gst_caps_make_locked (caps2, GST_LOCK_WRITE);
if (G_UNLIKELY (CAPS_IS_ANY (caps1))) {
for (i = GST_CAPS_LEN (caps2) - 1; i >= 0; i--) {
@@ -577,6 +578,7 @@ gst_caps_merge (GstCaps * caps1, GstCaps * caps2)
gst_caps_unref (com);
*/
}
+ gst_caps_unlock (caps2);
gst_caps_unref (caps2); /* guaranteed to free it */
}
diff --git a/gst/gstcaps.h b/gst/gstcaps.h
index 320471662..15f91c2c4 100644
--- a/gst/gstcaps.h
+++ b/gst/gstcaps.h
@@ -129,7 +129,7 @@ typedef enum {
*/
#define GST_STATIC_CAPS(string) \
{ \
- /* miniobject */ { { 0, 0, 0, 0, NULL, NULL, NULL, 0, NULL }, \
+ /* miniobject */ { { 0, 0, 0, 0, 0, NULL, NULL, NULL, 0, NULL }, \
/* caps */ NULL }, \
/* string */ string, \
GST_PADDING_INIT \
@@ -267,15 +267,17 @@ gst_caps_copy (const GstCaps * caps)
*/
#define gst_caps_is_writable(caps) gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (caps))
+#define gst_caps_try_lock(caps,mode) gst_mini_object_try_lock (GST_MINI_OBJECT_CAST (caps),mode)
+#define gst_caps_unlock(caps) gst_mini_object_unlock (GST_MINI_OBJECT_CAST (caps))
/**
- * gst_caps_make_writable:
+ * gst_caps_make_locked:
* @caps: (transfer full): a #GstCaps
+ * @mode: a #GstLockMode
*
- * Returns a writable copy of @caps.
+ * Returns a #GstCaps that can be accessed in @mode.
*
- * If there is only one reference count on @caps, the caller must be the owner,
- * and so this function will return the caps object unchanged. If on the other
- * hand there is more than one reference on the object, a new caps object will
+ * If @caps can be accessed in @mode, this function will return the locked caps
+ * object unchanged. If the lock could not be acquired, a new caps object will
* be returned. The caller's reference on @caps will be removed, and instead the
* caller will own a reference to the returned object.
*
@@ -283,10 +285,10 @@ gst_caps_copy (const GstCaps * caps)
* that it returns. Don't access the argument after calling this function. See
* also: gst_caps_ref().
*
- * Returns: (transfer full): a writable caps which may or may not be the
- * same as @caps
+ * Returns: (transfer full): a caps which may or may not be the
+ * same as @caps that can be accessed in @mode
*/
-#define gst_caps_make_writable(caps) GST_CAPS_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (caps)))
+#define gst_caps_make_locked(caps,mode) GST_CAPS_CAST (gst_mini_object_make_locked (GST_MINI_OBJECT_CAST (caps), mode))
/**
* gst_caps_replace:
diff --git a/gst/gstevent.c b/gst/gstevent.c
index 4ee64fcbb..7995c11e2 100644
--- a/gst/gstevent.c
+++ b/gst/gstevent.c
@@ -361,7 +361,7 @@ gst_event_writable_structure (GstEvent * event)
GstStructure *structure;
g_return_val_if_fail (GST_IS_EVENT (event), NULL);
- g_return_val_if_fail (gst_event_is_writable (event), NULL);
+ //g_return_val_if_fail (gst_event_is_writable (event), NULL);
structure = GST_EVENT_STRUCTURE (event);
diff --git a/gst/gstevent.h b/gst/gstevent.h
index d9db2c6fc..e3a2539f6 100644
--- a/gst/gstevent.h
+++ b/gst/gstevent.h
@@ -250,26 +250,11 @@ GST_EXPORT GType _gst_event_type;
*/
#define GST_EVENT_IS_STICKY(ev) !!(GST_EVENT_TYPE (ev) & GST_EVENT_TYPE_STICKY)
-/**
- * gst_event_is_writable:
- * @ev: a #GstEvent
- *
- * Tests if you can safely write data into a event's structure or validly
- * modify the seqnum and timestamp field.
- */
-#define gst_event_is_writable(ev) gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (ev))
-/**
- * gst_event_make_writable:
- * @ev: (transfer full): a #GstEvent
- *
- * Makes a writable event from the given event. If the source event is
- * already writable, this will simply return the same event. A copy will
- * otherwise be made using gst_event_copy().
- *
- * Returns: (transfer full): a writable event which may or may not be the
- * same as @ev
- */
-#define gst_event_make_writable(ev) GST_EVENT_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (ev)))
+
+#define gst_event_try_lock(event,mode) gst_mini_object_try_lock (GST_MINI_OBJECT_CAST (event),mode)
+#define gst_event_unlock(event) gst_mini_object_unlock (GST_MINI_OBJECT_CAST (event))
+#define gst_event_make_locked(event,mode) GST_EVENT_CAST (gst_mini_object_make_locked (GST_MINI_OBJECT_CAST (event), mode))
+
/**
* gst_event_replace:
* @old_event: (inout) (transfer full): pointer to a pointer to a #GstEvent
diff --git a/gst/gstmemory.c b/gst/gstmemory.c
index 480c6c840..3c7330a86 100644
--- a/gst/gstmemory.c
+++ b/gst/gstmemory.c
@@ -106,11 +106,8 @@ typedef struct
{
GstMemory mem;
gsize slice_size;
- guint8 *data;
GFreeFunc free_func;
- gsize maxsize;
- gsize offset;
- gsize size;
+ guint8 *data;
} GstMemoryDefault;
/* the default allocator */
@@ -129,13 +126,13 @@ _default_mem_init (GstMemoryDefault * mem, GstMemoryFlags flags,
mem->mem.flags = flags;
mem->mem.refcount = 1;
mem->mem.parent = parent ? gst_memory_ref (parent) : NULL;
- mem->mem.state = 0;
+ mem->mem.state = (flags & GST_MEMORY_FLAG_READONLY ? 0x5 : 0);
+ mem->mem.maxsize = maxsize;
+ mem->mem.offset = offset;
+ mem->mem.size = size;
mem->slice_size = slice_size;
mem->data = data;
mem->free_func = free_func;
- mem->maxsize = maxsize;
- mem->offset = offset;
- mem->size = size;
}
/* create a new memory block that manages the given memory */
@@ -191,62 +188,15 @@ _default_mem_alloc (const GstAllocator * allocator, gsize maxsize, gsize align)
return (GstMemory *) _default_mem_new_block (maxsize, align, 0, maxsize);
}
-static gsize
-_default_mem_get_sizes (GstMemoryDefault * mem, gsize * offset, gsize * maxsize)
-{
- if (offset)
- *offset = mem->offset;
- if (maxsize)
- *maxsize = mem->maxsize;
-
- return mem->size;
-}
-
-static void
-_default_mem_resize (GstMemoryDefault * mem, gssize offset, gsize size)
-{
- g_return_if_fail (offset >= 0 || mem->offset >= -offset);
- g_return_if_fail (size + mem->offset + offset <= mem->maxsize);
-
- mem->offset += offset;
- mem->size = size;
-}
-
static gpointer
-_default_mem_map (GstMemoryDefault * mem, gsize * size, gsize * maxsize,
- GstMapFlags flags)
+_default_mem_map (GstMemoryDefault * mem, GstMapFlags flags)
{
- if (size)
- *size = mem->size;
- if (maxsize)
- *maxsize = mem->maxsize - mem->offset;
-
- return mem->data + mem->offset;
+ return mem->data;
}
static gboolean
-_default_mem_unmap (GstMemoryDefault * mem, gpointer data, gsize size)
+_default_mem_unmap (GstMemoryDefault * mem)
{
- GST_DEBUG ("mem: %p, data %p, size %" G_GSIZE_FORMAT, mem, data, size);
- GST_DEBUG ("mem: %p, data %p, offset %" G_GSIZE_FORMAT ", size %"
- G_GSIZE_FORMAT ", maxsize %" G_GSIZE_FORMAT, mem, mem->data, mem->offset,
- mem->size, mem->maxsize);
-
- g_return_val_if_fail ((guint8 *) data >= mem->data
- && (guint8 *) data < mem->data + mem->maxsize, FALSE);
-
- if (mem->data + mem->offset != data) {
- gsize newoffset = (guint8 *) data - mem->data;
- if (size == -1)
- size = mem->offset + mem->size - newoffset;
- mem->offset = newoffset;
- }
-
- if (size != -1) {
- g_return_val_if_fail (mem->offset + size <= mem->maxsize, FALSE);
- mem->size = size;
- }
-
return TRUE;
}
@@ -268,10 +218,12 @@ _default_mem_copy (GstMemoryDefault * mem, gssize offset, gsize size)
GstMemoryDefault *copy;
if (size == -1)
- size = mem->size > offset ? mem->size - offset : 0;
+ size = mem->mem.size > offset ? mem->mem.size - offset : 0;
- copy = _default_mem_new_block (mem->maxsize, 0, mem->offset + offset, size);
- memcpy (copy->data, mem->data, mem->maxsize);
+ copy =
+ _default_mem_new_block (mem->mem.maxsize, 0, mem->mem.offset + offset,
+ size);
+ memcpy (copy->data, mem->data, mem->mem.maxsize);
return copy;
}
@@ -287,10 +239,11 @@ _default_mem_share (GstMemoryDefault * mem, gssize offset, gsize size)
parent = (GstMemory *) mem;
if (size == -1)
- size = mem->size - offset;
+ size = mem->mem.size - offset;
- sub = _default_mem_new (parent->flags, parent, mem->data, NULL, mem->maxsize,
- mem->offset + offset, size);
+ sub =
+ _default_mem_new (parent->flags, parent, mem->data, NULL,
+ mem->mem.maxsize, mem->mem.offset + offset, size);
return sub;
}
@@ -305,11 +258,12 @@ _default_mem_is_span (GstMemoryDefault * mem1, GstMemoryDefault * mem2,
parent = (GstMemoryDefault *) mem1->mem.parent;
- *offset = mem1->offset - parent->offset;
+ *offset = mem1->mem.offset - parent->mem.offset;
}
/* and memory is contiguous */
- return mem1->data + mem1->offset + mem1->size == mem2->data + mem2->offset;
+ return mem1->data + mem1->mem.offset + mem1->mem.size ==
+ mem2->data + mem2->mem.offset;
}
static GstMemory *
@@ -320,15 +274,16 @@ _fallback_copy (GstMemory * mem, gssize offset, gssize size)
gsize msize;
data = gst_memory_map (mem, &msize, NULL, GST_MAP_READ);
+ if (data == NULL)
+ return NULL;
if (size == -1)
size = msize > offset ? msize - offset : 0;
- /* use the same allocator as the memory we copy, FIXME, alignment? */
- copy = gst_allocator_alloc (mem->allocator, size, 0);
+ /* use the same allocator as the memory we copy */
+ copy = gst_allocator_alloc (mem->allocator, size, mem->align);
dest = gst_memory_map (copy, NULL, NULL, GST_MAP_WRITE);
memcpy (dest, data + offset, size);
- gst_memory_unmap (copy, dest, size);
-
- gst_memory_unmap (mem, data, msize);
+ gst_memory_unmap (copy);
+ gst_memory_unmap (mem);
return (GstMemory *) copy;
}
@@ -347,8 +302,6 @@ _priv_gst_memory_initialize (void)
{
static const GstMemoryInfo _mem_info = {
(GstMemoryAllocFunction) _default_mem_alloc,
- (GstMemoryGetSizesFunction) _default_mem_get_sizes,
- (GstMemoryResizeFunction) _default_mem_resize,
(GstMemoryMapFunction) _default_mem_map,
(GstMemoryUnmapFunction) _default_mem_unmap,
(GstMemoryFreeFunction) _default_mem_free,
@@ -450,7 +403,12 @@ gst_memory_get_sizes (GstMemory * mem, gsize * offset, gsize * maxsize)
{
g_return_val_if_fail (mem != NULL, 0);
- return mem->allocator->info.get_sizes (mem, offset, maxsize);
+ if (offset)
+ *offset = mem->offset;
+ if (maxsize)
+ *maxsize = mem->maxsize;
+
+ return mem->size;
}
/**
@@ -466,27 +424,57 @@ 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);
- mem->allocator->info.resize (mem, offset, size);
+ mem->offset += offset;
+ mem->size = size;
}
-/**
- * gst_memory_is_writable:
- * @mem: a #GstMemory
- *
- * Check if @mem is writable.
- *
- * Returns: %TRUE is @mem is writable.
- */
-gboolean
-gst_memory_is_writable (GstMemory * mem)
+static gboolean
+gst_memory_lock (GstMemory * mem, GstMapFlags flags)
{
- g_return_val_if_fail (mem != NULL, FALSE);
+ gint access_mode, state, newstate;
- return (mem->refcount == 1) &&
- ((mem->parent == NULL) || (mem->parent->refcount == 1)) &&
- ((mem->flags & GST_MEMORY_FLAG_READONLY) == 0);
+ access_mode = flags & 3;
+
+ do {
+ state = g_atomic_int_get (&mem->state);
+ if (state == 0) {
+ /* nothing mapped, set access_mode and refcount */
+ newstate = 4 | access_mode;
+ } else {
+ /* access_mode must match */
+ if ((state & access_mode) != access_mode)
+ goto lock_failed;
+ /* increase refcount */
+ newstate = state + 4;
+ }
+ } while (!g_atomic_int_compare_and_exchange (&mem->state, state, newstate));
+
+ return TRUE;
+
+lock_failed:
+ {
+ GST_ERROR ("lock failed %p: state %d, access_mode %d", mem, state,
+ access_mode);
+ return FALSE;
+ }
+}
+
+static void
+gst_memory_unlock (GstMemory * mem)
+{
+ gint state, newstate;
+
+ do {
+ state = g_atomic_int_get (&mem->state);
+ /* decrease the refcount */
+ newstate = state - 4;
+ /* last refcount, unset access_mode */
+ if (newstate < 4)
+ newstate = 0;
+ } while (!g_atomic_int_compare_and_exchange (&mem->state, state, newstate));
}
/**
@@ -501,92 +489,69 @@ gst_memory_is_writable (GstMemory * mem)
* @size and @maxsize will contain the size of the memory and the maximum
* allocated memory of @mem respectively. They can be set to NULL.
*
+ * This function can return NULL for various reasons:
+ * - the memory backed by @mem is not accessible with the given @flags.
+ * - the memory was already mapped with a different mapping.
+ *
+ * @pointer remains valid for as long as @mem is alive and until
+ * gst_memory_unmap() is called.
+ *
+ * For each gst_memory_map() call, a corresponding gst_memory_unmap() call
+ * should be done.
+ *
* Returns: (transfer none): a pointer to the memory of @mem.
*/
gpointer
gst_memory_map (GstMemory * mem, gsize * size, gsize * maxsize,
GstMapFlags flags)
{
- gpointer res;
- gint access_mode, state, newstate;
+ guint8 *res;
g_return_val_if_fail (mem != NULL, NULL);
- access_mode = flags & 3;
- g_return_val_if_fail (!(access_mode & GST_MAP_WRITE)
- || gst_memory_is_writable (mem), NULL);
+ if (!gst_memory_lock (mem, flags))
+ return NULL;
- do {
- state = g_atomic_int_get (&mem->state);
- if (state == 0) {
- /* nothing mapped, set access_mode and refcount */
- newstate = 4 | access_mode;
- } else {
- /* access_mode must match */
- g_return_val_if_fail ((state & access_mode) == access_mode, NULL);
- /* increase refcount */
- newstate = state + 4;
- }
- } while (!g_atomic_int_compare_and_exchange (&mem->state, state, newstate));
+ res = mem->allocator->info.map (mem, flags);
+
+ if (G_UNLIKELY (res == NULL))
+ goto error;
+
+ if (size)
+ *size = mem->size;
+ if (maxsize)
+ *maxsize = mem->maxsize - mem->offset;
- res = mem->allocator->info.map (mem, size, maxsize, flags);
+ return res + mem->offset;
- if (G_UNLIKELY (res == NULL)) {
+ /* ERRORS */
+error:
+ {
/* something went wrong, restore the orginal state again */
- do {
- state = g_atomic_int_get (&mem->state);
- /* there must be a ref */
- g_return_val_if_fail (state >= 4, NULL);
- /* decrease the refcount */
- newstate = state - 4;
- /* last refcount, unset access_mode */
- if (newstate < 4)
- newstate = 0;
- } while (!g_atomic_int_compare_and_exchange (&mem->state, state, newstate));
+ GST_ERROR ("mem %p: map failed", mem);
+ gst_memory_unlock (mem);
+ return NULL;
}
- return res;
}
/**
* gst_memory_unmap:
* @mem: a #GstMemory
- * @data: data to unmap
- * @size: new size of @mem, or -1
- *
- * 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.
*
- * It is possible to pass a different @data than that obtained from
- * gst_memory_map() in which case the offset of @mem will be updated.
+ * Release the memory obtained with gst_memory_map()
*
* Returns: TRUE when the memory was release successfully.
*/
gboolean
-gst_memory_unmap (GstMemory * mem, gpointer data, gssize size)
+gst_memory_unmap (GstMemory * mem)
{
- gboolean need_unmap = TRUE;
- gint state, newstate;
-
g_return_val_if_fail (mem != NULL, FALSE);
+ /* there must be a ref */
+ g_return_val_if_fail (g_atomic_int_get (&mem->state) >= 4, FALSE);
- do {
- state = g_atomic_int_get (&mem->state);
+ if (!mem->allocator->info.unmap (mem))
+ return FALSE;
- /* there must be a ref */
- g_return_val_if_fail (state >= 4, FALSE);
-
- if (need_unmap) {
- /* try to unmap, only do this once */
- if (!mem->allocator->info.unmap (mem, data, size))
- return FALSE;
- need_unmap = FALSE;
- }
- /* success, try to decrease the refcount */
- newstate = state - 4;
- /* last refcount, unset access_mode */
- if (newstate < 4)
- newstate = 0;
- } while (!g_atomic_int_compare_and_exchange (&mem->state, state, newstate));
+ gst_memory_unlock (mem);
return TRUE;
}
@@ -606,9 +571,16 @@ gst_memory_unmap (GstMemory * mem, gpointer data, gssize size)
GstMemory *
gst_memory_copy (GstMemory * mem, gssize offset, gssize size)
{
+ GstMemory *copy;
+
g_return_val_if_fail (mem != NULL, NULL);
+ g_return_val_if_fail (gst_memory_lock (mem, GST_MAP_READ), NULL);
- return mem->allocator->info.copy (mem, offset, size);
+ copy = mem->allocator->info.copy (mem, offset, size);
+
+ gst_memory_unlock (mem);
+
+ return copy;
}
/**
@@ -695,8 +667,6 @@ gst_allocator_register (const gchar * name, const GstMemoryInfo * info)
g_return_val_if_fail (name != NULL, NULL);
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (info->alloc != NULL, NULL);
- g_return_val_if_fail (info->get_sizes != NULL, NULL);
- g_return_val_if_fail (info->resize != NULL, NULL);
g_return_val_if_fail (info->map != NULL, NULL);
g_return_val_if_fail (info->unmap != NULL, NULL);
g_return_val_if_fail (info->free != NULL, NULL);
diff --git a/gst/gstmemory.h b/gst/gstmemory.h
index f0756aeac..d9e84beb3 100644
--- a/gst/gstmemory.h
+++ b/gst/gstmemory.h
@@ -62,6 +62,10 @@ typedef enum {
* @refcount: refcount
* @parent: parent memory block
* @state: private state
+ * @maxsize: the maximum size allocated
+ * @align: the alignment of the memory
+ * @offset: the offset where valid data starts
+ * @size: the size of valid data
*
* Base structure for memory implementations. Custom memory will put this structure
* as the first member of their structure.
@@ -73,6 +77,10 @@ struct _GstMemory {
gint refcount;
GstMemory *parent;
volatile gint state;
+ gsize maxsize;
+ gsize align;
+ gsize offset;
+ gsize size;
};
/**
@@ -123,62 +131,31 @@ typedef GstMemory * (*GstMemoryAllocFunction) (const GstAllocator *allocator,
gpointer user_data);
/**
- * GstMemoryGetSizesFunction:
- * @mem: a #GstMemory
- * @offset: result pointer for offset
- * @maxsize: result pointer for maxsize
- *
- * Retrieve the size, offset and maxsize of @mem.
- *
- * Returns: the size of @mem, the offset and the maximum allocated size in @maxsize.
- */
-typedef gsize (*GstMemoryGetSizesFunction) (GstMemory *mem, gsize *offset, gsize *maxsize);
-
-/**
- * GstMemoryResizeFunction:
- * @mem: a #GstMemory
- * @offset: the offset adjustement
- * @size: the new size or -1 to just adjust the offset
- *
- * Adjust the size and offset of @mem. @offset bytes will be adjusted 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, gssize offset, gssize 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.
+ * in @flags. @maxsize will contain the size of the returned memory.
*
- * Returns: a pointer to memory. @size bytes are currently used from the
- * returned pointer and @maxsize bytes can potentially be used.
+ * Returns: a pointer to memory of which @maxsize bytes can potentially be used.
+ * If the memory cannot be mapped according to @flags, the function will return NULL.
*/
-typedef gpointer (*GstMemoryMapFunction) (GstMemory *mem, gsize *size, gsize *maxsize,
- GstMapFlags flags);
+typedef gpointer (*GstMemoryMapFunction) (GstMemory *mem, GstMapFlags flags);
/**
* GstMemoryUnmapFunction:
* @mem: a #GstMemory
- * @data: the data pointer
- * @size: the new size, or -1 to not modify the size
+ * @data: a memory
+ * @maxsize: the size of @data
*
- * 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.
+ * Unmap the memory previously retrieved with gst_memory_map(). After this call,
+ * @data should not be used anymore.
*
* Returns: %TRUE on success.
*/
-typedef gboolean (*GstMemoryUnmapFunction) (GstMemory *mem, gpointer data, gssize size);
+typedef gboolean (*GstMemoryUnmapFunction) (GstMemory *mem);
/**
* GstMemoryFreeFunction:
@@ -234,8 +211,6 @@ typedef gboolean (*GstMemoryIsSpanFunction) (GstMemory *mem1, GstMemory *m
/**
* GstMemoryInfo:
* @alloc: the implementation of the GstMemoryAllocFunction
- * @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
@@ -249,8 +224,6 @@ typedef gboolean (*GstMemoryIsSpanFunction) (GstMemory *mem1, GstMemory *m
*/
struct _GstMemoryInfo {
GstMemoryAllocFunction alloc;
- GstMemoryGetSizesFunction get_sizes;
- GstMemoryResizeFunction resize;
GstMemoryMapFunction map;
GstMemoryUnmapFunction unmap;
GstMemoryFreeFunction free;
@@ -279,19 +252,17 @@ GstMemory * gst_memory_new_wrapped (GstMemoryFlags flags, gpointer data, GFr
gsize maxsize, gsize offset, gsize size);
/* refcounting */
-GstMemory * gst_memory_ref (GstMemory *mem);
-void gst_memory_unref (GstMemory *mem);
+GstMemory * gst_memory_ref (GstMemory *mem);
+void gst_memory_unref (GstMemory *mem);
/* getting/setting memory properties */
gsize gst_memory_get_sizes (GstMemory *mem, gsize *offset, gsize *maxsize);
void gst_memory_resize (GstMemory *mem, gssize offset, gsize size);
/* retrieving data */
-gboolean gst_memory_is_writable (GstMemory *mem);
-
gpointer gst_memory_map (GstMemory *mem, gsize *size, gsize *maxsize,
GstMapFlags flags);
-gboolean gst_memory_unmap (GstMemory *mem, gpointer data, gssize size);
+gboolean gst_memory_unmap (GstMemory *mem);
/* copy and subregions */
GstMemory * gst_memory_copy (GstMemory *mem, gssize offset, gssize size);
diff --git a/gst/gstminiobject.c b/gst/gstminiobject.c
index 78749ddc9..bfc572428 100644
--- a/gst/gstminiobject.c
+++ b/gst/gstminiobject.c
@@ -66,6 +66,7 @@ gst_mini_object_init (GstMiniObject * mini_object, GType type, gsize size)
mini_object->type = type;
mini_object->refcount = 1;
mini_object->flags = 0;
+ mini_object->lock = 0;
mini_object->size = size;
mini_object->n_weak_refs = 0;
mini_object->weak_refs = NULL;
@@ -97,47 +98,26 @@ gst_mini_object_copy (const GstMiniObject * mini_object)
}
/**
- * gst_mini_object_is_writable:
- * @mini_object: the mini-object to check
- *
- * Checks if a mini-object is writable. A mini-object is writable
- * if the reference count is one and the #GST_MINI_OBJECT_FLAG_READONLY
- * flag is not set. Modification of a mini-object should only be
- * done after verifying that it is writable.
- *
- * MT safe
- *
- * Returns: TRUE if the object is writable.
- */
-gboolean
-gst_mini_object_is_writable (const GstMiniObject * mini_object)
-{
- g_return_val_if_fail (mini_object != NULL, FALSE);
-
- return (GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object) == 1);
-}
-
-/**
- * gst_mini_object_make_writable:
+ * gst_mini_object_make_locked:
* @mini_object: (transfer full): the mini-object to make writable
*
- * Checks if a mini-object is writable. If not, a writable copy is made and
- * returned. This gives away the reference to the original mini object,
+ * Checks if @mini-object can be locked according to @mode. If not, a copy
+ * is made and returned. This gives away the reference to the original mini object,
* and returns a reference to the new object.
*
* MT safe
*
* Returns: (transfer full): a mini-object (possibly the same pointer) that
- * is writable.
+ * is locked according to @mode.
*/
GstMiniObject *
-gst_mini_object_make_writable (GstMiniObject * mini_object)
+gst_mini_object_make_locked (GstMiniObject * mini_object, GstLockMode mode)
{
GstMiniObject *ret;
g_return_val_if_fail (mini_object != NULL, NULL);
- if (gst_mini_object_is_writable (mini_object)) {
+ if (gst_mini_object_try_lock (mini_object, mode)) {
ret = mini_object;
} else {
ret = gst_mini_object_copy (mini_object);
@@ -145,7 +125,6 @@ gst_mini_object_make_writable (GstMiniObject * mini_object)
g_type_name (GST_MINI_OBJECT_TYPE (mini_object)), mini_object, ret);
gst_mini_object_unref (mini_object);
}
-
return ret;
}
@@ -155,12 +134,9 @@ gst_mini_object_make_writable (GstMiniObject * mini_object)
*
* Increase the reference count of the mini-object.
*
- * Note that the refcount affects the writeability
- * of @mini-object, see gst_mini_object_is_writable(). It is
- * important to note that keeping additional references to
- * GstMiniObject instances can potentially increase the number
- * of memcpy operations in a pipeline, especially if the miniobject
- * is a #GstBuffer.
+ * Note that the refcount does not affect the writability of @mini_object. If
+ * you don't want other threads to modify @mini_object, you should use
+ * gst_mini_object_try_lock().
*
* Returns: (transfer full): the mini-object.
*/
@@ -236,6 +212,79 @@ gst_mini_object_unref (GstMiniObject * mini_object)
}
/**
+ * gst_mini_object_try_lock:
+ * @mini_object: the mini-object
+ * @mode: the desired access mode
+ *
+ * Try to lock @mini_object in @mode. For each successful call to
+ * gst_mini_object_try_lock() a corresponding call to gst_mini_object_unlock()
+ * should be made.
+ *
+ * Once an object is locked in a certain mode, it cannot be locked in another
+ * mode. To make the object readonly, one can use a @mode of GST_LOCK_READ.
+ *
+ * Note that locking an object in write-only mode is dangerous when there are other
+ * references to the mini object because any attempt to read will fail as will
+ * any attempt to make a copy.
+ *
+ * Returns: %TRUE if @mini_object could be locked in @mode. %FALSE is returned
+ * when the object was already locked in a different mode.
+ */
+gboolean
+gst_mini_object_try_lock (GstMiniObject * mini_object, GstLockMode mode)
+{
+ gint access_mode, state, newstate;
+
+ access_mode = mode & 3;
+
+ do {
+ state = g_atomic_int_get (&mini_object->lock);
+ if (state == 0) {
+ /* nothing mapped, set access_mode and refcount */
+ newstate = 4 | access_mode;
+ } else {
+ /* access_mode must match */
+ if ((state & access_mode) != access_mode)
+ goto lock_failed;
+ /* increase refcount */
+ newstate = state + 4;
+ }
+ } while (!g_atomic_int_compare_and_exchange (&mini_object->lock, state,
+ newstate));
+
+ return TRUE;
+
+lock_failed:
+ {
+ GST_ERROR ("lock failed %p: state %d, access_mode %d", mini_object, state,
+ access_mode);
+ return FALSE;
+ }
+}
+
+/**
+ * gst_mini_object_lock:
+ * @mini_object: the mini-object
+ *
+ * Unlock @mini_object.
+ */
+void
+gst_mini_object_unlock (GstMiniObject * mini_object)
+{
+ gint state, newstate;
+
+ do {
+ state = g_atomic_int_get (&mini_object->lock);
+ /* decrease the refcount */
+ newstate = state - 4;
+ /* last refcount, unset access_mode */
+ if (newstate < 4)
+ newstate = 0;
+ } while (!g_atomic_int_compare_and_exchange (&mini_object->lock, state,
+ newstate));
+}
+
+/**
* gst_mini_object_replace:
* @olddata: (inout) (transfer full): pointer to a pointer to a mini-object to
* be replaced
diff --git a/gst/gstminiobject.h b/gst/gstminiobject.h
index f4807a6e3..837adbb47 100644
--- a/gst/gstminiobject.h
+++ b/gst/gstminiobject.h
@@ -158,11 +158,29 @@ typedef enum
#define GST_MINI_OBJECT_SIZE(obj) ((GST_MINI_OBJECT_CAST(obj))->size)
/**
+ * GstLockMode:
+ * @GST_LOCK_READ: map for read access
+ * @GST_LOCK_WRITE: map for write access
+ * @GST_LOCK_FLAG_LAST: first flag that can be used for custom purposes
+ *
+ * Flags used when locking miniobjects
+ */
+typedef enum {
+ GST_LOCK_READ = (1 << 0),
+ GST_LOCK_WRITE = (1 << 1),
+
+ GST_LOCK_FLAG_LAST = (1 << 4)
+} GstLockMode;
+
+#define GST_LOCK_READWRITE (GST_LOCK_READ | GST_LOCK_WRITE)
+
+/**
* GstMiniObject:
* @type: the GType of the object
* @refcount: atomic refcount
* @flags: extra flags.
* @size: the size of the structure
+ * @lock: atomic state of the locking
* @copy: a copy function
* @dispose: a dispose function
* @free: the free function
@@ -180,6 +198,7 @@ struct _GstMiniObject {
gint refcount;
guint flags;
gsize size;
+ gint lock;
GstMiniObjectCopyFunction copy;
GstMiniObjectDisposeFunction dispose;
@@ -199,8 +218,11 @@ void gst_mini_object_init (GstMiniObject *mini_object,
GType type, gsize size);
GstMiniObject * gst_mini_object_copy (const GstMiniObject *mini_object) G_GNUC_MALLOC;
-gboolean gst_mini_object_is_writable (const GstMiniObject *mini_object);
-GstMiniObject * gst_mini_object_make_writable (GstMiniObject *mini_object);
+
+/* locking */
+gboolean gst_mini_object_try_lock (GstMiniObject *mini_object, GstLockMode mode);
+GstMiniObject * gst_mini_object_make_locked (GstMiniObject *mini_object, GstLockMode mode);
+void gst_mini_object_unlock (GstMiniObject *mini_object);
/* refcounting */
GstMiniObject * gst_mini_object_ref (GstMiniObject *mini_object);
diff --git a/gst/gstquery.c b/gst/gstquery.c
index 12cf67da6..70886fc19 100644
--- a/gst/gstquery.c
+++ b/gst/gstquery.c
@@ -865,10 +865,20 @@ gst_query_get_structure (GstQuery * query)
GstStructure *
gst_query_writable_structure (GstQuery * query)
{
+ GstStructure *res;
+
g_return_val_if_fail (GST_IS_QUERY (query), NULL);
- g_return_val_if_fail (gst_query_is_writable (query), NULL);
- return GST_QUERY_STRUCTURE (query);
+ if (!gst_query_try_lock (query, GST_LOCK_WRITE)) {
+ g_warning ("could not lock query %p in WRITE mode", query);
+ return NULL;
+ }
+
+ res = GST_QUERY_STRUCTURE (query);
+
+ gst_query_unlock (query);
+
+ return res;
}
/**
@@ -916,7 +926,11 @@ gst_query_set_seeking (GstQuery * query, GstFormat format,
GstStructure *structure;
g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEEKING);
- g_return_if_fail (gst_query_is_writable (query));
+
+ if (!gst_query_try_lock (query, GST_LOCK_WRITE)) {
+ g_warning ("could not lock query %p in WRITE mode", query);
+ return;
+ }
structure = GST_QUERY_STRUCTURE (query);
gst_structure_id_set (structure,
@@ -924,6 +938,8 @@ gst_query_set_seeking (GstQuery * query, GstFormat format,
GST_QUARK (SEEKABLE), G_TYPE_BOOLEAN, seekable,
GST_QUARK (SEGMENT_START), G_TYPE_INT64, segment_start,
GST_QUARK (SEGMENT_END), G_TYPE_INT64, segment_end, NULL);
+
+ gst_query_unlock (query);
}
/**
@@ -1038,7 +1054,11 @@ gst_query_set_formats (GstQuery * query, gint n_formats, ...)
GstStructure *structure;
g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
- g_return_if_fail (gst_query_is_writable (query));
+
+ if (!gst_query_try_lock (query, GST_LOCK_WRITE)) {
+ g_warning ("could not lock query %p in WRITE mode", query);
+ return;
+ }
g_value_init (&list, GST_TYPE_LIST);
@@ -1053,6 +1073,8 @@ gst_query_set_formats (GstQuery * query, gint n_formats, ...)
g_value_unset (&list);
+ gst_query_unlock (query);
+
}
/**
@@ -1076,7 +1098,11 @@ gst_query_set_formatsv (GstQuery * query, gint n_formats,
GstStructure *structure;
g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
- g_return_if_fail (gst_query_is_writable (query));
+
+ if (!gst_query_try_lock (query, GST_LOCK_WRITE)) {
+ g_warning ("could not lock query %p in WRITE mode", query);
+ return;
+ }
g_value_init (&list, GST_TYPE_LIST);
for (i = 0; i < n_formats; i++) {
@@ -1086,6 +1112,8 @@ gst_query_set_formatsv (GstQuery * query, gint n_formats,
gst_structure_set_value (structure, "formats", &list);
g_value_unset (&list);
+
+ gst_query_unlock (query);
}
/**
@@ -1205,13 +1233,19 @@ gst_query_set_buffering_percent (GstQuery * query, gboolean busy, gint percent)
GstStructure *structure;
g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
- g_return_if_fail (gst_query_is_writable (query));
g_return_if_fail (percent >= 0 && percent <= 100);
+ if (!gst_query_try_lock (query, GST_LOCK_WRITE)) {
+ g_warning ("could not lock query %p in WRITE mode", query);
+ return;
+ }
+
structure = GST_QUERY_STRUCTURE (query);
gst_structure_id_set (structure,
GST_QUARK (BUSY), G_TYPE_BOOLEAN, busy,
GST_QUARK (BUFFER_PERCENT), G_TYPE_INT, percent, NULL);
+
+ gst_query_unlock (query);
}
/**
@@ -1261,7 +1295,11 @@ gst_query_set_buffering_stats (GstQuery * query, GstBufferingMode mode,
GstStructure *structure;
g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
- g_return_if_fail (gst_query_is_writable (query));
+
+ if (!gst_query_try_lock (query, GST_LOCK_WRITE)) {
+ g_warning ("could not lock query %p in WRITE mode", query);
+ return;
+ }
structure = GST_QUERY_STRUCTURE (query);
gst_structure_id_set (structure,
@@ -1269,6 +1307,8 @@ gst_query_set_buffering_stats (GstQuery * query, GstBufferingMode mode,
GST_QUARK (AVG_IN_RATE), G_TYPE_INT, avg_in,
GST_QUARK (AVG_OUT_RATE), G_TYPE_INT, avg_out,
GST_QUARK (BUFFERING_LEFT), G_TYPE_INT64, buffering_left, NULL);
+
+ gst_query_unlock (query);
}
/**
@@ -1329,7 +1369,11 @@ gst_query_set_buffering_range (GstQuery * query, GstFormat format,
GstStructure *structure;
g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
- g_return_if_fail (gst_query_is_writable (query));
+
+ if (!gst_query_try_lock (query, GST_LOCK_WRITE)) {
+ g_warning ("could not lock query %p in WRITE mode", query);
+ return;
+ }
structure = GST_QUERY_STRUCTURE (query);
gst_structure_id_set (structure,
@@ -1337,6 +1381,8 @@ gst_query_set_buffering_range (GstQuery * query, GstFormat format,
GST_QUARK (START_VALUE), G_TYPE_INT64, start,
GST_QUARK (STOP_VALUE), G_TYPE_INT64, stop,
GST_QUARK (ESTIMATED_TOTAL), G_TYPE_INT64, estimated_total, NULL);
+
+ gst_query_unlock (query);
}
/**
@@ -1401,10 +1447,12 @@ gst_query_add_buffering_range (GstQuery * query, gint64 start, gint64 stop)
GstStructure *structure;
g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING, FALSE);
- g_return_val_if_fail (gst_query_is_writable (query), FALSE);
+ g_return_val_if_fail (start < stop, FALSE);
- if (G_UNLIKELY (start >= stop))
+ if (!gst_query_try_lock (query, GST_LOCK_WRITE)) {
+ g_warning ("could not lock query %p in WRITE mode", query);
return FALSE;
+ }
structure = GST_QUERY_STRUCTURE (query);
array = ensure_array (structure, GST_QUARK (BUFFERING_RANGES));
@@ -1413,7 +1461,7 @@ gst_query_add_buffering_range (GstQuery * query, gint64 start, gint64 stop)
last_array_value = g_value_array_get_nth (array, array->n_values - 1);
if (G_UNLIKELY (start <= gst_value_get_int64_range_min (last_array_value)))
- return FALSE;
+ goto invalid_range;
}
g_value_init (&value, GST_TYPE_INT64_RANGE);
@@ -1421,7 +1469,16 @@ gst_query_add_buffering_range (GstQuery * query, gint64 start, gint64 stop)
g_value_array_append (array, &value);
/* skip the g_value_unset(&value) here, we know it's not needed */
+ gst_query_unlock (query);
+
return TRUE;
+
+ /* ERRORS */
+invalid_range:
+ {
+ gst_query_unlock (query);
+ return FALSE;
+ }
}
/**
@@ -1532,11 +1589,17 @@ gst_query_set_uri (GstQuery * query, const gchar * uri)
GstStructure *structure;
g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI);
- g_return_if_fail (gst_query_is_writable (query));
g_return_if_fail (gst_uri_is_valid (uri));
+ if (!gst_query_try_lock (query, GST_LOCK_WRITE)) {
+ g_warning ("could not lock query %p in WRITE mode", query);
+ return;
+ }
+
structure = GST_QUERY_STRUCTURE (query);
gst_structure_id_set (structure, GST_QUARK (URI), G_TYPE_STRING, uri, NULL);
+
+ gst_query_unlock (query);
}
/**
@@ -1640,10 +1703,14 @@ gst_query_set_allocation_params (GstQuery * query, guint size,
GstStructure *structure;
g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
- g_return_if_fail (gst_query_is_writable (query));
g_return_if_fail (((alignment + 1) & alignment) == 0);
g_return_if_fail (size != 0 || pool == NULL);
+ if (!gst_query_try_lock (query, GST_LOCK_WRITE)) {
+ g_warning ("could not lock query %p in WRITE mode", query);
+ return;
+ }
+
structure = GST_QUERY_STRUCTURE (query);
gst_structure_id_set (structure,
GST_QUARK (SIZE), G_TYPE_UINT, size,
@@ -1652,6 +1719,8 @@ gst_query_set_allocation_params (GstQuery * query, guint size,
GST_QUARK (PREFIX), G_TYPE_UINT, prefix,
GST_QUARK (ALIGN), G_TYPE_UINT, alignment,
GST_QUARK (POOL), GST_TYPE_BUFFER_POOL, pool, NULL);
+
+ gst_query_unlock (query);
}
/**
@@ -1701,7 +1770,11 @@ gst_query_add_allocation_meta (GstQuery * query, const gchar * api)
g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
g_return_if_fail (api != NULL);
- g_return_if_fail (gst_query_is_writable (query));
+
+ if (!gst_query_try_lock (query, GST_LOCK_WRITE)) {
+ g_warning ("could not lock query %p in WRITE mode", query);
+ return;
+ }
structure = GST_QUERY_STRUCTURE (query);
array = ensure_array (structure, GST_QUARK (META));
@@ -1710,6 +1783,8 @@ gst_query_add_allocation_meta (GstQuery * query, const gchar * api)
g_value_set_string (&api_value, api);
g_value_array_append (array, &api_value);
g_value_unset (&api_value);
+
+ gst_query_unlock (query);
}
/**
@@ -1810,7 +1885,11 @@ gst_query_add_allocation_memory (GstQuery * query, const gchar * alloc)
GstStructure *structure;
g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
- g_return_if_fail (gst_query_is_writable (query));
+
+ if (!gst_query_try_lock (query, GST_LOCK_WRITE)) {
+ g_warning ("could not lock query %p in WRITE mode", query);
+ return;
+ }
structure = GST_QUERY_STRUCTURE (query);
array = ensure_array (structure, GST_QUARK (ALLOCATOR));
@@ -1819,6 +1898,8 @@ gst_query_add_allocation_memory (GstQuery * query, const gchar * alloc)
g_value_set_string (&value, alloc);
g_value_array_append (array, &value);
g_value_unset (&value);
+
+ gst_query_unlock (query);
}
/**
@@ -1918,7 +1999,11 @@ gst_query_set_scheduling (GstQuery * query, GstSchedulingFlags flags,
GstStructure *structure;
g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING);
- g_return_if_fail (gst_query_is_writable (query));
+
+ if (!gst_query_try_lock (query, GST_LOCK_WRITE)) {
+ g_warning ("could not lock query %p in WRITE mode", query);
+ return;
+ }
structure = GST_QUERY_STRUCTURE (query);
gst_structure_id_set (structure,
@@ -1926,6 +2011,8 @@ gst_query_set_scheduling (GstQuery * query, GstSchedulingFlags flags,
GST_QUARK (MINSIZE), G_TYPE_INT, minsize,
GST_QUARK (MAXSIZE), G_TYPE_INT, maxsize,
GST_QUARK (ALIGN), G_TYPE_INT, align, NULL);
+
+ gst_query_unlock (query);
}
/**
@@ -1969,7 +2056,11 @@ gst_query_add_scheduling_mode (GstQuery * query, GstPadMode mode)
GstStructure *structure;
g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING);
- g_return_if_fail (gst_query_is_writable (query));
+
+ if (!gst_query_try_lock (query, GST_LOCK_WRITE)) {
+ g_warning ("could not lock query %p in WRITE mode", query);
+ return;
+ }
structure = GST_QUERY_STRUCTURE (query);
array = ensure_array (structure, GST_QUARK (MODES));
@@ -1978,6 +2069,8 @@ gst_query_add_scheduling_mode (GstQuery * query, GstPadMode mode)
g_value_set_enum (&value, mode);
g_value_array_append (array, &value);
g_value_unset (&value);
+
+ gst_query_unlock (query);
}
/**
@@ -2112,11 +2205,17 @@ gst_query_set_accept_caps_result (GstQuery * query, gboolean result)
GstStructure *structure;
g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ACCEPT_CAPS);
- g_return_if_fail (gst_query_is_writable (query));
+
+ if (!gst_query_try_lock (query, GST_LOCK_WRITE)) {
+ g_warning ("could not lock query %p in WRITE mode", query);
+ return;
+ }
structure = GST_QUERY_STRUCTURE (query);
gst_structure_id_set (structure,
GST_QUARK (RESULT), G_TYPE_BOOLEAN, result, NULL);
+
+ gst_query_unlock (query);
}
void
@@ -2201,10 +2300,16 @@ gst_query_set_caps_result (GstQuery * query, GstCaps * caps)
GstStructure *structure;
g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CAPS);
- g_return_if_fail (gst_query_is_writable (query));
+
+ if (!gst_query_try_lock (query, GST_LOCK_WRITE)) {
+ g_warning ("could not lock query %p in WRITE mode", query);
+ return;
+ }
structure = GST_QUERY_STRUCTURE (query);
gst_structure_id_set (structure, GST_QUARK (CAPS), GST_TYPE_CAPS, caps, NULL);
+
+ gst_query_unlock (query);
}
/**
diff --git a/gst/gstquery.h b/gst/gstquery.h
index aa2983de4..31862eb32 100644
--- a/gst/gstquery.h
+++ b/gst/gstquery.h
@@ -219,22 +219,10 @@ gst_query_copy (const GstQuery * q)
return GST_QUERY_CAST (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST (q)));
}
-/**
- * gst_query_is_writable:
- * @q: a #GstQuery
- *
- * Tests if you can safely write data into a query's structure.
- */
-#define gst_query_is_writable(q) gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (q))
-/**
- * gst_query_make_writable:
- * @q: (transfer full): a #GstQuery to make writable
- *
- * Makes a writable query from the given query.
- *
- * Returns: (transfer full): a new writable query (possibly same as @q)
- */
-#define gst_query_make_writable(q) GST_QUERY_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (q)))
+#define gst_query_try_lock(query,mode) gst_mini_object_try_lock (GST_MINI_OBJECT_CAST (query),mode)
+#define gst_query_unlock(query) gst_mini_object_unlock (GST_MINI_OBJECT_CAST (query))
+#define gst_query_make_locked(query,mode) GST_QUERY_CAST (gst_mini_object_make_locked (GST_MINI_OBJECT_CAST (query), mode))
+
/**
* gst_query_replace:
* @old_query: (inout) (transfer full): pointer to a pointer to a #GstQuery
diff --git a/libs/gst/base/gstbaseparse.c b/libs/gst/base/gstbaseparse.c
index 0014c6984..8365dc15b 100644
--- a/libs/gst/base/gstbaseparse.c
+++ b/libs/gst/base/gstbaseparse.c
@@ -2410,7 +2410,8 @@ gst_base_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
gst_buffer_get_size (buffer), GST_BUFFER_OFFSET (buffer));
if (G_UNLIKELY (parse->priv->passthrough)) {
gst_base_parse_frame_init (frame);
- frame->buffer = gst_buffer_make_writable (buffer);
+ frame->buffer = gst_buffer_make_locked (buffer, GST_LOCK_WRITE);
+ gst_buffer_unlock (frame->buffer);
return gst_base_parse_push_frame (parse, frame);
}
/* upstream feeding us in reverse playback;
@@ -2515,8 +2516,9 @@ gst_base_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
* fragment coming later, hopefully subclass skips efficiently ... */
timestamp = gst_adapter_prev_timestamp (parse->priv->adapter, NULL);
outbuf = gst_adapter_take_buffer (parse->priv->adapter, skip);
- outbuf = gst_buffer_make_writable (outbuf);
+ outbuf = gst_buffer_make_locked (outbuf, GST_LOCK_WRITE);
GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
+ gst_buffer_unlock (outbuf);
parse->priv->buffers_pending =
g_slist_prepend (parse->priv->buffers_pending, outbuf);
outbuf = NULL;
@@ -2567,13 +2569,14 @@ gst_base_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
/* FIXME: Would it be more efficient to make a subbuffer instead? */
outbuf = gst_adapter_take_buffer (parse->priv->adapter, fsize);
- outbuf = gst_buffer_make_writable (outbuf);
+ outbuf = gst_buffer_make_locked (outbuf, GST_LOCK_WRITE);
/* Subclass may want to know the data offset */
GST_BUFFER_OFFSET (outbuf) = parse->priv->offset;
parse->priv->offset += fsize;
GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE;
GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
+ gst_buffer_unlock (outbuf);
frame->buffer = outbuf;
ret = gst_base_parse_handle_and_push_frame (parse, bclass, frame);
diff --git a/libs/gst/base/gstbasesink.c b/libs/gst/base/gstbasesink.c
index 1afdfd997..723e4e632 100644
--- a/libs/gst/base/gstbasesink.c
+++ b/libs/gst/base/gstbasesink.c
@@ -3926,9 +3926,11 @@ gst_base_sink_negotiate_pull (GstBaseSink * basesink)
pull() without setcaps() */
result = TRUE;
} else {
- caps = gst_caps_make_writable (caps);
+ caps = gst_caps_make_locked (caps, GST_LOCK_WRITE);
/* try to fixate */
gst_base_sink_fixate (basesink, caps);
+ gst_caps_unlock (caps);
+
GST_DEBUG_OBJECT (basesink, "fixated to: %" GST_PTR_FORMAT, caps);
if (gst_caps_is_fixed (caps)) {
diff --git a/libs/gst/base/gstbasesrc.c b/libs/gst/base/gstbasesrc.c
index a0775d10d..a6e69d4f2 100644
--- a/libs/gst/base/gstbasesrc.c
+++ b/libs/gst/base/gstbasesrc.c
@@ -2286,8 +2286,9 @@ again:
if (offset == 0 && src->segment.time == 0
&& GST_BUFFER_TIMESTAMP (*buf) == -1 && !src->is_live) {
GST_DEBUG_OBJECT (src, "setting first timestamp to 0");
- *buf = gst_buffer_make_writable (*buf);
+ *buf = gst_buffer_make_locked (*buf, GST_LOCK_WRITE);
GST_BUFFER_TIMESTAMP (*buf) = 0;
+ gst_buffer_unlock (*buf);
}
/* now sync before pushing the buffer */
@@ -2590,8 +2591,9 @@ gst_base_src_loop (GstPad * pad)
if (G_UNLIKELY (src->priv->discont)) {
GST_INFO_OBJECT (src, "marking pending DISCONT");
- buf = gst_buffer_make_writable (buf);
+ buf = gst_buffer_make_locked (buf, GST_LOCK_WRITE);
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
+ gst_buffer_unlock (buf);
src->priv->discont = FALSE;
}
GST_LIVE_UNLOCK (src);
@@ -2846,8 +2848,9 @@ gst_base_src_default_negotiate (GstBaseSrc * basesrc)
* nego is not needed */
result = TRUE;
} else {
- caps = gst_caps_make_writable (caps);
+ caps = gst_caps_make_locked (caps, GST_LOCK_WRITE);
gst_base_src_fixate (basesrc, caps);
+ gst_caps_unlock (caps);
GST_DEBUG_OBJECT (basesrc, "fixated to: %" GST_PTR_FORMAT, caps);
if (gst_caps_is_fixed (caps)) {
/* yay, fixed caps, use those then, it's possible that the subclass does
diff --git a/libs/gst/base/gstbasetransform.c b/libs/gst/base/gstbasetransform.c
index 2cb1d8595..01e437a9f 100644
--- a/libs/gst/base/gstbasetransform.c
+++ b/libs/gst/base/gstbasetransform.c
@@ -1052,7 +1052,7 @@ gst_base_transform_find_transform (GstBaseTransform * trans, GstPad * pad,
/* second attempt at fixation, call the fixate vmethod */
/* caps could be fixed but the subclass may want to add fields */
if (klass->fixate_caps) {
- othercaps = gst_caps_make_writable (othercaps);
+ othercaps = gst_caps_make_locked (othercaps, GST_LOCK_READWRITE);
GST_DEBUG_OBJECT (trans, "calling faxate_caps for %" GST_PTR_FORMAT
" using caps %" GST_PTR_FORMAT " on pad %s:%s", othercaps, caps,
@@ -1060,6 +1060,7 @@ gst_base_transform_find_transform (GstBaseTransform * trans, GstPad * pad,
/* note that we pass the complete array of structures to the fixate
* function, it needs to truncate itself */
klass->fixate_caps (trans, GST_PAD_DIRECTION (pad), caps, othercaps);
+ gst_caps_unlock (othercaps);
is_fixed = gst_caps_is_fixed (othercaps);
GST_DEBUG_OBJECT (trans, "after fixating %" GST_PTR_FORMAT, othercaps);
}
@@ -1496,7 +1497,7 @@ default_copy_metadata (GstBaseTransform * trans,
/* this should not happen, buffers allocated from a pool or with
* new_allocate should always be writable. */
- if (!gst_buffer_is_writable (outbuf))
+ if (!gst_buffer_try_lock (outbuf, GST_LOCK_WRITE))
goto not_writable;
/* when we get here, the metadata should be writable */
@@ -1507,6 +1508,8 @@ default_copy_metadata (GstBaseTransform * trans,
if (!priv->gap_aware)
GST_BUFFER_FLAG_UNSET (outbuf, GST_BUFFER_FLAG_GAP);
+ gst_buffer_unlock (outbuf);
+
return TRUE;
/* ERRORS */
@@ -1892,7 +1895,7 @@ no_qos:
indata = gst_buffer_map (inbuf, &insize, NULL, GST_MAP_READ);
outdata = gst_buffer_map (*outbuf, &outsize, NULL, GST_MAP_WRITE);
- if (indata != outdata)
+ if (indata && outdata && indata != outdata)
memcpy (outdata, indata, insize);
gst_buffer_unmap (inbuf, indata, insize);
@@ -2041,8 +2044,9 @@ gst_base_transform_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
GST_DEBUG_OBJECT (trans, "we have a pending DISCONT");
if (!GST_BUFFER_IS_DISCONT (outbuf)) {
GST_DEBUG_OBJECT (trans, "marking DISCONT on output buffer");
- outbuf = gst_buffer_make_writable (outbuf);
+ outbuf = gst_buffer_make_locked (outbuf, GST_LOCK_WRITE);
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
+ gst_buffer_unlock (outbuf);
}
trans->priv->discont = FALSE;
}
diff --git a/libs/gst/base/gstcollectpads2.c b/libs/gst/base/gstcollectpads2.c
index cf1f50097..5fec71dcf 100644
--- a/libs/gst/base/gstcollectpads2.c
+++ b/libs/gst/base/gstcollectpads2.c
@@ -437,8 +437,9 @@ gst_collect_pads2_clip_running_time (GstCollectPads2 * pads,
GST_LOG_OBJECT (cdata->pad, "buffer ts %" GST_TIME_FORMAT " -> %"
GST_TIME_FORMAT " running time",
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), GST_TIME_ARGS (time));
- *outbuf = gst_buffer_make_writable (buf);
+ *outbuf = gst_buffer_make_locked (buf, GST_LOCK_WRITE);
GST_BUFFER_TIMESTAMP (*outbuf) = time;
+ gst_buffer_unlock (*outbuf);
}
}
diff --git a/plugins/elements/gstcapsfilter.c b/plugins/elements/gstcapsfilter.c
index ceed30885..15070b4da 100644
--- a/plugins/elements/gstcapsfilter.c
+++ b/plugins/elements/gstcapsfilter.c
@@ -350,8 +350,9 @@ gst_capsfilter_prepare_buf (GstBaseTransform * trans, GstBuffer * input,
g_return_val_if_fail (out_caps != NULL, GST_FLOW_ERROR);
}
- out_caps = gst_caps_make_writable (out_caps);
+ out_caps = gst_caps_make_locked (out_caps, GST_LOCK_READWRITE);
gst_caps_do_simplify (out_caps);
+ gst_caps_unlock (out_caps);
if (gst_caps_is_fixed (out_caps) && !gst_caps_is_empty (out_caps)) {
GST_DEBUG_OBJECT (trans, "Have fixed output caps %"
diff --git a/plugins/elements/gstfunnel.c b/plugins/elements/gstfunnel.c
index 82229108b..45c0d04d3 100644
--- a/plugins/elements/gstfunnel.c
+++ b/plugins/elements/gstfunnel.c
@@ -242,8 +242,9 @@ gst_funnel_sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
newts = gst_segment_to_running_time (&fpad->segment,
fpad->segment.format, GST_BUFFER_TIMESTAMP (buffer));
if (newts != GST_BUFFER_TIMESTAMP (buffer)) {
- buffer = gst_buffer_make_writable (buffer);
+ buffer = gst_buffer_make_locked (buffer, GST_LOCK_WRITE);
GST_BUFFER_TIMESTAMP (buffer) = newts;
+ gst_buffer_unlock (buffer);
}
if (!funnel->has_segment) {
diff --git a/plugins/elements/gstidentity.c b/plugins/elements/gstidentity.c
index 2a3350d48..3aca21a7d 100644
--- a/plugins/elements/gstidentity.c
+++ b/plugins/elements/gstidentity.c
@@ -407,13 +407,8 @@ gst_identity_prepare_output_buffer (GstBaseTransform * trans,
/* only bother if we may have to alter metadata */
if (identity->datarate > 0 || identity->single_segment) {
- if (gst_buffer_is_writable (in_buf))
- /* reuse */
- *out_buf = in_buf;
- else {
- /* copy */
- *out_buf = gst_buffer_copy (in_buf);
- }
+ *out_buf = gst_buffer_make_locked (in_buf, GST_LOCK_READWRITE);
+ gst_buffer_unlock (*out_buf);
} else
*out_buf = in_buf;
diff --git a/plugins/elements/gstinputselector.c b/plugins/elements/gstinputselector.c
index 17a0bfc51..1321af66e 100644
--- a/plugins/elements/gstinputselector.c
+++ b/plugins/elements/gstinputselector.c
@@ -700,10 +700,10 @@ gst_selector_pad_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
gst_pad_push_event (sel->srcpad, start_event);
if (selpad->discont) {
- buf = gst_buffer_make_writable (buf);
-
+ buf = gst_buffer_make_locked (buf, GST_LOCK_WRITE);
GST_DEBUG_OBJECT (pad, "Marking discont buffer %p", buf);
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
+ gst_buffer_unlock (buf);
selpad->discont = FALSE;
}
diff --git a/plugins/elements/gstqueue.c b/plugins/elements/gstqueue.c
index a1cb42d2a..f573eac0c 100644
--- a/plugins/elements/gstqueue.c
+++ b/plugins/elements/gstqueue.c
@@ -958,11 +958,12 @@ gst_queue_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
}
if (queue->tail_needs_discont) {
- GstBuffer *subbuffer = gst_buffer_make_writable (buffer);
+ GstBuffer *subbuffer = gst_buffer_make_locked (buffer, GST_LOCK_WRITE);
if (subbuffer) {
buffer = subbuffer;
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
+ gst_buffer_unref (subbuffer);
} else {
GST_DEBUG_OBJECT (queue, "Could not mark buffer as DISCONT");
}
@@ -1045,11 +1046,12 @@ next:
buffer = GST_BUFFER_CAST (data);
if (queue->head_needs_discont) {
- GstBuffer *subbuffer = gst_buffer_make_writable (buffer);
+ GstBuffer *subbuffer = gst_buffer_make_locked (buffer, GST_LOCK_WRITE);
if (subbuffer) {
buffer = subbuffer;
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
+ gst_buffer_unlock (buffer);
} else {
GST_DEBUG_OBJECT (queue, "Could not mark buffer as DISCONT");
}
diff --git a/plugins/elements/gstvalve.c b/plugins/elements/gstvalve.c
index 41bf207ac..7378a8e88 100644
--- a/plugins/elements/gstvalve.c
+++ b/plugins/elements/gstvalve.c
@@ -176,8 +176,9 @@ gst_valve_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
valve->discont = TRUE;
} else {
if (valve->discont) {
- buffer = gst_buffer_make_writable (buffer);
+ buffer = gst_buffer_make_locked (buffer, GST_LOCK_WRITE);
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
+ gst_buffer_unlock (buffer);
valve->discont = FALSE;
}
diff --git a/tests/check/gst/gstbuffer.c b/tests/check/gst/gstbuffer.c
index 1ac9688e6..02b6142de 100644
--- a/tests/check/gst/gstbuffer.c
+++ b/tests/check/gst/gstbuffer.c
@@ -41,12 +41,14 @@ GST_START_TEST (test_subbuffer)
buffer = gst_buffer_new_and_alloc (4);
/* check sizes, buffer starts out empty */
+ GST_DEBUG ("1");
data = gst_buffer_map (buffer, &size, &maxsize, GST_MAP_WRITE);
fail_unless (size == 4, "buffer has wrong size");
fail_unless (maxsize >= 4, "buffer has wrong size");
memset (data, 0, 4);
gst_buffer_unmap (buffer, data, 4);
+ GST_DEBUG ("2");
data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
/* set some metadata */
GST_BUFFER_TIMESTAMP (buffer) = 1;
@@ -54,9 +56,11 @@ GST_START_TEST (test_subbuffer)
GST_BUFFER_OFFSET (buffer) = 3;
GST_BUFFER_OFFSET_END (buffer) = 4;
+ GST_DEBUG ("3");
sub = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 1, 2);
fail_if (sub == NULL, "copy region of buffer returned NULL");
+ GST_DEBUG ("4");
sdata = gst_buffer_map (sub, &ssize, NULL, GST_MAP_READ);
fail_unless (ssize == 2, "subbuffer has wrong size");
fail_unless (memcmp (data + 1, sdata, 2) == 0,
@@ -72,14 +76,12 @@ GST_START_TEST (test_subbuffer)
gst_buffer_unref (sub);
/* create a subbuffer of size 0 */
+ GST_DEBUG ("5");
sub = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 1, 0);
fail_if (sub == NULL, "copy_region of buffer returned NULL");
sdata = gst_buffer_map (sub, &ssize, NULL, GST_MAP_READ);
- fail_unless (ssize == 0, "subbuffer has wrong size");
- fail_unless (memcmp (data + 1, sdata, 0) == 0,
- "subbuffer contains the wrong data");
+ fail_unless (sdata == NULL, "subbuffer has wrong data");
ASSERT_BUFFER_REFCOUNT (sub, "subbuffer", 1);
- gst_buffer_unmap (sub, sdata, ssize);
gst_buffer_unref (sub);
/* test if metadata is coppied, not a complete buffer copy so only the
@@ -270,16 +272,18 @@ GST_START_TEST (test_make_writable)
/* alloc'ed buffer with refcount 1 should be writable */
buf = gst_buffer_new_and_alloc (32);
- buf2 = gst_buffer_make_writable (buf);
+ buf2 = gst_buffer_make_locked (buf, GST_LOCK_WRITE);
fail_unless (buf == buf2,
"_make_writable() should have returned same buffer");
+ gst_buffer_unlock (buf2);
gst_buffer_unref (buf2);
/* alloc'ed buffer with refcount >1 should be copied */
buf = gst_buffer_new_and_alloc (32);
gst_buffer_ref (buf);
- buf2 = gst_buffer_make_writable (buf);
+ buf2 = gst_buffer_make_locked (buf, GST_LOCK_WRITE);
fail_unless (buf != buf2, "_make_writable() should have returned a copy!");
+ gst_buffer_unlock (buf2);
gst_buffer_unref (buf2);
gst_buffer_unref (buf);
}
@@ -316,18 +320,18 @@ GST_START_TEST (test_metadata_writable)
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
/* Buffer with refcount 1 should have writable metadata */
- fail_unless (gst_buffer_is_writable (buffer) == TRUE);
+ fail_unless (gst_buffer_try_lock (buffer, GST_LOCK_WRITE) == TRUE);
+ gst_buffer_unlock (buffer);
/* Check that a buffer with refcount 2 does not have writable metadata */
gst_buffer_ref (buffer);
ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 2);
- fail_unless (gst_buffer_is_writable (buffer) == FALSE);
+ fail_unless (gst_buffer_try_lock (buffer, GST_LOCK_WRITE) == FALSE);
/* Check that make_metadata_writable produces a new sub-buffer with
* writable metadata. */
- sub1 = gst_buffer_make_writable (buffer);
+ sub1 = gst_buffer_make_locked (buffer, GST_LOCK_WRITE);
fail_if (sub1 == buffer);
- fail_unless (gst_buffer_is_writable (sub1) == TRUE);
/* Check that make_metadata_writable() maintains the buffer flags */
fail_unless (GST_BUFFER_FLAG_IS_SET (sub1, GST_BUFFER_FLAG_DISCONT));
@@ -342,10 +346,12 @@ GST_START_TEST (test_metadata_writable)
/* Drop the subbuffer and check that the metadata is now writable again */
ASSERT_BUFFER_REFCOUNT (sub1, "sub1", 1);
+ gst_buffer_unlock (sub1);
gst_buffer_unref (sub1);
- fail_unless (gst_buffer_is_writable (buffer) == TRUE);
+ fail_unless (gst_buffer_try_lock (buffer, GST_LOCK_WRITE) == TRUE);
ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 1);
+ gst_buffer_unlock (buffer);
gst_buffer_unref (buffer);
}
@@ -382,14 +388,12 @@ GST_START_TEST (test_copy)
buffer = gst_buffer_new_and_alloc (0);
data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
fail_unless (data == NULL);
- gst_buffer_unmap (buffer, data, size);
/* copying a 0-sized buffer should not crash and also set
* the data member NULL. */
copy = gst_buffer_copy (buffer);
data = gst_buffer_map (copy, &size, NULL, GST_MAP_READ);
fail_unless (data == NULL);
- gst_buffer_unmap (copy, data, size);
gst_buffer_unref (copy);
gst_buffer_unref (buffer);
@@ -409,7 +413,6 @@ GST_START_TEST (test_try_new_and_alloc)
fail_unless (GST_IS_BUFFER (buf));
data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
fail_unless (data == NULL);
- gst_buffer_unmap (buf, data, size);
gst_buffer_unref (buf);
/* normal alloc should still work */
@@ -456,7 +459,7 @@ GST_START_TEST (test_size)
fail_unless (offset == 0);
fail_unless (maxalloc >= 100);
- mem = gst_buffer_peek_memory (buf, 0, GST_MAP_WRITE);
+ mem = gst_buffer_peek_memory (buf, 0);
gst_memory_resize (mem, 10, 70);
size = gst_buffer_get_sizes (buf, &offset, &maxsize);
diff --git a/tests/check/gst/gstmemory.c b/tests/check/gst/gstmemory.c
index 02115c751..f50b225e2 100644
--- a/tests/check/gst/gstmemory.c
+++ b/tests/check/gst/gstmemory.c
@@ -45,7 +45,7 @@ GST_START_TEST (test_submemory)
fail_unless (size == 4, "memory has wrong size");
fail_unless (maxsize >= 4, "memory has wrong size");
memset (data, 0, 4);
- gst_memory_unmap (memory, data, 4);
+ gst_memory_unmap (memory);
data = gst_memory_map (memory, &size, NULL, GST_MAP_READ);
@@ -57,7 +57,7 @@ GST_START_TEST (test_submemory)
fail_unless (memcmp (data + 1, sdata, 2) == 0,
"submemory contains the wrong data");
ASSERT_MEMORY_REFCOUNT (sub, "submemory", 1);
- gst_memory_unmap (sub, sdata, ssize);
+ gst_memory_unmap (sub);
gst_memory_unref (sub);
/* create a submemory of size 0 */
@@ -68,7 +68,7 @@ GST_START_TEST (test_submemory)
fail_unless (memcmp (data + 1, sdata, 0) == 0,
"submemory contains the wrong data");
ASSERT_MEMORY_REFCOUNT (sub, "submemory", 1);
- gst_memory_unmap (sub, sdata, ssize);
+ gst_memory_unmap (sub);
gst_memory_unref (sub);
/* test if metadata is coppied, not a complete memory copy so only the
@@ -89,7 +89,7 @@ GST_START_TEST (test_submemory)
/* clean up */
gst_memory_unref (sub);
- gst_memory_unmap (memory, data, size);
+ gst_memory_unmap (memory);
gst_memory_unref (memory);
}
@@ -134,7 +134,6 @@ create_read_only_memory (void)
/* assign some read-only data to the new memory */
mem = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
(gpointer) ro_memory, NULL, sizeof (ro_memory), 0, sizeof (ro_memory));
- fail_if (gst_memory_is_writable (mem));
return mem;
}
@@ -148,24 +147,21 @@ GST_START_TEST (test_writable)
/* create read-only memory and try to write */
mem = create_read_only_memory ();
- ASSERT_CRITICAL (gst_memory_map (mem, &size, NULL, GST_MAP_WRITE));
- fail_if (gst_memory_is_writable (mem));
+ fail_if (gst_memory_map (mem, &size, NULL, GST_MAP_WRITE));
mem2 = gst_memory_copy (mem, 0, -1);
- fail_if (gst_memory_is_writable (mem));
- fail_unless (gst_memory_is_writable (mem2));
data = gst_memory_map (mem2, &size, NULL, GST_MAP_WRITE);
data[4] = 'a';
- gst_memory_unmap (mem2, data, size);
+ gst_memory_unmap (mem2);
gst_memory_ref (mem2);
- ASSERT_CRITICAL (gst_memory_map (mem, &size, NULL, GST_MAP_WRITE));
+ fail_if (gst_memory_map (mem, &size, NULL, GST_MAP_WRITE));
gst_memory_unref (mem2);
data = gst_memory_map (mem2, &size, NULL, GST_MAP_WRITE);
data[4] = 'a';
- gst_memory_unmap (mem2, data, size);
+ gst_memory_unmap (mem2);
gst_memory_unref (mem2);
@@ -183,10 +179,9 @@ GST_START_TEST (test_submemory_writable)
mem = create_read_only_memory ();
sub_mem = gst_memory_share (mem, 0, 8);
- fail_if (gst_memory_is_writable (sub_mem));
- ASSERT_CRITICAL (gst_memory_map (mem, &size, NULL, GST_MAP_WRITE));
- ASSERT_CRITICAL (gst_memory_map (sub_mem, &size, NULL, GST_MAP_WRITE));
+ fail_if (gst_memory_map (mem, &size, NULL, GST_MAP_WRITE));
+ fail_if (gst_memory_map (sub_mem, &size, NULL, GST_MAP_WRITE));
gst_memory_unref (sub_mem);
gst_memory_unref (mem);
@@ -198,7 +193,6 @@ GST_START_TEST (test_copy)
{
GstMemory *memory, *copy;
gsize size, ssize;
- guint8 *data, *sdata;
memory = gst_allocator_alloc (NULL, 4, 0);
ASSERT_MEMORY_REFCOUNT (memory, "memory", 1);
@@ -209,28 +203,28 @@ GST_START_TEST (test_copy)
/* memorys are copied and must point to different memory */
fail_if (memory == copy);
- data = gst_memory_map (memory, &size, NULL, GST_MAP_READ);
- sdata = gst_memory_map (copy, &ssize, NULL, GST_MAP_READ);
+ gst_memory_map (memory, &size, NULL, GST_MAP_READ);
+ gst_memory_map (copy, &ssize, NULL, GST_MAP_READ);
/* NOTE that data is refcounted */
fail_unless (size == ssize);
- gst_memory_unmap (copy, sdata, ssize);
- gst_memory_unmap (memory, data, size);
+ gst_memory_unmap (copy);
+ gst_memory_unmap (memory);
gst_memory_unref (copy);
gst_memory_unref (memory);
memory = gst_allocator_alloc (NULL, 0, 0);
- data = gst_memory_map (memory, &size, NULL, GST_MAP_READ);
+ gst_memory_map (memory, &size, NULL, GST_MAP_READ);
fail_unless (size == 0);
- gst_memory_unmap (memory, data, size);
+ gst_memory_unmap (memory);
/* copying a 0-sized memory should not crash */
copy = gst_memory_copy (memory, 0, -1);
- data = gst_memory_map (copy, &size, NULL, GST_MAP_READ);
+ gst_memory_map (copy, &size, NULL, GST_MAP_READ);
fail_unless (size == 0);
- gst_memory_unmap (copy, data, size);
+ gst_memory_unmap (copy);
gst_memory_unref (copy);
gst_memory_unref (memory);
@@ -248,7 +242,7 @@ GST_START_TEST (test_try_new_and_alloc)
fail_unless (mem != NULL);
data = gst_memory_map (mem, &size, NULL, GST_MAP_READ);
fail_unless (size == 0);
- gst_memory_unmap (mem, data, size);
+ gst_memory_unmap (mem);
gst_memory_unref (mem);
/* normal alloc should still work */
@@ -258,7 +252,7 @@ GST_START_TEST (test_try_new_and_alloc)
fail_unless (data != NULL);
fail_unless (size == (640 * 480 * 4));
data[640 * 479 * 4 + 479] = 0xff;
- gst_memory_unmap (mem, data, size);
+ gst_memory_unmap (mem);
gst_memory_unref (mem);
@@ -397,51 +391,7 @@ GST_START_TEST (test_map)
fail_unless (data != NULL);
fail_unless (size == 100);
fail_unless (maxsize == maxalloc);
- ASSERT_CRITICAL (gst_memory_unmap (mem, (guint8 *) data - 1, maxsize + 1));
- gst_memory_unmap (mem, data, size);
-
- /* make smaller by unmapping less */
- data = gst_memory_map (mem, &size, &maxsize, GST_MAP_READ);
- fail_unless (data != NULL);
- fail_unless (size == 100);
- fail_unless (maxsize == maxalloc);
- gst_memory_unmap (mem, data, size - 1);
-
- size = gst_memory_get_sizes (mem, &offset, &maxalloc);
- fail_unless (size == 99);
- fail_unless (offset == 0);
- fail_unless (maxalloc >= 100);
-
- /* make bigger by unmapping more */
- data = gst_memory_map (mem, &size, &maxsize, GST_MAP_READ);
- fail_unless (data != NULL);
- fail_unless (size == 99);
- fail_unless (maxsize == maxalloc);
- gst_memory_unmap (mem, data, size + 1);
-
- size = gst_memory_get_sizes (mem, &offset, &maxalloc);
- fail_unless (size == 100);
- fail_unless (offset == 0);
- fail_unless (maxalloc >= 100);
-
- /* resize beyond the maxsize */
- data = gst_memory_map (mem, &size, &maxsize, GST_MAP_READ);
- fail_unless (data != NULL);
- fail_unless (size == 100);
- fail_unless (maxsize == maxalloc);
- ASSERT_CRITICAL (gst_memory_unmap (mem, data, maxsize + 1));
- gst_memory_unmap (mem, data, maxsize);
-
- /* add offset, maxsize should be smaller now */
- gst_memory_resize (mem, 1, 99);
-
- data = gst_memory_map (mem, &size, &maxsize, GST_MAP_READ);
- fail_unless (data != NULL);
- fail_unless (size == 99);
- fail_unless (maxsize == maxalloc - 1);
- ASSERT_CRITICAL (gst_memory_unmap (mem, data, maxsize + 1));
- gst_memory_unmap (mem, data, maxsize);
-
+ gst_memory_unmap (mem);
gst_memory_unref (mem);
}
@@ -464,52 +414,38 @@ GST_START_TEST (test_map_nested)
fail_unless (data2 == data1);
fail_unless (size2 == 100);
- /* unmap in reverse order */
- gst_memory_unmap (mem, data2, size2);
- gst_memory_unmap (mem, data1, size1);
-
- /* nested mapping */
- data1 = gst_memory_map (mem, &size1, &maxsize1, GST_MAP_READ);
- fail_unless (data1 != NULL);
- fail_unless (size1 == 100);
-
- data2 = gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READ);
- fail_unless (data2 == data1);
- fail_unless (size2 == 100);
-
- /* unmap in different order */
- gst_memory_unmap (mem, data1, size1);
- gst_memory_unmap (mem, data2, size2);
+ /* unmap */
+ gst_memory_unmap (mem);
+ gst_memory_unmap (mem);
data1 = gst_memory_map (mem, &size1, &maxsize1, GST_MAP_READ);
/* not allowed */
- ASSERT_CRITICAL (gst_memory_map (mem, &size2, &maxsize2, GST_MAP_WRITE));
- ASSERT_CRITICAL (gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READWRITE));
+ fail_if (gst_memory_map (mem, &size2, &maxsize2, GST_MAP_WRITE));
+ fail_if (gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READWRITE));
data2 = gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READ);
- gst_memory_unmap (mem, data1, size1);
- gst_memory_unmap (mem, data2, size2);
+ gst_memory_unmap (mem);
+ gst_memory_unmap (mem);
fail_unless (mem->state == 0);
data1 = gst_memory_map (mem, &size1, &maxsize1, GST_MAP_WRITE);
/* not allowed */
- ASSERT_CRITICAL (gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READ));
- ASSERT_CRITICAL (gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READWRITE));
+ fail_if (gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READ));
+ fail_if (gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READWRITE));
data2 = gst_memory_map (mem, &size2, &maxsize2, GST_MAP_WRITE);
- gst_memory_unmap (mem, data1, size1);
- gst_memory_unmap (mem, data2, size2);
+ gst_memory_unmap (mem);
+ gst_memory_unmap (mem);
/* nothing was mapped */
- ASSERT_CRITICAL (gst_memory_unmap (mem, data2, size2));
+ ASSERT_CRITICAL (gst_memory_unmap (mem));
data1 = gst_memory_map (mem, &size1, &maxsize1, GST_MAP_READWRITE);
data2 = gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READ);
- gst_memory_unmap (mem, data2, size2);
+ gst_memory_unmap (mem);
data2 = gst_memory_map (mem, &size2, &maxsize2, GST_MAP_WRITE);
- gst_memory_unmap (mem, data2, size2);
+ gst_memory_unmap (mem);
/* ut of range */
- ASSERT_CRITICAL (gst_memory_unmap (mem, (guint8 *) data1 - 1, size1));
- gst_memory_unmap (mem, data1, size1);
+ gst_memory_unmap (mem);
/* nothing was mapped */
- ASSERT_CRITICAL (gst_memory_unmap (mem, data1, size1));
+ ASSERT_CRITICAL (gst_memory_unmap (mem));
gst_memory_unref (mem);
}
@@ -535,32 +471,23 @@ GST_START_TEST (test_map_resize)
fail_unless (size == 99);
fail_unless (offset == 1);
fail_unless (maxalloc >= 100);
-
- /* unmap the buffer with original pointer and size, should restore the offset
- * and size */
- gst_memory_unmap (mem, data, 100);
+ gst_memory_unmap (mem);
size = gst_memory_get_sizes (mem, &offset, &maxalloc);
- fail_unless (size == 100);
- fail_unless (offset == 0);
+ fail_unless (size == 99);
+ fail_unless (offset == 1);
fail_unless (maxalloc >= 100);
data = gst_memory_map (mem, &size, &maxsize, GST_MAP_READ);
fail_unless (data != NULL);
- fail_unless (size == 100);
- fail_unless (maxsize >= 100);
-
- /* resize the buffer with unmap */
- gst_memory_unmap (mem, (guint8 *) data + 1, 99);
-
- size = gst_memory_get_sizes (mem, &offset, &maxalloc);
fail_unless (size == 99);
- fail_unless (offset == 1);
- fail_unless (maxalloc >= 100);
+ fail_unless (maxsize >= 100);
+ gst_memory_unmap (mem);
/* and larger */
data = gst_memory_map (mem, &size, &maxsize, GST_MAP_READ);
- gst_memory_unmap (mem, (guint8 *) data - 1, 100);
+ gst_memory_resize (mem, -1, 100);
+ gst_memory_unmap (mem);
size = gst_memory_get_sizes (mem, &offset, &maxalloc);
fail_unless (size == 100);
@@ -568,21 +495,7 @@ GST_START_TEST (test_map_resize)
fail_unless (maxalloc >= 100);
data = gst_memory_map (mem, &size, &maxsize, GST_MAP_READ);
- gst_memory_unmap (mem, (guint8 *) data + 1, -1);
-
- size = gst_memory_get_sizes (mem, &offset, &maxalloc);
- fail_unless (size == 99);
- fail_unless (offset == 1);
- fail_unless (maxalloc >= 100);
-
- data = gst_memory_map (mem, &size, &maxsize, GST_MAP_READ);
- gst_memory_unmap (mem, (guint8 *) data - 1, -1);
-
- size = gst_memory_get_sizes (mem, &offset, &maxalloc);
- fail_unless (size == 100);
- fail_unless (offset == 0);
- fail_unless (maxalloc >= 100);
-
+ gst_memory_unmap (mem);
gst_memory_unref (mem);
}
diff --git a/tests/check/gst/gstminiobject.c b/tests/check/gst/gstminiobject.c
index 237f7e40c..794da0024 100644
--- a/tests/check/gst/gstminiobject.c
+++ b/tests/check/gst/gstminiobject.c
@@ -46,12 +46,12 @@ GST_START_TEST (test_is_writable)
buffer = gst_buffer_new_and_alloc (4);
mobj = GST_MINI_OBJECT_CAST (buffer);
- fail_unless (gst_mini_object_is_writable (mobj),
+ fail_unless (gst_mini_object_try_lock (mobj, GST_LOCK_WRITE),
"A buffer with one ref should be writable");
fail_if (gst_mini_object_ref (mobj) == NULL, "Could not ref the mobj");
- fail_if (gst_mini_object_is_writable (mobj),
+ fail_if (gst_mini_object_try_lock (mobj, GST_LOCK_WRITE),
"A buffer with two refs should not be writable");
}
diff --git a/tools/gst-inspect.c b/tools/gst-inspect.c
index 37684cff7..8d1c4db36 100644
--- a/tools/gst-inspect.c
+++ b/tools/gst-inspect.c
@@ -1389,7 +1389,7 @@ print_plugin_automatic_install_info_codecs (GstElementFactory * factory)
return;
}
- caps = gst_caps_make_writable (caps);
+ caps = gst_caps_make_locked (caps, GST_LOCK_READWRITE);
num = gst_caps_get_size (caps);
for (i = 0; i < num; ++i) {
GstStructure *s;
@@ -1410,6 +1410,7 @@ print_plugin_automatic_install_info_codecs (GstElementFactory * factory)
g_print ("%s-%s\n", type_name, s_str);
g_free (s_str);
}
+ gst_caps_unlock (caps);
gst_caps_unref (caps);
}