adapter: add function to get a list of buffers

Add a function to retrieve a list of buffers containing the first N bytes from
the adapter. This can be done without a memcpy and should make it possible to
transfer the list to a GstBufferList later.
This commit is contained in:
Wim Taymans 2010-09-17 15:51:08 +02:00
parent a144882871
commit 1afaa1680f
5 changed files with 92 additions and 0 deletions

View file

@ -205,6 +205,7 @@ gst_adapter_available
gst_adapter_available_fast
gst_adapter_take
gst_adapter_take_buffer
gst_adapter_take_list
gst_adapter_prev_timestamp
gst_adapter_masked_scan_uint32
gst_adapter_masked_scan_uint32_peek

View file

@ -708,6 +708,54 @@ done:
return buffer;
}
/**
* gst_adapter_take_list:
* @adapter: a #GstAdapter
* @nbytes: the number of bytes to take
*
* Returns a #GSList of buffers containing the first @nbytes bytes of the
* @adapter. The returned bytes will be flushed from the adapter.
* When the caller can deal with individual buffers, this function is more
* performant because no memory should be coppied.
*
* Caller owns returned list and contained buffers. gst_buffer_unref() each
* buffer in the list before freeng the list after usage.
*
* Since: 0.10.24
*
* Returns: a #GSList of buffers containing the first @nbytes of the adapter,
* or #NULL if @nbytes bytes are not available
*/
GList *
gst_adapter_take_list (GstAdapter * adapter, guint nbytes)
{
GList *result = NULL, *tail = NULL;
GstBuffer *cur;
guint hsize, skip;
g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
g_return_val_if_fail (nbytes <= adapter->size, NULL);
GST_LOG_OBJECT (adapter, "taking %u bytes", nbytes);
while (nbytes > 0) {
cur = adapter->buflist->data;
skip = adapter->skip;
hsize = MIN (nbytes, GST_BUFFER_SIZE (cur) - skip);
cur = gst_adapter_take_buffer (adapter, hsize);
if (result == NULL) {
result = tail = g_list_append (result, cur);
} else {
tail = g_list_append (tail, cur);
tail = g_list_next (tail);
}
nbytes -= hsize;
}
return result;
}
/**
* gst_adapter_available:
* @adapter: a #GstAdapter

View file

@ -90,6 +90,7 @@ void gst_adapter_copy (GstAdapter *adapter, gu
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);
GList* gst_adapter_take_list (GstAdapter *adapter, guint nbytes);
guint gst_adapter_available (GstAdapter *adapter);
guint gst_adapter_available_fast (GstAdapter *adapter);

View file

@ -728,6 +728,46 @@ GST_START_TEST (test_scan)
GST_END_TEST;
/* Fill a buffer with a sequence of 32 bit ints and read them back out
* using take_buffer, checking that they're still in the right order */
GST_START_TEST (test_take_list)
{
GstAdapter *adapter;
int i = 0;
adapter = create_and_fill_adapter ();
while (gst_adapter_available (adapter) >= sizeof (guint32)) {
GList *list, *walk;
GstBuffer *buf;
guint size;
guint8 *data;
list = gst_adapter_take_list (adapter, sizeof (guint32) * 5);
fail_unless (list != NULL);
for (walk = list; walk; walk = g_list_next (walk)) {
buf = walk->data;
data = GST_BUFFER_DATA (buf);
size = GST_BUFFER_SIZE (buf);
while (size > 0) {
fail_unless (GST_READ_UINT32_LE (data) == i);
i++;
data += sizeof (guint32);
size -= sizeof (guint32);
}
gst_buffer_unref (buf);
}
g_list_free (list);
}
fail_unless (gst_adapter_available (adapter) == 0,
"Data was left in the adapter");
g_object_unref (adapter);
}
GST_END_TEST;
static Suite *
gst_adapter_suite (void)
{
@ -745,6 +785,7 @@ gst_adapter_suite (void)
tcase_add_test (tc_chain, test_take_buf_order);
tcase_add_test (tc_chain, test_timestamp);
tcase_add_test (tc_chain, test_scan);
tcase_add_test (tc_chain, test_take_list);
return s;
}

View file

@ -13,6 +13,7 @@ EXPORTS
gst_adapter_push
gst_adapter_take
gst_adapter_take_buffer
gst_adapter_take_list
gst_base_sink_do_preroll
gst_base_sink_get_blocksize
gst_base_sink_get_last_buffer