mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 06:54:49 +00:00
adapter: add support for 0 sized buffers
Add support for 0 sized buffers. This is interesting in combination with the timestamp functions. Fixes #629553
This commit is contained in:
parent
47743aa7ac
commit
1dde3cb440
2 changed files with 112 additions and 31 deletions
|
@ -271,10 +271,13 @@ copy_into_unchecked (GstAdapter * adapter, guint8 * dest, guint skip,
|
||||||
while (size > 0) {
|
while (size > 0) {
|
||||||
g = g_slist_next (g);
|
g = g_slist_next (g);
|
||||||
buf = g->data;
|
buf = g->data;
|
||||||
csize = MIN (GST_BUFFER_SIZE (buf), size);
|
bsize = GST_BUFFER_SIZE (buf);
|
||||||
memcpy (dest, GST_BUFFER_DATA (buf), csize);
|
if (G_LIKELY (bsize > 0)) {
|
||||||
size -= csize;
|
csize = MIN (bsize, size);
|
||||||
dest += csize;
|
memcpy (dest, GST_BUFFER_DATA (buf), csize);
|
||||||
|
size -= csize;
|
||||||
|
dest += csize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,8 +288,6 @@ copy_into_unchecked (GstAdapter * adapter, guint8 * dest, guint skip,
|
||||||
*
|
*
|
||||||
* Adds the data from @buf to the data stored inside @adapter and takes
|
* Adds the data from @buf to the data stored inside @adapter and takes
|
||||||
* ownership of the buffer.
|
* ownership of the buffer.
|
||||||
* Empty buffers will be automatically dereferenced and not stored in the
|
|
||||||
* @adapter.
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
gst_adapter_push (GstAdapter * adapter, GstBuffer * buf)
|
gst_adapter_push (GstAdapter * adapter, GstBuffer * buf)
|
||||||
|
@ -297,27 +298,19 @@ gst_adapter_push (GstAdapter * adapter, GstBuffer * buf)
|
||||||
g_return_if_fail (GST_IS_BUFFER (buf));
|
g_return_if_fail (GST_IS_BUFFER (buf));
|
||||||
|
|
||||||
size = GST_BUFFER_SIZE (buf);
|
size = GST_BUFFER_SIZE (buf);
|
||||||
|
adapter->size += size;
|
||||||
|
|
||||||
if (G_UNLIKELY (size == 0)) {
|
/* Note: merging buffers at this point is premature. */
|
||||||
/* we can't have empty buffers, several parts in this file rely on it, this
|
if (G_UNLIKELY (adapter->buflist == NULL)) {
|
||||||
* has some problems for the timestamp tracking. */
|
GST_LOG_OBJECT (adapter, "pushing first %u bytes", size);
|
||||||
GST_LOG_OBJECT (adapter, "discarding empty buffer");
|
adapter->buflist = adapter->buflist_end = g_slist_append (NULL, buf);
|
||||||
gst_buffer_unref (buf);
|
update_timestamp (adapter, buf);
|
||||||
} else {
|
} else {
|
||||||
adapter->size += size;
|
/* Otherwise append to the end, and advance our end pointer */
|
||||||
|
GST_LOG_OBJECT (adapter, "pushing %u bytes at end, size now %u", size,
|
||||||
/* Note: merging buffers at this point is premature. */
|
adapter->size);
|
||||||
if (G_UNLIKELY (adapter->buflist == NULL)) {
|
adapter->buflist_end = g_slist_append (adapter->buflist_end, buf);
|
||||||
GST_LOG_OBJECT (adapter, "pushing first %u bytes", size);
|
adapter->buflist_end = g_slist_next (adapter->buflist_end);
|
||||||
adapter->buflist = adapter->buflist_end = g_slist_append (NULL, buf);
|
|
||||||
update_timestamp (adapter, buf);
|
|
||||||
} else {
|
|
||||||
/* Otherwise append to the end, and advance our end pointer */
|
|
||||||
GST_LOG_OBJECT (adapter, "pushing %u bytes at end, size now %u", size,
|
|
||||||
adapter->size);
|
|
||||||
adapter->buflist_end = g_slist_append (adapter->buflist_end, buf);
|
|
||||||
adapter->buflist_end = g_slist_next (adapter->buflist_end);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -711,22 +704,29 @@ gst_adapter_available (GstAdapter * adapter)
|
||||||
guint
|
guint
|
||||||
gst_adapter_available_fast (GstAdapter * adapter)
|
gst_adapter_available_fast (GstAdapter * adapter)
|
||||||
{
|
{
|
||||||
GstBuffer *first;
|
GstBuffer *cur;
|
||||||
guint size;
|
guint size;
|
||||||
|
GSList *g;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_ADAPTER (adapter), 0);
|
g_return_val_if_fail (GST_IS_ADAPTER (adapter), 0);
|
||||||
|
|
||||||
/* no buffers, we have no data */
|
/* no data */
|
||||||
if (!adapter->buflist)
|
if (adapter->size == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* some stuff we already assembled */
|
/* some stuff we already assembled */
|
||||||
if (adapter->assembled_len)
|
if (adapter->assembled_len)
|
||||||
return adapter->assembled_len;
|
return adapter->assembled_len;
|
||||||
|
|
||||||
/* take the first buffer and its size */
|
/* take the first non-zero buffer */
|
||||||
first = GST_BUFFER_CAST (adapter->buflist->data);
|
g = adapter->buflist;
|
||||||
size = GST_BUFFER_SIZE (first);
|
while (TRUE) {
|
||||||
|
cur = g->data;
|
||||||
|
size = GST_BUFFER_SIZE (cur);
|
||||||
|
if (size != 0)
|
||||||
|
break;
|
||||||
|
g = g_slist_next (g);
|
||||||
|
}
|
||||||
|
|
||||||
/* we can quickly get the (remaining) data of the first buffer */
|
/* we can quickly get the (remaining) data of the first buffer */
|
||||||
return size - adapter->skip;
|
return size - adapter->skip;
|
||||||
|
|
|
@ -335,6 +335,8 @@ GST_START_TEST (test_timestamp)
|
||||||
guint avail;
|
guint avail;
|
||||||
GstClockTime timestamp;
|
GstClockTime timestamp;
|
||||||
guint64 dist;
|
guint64 dist;
|
||||||
|
guint8 *data;
|
||||||
|
const guint8 *cdata;
|
||||||
|
|
||||||
adapter = gst_adapter_new ();
|
adapter = gst_adapter_new ();
|
||||||
fail_unless (adapter != NULL);
|
fail_unless (adapter != NULL);
|
||||||
|
@ -448,6 +450,85 @@ GST_START_TEST (test_timestamp)
|
||||||
fail_unless (timestamp == GST_CLOCK_TIME_NONE);
|
fail_unless (timestamp == GST_CLOCK_TIME_NONE);
|
||||||
fail_unless (dist == 0);
|
fail_unless (dist == 0);
|
||||||
|
|
||||||
|
/* push an empty buffer with timestamp in the adapter */
|
||||||
|
buffer = gst_buffer_new ();
|
||||||
|
GST_BUFFER_TIMESTAMP (buffer) = 2 * GST_SECOND;
|
||||||
|
gst_adapter_push (adapter, buffer);
|
||||||
|
avail = gst_adapter_available (adapter);
|
||||||
|
fail_unless (avail == 0);
|
||||||
|
timestamp = gst_adapter_prev_timestamp (adapter, &dist);
|
||||||
|
fail_unless (timestamp == 2 * GST_SECOND);
|
||||||
|
fail_unless (dist == 0);
|
||||||
|
|
||||||
|
/* push another empty buffer */
|
||||||
|
buffer = gst_buffer_new ();
|
||||||
|
GST_BUFFER_TIMESTAMP (buffer) = 3 * GST_SECOND;
|
||||||
|
gst_adapter_push (adapter, buffer);
|
||||||
|
avail = gst_adapter_available (adapter);
|
||||||
|
fail_unless (avail == 0);
|
||||||
|
timestamp = gst_adapter_prev_timestamp (adapter, &dist);
|
||||||
|
fail_unless (timestamp == 2 * GST_SECOND);
|
||||||
|
fail_unless (dist == 0);
|
||||||
|
|
||||||
|
/* push a buffer with timestamp in the adapter */
|
||||||
|
buffer = gst_buffer_new_and_alloc (100);
|
||||||
|
GST_BUFFER_TIMESTAMP (buffer) = 4 * GST_SECOND;
|
||||||
|
gst_adapter_push (adapter, buffer);
|
||||||
|
avail = gst_adapter_available (adapter);
|
||||||
|
fail_unless (avail == 100);
|
||||||
|
timestamp = gst_adapter_prev_timestamp (adapter, &dist);
|
||||||
|
fail_unless (timestamp == 2 * GST_SECOND);
|
||||||
|
fail_unless (dist == 0);
|
||||||
|
|
||||||
|
gst_adapter_flush (adapter, 1);
|
||||||
|
avail = gst_adapter_available (adapter);
|
||||||
|
fail_unless (avail == 99);
|
||||||
|
timestamp = gst_adapter_prev_timestamp (adapter, &dist);
|
||||||
|
fail_unless (timestamp == 4 * GST_SECOND);
|
||||||
|
fail_unless (dist == 1);
|
||||||
|
|
||||||
|
/* push an empty buffer with timestamp in the adapter */
|
||||||
|
buffer = gst_buffer_new ();
|
||||||
|
GST_BUFFER_TIMESTAMP (buffer) = 5 * GST_SECOND;
|
||||||
|
gst_adapter_push (adapter, buffer);
|
||||||
|
avail = gst_adapter_available (adapter);
|
||||||
|
fail_unless (avail == 99);
|
||||||
|
timestamp = gst_adapter_prev_timestamp (adapter, &dist);
|
||||||
|
fail_unless (timestamp == 4 * GST_SECOND);
|
||||||
|
fail_unless (dist == 1);
|
||||||
|
|
||||||
|
/* push buffer without timestamp */
|
||||||
|
buffer = gst_buffer_new_and_alloc (100);
|
||||||
|
gst_adapter_push (adapter, buffer);
|
||||||
|
avail = gst_adapter_available (adapter);
|
||||||
|
fail_unless (avail == 199);
|
||||||
|
timestamp = gst_adapter_prev_timestamp (adapter, &dist);
|
||||||
|
fail_unless (timestamp == 4 * GST_SECOND);
|
||||||
|
fail_unless (dist == 1);
|
||||||
|
|
||||||
|
/* remove first buffer, timestamp of empty buffer is visible */
|
||||||
|
buffer = gst_adapter_take_buffer (adapter, 99);
|
||||||
|
fail_unless (buffer != NULL);
|
||||||
|
fail_unless (GST_BUFFER_SIZE (buffer) == 99);
|
||||||
|
gst_buffer_unref (buffer);
|
||||||
|
avail = gst_adapter_available (adapter);
|
||||||
|
fail_unless (avail == 100);
|
||||||
|
timestamp = gst_adapter_prev_timestamp (adapter, &dist);
|
||||||
|
fail_unless (timestamp == 5 * GST_SECOND);
|
||||||
|
fail_unless (dist == 0);
|
||||||
|
|
||||||
|
/* remove empty buffer, timestamp still visible */
|
||||||
|
cdata = gst_adapter_peek (adapter, 50);
|
||||||
|
fail_unless (cdata != NULL);
|
||||||
|
data = gst_adapter_take (adapter, 50);
|
||||||
|
fail_unless (data != NULL);
|
||||||
|
g_free (data);
|
||||||
|
avail = gst_adapter_available (adapter);
|
||||||
|
fail_unless (avail == 50);
|
||||||
|
timestamp = gst_adapter_prev_timestamp (adapter, &dist);
|
||||||
|
fail_unless (timestamp == 5 * GST_SECOND);
|
||||||
|
fail_unless (dist == 50);
|
||||||
|
|
||||||
g_object_unref (adapter);
|
g_object_unref (adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue