diff --git a/gst/gstbuffer.c b/gst/gstbuffer.c index 0b8692b2ee..e0192f2cbc 100644 --- a/gst/gstbuffer.c +++ b/gst/gstbuffer.c @@ -154,16 +154,6 @@ static size_t _gst_buffer_data_alignment = BUFFER_ALIGNMENT; #else #error "No buffer alignment configured" #endif - -static inline gboolean -aligned_malloc (gpointer * memptr, guint size) -{ - gint res; - - res = posix_memalign (memptr, _gst_buffer_data_alignment, size); - return (res == 0); -} - #endif /* HAVE_POSIX_MEMALIGN */ void @@ -179,58 +169,21 @@ _gst_buffer_initialize (void) } } -void -gst_buffer_copy_memory (GstBuffer * dest, GstBuffer * src, - gsize offset, gsize size, gboolean merge) -{ - GPtrArray *sarr = (GPtrArray *) src->memory; - GPtrArray *darr = (GPtrArray *) dest->memory; - guint i, len; - - len = sarr->len; - - for (i = 0; i < len; i++) { - GstMemory *mem = g_ptr_array_index (sarr, i); - g_ptr_array_add (darr, gst_memory_copy (mem)); - } -} - -void -gst_buffer_share_memory (GstBuffer * dest, GstBuffer * src) -{ - GPtrArray *sarr = (GPtrArray *) src->memory; - GPtrArray *darr = (GPtrArray *) dest->memory; - guint i, len; - - len = sarr->len; - - for (i = 0; i < len; i++) { - GstMemory *mem = g_ptr_array_index (sarr, i); - g_ptr_array_add (darr, gst_memory_ref (mem)); - } -} - - /** - * gst_buffer_copy_metadata: + * gst_buffer_copy_into: * @dest: a destination #GstBuffer * @src: a source #GstBuffer * @flags: flags indicating what metadata fields should be copied. + * @offset: offset to copy from + * @trim: bytes to trim from end * - * Copies the metadata from @src into @dest. The data, size and mallocdata - * fields are not copied. + * Copies the information from @src into @dest. * - * @flags indicate which fields will be copied. Use #GST_BUFFER_COPY_ALL to copy - * all the metadata fields. - * - * This function is typically called from a custom buffer copy function after - * creating @dest and setting the data, size, mallocdata. - * - * Since: 0.10.13 + * @flags indicate which fields will be copied. */ void -gst_buffer_copy_metadata (GstBuffer * dest, GstBuffer * src, - GstBufferCopyFlags flags) +gst_buffer_copy_into (GstBuffer * dest, GstBuffer * src, + GstBufferCopyFlags flags, gsize offset, gsize trim) { GstMetaItem *walk; @@ -260,16 +213,45 @@ gst_buffer_copy_metadata (GstBuffer * dest, GstBuffer * src, } if (flags & GST_BUFFER_COPY_TIMESTAMPS) { - GST_BUFFER_TIMESTAMP (dest) = GST_BUFFER_TIMESTAMP (src); - GST_BUFFER_DURATION (dest) = GST_BUFFER_DURATION (src); - GST_BUFFER_OFFSET (dest) = GST_BUFFER_OFFSET (src); - GST_BUFFER_OFFSET_END (dest) = GST_BUFFER_OFFSET_END (src); + if (offset == 0) { + GST_BUFFER_TIMESTAMP (dest) = GST_BUFFER_TIMESTAMP (src); + GST_BUFFER_OFFSET (dest) = GST_BUFFER_OFFSET (src); + if (trim == 0) { + GST_BUFFER_DURATION (dest) = GST_BUFFER_DURATION (src); + GST_BUFFER_OFFSET_END (dest) = GST_BUFFER_OFFSET_END (src); + } + } else { + GST_BUFFER_TIMESTAMP (dest) = GST_CLOCK_TIME_NONE; + GST_BUFFER_DURATION (dest) = GST_CLOCK_TIME_NONE; + GST_BUFFER_OFFSET (dest) = GST_BUFFER_OFFSET_NONE; + GST_BUFFER_OFFSET_END (dest) = GST_BUFFER_OFFSET_NONE; + } } if (flags & GST_BUFFER_COPY_CAPS) { gst_caps_replace (&GST_BUFFER_CAPS (dest), GST_BUFFER_CAPS (src)); } + if (flags & GST_BUFFER_COPY_MEMORY) { + GPtrArray *sarr = (GPtrArray *) src->memory; + GPtrArray *darr = (GPtrArray *) dest->memory; + guint i, len; + + len = sarr->len; + + if (flags & GST_BUFFER_COPY_MEMORY_SHARE) { + for (i = 0; i < len; i++) { + GstMemory *mem = g_ptr_array_index (sarr, i); + g_ptr_array_add (darr, gst_memory_ref (mem)); + } + } else { + for (i = 0; i < len; i++) { + GstMemory *mem = g_ptr_array_index (sarr, i); + g_ptr_array_add (darr, gst_memory_copy (mem)); + } + } + } + for (walk = src->priv; walk; walk = walk->next) { GstMeta *meta = &walk->meta; const GstMetaInfo *info = meta->info; @@ -291,8 +273,7 @@ _gst_buffer_copy (GstBuffer * buffer) copy = gst_buffer_new (); /* we simply copy everything from our parent */ - gst_buffer_copy_memory (copy, buffer, 0, 0, FALSE); - gst_buffer_copy_metadata (copy, buffer, GST_BUFFER_COPY_ALL); + gst_buffer_copy_into (copy, buffer, GST_BUFFER_COPY_ALL, 0, 0); return copy; } @@ -337,7 +318,7 @@ _gst_buffer_free (GstBuffer * buffer) g_slice_free (GstMetaItem, walk); } - /* free our data */ + /* free our data, unrefs the memory too */ g_ptr_array_free (buffer->memory, TRUE); g_slice_free1 (GST_MINI_OBJECT_SIZE (buffer), buffer); @@ -445,6 +426,8 @@ gst_buffer_try_new_and_alloc (guint size) GST_CAT_WARNING (GST_CAT_BUFFER, "failed to allocate %d bytes", size); return NULL; } + + newbuf = gst_buffer_new (); gst_buffer_take_memory (newbuf, mem); GST_CAT_LOG (GST_CAT_BUFFER, "new %p of size %d", newbuf, size); @@ -488,7 +471,7 @@ gst_buffer_remove_memory (GstBuffer * buffer, guint idx) } gsize -gst_buffer_get_memory_size (GstBuffer * buffer) +gst_buffer_get_size (GstBuffer * buffer) { GPtrArray *arr = (GPtrArray *) buffer->memory; guint i, size, len; @@ -507,13 +490,39 @@ gpointer gst_buffer_map (GstBuffer * buffer, gsize * size, gsize * maxsize, GstMapFlags flags) { - return NULL; + GPtrArray *arr = (GPtrArray *) buffer->memory; + guint len; + gpointer data; + + len = arr->len; + + if (G_LIKELY (len == 1)) { + GstMemory *mem = g_ptr_array_index (arr, 0); + + data = gst_memory_map (mem, size, maxsize, flags); + } else { + data = NULL; + } + return data; } gboolean gst_buffer_unmap (GstBuffer * buffer, gpointer data, gsize size) { - return FALSE; + GPtrArray *arr = (GPtrArray *) buffer->memory; + gboolean result; + guint len; + + len = arr->len; + + if (G_LIKELY (len == 1)) { + GstMemory *mem = g_ptr_array_index (arr, 0); + + result = gst_memory_unmap (mem, data, size); + } else { + result = FALSE; + } + return result; } /** @@ -614,15 +623,12 @@ gst_buffer_make_metadata_writable (GstBuffer * buf) ret = gst_buffer_new (); /* we simply copy everything from our parent */ - gst_buffer_share_memory (ret, buf); - gst_buffer_copy_metadata (ret, buf, GST_BUFFER_COPY_ALL); + gst_buffer_copy_into (ret, buf, GST_BUFFER_SHARE_ALL, 0, 0); gst_buffer_unref (buf); } return ret; } -#define GST_IS_SUBBUFFER(obj) (GST_BUFFER_CAST(obj)->parent != NULL) - /** * gst_buffer_create_sub: * @parent: a #GstBuffer. @@ -645,88 +651,25 @@ gst_buffer_make_metadata_writable (GstBuffer * buf) * invalid. */ GstBuffer * -gst_buffer_create_sub (GstBuffer * buffer, guint offset, guint size) +gst_buffer_create_sub (GstBuffer * buffer, gsize offset, gsize size) { GstBuffer *subbuffer; - GstBuffer *parent; - gboolean complete; - GstMetaItem *walk; + gsize bufsize; g_return_val_if_fail (buffer != NULL, NULL); g_return_val_if_fail (buffer->mini_object.refcount > 0, NULL); - g_return_val_if_fail (buffer->size >= offset + size, NULL); - /* find real parent */ - if (GST_IS_SUBBUFFER (buffer)) { - parent = buffer->parent; - } else { - parent = buffer; - } - gst_buffer_ref (parent); + bufsize = gst_buffer_get_size (buffer); + g_return_val_if_fail (bufsize >= offset + size, NULL); /* create the new buffer */ subbuffer = gst_buffer_new (); - subbuffer->parent = parent; - GST_BUFFER_FLAG_SET (subbuffer, GST_BUFFER_FLAG_READONLY); - GST_CAT_LOG (GST_CAT_BUFFER, "new subbuffer %p (parent %p)", subbuffer, - parent); + GST_CAT_LOG (GST_CAT_BUFFER, "new subbuffer %p of %p", subbuffer, buffer); - /* set the right values in the child */ - GST_BUFFER_DATA (subbuffer) = buffer->data + offset; - GST_BUFFER_SIZE (subbuffer) = size; + gst_buffer_copy_into (subbuffer, buffer, GST_BUFFER_SHARE_ALL, offset, + bufsize - (size + offset)); - if ((offset == 0) && (size == GST_BUFFER_SIZE (buffer))) { - /* copy all the flags except IN_CAPS */ - GST_BUFFER_FLAG_SET (subbuffer, GST_BUFFER_FLAGS (buffer)); - GST_BUFFER_FLAG_UNSET (subbuffer, GST_BUFFER_FLAG_IN_CAPS); - } else { - /* copy only PREROLL & GAP flags */ - GST_BUFFER_FLAG_SET (subbuffer, (GST_BUFFER_FLAGS (buffer) & - (GST_BUFFER_FLAG_PREROLL | GST_BUFFER_FLAG_GAP))); - } - - /* we can copy the timestamp and offset if the new buffer starts at - * offset 0 */ - if (offset == 0) { - GST_BUFFER_TIMESTAMP (subbuffer) = GST_BUFFER_TIMESTAMP (buffer); - GST_BUFFER_OFFSET (subbuffer) = GST_BUFFER_OFFSET (buffer); - complete = (buffer->size == size); - } else { - GST_BUFFER_TIMESTAMP (subbuffer) = GST_CLOCK_TIME_NONE; - GST_BUFFER_OFFSET (subbuffer) = GST_BUFFER_OFFSET_NONE; - complete = FALSE; - } - - if (complete) { - GstCaps *caps; - - /* if we copied the complete buffer we can copy the duration, - * offset_end and caps as well */ - GST_BUFFER_DURATION (subbuffer) = GST_BUFFER_DURATION (buffer); - GST_BUFFER_OFFSET_END (subbuffer) = GST_BUFFER_OFFSET_END (buffer); - if ((caps = GST_BUFFER_CAPS (buffer))) - gst_caps_ref (caps); - GST_BUFFER_CAPS (subbuffer) = caps; - } else { - GST_BUFFER_DURATION (subbuffer) = GST_CLOCK_TIME_NONE; - GST_BUFFER_OFFSET_END (subbuffer) = GST_BUFFER_OFFSET_NONE; - GST_BUFFER_CAPS (subbuffer) = NULL; - } - /* call subbuffer functions for metadata */ - for (walk = buffer->priv; walk; walk = walk->next) { - GstMeta *meta = &walk->meta; - const GstMetaInfo *info = meta->info; - GstMetaTransformSubbuffer subdata; - - subdata.data.type = GST_META_TRANSFORM_TRIM; - subdata.offset = offset; - subdata.size = size; - - if (info->transform_func) - info->transform_func (subbuffer, meta, buffer, - (GstMetaTransformData *) & subdata); - } return subbuffer; } @@ -736,7 +679,7 @@ gst_buffer_create_sub (GstBuffer * buffer, guint offset, guint size) * @buf2: the second #GstBuffer. * * Determines whether a gst_buffer_span() can be done without copying - * the contents, that is, whether the data areas are contiguous sub-buffers of + * the contents, that is, whether the data areas are contiguous sub-buffers of * the same buffer. * * MT safe. @@ -746,14 +689,17 @@ gst_buffer_create_sub (GstBuffer * buffer, guint offset, guint size) gboolean gst_buffer_is_span_fast (GstBuffer * buf1, GstBuffer * buf2) { + GPtrArray *arr1, *arr2; + g_return_val_if_fail (buf1 != NULL && buf2 != NULL, FALSE); g_return_val_if_fail (buf1->mini_object.refcount > 0, FALSE); g_return_val_if_fail (buf2->mini_object.refcount > 0, FALSE); - /* it's only fast if we have subbuffers of the same parent */ - return (GST_IS_SUBBUFFER (buf1) && - GST_IS_SUBBUFFER (buf2) && (buf1->parent == buf2->parent) - && ((buf1->data + buf1->size) == buf2->data)); + arr1 = (GPtrArray *) buf1->memory; + arr2 = (GPtrArray *) buf2->memory; + + return gst_memory_is_span ((GstMemory **) arr1->pdata, arr1->len, + (GstMemory **) arr2->pdata, arr2->len, NULL, NULL); } /** @@ -780,36 +726,27 @@ gst_buffer_is_span_fast (GstBuffer * buf1, GstBuffer * buf2) * buffers, or NULL if the arguments are invalid. */ GstBuffer * -gst_buffer_span (GstBuffer * buf1, guint32 offset, GstBuffer * buf2, - guint32 len) +gst_buffer_span (GstBuffer * buf1, gsize offset, GstBuffer * buf2, gsize len) { GstBuffer *newbuf; + GPtrArray *arr1, *arr2; + GstMemory *mem; g_return_val_if_fail (buf1 != NULL && buf2 != NULL, 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 <= buf1->size + buf2->size - offset, NULL); - /* if the two buffers have the same parent and are adjacent */ - if (gst_buffer_is_span_fast (buf1, buf2)) { - GstBuffer *parent = buf1->parent; + newbuf = gst_buffer_new (); - /* we simply create a subbuffer of the common parent */ - newbuf = gst_buffer_create_sub (parent, - buf1->data - parent->data + offset, len); - } else { - GST_CAT_DEBUG (GST_CAT_BUFFER, - "slow path taken while spanning buffers %p and %p", buf1, buf2); - /* otherwise we simply have to brute-force copy the buffers */ - newbuf = gst_buffer_new_and_alloc (len); + arr1 = (GPtrArray *) buf1->memory; + arr2 = (GPtrArray *) buf2->memory; - /* copy the first buffer's data across */ - memcpy (newbuf->data, buf1->data + offset, buf1->size - offset); - /* copy the second buffer's data across */ - memcpy (newbuf->data + (buf1->size - offset), buf2->data, - len - (buf1->size - offset)); - } + mem = gst_memory_span ((GstMemory **) arr1->pdata, arr1->len, offset, + (GstMemory **) arr2->pdata, arr2->len, len); + gst_buffer_take_memory (newbuf, mem); + +#if 0 /* if the offset is 0, the new buffer has the same timestamp as buf1 */ if (offset == 0) { GST_BUFFER_OFFSET (newbuf) = GST_BUFFER_OFFSET (buf1); @@ -831,6 +768,7 @@ gst_buffer_span (GstBuffer * buf1, guint32 offset, GstBuffer * buf2, } } } +#endif return newbuf; } diff --git a/gst/gstbuffer.h b/gst/gstbuffer.h index aa229e962b..420c8fb60d 100644 --- a/gst/gstbuffer.h +++ b/gst/gstbuffer.h @@ -302,7 +302,7 @@ void gst_buffer_take_memory (GstBuffer *buffer, GstMemory *mem); GstMemory * gst_buffer_peek_memory (GstBuffer *buffer, guint idx); void gst_buffer_remove_memory (GstBuffer *buffer, guint idx); -gsize gst_buffer_get_memory_size (GstBuffer *buffer); +gsize gst_buffer_get_size (GstBuffer *buffer); /* getting memory */ gpointer gst_buffer_map (GstBuffer *buffer, gsize *size, gsize *maxsize, @@ -406,27 +406,32 @@ gst_buffer_copy (const GstBuffer * buf) * Since: 0.10.13 */ typedef enum { - GST_BUFFER_COPY_FLAGS = (1 << 0), - GST_BUFFER_COPY_TIMESTAMPS = (1 << 1), - GST_BUFFER_COPY_CAPS = (1 << 2) + GST_BUFFER_COPY_FLAGS = (1 << 0), + GST_BUFFER_COPY_TIMESTAMPS = (1 << 1), + GST_BUFFER_COPY_CAPS = (1 << 2), + GST_BUFFER_COPY_MEMORY = (1 << 3), + GST_BUFFER_COPY_MEMORY_MERGE = (1 << 4), + GST_BUFFER_COPY_MEMORY_SHARE = (1 << 5), } GstBufferCopyFlags; +#define GST_BUFFER_COPY_METADATA (GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_CAPS) + /** * GST_BUFFER_COPY_ALL: * * Combination of all possible fields that can be copied with - * gst_buffer_copy_metadata(). + * gst_buffer_copy_into(). * * Since: 0.10.13 */ -#define GST_BUFFER_COPY_ALL (GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_CAPS) +#define GST_BUFFER_COPY_ALL (GST_BUFFER_COPY_METADATA | GST_BUFFER_COPY_MEMORY) + +#define GST_BUFFER_SHARE_ALL (GST_BUFFER_COPY_METADATA | GST_BUFFER_COPY_MEMORY | GST_BUFFER_COPY_MEMORY_SHARE) /* copies memory or metadata into newly allocated buffer */ -void gst_buffer_copy_memory (GstBuffer *dest, GstBuffer *src, - gsize offset, gsize size, gboolean merge); -void gst_buffer_share_memory (GstBuffer *dest, GstBuffer *src); -void gst_buffer_copy_metadata (GstBuffer *dest, GstBuffer *src, - GstBufferCopyFlags flags); +void gst_buffer_copy_into (GstBuffer *dest, GstBuffer *src, + GstBufferCopyFlags flags, + gsize offset, gsize trim); /** * gst_buffer_is_writable: @@ -481,11 +486,11 @@ GstCaps* gst_buffer_get_caps (GstBuffer *buffer); void gst_buffer_set_caps (GstBuffer *buffer, GstCaps *caps); /* creating a subbuffer */ -GstBuffer* gst_buffer_create_sub (GstBuffer *parent, guint offset, guint size); +GstBuffer* gst_buffer_create_sub (GstBuffer *parent, gsize offset, gsize size); /* span, two buffers, intelligently */ gboolean gst_buffer_is_span_fast (GstBuffer *buf1, GstBuffer *buf2); -GstBuffer* gst_buffer_span (GstBuffer *buf1, guint32 offset, GstBuffer *buf2, guint32 len); +GstBuffer* gst_buffer_span (GstBuffer *buf1, gsize offset, GstBuffer *buf2, gsize len); /* metadata */ #include diff --git a/gst/gstbufferlist.c b/gst/gstbufferlist.c index 7bcc7468d3..27138039cc 100644 --- a/gst/gstbufferlist.c +++ b/gst/gstbufferlist.c @@ -836,9 +836,9 @@ GstBuffer * gst_buffer_list_iterator_merge_group (const GstBufferListIterator * it) { GList *tmp; - guint size; + gsize size, bsize; GstBuffer *buf; - guint8 *ptr; + guint8 *dest, *ptr, *bdata; g_return_val_if_fail (it != NULL, NULL); @@ -847,7 +847,7 @@ gst_buffer_list_iterator_merge_group (const GstBufferListIterator * it) tmp = it->next; while (tmp && tmp->data != GROUP_START) { if (tmp->data != STOLEN) { - size += GST_BUFFER_SIZE (tmp->data); + size += gst_buffer_get_size (tmp->data); } tmp = g_list_next (tmp); } @@ -860,19 +860,26 @@ gst_buffer_list_iterator_merge_group (const GstBufferListIterator * it) buf = gst_buffer_new_and_alloc (size); /* copy metadata from the next buffer after the implicit cursor */ - gst_buffer_copy_metadata (buf, GST_BUFFER_CAST (it->next->data), - GST_BUFFER_COPY_ALL); + gst_buffer_copy_into (buf, GST_BUFFER_CAST (it->next->data), + GST_BUFFER_COPY_METADATA, 0, 0); /* copy data of all buffers before the next group start into the new buffer */ - ptr = GST_BUFFER_DATA (buf); + dest = ptr = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE); tmp = it->next; do { if (tmp->data != STOLEN) { - memcpy (ptr, GST_BUFFER_DATA (tmp->data), GST_BUFFER_SIZE (tmp->data)); - ptr += GST_BUFFER_SIZE (tmp->data); + + bdata = + gst_buffer_map (GST_BUFFER_CAST (tmp->data), &bsize, NULL, + GST_MAP_READ); + memcpy (ptr, bdata, bsize); + gst_buffer_unmap (GST_BUFFER_CAST (tmp->data), bdata, bsize); + ptr += bsize; } tmp = g_list_next (tmp); } while (tmp && tmp->data != GROUP_START); + gst_buffer_unmap (buf, dest, size); + return buf; } diff --git a/gst/gstbufferpool.c b/gst/gstbufferpool.c index 83acd68289..6e85495185 100644 --- a/gst/gstbufferpool.c +++ b/gst/gstbufferpool.c @@ -160,22 +160,14 @@ static GstFlowReturn default_alloc_buffer (GstBufferPool * pool, GstBuffer ** buffer, GstBufferPoolParams * params) { - guint size, align; + guint align; GstBufferPoolPrivate *priv = pool->priv; *buffer = gst_buffer_new (); align = priv->align - 1; - size = priv->prefix + priv->postfix + priv->size + align; - if (size > 0) { - guint8 *memptr; - memptr = g_malloc (size); - GST_BUFFER_MALLOCDATA (*buffer) = memptr; - memptr = (guint8 *) ((guintptr) (memptr + align) & ~align); - GST_BUFFER_DATA (*buffer) = memptr + priv->prefix; - GST_BUFFER_SIZE (*buffer) = priv->size; - } + gst_buffer_take_memory (*buffer, gst_memory_new_alloc (priv->size, align)); return GST_FLOW_OK; } diff --git a/gst/gstmemory.c b/gst/gstmemory.c index 02bc279918..cadea03e0f 100644 --- a/gst/gstmemory.c +++ b/gst/gstmemory.c @@ -220,44 +220,14 @@ _default_mem_sub (GstMemoryDefault * mem, gsize offset, gsize size) } static gboolean -_default_mem_is_span (GstMemoryDefault * mem1, GstMemoryDefault * mem2) +_default_mem_is_span (GstMemoryDefault * mem1, GstMemoryDefault * mem2, + gsize * offset) { - /* need to have the same implementation */ - if (mem1->mem.impl != mem2->mem.impl) - return FALSE; - - /* need to have the same parent */ - if (mem1->mem.parent == NULL || mem1->mem.parent != mem2->mem.parent) - return FALSE; + if (offset) + *offset = mem1->offset; /* and memory is contiguous */ - if (mem1->data + mem1->offset + mem1->size != mem2->data + mem2->offset) - return FALSE; - - return TRUE; -} - -static GstMemoryDefault * -_default_mem_span (GstMemoryDefault * mem1, gsize offset, - GstMemoryDefault * mem2, gsize size) -{ - GstMemoryDefault *span; - - if (_default_mem_is_span (mem1, mem2)) { - GstMemoryDefault *parent = (GstMemoryDefault *) mem1->mem.parent; - - span = - _default_mem_sub (parent, mem1->offset - parent->offset + offset, size); - } else { - gsize len1; - - len1 = mem1->size - offset; - - span = _default_mem_new_block (size, 0, 0, size); - memcpy (span->data, mem1->data + mem1->offset + offset, len1); - memcpy (span->data + len1, mem2->data + mem2->offset, size - len1); - } - return span; + return mem1->data + mem1->offset + mem1->size == mem2->data + mem2->offset; } static void @@ -301,32 +271,11 @@ _fallback_sub (GstMemory * mem, gsize offset, gsize size) } static gboolean -_fallback_is_span (GstMemory * mem1, GstMemory * mem2) +_fallback_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset) { return FALSE; } -static GstMemory * -_fallback_span (GstMemory * mem1, gsize offset, GstMemory * mem2, gsize size) -{ - GstMemoryDefault *span; - guint8 *data; - gsize ssize, len1; - - span = _default_mem_new_block (size, 0, 0, size); - - data = gst_memory_map (mem1, &ssize, NULL, GST_MAP_READ); - len1 = ssize - offset; - memcpy (span->data, data + offset, len1); - gst_memory_unmap (mem1, data, size); - - data = gst_memory_map (mem2, &ssize, NULL, GST_MAP_READ); - memcpy (span->data + len1, data, ssize - len1); - gst_memory_unmap (mem2, data, size); - - return (GstMemory *) span; -} - const GstMemoryImpl * gst_memory_register (const gchar * name, const GstMemoryInfo * info) { @@ -350,7 +299,6 @@ gst_memory_register (const gchar * name, const GstMemoryInfo * info) INSTALL_FALLBACK (extract); INSTALL_FALLBACK (sub); INSTALL_FALLBACK (is_span); - INSTALL_FALLBACK (span); GST_DEBUG ("register \"%s\" of size %" G_GSIZE_FORMAT, name); @@ -376,8 +324,7 @@ _gst_memory_init (void) (GstMemoryCopyFunction) _default_mem_copy, (GstMemoryExtractFunction) _default_mem_extract, (GstMemorySubFunction) _default_mem_sub, - (GstMemoryIsSpanFunction) _default_mem_is_span, - (GstMemorySpanFunction) _default_mem_span + (GstMemoryIsSpanFunction) _default_mem_is_span }; static const GstMemoryInfo _sub_info = { (GstMemoryGetSizesFunction) _default_mem_get_sizes, @@ -388,7 +335,6 @@ _gst_memory_init (void) NULL, NULL, NULL, - NULL, NULL }; @@ -474,21 +420,99 @@ gst_memory_sub (GstMemory * mem, gsize offset, gsize size) } gboolean -gst_memory_is_span (GstMemory * mem1, GstMemory * mem2) +gst_memory_is_span (GstMemory ** mem1, gsize len1, GstMemory ** mem2, + gsize len2, GstMemory ** parent, 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); - return mem1->impl->info.is_span (mem1, mem2); + arr = mem1; + len = len1; + m1 = m2 = NULL; + + for (count = 0; count < 2; count++) { + gsize offs; + + 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) { + *offset = offs; + have_offset = TRUE; + } + } + } + arr = mem2; + len = len2; + } + if (!have_offset) + return FALSE; + + return TRUE; } GstMemory * -gst_memory_span (GstMemory * mem1, gsize offset, GstMemory * mem2, gsize size) +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); - return mem1->impl->info.span (mem1, offset, mem2, size); + 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; } GstMemory * diff --git a/gst/gstmemory.h b/gst/gstmemory.h index 652dd9afe9..c3718213a8 100644 --- a/gst/gstmemory.h +++ b/gst/gstmemory.h @@ -79,9 +79,8 @@ 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); -typedef GstMemory * (*GstMemorySpanFunction) (GstMemory *mem1, gsize offset, - GstMemory *mem2, gsize size); +typedef gboolean (*GstMemoryIsSpanFunction) (GstMemory *mem1, GstMemory *mem2, + gsize *offset); /** * GstMemoryInfo: @@ -100,7 +99,6 @@ struct _GstMemoryInfo { GstMemoryExtractFunction extract; GstMemorySubFunction sub; GstMemoryIsSpanFunction is_span; - GstMemorySpanFunction span; }; void _gst_memory_init (void); @@ -120,9 +118,11 @@ void gst_memory_extract (GstMemory *mem, gsize offset, gpointer dest, gsize size); GstMemory * gst_memory_sub (GstMemory *mem, gsize offset, gsize size); -gboolean gst_memory_is_span (GstMemory *mem1, GstMemory *mem2); -GstMemory * gst_memory_span (GstMemory *mem1, gsize offset, - GstMemory *mem2, gsize size); +gboolean gst_memory_is_span (GstMemory **mem1, gsize len1, + GstMemory **mem2, gsize len2, + GstMemory **parent, gsize *offset); +GstMemory * gst_memory_span (GstMemory **mem1, gsize len1, gsize offset, + GstMemory **mem2, gsize len2, gsize size); GstMemory * gst_memory_new_wrapped (gpointer data, GFreeFunc free_func, diff --git a/gst/gstmeta.c b/gst/gstmeta.c index 827f9f71ad..d64b719e63 100644 --- a/gst/gstmeta.c +++ b/gst/gstmeta.c @@ -241,7 +241,7 @@ meta_timing_transform (GstBuffer * transbuf, GstMetaTiming * meta, size = subdata->size; } else { offset = 0; - size = GST_BUFFER_SIZE (buffer); + size = gst_buffer_get_size (buffer); } GST_DEBUG ("trans called from buffer %p to %p, meta %p, %u-%u", buffer, @@ -252,7 +252,7 @@ meta_timing_transform (GstBuffer * transbuf, GstMetaTiming * meta, /* same offset, copy timestamps */ timing->pts = meta->pts; timing->dts = meta->dts; - if (size == GST_BUFFER_SIZE (buffer)) { + if (size == gst_buffer_get_size (buffer)) { /* same size, copy duration */ timing->duration = meta->duration; } else { diff --git a/gst/gstpad.c b/gst/gstpad.c index 829aaf0180..46f0f682c8 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -2960,7 +2960,8 @@ gst_pad_alloc_buffer_full (GstPad * pad, guint64 offset, gint size, } /* sanity check (only if caps are the same) */ - if (G_LIKELY (newcaps == caps) && G_UNLIKELY (GST_BUFFER_SIZE (*buf) < size)) + if (G_LIKELY (newcaps == caps) + && G_UNLIKELY (gst_buffer_get_size (*buf) < size)) goto wrong_size_fallback; return ret; @@ -2997,7 +2998,7 @@ wrong_size_fallback: { GST_CAT_ERROR_OBJECT (GST_CAT_PADS, pad, "buffer returned by alloc " "function is too small (%u < %d), doing fallback buffer alloc", - GST_BUFFER_SIZE (*buf), size); + gst_buffer_get_size (*buf), size); gst_buffer_unref (*buf);