mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-07 07:58:51 +00:00
adapter: more optimisations
Remove duplicate copy code (_peek_into and _copy) and make a unified optimized copy function.
This commit is contained in:
parent
198dbe545c
commit
d6b21ba529
1 changed files with 60 additions and 73 deletions
|
@ -231,6 +231,45 @@ update_timestamp (GstAdapter * adapter, GstBuffer * buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* copy data into @dest, skipping @skip bytes from the head buffers */
|
||||||
|
static void
|
||||||
|
copy_into_unchecked (GstAdapter * adapter, guint8 * dest, guint skip,
|
||||||
|
guint size)
|
||||||
|
{
|
||||||
|
GSList *g;
|
||||||
|
GstBuffer *buf;
|
||||||
|
guint bsize, csize;
|
||||||
|
|
||||||
|
/* first step, do skipping and copy partial first buffer, we don't have to
|
||||||
|
* check for valid list entries, we keep things consistent. */
|
||||||
|
g = adapter->buflist;
|
||||||
|
while (skip > 0) {
|
||||||
|
buf = g->data;
|
||||||
|
g = g_slist_next (g);
|
||||||
|
bsize = GST_BUFFER_SIZE (buf);
|
||||||
|
if (G_LIKELY (skip < bsize)) {
|
||||||
|
/* last bit */
|
||||||
|
csize = MIN (bsize - skip, size);
|
||||||
|
memcpy (dest, GST_BUFFER_DATA (buf) + skip, csize);
|
||||||
|
size -= csize;
|
||||||
|
dest += csize;
|
||||||
|
/* break out and move to next step */
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
skip -= bsize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* second step, copy remainder */
|
||||||
|
while (size > 0) {
|
||||||
|
buf = g->data;
|
||||||
|
g = g_slist_next (g);
|
||||||
|
csize = MIN (GST_BUFFER_SIZE (buf), size);
|
||||||
|
memcpy (dest, GST_BUFFER_DATA (buf), csize);
|
||||||
|
size -= csize;
|
||||||
|
dest += csize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_adapter_push:
|
* gst_adapter_push:
|
||||||
* @adapter: a #GstAdapter
|
* @adapter: a #GstAdapter
|
||||||
|
@ -252,6 +291,8 @@ gst_adapter_push (GstAdapter * adapter, GstBuffer * buf)
|
||||||
size = GST_BUFFER_SIZE (buf);
|
size = GST_BUFFER_SIZE (buf);
|
||||||
|
|
||||||
if (G_UNLIKELY (size == 0)) {
|
if (G_UNLIKELY (size == 0)) {
|
||||||
|
/* we can't have empty buffers, several parts in this file rely on it, this
|
||||||
|
* has some problems for the timestamp tracking. */
|
||||||
GST_LOG_OBJECT (adapter, "discarding empty buffer");
|
GST_LOG_OBJECT (adapter, "discarding empty buffer");
|
||||||
gst_buffer_unref (buf);
|
gst_buffer_unref (buf);
|
||||||
} else {
|
} else {
|
||||||
|
@ -272,34 +313,6 @@ gst_adapter_push (GstAdapter * adapter, GstBuffer * buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Internal function that copies data into the given buffer, size must be
|
|
||||||
* bigger than the first buffer */
|
|
||||||
static void
|
|
||||||
gst_adapter_peek_into (GstAdapter * adapter, guint8 * data, guint size)
|
|
||||||
{
|
|
||||||
GstBuffer *cur;
|
|
||||||
GSList *cur_list;
|
|
||||||
guint copied, to_copy;
|
|
||||||
|
|
||||||
/* The first buffer might be partly consumed, so need to handle
|
|
||||||
* 'skipped' bytes. */
|
|
||||||
cur = adapter->buflist->data;
|
|
||||||
copied = MIN (GST_BUFFER_SIZE (cur) - adapter->skip, size);
|
|
||||||
memcpy (data, GST_BUFFER_DATA (cur) + adapter->skip, copied);
|
|
||||||
data += copied;
|
|
||||||
|
|
||||||
cur_list = g_slist_next (adapter->buflist);
|
|
||||||
while (copied < size) {
|
|
||||||
g_assert (cur_list);
|
|
||||||
cur = cur_list->data;
|
|
||||||
cur_list = g_slist_next (cur_list);
|
|
||||||
to_copy = MIN (GST_BUFFER_SIZE (cur), size - copied);
|
|
||||||
memcpy (data, GST_BUFFER_DATA (cur), to_copy);
|
|
||||||
data += to_copy;
|
|
||||||
copied += to_copy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Internal method only. Tries to merge buffers at the head of the queue
|
/* Internal method only. Tries to merge buffers at the head of the queue
|
||||||
* to form a single larger buffer of size 'size'. Only merges buffers that
|
* to form a single larger buffer of size 'size'. Only merges buffers that
|
||||||
* where 'gst_buffer_is_span_fast' returns TRUE.
|
* where 'gst_buffer_is_span_fast' returns TRUE.
|
||||||
|
@ -369,6 +382,7 @@ const guint8 *
|
||||||
gst_adapter_peek (GstAdapter * adapter, guint size)
|
gst_adapter_peek (GstAdapter * adapter, guint size)
|
||||||
{
|
{
|
||||||
GstBuffer *cur;
|
GstBuffer *cur;
|
||||||
|
guint skip;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
|
g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
|
||||||
g_return_val_if_fail (size > 0, NULL);
|
g_return_val_if_fail (size > 0, NULL);
|
||||||
|
@ -385,16 +399,17 @@ gst_adapter_peek (GstAdapter * adapter, guint size)
|
||||||
|
|
||||||
/* our head buffer has enough data left, return it */
|
/* our head buffer has enough data left, return it */
|
||||||
cur = adapter->buflist->data;
|
cur = adapter->buflist->data;
|
||||||
if (GST_BUFFER_SIZE (cur) >= size + adapter->skip)
|
skip = adapter->skip;
|
||||||
return GST_BUFFER_DATA (cur) + adapter->skip;
|
if (GST_BUFFER_SIZE (cur) >= size + skip)
|
||||||
|
return GST_BUFFER_DATA (cur) + skip;
|
||||||
|
|
||||||
/* We may be able to efficiently merge buffers in our pool to
|
/* We may be able to efficiently merge buffers in our pool to
|
||||||
* gather a big enough chunk to return it from the head buffer directly */
|
* gather a big enough chunk to return it from the head buffer directly */
|
||||||
if (gst_adapter_try_to_merge_up (adapter, size)) {
|
if (gst_adapter_try_to_merge_up (adapter, size)) {
|
||||||
/* Merged something! Check if there's enough avail now */
|
/* Merged something! Check if there's enough avail now */
|
||||||
cur = adapter->buflist->data;
|
cur = adapter->buflist->data;
|
||||||
if (GST_BUFFER_SIZE (cur) >= size + adapter->skip)
|
if (GST_BUFFER_SIZE (cur) >= size + skip)
|
||||||
return GST_BUFFER_DATA (cur) + adapter->skip;
|
return GST_BUFFER_DATA (cur) + skip;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Gonna need to copy stuff out */
|
/* Gonna need to copy stuff out */
|
||||||
|
@ -409,7 +424,7 @@ gst_adapter_peek (GstAdapter * adapter, guint size)
|
||||||
}
|
}
|
||||||
adapter->assembled_len = size;
|
adapter->assembled_len = size;
|
||||||
|
|
||||||
gst_adapter_peek_into (adapter, adapter->assembled_data, size);
|
copy_into_unchecked (adapter, adapter->assembled_data, skip, size);
|
||||||
|
|
||||||
return adapter->assembled_data;
|
return adapter->assembled_data;
|
||||||
}
|
}
|
||||||
|
@ -433,37 +448,11 @@ gst_adapter_peek (GstAdapter * adapter, guint size)
|
||||||
void
|
void
|
||||||
gst_adapter_copy (GstAdapter * adapter, guint8 * dest, guint offset, guint size)
|
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 (GST_IS_ADAPTER (adapter));
|
||||||
g_return_if_fail (size > 0);
|
g_return_if_fail (size > 0);
|
||||||
|
g_return_if_fail (offset + size <= adapter->size);
|
||||||
|
|
||||||
/* we don't have enough data, return. This is unlikely
|
copy_into_unchecked (adapter, dest, offset + adapter->skip, size);
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -550,7 +539,7 @@ gst_adapter_take (GstAdapter * adapter, guint nbytes)
|
||||||
memcpy (data, adapter->assembled_data, nbytes);
|
memcpy (data, adapter->assembled_data, nbytes);
|
||||||
} else {
|
} else {
|
||||||
GST_LOG_OBJECT (adapter, "taking %u bytes by collection", nbytes);
|
GST_LOG_OBJECT (adapter, "taking %u bytes by collection", nbytes);
|
||||||
gst_adapter_peek_into (adapter, data, nbytes);
|
copy_into_unchecked (adapter, data, adapter->skip, nbytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_adapter_flush (adapter, nbytes);
|
gst_adapter_flush (adapter, nbytes);
|
||||||
|
@ -581,7 +570,7 @@ gst_adapter_take_buffer (GstAdapter * adapter, guint nbytes)
|
||||||
{
|
{
|
||||||
GstBuffer *buffer;
|
GstBuffer *buffer;
|
||||||
GstBuffer *cur;
|
GstBuffer *cur;
|
||||||
guint hsize;
|
guint hsize, skip;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
|
g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
|
||||||
g_return_val_if_fail (nbytes > 0, NULL);
|
g_return_val_if_fail (nbytes > 0, NULL);
|
||||||
|
@ -595,28 +584,29 @@ gst_adapter_take_buffer (GstAdapter * adapter, guint nbytes)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
cur = adapter->buflist->data;
|
cur = adapter->buflist->data;
|
||||||
|
skip = adapter->skip;
|
||||||
hsize = GST_BUFFER_SIZE (cur);
|
hsize = GST_BUFFER_SIZE (cur);
|
||||||
|
|
||||||
/* our head buffer has enough data left, return it */
|
/* our head buffer has enough data left, return it */
|
||||||
if (adapter->skip == 0 && hsize == nbytes) {
|
if (skip == 0 && hsize == nbytes) {
|
||||||
GST_LOG_OBJECT (adapter, "providing buffer of %d bytes as head buffer",
|
GST_LOG_OBJECT (adapter, "providing buffer of %d bytes as head buffer",
|
||||||
nbytes);
|
nbytes);
|
||||||
buffer = gst_buffer_ref (cur);
|
buffer = gst_buffer_ref (cur);
|
||||||
goto done;
|
goto done;
|
||||||
} else if (hsize >= nbytes + adapter->skip) {
|
} else if (hsize >= nbytes + skip) {
|
||||||
GST_LOG_OBJECT (adapter, "providing buffer of %d bytes via sub-buffer",
|
GST_LOG_OBJECT (adapter, "providing buffer of %d bytes via sub-buffer",
|
||||||
nbytes);
|
nbytes);
|
||||||
buffer = gst_buffer_create_sub (cur, adapter->skip, nbytes);
|
buffer = gst_buffer_create_sub (cur, skip, nbytes);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gst_adapter_try_to_merge_up (adapter, nbytes)) {
|
if (gst_adapter_try_to_merge_up (adapter, nbytes)) {
|
||||||
/* Merged something, let's try again for sub-buffering */
|
/* Merged something, let's try again for sub-buffering */
|
||||||
cur = adapter->buflist->data;
|
cur = adapter->buflist->data;
|
||||||
if (GST_BUFFER_SIZE (cur) >= nbytes + adapter->skip) {
|
if (GST_BUFFER_SIZE (cur) >= nbytes + skip) {
|
||||||
GST_LOG_OBJECT (adapter, "providing buffer of %d bytes via sub-buffer",
|
GST_LOG_OBJECT (adapter, "providing buffer of %d bytes via sub-buffer",
|
||||||
nbytes);
|
nbytes);
|
||||||
buffer = gst_buffer_create_sub (cur, adapter->skip, nbytes);
|
buffer = gst_buffer_create_sub (cur, skip, nbytes);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -629,7 +619,7 @@ gst_adapter_take_buffer (GstAdapter * adapter, guint nbytes)
|
||||||
memcpy (GST_BUFFER_DATA (buffer), adapter->assembled_data, nbytes);
|
memcpy (GST_BUFFER_DATA (buffer), adapter->assembled_data, nbytes);
|
||||||
} else {
|
} else {
|
||||||
GST_LOG_OBJECT (adapter, "taking %u bytes by collection", nbytes);
|
GST_LOG_OBJECT (adapter, "taking %u bytes by collection", nbytes);
|
||||||
gst_adapter_peek_into (adapter, GST_BUFFER_DATA (buffer), nbytes);
|
copy_into_unchecked (adapter, GST_BUFFER_DATA (buffer), skip, nbytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
@ -687,10 +677,7 @@ gst_adapter_available_fast (GstAdapter * adapter)
|
||||||
first = GST_BUFFER_CAST (adapter->buflist->data);
|
first = GST_BUFFER_CAST (adapter->buflist->data);
|
||||||
size = GST_BUFFER_SIZE (first);
|
size = GST_BUFFER_SIZE (first);
|
||||||
|
|
||||||
/* we cannot have skipped more than the first buffer */
|
/* we can quickly get the (remaining) data of the first buffer */
|
||||||
g_assert (size > adapter->skip);
|
|
||||||
|
|
||||||
/* we can quickly get the data of the first buffer */
|
|
||||||
return size - adapter->skip;
|
return size - adapter->skip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue