diff options
Diffstat (limited to 'gst/gstbuffer.c')
-rw-r--r-- | gst/gstbuffer.c | 190 |
1 files changed, 144 insertions, 46 deletions
diff --git a/gst/gstbuffer.c b/gst/gstbuffer.c index 74682dc..8212ec2 100644 --- a/gst/gstbuffer.c +++ b/gst/gstbuffer.c @@ -16,8 +16,8 @@ * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. */ /** @@ -201,7 +201,7 @@ _is_span (GstMemory ** mem, gsize len, gsize * poffset, GstMemory ** parent) static GstMemory * _get_merged_memory (GstBuffer * buffer, guint idx, guint length) { - GstMemory **mem, *result; + GstMemory **mem, *result = NULL; GST_CAT_LOG (GST_CAT_BUFFER, "buffer %p, idx %u, length %u", buffer, idx, length); @@ -219,11 +219,11 @@ _get_merged_memory (GstBuffer * buffer, guint idx, guint length) size = gst_buffer_get_sizes_range (buffer, idx, length, NULL, NULL); if (G_UNLIKELY (_is_span (mem + idx, length, &poffset, &parent))) { - if (GST_MEMORY_IS_NO_SHARE (parent)) { + if (!GST_MEMORY_IS_NO_SHARE (parent)) + result = gst_memory_share (parent, poffset, size); + if (!result) { GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "copy for merge %p", parent); result = gst_memory_copy (parent, poffset, size); - } else { - result = gst_memory_share (parent, poffset, size); } } else { gsize i, tocopy, left; @@ -331,6 +331,25 @@ _priv_gst_buffer_initialize (void) } /** + * gst_buffer_get_max_memory: + * + * Get the maximum amount of memory blocks that a buffer can hold. This is a + * compile time constant that can be queried with the function. + * + * When more memory blocks are added, existing memory blocks will be merged + * together to make room for the new block. + * + * Returns: the maximum amount of memory blocks that a buffer can hold. + * + * Since: 1.2.0 + */ +guint +gst_buffer_get_max_memory (void) +{ + return GST_BUFFER_MEM_MAX; +} + +/** * gst_buffer_copy_into: * @dest: a destination #GstBuffer * @src: a source #GstBuffer @@ -344,8 +363,10 @@ _priv_gst_buffer_initialize (void) * the memory from @src will be appended to @dest. * * @flags indicate which fields will be copied. + * + * Returns: %TRUE if the copying succeeded, %FALSE otherwise. */ -void +gboolean gst_buffer_copy_into (GstBuffer * dest, GstBuffer * src, GstBufferCopyFlags flags, gsize offset, gsize size) { @@ -353,24 +374,24 @@ gst_buffer_copy_into (GstBuffer * dest, GstBuffer * src, gsize bufsize; gboolean region = FALSE; - g_return_if_fail (dest != NULL); - g_return_if_fail (src != NULL); + g_return_val_if_fail (dest != NULL, FALSE); + g_return_val_if_fail (src != NULL, FALSE); /* nothing to copy if the buffers are the same */ if (G_UNLIKELY (dest == src)) - return; + return TRUE; - g_return_if_fail (gst_buffer_is_writable (dest)); + g_return_val_if_fail (gst_buffer_is_writable (dest), FALSE); bufsize = gst_buffer_get_size (src); - g_return_if_fail (bufsize >= offset); + g_return_val_if_fail (bufsize >= offset, FALSE); if (offset > 0) region = TRUE; if (size == -1) size = bufsize - offset; if (size < bufsize) region = TRUE; - g_return_if_fail (bufsize >= offset + size); + g_return_val_if_fail (bufsize >= offset + size, FALSE); GST_CAT_LOG (GST_CAT_BUFFER, "copy %p to %p, offset %" G_GSIZE_FORMAT "-%" G_GSIZE_FORMAT "/%" G_GSIZE_FORMAT, src, dest, offset, size, @@ -400,43 +421,66 @@ gst_buffer_copy_into (GstBuffer * dest, GstBuffer * src, } if (flags & GST_BUFFER_COPY_MEMORY) { - GstMemory *mem; - gsize skip, left, len, i, bsize; + gsize skip, left, len, dest_len, i, bsize; + gboolean deep; + + deep = flags & GST_BUFFER_COPY_DEEP; len = GST_BUFFER_MEM_LEN (src); + dest_len = GST_BUFFER_MEM_LEN (dest); left = size; skip = offset; /* copy and make regions of the memory */ for (i = 0; i < len && left > 0; i++) { - mem = GST_BUFFER_MEM_PTR (src, i); + GstMemory *mem = GST_BUFFER_MEM_PTR (src, i); + bsize = gst_memory_get_sizes (mem, NULL, NULL); if (bsize <= skip) { /* don't copy buffer */ skip -= bsize; } else { + GstMemory *newmem = NULL; gsize tocopy; tocopy = MIN (bsize - skip, left); - if (GST_MEMORY_IS_NO_SHARE (mem)) { - /* no share, always copy then */ - mem = gst_memory_copy (mem, skip, tocopy); - skip = 0; - } else if (tocopy < bsize) { + + if (tocopy < bsize && !deep && !GST_MEMORY_IS_NO_SHARE (mem)) { /* we need to clip something */ - mem = gst_memory_share (mem, skip, tocopy); + newmem = gst_memory_share (mem, skip, tocopy); + if (newmem) + skip = 0; + } + + if (deep || GST_MEMORY_IS_NO_SHARE (mem) || (!newmem && tocopy < bsize)) { + /* deep copy or we're not allowed to share this memory + * between buffers, always copy then */ + newmem = gst_memory_copy (mem, skip, tocopy); skip = 0; - } else { - mem = gst_memory_ref (mem); + } else if (!newmem) { + newmem = gst_memory_ref (mem); + } + + if (!newmem) { + gst_buffer_remove_memory_range (dest, dest_len, -1); + return FALSE; } - _memory_add (dest, -1, mem, TRUE); + + _memory_add (dest, -1, newmem, TRUE); left -= tocopy; } } if (flags & GST_BUFFER_COPY_MERGE) { + GstMemory *mem; + len = GST_BUFFER_MEM_LEN (dest); - _replace_memory (dest, len, 0, len, _get_merged_memory (dest, 0, len)); + mem = _get_merged_memory (dest, 0, len); + if (!mem) { + gst_buffer_remove_memory_range (dest, dest_len, -1); + return FALSE; + } + _replace_memory (dest, len, 0, len, mem); } } @@ -457,6 +501,8 @@ gst_buffer_copy_into (GstBuffer * dest, GstBuffer * src, } } } + + return TRUE; } static GstBuffer * @@ -470,7 +516,8 @@ _gst_buffer_copy (GstBuffer * buffer) copy = gst_buffer_new (); /* we simply copy everything from our parent */ - gst_buffer_copy_into (copy, buffer, GST_BUFFER_COPY_ALL, 0, -1); + if (!gst_buffer_copy_into (copy, buffer, GST_BUFFER_COPY_ALL, 0, -1)) + gst_buffer_replace (©, NULL); return copy; } @@ -714,12 +761,14 @@ gst_buffer_new_wrapped_full (GstMemoryFlags flags, gpointer data, gsize maxsize, gsize offset, gsize size, gpointer user_data, GDestroyNotify notify) { + GstMemory *mem; GstBuffer *newbuf; newbuf = gst_buffer_new (); - gst_buffer_append_memory (newbuf, - gst_memory_new_wrapped (flags, data, maxsize, offset, size, - user_data, notify)); + mem = + gst_memory_new_wrapped (flags, data, maxsize, offset, size, user_data, + notify); + _memory_add (newbuf, -1, mem, TRUE); return newbuf; } @@ -746,7 +795,8 @@ gst_buffer_new_wrapped (gpointer data, gsize size) * gst_buffer_n_memory: * @buffer: a #GstBuffer. * - * Get the amount of memory blocks that this buffer has. + * Get the amount of memory blocks that this buffer has. This amount is never + * larger than what gst_buffer_get_max_memory() returns. * * Returns: (transfer full): the amount of memory block in this buffer. */ @@ -765,6 +815,9 @@ gst_buffer_n_memory (GstBuffer * buffer) * * Prepend the memory block @mem to @buffer. This function takes * ownership of @mem and thus doesn't increase its refcount. + * + * This function is identical to gst_buffer_insert_memory() with an index of 0. + * See gst_buffer_insert_memory() for more details. */ void gst_buffer_prepend_memory (GstBuffer * buffer, GstMemory * mem) @@ -779,6 +832,9 @@ gst_buffer_prepend_memory (GstBuffer * buffer, GstMemory * mem) * * Append the memory block @mem to @buffer. This function takes * ownership of @mem and thus doesn't increase its refcount. + * + * This function is identical to gst_buffer_insert_memory() with an index of -1. + * See gst_buffer_insert_memory() for more details. */ void gst_buffer_append_memory (GstBuffer * buffer, GstMemory * mem) @@ -794,6 +850,10 @@ gst_buffer_append_memory (GstBuffer * buffer, GstMemory * mem) * * Insert the memory block @mem to @buffer at @idx. This function takes ownership * of @mem and thus doesn't increase its refcount. + * + * Only gst_buffer_get_max_memory() can be added to a buffer. If more memory is + * added, existing memory blocks will automatically be merged to make room for + * the new memory. */ void gst_buffer_insert_memory (GstBuffer * buffer, gint idx, GstMemory * mem) @@ -1255,19 +1315,22 @@ gst_buffer_set_size (GstBuffer * buffer, gssize size) * * Set the total size of the @length memory blocks starting at @idx in * @buffer + * + * Returns: %TRUE if resizing succeeded, %FALSE otherwise. */ -void +gboolean gst_buffer_resize_range (GstBuffer * buffer, guint idx, gint length, gssize offset, gssize size) { guint i, len, end; gsize bsize, bufsize, bufoffs, bufmax; - g_return_if_fail (gst_buffer_is_writable (buffer)); - g_return_if_fail (size >= -1); + g_return_val_if_fail (gst_buffer_is_writable (buffer), FALSE); + g_return_val_if_fail (size >= -1, FALSE); + len = GST_BUFFER_MEM_LEN (buffer); - g_return_if_fail ((len == 0 && idx == 0 && length == -1) || - (length == -1 && idx < len) || (length + idx <= len)); + g_return_val_if_fail ((len == 0 && idx == 0 && length == -1) || + (length == -1 && idx < len) || (length + idx <= len), FALSE); if (length == -1) length = len - idx; @@ -1280,17 +1343,17 @@ gst_buffer_resize_range (GstBuffer * buffer, guint idx, gint length, /* we can't go back further than the current offset or past the end of the * buffer */ - g_return_if_fail ((offset < 0 && bufoffs >= -offset) || (offset >= 0 - && bufoffs + offset <= bufmax)); + g_return_val_if_fail ((offset < 0 && bufoffs >= -offset) || (offset >= 0 + && bufoffs + offset <= bufmax), FALSE); if (size == -1) { - g_return_if_fail (bufsize >= offset); + g_return_val_if_fail (bufsize >= offset, FALSE); size = bufsize - offset; } - g_return_if_fail (bufmax >= bufoffs + offset + size); + g_return_val_if_fail (bufmax >= bufoffs + offset + size, FALSE); /* no change */ if (offset == 0 && size == bufsize) - return; + return TRUE; end = idx + length; /* copy and trim */ @@ -1319,13 +1382,17 @@ gst_buffer_resize_range (GstBuffer * buffer, guint idx, gint length, if (gst_memory_is_writable (mem)) { gst_memory_resize (mem, offset, left); } else { - GstMemory *newmem; + GstMemory *newmem = NULL; - if (GST_MEMORY_IS_NO_SHARE (mem)) - newmem = gst_memory_copy (mem, offset, left); - else + if (!GST_MEMORY_IS_NO_SHARE (mem)) newmem = gst_memory_share (mem, offset, left); + if (!newmem) + newmem = gst_memory_copy (mem, offset, left); + + if (newmem == NULL) + return FALSE; + gst_memory_lock (newmem, GST_LOCK_FLAG_EXCLUSIVE); GST_BUFFER_MEM_PTR (buffer, i) = newmem; gst_memory_unlock (mem, GST_LOCK_FLAG_EXCLUSIVE); @@ -1336,6 +1403,8 @@ gst_buffer_resize_range (GstBuffer * buffer, guint idx, gint length, offset = noffs; size -= left; } + + return TRUE; } /** @@ -1724,7 +1793,8 @@ gst_buffer_copy_region (GstBuffer * buffer, GstBufferCopyFlags flags, GST_CAT_LOG (GST_CAT_BUFFER, "new region copy %p of %p %" G_GSIZE_FORMAT "-%" G_GSIZE_FORMAT, copy, buffer, offset, size); - gst_buffer_copy_into (copy, buffer, flags, offset, size); + if (!gst_buffer_copy_into (copy, buffer, flags, offset, size)) + gst_buffer_replace (©, NULL); return copy; } @@ -2013,3 +2083,31 @@ gst_buffer_foreach_meta (GstBuffer * buffer, GstBufferForeachMetaFunc func, } return res; } + +/** + * gst_buffer_extract_dup: + * @buffer: a #GstBuffer + * @offset: the offset to extract + * @size: the size to extract + * @dest: (array length=dest_size) (element-type guint8) (out): A pointer where + * the destination array will be written. + * @dest_size: (out): A location where the size of @dest can be written + * + * Extracts a copy of at most @size bytes the data at @offset into a #GBytes. + * @dest must be freed using g_free() when done. + * + * Since: 3.2 + */ + +void +gst_buffer_extract_dup (GstBuffer * buffer, gsize offset, gsize size, + gpointer * dest, gsize * dest_size) +{ + gsize real_size; + + real_size = gst_buffer_get_size (buffer); + + *dest = g_malloc (MIN (real_size - offset, size)); + + *dest_size = gst_buffer_extract (buffer, offset, *dest, size); +} |