From 4e32ac8463aab66c5bda5a460dffda45b0aaf2d6 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 29 Mar 2011 16:52:21 +0200 Subject: [PATCH] buffer: clean up _span and add more g_return_if.. --- gst/gstbuffer.c | 186 ++++++++++++++++++++++++++++------ gst/gstmemory.c | 100 +++--------------- gst/gstmemory.h | 4 +- win32/common/libgstreamer.def | 1 - 4 files changed, 170 insertions(+), 121 deletions(-) diff --git a/gst/gstbuffer.c b/gst/gstbuffer.c index 75687a6522..e3ce594d98 100644 --- a/gst/gstbuffer.c +++ b/gst/gstbuffer.c @@ -131,6 +131,9 @@ GType _gst_buffer_type = 0; +static GstMemory *_gst_buffer_arr_span (GstMemory ** mem[], gsize len[], + guint n, gsize offset, gsize size); + typedef struct _GstMetaItem GstMetaItem; struct _GstMetaItem @@ -157,12 +160,38 @@ typedef struct GstMetaItem *item; } GstBufferImpl; +static void +_span_memory (GstBuffer * buffer, gsize offset, gsize size) +{ + GstMemory *span, **mem[1]; + gsize len[1], i; + + /* not enough room, span buffers */ + mem[0] = GST_BUFFER_MEM_ARRAY (buffer); + len[0] = GST_BUFFER_MEM_LEN (buffer); + span = _gst_buffer_arr_span (mem, len, 1, offset, size); + + /* unref old buffers */ + for (i = 0; i < len[0]; i++) + gst_memory_unref (mem[0][i]); + + /* replace with single spanned buffer */ + GST_BUFFER_MEM_PTR (buffer, 0) = span; + GST_BUFFER_MEM_LEN (buffer) = 1; +} + static inline void _memory_add (GstBuffer * buffer, GstMemory * mem) { guint len = GST_BUFFER_MEM_LEN (buffer); - /* FIXME, span buffers when we run out of places */ - g_return_if_fail (len < GST_BUFFER_MEM_MAX); + + if (G_UNLIKELY (len >= GST_BUFFER_MEM_MAX)) { + gsize size = gst_buffer_get_size (buffer); + /* to many buffer, span them */ + _span_memory (buffer, 0, size); + /* we now have 1 single spanned buffer */ + len = 1; + } GST_BUFFER_MEM_PTR (buffer, len) = mem; GST_BUFFER_MEM_LEN (buffer) = len + 1; } @@ -223,12 +252,13 @@ gst_buffer_copy_into (GstBuffer * dest, GstBuffer * src, if (G_UNLIKELY (dest == src)) return; + g_return_if_fail (gst_buffer_is_writable (dest)); + bufsize = gst_buffer_get_size (src); + g_return_if_fail (bufsize >= offset); if (size == -1) size = bufsize - offset; - g_return_if_fail (bufsize >= offset + size); - g_return_if_fail (gst_buffer_is_writable (dest)); GST_CAT_LOG (GST_CAT_BUFFER, "copy %p to %p, offset %" G_GSIZE_FORMAT "-%" G_GSIZE_FORMAT "/%" G_GSIZE_FORMAT, src, dest, offset, size, @@ -646,7 +676,7 @@ gst_buffer_trim (GstBuffer * buffer, gsize offset, gsize size) { guint len; guint si, di; - gsize bsize; + gsize bsize, bufsize; GstMemory *mem; GST_CAT_LOG (GST_CAT_BUFFER, "trim %p %" G_GSIZE_FORMAT "-%" G_GSIZE_FORMAT, @@ -654,6 +684,12 @@ gst_buffer_trim (GstBuffer * buffer, gsize offset, gsize size) g_return_if_fail (gst_buffer_is_writable (buffer)); + bufsize = gst_buffer_get_size (buffer); + g_return_if_fail (bufsize >= offset); + if (size == -1) + size = bufsize - offset; + g_return_if_fail (bufsize >= offset + size); + len = GST_BUFFER_MEM_LEN (buffer); /* copy and trim */ @@ -963,8 +999,10 @@ gst_buffer_create_sub (GstBuffer * buffer, gsize offset, gsize size) g_return_val_if_fail (buffer != NULL, NULL); g_return_val_if_fail (buffer->mini_object.refcount > 0, NULL); - bufsize = gst_buffer_get_size (buffer); + g_return_val_if_fail (bufsize >= offset, NULL); + if (size == -1) + size = bufsize - offset; g_return_val_if_fail (bufsize >= offset + size, NULL); /* create the new buffer */ @@ -978,6 +1016,92 @@ gst_buffer_create_sub (GstBuffer * buffer, gsize offset, gsize size) return subbuffer; } +static gboolean +_gst_buffer_arr_is_span_fast (GstMemory ** mem[], gsize len[], guint n, + gsize * offset, GstMemory ** parent) +{ + GstMemory *mcur, *mprv; + gboolean have_offset = FALSE; + guint count, i; + + mcur = mprv = NULL; + for (count = 0; count < n; count++) { + gsize offs, clen; + GstMemory **cmem; + + cmem = mem[count]; + clen = len[count]; + + for (i = 0; i < clen; i++) { + if (mcur) + mprv = mcur; + mcur = cmem[i]; + + if (mprv && mcur) { + /* check is memory is contiguous */ + if (!gst_memory_is_span (mprv, mcur, &offs)) + return FALSE; + + if (!have_offset) { + if (offset) + *offset = offs; + if (parent) + *parent = mprv->parent; + + have_offset = TRUE; + } + } + } + } + return have_offset; +} + +static GstMemory * +_gst_buffer_arr_span (GstMemory ** mem[], gsize len[], guint n, gsize offset, + gsize size) +{ + GstMemory *span, *parent; + gsize poffset; + + if (_gst_buffer_arr_is_span_fast (mem, len, n, &poffset, &parent)) { + span = gst_memory_sub (parent, offset + poffset, size); + } else { + gsize count, left; + guint8 *dest, *ptr; + + span = gst_memory_new_alloc (size, 0); + dest = gst_memory_map (span, NULL, NULL, GST_MAP_WRITE); + + ptr = dest; + left = size; + + for (count = 0; count < n; count++) { + gsize i, tocopy, clen, ssize; + guint8 *src; + GstMemory **cmem; + + cmem = mem[count]; + clen = len[count]; + + for (i = 0; i < clen && left > 0; i++) { + src = gst_memory_map (cmem[i], &ssize, NULL, GST_MAP_READ); + tocopy = MIN (ssize, left); + if (tocopy > offset) { + memcpy (ptr, src + offset, tocopy - offset); + left -= tocopy; + ptr += tocopy; + offset = 0; + } else { + offset -= tocopy; + } + gst_memory_unmap (cmem[i], src, ssize); + } + } + gst_memory_unmap (span, dest, size); + } + return span; +} + /** * gst_buffer_is_span_fast: * @buf1: the first #GstBuffer. @@ -994,20 +1118,20 @@ gst_buffer_create_sub (GstBuffer * buffer, gsize offset, gsize size) gboolean gst_buffer_is_span_fast (GstBuffer * buf1, GstBuffer * buf2) { - GstMemory **arr1, **arr2; - gsize len1, len2; + GstMemory **mem[2]; + gsize len[2]; g_return_val_if_fail (GST_IS_BUFFER (buf1), FALSE); g_return_val_if_fail (GST_IS_BUFFER (buf2), FALSE); g_return_val_if_fail (buf1->mini_object.refcount > 0, FALSE); g_return_val_if_fail (buf2->mini_object.refcount > 0, FALSE); - arr1 = GST_BUFFER_MEM_ARRAY (buf1); - len1 = GST_BUFFER_MEM_LEN (buf1); - arr2 = GST_BUFFER_MEM_ARRAY (buf2); - len2 = GST_BUFFER_MEM_LEN (buf2); + mem[0] = GST_BUFFER_MEM_ARRAY (buf1); + len[0] = GST_BUFFER_MEM_LEN (buf1); + mem[1] = GST_BUFFER_MEM_ARRAY (buf2); + len[1] = GST_BUFFER_MEM_LEN (buf2); - return gst_memory_is_span (arr1, len1, arr2, len2, NULL, NULL); + return _gst_buffer_arr_is_span_fast (mem, len, 2, NULL, NULL); } /** @@ -1016,7 +1140,7 @@ gst_buffer_is_span_fast (GstBuffer * buf1, GstBuffer * buf2) * @offset: the offset in the first buffer from where the new * buffer should start. * @buf2: the second source #GstBuffer to merge. - * @len: the total length of the new buffer. + * @size: the total size of the new buffer. * * Creates a new buffer that consists of part of buf1 and buf2. * Logically, buf1 and buf2 are concatenated into a single larger @@ -1034,30 +1158,34 @@ gst_buffer_is_span_fast (GstBuffer * buf1, GstBuffer * buf2) * buffers, or NULL if the arguments are invalid. */ GstBuffer * -gst_buffer_span (GstBuffer * buf1, gsize offset, GstBuffer * buf2, gsize len) +gst_buffer_span (GstBuffer * buf1, gsize offset, GstBuffer * buf2, gsize size) { GstBuffer *newbuf; - GstMemory **arr1, **arr2; - gsize len1, len2; - GstMemory *mem; + GstMemory *span; + GstMemory **mem[2]; + gsize len[2], len1, len2; g_return_val_if_fail (GST_IS_BUFFER (buf1), NULL); g_return_val_if_fail (GST_IS_BUFFER (buf2), NULL); g_return_val_if_fail (buf1->mini_object.refcount > 0, NULL); g_return_val_if_fail (buf2->mini_object.refcount > 0, NULL); - g_return_val_if_fail (len > 0, NULL); - g_return_val_if_fail (len <= gst_buffer_get_size (buf1) + - gst_buffer_get_size (buf2) - offset, NULL); + len1 = gst_buffer_get_size (buf1); + len2 = gst_buffer_get_size (buf2); + g_return_val_if_fail (len1 + len2 > offset, NULL); + if (size == -1) + size = len1 + len2 - offset; + else + g_return_val_if_fail (size <= len1 + len2 - offset, NULL); + + mem[0] = GST_BUFFER_MEM_ARRAY (buf1); + len[0] = GST_BUFFER_MEM_LEN (buf1); + mem[1] = GST_BUFFER_MEM_ARRAY (buf2); + len[1] = GST_BUFFER_MEM_LEN (buf2); + + span = _gst_buffer_arr_span (mem, len, 2, offset, size); newbuf = gst_buffer_new (); - - arr1 = GST_BUFFER_MEM_ARRAY (buf1); - len1 = GST_BUFFER_MEM_LEN (buf1); - arr2 = GST_BUFFER_MEM_ARRAY (buf2); - len2 = GST_BUFFER_MEM_LEN (buf2); - - mem = gst_memory_span (arr1, len1, offset, arr2, len2, len); - _memory_add (newbuf, mem); + _memory_add (newbuf, span); #if 0 /* if the offset is 0, the new buffer has the same timestamp as buf1 */ diff --git a/gst/gstmemory.c b/gst/gstmemory.c index 5412f224f4..38df7ed8c7 100644 --- a/gst/gstmemory.c +++ b/gst/gstmemory.c @@ -213,6 +213,9 @@ _default_mem_sub (GstMemoryDefault * mem, gsize offset, gsize size) if ((parent = mem->mem.parent) == NULL) parent = (GstMemory *) mem; + if (size == -1) + size = mem->size - offset; + sub = _default_mem_new (parent->flags, parent, mem->data, NULL, mem->maxsize, mem->offset + offset, size); @@ -478,101 +481,22 @@ gst_memory_sub (GstMemory * mem, gsize offset, gsize size) } gboolean -gst_memory_is_span (GstMemory ** mem1, gsize len1, GstMemory ** mem2, - gsize len2, GstMemory ** parent, gsize * offset) +gst_memory_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset) { - GstMemory *m1, *m2, **arr; - gsize len, i; - guint count; - gboolean have_offset = FALSE; - g_return_val_if_fail (mem1 != NULL, FALSE); g_return_val_if_fail (mem2 != NULL, FALSE); - arr = mem1; - len = len1; - m1 = m2 = NULL; + /* need to have the same implementation */ + if (mem1->impl != mem2->impl) + return FALSE; - for (count = 0; count < 2; count++) { - gsize offs; + /* need to have the same parent */ + if (mem1->parent == NULL || mem1->parent != mem2->parent) + return FALSE; - for (i = 0; i < len; i++) { - if (m2) - m1 = m2; - m2 = arr[i]; - - if (m1 && m2) { - /* need to have the same implementation */ - if (m1->impl != m2->impl) - return FALSE; - - /* need to have the same parent */ - if (m1->parent == NULL || m1->parent != m2->parent) - return FALSE; - - /* and memory is contiguous */ - if (!m1->impl->info.is_span (m1, m2, &offs)) - return FALSE; - - if (!have_offset) { - if (offset) - *offset = offs; - if (parent) - *parent = m1->parent; - - have_offset = TRUE; - } - } - } - arr = mem2; - len = len2; - } - if (!have_offset) + /* and memory is contiguous */ + if (!mem1->impl->info.is_span (mem1, mem2, offset)) return FALSE; return TRUE; } - -GstMemory * -gst_memory_span (GstMemory ** mem1, gsize len1, gsize offset, GstMemory ** mem2, - gsize len2, gsize size) -{ - GstMemory *span, **mem, *parent; - guint8 *data, *dest; - gsize count, ssize, tocopy, len, poffset, i; - - g_return_val_if_fail (mem1 != NULL, NULL); - g_return_val_if_fail (mem2 != NULL, NULL); - - if (gst_memory_is_span (mem1, len1, mem2, len2, &parent, &poffset)) { - span = gst_memory_sub (parent, offset + poffset, size); - } else { - GstMemoryDefault *tspan; - - tspan = _default_mem_new_block (size, 0, 0, size); - dest = tspan->data; - - mem = mem1; - len = len1; - - for (count = 0; count < 2; count++) { - for (i = 0; i < len && size > 0; i++) { - data = gst_memory_map (mem[i], &ssize, NULL, GST_MAP_READ); - tocopy = MIN (ssize, size); - if (tocopy > offset) { - memcpy (dest, data + offset, tocopy - offset); - size -= tocopy; - dest += tocopy; - offset = 0; - } else { - offset -= tocopy; - } - gst_memory_unmap (mem[i], data, ssize); - } - mem = mem2; - len = len2; - } - span = (GstMemory *) tspan; - } - return span; -} diff --git a/gst/gstmemory.h b/gst/gstmemory.h index 99b2ee91ac..517c591f23 100644 --- a/gst/gstmemory.h +++ b/gst/gstmemory.h @@ -135,9 +135,7 @@ GstMemory * gst_memory_copy (GstMemory *mem, gsize offset, gsize size); GstMemory * gst_memory_sub (GstMemory *mem, gsize offset, gsize size); /* memory arrays */ -gboolean gst_memory_is_span (GstMemory **mem1, gsize len1, - GstMemory **mem2, gsize len2, - GstMemory **parent, gsize *offset); +gboolean gst_memory_is_span (GstMemory *mem1, GstMemory *mem2, gsize *offset); GstMemory * gst_memory_span (GstMemory **mem1, gsize len1, gsize offset, GstMemory **mem2, gsize len2, gsize size); diff --git a/win32/common/libgstreamer.def b/win32/common/libgstreamer.def index 2d65d42bd6..207ca55b88 100644 --- a/win32/common/libgstreamer.def +++ b/win32/common/libgstreamer.def @@ -541,7 +541,6 @@ EXPORTS gst_memory_new_wrapped gst_memory_ref gst_memory_register - gst_memory_span gst_memory_sub gst_memory_trim gst_memory_unmap