1 /* GstHarness - A test-harness for GStreamer testing
3 * Copyright (C) 2012-2015 Pexip <pexip.com>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
23 * @short_description: A test-harness for writing GStreamer unit tests
24 * @see_also: #GstTestClock,\
26 * #GstHarness is meant to make writing unit test for GStreamer much easier.
27 * It can be thought of as a way of treating a #GstElement as a black box,
28 * deterministically feeding it data, and controlling what data it outputs.
30 * The basic structure of #GstHarness is two "floating" #GstPads that connect
31 * to the harnessed #GstElement src and sink #GstPads like so:
34 * __________________________
35 * _____ | _____ _____ | _____
37 * | src |--+-| sink| Element | src |-+--| sink|
38 * |_____| | |_____| |_____| | |_____|
39 * |__________________________|
43 * With this, you can now simulate any environment the #GstElement might find
44 * itself in. By specifying the #GstCaps of the harness #GstPads, using
45 * functions like gst_harness_set_src_caps() or gst_harness_set_sink_caps_str(),
46 * you can test how the #GstElement interacts with different caps sets.
48 * Your harnessed #GstElement can of course also be a bin, and using
49 * gst_harness_new_parse() supporting standard gst-launch syntax, you can
50 * easily test a whole pipeline instead of just one element.
52 * You can then go on to push #GstBuffers and #GstEvents on to the srcpad,
53 * using functions like gst_harness_push() and gst_harness_push_event(), and
54 * then pull them out to examine them with gst_harness_pull() and
55 * gst_harness_pull_event().
58 * <title>A simple buffer-in buffer-out example</title>
59 * <programlisting language="c">
60 * #include <gst/gst.h>
61 * #include <gst/check/gstharness.h>
66 * // attach the harness to the src and sink pad of GstQueue
67 * h = gst_harness_new ("queue");
69 * // we must specify a caps before pushing buffers
70 * gst_harness_set_src_caps_str (h, "mycaps");
72 * // create a buffer of size 42
73 * in_buf = gst_harness_create_buffer (h, 42);
75 * // push the buffer into the queue
76 * gst_harness_push (h, in_buf);
78 * // pull the buffer from the queue
79 * out_buf = gst_harness_pull (h);
81 * // validate the buffer in is the same as buffer out
82 * fail_unless (in_buf == out_buf);
85 * gst_buffer_unref (out_buf);
86 * gst_harness_teardown (h);
91 * Another main feature of the #GstHarness is its integration with the
92 * #GstTestClock. Operating the #GstTestClock can be very challenging, but
93 * #GstHarness simplifies some of the most desired actions a lot, like wanting
94 * to manually advance the clock while at the same time releasing a #GstClockID
95 * that is waiting, with functions like gst_harness_crank_single_clock_wait().
97 * #GstHarness also supports sub-harnesses, as a way of generating and
98 * validating data. A sub-harness is another #GstHarness that is managed by
99 * the "parent" harness, and can either be created by using the standard
100 * gst_harness_new type functions directly on the (GstHarness *)->src_harness,
101 * or using the much more convenient gst_harness_add_src() or
102 * gst_harness_add_sink_parse(). If you have a decoder-element you want to test,
103 * (like vp8dec) it can be very useful to add a src-harness with both a
104 * src-element (videotestsrc) and an encoder (vp8enc) to feed the decoder data
105 * with different configurations, by simply doing:
108 * <programlisting language="c">
109 * GstHarness * h = gst_harness_new (h, "vp8dec");
110 * gst_harness_add_src_parse (h, "videotestsrc is-live=1 ! vp8enc", TRUE);
114 * and then feeding it data with:
117 * <programlisting language="c">
118 * gst_harness_push_from_src (h);
127 /* we have code with side effects in asserts, so make sure they are active */
128 #ifdef G_DISABLE_ASSERT
129 #error "GstHarness must be compiled with G_DISABLE_ASSERT undefined"
132 #include "gstharness.h"
138 static void gst_harness_stress_free (GstHarnessThread * t);
140 #define HARNESS_KEY "harness"
141 #define HARNESS_REF "harness-ref"
142 #define HARNESS_LOCK(h) g_mutex_lock (&(h)->priv->priv_mutex)
143 #define HARNESS_UNLOCK(h) g_mutex_unlock (&(h)->priv->priv_mutex)
145 static GstStaticPadTemplate hsrctemplate = GST_STATIC_PAD_TEMPLATE ("src",
148 GST_STATIC_CAPS_ANY);
149 static GstStaticPadTemplate hsinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
152 GST_STATIC_CAPS_ANY);
154 struct _GstHarnessPrivate
156 gchar *element_sinkpad_name;
157 gchar *element_srcpad_name;
163 GstPad *sink_forward_pad;
164 GstTestClock *testclock;
166 volatile gint recv_buffers;
167 volatile gint recv_events;
168 volatile gint recv_upstream_events;
170 GAsyncQueue *buffer_queue;
171 GAsyncQueue *src_event_queue;
172 GAsyncQueue *sink_event_queue;
174 GstClockTime latency_min;
175 GstClockTime latency_max;
176 gboolean has_clock_wait;
177 gboolean drop_buffers;
178 GstClockTime last_push_ts;
181 GstAllocator *allocator;
182 GstAllocationParams allocation_params;
183 GstAllocator *propose_allocator;
184 GstAllocationParams propose_allocation_params;
186 gboolean blocking_push_mode;
187 GCond blocking_push_cond;
188 GMutex blocking_push_mutex;
195 gst_harness_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
197 GstHarness *h = g_object_get_data (G_OBJECT (pad), HARNESS_KEY);
198 GstHarnessPrivate *priv = h->priv;
200 g_assert (h != NULL);
201 g_mutex_lock (&priv->blocking_push_mutex);
202 g_atomic_int_inc (&priv->recv_buffers);
204 if (priv->drop_buffers)
205 gst_buffer_unref (buffer);
207 g_async_queue_push (priv->buffer_queue, buffer);
209 if (priv->blocking_push_mode) {
210 g_cond_wait (&priv->blocking_push_cond, &priv->blocking_push_mutex);
212 g_mutex_unlock (&priv->blocking_push_mutex);
218 gst_harness_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
220 GstHarness *h = g_object_get_data (G_OBJECT (pad), HARNESS_KEY);
221 GstHarnessPrivate *priv = h->priv;
223 g_assert (h != NULL);
224 g_atomic_int_inc (&priv->recv_upstream_events);
225 g_async_queue_push (priv->src_event_queue, event);
230 gst_harness_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
232 GstHarness *h = g_object_get_data (G_OBJECT (pad), HARNESS_KEY);
233 GstHarnessPrivate *priv = h->priv;
237 g_assert (h != NULL);
239 g_atomic_int_inc (&priv->recv_events);
241 switch (GST_EVENT_TYPE (event)) {
242 case GST_EVENT_STREAM_START:
244 case GST_EVENT_SEGMENT:
253 if (priv->forwarding && forward && priv->sink_forward_pad) {
254 GstPad *fwdpad = gst_object_ref (priv->sink_forward_pad);
256 ret = gst_pad_push_event (fwdpad, event);
257 gst_object_unref (fwdpad);
260 g_async_queue_push (priv->sink_event_queue, event);
268 gst_harness_decide_allocation (GstHarness * h, GstCaps * caps)
270 GstHarnessPrivate *priv = h->priv;
272 GstAllocator *allocator;
273 GstAllocationParams params;
274 GstBufferPool *pool = NULL;
275 guint size, min, max;
277 query = gst_query_new_allocation (caps, FALSE);
278 gst_pad_peer_query (h->srcpad, query);
280 if (gst_query_get_n_allocation_params (query) > 0) {
281 gst_query_parse_nth_allocation_param (query, 0, &allocator, ¶ms);
284 gst_allocation_params_init (¶ms);
287 if (gst_query_get_n_allocation_pools (query) > 0) {
288 gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
290 /* Most elements create their own pools if pool == NULL. Not sure if we
291 * want to do that in the harness since we may want to test the pool
292 * implementation of the elements. Not creating a pool will however ignore
293 * the returned size. */
295 pool = gst_buffer_pool_new ();
299 size = min = max = 0;
301 gst_query_unref (query);
304 GstStructure *config = gst_buffer_pool_get_config (pool);
305 gst_buffer_pool_config_set_params (config, caps, size, min, max);
306 gst_buffer_pool_config_set_allocator (config, allocator, ¶ms);
307 gst_buffer_pool_set_config (pool, config);
310 if (pool != priv->pool) {
311 if (priv->pool != NULL)
312 gst_buffer_pool_set_active (priv->pool, FALSE);
314 gst_buffer_pool_set_active (pool, TRUE);
317 priv->allocation_params = params;
319 gst_object_unref (priv->allocator);
320 priv->allocator = allocator;
322 gst_object_unref (priv->pool);
327 gst_harness_negotiate (GstHarness * h)
331 caps = gst_pad_get_current_caps (h->srcpad);
333 gst_harness_decide_allocation (h, caps);
334 gst_caps_unref (caps);
336 GST_FIXME_OBJECT (h, "Cannot negotiate allocation because caps is not set");
341 gst_harness_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
343 GstHarness *h = g_object_get_data (G_OBJECT (pad), HARNESS_KEY);
344 GstHarnessPrivate *priv = h->priv;
346 g_assert (h != NULL);
348 // FIXME: forward all queries?
350 switch (GST_QUERY_TYPE (query)) {
351 case GST_QUERY_LATENCY:
352 gst_query_set_latency (query, TRUE, priv->latency_min, priv->latency_max);
356 GstCaps *caps, *filter = NULL;
358 if (priv->sink_caps) {
359 caps = gst_caps_ref (priv->sink_caps);
361 caps = gst_pad_get_pad_template_caps (pad);
364 gst_query_parse_caps (query, &filter);
365 if (filter != NULL) {
366 gst_caps_take (&caps,
367 gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST));
370 gst_query_set_caps_result (query, caps);
371 gst_caps_unref (caps);
374 case GST_QUERY_ALLOCATION:
377 if (priv->forwarding && priv->sink_forward_pad != NULL) {
378 GstPad *peer = gst_pad_get_peer (priv->sink_forward_pad);
379 g_assert (peer != NULL);
381 res = gst_pad_query (peer, query);
382 gst_object_unref (peer);
389 gst_query_parse_allocation (query, &caps, &need_pool);
391 /* FIXME: Can this be removed? */
392 size = gst_query_get_n_allocation_params (query);
393 g_assert_cmpuint (0, ==, size);
394 gst_query_add_allocation_param (query,
395 priv->propose_allocator, &priv->propose_allocation_params);
397 GST_DEBUG_OBJECT (pad, "proposing allocation %" GST_PTR_FORMAT,
398 priv->propose_allocator);
404 res = gst_pad_query_default (pad, parent, query);
411 gst_harness_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
413 GstHarness *h = g_object_get_data (G_OBJECT (pad), HARNESS_KEY);
414 GstHarnessPrivate *priv = h->priv;
416 g_assert (h != NULL);
418 switch (GST_QUERY_TYPE (query)) {
419 case GST_QUERY_LATENCY:
420 gst_query_set_latency (query, TRUE, priv->latency_min, priv->latency_max);
424 GstCaps *caps, *filter = NULL;
426 if (priv->src_caps) {
427 caps = gst_caps_ref (priv->src_caps);
429 caps = gst_pad_get_pad_template_caps (pad);
432 gst_query_parse_caps (query, &filter);
433 if (filter != NULL) {
434 gst_caps_take (&caps,
435 gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST));
438 gst_query_set_caps_result (query, caps);
439 gst_caps_unref (caps);
443 res = gst_pad_query_default (pad, parent, query);
449 gst_harness_element_ref (GstHarness * h)
453 GST_OBJECT_LOCK (h->element);
454 data = g_object_get_data (G_OBJECT (h->element), HARNESS_REF);
456 data = g_new0 (guint, 1);
458 g_object_set_data_full (G_OBJECT (h->element), HARNESS_REF, data, g_free);
462 GST_OBJECT_UNLOCK (h->element);
466 gst_harness_element_unref (GstHarness * h)
471 GST_OBJECT_LOCK (h->element);
472 data = g_object_get_data (G_OBJECT (h->element), HARNESS_REF);
473 g_assert (data != NULL);
476 GST_OBJECT_UNLOCK (h->element);
482 gst_harness_link_element_srcpad (GstHarness * h,
483 const gchar * element_srcpad_name)
485 GstHarnessPrivate *priv = h->priv;
486 GstPad *srcpad = gst_element_get_static_pad (h->element,
487 element_srcpad_name);
488 GstPadLinkReturn link;
490 srcpad = gst_element_get_request_pad (h->element, element_srcpad_name);
492 link = gst_pad_link (srcpad, h->sinkpad);
493 g_assert_cmpint (link, ==, GST_PAD_LINK_OK);
494 g_free (priv->element_srcpad_name);
495 priv->element_srcpad_name = gst_pad_get_name (srcpad);
497 gst_object_unref (srcpad);
501 gst_harness_link_element_sinkpad (GstHarness * h,
502 const gchar * element_sinkpad_name)
504 GstHarnessPrivate *priv = h->priv;
505 GstPad *sinkpad = gst_element_get_static_pad (h->element,
506 element_sinkpad_name);
507 GstPadLinkReturn link;
509 sinkpad = gst_element_get_request_pad (h->element, element_sinkpad_name);
511 link = gst_pad_link (h->srcpad, sinkpad);
512 g_assert_cmpint (link, ==, GST_PAD_LINK_OK);
513 g_free (priv->element_sinkpad_name);
514 priv->element_sinkpad_name = gst_pad_get_name (sinkpad);
516 gst_object_unref (sinkpad);
520 gst_harness_setup_src_pad (GstHarness * h,
521 GstStaticPadTemplate * src_tmpl, const gchar * element_sinkpad_name)
523 GstHarnessPrivate *priv = h->priv;
525 g_assert (h->srcpad == NULL);
527 priv->src_event_queue =
528 g_async_queue_new_full ((GDestroyNotify) gst_event_unref);
531 h->srcpad = gst_pad_new_from_static_template (src_tmpl, "src");
532 g_assert (h->srcpad);
533 g_object_set_data (G_OBJECT (h->srcpad), HARNESS_KEY, h);
535 gst_pad_set_query_function (h->srcpad, gst_harness_src_query);
536 gst_pad_set_event_function (h->srcpad, gst_harness_src_event);
538 gst_pad_set_active (h->srcpad, TRUE);
540 if (element_sinkpad_name)
541 gst_harness_link_element_sinkpad (h, element_sinkpad_name);
545 gst_harness_setup_sink_pad (GstHarness * h,
546 GstStaticPadTemplate * sink_tmpl, const gchar * element_srcpad_name)
548 GstHarnessPrivate *priv = h->priv;
549 g_assert (sink_tmpl);
550 g_assert (h->sinkpad == NULL);
552 priv->buffer_queue = g_async_queue_new_full (
553 (GDestroyNotify) gst_buffer_unref);
554 priv->sink_event_queue = g_async_queue_new_full (
555 (GDestroyNotify) gst_event_unref);
558 h->sinkpad = gst_pad_new_from_static_template (sink_tmpl, "sink");
559 g_assert (h->sinkpad);
560 g_object_set_data (G_OBJECT (h->sinkpad), HARNESS_KEY, h);
562 gst_pad_set_chain_function (h->sinkpad, gst_harness_chain);
563 gst_pad_set_query_function (h->sinkpad, gst_harness_sink_query);
564 gst_pad_set_event_function (h->sinkpad, gst_harness_sink_event);
566 gst_pad_set_active (h->sinkpad, TRUE);
568 if (element_srcpad_name)
569 gst_harness_link_element_srcpad (h, element_srcpad_name);
573 check_element_type (GstElement * element, gboolean * has_sinkpad,
574 gboolean * has_srcpad)
576 GstElementClass *element_class = GST_ELEMENT_GET_CLASS (element);
577 const GList *tmpl_list;
579 *has_srcpad = element->numsrcpads > 0;
580 *has_sinkpad = element->numsinkpads > 0;
582 tmpl_list = gst_element_class_get_pad_template_list (element_class);
585 GstPadTemplate *pad_tmpl = (GstPadTemplate *) tmpl_list->data;
586 tmpl_list = g_list_next (tmpl_list);
587 if (GST_PAD_TEMPLATE_DIRECTION (pad_tmpl) == GST_PAD_SRC)
589 if (GST_PAD_TEMPLATE_DIRECTION (pad_tmpl) == GST_PAD_SINK)
590 *has_sinkpad |= TRUE;
595 turn_async_and_sync_off (GstElement * element)
597 GObjectClass *class = G_OBJECT_GET_CLASS (element);
598 if (g_object_class_find_property (class, "async"))
599 g_object_set (element, "async", FALSE, NULL);
600 if (g_object_class_find_property (class, "sync"))
601 g_object_set (element, "sync", FALSE, NULL);
605 gst_pad_is_request_pad (GstPad * pad)
607 GstPadTemplate *temp;
612 temp = gst_pad_get_pad_template (pad);
615 is_request = GST_PAD_TEMPLATE_PRESENCE (temp) == GST_PAD_REQUEST;
616 gst_object_unref (temp);
621 * gst_harness_new_empty: (skip)
623 * Creates a new empty harness. Use gst_harness_add_element_full() to add
624 * an #GstElement to it.
628 * Returns: (transfer full): a #GstHarness, or %NULL if the harness could
634 gst_harness_new_empty (void)
637 GstHarnessPrivate *priv;
639 h = g_new0 (GstHarness, 1);
640 g_assert (h != NULL);
641 h->priv = g_new0 (GstHarnessPrivate, 1);
644 GST_DEBUG_OBJECT (h, "about to create new harness %p", h);
645 priv->last_push_ts = GST_CLOCK_TIME_NONE;
646 priv->latency_min = 0;
647 priv->latency_max = GST_CLOCK_TIME_NONE;
648 priv->drop_buffers = FALSE;
649 priv->testclock = GST_TEST_CLOCK_CAST (gst_test_clock_new ());
651 priv->propose_allocator = NULL;
652 gst_allocation_params_init (&priv->propose_allocation_params);
654 g_mutex_init (&priv->blocking_push_mutex);
655 g_cond_init (&priv->blocking_push_cond);
656 g_mutex_init (&priv->priv_mutex);
658 priv->stress = g_ptr_array_new_with_free_func (
659 (GDestroyNotify) gst_harness_stress_free);
661 /* we have forwarding on as a default */
662 gst_harness_set_forwarding (h, TRUE);
668 * gst_harness_add_element_full: (skip)
670 * @element: a #GstElement to add to the harness (transfer none)
671 * @hsrc: (allow-none): a #GstStaticPadTemplate describing the harness srcpad.
672 * %NULL will not create a harness srcpad.
673 * @element_sinkpad_name: (allow-none): a #gchar with the name of the element
674 * sinkpad that is then linked to the harness srcpad. Can be a static or request
675 * or a sometimes pad that has been added. %NULL will not get/request a sinkpad
676 * from the element. (Like if the element is a src.)
677 * @hsink: (allow-none): a #GstStaticPadTemplate describing the harness sinkpad.
678 * %NULL will not create a harness sinkpad.
679 * @element_srcpad_name: (allow-none): a #gchar with the name of the element
680 * srcpad that is then linked to the harness sinkpad, similar to the
681 * @element_sinkpad_name.
683 * Adds a #GstElement to an empty #GstHarness
690 gst_harness_add_element_full (GstHarness * h, GstElement * element,
691 GstStaticPadTemplate * hsrc, const gchar * element_sinkpad_name,
692 GstStaticPadTemplate * hsink, const gchar * element_srcpad_name)
694 gboolean has_sinkpad, has_srcpad;
696 g_return_if_fail (element != NULL);
697 g_return_if_fail (h->element == NULL);
699 h->element = gst_object_ref (element);
700 check_element_type (element, &has_sinkpad, &has_srcpad);
702 /* setup the loose srcpad linked to the element sinkpad */
704 gst_harness_setup_src_pad (h, hsrc, element_sinkpad_name);
706 /* setup the loose sinkpad linked to the element srcpad */
708 gst_harness_setup_sink_pad (h, hsink, element_srcpad_name);
710 /* as a harness sink, we should not need sync and async */
711 if (has_sinkpad && !has_srcpad)
712 turn_async_and_sync_off (h->element);
714 if (h->srcpad != NULL) {
716 gchar *stream_id = g_strdup_printf ("%s-%p",
717 GST_OBJECT_NAME (h->element), h);
718 handled = gst_pad_push_event (h->srcpad,
719 gst_event_new_stream_start (stream_id));
724 /* don't start sources, they start producing data! */
726 gst_harness_play (h);
728 /* if the element already has a testclock attached, we replace our own with it */
729 if (GST_ELEMENT_CLOCK (element)
730 && GST_IS_TEST_CLOCK (GST_ELEMENT_CLOCK (element))) {
731 gst_object_replace ((GstObject **) & h->priv->testclock,
732 (GstObject *) GST_ELEMENT_CLOCK (element));
735 gst_harness_element_ref (h);
737 GST_DEBUG_OBJECT (h, "added element to harness %p "
738 "with element_srcpad_name (%p, %s, %s) and element_sinkpad_name (%p, %s, %s)",
739 h, h->srcpad, GST_DEBUG_PAD_NAME (h->srcpad),
740 h->sinkpad, GST_DEBUG_PAD_NAME (h->sinkpad));
744 * gst_harness_new_full: (skip)
745 * @element: a #GstElement to attach the harness to (transfer none)
746 * @hsrc: (allow-none): a #GstStaticPadTemplate describing the harness srcpad.
747 * %NULL will not create a harness srcpad.
748 * @element_sinkpad_name: (allow-none): a #gchar with the name of the element
749 * sinkpad that is then linked to the harness srcpad. Can be a static or request
750 * or a sometimes pad that has been added. %NULL will not get/request a sinkpad
751 * from the element. (Like if the element is a src.)
752 * @hsink: (allow-none): a #GstStaticPadTemplate describing the harness sinkpad.
753 * %NULL will not create a harness sinkpad.
754 * @element_srcpad_name: (allow-none): a #gchar with the name of the element
755 * srcpad that is then linked to the harness sinkpad, similar to the
756 * @element_sinkpad_name.
758 * Creates a new harness.
762 * Returns: (transfer full): a #GstHarness, or %NULL if the harness could
768 gst_harness_new_full (GstElement * element,
769 GstStaticPadTemplate * hsrc, const gchar * element_sinkpad_name,
770 GstStaticPadTemplate * hsink, const gchar * element_srcpad_name)
773 h = gst_harness_new_empty ();
774 gst_harness_add_element_full (h, element,
775 hsrc, element_sinkpad_name, hsink, element_srcpad_name);
780 * gst_harness_new_with_element: (skip)
781 * @element: a #GstElement to attach the harness to (transfer none)
782 * @element_sinkpad_name: (allow-none): a #gchar with the name of the element
783 * sinkpad that is then linked to the harness srcpad. %NULL does not attach a
785 * @element_srcpad_name: (allow-none): a #gchar with the name of the element
786 * srcpad that is then linked to the harness sinkpad. %NULL does not attach a
789 * Creates a new harness. Works in the same way as gst_harness_new_full(), only
790 * that generic padtemplates are used for the harness src and sinkpads, which
791 * will be sufficient in most usecases.
795 * Returns: (transfer full): a #GstHarness, or %NULL if the harness could
801 gst_harness_new_with_element (GstElement * element,
802 const gchar * element_sinkpad_name, const gchar * element_srcpad_name)
804 return gst_harness_new_full (element,
805 &hsrctemplate, element_sinkpad_name, &hsinktemplate, element_srcpad_name);
809 * gst_harness_new_with_padnames: (skip)
810 * @element_name: a #gchar describing the #GstElement name
811 * @element_sinkpad_name: (allow-none): a #gchar with the name of the element
812 * sinkpad that is then linked to the harness srcpad. %NULL does not attach a
814 * @element_srcpad_name: (allow-none): a #gchar with the name of the element
815 * srcpad that is then linked to the harness sinkpad. %NULL does not attach a
818 * Creates a new harness. Works like gst_harness_new_with_element(),
819 * except you specify the factoryname of the #GstElement
823 * Returns: (transfer full): a #GstHarness, or %NULL if the harness could
829 gst_harness_new_with_padnames (const gchar * element_name,
830 const gchar * element_sinkpad_name, const gchar * element_srcpad_name)
833 GstElement *element = gst_element_factory_make (element_name, NULL);
834 g_assert (element != NULL);
836 h = gst_harness_new_with_element (element, element_sinkpad_name,
837 element_srcpad_name);
838 gst_object_unref (element);
843 * gst_harness_new_with_templates: (skip)
844 * @element_name: a #gchar describing the #GstElement name
845 * @hsrc: (allow-none): a #GstStaticPadTemplate describing the harness srcpad.
846 * %NULL will not create a harness srcpad.
847 * @hsink: (allow-none): a #GstStaticPadTemplate describing the harness sinkpad.
848 * %NULL will not create a harness sinkpad.
850 * Creates a new harness, like gst_harness_new_full(), except it
851 * assumes the #GstElement sinkpad is named "sink" and srcpad is named "src"
855 * Returns: (transfer full): a #GstHarness, or %NULL if the harness could
861 gst_harness_new_with_templates (const gchar * element_name,
862 GstStaticPadTemplate * hsrc, GstStaticPadTemplate * hsink)
865 GstElement *element = gst_element_factory_make (element_name, NULL);
866 g_assert (element != NULL);
868 h = gst_harness_new_full (element, hsrc, "sink", hsink, "src");
869 gst_object_unref (element);
874 * gst_harness_new: (skip)
875 * @element_name: a #gchar describing the #GstElement name
877 * Creates a new harness. Works like gst_harness_new_with_padnames(), except it
878 * assumes the #GstElement sinkpad is named "sink" and srcpad is named "src"
882 * Returns: (transfer full): a #GstHarness, or %NULL if the harness could
888 gst_harness_new (const gchar * element_name)
890 return gst_harness_new_with_padnames (element_name, "sink", "src");
894 * gst_harness_add_parse: (skip)
896 * @launchline: a #gchar describing a gst-launch type line
898 * Parses the @launchline and puts that in a #GstBin,
899 * and then attches the supplied #GstHarness to the bin.
906 gst_harness_add_parse (GstHarness * h, const gchar * launchline)
912 gboolean done = FALSE;
914 g_return_if_fail (launchline != NULL);
916 desc = g_strdup_printf ("bin.( %s )", launchline);
918 (GstBin *) gst_parse_launch_full (desc, NULL, GST_PARSE_FLAG_NONE, NULL);
921 if (G_UNLIKELY (bin == NULL))
924 /* find pads and ghost them if necessary */
925 if ((pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SRC)) != NULL) {
926 gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("src", pad));
927 gst_object_unref (pad);
929 if ((pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SINK)) != NULL) {
930 gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("sink", pad));
931 gst_object_unref (pad);
934 iter = gst_bin_iterate_sinks (bin);
936 GValue item = { 0, };
938 switch (gst_iterator_next (iter, &item)) {
939 case GST_ITERATOR_OK:
940 turn_async_and_sync_off (GST_ELEMENT (g_value_get_object (&item)));
941 g_value_reset (&item);
943 case GST_ITERATOR_DONE:
946 case GST_ITERATOR_RESYNC:
947 gst_iterator_resync (iter);
949 case GST_ITERATOR_ERROR:
950 gst_object_unref (bin);
951 gst_iterator_free (iter);
952 g_return_if_reached ();
956 gst_iterator_free (iter);
958 gst_harness_add_element_full (h, GST_ELEMENT_CAST (bin),
959 &hsrctemplate, "sink", &hsinktemplate, "src");
960 gst_object_unref (bin);
964 * gst_harness_new_parse: (skip)
965 * @launchline: a #gchar describing a gst-launch type line
967 * Creates a new harness, parsing the @launchline and putting that in a #GstBin,
968 * and then attches the harness to the bin.
972 * Returns: (transfer full): a #GstHarness, or %NULL if the harness could
978 gst_harness_new_parse (const gchar * launchline)
981 h = gst_harness_new_empty ();
982 gst_harness_add_parse (h, launchline);
987 * gst_harness_teardown:
990 * Tears down a @GstHarness, freeing all resources allocated using it.
997 gst_harness_teardown (GstHarness * h)
999 GstHarnessPrivate *priv = h->priv;
1001 if (priv->blocking_push_mode) {
1002 g_mutex_lock (&priv->blocking_push_mutex);
1003 priv->blocking_push_mode = FALSE;
1004 g_cond_signal (&priv->blocking_push_cond);
1005 g_mutex_unlock (&priv->blocking_push_mutex);
1008 if (h->src_harness) {
1009 gst_harness_teardown (h->src_harness);
1012 gst_object_replace ((GstObject **) & priv->sink_forward_pad, NULL);
1013 if (h->sink_harness) {
1014 gst_harness_teardown (h->sink_harness);
1018 gst_caps_unref (priv->src_caps);
1020 if (priv->sink_caps)
1021 gst_caps_unref (priv->sink_caps);
1024 if (gst_pad_is_request_pad (GST_PAD_PEER (h->srcpad)))
1025 gst_element_release_request_pad (h->element, GST_PAD_PEER (h->srcpad));
1026 g_free (priv->element_sinkpad_name);
1028 gst_pad_set_active (h->srcpad, FALSE);
1029 gst_object_unref (h->srcpad);
1031 g_async_queue_unref (priv->src_event_queue);
1035 if (gst_pad_is_request_pad (GST_PAD_PEER (h->sinkpad)))
1036 gst_element_release_request_pad (h->element, GST_PAD_PEER (h->sinkpad));
1037 g_free (priv->element_srcpad_name);
1039 gst_pad_set_active (h->sinkpad, FALSE);
1040 gst_object_unref (h->sinkpad);
1042 g_async_queue_unref (priv->buffer_queue);
1043 g_async_queue_unref (priv->sink_event_queue);
1046 gst_object_replace ((GstObject **) & priv->propose_allocator, NULL);
1047 gst_object_replace ((GstObject **) & priv->allocator, NULL);
1048 gst_object_replace ((GstObject **) & priv->pool, NULL);
1050 /* if we hold the last ref, set to NULL */
1051 if (gst_harness_element_unref (h) == 0) {
1052 gboolean state_change;
1053 GstState state, pending;
1054 state_change = gst_element_set_state (h->element, GST_STATE_NULL);
1055 g_assert (state_change == GST_STATE_CHANGE_SUCCESS);
1056 state_change = gst_element_get_state (h->element, &state, &pending, 0);
1057 g_assert (state_change == GST_STATE_CHANGE_SUCCESS);
1058 g_assert (state == GST_STATE_NULL);
1061 g_cond_clear (&priv->blocking_push_cond);
1062 g_mutex_clear (&priv->blocking_push_mutex);
1063 g_mutex_clear (&priv->priv_mutex);
1065 g_ptr_array_unref (priv->stress);
1067 gst_object_unref (h->element);
1069 gst_object_replace ((GstObject **) & priv->testclock, NULL);
1076 * gst_harness_add_element_src_pad:
1078 * @srcpad: a #GstPad to link to the harness sinkpad
1080 * Links the specifed #GstPad the @GstHarness sinkpad. This can be useful if
1081 * perhaps the srcpad did not exist at the time of creating the harness,
1082 * like a demuxer that provides a sometimes-pad after receiving data.
1089 gst_harness_add_element_src_pad (GstHarness * h, GstPad * srcpad)
1091 GstHarnessPrivate *priv = h->priv;
1092 GstPadLinkReturn link;
1093 if (h->sinkpad == NULL)
1094 gst_harness_setup_sink_pad (h, &hsinktemplate, NULL);
1095 link = gst_pad_link (srcpad, h->sinkpad);
1096 g_assert_cmpint (link, ==, GST_PAD_LINK_OK);
1097 g_free (priv->element_srcpad_name);
1098 priv->element_srcpad_name = gst_pad_get_name (srcpad);
1102 * gst_harness_add_element_sink_pad:
1104 * @sinkpad: a #GstPad to link to the harness srcpad
1106 * Links the specifed #GstPad the @GstHarness srcpad.
1113 gst_harness_add_element_sink_pad (GstHarness * h, GstPad * sinkpad)
1115 GstHarnessPrivate *priv = h->priv;
1116 GstPadLinkReturn link;
1117 if (h->srcpad == NULL)
1118 gst_harness_setup_src_pad (h, &hsrctemplate, NULL);
1119 link = gst_pad_link (h->srcpad, sinkpad);
1120 g_assert_cmpint (link, ==, GST_PAD_LINK_OK);
1121 g_free (priv->element_sinkpad_name);
1122 priv->element_sinkpad_name = gst_pad_get_name (sinkpad);
1126 * gst_harness_set_src_caps:
1128 * @caps: (transfer full): a #GstCaps to set on the harness srcpad
1130 * Sets the @GstHarness srcpad caps. This must be done before any buffers
1131 * can legally be pushed from the harness to the element.
1138 gst_harness_set_src_caps (GstHarness * h, GstCaps * caps)
1140 GstHarnessPrivate *priv = h->priv;
1144 handled = gst_pad_push_event (h->srcpad, gst_event_new_caps (caps));
1146 gst_caps_take (&priv->src_caps, caps);
1148 gst_segment_init (&segment, GST_FORMAT_TIME);
1149 handled = gst_pad_push_event (h->srcpad, gst_event_new_segment (&segment));
1153 * gst_harness_set_sink_caps:
1155 * @caps: (transfer full): a #GstCaps to set on the harness sinkpad
1157 * Sets the @GstHarness sinkpad caps.
1164 gst_harness_set_sink_caps (GstHarness * h, GstCaps * caps)
1166 GstHarnessPrivate *priv = h->priv;
1168 gst_caps_take (&priv->sink_caps, caps);
1169 gst_pad_push_event (h->sinkpad, gst_event_new_reconfigure ());
1173 * gst_harness_set_caps:
1175 * @in: (transfer full): a #GstCaps to set on the harness srcpad
1176 * @out: (transfer full): a #GstCaps to set on the harness sinkpad
1178 * Sets the @GstHarness srcpad and sinkpad caps.
1185 gst_harness_set_caps (GstHarness * h, GstCaps * in, GstCaps * out)
1187 gst_harness_set_sink_caps (h, out);
1188 gst_harness_set_src_caps (h, in);
1192 * gst_harness_set_src_caps_str:
1194 * @str: a @gchar describing a #GstCaps to set on the harness srcpad
1196 * Sets the @GstHarness srcpad caps using a string. This must be done before
1197 * any buffers can legally be pushed from the harness to the element.
1204 gst_harness_set_src_caps_str (GstHarness * h, const gchar * str)
1206 gst_harness_set_src_caps (h, gst_caps_from_string (str));
1210 * gst_harness_set_sink_caps_str:
1212 * @str: a @gchar describing a #GstCaps to set on the harness sinkpad
1214 * Sets the @GstHarness sinkpad caps using a string.
1221 gst_harness_set_sink_caps_str (GstHarness * h, const gchar * str)
1223 gst_harness_set_sink_caps (h, gst_caps_from_string (str));
1227 * gst_harness_set_caps_str:
1229 * @in: a @gchar describing a #GstCaps to set on the harness srcpad
1230 * @out: a @gchar describing a #GstCaps to set on the harness sinkpad
1232 * Sets the @GstHarness srcpad and sinkpad caps using strings.
1239 gst_harness_set_caps_str (GstHarness * h, const gchar * in, const gchar * out)
1241 gst_harness_set_sink_caps_str (h, out);
1242 gst_harness_set_src_caps_str (h, in);
1246 * gst_harness_use_systemclock:
1249 * Sets the system #GstClock on the @GstHarness #GstElement
1256 gst_harness_use_systemclock (GstHarness * h)
1258 GstClock *clock = gst_system_clock_obtain ();
1259 g_assert (clock != NULL);
1260 gst_element_set_clock (h->element, clock);
1261 gst_object_unref (clock);
1265 * gst_harness_use_testclock:
1268 * Sets the #GstTestClock on the #GstHarness #GstElement
1275 gst_harness_use_testclock (GstHarness * h)
1277 gst_element_set_clock (h->element, GST_CLOCK_CAST (h->priv->testclock));
1281 * gst_harness_get_testclock:
1284 * Get the #GstTestClock. Useful if specific operations on the testclock is
1289 * Returns: (transfer full): a #GstTestClock, or %NULL if the testclock is not
1295 gst_harness_get_testclock (GstHarness * h)
1297 return gst_object_ref (h->priv->testclock);
1301 * gst_harness_set_time:
1303 * @time: a #GstClockTime to advance the clock to
1305 * Advance the #GstTestClock to a specific time.
1309 * Returns: a @gboolean %TRUE if the time could be set. %FALSE if not.
1314 gst_harness_set_time (GstHarness * h, GstClockTime time)
1316 gst_test_clock_set_time (h->priv->testclock, time);
1321 * gst_harness_wait_for_clock_id_waits:
1323 * @waits: a #guint describing the numbers of #GstClockID registered with
1325 * @timeout: a #guint describing how many seconds to wait for @waits to be true
1327 * Waits for @timeout seconds until @waits number of #GstClockID waits is
1328 * registered with the #GstTestClock. Useful for writing deterministic tests,
1329 * where you want to make sure that an expected number of waits have been
1334 * Returns: a @gboolean %TRUE if the waits have been registered, %FALSE if not.
1335 * (Could be that it timed out waiting or that more waits then waits was found)
1340 gst_harness_wait_for_clock_id_waits (GstHarness * h, guint waits, guint timeout)
1342 GstTestClock *testclock = h->priv->testclock;
1346 start_time = g_get_monotonic_time ();
1347 while (gst_test_clock_peek_id_count (testclock) < waits) {
1350 g_usleep (G_USEC_PER_SEC / 1000);
1351 time_spent = g_get_monotonic_time () - start_time;
1352 if ((time_spent / G_USEC_PER_SEC) > timeout)
1356 ret = (waits == gst_test_clock_peek_id_count (testclock));
1362 * gst_harness_crank_single_clock_wait:
1365 * A "crank" consists of three steps:
1366 * 1: Wait for a #GstClockID to be registered with the #GstTestClock.
1367 * 2: Advance the #GstTestClock to the time the #GstClockID is waiting for.
1368 * 3: Release the #GstClockID wait.
1369 * Together, this provides an easy way to not have to think about the details
1370 * around clocks and time, but still being able to write deterministic tests
1371 * that are dependant on this. A "crank" can be though of as the notion of
1372 * manually driving the clock forward to its next logical step.
1376 * Returns: a @gboolean %TRUE if the "crank" was successful, %FALSE if not.
1381 gst_harness_crank_single_clock_wait (GstHarness * h)
1383 return gst_test_clock_crank (h->priv->testclock);
1387 * gst_harness_crank_multiple_clock_waits:
1389 * @waits: a #guint describing the number of #GstClockIDs to crank
1391 * Similar to gst_harness_crank_single_clock_wait(), this is the function to use
1392 * if your harnessed element(s) are using more then one gst_clock_id_wait.
1393 * Failing to do so can (and will) make it racy which #GstClockID you actually
1394 * are releasing, where as this function will process all the waits at the
1395 * same time, ensuring that one thread can't register another wait before
1396 * both are released.
1400 * Returns: a @gboolean %TRUE if the "crank" was successful, %FALSE if not.
1405 gst_harness_crank_multiple_clock_waits (GstHarness * h, guint waits)
1407 GstTestClock *testclock = h->priv->testclock;
1411 gst_test_clock_wait_for_multiple_pending_ids (testclock, waits, &pending);
1412 gst_harness_set_time (h, gst_test_clock_id_list_get_latest_time (pending));
1413 processed = gst_test_clock_process_id_list (testclock, pending);
1415 g_list_free_full (pending, gst_clock_id_unref);
1416 return processed == waits;
1423 * This will set the harnessed #GstElement to %GST_STATE_PLAYING.
1424 * #GstElements without a sink-#GstPad and with the %GST_ELEMENT_FLAG_SOURCE
1425 * flag set is concidered a src #GstElement
1426 * Non-src #GstElements (like sinks and filters) are automatically set to
1427 * playing by the #GstHarness, but src #GstElements are not to avoid them
1428 * starting to produce buffers.
1429 * Hence, for src #GstElement you must call gst_harness_play() explicitly.
1436 gst_harness_play (GstHarness * h)
1438 GstState state, pending;
1439 gboolean state_change;
1440 state_change = gst_element_set_state (h->element, GST_STATE_PLAYING);
1441 g_assert_cmpint (GST_STATE_CHANGE_SUCCESS, ==, state_change);
1442 state_change = gst_element_get_state (h->element, &state, &pending, 0);
1443 g_assert_cmpint (GST_STATE_CHANGE_SUCCESS, ==, state_change);
1444 g_assert_cmpint (GST_STATE_PLAYING, ==, state);
1448 * gst_harness_set_blocking_push_mode:
1451 * Setting this will make the harness block in the chain-function, and
1452 * then release when gst_harness_pull() or gst_harness_try_pull() is called.
1453 * Can be useful when wanting to control a src-element that is not implementing
1454 * gst_clock_id_wait() so it can't be controlled by the #GstTestClock, since
1455 * it otherwise would produce buffers as fast as possible.
1462 gst_harness_set_blocking_push_mode (GstHarness * h)
1464 GstHarnessPrivate *priv = h->priv;
1465 priv->blocking_push_mode = TRUE;
1469 * gst_harness_set_forwarding:
1471 * @forwarding: a #gboolean to enable/disable forwarding
1473 * As a convenience, a src-harness will forward %GST_EVENT_STREAM_START,
1474 * %GST_EVENT_CAPS and %GST_EVENT_SEGMENT to the main-harness if forwarding
1475 * is enabled, and forward any sticky-events from the main-harness to
1476 * the sink-harness. It will also forward the %GST_QUERY_ALLOCATION.
1478 * If forwarding is disabled, the user will have to either manually push
1479 * these events from the src-harness using gst_harness_src_push_event(), or
1480 * create and push them manually. While this will allow full control and
1481 * inspection of these events, for the most cases having forwarding enabled
1482 * will be sufficient when writing a test where the src-harness' main function
1483 * is providing data for the main-harness.
1485 * Forwarding is enabled by default.
1492 gst_harness_set_forwarding (GstHarness * h, gboolean forwarding)
1494 GstHarnessPrivate *priv = h->priv;
1495 priv->forwarding = forwarding;
1497 gst_harness_set_forwarding (h->src_harness, forwarding);
1498 if (h->sink_harness)
1499 gst_harness_set_forwarding (h->sink_harness, forwarding);
1503 gst_harness_set_forward_pad (GstHarness * h, GstPad * fwdpad)
1506 gst_object_replace ((GstObject **) & h->priv->sink_forward_pad,
1507 (GstObject *) fwdpad);
1512 * gst_harness_create_buffer:
1514 * @size: a #gsize specifying the size of the buffer
1516 * Allocates a buffer using a #GstBufferPool if present, or else using the
1517 * configured #GstAllocator and #GstAllocationParams
1521 * Returns: a #GstBuffer of size @size
1526 gst_harness_create_buffer (GstHarness * h, gsize size)
1528 GstHarnessPrivate *priv = h->priv;
1529 GstBuffer *ret = NULL;
1532 if (gst_pad_check_reconfigure (h->srcpad))
1533 gst_harness_negotiate (h);
1536 flow = gst_buffer_pool_acquire_buffer (priv->pool, &ret, NULL);
1537 g_assert_cmpint (flow, ==, GST_FLOW_OK);
1538 if (gst_buffer_get_size (ret) != size) {
1539 GST_DEBUG_OBJECT (h,
1540 "use fallback, pool is configured with a different size (%zu != %zu)",
1541 size, gst_buffer_get_size (ret));
1542 gst_buffer_unref (ret);
1549 gst_buffer_new_allocate (priv->allocator, size,
1550 &priv->allocation_params);
1552 g_assert (ret != NULL);
1559 * @buffer: a #GstBuffer to push
1561 * Pushes a #GstBuffer on the #GstHarness srcpad. The standard way of
1562 * interacting with an harnessed element.
1566 * Returns: a #GstFlowReturn with the result from the push
1571 gst_harness_push (GstHarness * h, GstBuffer * buffer)
1573 GstHarnessPrivate *priv = h->priv;
1574 g_assert (buffer != NULL);
1575 priv->last_push_ts = GST_BUFFER_TIMESTAMP (buffer);
1576 return gst_pad_push (h->srcpad, buffer);
1583 * Pulls a #GstBuffer from the #GAsyncQueue on the #GstHarness sinkpad. The pull
1584 * will timeout in 60 seconds. This is the standard way of getting a buffer
1585 * from a harnessed #GstElement.
1589 * Returns: a #GstBuffer or %NULL if timed out.
1594 gst_harness_pull (GstHarness * h)
1596 GstHarnessPrivate *priv = h->priv;
1597 GstBuffer *buf = (GstBuffer *) g_async_queue_timeout_pop (priv->buffer_queue,
1598 G_USEC_PER_SEC * 60);
1600 if (priv->blocking_push_mode) {
1601 g_mutex_lock (&priv->blocking_push_mutex);
1602 g_cond_signal (&priv->blocking_push_cond);
1603 g_mutex_unlock (&priv->blocking_push_mutex);
1610 * gst_harness_try_pull:
1613 * Pulls a #GstBuffer from the #GAsyncQueue on the #GstHarness sinkpad. Unlike
1614 * gst_harness_pull this will not wait for any buffers if not any are present,
1615 * and return %NULL straight away.
1619 * Returns: a #GstBuffer or %NULL if no buffers are present in the #GAsyncQueue
1624 gst_harness_try_pull (GstHarness * h)
1626 GstHarnessPrivate *priv = h->priv;
1627 GstBuffer *buf = (GstBuffer *) g_async_queue_try_pop (priv->buffer_queue);
1629 if (priv->blocking_push_mode) {
1630 g_mutex_lock (&priv->blocking_push_mutex);
1631 g_cond_signal (&priv->blocking_push_cond);
1632 g_mutex_unlock (&priv->blocking_push_mutex);
1639 * gst_harness_push_and_pull:
1641 * @buffer: a #GstBuffer to push
1643 * Basically a gst_harness_push and a gst_harness_pull in one line. Reflects
1644 * the fact that you often want to do exactly this in your test: Push one buffer
1645 * in, and inspect the outcome.
1649 * Returns: a #GstBuffer or %NULL if timed out.
1654 gst_harness_push_and_pull (GstHarness * h, GstBuffer * buffer)
1656 gst_harness_push (h, buffer);
1657 return gst_harness_pull (h);
1661 * gst_harness_buffers_received:
1664 * The total number of #GstBuffers that has arrived on the #GstHarness sinkpad.
1665 * This number includes buffers that have been dropped as well as buffers
1666 * that have already been pulled out.
1670 * Returns: a #guint number of buffers received
1675 gst_harness_buffers_received (GstHarness * h)
1677 GstHarnessPrivate *priv = h->priv;
1678 return g_atomic_int_get (&priv->recv_buffers);
1682 * gst_harness_buffers_in_queue:
1685 * The number of #GstBuffers currently in the #GstHarness sinkpad #GAsyncQueue
1689 * Returns: a #guint number of buffers in the queue
1694 gst_harness_buffers_in_queue (GstHarness * h)
1696 GstHarnessPrivate *priv = h->priv;
1697 return g_async_queue_length (priv->buffer_queue);
1701 * gst_harness_set_drop_buffers:
1703 * @drop_buffers: a #gboolean specifying to drop outgoing buffers or not
1705 * When set to %TRUE, instead of placing the buffers arriving from the harnessed
1706 * #GstElement inside the sinkpads #GAsyncQueue, they are instead unreffed.
1713 gst_harness_set_drop_buffers (GstHarness * h, gboolean drop_buffers)
1715 GstHarnessPrivate *priv = h->priv;
1716 priv->drop_buffers = drop_buffers;
1720 * gst_harness_dump_to_file:
1722 * @filename: a #gchar with a the name of a file
1724 * Allows you to dump the #GstBuffers the #GstHarness sinkpad #GAsyncQueue
1732 gst_harness_dump_to_file (GstHarness * h, const gchar * filename)
1734 GstHarnessPrivate *priv = h->priv;
1737 fd = fopen (filename, "wb");
1740 while ((buf = g_async_queue_try_pop (priv->buffer_queue))) {
1742 gst_buffer_map (buf, &info, GST_MAP_READ);
1743 fwrite (info.data, 1, info.size, fd);
1744 gst_buffer_unmap (buf, &info);
1745 gst_buffer_unref (buf);
1753 * gst_harness_get_last_pushed_timestamp:
1756 * Get the timestamp of the last #GstBuffer pushed on the #GstHarness srcpad,
1757 * typically with gst_harness_push or gst_harness_push_from_src.
1761 * Returns: a #GstClockTime with the timestamp or %GST_CLOCK_TIME_NONE if no
1762 * #GstBuffer has been pushed on the #GstHarness srcpad
1767 gst_harness_get_last_pushed_timestamp (GstHarness * h)
1769 GstHarnessPrivate *priv = h->priv;
1770 return priv->last_push_ts;
1774 * gst_harness_push_event:
1776 * @event: a #GstEvent to push
1778 * Pushes an #GstEvent on the #GstHarness srcpad.
1782 * Returns: a #gboolean with the result from the push
1787 gst_harness_push_event (GstHarness * h, GstEvent * event)
1789 return gst_pad_push_event (h->srcpad, event);
1793 * gst_harness_pull_event:
1796 * Pulls an #GstEvent from the #GAsyncQueue on the #GstHarness sinkpad.
1797 * Timeouts after 60 seconds similar to gst_harness_pull.
1801 * Returns: a #GstEvent or %NULL if timed out.
1806 gst_harness_pull_event (GstHarness * h)
1808 GstHarnessPrivate *priv = h->priv;
1809 return (GstEvent *) g_async_queue_timeout_pop (priv->sink_event_queue,
1810 G_USEC_PER_SEC * 60);
1814 * gst_harness_try_pull_event:
1817 * Pulls an #GstEvent from the #GAsyncQueue on the #GstHarness sinkpad.
1818 * See gst_harness_try_pull for details.
1822 * Returns: a #GstEvent or %NULL if no buffers are present in the #GAsyncQueue
1827 gst_harness_try_pull_event (GstHarness * h)
1829 GstHarnessPrivate *priv = h->priv;
1830 return (GstEvent *) g_async_queue_try_pop (priv->sink_event_queue);
1834 * gst_harness_events_received:
1837 * The total number of #GstEvents that has arrived on the #GstHarness sinkpad
1838 * This number includes events handled by the harness as well as events
1839 * that have already been pulled out.
1843 * Returns: a #guint number of events received
1848 gst_harness_events_received (GstHarness * h)
1850 GstHarnessPrivate *priv = h->priv;
1851 return g_atomic_int_get (&priv->recv_events);
1855 * gst_harness_events_in_queue:
1858 * The number of #GstEvents currently in the #GstHarness sinkpad #GAsyncQueue
1862 * Returns: a #guint number of events in the queue
1867 gst_harness_events_in_queue (GstHarness * h)
1869 GstHarnessPrivate *priv = h->priv;
1870 return g_async_queue_length (priv->sink_event_queue);
1874 * gst_harness_push_upstream_event:
1876 * @event: a #GstEvent to push
1878 * Pushes an #GstEvent on the #GstHarness sinkpad.
1882 * Returns: a #gboolean with the result from the push
1887 gst_harness_push_upstream_event (GstHarness * h, GstEvent * event)
1889 g_return_val_if_fail (event != NULL, FALSE);
1890 g_return_val_if_fail (GST_EVENT_IS_UPSTREAM (event), FALSE);
1892 return gst_pad_push_event (h->sinkpad, event);
1896 * gst_harness_pull_upstream_event:
1899 * Pulls an #GstEvent from the #GAsyncQueue on the #GstHarness srcpad.
1900 * Timeouts after 60 seconds similar to gst_harness_pull.
1904 * Returns: a #GstEvent or %NULL if timed out.
1909 gst_harness_pull_upstream_event (GstHarness * h)
1911 GstHarnessPrivate *priv = h->priv;
1912 return (GstEvent *) g_async_queue_timeout_pop (priv->src_event_queue,
1913 G_USEC_PER_SEC * 60);
1917 * gst_harness_try_pull_upstream_event:
1920 * Pulls an #GstEvent from the #GAsyncQueue on the #GstHarness srcpad.
1921 * See gst_harness_try_pull for details.
1925 * Returns: a #GstEvent or %NULL if no buffers are present in the #GAsyncQueue
1930 gst_harness_try_pull_upstream_event (GstHarness * h)
1932 GstHarnessPrivate *priv = h->priv;
1933 return (GstEvent *) g_async_queue_try_pop (priv->src_event_queue);
1937 * gst_harness_upstream_events_received:
1940 * The total number of #GstEvents that has arrived on the #GstHarness srcpad
1941 * This number includes events handled by the harness as well as events
1942 * that have already been pulled out.
1946 * Returns: a #guint number of events received
1951 gst_harness_upstream_events_received (GstHarness * h)
1953 GstHarnessPrivate *priv = h->priv;
1954 return g_atomic_int_get (&priv->recv_upstream_events);
1958 * gst_harness_upstream_events_in_queue:
1961 * The number of #GstEvents currently in the #GstHarness srcpad #GAsyncQueue
1965 * Returns: a #guint number of events in the queue
1970 gst_harness_upstream_events_in_queue (GstHarness * h)
1972 GstHarnessPrivate *priv = h->priv;
1973 return g_async_queue_length (priv->src_event_queue);
1977 * gst_harness_query_latency:
1980 * Get the min latency reported by any harnessed #GstElement.
1984 * Returns: a #GstClockTime with min latency
1989 gst_harness_query_latency (GstHarness * h)
1993 GstClockTime min = GST_CLOCK_TIME_NONE;
1996 query = gst_query_new_latency ();
1998 if (gst_pad_peer_query (h->sinkpad, query)) {
1999 gst_query_parse_latency (query, &is_live, &min, &max);
2001 gst_query_unref (query);
2007 * gst_harness_set_upstream_latency:
2009 * @latency: a #GstClockTime specifying the latency
2011 * Sets the min latency reported by #GstHarness when receiving a latency-query
2015 * Returns: a #GstClockTime with min latency
2020 gst_harness_set_upstream_latency (GstHarness * h, GstClockTime latency)
2022 GstHarnessPrivate *priv = h->priv;
2023 priv->latency_min = latency;
2027 * gst_harness_get_allocator:
2029 * @allocator: (out) (allow-none) (transfer none): the #GstAllocator used
2030 * @params: (out) (allow-none) (transfer full): the #GstAllocationParams of
2033 * Gets the @allocator and its @params that has been decided to use after an
2041 gst_harness_get_allocator (GstHarness * h, GstAllocator ** allocator,
2042 GstAllocationParams * params)
2044 GstHarnessPrivate *priv = h->priv;
2046 *allocator = priv->allocator;
2048 *params = priv->allocation_params;
2053 * gst_harness_set_propose_allocator:
2055 * @allocator: (allow-none) (transfer full): a #GstAllocator
2056 * @params: (allow-none) (transfer none): a #GstAllocationParams
2058 * Sets the @allocator and @params to propose when receiving an allocation
2066 gst_harness_set_propose_allocator (GstHarness * h, GstAllocator * allocator,
2067 const GstAllocationParams * params)
2069 GstHarnessPrivate *priv = h->priv;
2071 priv->propose_allocator = allocator;
2073 priv->propose_allocation_params = *params;
2077 * gst_harness_add_src_harness:
2079 * @src_harness: (transfer full): a #GstHarness to be added as a src-harness.
2080 * @has_clock_wait: a #gboolean specifying if the #GstElement uses
2081 * gst_clock_wait_id internally.
2083 * A src-harness is a great way of providing the #GstHarness with data.
2084 * By adding a src-type #GstElement, it is then easy to use functions like
2085 * gst_harness_push_from_src or gst_harness_src_crank_and_push_many
2086 * to provide your harnessed element with input. The @has_clock_wait variable
2087 * is a greate way to control you src-element with, in that you can have it
2088 * produce a buffer for you by simply cranking the clock, and not have it
2089 * spin out of control producing buffers as fast as possible.
2091 * If a src-harness already exists it will be replaced.
2098 gst_harness_add_src_harness (GstHarness * h,
2099 GstHarness * src_harness, gboolean has_clock_wait)
2102 gst_harness_teardown (h->src_harness);
2103 h->src_harness = src_harness;
2105 gst_harness_set_forward_pad (h->src_harness, h->srcpad);
2106 gst_harness_use_testclock (h->src_harness);
2107 h->src_harness->priv->has_clock_wait = has_clock_wait;
2108 gst_harness_set_forwarding (h->src_harness, h->priv->forwarding);
2112 * gst_harness_add_src:
2114 * @src_element_name: a #gchar with the name of a #GstElement
2115 * @has_clock_wait: a #gboolean specifying if the #GstElement uses
2116 * gst_clock_wait_id internally.
2118 * Similar to gst_harness_add_src_harness, this is a convenience to
2119 * directly create a src-harness using the @src_element_name name specified.
2126 gst_harness_add_src (GstHarness * h,
2127 const gchar * src_element_name, gboolean has_clock_wait)
2129 GstHarness *src_harness = gst_harness_new (src_element_name);
2130 gst_harness_add_src_harness (h, src_harness, has_clock_wait);
2134 * gst_harness_add_src_parse:
2136 * @launchline: a #gchar describing a gst-launch type line
2137 * @has_clock_wait: a #gboolean specifying if the #GstElement uses
2138 * gst_clock_wait_id internally.
2140 * Similar to gst_harness_add_src, this allows you to specify a launch-line,
2141 * which can be useful for both having more then one #GstElement acting as your
2142 * src (Like a src producing raw buffers, and then an encoder, providing encoded
2143 * data), but also by allowing you to set properties like "is-live" directly on
2151 gst_harness_add_src_parse (GstHarness * h,
2152 const gchar * launchline, gboolean has_clock_wait)
2154 GstHarness *src_harness = gst_harness_new_parse (launchline);
2155 gst_harness_add_src_harness (h, src_harness, has_clock_wait);
2159 * gst_harness_push_from_src:
2162 * Transfer data from the src-#GstHarness to the main-#GstHarness. It consists
2164 * 1: Make sure the src is started. (see: gst_harness_play)
2165 * 2: Crank the clock (see: gst_harness_crank_single_clock_wait)
2166 * 3: Pull a #GstBuffer from the src-#GstHarness (see: gst_harness_pull)
2167 * 4: Push the same #GstBuffer into the main-#GstHarness (see: gst_harness_push)
2171 * Returns: a #GstFlowReturn with the result of the push
2176 gst_harness_push_from_src (GstHarness * h)
2181 g_assert (h->src_harness);
2183 /* FIXME: this *is* the right time to start the src,
2184 but maybe a flag so we don't keep telling it to play? */
2185 gst_harness_play (h->src_harness);
2187 if (h->src_harness->priv->has_clock_wait) {
2188 crank = gst_harness_crank_single_clock_wait (h->src_harness);
2192 buf = gst_harness_pull (h->src_harness);
2193 g_assert (buf != NULL);
2194 return gst_harness_push (h, buf);
2198 * gst_harness_src_crank_and_push_many:
2200 * @cranks: a #gint with the number of calls to gst_harness_crank_single_clock_wait
2201 * @pushes: a #gint with the number of calls to gst_harness_push
2203 * Transfer data from the src-#GstHarness to the main-#GstHarness. Similar to
2204 * gst_harness_push_from_src, this variant allows you to specify how many cranks
2205 * and how many pushes to perform. This can be useful for both moving a lot
2206 * of data at the same time, as well as cases when one crank does not equal one
2207 * buffer to push and v.v.
2211 * Returns: a #GstFlowReturn with the result of the push
2216 gst_harness_src_crank_and_push_many (GstHarness * h, gint cranks, gint pushes)
2218 GstFlowReturn ret = GST_FLOW_OK;
2221 g_assert (h->src_harness);
2222 gst_harness_play (h->src_harness);
2224 for (int i = 0; i < cranks; i++) {
2225 crank = gst_harness_crank_single_clock_wait (h->src_harness);
2229 for (int i = 0; i < pushes; i++) {
2231 buf = gst_harness_pull (h->src_harness);
2232 g_assert (buf != NULL);
2233 ret = gst_harness_push (h, buf);
2234 if (ret != GST_FLOW_OK)
2242 * gst_harness_src_push_event:
2245 * Similar to what gst_harness_src_push does with #GstBuffers, this transfers
2246 * a #GstEvent from the src-#GstHarness to the main-#GstHarness. Note that
2247 * some #GstEvents are being transferred automagically. Look at sink_forward_pad
2252 * Returns: a #gboolean with the result of the push
2257 gst_harness_src_push_event (GstHarness * h)
2259 return gst_harness_push_event (h, gst_harness_pull_event (h->src_harness));
2264 forward_sticky_events (GstPad * pad, GstEvent ** ev, gpointer user_data)
2266 GstHarness *h = user_data;
2267 return gst_pad_push_event (h->priv->sink_forward_pad, gst_event_ref (*ev));
2271 * gst_harness_add_sink_harness:
2273 * @sink_harness: (transfer full): a #GstHarness to be added as a sink-harness.
2275 * Similar to gst_harness_add_src, this allows you to send the data coming out
2276 * of your harnessed #GstElement to a sink-element, allowing to test different
2277 * responses the element output might create in sink elements. An example might
2278 * be an existing sink providing some analytical data on the input it receives that
2279 * can be useful to your testing. If the goal is to test a sink-element itself,
2280 * this is better acheived using gst_harness_new directly on the sink.
2282 * If a sink-harness already exists it will be replaced.
2289 gst_harness_add_sink_harness (GstHarness * h, GstHarness * sink_harness)
2291 GstHarnessPrivate *priv = h->priv;
2293 if (h->sink_harness) {
2294 gst_harness_set_forward_pad (h, NULL);
2295 gst_harness_teardown (h->sink_harness);
2297 h->sink_harness = sink_harness;
2298 gst_harness_set_forward_pad (h, h->sink_harness->srcpad);
2299 gst_harness_use_testclock (h->sink_harness);
2300 if (priv->forwarding && h->sinkpad)
2301 gst_pad_sticky_events_foreach (h->sinkpad, forward_sticky_events, h);
2302 gst_harness_set_forwarding (h->sink_harness, priv->forwarding);
2306 * gst_harness_add_sink:
2308 * @sink_element_name: a #gchar with the name of a #GstElement
2310 * Similar to gst_harness_add_sink_harness, this is a convenience to
2311 * directly create a sink-harness using the @sink_element_name name specified.
2318 gst_harness_add_sink (GstHarness * h, const gchar * sink_element_name)
2320 GstHarness *sink_harness = gst_harness_new (sink_element_name);
2321 gst_harness_add_sink_harness (h, sink_harness);
2325 * gst_harness_add_sink_parse:
2327 * @launchline: a #gchar with the name of a #GstElement
2329 * Similar to gst_harness_add_sink, this allows you to specify a launch-line
2330 * instead of just an element name. See gst_harness_add_src_parse for details.
2337 gst_harness_add_sink_parse (GstHarness * h, const gchar * launchline)
2339 GstHarness *sink_harness = gst_harness_new_parse (launchline);
2340 gst_harness_add_sink_harness (h, sink_harness);
2344 * gst_harness_push_to_sink:
2347 * Transfer one #GstBuffer from the main-#GstHarness to the sink-#GstHarness.
2348 * See gst_harness_push_from_src for details.
2352 * Returns: a #GstFlowReturn with the result of the push
2357 gst_harness_push_to_sink (GstHarness * h)
2360 g_assert (h->sink_harness);
2361 buf = gst_harness_pull (h);
2362 g_assert (buf != NULL);
2363 return gst_harness_push (h->sink_harness, buf);
2367 * gst_harness_sink_push_many:
2369 * @pushes: a #gint with the number of calls to gst_harness_push_to_sink
2371 * Convenience that calls gst_harness_push_to_sink @pushes number of times.
2372 * Will abort the pushing if any one push fails.
2376 * Returns: a #GstFlowReturn with the result of the push
2381 gst_harness_sink_push_many (GstHarness * h, gint pushes)
2383 GstFlowReturn ret = GST_FLOW_OK;
2384 g_assert (h->sink_harness);
2385 for (int i = 0; i < pushes; i++) {
2386 ret = gst_harness_push_to_sink (h);
2387 if (ret != GST_FLOW_OK)
2394 * gst_harness_find_element:
2396 * @element_name: a #gchar with a #GstElementFactory name
2398 * Most useful in conjunction with gst_harness_new_parse, this will scan the
2399 * #GstElements inside the #GstHarness, and check if any of them matches
2400 * @element_name. Typical usecase being that you need to access one of the
2401 * harnessed elements for properties and/or signals.
2405 * Returns: (transfer full) (allow-none): a #GstElement or %NULL if not found
2410 gst_harness_find_element (GstHarness * h, const gchar * element_name)
2412 gboolean done = FALSE;
2414 GValue data = G_VALUE_INIT;
2416 iter = gst_bin_iterate_elements (GST_BIN (h->element));
2420 switch (gst_iterator_next (iter, &data)) {
2421 case GST_ITERATOR_OK:
2423 GstElement *element = g_value_get_object (&data);
2424 GstPluginFeature *feature =
2425 GST_PLUGIN_FEATURE (gst_element_get_factory (element));
2426 if (!strcmp (element_name, gst_plugin_feature_get_name (feature))) {
2427 gst_iterator_free (iter);
2430 g_value_reset (&data);
2433 case GST_ITERATOR_RESYNC:
2434 gst_iterator_resync (iter);
2436 case GST_ITERATOR_ERROR:
2437 case GST_ITERATOR_DONE:
2442 gst_iterator_free (iter);
2450 * @element_name: a #gchar with a #GstElementFactory name
2451 * @first_property_name: a #gchar with the first property name
2452 * @...: value for the first property, followed optionally by more
2453 * name/value pairs, followed by %NULL
2455 * A convenience function to allows you to call g_object_set on a #GstElement
2456 * that are residing inside the #GstHarness, by using normal g_object_set
2464 gst_harness_set (GstHarness * h,
2465 const gchar * element_name, const gchar * first_property_name, ...)
2468 GstElement *element = gst_harness_find_element (h, element_name);
2469 va_start (var_args, first_property_name);
2470 g_object_set_valist (G_OBJECT (element), first_property_name, var_args);
2472 gst_object_unref (element);
2478 * @element_name: a #gchar with a #GstElementFactory name
2479 * @first_property_name: a #gchar with the first property name
2480 * @...: return location for the first property, followed optionally by more
2481 * name/return location pairs, followed by %NULL
2483 * A convenience function to allows you to call g_object_get on a #GstElement
2484 * that are residing inside the #GstHarness, by using normal g_object_get
2492 gst_harness_get (GstHarness * h,
2493 const gchar * element_name, const gchar * first_property_name, ...)
2496 GstElement *element = gst_harness_find_element (h, element_name);
2497 va_start (var_args, first_property_name);
2498 g_object_get_valist (G_OBJECT (element), first_property_name, var_args);
2500 gst_object_unref (element);
2504 * gst_harness_add_probe:
2506 * @element_name: a #gchar with a #GstElementFactory name
2507 * @pad_name: a #gchar with the name of the pad to attach the probe to
2508 * @mask: a #GstPadProbeType (see gst_pad_add_probe)
2509 * @callback: a #GstPadProbeCallback (see gst_pad_add_probe)
2510 * @user_data: a #gpointer (see gst_pad_add_probe)
2511 * @destroy_data: a #GDestroyNotify (see gst_pad_add_probe)
2513 * A convenience function to allows you to call gst_pad_add_probe on a
2514 * #GstPad of a #GstElement that are residing inside the #GstHarness,
2515 * by using normal gst_pad_add_probe syntax
2522 gst_harness_add_probe (GstHarness * h,
2523 const gchar * element_name, const gchar * pad_name, GstPadProbeType mask,
2524 GstPadProbeCallback callback, gpointer user_data,
2525 GDestroyNotify destroy_data)
2527 GstElement *element = gst_harness_find_element (h, element_name);
2528 GstPad *pad = gst_element_get_static_pad (element, pad_name);
2529 gst_pad_add_probe (pad, mask, callback, user_data, destroy_data);
2530 gst_object_unref (pad);
2531 gst_object_unref (element);
2534 /******************************************************************************/
2536 /******************************************************************************/
2537 struct _GstHarnessThread
2545 GDestroyNotify freefunc;
2555 } GstHarnessCustomThread;
2563 GstHarnessPrepareBufferFunc func;
2565 GDestroyNotify notify;
2566 } GstHarnessPushBufferThread;
2572 GstHarnessPrepareEventFunc func;
2574 GDestroyNotify notify;
2575 } GstHarnessPushEventThread;
2583 } GstHarnessPropThread;
2589 GstPadTemplate *templ;
2595 } GstHarnessReqPadThread;
2598 gst_harness_thread_init (GstHarnessThread * t, GDestroyNotify freefunc,
2599 GstHarness * h, gulong sleep)
2601 t->freefunc = freefunc;
2605 g_ptr_array_add (h->priv->stress, t);
2609 gst_harness_thread_free (GstHarnessThread * t)
2611 g_slice_free (GstHarnessThread, t);
2615 gst_harness_custom_thread_free (GstHarnessCustomThread * t)
2617 g_slice_free (GstHarnessCustomThread, t);
2621 gst_harness_push_buffer_thread_free (GstHarnessPushBufferThread * t)
2624 gst_caps_replace (&t->caps, NULL);
2625 if (t->notify != NULL)
2626 t->notify (t->data);
2627 g_slice_free (GstHarnessPushBufferThread, t);
2632 gst_harness_push_event_thread_free (GstHarnessPushEventThread * t)
2635 if (t->notify != NULL)
2636 t->notify (t->data);
2637 g_slice_free (GstHarnessPushEventThread, t);
2642 gst_harness_property_thread_free (GstHarnessPropThread * t)
2646 g_value_unset (&t->value);
2647 g_slice_free (GstHarnessPropThread, t);
2652 gst_harness_requestpad_release (GstPad * pad, GstElement * element)
2654 gst_element_release_request_pad (element, pad);
2655 gst_object_unref (pad);
2659 gst_harness_requestpad_release_pads (GstHarnessReqPadThread * rpt)
2661 g_slist_foreach (rpt->pads, (GFunc) gst_harness_requestpad_release,
2663 g_slist_free (rpt->pads);
2668 gst_harness_requestpad_thread_free (GstHarnessReqPadThread * t)
2671 gst_object_replace ((GstObject **) & t->templ, NULL);
2673 gst_caps_replace (&t->caps, NULL);
2675 gst_harness_requestpad_release_pads (t);
2676 g_slice_free (GstHarnessReqPadThread, t);
2680 #define GST_HARNESS_THREAD_START(ID, t) \
2681 (((GstHarnessThread *)t)->running = TRUE, \
2682 ((GstHarnessThread *)t)->thread = g_thread_new ( \
2683 "gst-harness-stress-"G_STRINGIFY(ID), \
2684 (GThreadFunc)gst_harness_stress_##ID##_func, t))
2685 #define GST_HARNESS_THREAD_END(t) \
2686 (t->running = FALSE, \
2687 GPOINTER_TO_UINT (g_thread_join (t->thread)))
2690 gst_harness_stress_free (GstHarnessThread * t)
2692 if (t != NULL && t->freefunc != NULL)
2697 gst_harness_stress_custom_func (GstHarnessThread * t)
2699 GstHarnessCustomThread *ct = (GstHarnessCustomThread *) t;
2702 if (ct->init != NULL)
2703 ct->init (ct, ct->data);
2705 while (t->running) {
2706 ct->callback (ct, ct->data);
2709 g_usleep (t->sleep);
2711 return GUINT_TO_POINTER (count);
2716 gst_harness_stress_statechange_func (GstHarnessThread * t)
2720 while (t->running) {
2721 GstClock *clock = gst_element_get_clock (t->h->element);
2723 gboolean done = FALSE;
2726 change = gst_element_set_state (t->h->element, GST_STATE_NULL);
2727 g_assert (change == GST_STATE_CHANGE_SUCCESS);
2730 it = gst_element_iterate_sink_pads (t->h->element);
2732 GValue item = G_VALUE_INIT;
2733 switch (gst_iterator_next (it, &item)) {
2734 case GST_ITERATOR_OK:
2736 GstPad *sinkpad = g_value_get_object (&item);
2737 GstPad *srcpad = gst_pad_get_peer (sinkpad);
2738 if (srcpad != NULL) {
2739 gst_pad_unlink (srcpad, sinkpad);
2740 gst_pad_link (srcpad, sinkpad);
2741 gst_object_unref (srcpad);
2743 g_value_reset (&item);
2746 case GST_ITERATOR_RESYNC:
2747 gst_iterator_resync (it);
2749 case GST_ITERATOR_ERROR:
2750 g_assert_not_reached ();
2751 case GST_ITERATOR_DONE:
2755 g_value_unset (&item);
2757 gst_iterator_free (it);
2759 if (clock != NULL) {
2760 gst_element_set_clock (t->h->element, clock);
2761 gst_object_unref (clock);
2763 change = gst_element_set_state (t->h->element, GST_STATE_PLAYING);
2764 g_assert (change == GST_STATE_CHANGE_SUCCESS);
2767 g_usleep (t->sleep);
2769 return GUINT_TO_POINTER (count);
2773 gst_harness_stress_buffer_func (GstHarnessThread * t)
2775 GstHarnessPushBufferThread *pt = (GstHarnessPushBufferThread *) t;
2780 /* Push stream start, caps and segment events */
2781 sid = g_strdup_printf ("%s-%p", GST_OBJECT_NAME (t->h->element), t->h);
2782 handled = gst_pad_push_event (t->h->srcpad, gst_event_new_stream_start (sid));
2785 handled = gst_pad_push_event (t->h->srcpad, gst_event_new_caps (pt->caps));
2787 handled = gst_pad_push_event (t->h->srcpad,
2788 gst_event_new_segment (&pt->segment));
2791 while (t->running) {
2792 gst_harness_push (t->h, pt->func (t->h, pt->data));
2795 g_usleep (t->sleep);
2797 return GUINT_TO_POINTER (count);
2801 gst_harness_stress_event_func (GstHarnessThread * t)
2803 GstHarnessPushEventThread *pet = (GstHarnessPushEventThread *) t;
2806 while (t->running) {
2807 gst_harness_push_event (t->h, pet->func (t->h, pet->data));
2810 g_usleep (t->sleep);
2812 return GUINT_TO_POINTER (count);
2816 gst_harness_stress_upstream_event_func (GstHarnessThread * t)
2818 GstHarnessPushEventThread *pet = (GstHarnessPushEventThread *) t;
2821 while (t->running) {
2822 gst_harness_push_upstream_event (t->h, pet->func (t->h, pet->data));
2825 g_usleep (t->sleep);
2827 return GUINT_TO_POINTER (count);
2831 gst_harness_stress_property_func (GstHarnessThread * t)
2833 GstHarnessPropThread *pt = (GstHarnessPropThread *) t;
2836 while (t->running) {
2837 GValue value = G_VALUE_INIT;
2839 g_object_set_property (G_OBJECT (t->h->element), pt->name, &pt->value);
2841 g_value_init (&value, G_VALUE_TYPE (&pt->value));
2842 g_object_get_property (G_OBJECT (t->h->element), pt->name, &value);
2843 g_value_reset (&value);
2846 g_usleep (t->sleep);
2848 return GUINT_TO_POINTER (count);
2852 gst_harness_stress_requestpad_func (GstHarnessThread * t)
2854 GstHarnessReqPadThread *rpt = (GstHarnessReqPadThread *) t;
2857 while (t->running) {
2861 gst_harness_requestpad_release_pads (rpt);
2865 reqpad = gst_element_request_pad (t->h->element,
2866 rpt->templ, rpt->name, rpt->caps);
2868 g_assert (reqpad != NULL);
2870 rpt->pads = g_slist_prepend (rpt->pads, reqpad);
2873 g_usleep (t->sleep);
2875 return GUINT_TO_POINTER (count);
2879 * gst_harness_stress_thread_stop:
2880 * @t: a #GstHarnessThread
2882 * Stop the running #GstHarnessThread
2889 gst_harness_stress_thread_stop (GstHarnessThread * t)
2893 g_return_val_if_fail (t != NULL, 0);
2895 ret = GST_HARNESS_THREAD_END (t);
2896 g_ptr_array_remove (t->h->priv->stress, t);
2901 * gst_harness_stress_custom_start: (skip)
2903 * @init: (allow-none): a #GFunc that is called initially and only once
2904 * @callback: a #GFunc that is called as often as possible
2905 * @data: a #gpointer with custom data to pass to the @callback function
2906 * @sleep: a #gulong specifying how long to sleep in (microseconds) for
2907 * each call to the @callback
2909 * Start a custom stress-thread that will call your @callback for every
2910 * iteration allowing you to do something nasty.
2914 * Returns: a #GstHarnessThread
2919 gst_harness_stress_custom_start (GstHarness * h,
2920 GFunc init, GFunc callback, gpointer data, gulong sleep)
2922 GstHarnessCustomThread *t = g_slice_new0 (GstHarnessCustomThread);
2923 gst_harness_thread_init (&t->t,
2924 (GDestroyNotify) gst_harness_custom_thread_free, h, sleep);
2927 t->callback = callback;
2930 GST_HARNESS_THREAD_START (custom, t);
2935 * gst_harness_stress_statechange_start_full: (skip)
2937 * @sleep: a #gulong specifying how long to sleep in (microseconds) for
2940 * Change the state of your harnessed #GstElement from NULL to PLAYING and
2941 * back again, only pausing for @sleep microseconds every time.
2945 * Returns: a #GstHarnessThread
2950 gst_harness_stress_statechange_start_full (GstHarness * h, gulong sleep)
2952 GstHarnessThread *t = g_slice_new0 (GstHarnessThread);
2953 gst_harness_thread_init (t,
2954 (GDestroyNotify) gst_harness_thread_free, h, sleep);
2955 GST_HARNESS_THREAD_START (statechange, t);
2960 gst_harness_ref_buffer (GstHarness * h, gpointer data)
2963 return gst_buffer_ref (GST_BUFFER_CAST (data));
2967 gst_harness_ref_event (GstHarness * h, gpointer data)
2970 return gst_event_ref (GST_EVENT_CAST (data));
2974 * gst_harness_stress_push_buffer_start_full: (skip)
2976 * @caps: a #GstCaps for the #GstBuffer
2977 * @segment: a #GstSegment
2978 * @buf: a #GstBuffer to push
2979 * @sleep: a #gulong specifying how long to sleep in (microseconds) for
2980 * each call to gst_pad_push
2982 * Push a #GstBuffer in intervals of @sleep microseconds.
2986 * Returns: a #GstHarnessThread
2991 gst_harness_stress_push_buffer_start_full (GstHarness * h,
2992 GstCaps * caps, const GstSegment * segment, GstBuffer * buf, gulong sleep)
2994 return gst_harness_stress_push_buffer_with_cb_start_full (h, caps, segment,
2995 gst_harness_ref_buffer, gst_buffer_ref (buf),
2996 (GDestroyNotify) gst_buffer_unref, sleep);
3000 * gst_harness_stress_push_buffer_with_cb_start_full: (skip)
3002 * @caps: a #GstCaps for the #GstBuffer
3003 * @segment: a #GstSegment
3004 * @func: a #GstHarnessPrepareBufferFunc function called before every iteration
3005 * to prepare / create a #GstBuffer for pushing
3006 * @data: a #gpointer with data to the #GstHarnessPrepareBufferFunc function
3007 * @notify: a #GDestroyNotify that is called when thread is stopped
3008 * @sleep: a #gulong specifying how long to sleep in (microseconds) for
3009 * each call to gst_pad_push
3011 * Push a #GstBuffer returned by @func in intervals of @sleep microseconds.
3015 * Returns: a #GstHarnessThread
3020 gst_harness_stress_push_buffer_with_cb_start_full (GstHarness * h,
3021 GstCaps * caps, const GstSegment * segment,
3022 GstHarnessPrepareBufferFunc func, gpointer data, GDestroyNotify notify,
3025 GstHarnessPushBufferThread *t = g_slice_new0 (GstHarnessPushBufferThread);
3026 gst_harness_thread_init (&t->t,
3027 (GDestroyNotify) gst_harness_push_buffer_thread_free, h, sleep);
3029 gst_caps_replace (&t->caps, caps);
3030 t->segment = *segment;
3035 GST_HARNESS_THREAD_START (buffer, t);
3040 * gst_harness_stress_push_event_start_full: (skip)
3042 * @event: a #GstEvent to push
3043 * @sleep: a #gulong specifying how long to sleep in (microseconds) for
3044 * each gst_event_push with @event
3046 * Push the @event onto the harnessed #GstElement sinkpad in intervals of
3047 * @sleep microseconds
3051 * Returns: a #GstHarnessThread
3056 gst_harness_stress_push_event_start_full (GstHarness * h,
3057 GstEvent * event, gulong sleep)
3059 return gst_harness_stress_push_event_with_cb_start_full (h,
3060 gst_harness_ref_event, gst_event_ref (event),
3061 (GDestroyNotify) gst_event_unref, sleep);
3065 * gst_harness_stress_push_event_with_cb_start_full: (skip)
3067 * @func: a #GstHarnessPrepareEventFunc function called before every iteration
3068 * to prepare / create a #GstEvent for pushing
3069 * @data: a #gpointer with data to the #GstHarnessPrepareEventFunc function
3070 * @notify: a #GDestroyNotify that is called when thread is stopped
3071 * @sleep: a #gulong specifying how long to sleep in (microseconds) for
3072 * each call to gst_pad_push
3074 * Push a #GstEvent returned by @func onto the harnessed #GstElement sinkpad
3075 * in intervals of @sleep microseconds.
3079 * Returns: a #GstHarnessThread
3084 gst_harness_stress_push_event_with_cb_start_full (GstHarness * h,
3085 GstHarnessPrepareEventFunc func, gpointer data, GDestroyNotify notify,
3088 GstHarnessPushEventThread *t = g_slice_new0 (GstHarnessPushEventThread);
3089 gst_harness_thread_init (&t->t,
3090 (GDestroyNotify) gst_harness_push_event_thread_free, h, sleep);
3096 GST_HARNESS_THREAD_START (event, t);
3101 * gst_harness_stress_push_upstream_event_start_full: (skip)
3103 * @event: a #GstEvent to push
3104 * @sleep: a #gulong specifying how long to sleep in (microseconds) for
3105 * each gst_event_push with @event
3107 * Push the @event onto the harnessed #GstElement srcpad in intervals of
3108 * @sleep microseconds.
3112 * Returns: a #GstHarnessThread
3117 gst_harness_stress_push_upstream_event_start_full (GstHarness * h,
3118 GstEvent * event, gulong sleep)
3120 return gst_harness_stress_push_upstream_event_with_cb_start_full (h,
3121 gst_harness_ref_event, gst_event_ref (event),
3122 (GDestroyNotify) gst_event_unref, sleep);
3126 * gst_harness_stress_push_upstream_event_with_cb_start_full: (skip)
3128 * @func: a #GstHarnessPrepareEventFunc function called before every iteration
3129 * to prepare / create a #GstEvent for pushing
3130 * @data: a #gpointer with data to the #GstHarnessPrepareEventFunc function
3131 * @notify: a #GDestroyNotify that is called when thread is stopped
3132 * @sleep: a #gulong specifying how long to sleep in (microseconds) for
3133 * each call to gst_pad_push
3135 * Push a #GstEvent returned by @func onto the harnessed #GstElement srcpad
3136 * in intervals of @sleep microseconds.
3140 * Returns: a #GstHarnessThread
3145 gst_harness_stress_push_upstream_event_with_cb_start_full (GstHarness * h,
3146 GstHarnessPrepareEventFunc func, gpointer data, GDestroyNotify notify,
3149 GstHarnessPushEventThread *t = g_slice_new0 (GstHarnessPushEventThread);
3150 gst_harness_thread_init (&t->t,
3151 (GDestroyNotify) gst_harness_push_event_thread_free, h, sleep);
3157 GST_HARNESS_THREAD_START (upstream_event, t);
3162 * gst_harness_stress_property_start_full: (skip)
3164 * @name: a #gchar specifying a property name
3165 * @value: a #GValue to set the property to
3166 * @sleep: a #gulong specifying how long to sleep in (microseconds) for
3167 * each g_object_set with @name and @value
3169 * Call g_object_set with @name and @value in intervals of @sleep microseconds
3173 * Returns: a #GstHarnessThread
3178 gst_harness_stress_property_start_full (GstHarness * h,
3179 const gchar * name, const GValue * value, gulong sleep)
3181 GstHarnessPropThread *t = g_slice_new0 (GstHarnessPropThread);
3182 gst_harness_thread_init (&t->t,
3183 (GDestroyNotify) gst_harness_property_thread_free, h, sleep);
3185 t->name = g_strdup (name);
3186 g_value_init (&t->value, G_VALUE_TYPE (value));
3187 g_value_copy (value, &t->value);
3189 GST_HARNESS_THREAD_START (property, t);
3194 * gst_harness_stress_requestpad_start_full: (skip)
3196 * @templ: a #GstPadTemplate
3199 * @release: a #gboolean
3200 * @sleep: a #gulong specifying how long to sleep in (microseconds) for
3201 * each gst_element_request_pad
3203 * Call gst_element_request_pad in intervals of @sleep microseconds
3207 * Returns: a #GstHarnessThread
3212 gst_harness_stress_requestpad_start_full (GstHarness * h,
3213 GstPadTemplate * templ, const gchar * name, GstCaps * caps,
3214 gboolean release, gulong sleep)
3216 GstHarnessReqPadThread *t = g_slice_new0 (GstHarnessReqPadThread);
3217 gst_harness_thread_init (&t->t,
3218 (GDestroyNotify) gst_harness_requestpad_thread_free, h, sleep);
3220 t->templ = gst_object_ref (templ);
3221 t->name = g_strdup (name);
3222 gst_caps_replace (&t->caps, caps);
3223 t->release = release;
3225 GST_HARNESS_THREAD_START (requestpad, t);