diff --git a/libs/gst/base/gstadapter.c b/libs/gst/base/gstadapter.c index 4c69e4d..df5e22e 100644 --- a/libs/gst/base/gstadapter.c +++ b/libs/gst/base/gstadapter.c @@ -837,3 +837,124 @@ gst_adapter_masked_scan_uint32 (GstAdapter * adapter, guint32 mask, /* nothing found */ return -1; } + +/** + * gst_adapter_read_valist: + * @format: the format of the items to read + * + * b = byte + * w = 16 bits LE + * W = 16 bits BE + * t = 24 bits LE + * T = 24 bits BE + * i = 32 bits LE, float 32 bits LE + * I = 32 bits BE, float 32 bits BE + * q = 64 bits LE, float 64 bits LE + * Q = 64 bits BE, float 64 bits BE + * + * + */ +gint +gst_adapter_read_valist (GstAdapter * adapter, const gchar * format, + va_list varargs) +{ + GSList *g; + guint skip, bsize, i, count; + guint8 *bdata, *dest; + GstBuffer *buf; + guint dlen, start, tocopy; + gint inc; + gboolean le; + + skip = adapter->skip; + + count = 0; + + /* first step, position on the first buffer */ + if (!(g = adapter->buflist)) + goto done; + + buf = g->data; + bsize = GST_BUFFER_SIZE (buf) - skip; + bdata = GST_BUFFER_DATA (buf) + skip; + + while (TRUE) { + le = G_BYTE_ORDER == G_LITTLE_ENDIAN; + switch (format[count]) { + case 'b': + dlen = 1; + break; + case 'w': + le = !le; + case 'W': + dlen = 2; + break; + case 't': + le = !le; + case 'T': + dlen = 3; + break; + case 'i': + le = !le; + case 'I': + dlen = 4; + break; + case 'q': + le = !le; + case 'Q': + dlen = 8; + break; + default: + case '\0': + goto done; + } + if (le) { + start = dlen - 1; + inc = -1; + } else { + start = 0; + inc = 1; + } + /* get destination */ + dest = va_arg (varargs, guint8 *); + + /* now copy the data */ + do { + tocopy = MIN (bsize, dlen); + for (i = 0; i < tocopy; i++, start += inc) { + dest[start] = *bdata++; + } + bsize -= tocopy; + if (bsize == 0) { + /* go to next buffer */ + if (!(g = g_slist_next (g))) + goto done; + + buf = g->data; + bsize = GST_BUFFER_SIZE (buf); + bdata = GST_BUFFER_DATA (buf); + } + dlen -= tocopy; + if (dlen == 0) + break; + } while (TRUE); + + count++; + } + +done: + return count; +} + +gint +gst_adapter_read (GstAdapter * adapter, const gchar * format, ...) +{ + va_list varargs; + gint res; + + va_start (varargs, format); + res = gst_adapter_read_valist (adapter, format, varargs); + va_end (varargs); + + return res; +} diff --git a/libs/gst/base/gstadapter.h b/libs/gst/base/gstadapter.h index 49e408e..d6cf298 100644 --- a/libs/gst/base/gstadapter.h +++ b/libs/gst/base/gstadapter.h @@ -98,6 +98,10 @@ GstClockTime gst_adapter_prev_timestamp (GstAdapter *adapter, gu guint gst_adapter_masked_scan_uint32 (GstAdapter * adapter, guint32 mask, guint32 pattern, guint offset, guint size); +gint gst_adapter_read_valist (GstAdapter *adapter, const gchar *format, + va_list varargs); +gint gst_adapter_read (GstAdapter *adapter, const gchar *format, + ...); G_END_DECLS diff --git a/tests/check/libs/adapter.c b/tests/check/libs/adapter.c index 34cef23..d550273 100644 --- a/tests/check/libs/adapter.c +++ b/tests/check/libs/adapter.c @@ -601,6 +601,76 @@ GST_START_TEST (test_scan) GST_END_TEST; +GST_START_TEST (test_read) +{ + GstAdapter *adapter; + GstBuffer *buffer; + guint8 *data; + guint count; + guint i; + guint8 b[5]; + guint16 i16[5]; + guint32 i32[5]; + //guint64 i64[5]; + + adapter = gst_adapter_new (); + fail_unless (adapter != NULL); + + buffer = gst_buffer_new_and_alloc (100); + data = GST_BUFFER_DATA (buffer); + /* fill with pattern */ + for (i = 0; i < 100; i++) + data[i] = i; + + gst_adapter_push (adapter, buffer); + + count = gst_adapter_read (adapter, "bbbbb", &b[0], &b[1], + &b[2], &b[3], &b[4]); + fail_unless (count == 5); + for (i = 0; i < count; i++) + fail_unless (b[i] == i); + + count = gst_adapter_read (adapter, "wwwww", &i16[0], &i16[1], + &i16[2], &i16[3], &i16[4]); + fail_unless (count == 5); + fail_unless (i16[0] == 0x0100); + fail_unless (i16[1] == 0x0302); + fail_unless (i16[2] == 0x0504); + fail_unless (i16[3] == 0x0706); + fail_unless (i16[4] == 0x0908); + + count = gst_adapter_read (adapter, "WWWWW", &i16[0], &i16[1], + &i16[2], &i16[3], &i16[4]); + fail_unless (count == 5); + fail_unless (i16[0] == 0x0001); + fail_unless (i16[1] == 0x0203); + fail_unless (i16[2] == 0x0405); + fail_unless (i16[3] == 0x0607); + fail_unless (i16[4] == 0x0809); + + count = gst_adapter_read (adapter, "wWbWw", &i16[0], &i16[1], + &b[0], &i16[2], &i16[3]); + fail_unless (count == 5); + fail_unless (i16[0] == 0x0100); + fail_unless (i16[1] == 0x0203); + fail_unless (b[0] == 0x04); + fail_unless (i16[2] == 0x0506); + fail_unless (i16[3] == 0x0807); + + count = gst_adapter_read (adapter, "bWwiI", &b[0], &i16[0], + &i16[1], &i32[0], &i32[1]); + fail_unless (count == 5); + fail_unless (b[0] == 0x00); + fail_unless (i16[0] == 0x0102); + fail_unless (i16[1] == 0x0403); + fail_unless (i32[0] == 0x08070605); + fail_unless (i32[1] == 0x090a0b0c); + + g_object_unref (adapter); +} + +GST_END_TEST; + static Suite * gst_adapter_suite (void) { @@ -618,6 +688,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_read); return s; }