diff --git a/docs/libs/gstreamer-libs-sections.txt b/docs/libs/gstreamer-libs-sections.txt index 4a36b480ae..003210c978 100644 --- a/docs/libs/gstreamer-libs-sections.txt +++ b/docs/libs/gstreamer-libs-sections.txt @@ -1320,6 +1320,9 @@ gst_harness_buffers_received gst_harness_buffers_in_queue gst_harness_set_drop_buffers gst_harness_dump_to_file +gst_harness_take_all_data +gst_harness_take_all_data_as_buffer +gst_harness_take_all_data_as_bytes gst_harness_get_last_pushed_timestamp gst_harness_push_event diff --git a/libs/gst/check/Makefile.am b/libs/gst/check/Makefile.am index c5d7347610..849a7072f4 100644 --- a/libs/gst/check/Makefile.am +++ b/libs/gst/check/Makefile.am @@ -169,6 +169,9 @@ LIBGSTCHECK_EXPORTED_FUNCS = \ gst_harness_stress_requestpad_start_full \ gst_harness_stress_statechange_start_full \ gst_harness_stress_thread_stop \ + gst_harness_take_all_data \ + gst_harness_take_all_data_as_buffer \ + gst_harness_take_all_data_as_bytes \ gst_harness_teardown \ gst_harness_try_pull \ gst_harness_try_pull_event \ diff --git a/libs/gst/check/gstharness.c b/libs/gst/check/gstharness.c index 0bd8d8558e..faf94cfa77 100644 --- a/libs/gst/check/gstharness.c +++ b/libs/gst/check/gstharness.c @@ -1721,6 +1721,99 @@ gst_harness_set_drop_buffers (GstHarness * h, gboolean drop_buffers) priv->drop_buffers = drop_buffers; } +/** + * gst_harness_take_all_data_as_buffer: + * @h: a #GstHarness + * + * Pulls all pending data from the harness and returns it as a single buffer. + * + * Returns: (transfer full): the data as a buffer. Unref with gst_buffer_unref() + * when no longer needed. + * + * Since: 1.14 + */ +GstBuffer * +gst_harness_take_all_data_as_buffer (GstHarness * h) +{ + GstHarnessPrivate *priv; + GstBuffer *ret, *buf; + + g_return_val_if_fail (h != NULL, NULL); + + priv = h->priv; + + g_async_queue_lock (priv->buffer_queue); + + ret = g_async_queue_try_pop_unlocked (priv->buffer_queue); + + if (ret == NULL) { + ret = gst_buffer_new (); + } else { + /* buffer appending isn't very efficient for larger numbers of buffers + * or lots of memories, but this function is not performance critical and + * we can still improve it if and when the need arises. For now KISS. */ + while ((buf = g_async_queue_try_pop_unlocked (priv->buffer_queue))) + ret = gst_buffer_append (ret, buf); + } + + g_async_queue_unlock (priv->buffer_queue); + + return ret; +} + +/** + * gst_harness_take_all_data: (skip) + * @h: a #GstHarness + * @size: (out): the size of the data in bytes + * + * Pulls all pending data from the harness and returns it as a single + * data slice. + * + * Returns: (transfer full): a pointer to the data, newly allocated. Free + * with g_free() when no longer needed. Will return %NULL if there is no + * data. + * + * Since: 1.14 + */ +guint8 * +gst_harness_take_all_data (GstHarness * h, gsize * size) +{ + GstBuffer *buf; + guint8 *data = NULL; + + g_return_val_if_fail (h != NULL, NULL); + g_return_val_if_fail (size != NULL, NULL); + + buf = gst_harness_take_all_data_as_buffer (h); + gst_buffer_extract_dup (buf, 0, -1, (gpointer *) & data, size); + gst_buffer_unref (buf); + return data; +} + +/** + * gst_harness_take_all_data_as_bytes: + * @h: a #GstHarness + * + * Pulls all pending data from the harness and returns it as a single #GBytes. + * + * Returns: (transfer full): a pointer to the data, newly allocated. Free + * with g_free() when no longer needed. + * + * Since: 1.14 + */ +GBytes * +gst_harness_take_all_data_as_bytes (GstHarness * h) +{ + guint8 *data; + gsize size = 0; + + g_return_val_if_fail (h != NULL, NULL); + + data = gst_harness_take_all_data (h, &size); + return g_bytes_new_take (data, size); +} + + /** * gst_harness_dump_to_file: * @h: a #GstHarness diff --git a/libs/gst/check/gstharness.h b/libs/gst/check/gstharness.h index 77731366bd..3c5c4dd3d2 100644 --- a/libs/gst/check/gstharness.h +++ b/libs/gst/check/gstharness.h @@ -202,6 +202,15 @@ void gst_harness_set_drop_buffers (GstHarness * h, gboolean drop_buffe GST_EXPORT void gst_harness_dump_to_file (GstHarness * h, const gchar * filename); +GST_EXPORT +guint8 * gst_harness_take_all_data (GstHarness * h, gsize * size); + +GST_EXPORT +GstBuffer * gst_harness_take_all_data_as_buffer (GstHarness * h); + +GST_EXPORT +GBytes * gst_harness_take_all_data_as_bytes (GstHarness * h); + GST_EXPORT GstClockTime gst_harness_get_last_pushed_timestamp (GstHarness * h); diff --git a/tests/check/libs/gstharness.c b/tests/check/libs/gstharness.c index 9edbaee7a8..633d538333 100644 --- a/tests/check/libs/gstharness.c +++ b/tests/check/libs/gstharness.c @@ -170,6 +170,82 @@ GST_START_TEST (test_forward_event_and_query_to_sink_harness_while_teardown) GST_END_TEST; +static GstHarness * +harness_new_and_fill_with_data (void) +{ + GstHarness *h = gst_harness_new_parse ("fakesrc num-buffers=5 " + "filltype=pattern-span sizetype=fixed sizemin=10 sizemax=10"); + gboolean have_eos = FALSE; + + gst_harness_play (h); + + do { + GstEvent *e = gst_harness_pull_event (h); + have_eos = GST_EVENT_TYPE (e) == GST_EVENT_EOS; + gst_event_unref (e); + } while (!have_eos); + + return h; +} + +GST_START_TEST (test_get_all_data) +{ + guint8 expected[50]; + const guint8 *cdata; + GstHarness *h; + GstBuffer *buf; + GBytes *bytes; + guint8 *data; + gsize size; + guint i; + + for (i = 0; i < G_N_ELEMENTS (expected); ++i) + expected[i] = i; + + h = harness_new_and_fill_with_data (); + buf = gst_harness_take_all_data_as_buffer (h); + fail_unless (buf != NULL); + fail_unless_equals_int (gst_buffer_get_size (buf), 5 * 10); + fail_unless (gst_buffer_memcmp (buf, 0, expected, 5 * 10) == 0); + gst_buffer_unref (buf); + /* There should be nothing left now. We should still get a non-NULL buffer */ + buf = gst_harness_take_all_data_as_buffer (h); + fail_unless (buf != NULL); + fail_unless_equals_int (gst_buffer_get_size (buf), 0); + gst_buffer_unref (buf); + gst_harness_teardown (h); + + h = harness_new_and_fill_with_data (); + bytes = gst_harness_take_all_data_as_bytes (h); + fail_unless (bytes != NULL); + cdata = g_bytes_get_data (bytes, &size); + fail_unless_equals_int (size, 5 * 10); + fail_unless (memcmp (cdata, expected, 50) == 0); + g_bytes_unref (bytes); + /* There should be nothing left now. We should still get a non-NULL bytes */ + bytes = gst_harness_take_all_data_as_bytes (h); + fail_unless (bytes != NULL); + cdata = g_bytes_get_data (bytes, &size); + fail_unless (cdata == NULL); + fail_unless_equals_int (size, 0); + g_bytes_unref (bytes); + gst_harness_teardown (h); + + h = harness_new_and_fill_with_data (); + data = gst_harness_take_all_data (h, &size); + fail_unless (data != NULL); + fail_unless_equals_int (size, 5 * 10); + fail_unless (memcmp (data, expected, 50) == 0); + g_free (data); + /* There should be nothing left now. */ + data = gst_harness_take_all_data (h, &size); + fail_unless (data == NULL); + fail_unless_equals_int (size, 0); + gst_harness_teardown (h); +} + +GST_END_TEST; + static Suite * gst_harness_suite (void) { @@ -185,6 +261,7 @@ gst_harness_suite (void) tcase_add_test (tc_chain, test_forward_event_and_query_to_sink_harness_while_teardown); + tcase_add_test (tc_chain, test_get_all_data); return s; }