diff options
author | Wim Taymans <wim.taymans@collabora.co.uk> | 2012-01-18 14:45:28 +0100 |
---|---|---|
committer | Wim Taymans <wim.taymans@collabora.co.uk> | 2012-01-18 14:45:28 +0100 |
commit | 7fb3ec7a086600411264cae0b21b51540060057d (patch) | |
tree | 32f231d0e8182aa85f6138bbc0016df7fe1c1dc0 | |
parent | 10d901291e7bad1736a5a9792fa20884cde2b2b0 (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.c | 290 | ||||
-rw-r--r-- | gst/gstbuffer.h | 54 | ||||
-rw-r--r-- | gst/gstcaps.c | 6 | ||||
-rw-r--r-- | gst/gstcaps.h | 20 | ||||
-rw-r--r-- | gst/gstevent.c | 2 | ||||
-rw-r--r-- | gst/gstevent.h | 25 | ||||
-rw-r--r-- | gst/gstmemory.c | 274 | ||||
-rw-r--r-- | gst/gstmemory.h | 69 | ||||
-rw-r--r-- | gst/gstminiobject.c | 117 | ||||
-rw-r--r-- | gst/gstminiobject.h | 26 | ||||
-rw-r--r-- | gst/gstquery.c | 143 | ||||
-rw-r--r-- | gst/gstquery.h | 20 | ||||
-rw-r--r-- | libs/gst/base/gstbaseparse.c | 9 | ||||
-rw-r--r-- | libs/gst/base/gstbasesink.c | 4 | ||||
-rw-r--r-- | libs/gst/base/gstbasesrc.c | 9 | ||||
-rw-r--r-- | libs/gst/base/gstbasetransform.c | 12 | ||||
-rw-r--r-- | libs/gst/base/gstcollectpads2.c | 3 | ||||
-rw-r--r-- | plugins/elements/gstcapsfilter.c | 3 | ||||
-rw-r--r-- | plugins/elements/gstfunnel.c | 3 | ||||
-rw-r--r-- | plugins/elements/gstidentity.c | 9 | ||||
-rw-r--r-- | plugins/elements/gstinputselector.c | 4 | ||||
-rw-r--r-- | plugins/elements/gstqueue.c | 6 | ||||
-rw-r--r-- | plugins/elements/gstvalve.c | 3 | ||||
-rw-r--r-- | tests/check/gst/gstbuffer.c | 33 | ||||
-rw-r--r-- | tests/check/gst/gstmemory.c | 177 | ||||
-rw-r--r-- | tests/check/gst/gstminiobject.c | 4 | ||||
-rw-r--r-- | tools/gst-inspect.c | 3 |
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); } |