From: Wim Taymans Date: Tue, 29 Mar 2011 17:17:55 +0000 (+0200) Subject: memory: further memory tweaking X-Git-Tag: RELEASE-0.11.0~487 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=030fcde837629718437558da3c33a5c47ad6a4cc;p=platform%2Fupstream%2Fgstreamer.git memory: further memory tweaking Allow for automatic merging of memory block in the _map function and automatic freeing of the temporary memory. Remove some unneeded functions. Add possibility to force writable spanned memory. --- diff --git a/gst/gstbuffer.c b/gst/gstbuffer.c index 8faadaa..b0facd2 100644 --- a/gst/gstbuffer.c +++ b/gst/gstbuffer.c @@ -132,7 +132,7 @@ GType _gst_buffer_type = 0; static GstMemory *_gst_buffer_arr_span (GstMemory ** mem[], gsize len[], - guint n, gsize offset, gsize size); + guint n, gsize offset, gsize size, gboolean writable); typedef struct _GstMetaItem GstMetaItem; @@ -160,26 +160,36 @@ typedef struct GstMetaItem *item; } GstBufferImpl; -static void -_span_memory (GstBuffer * buffer, gsize offset, gsize size) +static GstMemory * +_span_memory (GstBuffer * buffer, gsize offset, gsize size, gboolean writable) { GstMemory *span, **mem[1]; - gsize len[1], i; + gsize len[1]; /* not enough room, span buffers */ mem[0] = GST_BUFFER_MEM_ARRAY (buffer); len[0] = GST_BUFFER_MEM_LEN (buffer); - if (len[0] == 1) - return; - span = _gst_buffer_arr_span (mem, len, 1, offset, size); + if (size == -1) + size = gst_buffer_get_size (buffer); + + span = _gst_buffer_arr_span (mem, len, 1, offset, size, writable); + + return span; +} + +static void +_replace_memory (GstBuffer * buffer, GstMemory * mem) +{ + gsize len, i; /* unref old buffers */ - for (i = 0; i < len[0]; i++) - gst_memory_unref (mem[0][i]); + len = GST_BUFFER_MEM_LEN (buffer); + for (i = 0; i < len; i++) + gst_memory_unref (GST_BUFFER_MEM_PTR (buffer, i)); /* replace with single spanned buffer */ - GST_BUFFER_MEM_PTR (buffer, 0) = span; + GST_BUFFER_MEM_PTR (buffer, 0) = mem; GST_BUFFER_MEM_LEN (buffer) = 1; } @@ -189,12 +199,12 @@ _memory_add (GstBuffer * buffer, GstMemory * mem) guint len = GST_BUFFER_MEM_LEN (buffer); 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); + _replace_memory (buffer, _span_memory (buffer, 0, -1, FALSE)); /* we now have 1 single spanned buffer */ len = 1; } + /* and append the new buffer */ GST_BUFFER_MEM_PTR (buffer, len) = mem; GST_BUFFER_MEM_LEN (buffer) = len + 1; } @@ -328,7 +338,7 @@ gst_buffer_copy_into (GstBuffer * dest, GstBuffer * src, } } if (flags & GST_BUFFER_COPY_MERGE) { - _span_memory (dest, 0, size); + _replace_memory (dest, _span_memory (dest, 0, size, FALSE)); } } @@ -598,16 +608,30 @@ gst_buffer_take_memory (GstBuffer * buffer, GstMemory * mem) * Returns: a #GstMemory at @idx. */ GstMemory * -gst_buffer_peek_memory (GstBuffer * buffer, guint idx) +gst_buffer_peek_memory (GstBuffer * buffer, guint idx, GstMapFlags flags) { 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 = GST_BUFFER_MEM_PTR (buffer, idx); return mem; + + /* ERRORS */ +not_writable: + { + g_return_val_if_fail (gst_buffer_is_writable (buffer), NULL); + return NULL; + } } /** @@ -759,38 +783,66 @@ gst_buffer_map (GstBuffer * buffer, gsize * size, gsize * maxsize, { guint len; gpointer data; + GstMemory *mem; + gboolean write, writable; g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL); - len = GST_BUFFER_MEM_LEN (buffer); + write = (flags & GST_MAP_WRITE) != 0; + writable = gst_buffer_is_writable (buffer); - if (G_UNLIKELY ((flags & GST_MAP_WRITE) && !gst_buffer_is_writable (buffer))) + /* check if we can write when asked for write access */ + if (G_UNLIKELY (write && !writable)) goto not_writable; - if (G_LIKELY (len == 1)) { - GstMemory *mem; - - mem = GST_BUFFER_MEM_PTR (buffer, 0); + len = GST_BUFFER_MEM_LEN (buffer); - if (flags & GST_MAP_WRITE) { - if (G_UNLIKELY (!GST_MEMORY_IS_WRITABLE (mem))) { - GstMemory *copy; + if (G_UNLIKELY (len == 0)) { + /* no memory, return immediately */ + if (size) + *size = 0; + if (maxsize) + *maxsize = 0; + return NULL; + } - /* replace with a writable copy */ - copy = gst_memory_copy (mem, 0, gst_memory_get_sizes (mem, NULL)); - GST_BUFFER_MEM_PTR (buffer, 0) = copy; - gst_memory_unref (mem); - mem = copy; - } + 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; } + } - data = gst_memory_map (mem, size, maxsize, flags); - } else { - /* FIXME, implement me */ - data = NULL; - if (size) - *size = 0; + 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; + gst_memory_unref (mem); + mem = copy; } + + data = gst_memory_map (mem, size, maxsize, flags); + return data; /* ERROR */ @@ -827,8 +879,11 @@ gst_buffer_unmap (GstBuffer * buffer, gpointer data, gsize size) result = gst_memory_unmap (mem, data, size); } else { - /* FIXME, implement me */ - result = FALSE; + /* 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; } return result; } @@ -1064,12 +1119,13 @@ _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) + gsize size, gboolean writable) { GstMemory *span, *parent; gsize poffset; - if (_gst_buffer_arr_is_span_fast (mem, len, n, &poffset, &parent)) { + if (!writable + && _gst_buffer_arr_is_span_fast (mem, len, n, &poffset, &parent)) { span = gst_memory_sub (parent, offset + poffset, size); } else { gsize count, left; @@ -1188,7 +1244,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); + span = _gst_buffer_arr_span (mem, len, 2, offset, size, FALSE); newbuf = gst_buffer_new (); _memory_add (newbuf, span); diff --git a/gst/gstbuffer.h b/gst/gstbuffer.h index 591ab49..b4cc88e 100644 --- a/gst/gstbuffer.h +++ b/gst/gstbuffer.h @@ -284,7 +284,7 @@ GstBuffer * gst_buffer_new_and_alloc (guint size); /* memory blocks */ guint gst_buffer_n_memory (GstBuffer *buffer); void gst_buffer_take_memory (GstBuffer *buffer, GstMemory *mem); -GstMemory * gst_buffer_peek_memory (GstBuffer *buffer, guint idx); +GstMemory * gst_buffer_peek_memory (GstBuffer *buffer, guint idx, GstMapFlags flags); void gst_buffer_remove_memory_range (GstBuffer *buffer, guint idx, guint length); /** diff --git a/gst/gstmemory.c b/gst/gstmemory.c index 38df7ed..75b94ab 100644 --- a/gst/gstmemory.c +++ b/gst/gstmemory.c @@ -188,21 +188,14 @@ _default_mem_copy (GstMemoryDefault * mem, gsize offset, gsize size) { GstMemoryDefault *copy; + if (size == -1) + size = mem->size > offset ? mem->size - offset : 0; copy = _default_mem_new_block (mem->maxsize, 0, mem->offset + offset, size); memcpy (copy->data, mem->data, mem->maxsize); return copy; } -static void -_default_mem_extract (GstMemoryDefault * mem, gsize offset, gpointer dest, - gsize size) -{ - g_return_if_fail (size + mem->offset + offset <= mem->maxsize); - - memcpy (dest, mem->data + mem->offset + offset, size); -} - static GstMemoryDefault * _default_mem_sub (GstMemoryDefault * mem, gsize offset, gsize size) { @@ -233,17 +226,6 @@ _default_mem_is_span (GstMemoryDefault * mem1, GstMemoryDefault * mem2, return mem1->data + mem1->offset + mem1->size == mem2->data + mem2->offset; } -static void -_fallback_extract (GstMemory * mem, gsize offset, gpointer dest, gsize size) -{ - guint8 *data; - gsize msize; - - data = gst_memory_map (mem, &msize, NULL, GST_MAP_READ); - memcpy (dest, data + offset, size); - gst_memory_unmap (mem, data, msize); -} - static GstMemory * _fallback_copy (GstMemory * mem, gsize offset, gsize size) { @@ -252,6 +234,8 @@ _fallback_copy (GstMemory * mem, gsize offset, gsize size) gsize msize; data = gst_memory_map (mem, &msize, NULL, GST_MAP_READ); + if (size == -1) + size = msize > offset ? msize - offset : 0; copy = _default_mem_new_block (size, 0, 0, size); memcpy (copy->data, data + offset, size); gst_memory_unmap (mem, data, msize); @@ -289,7 +273,6 @@ _gst_memory_init (void) (GstMemoryUnmapFunction) _default_mem_unmap, (GstMemoryFreeFunction) _default_mem_free, (GstMemoryCopyFunction) _default_mem_copy, - (GstMemoryExtractFunction) _default_mem_extract, (GstMemorySubFunction) _default_mem_sub, (GstMemoryIsSpanFunction) _default_mem_is_span }; @@ -301,7 +284,6 @@ _gst_memory_init (void) (GstMemoryFreeFunction) _default_mem_free, NULL, NULL, - NULL, NULL }; @@ -336,7 +318,6 @@ gst_memory_register (const gchar * name, const GstMemoryInfo * info) impl->name = g_quark_from_string (name); impl->info = *info; INSTALL_FALLBACK (copy); - INSTALL_FALLBACK (extract); INSTALL_FALLBACK (sub); INSTALL_FALLBACK (is_span); @@ -456,15 +437,6 @@ gst_memory_copy (GstMemory * mem, gsize offset, gsize size) } void -gst_memory_extract (GstMemory * mem, gsize offset, gpointer dest, gsize size) -{ - g_return_if_fail (mem != NULL); - g_return_if_fail (dest != NULL); - - return mem->impl->info.extract (mem, offset, dest, size); -} - -void gst_memory_trim (GstMemory * mem, gsize offset, gsize size) { g_return_if_fail (mem != NULL); diff --git a/gst/gstmemory.h b/gst/gstmemory.h index 517c591..80d537d 100644 --- a/gst/gstmemory.h +++ b/gst/gstmemory.h @@ -81,8 +81,6 @@ typedef gboolean (*GstMemoryUnmapFunction) (GstMemory *mem, gpointer data, gsiz typedef void (*GstMemoryFreeFunction) (GstMemory *mem); typedef GstMemory * (*GstMemoryCopyFunction) (GstMemory *mem, gsize offset, gsize size); -typedef void (*GstMemoryExtractFunction) (GstMemory *mem, gsize offset, - gpointer dest, gsize size); typedef void (*GstMemoryTrimFunction) (GstMemory *mem, gsize offset, gsize size); typedef GstMemory * (*GstMemorySubFunction) (GstMemory *mem, gsize offset, gsize size); typedef gboolean (*GstMemoryIsSpanFunction) (GstMemory *mem1, GstMemory *mem2, @@ -102,7 +100,6 @@ struct _GstMemoryInfo { GstMemoryFreeFunction free; GstMemoryCopyFunction copy; - GstMemoryExtractFunction extract; GstMemorySubFunction sub; GstMemoryIsSpanFunction is_span; }; @@ -128,13 +125,12 @@ void gst_memory_trim (GstMemory *mem, gsize offset, gsize size); gpointer gst_memory_map (GstMemory *mem, gsize *size, gsize *maxsize, GstMapFlags flags); gboolean gst_memory_unmap (GstMemory *mem, gpointer data, gsize size); -void gst_memory_extract (GstMemory *mem, gsize offset, gpointer dest, - gsize size); + /* copy and subregions */ GstMemory * gst_memory_copy (GstMemory *mem, gsize offset, gsize size); GstMemory * gst_memory_sub (GstMemory *mem, gsize offset, gsize size); -/* memory arrays */ +/* span memory */ 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 207ca55..4ab8c7f 100644 --- a/win32/common/libgstreamer.def +++ b/win32/common/libgstreamer.def @@ -531,7 +531,6 @@ EXPORTS gst_marshal_VOID__POINTER_OBJECT gst_marshal_VOID__UINT_BOXED gst_memory_copy - gst_memory_extract gst_memory_flags_get_type gst_memory_get_sizes gst_memory_is_span