diff --git a/ChangeLog b/ChangeLog index 3ee36b4d81..ca0f35a450 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2007-01-25 Wim Taymans + + Patch by: David Schleef + + * docs/libs/gstreamer-libs-sections.txt: + * libs/gst/base/gstadapter.c: (gst_adapter_copy): + * libs/gst/base/gstadapter.h: + API: gst_adapter_copy() that can reduce the amount of memcpy when + getting data from the adapter. Fixes #388201. + 2007-01-25 Edward Hervey * gst/gstregistrybinary.c: (gst_registry_binary_read_cache): diff --git a/docs/libs/gstreamer-libs-sections.txt b/docs/libs/gstreamer-libs-sections.txt index f027750985..4279ec9da6 100644 --- a/docs/libs/gstreamer-libs-sections.txt +++ b/docs/libs/gstreamer-libs-sections.txt @@ -123,6 +123,7 @@ gst_adapter_new gst_adapter_clear gst_adapter_push gst_adapter_peek +gst_adapter_copy gst_adapter_flush gst_adapter_available gst_adapter_available_fast diff --git a/libs/gst/base/gstadapter.c b/libs/gst/base/gstadapter.c index 36af32cf95..1bd0e526b9 100644 --- a/libs/gst/base/gstadapter.c +++ b/libs/gst/base/gstadapter.c @@ -302,6 +302,58 @@ gst_adapter_peek (GstAdapter * adapter, guint size) return adapter->assembled_data; } +/** + * gst_adapter_copy: + * @adapter: a #GstAdapter + * @dest: the memory where to copy to + * @offset: the bytes offset in the adapter to start from + * @size: the number of bytes to copy + * + * Copies @size bytes of data starting at @offset out of the buffers + * contained in @GstAdapter into an array @dest provided by the caller. + * + * The array @dest should be large enough to contain @size bytes. + * The user should check that the adapter has (@offset + @size) bytes + * available before calling this function. + * + * Since: 0.10.12 + */ +void +gst_adapter_copy (GstAdapter * adapter, guint8 * dest, guint offset, guint size) +{ + GSList *g; + int skip; + + g_return_if_fail (GST_IS_ADAPTER (adapter)); + g_return_if_fail (size > 0); + + /* we don't have enough data, return. This is unlikely + * as one usually does an _available() first instead of copying a + * random size. */ + if (G_UNLIKELY (offset + size > adapter->size)) + return; + + skip = adapter->skip; + for (g = adapter->buflist; g && size > 0; g = g_slist_next (g)) { + GstBuffer *buf; + + buf = g->data; + if (offset < GST_BUFFER_SIZE (buf) - skip) { + int n; + + n = MIN (GST_BUFFER_SIZE (buf) - skip - offset, size); + memcpy (dest, GST_BUFFER_DATA (buf) + skip + offset, n); + + dest += n; + offset = 0; + size -= n; + } else { + offset -= GST_BUFFER_SIZE (buf) - skip; + } + skip = 0; + } +} + /** * gst_adapter_flush: * @adapter: a #GstAdapter diff --git a/libs/gst/base/gstadapter.h b/libs/gst/base/gstadapter.h index 1ae993b627..3dc52c0e39 100644 --- a/libs/gst/base/gstadapter.h +++ b/libs/gst/base/gstadapter.h @@ -78,6 +78,8 @@ GstAdapter * gst_adapter_new (void); void gst_adapter_clear (GstAdapter *adapter); void gst_adapter_push (GstAdapter *adapter, GstBuffer* buf); const guint8 * gst_adapter_peek (GstAdapter *adapter, guint size); +void gst_adapter_copy (GstAdapter *adapter, guint8 *dest, + guint offset, guint size); void gst_adapter_flush (GstAdapter *adapter, guint flush); guint8* gst_adapter_take (GstAdapter *adapter, guint nbytes); GstBuffer* gst_adapter_take_buffer (GstAdapter *adapter, guint nbytes);