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.
24 * @short_description: A test-harness for writing GStreamer unit tests
25 * @see_also: #GstTestClock
27 * #GstHarness is meant to make writing unit test for GStreamer much easier.
28 * It can be thought of as a way of treating a #GstElement as a black box,
29 * deterministically feeding it data, and controlling what data it outputs.
31 * The basic structure of #GstHarness is two "floating" #GstPads that connect
32 * to the harnessed #GstElement src and sink #GstPads like so:
35 * __________________________
36 * _____ | _____ _____ | _____
38 * | src |--+-| sink| Element | src |-+--| sink|
39 * |_____| | |_____| |_____| | |_____|
40 * |__________________________|
44 * With this, you can now simulate any environment the #GstElement might find
45 * itself in. By specifying the #GstCaps of the harness #GstPads, using
46 * functions like gst_harness_set_src_caps() or gst_harness_set_sink_caps_str(),
47 * you can test how the #GstElement interacts with different caps sets.
49 * Your harnessed #GstElement can of course also be a bin, and using
50 * gst_harness_new_parse() supporting standard gst-launch syntax, you can
51 * easily test a whole pipeline instead of just one element.
53 * You can then go on to push #GstBuffers and #GstEvents on to the srcpad,
54 * using functions like gst_harness_push() and gst_harness_push_event(), and
55 * then pull them out to examine them with gst_harness_pull() and
56 * gst_harness_pull_event().
58 * ## A simple buffer-in buffer-out example
60 * |[<!-- language="C" -->
61 * #include <gst/gst.h>
62 * #include <gst/check/gstharness.h>
67 * // attach the harness to the src and sink pad of GstQueue
68 * h = gst_harness_new ("queue");
70 * // we must specify a caps before pushing buffers
71 * gst_harness_set_src_caps_str (h, "mycaps");
73 * // create a buffer of size 42
74 * in_buf = gst_harness_create_buffer (h, 42);
76 * // push the buffer into the queue
77 * gst_harness_push (h, in_buf);
79 * // pull the buffer from the queue
80 * out_buf = gst_harness_pull (h);
82 * // validate the buffer in is the same as buffer out
83 * fail_unless (in_buf == out_buf);
86 * gst_buffer_unref (out_buf);
87 * 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:
107 * |[<!-- language="C" -->
108 * GstHarness * h = gst_harness_new (h, "vp8dec");
109 * gst_harness_add_src_parse (h, "videotestsrc is-live=1 ! vp8enc", TRUE);
112 * and then feeding it data with:
114 * |[<!-- language="C" -->
115 * gst_harness_push_from_src (h);
123 /* we have code with side effects in asserts, so make sure they are active */
124 #ifdef G_DISABLE_ASSERT
125 #error "GstHarness must be compiled with G_DISABLE_ASSERT undefined"
128 #include "gstharness.h"
134 static void gst_harness_stress_free (GstHarnessThread * t);
136 #define HARNESS_KEY "harness"
137 #define HARNESS_REF "harness-ref"
138 #define HARNESS_LOCK(h) g_mutex_lock (&(h)->priv->priv_mutex)
139 #define HARNESS_UNLOCK(h) g_mutex_unlock (&(h)->priv->priv_mutex)
141 static GstStaticPadTemplate hsrctemplate = GST_STATIC_PAD_TEMPLATE ("src",
144 GST_STATIC_CAPS_ANY);
145 static GstStaticPadTemplate hsinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
148 GST_STATIC_CAPS_ANY);
150 struct _GstHarnessPrivate
152 gchar *element_sinkpad_name;
153 gchar *element_srcpad_name;
159 GstPad *sink_forward_pad;
160 GstTestClock *testclock;
162 volatile gint recv_buffers;
163 volatile gint recv_events;
164 volatile gint recv_upstream_events;
166 GAsyncQueue *buffer_queue;
167 GAsyncQueue *src_event_queue;
168 GAsyncQueue *sink_event_queue;
170 GstClockTime latency_min;
171 GstClockTime latency_max;
172 gboolean has_clock_wait;
173 gboolean drop_buffers;
174 GstClockTime last_push_ts;
177 GstAllocator *allocator;
178 GstAllocationParams allocation_params;
179 GstAllocator *propose_allocator;
180 GstAllocationParams propose_allocation_params;
182 gboolean blocking_push_mode;
183 GCond blocking_push_cond;
184 GMutex blocking_push_mutex;
191 gst_harness_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
193 GstHarness *h = g_object_get_data (G_OBJECT (pad), HARNESS_KEY);
194 GstHarnessPrivate *priv = h->priv;
196 g_assert (h != NULL);
197 g_mutex_lock (&priv->blocking_push_mutex);
198 g_atomic_int_inc (&priv->recv_buffers);
200 if (priv->drop_buffers)
201 gst_buffer_unref (buffer);
203 g_async_queue_push (priv->buffer_queue, buffer);
205 if (priv->blocking_push_mode) {
206 g_cond_wait (&priv->blocking_push_cond, &priv->blocking_push_mutex);
208 g_mutex_unlock (&priv->blocking_push_mutex);
214 gst_harness_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
216 GstHarness *h = g_object_get_data (G_OBJECT (pad), HARNESS_KEY);
217 GstHarnessPrivate *priv = h->priv;
219 g_assert (h != NULL);
220 g_atomic_int_inc (&priv->recv_upstream_events);
221 g_async_queue_push (priv->src_event_queue, event);
226 gst_harness_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
228 GstHarness *h = g_object_get_data (G_OBJECT (pad), HARNESS_KEY);
229 GstHarnessPrivate *priv = h->priv;
233 g_assert (h != NULL);
235 g_atomic_int_inc (&priv->recv_events);
237 switch (GST_EVENT_TYPE (event)) {
238 case GST_EVENT_STREAM_START:
240 case GST_EVENT_SEGMENT:
249 if (priv->forwarding && forward && priv->sink_forward_pad) {
250 GstPad *fwdpad = gst_object_ref (priv->sink_forward_pad);
252 ret = gst_pad_push_event (fwdpad, event);
253 gst_object_unref (fwdpad);
256 g_async_queue_push (priv->sink_event_queue, event);
264 gst_harness_decide_allocation (GstHarness * h, GstCaps * caps)
266 GstHarnessPrivate *priv = h->priv;
268 GstAllocator *allocator;
269 GstAllocationParams params;
270 GstBufferPool *pool = NULL;
271 guint size, min, max;
273 query = gst_query_new_allocation (caps, FALSE);
274 gst_pad_peer_query (h->srcpad, query);
276 if (gst_query_get_n_allocation_params (query) > 0) {
277 gst_query_parse_nth_allocation_param (query, 0, &allocator, ¶ms);
280 gst_allocation_params_init (¶ms);
283 if (gst_query_get_n_allocation_pools (query) > 0) {
284 gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
286 /* Most elements create their own pools if pool == NULL. Not sure if we
287 * want to do that in the harness since we may want to test the pool
288 * implementation of the elements. Not creating a pool will however ignore
289 * the returned size. */
291 pool = gst_buffer_pool_new ();
295 size = min = max = 0;
297 gst_query_unref (query);
300 GstStructure *config = gst_buffer_pool_get_config (pool);
301 gst_buffer_pool_config_set_params (config, caps, size, min, max);
302 gst_buffer_pool_config_set_allocator (config, allocator, ¶ms);
303 gst_buffer_pool_set_config (pool, config);
306 if (pool != priv->pool) {
307 if (priv->pool != NULL)
308 gst_buffer_pool_set_active (priv->pool, FALSE);
310 gst_buffer_pool_set_active (pool, TRUE);
313 priv->allocation_params = params;
315 gst_object_unref (priv->allocator);
316 priv->allocator = allocator;
318 gst_object_unref (priv->pool);
323 gst_harness_negotiate (GstHarness * h)
327 caps = gst_pad_get_current_caps (h->srcpad);
329 gst_harness_decide_allocation (h, caps);
330 gst_caps_unref (caps);
332 GST_FIXME_OBJECT (h, "Cannot negotiate allocation because caps is not set");
337 gst_harness_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
339 GstHarness *h = g_object_get_data (G_OBJECT (pad), HARNESS_KEY);
340 GstHarnessPrivate *priv = h->priv;
342 g_assert (h != NULL);
344 // FIXME: forward all queries?
346 switch (GST_QUERY_TYPE (query)) {
347 case GST_QUERY_LATENCY:
348 gst_query_set_latency (query, TRUE, priv->latency_min, priv->latency_max);
352 GstCaps *caps, *filter = NULL;
354 if (priv->sink_caps) {
355 caps = gst_caps_ref (priv->sink_caps);
357 caps = gst_pad_get_pad_template_caps (pad);
360 gst_query_parse_caps (query, &filter);
361 if (filter != NULL) {
362 gst_caps_take (&caps,
363 gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST));
366 gst_query_set_caps_result (query, caps);
367 gst_caps_unref (caps);
370 case GST_QUERY_ALLOCATION:
373 if (priv->forwarding && priv->sink_forward_pad != NULL) {
374 GstPad *peer = gst_pad_get_peer (priv->sink_forward_pad);
375 g_assert (peer != NULL);
377 res = gst_pad_query (peer, query);
378 gst_object_unref (peer);
385 gst_query_parse_allocation (query, &caps, &need_pool);
387 /* FIXME: Can this be removed? */
388 size = gst_query_get_n_allocation_params (query);
389 g_assert_cmpuint (0, ==, size);
390 gst_query_add_allocation_param (query,
391 priv->propose_allocator, &priv->propose_allocation_params);
393 GST_DEBUG_OBJECT (pad, "proposing allocation %" GST_PTR_FORMAT,
394 priv->propose_allocator);
400 res = gst_pad_query_default (pad, parent, query);
407 gst_harness_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
409 GstHarness *h = g_object_get_data (G_OBJECT (pad), HARNESS_KEY);
410 GstHarnessPrivate *priv = h->priv;
412 g_assert (h != NULL);
414 switch (GST_QUERY_TYPE (query)) {
415 case GST_QUERY_LATENCY:
416 gst_query_set_latency (query, TRUE, priv->latency_min, priv->latency_max);
420 GstCaps *caps, *filter = NULL;
422 if (priv->src_caps) {
423 caps = gst_caps_ref (priv->src_caps);
425 caps = gst_pad_get_pad_template_caps (pad);
428 gst_query_parse_caps (query, &filter);
429 if (filter != NULL) {
430 gst_caps_take (&caps,
431 gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST));
434 gst_query_set_caps_result (query, caps);
435 gst_caps_unref (caps);
439 res = gst_pad_query_default (pad, parent, query);
445 gst_harness_element_ref (GstHarness * h)
449 GST_OBJECT_LOCK (h->element);
450 data = g_object_get_data (G_OBJECT (h->element), HARNESS_REF);
452 data = g_new0 (guint, 1);
454 g_object_set_data_full (G_OBJECT (h->element), HARNESS_REF, data, g_free);
458 GST_OBJECT_UNLOCK (h->element);
462 gst_harness_element_unref (GstHarness * h)
467 GST_OBJECT_LOCK (h->element);
468 data = g_object_get_data (G_OBJECT (h->element), HARNESS_REF);
469 g_assert (data != NULL);
472 GST_OBJECT_UNLOCK (h->element);
478 gst_harness_link_element_srcpad (GstHarness * h,
479 const gchar * element_srcpad_name)
481 GstHarnessPrivate *priv = h->priv;
482 GstPad *srcpad = gst_element_get_static_pad (h->element,
483 element_srcpad_name);
484 GstPadLinkReturn link;
486 srcpad = gst_element_get_request_pad (h->element, element_srcpad_name);
488 link = gst_pad_link (srcpad, h->sinkpad);
489 g_assert_cmpint (link, ==, GST_PAD_LINK_OK);
490 g_free (priv->element_srcpad_name);
491 priv->element_srcpad_name = gst_pad_get_name (srcpad);
493 gst_object_unref (srcpad);
497 gst_harness_link_element_sinkpad (GstHarness * h,
498 const gchar * element_sinkpad_name)
500 GstHarnessPrivate *priv = h->priv;
501 GstPad *sinkpad = gst_element_get_static_pad (h->element,
502 element_sinkpad_name);
503 GstPadLinkReturn link;
505 sinkpad = gst_element_get_request_pad (h->element, element_sinkpad_name);
507 link = gst_pad_link (h->srcpad, sinkpad);
508 g_assert_cmpint (link, ==, GST_PAD_LINK_OK);
509 g_free (priv->element_sinkpad_name);
510 priv->element_sinkpad_name = gst_pad_get_name (sinkpad);
512 gst_object_unref (sinkpad);
516 gst_harness_setup_src_pad (GstHarness * h,
517 GstStaticPadTemplate * src_tmpl, const gchar * element_sinkpad_name)
519 GstHarnessPrivate *priv = h->priv;
521 g_assert (h->srcpad == NULL);
523 priv->src_event_queue =
524 g_async_queue_new_full ((GDestroyNotify) gst_event_unref);
527 h->srcpad = gst_pad_new_from_static_template (src_tmpl, "src");
528 g_assert (h->srcpad);
529 g_object_set_data (G_OBJECT (h->srcpad), HARNESS_KEY, h);
531 gst_pad_set_query_function (h->srcpad, gst_harness_src_query);
532 gst_pad_set_event_function (h->srcpad, gst_harness_src_event);
534 gst_pad_set_active (h->srcpad, TRUE);
536 if (element_sinkpad_name)
537 gst_harness_link_element_sinkpad (h, element_sinkpad_name);
541 gst_harness_setup_sink_pad (GstHarness * h,
542 GstStaticPadTemplate * sink_tmpl, const gchar * element_srcpad_name)
544 GstHarnessPrivate *priv = h->priv;
545 g_assert (sink_tmpl);
546 g_assert (h->sinkpad == NULL);
548 priv->buffer_queue = g_async_queue_new_full (
549 (GDestroyNotify) gst_buffer_unref);
550 priv->sink_event_queue = g_async_queue_new_full (
551 (GDestroyNotify) gst_event_unref);
554 h->sinkpad = gst_pad_new_from_static_template (sink_tmpl, "sink");
555 g_assert (h->sinkpad);
556 g_object_set_data (G_OBJECT (h->sinkpad), HARNESS_KEY, h);
558 gst_pad_set_chain_function (h->sinkpad, gst_harness_chain);
559 gst_pad_set_query_function (h->sinkpad, gst_harness_sink_query);
560 gst_pad_set_event_function (h->sinkpad, gst_harness_sink_event);
562 gst_pad_set_active (h->sinkpad, TRUE);
564 if (element_srcpad_name)
565 gst_harness_link_element_srcpad (h, element_srcpad_name);
569 check_element_type (GstElement * element, gboolean * has_sinkpad,
570 gboolean * has_srcpad)
572 GstElementClass *element_class = GST_ELEMENT_GET_CLASS (element);
573 const GList *tmpl_list;
575 *has_srcpad = element->numsrcpads > 0;
576 *has_sinkpad = element->numsinkpads > 0;
578 tmpl_list = gst_element_class_get_pad_template_list (element_class);
581 GstPadTemplate *pad_tmpl = (GstPadTemplate *) tmpl_list->data;
582 tmpl_list = g_list_next (tmpl_list);
583 if (GST_PAD_TEMPLATE_DIRECTION (pad_tmpl) == GST_PAD_SRC)
585 if (GST_PAD_TEMPLATE_DIRECTION (pad_tmpl) == GST_PAD_SINK)
586 *has_sinkpad |= TRUE;
591 turn_async_and_sync_off (GstElement * element)
593 GObjectClass *class = G_OBJECT_GET_CLASS (element);
594 if (g_object_class_find_property (class, "async"))
595 g_object_set (element, "async", FALSE, NULL);
596 if (g_object_class_find_property (class, "sync"))
597 g_object_set (element, "sync", FALSE, NULL);
601 gst_pad_is_request_pad (GstPad * pad)
603 GstPadTemplate *temp;
608 temp = gst_pad_get_pad_template (pad);
611 is_request = GST_PAD_TEMPLATE_PRESENCE (temp) == GST_PAD_REQUEST;
612 gst_object_unref (temp);
617 * gst_harness_new_empty: (skip)
619 * Creates a new empty harness. Use gst_harness_add_element_full() to add
620 * an #GstElement to it.
624 * Returns: (transfer full): a #GstHarness, or %NULL if the harness could
630 gst_harness_new_empty (void)
633 GstHarnessPrivate *priv;
635 h = g_new0 (GstHarness, 1);
636 g_assert (h != NULL);
637 h->priv = g_new0 (GstHarnessPrivate, 1);
640 GST_DEBUG_OBJECT (h, "about to create new harness %p", h);
641 priv->last_push_ts = GST_CLOCK_TIME_NONE;
642 priv->latency_min = 0;
643 priv->latency_max = GST_CLOCK_TIME_NONE;
644 priv->drop_buffers = FALSE;
645 priv->testclock = GST_TEST_CLOCK_CAST (gst_test_clock_new ());
647 priv->propose_allocator = NULL;
648 gst_allocation_params_init (&priv->propose_allocation_params);
650 g_mutex_init (&priv->blocking_push_mutex);
651 g_cond_init (&priv->blocking_push_cond);
652 g_mutex_init (&priv->priv_mutex);
654 priv->stress = g_ptr_array_new_with_free_func (
655 (GDestroyNotify) gst_harness_stress_free);
657 /* we have forwarding on as a default */
658 gst_harness_set_forwarding (h, TRUE);
664 * gst_harness_add_element_full: (skip)
666 * @element: a #GstElement to add to the harness (transfer none)
667 * @hsrc: (allow-none): a #GstStaticPadTemplate describing the harness srcpad.
668 * %NULL will not create a harness srcpad.
669 * @element_sinkpad_name: (allow-none): a #gchar with the name of the element
670 * sinkpad that is then linked to the harness srcpad. Can be a static or request
671 * or a sometimes pad that has been added. %NULL will not get/request a sinkpad
672 * from the element. (Like if the element is a src.)
673 * @hsink: (allow-none): a #GstStaticPadTemplate describing the harness sinkpad.
674 * %NULL will not create a harness sinkpad.
675 * @element_srcpad_name: (allow-none): a #gchar with the name of the element
676 * srcpad that is then linked to the harness sinkpad, similar to the
677 * @element_sinkpad_name.
679 * Adds a #GstElement to an empty #GstHarness
686 gst_harness_add_element_full (GstHarness * h, GstElement * element,
687 GstStaticPadTemplate * hsrc, const gchar * element_sinkpad_name,
688 GstStaticPadTemplate * hsink, const gchar * element_srcpad_name)
690 GstClock *element_clock;
691 gboolean has_sinkpad, has_srcpad;
693 g_return_if_fail (element != NULL);
694 g_return_if_fail (h->element == NULL);
696 element_clock = GST_ELEMENT_CLOCK (element);
697 h->element = gst_object_ref (element);
698 check_element_type (element, &has_sinkpad, &has_srcpad);
700 /* setup the loose srcpad linked to the element sinkpad */
702 gst_harness_setup_src_pad (h, hsrc, element_sinkpad_name);
704 /* setup the loose sinkpad linked to the element srcpad */
706 gst_harness_setup_sink_pad (h, hsink, element_srcpad_name);
708 /* as a harness sink, we should not need sync and async */
709 if (has_sinkpad && !has_srcpad)
710 turn_async_and_sync_off (h->element);
712 if (h->srcpad != NULL) {
714 gchar *stream_id = g_strdup_printf ("%s-%p",
715 GST_OBJECT_NAME (h->element), h);
716 handled = gst_pad_push_event (h->srcpad,
717 gst_event_new_stream_start (stream_id));
722 /* if the element already has a testclock attached,
723 we replace our own with it, if no clock we attach the testclock */
725 if (GST_IS_TEST_CLOCK (element_clock)) {
726 gst_object_replace ((GstObject **) & h->priv->testclock,
727 (GstObject *) GST_ELEMENT_CLOCK (element));
730 gst_harness_use_testclock (h);
733 /* don't start sources, they start producing data! */
735 gst_harness_play (h);
737 gst_harness_element_ref (h);
739 GST_DEBUG_OBJECT (h, "added element to harness %p "
740 "with element_srcpad_name (%p, %s, %s) and element_sinkpad_name (%p, %s, %s)",
741 h, h->srcpad, GST_DEBUG_PAD_NAME (h->srcpad),
742 h->sinkpad, GST_DEBUG_PAD_NAME (h->sinkpad));
746 * gst_harness_new_full: (skip)
747 * @element: a #GstElement to attach the harness to (transfer none)
748 * @hsrc: (allow-none): a #GstStaticPadTemplate describing the harness srcpad.
749 * %NULL will not create a harness srcpad.
750 * @element_sinkpad_name: (allow-none): a #gchar with the name of the element
751 * sinkpad that is then linked to the harness srcpad. Can be a static or request
752 * or a sometimes pad that has been added. %NULL will not get/request a sinkpad
753 * from the element. (Like if the element is a src.)
754 * @hsink: (allow-none): a #GstStaticPadTemplate describing the harness sinkpad.
755 * %NULL will not create a harness sinkpad.
756 * @element_srcpad_name: (allow-none): a #gchar with the name of the element
757 * srcpad that is then linked to the harness sinkpad, similar to the
758 * @element_sinkpad_name.
760 * Creates a new harness.
764 * Returns: (transfer full): a #GstHarness, or %NULL if the harness could
770 gst_harness_new_full (GstElement * element,
771 GstStaticPadTemplate * hsrc, const gchar * element_sinkpad_name,
772 GstStaticPadTemplate * hsink, const gchar * element_srcpad_name)
775 h = gst_harness_new_empty ();
776 gst_harness_add_element_full (h, element,
777 hsrc, element_sinkpad_name, hsink, element_srcpad_name);
782 * gst_harness_new_with_element: (skip)
783 * @element: a #GstElement to attach the harness to (transfer none)
784 * @element_sinkpad_name: (allow-none): a #gchar with the name of the element
785 * sinkpad that is then linked to the harness srcpad. %NULL does not attach a
787 * @element_srcpad_name: (allow-none): a #gchar with the name of the element
788 * srcpad that is then linked to the harness sinkpad. %NULL does not attach a
791 * Creates a new harness. Works in the same way as gst_harness_new_full(), only
792 * that generic padtemplates are used for the harness src and sinkpads, which
793 * will be sufficient in most usecases.
797 * Returns: (transfer full): a #GstHarness, or %NULL if the harness could
803 gst_harness_new_with_element (GstElement * element,
804 const gchar * element_sinkpad_name, const gchar * element_srcpad_name)
806 return gst_harness_new_full (element,
807 &hsrctemplate, element_sinkpad_name, &hsinktemplate, element_srcpad_name);
811 * gst_harness_new_with_padnames: (skip)
812 * @element_name: a #gchar describing the #GstElement name
813 * @element_sinkpad_name: (allow-none): a #gchar with the name of the element
814 * sinkpad that is then linked to the harness srcpad. %NULL does not attach a
816 * @element_srcpad_name: (allow-none): a #gchar with the name of the element
817 * srcpad that is then linked to the harness sinkpad. %NULL does not attach a
820 * Creates a new harness. Works like gst_harness_new_with_element(),
821 * except you specify the factoryname of the #GstElement
825 * Returns: (transfer full): a #GstHarness, or %NULL if the harness could
831 gst_harness_new_with_padnames (const gchar * element_name,
832 const gchar * element_sinkpad_name, const gchar * element_srcpad_name)
835 GstElement *element = gst_element_factory_make (element_name, NULL);
836 g_assert (element != NULL);
838 h = gst_harness_new_with_element (element, element_sinkpad_name,
839 element_srcpad_name);
840 gst_object_unref (element);
845 * gst_harness_new_with_templates: (skip)
846 * @element_name: a #gchar describing the #GstElement name
847 * @hsrc: (allow-none): a #GstStaticPadTemplate describing the harness srcpad.
848 * %NULL will not create a harness srcpad.
849 * @hsink: (allow-none): a #GstStaticPadTemplate describing the harness sinkpad.
850 * %NULL will not create a harness sinkpad.
852 * Creates a new harness, like gst_harness_new_full(), except it
853 * assumes the #GstElement sinkpad is named "sink" and srcpad is named "src"
857 * Returns: (transfer full): a #GstHarness, or %NULL if the harness could
863 gst_harness_new_with_templates (const gchar * element_name,
864 GstStaticPadTemplate * hsrc, GstStaticPadTemplate * hsink)
867 GstElement *element = gst_element_factory_make (element_name, NULL);
868 g_assert (element != NULL);
870 h = gst_harness_new_full (element, hsrc, "sink", hsink, "src");
871 gst_object_unref (element);
876 * gst_harness_new: (skip)
877 * @element_name: a #gchar describing the #GstElement name
879 * Creates a new harness. Works like gst_harness_new_with_padnames(), except it
880 * assumes the #GstElement sinkpad is named "sink" and srcpad is named "src"
884 * Returns: (transfer full): a #GstHarness, or %NULL if the harness could
890 gst_harness_new (const gchar * element_name)
892 return gst_harness_new_with_padnames (element_name, "sink", "src");
896 * gst_harness_add_parse: (skip)
898 * @launchline: a #gchar describing a gst-launch type line
900 * Parses the @launchline and puts that in a #GstBin,
901 * and then attches the supplied #GstHarness to the bin.
908 gst_harness_add_parse (GstHarness * h, const gchar * launchline)
914 gboolean done = FALSE;
915 GError *error = NULL;
917 g_return_if_fail (launchline != NULL);
919 desc = g_strdup_printf ("bin.( %s )", launchline);
921 (GstBin *) gst_parse_launch_full (desc, NULL, GST_PARSE_FLAG_FATAL_ERRORS,
924 if (G_UNLIKELY (error != NULL)) {
925 g_error ("Unable to create pipeline '%s': %s", desc, error->message);
929 /* find pads and ghost them if necessary */
930 if ((pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SRC)) != NULL) {
931 gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("src", pad));
932 gst_object_unref (pad);
934 if ((pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SINK)) != NULL) {
935 gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("sink", pad));
936 gst_object_unref (pad);
939 iter = gst_bin_iterate_sinks (bin);
941 GValue item = { 0, };
943 switch (gst_iterator_next (iter, &item)) {
944 case GST_ITERATOR_OK:
945 turn_async_and_sync_off (GST_ELEMENT (g_value_get_object (&item)));
946 g_value_reset (&item);
948 case GST_ITERATOR_DONE:
951 case GST_ITERATOR_RESYNC:
952 gst_iterator_resync (iter);
954 case GST_ITERATOR_ERROR:
955 gst_object_unref (bin);
956 gst_iterator_free (iter);
957 g_return_if_reached ();
961 gst_iterator_free (iter);
963 gst_harness_add_element_full (h, GST_ELEMENT_CAST (bin),
964 &hsrctemplate, "sink", &hsinktemplate, "src");
965 gst_object_unref (bin);
969 * gst_harness_new_parse: (skip)
970 * @launchline: a #gchar describing a gst-launch type line
972 * Creates a new harness, parsing the @launchline and putting that in a #GstBin,
973 * and then attches the harness to the bin.
977 * Returns: (transfer full): a #GstHarness, or %NULL if the harness could
983 gst_harness_new_parse (const gchar * launchline)
986 h = gst_harness_new_empty ();
987 gst_harness_add_parse (h, launchline);
992 * gst_harness_teardown:
995 * Tears down a @GstHarness, freeing all resources allocated using it.
1002 gst_harness_teardown (GstHarness * h)
1004 GstHarnessPrivate *priv = h->priv;
1006 if (priv->blocking_push_mode) {
1007 g_mutex_lock (&priv->blocking_push_mutex);
1008 priv->blocking_push_mode = FALSE;
1009 g_cond_signal (&priv->blocking_push_cond);
1010 g_mutex_unlock (&priv->blocking_push_mutex);
1013 if (h->src_harness) {
1014 gst_harness_teardown (h->src_harness);
1017 gst_object_replace ((GstObject **) & priv->sink_forward_pad, NULL);
1018 if (h->sink_harness) {
1019 gst_harness_teardown (h->sink_harness);
1023 gst_caps_unref (priv->src_caps);
1025 if (priv->sink_caps)
1026 gst_caps_unref (priv->sink_caps);
1029 if (gst_pad_is_request_pad (GST_PAD_PEER (h->srcpad)))
1030 gst_element_release_request_pad (h->element, GST_PAD_PEER (h->srcpad));
1031 g_free (priv->element_sinkpad_name);
1033 gst_pad_set_active (h->srcpad, FALSE);
1034 gst_object_unref (h->srcpad);
1036 g_async_queue_unref (priv->src_event_queue);
1040 if (gst_pad_is_request_pad (GST_PAD_PEER (h->sinkpad)))
1041 gst_element_release_request_pad (h->element, GST_PAD_PEER (h->sinkpad));
1042 g_free (priv->element_srcpad_name);
1044 gst_pad_set_active (h->sinkpad, FALSE);
1045 gst_object_unref (h->sinkpad);
1047 g_async_queue_unref (priv->buffer_queue);
1048 g_async_queue_unref (priv->sink_event_queue);
1051 gst_object_replace ((GstObject **) & priv->propose_allocator, NULL);
1052 gst_object_replace ((GstObject **) & priv->allocator, NULL);
1053 gst_object_replace ((GstObject **) & priv->pool, NULL);
1055 /* if we hold the last ref, set to NULL */
1056 if (gst_harness_element_unref (h) == 0) {
1057 gboolean state_change;
1058 GstState state, pending;
1059 state_change = gst_element_set_state (h->element, GST_STATE_NULL);
1060 g_assert (state_change == GST_STATE_CHANGE_SUCCESS);
1061 state_change = gst_element_get_state (h->element, &state, &pending, 0);
1062 g_assert (state_change == GST_STATE_CHANGE_SUCCESS);
1063 g_assert (state == GST_STATE_NULL);
1066 g_cond_clear (&priv->blocking_push_cond);
1067 g_mutex_clear (&priv->blocking_push_mutex);
1068 g_mutex_clear (&priv->priv_mutex);
1070 g_ptr_array_unref (priv->stress);
1072 gst_object_unref (h->element);
1074 gst_object_replace ((GstObject **) & priv->testclock, NULL);
1081 * gst_harness_add_element_src_pad:
1083 * @srcpad: a #GstPad to link to the harness sinkpad
1085 * Links the specifed #GstPad the @GstHarness sinkpad. This can be useful if
1086 * perhaps the srcpad did not exist at the time of creating the harness,
1087 * like a demuxer that provides a sometimes-pad after receiving data.
1094 gst_harness_add_element_src_pad (GstHarness * h, GstPad * srcpad)
1096 GstHarnessPrivate *priv = h->priv;
1097 GstPadLinkReturn link;
1098 if (h->sinkpad == NULL)
1099 gst_harness_setup_sink_pad (h, &hsinktemplate, NULL);
1100 link = gst_pad_link (srcpad, h->sinkpad);
1101 g_assert_cmpint (link, ==, GST_PAD_LINK_OK);
1102 g_free (priv->element_srcpad_name);
1103 priv->element_srcpad_name = gst_pad_get_name (srcpad);
1107 * gst_harness_add_element_sink_pad:
1109 * @sinkpad: a #GstPad to link to the harness srcpad
1111 * Links the specifed #GstPad the @GstHarness srcpad.
1118 gst_harness_add_element_sink_pad (GstHarness * h, GstPad * sinkpad)
1120 GstHarnessPrivate *priv = h->priv;
1121 GstPadLinkReturn link;
1122 if (h->srcpad == NULL)
1123 gst_harness_setup_src_pad (h, &hsrctemplate, NULL);
1124 link = gst_pad_link (h->srcpad, sinkpad);
1125 g_assert_cmpint (link, ==, GST_PAD_LINK_OK);
1126 g_free (priv->element_sinkpad_name);
1127 priv->element_sinkpad_name = gst_pad_get_name (sinkpad);
1131 * gst_harness_set_src_caps:
1133 * @caps: (transfer full): a #GstCaps to set on the harness srcpad
1135 * Sets the @GstHarness srcpad caps. This must be done before any buffers
1136 * can legally be pushed from the harness to the element.
1143 gst_harness_set_src_caps (GstHarness * h, GstCaps * caps)
1145 GstHarnessPrivate *priv = h->priv;
1149 handled = gst_pad_push_event (h->srcpad, gst_event_new_caps (caps));
1151 gst_caps_take (&priv->src_caps, caps);
1153 gst_segment_init (&segment, GST_FORMAT_TIME);
1154 handled = gst_pad_push_event (h->srcpad, gst_event_new_segment (&segment));
1158 * gst_harness_set_sink_caps:
1160 * @caps: (transfer full): a #GstCaps to set on the harness sinkpad
1162 * Sets the @GstHarness sinkpad caps.
1169 gst_harness_set_sink_caps (GstHarness * h, GstCaps * caps)
1171 GstHarnessPrivate *priv = h->priv;
1173 gst_caps_take (&priv->sink_caps, caps);
1174 gst_pad_push_event (h->sinkpad, gst_event_new_reconfigure ());
1178 * gst_harness_set_caps:
1180 * @in: (transfer full): a #GstCaps to set on the harness srcpad
1181 * @out: (transfer full): a #GstCaps to set on the harness sinkpad
1183 * Sets the @GstHarness srcpad and sinkpad caps.
1190 gst_harness_set_caps (GstHarness * h, GstCaps * in, GstCaps * out)
1192 gst_harness_set_sink_caps (h, out);
1193 gst_harness_set_src_caps (h, in);
1197 * gst_harness_set_src_caps_str:
1199 * @str: a @gchar describing a #GstCaps to set on the harness srcpad
1201 * Sets the @GstHarness srcpad caps using a string. This must be done before
1202 * any buffers can legally be pushed from the harness to the element.
1209 gst_harness_set_src_caps_str (GstHarness * h, const gchar * str)
1211 gst_harness_set_src_caps (h, gst_caps_from_string (str));
1215 * gst_harness_set_sink_caps_str:
1217 * @str: a @gchar describing a #GstCaps to set on the harness sinkpad
1219 * Sets the @GstHarness sinkpad caps using a string.
1226 gst_harness_set_sink_caps_str (GstHarness * h, const gchar * str)
1228 gst_harness_set_sink_caps (h, gst_caps_from_string (str));
1232 * gst_harness_set_caps_str:
1234 * @in: a @gchar describing a #GstCaps to set on the harness srcpad
1235 * @out: a @gchar describing a #GstCaps to set on the harness sinkpad
1237 * Sets the @GstHarness srcpad and sinkpad caps using strings.
1244 gst_harness_set_caps_str (GstHarness * h, const gchar * in, const gchar * out)
1246 gst_harness_set_sink_caps_str (h, out);
1247 gst_harness_set_src_caps_str (h, in);
1251 * gst_harness_use_systemclock:
1254 * Sets the system #GstClock on the @GstHarness #GstElement
1261 gst_harness_use_systemclock (GstHarness * h)
1263 GstClock *clock = gst_system_clock_obtain ();
1264 g_assert (clock != NULL);
1265 gst_element_set_clock (h->element, clock);
1266 gst_object_unref (clock);
1270 * gst_harness_use_testclock:
1273 * Sets the #GstTestClock on the #GstHarness #GstElement
1280 gst_harness_use_testclock (GstHarness * h)
1282 gst_element_set_clock (h->element, GST_CLOCK_CAST (h->priv->testclock));
1286 * gst_harness_get_testclock:
1289 * Get the #GstTestClock. Useful if specific operations on the testclock is
1294 * Returns: (transfer full): a #GstTestClock, or %NULL if the testclock is not
1300 gst_harness_get_testclock (GstHarness * h)
1302 return gst_object_ref (h->priv->testclock);
1306 * gst_harness_set_time:
1308 * @time: a #GstClockTime to advance the clock to
1310 * Advance the #GstTestClock to a specific time.
1314 * Returns: a @gboolean %TRUE if the time could be set. %FALSE if not.
1319 gst_harness_set_time (GstHarness * h, GstClockTime time)
1321 gst_test_clock_set_time (h->priv->testclock, time);
1326 * gst_harness_wait_for_clock_id_waits:
1328 * @waits: a #guint describing the numbers of #GstClockID registered with
1330 * @timeout: a #guint describing how many seconds to wait for @waits to be true
1332 * Waits for @timeout seconds until @waits number of #GstClockID waits is
1333 * registered with the #GstTestClock. Useful for writing deterministic tests,
1334 * where you want to make sure that an expected number of waits have been
1339 * Returns: a @gboolean %TRUE if the waits have been registered, %FALSE if not.
1340 * (Could be that it timed out waiting or that more waits then waits was found)
1345 gst_harness_wait_for_clock_id_waits (GstHarness * h, guint waits, guint timeout)
1347 GstTestClock *testclock = h->priv->testclock;
1351 start_time = g_get_monotonic_time ();
1352 while (gst_test_clock_peek_id_count (testclock) < waits) {
1355 g_usleep (G_USEC_PER_SEC / 1000);
1356 time_spent = g_get_monotonic_time () - start_time;
1357 if ((time_spent / G_USEC_PER_SEC) > timeout)
1361 ret = (waits == gst_test_clock_peek_id_count (testclock));
1367 * gst_harness_crank_single_clock_wait:
1370 * A "crank" consists of three steps:
1371 * 1: Wait for a #GstClockID to be registered with the #GstTestClock.
1372 * 2: Advance the #GstTestClock to the time the #GstClockID is waiting for.
1373 * 3: Release the #GstClockID wait.
1374 * Together, this provides an easy way to not have to think about the details
1375 * around clocks and time, but still being able to write deterministic tests
1376 * that are dependant on this. A "crank" can be though of as the notion of
1377 * manually driving the clock forward to its next logical step.
1381 * Returns: a @gboolean %TRUE if the "crank" was successful, %FALSE if not.
1386 gst_harness_crank_single_clock_wait (GstHarness * h)
1388 return gst_test_clock_crank (h->priv->testclock);
1392 * gst_harness_crank_multiple_clock_waits:
1394 * @waits: a #guint describing the number of #GstClockIDs to crank
1396 * Similar to gst_harness_crank_single_clock_wait(), this is the function to use
1397 * if your harnessed element(s) are using more then one gst_clock_id_wait.
1398 * Failing to do so can (and will) make it racy which #GstClockID you actually
1399 * are releasing, where as this function will process all the waits at the
1400 * same time, ensuring that one thread can't register another wait before
1401 * both are released.
1405 * Returns: a @gboolean %TRUE if the "crank" was successful, %FALSE if not.
1410 gst_harness_crank_multiple_clock_waits (GstHarness * h, guint waits)
1412 GstTestClock *testclock = h->priv->testclock;
1416 gst_test_clock_wait_for_multiple_pending_ids (testclock, waits, &pending);
1417 gst_harness_set_time (h, gst_test_clock_id_list_get_latest_time (pending));
1418 processed = gst_test_clock_process_id_list (testclock, pending);
1420 g_list_free_full (pending, gst_clock_id_unref);
1421 return processed == waits;
1428 * This will set the harnessed #GstElement to %GST_STATE_PLAYING.
1429 * #GstElements without a sink-#GstPad and with the %GST_ELEMENT_FLAG_SOURCE
1430 * flag set is concidered a src #GstElement
1431 * Non-src #GstElements (like sinks and filters) are automatically set to
1432 * playing by the #GstHarness, but src #GstElements are not to avoid them
1433 * starting to produce buffers.
1434 * Hence, for src #GstElement you must call gst_harness_play() explicitly.
1441 gst_harness_play (GstHarness * h)
1443 GstState state, pending;
1444 gboolean state_change;
1445 state_change = gst_element_set_state (h->element, GST_STATE_PLAYING);
1446 g_assert_cmpint (GST_STATE_CHANGE_SUCCESS, ==, state_change);
1447 state_change = gst_element_get_state (h->element, &state, &pending, 0);
1448 g_assert_cmpint (GST_STATE_CHANGE_SUCCESS, ==, state_change);
1449 g_assert_cmpint (GST_STATE_PLAYING, ==, state);
1453 * gst_harness_set_blocking_push_mode:
1456 * Setting this will make the harness block in the chain-function, and
1457 * then release when gst_harness_pull() or gst_harness_try_pull() is called.
1458 * Can be useful when wanting to control a src-element that is not implementing
1459 * gst_clock_id_wait() so it can't be controlled by the #GstTestClock, since
1460 * it otherwise would produce buffers as fast as possible.
1467 gst_harness_set_blocking_push_mode (GstHarness * h)
1469 GstHarnessPrivate *priv = h->priv;
1470 priv->blocking_push_mode = TRUE;
1474 * gst_harness_set_forwarding:
1476 * @forwarding: a #gboolean to enable/disable forwarding
1478 * As a convenience, a src-harness will forward %GST_EVENT_STREAM_START,
1479 * %GST_EVENT_CAPS and %GST_EVENT_SEGMENT to the main-harness if forwarding
1480 * is enabled, and forward any sticky-events from the main-harness to
1481 * the sink-harness. It will also forward the %GST_QUERY_ALLOCATION.
1483 * If forwarding is disabled, the user will have to either manually push
1484 * these events from the src-harness using gst_harness_src_push_event(), or
1485 * create and push them manually. While this will allow full control and
1486 * inspection of these events, for the most cases having forwarding enabled
1487 * will be sufficient when writing a test where the src-harness' main function
1488 * is providing data for the main-harness.
1490 * Forwarding is enabled by default.
1497 gst_harness_set_forwarding (GstHarness * h, gboolean forwarding)
1499 GstHarnessPrivate *priv = h->priv;
1500 priv->forwarding = forwarding;
1502 gst_harness_set_forwarding (h->src_harness, forwarding);
1503 if (h->sink_harness)
1504 gst_harness_set_forwarding (h->sink_harness, forwarding);
1508 gst_harness_set_forward_pad (GstHarness * h, GstPad * fwdpad)
1511 gst_object_replace ((GstObject **) & h->priv->sink_forward_pad,
1512 (GstObject *) fwdpad);
1517 * gst_harness_create_buffer:
1519 * @size: a #gsize specifying the size of the buffer
1521 * Allocates a buffer using a #GstBufferPool if present, or else using the
1522 * configured #GstAllocator and #GstAllocationParams
1526 * Returns: a #GstBuffer of size @size
1531 gst_harness_create_buffer (GstHarness * h, gsize size)
1533 GstHarnessPrivate *priv = h->priv;
1534 GstBuffer *ret = NULL;
1537 if (gst_pad_check_reconfigure (h->srcpad))
1538 gst_harness_negotiate (h);
1541 flow = gst_buffer_pool_acquire_buffer (priv->pool, &ret, NULL);
1542 g_assert_cmpint (flow, ==, GST_FLOW_OK);
1543 if (gst_buffer_get_size (ret) != size) {
1544 GST_DEBUG_OBJECT (h,
1545 "use fallback, pool is configured with a different size (%zu != %zu)",
1546 size, gst_buffer_get_size (ret));
1547 gst_buffer_unref (ret);
1554 gst_buffer_new_allocate (priv->allocator, size,
1555 &priv->allocation_params);
1557 g_assert (ret != NULL);
1564 * @buffer: a #GstBuffer to push
1566 * Pushes a #GstBuffer on the #GstHarness srcpad. The standard way of
1567 * interacting with an harnessed element.
1571 * Returns: a #GstFlowReturn with the result from the push
1576 gst_harness_push (GstHarness * h, GstBuffer * buffer)
1578 GstHarnessPrivate *priv = h->priv;
1579 g_assert (buffer != NULL);
1580 priv->last_push_ts = GST_BUFFER_TIMESTAMP (buffer);
1581 return gst_pad_push (h->srcpad, buffer);
1588 * Pulls a #GstBuffer from the #GAsyncQueue on the #GstHarness sinkpad. The pull
1589 * will timeout in 60 seconds. This is the standard way of getting a buffer
1590 * from a harnessed #GstElement.
1594 * Returns: a #GstBuffer or %NULL if timed out.
1599 gst_harness_pull (GstHarness * h)
1601 GstHarnessPrivate *priv = h->priv;
1602 GstBuffer *buf = (GstBuffer *) g_async_queue_timeout_pop (priv->buffer_queue,
1603 G_USEC_PER_SEC * 60);
1605 if (priv->blocking_push_mode) {
1606 g_mutex_lock (&priv->blocking_push_mutex);
1607 g_cond_signal (&priv->blocking_push_cond);
1608 g_mutex_unlock (&priv->blocking_push_mutex);
1615 * gst_harness_try_pull:
1618 * Pulls a #GstBuffer from the #GAsyncQueue on the #GstHarness sinkpad. Unlike
1619 * gst_harness_pull this will not wait for any buffers if not any are present,
1620 * and return %NULL straight away.
1624 * Returns: a #GstBuffer or %NULL if no buffers are present in the #GAsyncQueue
1629 gst_harness_try_pull (GstHarness * h)
1631 GstHarnessPrivate *priv = h->priv;
1632 GstBuffer *buf = (GstBuffer *) g_async_queue_try_pop (priv->buffer_queue);
1634 if (priv->blocking_push_mode) {
1635 g_mutex_lock (&priv->blocking_push_mutex);
1636 g_cond_signal (&priv->blocking_push_cond);
1637 g_mutex_unlock (&priv->blocking_push_mutex);
1644 * gst_harness_push_and_pull:
1646 * @buffer: a #GstBuffer to push
1648 * Basically a gst_harness_push and a gst_harness_pull in one line. Reflects
1649 * the fact that you often want to do exactly this in your test: Push one buffer
1650 * in, and inspect the outcome.
1654 * Returns: a #GstBuffer or %NULL if timed out.
1659 gst_harness_push_and_pull (GstHarness * h, GstBuffer * buffer)
1661 gst_harness_push (h, buffer);
1662 return gst_harness_pull (h);
1666 * gst_harness_buffers_received:
1669 * The total number of #GstBuffers that has arrived on the #GstHarness sinkpad.
1670 * This number includes buffers that have been dropped as well as buffers
1671 * that have already been pulled out.
1675 * Returns: a #guint number of buffers received
1680 gst_harness_buffers_received (GstHarness * h)
1682 GstHarnessPrivate *priv = h->priv;
1683 return g_atomic_int_get (&priv->recv_buffers);
1687 * gst_harness_buffers_in_queue:
1690 * The number of #GstBuffers currently in the #GstHarness sinkpad #GAsyncQueue
1694 * Returns: a #guint number of buffers in the queue
1699 gst_harness_buffers_in_queue (GstHarness * h)
1701 GstHarnessPrivate *priv = h->priv;
1702 return g_async_queue_length (priv->buffer_queue);
1706 * gst_harness_set_drop_buffers:
1708 * @drop_buffers: a #gboolean specifying to drop outgoing buffers or not
1710 * When set to %TRUE, instead of placing the buffers arriving from the harnessed
1711 * #GstElement inside the sinkpads #GAsyncQueue, they are instead unreffed.
1718 gst_harness_set_drop_buffers (GstHarness * h, gboolean drop_buffers)
1720 GstHarnessPrivate *priv = h->priv;
1721 priv->drop_buffers = drop_buffers;
1725 * gst_harness_dump_to_file:
1727 * @filename: a #gchar with a the name of a file
1729 * Allows you to dump the #GstBuffers the #GstHarness sinkpad #GAsyncQueue
1737 gst_harness_dump_to_file (GstHarness * h, const gchar * filename)
1739 GstHarnessPrivate *priv = h->priv;
1742 fd = fopen (filename, "wb");
1745 while ((buf = g_async_queue_try_pop (priv->buffer_queue))) {
1747 if (gst_buffer_map (buf, &info, GST_MAP_READ)) {
1748 fwrite (info.data, 1, info.size, fd);
1749 gst_buffer_unmap (buf, &info);
1751 GST_ERROR ("failed to map buffer %p", buf);
1753 gst_buffer_unref (buf);
1761 * gst_harness_get_last_pushed_timestamp:
1764 * Get the timestamp of the last #GstBuffer pushed on the #GstHarness srcpad,
1765 * typically with gst_harness_push or gst_harness_push_from_src.
1769 * Returns: a #GstClockTime with the timestamp or %GST_CLOCK_TIME_NONE if no
1770 * #GstBuffer has been pushed on the #GstHarness srcpad
1775 gst_harness_get_last_pushed_timestamp (GstHarness * h)
1777 GstHarnessPrivate *priv = h->priv;
1778 return priv->last_push_ts;
1782 * gst_harness_push_event:
1784 * @event: a #GstEvent to push
1786 * Pushes an #GstEvent on the #GstHarness srcpad.
1790 * Returns: a #gboolean with the result from the push
1795 gst_harness_push_event (GstHarness * h, GstEvent * event)
1797 return gst_pad_push_event (h->srcpad, event);
1801 * gst_harness_pull_event:
1804 * Pulls an #GstEvent from the #GAsyncQueue on the #GstHarness sinkpad.
1805 * Timeouts after 60 seconds similar to gst_harness_pull.
1809 * Returns: a #GstEvent or %NULL if timed out.
1814 gst_harness_pull_event (GstHarness * h)
1816 GstHarnessPrivate *priv = h->priv;
1817 return (GstEvent *) g_async_queue_timeout_pop (priv->sink_event_queue,
1818 G_USEC_PER_SEC * 60);
1822 * gst_harness_try_pull_event:
1825 * Pulls an #GstEvent from the #GAsyncQueue on the #GstHarness sinkpad.
1826 * See gst_harness_try_pull for details.
1830 * Returns: a #GstEvent or %NULL if no buffers are present in the #GAsyncQueue
1835 gst_harness_try_pull_event (GstHarness * h)
1837 GstHarnessPrivate *priv = h->priv;
1838 return (GstEvent *) g_async_queue_try_pop (priv->sink_event_queue);
1842 * gst_harness_events_received:
1845 * The total number of #GstEvents that has arrived on the #GstHarness sinkpad
1846 * This number includes events handled by the harness as well as events
1847 * that have already been pulled out.
1851 * Returns: a #guint number of events received
1856 gst_harness_events_received (GstHarness * h)
1858 GstHarnessPrivate *priv = h->priv;
1859 return g_atomic_int_get (&priv->recv_events);
1863 * gst_harness_events_in_queue:
1866 * The number of #GstEvents currently in the #GstHarness sinkpad #GAsyncQueue
1870 * Returns: a #guint number of events in the queue
1875 gst_harness_events_in_queue (GstHarness * h)
1877 GstHarnessPrivate *priv = h->priv;
1878 return g_async_queue_length (priv->sink_event_queue);
1882 * gst_harness_push_upstream_event:
1884 * @event: a #GstEvent to push
1886 * Pushes an #GstEvent on the #GstHarness sinkpad.
1890 * Returns: a #gboolean with the result from the push
1895 gst_harness_push_upstream_event (GstHarness * h, GstEvent * event)
1897 g_return_val_if_fail (event != NULL, FALSE);
1898 g_return_val_if_fail (GST_EVENT_IS_UPSTREAM (event), FALSE);
1900 return gst_pad_push_event (h->sinkpad, event);
1904 * gst_harness_pull_upstream_event:
1907 * Pulls an #GstEvent from the #GAsyncQueue on the #GstHarness srcpad.
1908 * Timeouts after 60 seconds similar to gst_harness_pull.
1912 * Returns: a #GstEvent or %NULL if timed out.
1917 gst_harness_pull_upstream_event (GstHarness * h)
1919 GstHarnessPrivate *priv = h->priv;
1920 return (GstEvent *) g_async_queue_timeout_pop (priv->src_event_queue,
1921 G_USEC_PER_SEC * 60);
1925 * gst_harness_try_pull_upstream_event:
1928 * Pulls an #GstEvent from the #GAsyncQueue on the #GstHarness srcpad.
1929 * See gst_harness_try_pull for details.
1933 * Returns: a #GstEvent or %NULL if no buffers are present in the #GAsyncQueue
1938 gst_harness_try_pull_upstream_event (GstHarness * h)
1940 GstHarnessPrivate *priv = h->priv;
1941 return (GstEvent *) g_async_queue_try_pop (priv->src_event_queue);
1945 * gst_harness_upstream_events_received:
1948 * The total number of #GstEvents that has arrived on the #GstHarness srcpad
1949 * This number includes events handled by the harness as well as events
1950 * that have already been pulled out.
1954 * Returns: a #guint number of events received
1959 gst_harness_upstream_events_received (GstHarness * h)
1961 GstHarnessPrivate *priv = h->priv;
1962 return g_atomic_int_get (&priv->recv_upstream_events);
1966 * gst_harness_upstream_events_in_queue:
1969 * The number of #GstEvents currently in the #GstHarness srcpad #GAsyncQueue
1973 * Returns: a #guint number of events in the queue
1978 gst_harness_upstream_events_in_queue (GstHarness * h)
1980 GstHarnessPrivate *priv = h->priv;
1981 return g_async_queue_length (priv->src_event_queue);
1985 * gst_harness_query_latency:
1988 * Get the min latency reported by any harnessed #GstElement.
1992 * Returns: a #GstClockTime with min latency
1997 gst_harness_query_latency (GstHarness * h)
2001 GstClockTime min = GST_CLOCK_TIME_NONE;
2004 query = gst_query_new_latency ();
2006 if (gst_pad_peer_query (h->sinkpad, query)) {
2007 gst_query_parse_latency (query, &is_live, &min, &max);
2009 gst_query_unref (query);
2015 * gst_harness_set_upstream_latency:
2017 * @latency: a #GstClockTime specifying the latency
2019 * Sets the min latency reported by #GstHarness when receiving a latency-query
2024 gst_harness_set_upstream_latency (GstHarness * h, GstClockTime latency)
2026 GstHarnessPrivate *priv = h->priv;
2027 priv->latency_min = latency;
2031 * gst_harness_get_allocator:
2033 * @allocator: (out) (allow-none) (transfer none): the #GstAllocator used
2034 * @params: (out) (allow-none) (transfer full): the #GstAllocationParams of
2037 * Gets the @allocator and its @params that has been decided to use after an
2045 gst_harness_get_allocator (GstHarness * h, GstAllocator ** allocator,
2046 GstAllocationParams * params)
2048 GstHarnessPrivate *priv = h->priv;
2050 *allocator = priv->allocator;
2052 *params = priv->allocation_params;
2057 * gst_harness_set_propose_allocator:
2059 * @allocator: (allow-none) (transfer full): a #GstAllocator
2060 * @params: (allow-none) (transfer none): a #GstAllocationParams
2062 * Sets the @allocator and @params to propose when receiving an allocation
2070 gst_harness_set_propose_allocator (GstHarness * h, GstAllocator * allocator,
2071 const GstAllocationParams * params)
2073 GstHarnessPrivate *priv = h->priv;
2075 priv->propose_allocator = allocator;
2077 priv->propose_allocation_params = *params;
2081 * gst_harness_add_src_harness:
2083 * @src_harness: (transfer full): a #GstHarness to be added as a src-harness.
2084 * @has_clock_wait: a #gboolean specifying if the #GstElement uses
2085 * gst_clock_wait_id internally.
2087 * A src-harness is a great way of providing the #GstHarness with data.
2088 * By adding a src-type #GstElement, it is then easy to use functions like
2089 * gst_harness_push_from_src or gst_harness_src_crank_and_push_many
2090 * to provide your harnessed element with input. The @has_clock_wait variable
2091 * is a greate way to control you src-element with, in that you can have it
2092 * produce a buffer for you by simply cranking the clock, and not have it
2093 * spin out of control producing buffers as fast as possible.
2095 * If a src-harness already exists it will be replaced.
2102 gst_harness_add_src_harness (GstHarness * h,
2103 GstHarness * src_harness, gboolean has_clock_wait)
2106 gst_harness_teardown (h->src_harness);
2107 h->src_harness = src_harness;
2108 gst_harness_set_forward_pad (h->src_harness, h->srcpad);
2109 h->src_harness->priv->has_clock_wait = has_clock_wait;
2110 gst_harness_set_forwarding (h->src_harness, h->priv->forwarding);
2114 * gst_harness_add_src:
2116 * @src_element_name: a #gchar with the name of a #GstElement
2117 * @has_clock_wait: a #gboolean specifying if the #GstElement uses
2118 * gst_clock_wait_id internally.
2120 * Similar to gst_harness_add_src_harness, this is a convenience to
2121 * directly create a src-harness using the @src_element_name name specified.
2128 gst_harness_add_src (GstHarness * h,
2129 const gchar * src_element_name, gboolean has_clock_wait)
2131 GstHarness *src_harness = gst_harness_new (src_element_name);
2132 gst_harness_add_src_harness (h, src_harness, has_clock_wait);
2136 * gst_harness_add_src_parse:
2138 * @launchline: a #gchar describing a gst-launch type line
2139 * @has_clock_wait: a #gboolean specifying if the #GstElement uses
2140 * gst_clock_wait_id internally.
2142 * Similar to gst_harness_add_src, this allows you to specify a launch-line,
2143 * which can be useful for both having more then one #GstElement acting as your
2144 * src (Like a src producing raw buffers, and then an encoder, providing encoded
2145 * data), but also by allowing you to set properties like "is-live" directly on
2153 gst_harness_add_src_parse (GstHarness * h,
2154 const gchar * launchline, gboolean has_clock_wait)
2156 GstHarness *src_harness = gst_harness_new_parse (launchline);
2157 gst_harness_add_src_harness (h, src_harness, has_clock_wait);
2161 * gst_harness_push_from_src:
2164 * Transfer data from the src-#GstHarness to the main-#GstHarness. It consists
2166 * 1: Make sure the src is started. (see: gst_harness_play)
2167 * 2: Crank the clock (see: gst_harness_crank_single_clock_wait)
2168 * 3: Pull a #GstBuffer from the src-#GstHarness (see: gst_harness_pull)
2169 * 4: Push the same #GstBuffer into the main-#GstHarness (see: gst_harness_push)
2173 * Returns: a #GstFlowReturn with the result of the push
2178 gst_harness_push_from_src (GstHarness * h)
2183 g_assert (h->src_harness);
2185 /* FIXME: this *is* the right time to start the src,
2186 but maybe a flag so we don't keep telling it to play? */
2187 gst_harness_play (h->src_harness);
2189 if (h->src_harness->priv->has_clock_wait) {
2190 crank = gst_harness_crank_single_clock_wait (h->src_harness);
2194 buf = gst_harness_pull (h->src_harness);
2195 g_assert (buf != NULL);
2196 return gst_harness_push (h, buf);
2200 * gst_harness_src_crank_and_push_many:
2202 * @cranks: a #gint with the number of calls to gst_harness_crank_single_clock_wait
2203 * @pushes: a #gint with the number of calls to gst_harness_push
2205 * Transfer data from the src-#GstHarness to the main-#GstHarness. Similar to
2206 * gst_harness_push_from_src, this variant allows you to specify how many cranks
2207 * and how many pushes to perform. This can be useful for both moving a lot
2208 * of data at the same time, as well as cases when one crank does not equal one
2209 * buffer to push and v.v.
2213 * Returns: a #GstFlowReturn with the result of the push
2218 gst_harness_src_crank_and_push_many (GstHarness * h, gint cranks, gint pushes)
2220 GstFlowReturn ret = GST_FLOW_OK;
2224 g_assert (h->src_harness);
2225 gst_harness_play (h->src_harness);
2227 for (i = 0; i < cranks; i++) {
2228 crank = gst_harness_crank_single_clock_wait (h->src_harness);
2232 for (i = 0; i < pushes; i++) {
2234 buf = gst_harness_pull (h->src_harness);
2235 g_assert (buf != NULL);
2236 ret = gst_harness_push (h, buf);
2237 if (ret != GST_FLOW_OK)
2245 * gst_harness_src_push_event:
2248 * Similar to what gst_harness_src_push does with #GstBuffers, this transfers
2249 * a #GstEvent from the src-#GstHarness to the main-#GstHarness. Note that
2250 * some #GstEvents are being transferred automagically. Look at sink_forward_pad
2255 * Returns: a #gboolean with the result of the push
2260 gst_harness_src_push_event (GstHarness * h)
2262 return gst_harness_push_event (h, gst_harness_pull_event (h->src_harness));
2267 forward_sticky_events (GstPad * pad, GstEvent ** ev, gpointer user_data)
2269 GstHarness *h = user_data;
2270 return gst_pad_push_event (h->priv->sink_forward_pad, gst_event_ref (*ev));
2274 * gst_harness_add_sink_harness:
2276 * @sink_harness: (transfer full): a #GstHarness to be added as a sink-harness.
2278 * Similar to gst_harness_add_src, this allows you to send the data coming out
2279 * of your harnessed #GstElement to a sink-element, allowing to test different
2280 * responses the element output might create in sink elements. An example might
2281 * be an existing sink providing some analytical data on the input it receives that
2282 * can be useful to your testing. If the goal is to test a sink-element itself,
2283 * this is better acheived using gst_harness_new directly on the sink.
2285 * If a sink-harness already exists it will be replaced.
2292 gst_harness_add_sink_harness (GstHarness * h, GstHarness * sink_harness)
2294 GstHarnessPrivate *priv = h->priv;
2296 if (h->sink_harness) {
2297 gst_harness_set_forward_pad (h, NULL);
2298 gst_harness_teardown (h->sink_harness);
2300 h->sink_harness = sink_harness;
2301 gst_harness_set_forward_pad (h, h->sink_harness->srcpad);
2302 if (priv->forwarding && h->sinkpad)
2303 gst_pad_sticky_events_foreach (h->sinkpad, forward_sticky_events, h);
2304 gst_harness_set_forwarding (h->sink_harness, priv->forwarding);
2308 * gst_harness_add_sink:
2310 * @sink_element_name: a #gchar with the name of a #GstElement
2312 * Similar to gst_harness_add_sink_harness, this is a convenience to
2313 * directly create a sink-harness using the @sink_element_name name specified.
2320 gst_harness_add_sink (GstHarness * h, const gchar * sink_element_name)
2322 GstHarness *sink_harness = gst_harness_new (sink_element_name);
2323 gst_harness_add_sink_harness (h, sink_harness);
2327 * gst_harness_add_sink_parse:
2329 * @launchline: a #gchar with the name of a #GstElement
2331 * Similar to gst_harness_add_sink, this allows you to specify a launch-line
2332 * instead of just an element name. See gst_harness_add_src_parse for details.
2339 gst_harness_add_sink_parse (GstHarness * h, const gchar * launchline)
2341 GstHarness *sink_harness = gst_harness_new_parse (launchline);
2342 gst_harness_add_sink_harness (h, sink_harness);
2346 * gst_harness_push_to_sink:
2349 * Transfer one #GstBuffer from the main-#GstHarness to the sink-#GstHarness.
2350 * See gst_harness_push_from_src for details.
2354 * Returns: a #GstFlowReturn with the result of the push
2359 gst_harness_push_to_sink (GstHarness * h)
2362 g_assert (h->sink_harness);
2363 buf = gst_harness_pull (h);
2364 g_assert (buf != NULL);
2365 return gst_harness_push (h->sink_harness, buf);
2369 * gst_harness_sink_push_many:
2371 * @pushes: a #gint with the number of calls to gst_harness_push_to_sink
2373 * Convenience that calls gst_harness_push_to_sink @pushes number of times.
2374 * Will abort the pushing if any one push fails.
2378 * Returns: a #GstFlowReturn with the result of the push
2383 gst_harness_sink_push_many (GstHarness * h, gint pushes)
2385 GstFlowReturn ret = GST_FLOW_OK;
2387 g_assert (h->sink_harness);
2388 for (i = 0; i < pushes; i++) {
2389 ret = gst_harness_push_to_sink (h);
2390 if (ret != GST_FLOW_OK)
2397 * gst_harness_find_element:
2399 * @element_name: a #gchar with a #GstElementFactory name
2401 * Most useful in conjunction with gst_harness_new_parse, this will scan the
2402 * #GstElements inside the #GstHarness, and check if any of them matches
2403 * @element_name. Typical usecase being that you need to access one of the
2404 * harnessed elements for properties and/or signals.
2408 * Returns: (transfer full) (allow-none): a #GstElement or %NULL if not found
2413 gst_harness_find_element (GstHarness * h, const gchar * element_name)
2415 gboolean done = FALSE;
2417 GValue data = G_VALUE_INIT;
2419 iter = gst_bin_iterate_elements (GST_BIN (h->element));
2423 switch (gst_iterator_next (iter, &data)) {
2424 case GST_ITERATOR_OK:
2426 GstElement *element = g_value_get_object (&data);
2427 GstPluginFeature *feature =
2428 GST_PLUGIN_FEATURE (gst_element_get_factory (element));
2429 if (!strcmp (element_name, gst_plugin_feature_get_name (feature))) {
2430 gst_iterator_free (iter);
2433 g_value_reset (&data);
2436 case GST_ITERATOR_RESYNC:
2437 gst_iterator_resync (iter);
2439 case GST_ITERATOR_ERROR:
2440 case GST_ITERATOR_DONE:
2445 gst_iterator_free (iter);
2453 * @element_name: a #gchar with a #GstElementFactory name
2454 * @first_property_name: a #gchar with the first property name
2455 * @...: value for the first property, followed optionally by more
2456 * name/value pairs, followed by %NULL
2458 * A convenience function to allows you to call g_object_set on a #GstElement
2459 * that are residing inside the #GstHarness, by using normal g_object_set
2467 gst_harness_set (GstHarness * h,
2468 const gchar * element_name, const gchar * first_property_name, ...)
2471 GstElement *element = gst_harness_find_element (h, element_name);
2472 va_start (var_args, first_property_name);
2473 g_object_set_valist (G_OBJECT (element), first_property_name, var_args);
2475 gst_object_unref (element);
2481 * @element_name: a #gchar with a #GstElementFactory name
2482 * @first_property_name: a #gchar with the first property name
2483 * @...: return location for the first property, followed optionally by more
2484 * name/return location pairs, followed by %NULL
2486 * A convenience function to allows you to call g_object_get on a #GstElement
2487 * that are residing inside the #GstHarness, by using normal g_object_get
2495 gst_harness_get (GstHarness * h,
2496 const gchar * element_name, const gchar * first_property_name, ...)
2499 GstElement *element = gst_harness_find_element (h, element_name);
2500 va_start (var_args, first_property_name);
2501 g_object_get_valist (G_OBJECT (element), first_property_name, var_args);
2503 gst_object_unref (element);
2507 * gst_harness_add_probe:
2509 * @element_name: a #gchar with a #GstElementFactory name
2510 * @pad_name: a #gchar with the name of the pad to attach the probe to
2511 * @mask: a #GstPadProbeType (see gst_pad_add_probe)
2512 * @callback: a #GstPadProbeCallback (see gst_pad_add_probe)
2513 * @user_data: a #gpointer (see gst_pad_add_probe)
2514 * @destroy_data: a #GDestroyNotify (see gst_pad_add_probe)
2516 * A convenience function to allows you to call gst_pad_add_probe on a
2517 * #GstPad of a #GstElement that are residing inside the #GstHarness,
2518 * by using normal gst_pad_add_probe syntax
2525 gst_harness_add_probe (GstHarness * h,
2526 const gchar * element_name, const gchar * pad_name, GstPadProbeType mask,
2527 GstPadProbeCallback callback, gpointer user_data,
2528 GDestroyNotify destroy_data)
2530 GstElement *element = gst_harness_find_element (h, element_name);
2531 GstPad *pad = gst_element_get_static_pad (element, pad_name);
2532 gst_pad_add_probe (pad, mask, callback, user_data, destroy_data);
2533 gst_object_unref (pad);
2534 gst_object_unref (element);
2537 /******************************************************************************/
2539 /******************************************************************************/
2540 struct _GstHarnessThread
2548 GDestroyNotify freefunc;
2558 } GstHarnessCustomThread;
2566 GstHarnessPrepareBufferFunc func;
2568 GDestroyNotify notify;
2569 } GstHarnessPushBufferThread;
2575 GstHarnessPrepareEventFunc func;
2577 GDestroyNotify notify;
2578 } GstHarnessPushEventThread;
2586 } GstHarnessPropThread;
2592 GstPadTemplate *templ;
2598 } GstHarnessReqPadThread;
2601 gst_harness_thread_init (GstHarnessThread * t, GDestroyNotify freefunc,
2602 GstHarness * h, gulong sleep)
2604 t->freefunc = freefunc;
2608 g_ptr_array_add (h->priv->stress, t);
2612 gst_harness_thread_free (GstHarnessThread * t)
2614 g_slice_free (GstHarnessThread, t);
2618 gst_harness_custom_thread_free (GstHarnessCustomThread * t)
2620 g_slice_free (GstHarnessCustomThread, t);
2624 gst_harness_push_buffer_thread_free (GstHarnessPushBufferThread * t)
2627 gst_caps_replace (&t->caps, NULL);
2628 if (t->notify != NULL)
2629 t->notify (t->data);
2630 g_slice_free (GstHarnessPushBufferThread, t);
2635 gst_harness_push_event_thread_free (GstHarnessPushEventThread * t)
2638 if (t->notify != NULL)
2639 t->notify (t->data);
2640 g_slice_free (GstHarnessPushEventThread, t);
2645 gst_harness_property_thread_free (GstHarnessPropThread * t)
2649 g_value_unset (&t->value);
2650 g_slice_free (GstHarnessPropThread, t);
2655 gst_harness_requestpad_release (GstPad * pad, GstElement * element)
2657 gst_element_release_request_pad (element, pad);
2658 gst_object_unref (pad);
2662 gst_harness_requestpad_release_pads (GstHarnessReqPadThread * rpt)
2664 g_slist_foreach (rpt->pads, (GFunc) gst_harness_requestpad_release,
2666 g_slist_free (rpt->pads);
2671 gst_harness_requestpad_thread_free (GstHarnessReqPadThread * t)
2674 gst_object_replace ((GstObject **) & t->templ, NULL);
2676 gst_caps_replace (&t->caps, NULL);
2678 gst_harness_requestpad_release_pads (t);
2679 g_slice_free (GstHarnessReqPadThread, t);
2683 #define GST_HARNESS_THREAD_START(ID, t) \
2684 (((GstHarnessThread *)t)->running = TRUE, \
2685 ((GstHarnessThread *)t)->thread = g_thread_new ( \
2686 "gst-harness-stress-"G_STRINGIFY(ID), \
2687 (GThreadFunc)gst_harness_stress_##ID##_func, t))
2688 #define GST_HARNESS_THREAD_END(t) \
2689 (t->running = FALSE, \
2690 GPOINTER_TO_UINT (g_thread_join (t->thread)))
2693 gst_harness_stress_free (GstHarnessThread * t)
2695 if (t != NULL && t->freefunc != NULL)
2700 gst_harness_stress_custom_func (GstHarnessThread * t)
2702 GstHarnessCustomThread *ct = (GstHarnessCustomThread *) t;
2705 if (ct->init != NULL)
2706 ct->init (ct, ct->data);
2708 while (t->running) {
2709 ct->callback (ct, ct->data);
2712 g_usleep (t->sleep);
2714 return GUINT_TO_POINTER (count);
2719 gst_harness_stress_statechange_func (GstHarnessThread * t)
2723 while (t->running) {
2724 GstClock *clock = gst_element_get_clock (t->h->element);
2726 gboolean done = FALSE;
2729 change = gst_element_set_state (t->h->element, GST_STATE_NULL);
2730 g_assert (change == GST_STATE_CHANGE_SUCCESS);
2733 it = gst_element_iterate_sink_pads (t->h->element);
2735 GValue item = G_VALUE_INIT;
2736 switch (gst_iterator_next (it, &item)) {
2737 case GST_ITERATOR_OK:
2739 GstPad *sinkpad = g_value_get_object (&item);
2740 GstPad *srcpad = gst_pad_get_peer (sinkpad);
2741 if (srcpad != NULL) {
2742 gst_pad_unlink (srcpad, sinkpad);
2743 gst_pad_link (srcpad, sinkpad);
2744 gst_object_unref (srcpad);
2746 g_value_reset (&item);
2749 case GST_ITERATOR_RESYNC:
2750 gst_iterator_resync (it);
2752 case GST_ITERATOR_ERROR:
2753 g_assert_not_reached ();
2754 case GST_ITERATOR_DONE:
2758 g_value_unset (&item);
2760 gst_iterator_free (it);
2762 if (clock != NULL) {
2763 gst_element_set_clock (t->h->element, clock);
2764 gst_object_unref (clock);
2766 change = gst_element_set_state (t->h->element, GST_STATE_PLAYING);
2767 g_assert (change == GST_STATE_CHANGE_SUCCESS);
2770 g_usleep (t->sleep);
2772 return GUINT_TO_POINTER (count);
2776 gst_harness_stress_buffer_func (GstHarnessThread * t)
2778 GstHarnessPushBufferThread *pt = (GstHarnessPushBufferThread *) t;
2783 /* Push stream start, caps and segment events */
2784 sid = g_strdup_printf ("%s-%p", GST_OBJECT_NAME (t->h->element), t->h);
2785 handled = gst_pad_push_event (t->h->srcpad, gst_event_new_stream_start (sid));
2788 handled = gst_pad_push_event (t->h->srcpad, gst_event_new_caps (pt->caps));
2790 handled = gst_pad_push_event (t->h->srcpad,
2791 gst_event_new_segment (&pt->segment));
2794 while (t->running) {
2795 gst_harness_push (t->h, pt->func (t->h, pt->data));
2798 g_usleep (t->sleep);
2800 return GUINT_TO_POINTER (count);
2804 gst_harness_stress_event_func (GstHarnessThread * t)
2806 GstHarnessPushEventThread *pet = (GstHarnessPushEventThread *) t;
2809 while (t->running) {
2810 gst_harness_push_event (t->h, pet->func (t->h, pet->data));
2813 g_usleep (t->sleep);
2815 return GUINT_TO_POINTER (count);
2819 gst_harness_stress_upstream_event_func (GstHarnessThread * t)
2821 GstHarnessPushEventThread *pet = (GstHarnessPushEventThread *) t;
2824 while (t->running) {
2825 gst_harness_push_upstream_event (t->h, pet->func (t->h, pet->data));
2828 g_usleep (t->sleep);
2830 return GUINT_TO_POINTER (count);
2834 gst_harness_stress_property_func (GstHarnessThread * t)
2836 GstHarnessPropThread *pt = (GstHarnessPropThread *) t;
2839 while (t->running) {
2840 GValue value = G_VALUE_INIT;
2842 g_object_set_property (G_OBJECT (t->h->element), pt->name, &pt->value);
2844 g_value_init (&value, G_VALUE_TYPE (&pt->value));
2845 g_object_get_property (G_OBJECT (t->h->element), pt->name, &value);
2846 g_value_reset (&value);
2849 g_usleep (t->sleep);
2851 return GUINT_TO_POINTER (count);
2855 gst_harness_stress_requestpad_func (GstHarnessThread * t)
2857 GstHarnessReqPadThread *rpt = (GstHarnessReqPadThread *) t;
2860 while (t->running) {
2864 gst_harness_requestpad_release_pads (rpt);
2868 reqpad = gst_element_request_pad (t->h->element,
2869 rpt->templ, rpt->name, rpt->caps);
2871 g_assert (reqpad != NULL);
2873 rpt->pads = g_slist_prepend (rpt->pads, reqpad);
2876 g_usleep (t->sleep);
2878 return GUINT_TO_POINTER (count);
2882 * gst_harness_stress_thread_stop:
2883 * @t: a #GstHarnessThread
2885 * Stop the running #GstHarnessThread
2892 gst_harness_stress_thread_stop (GstHarnessThread * t)
2896 g_return_val_if_fail (t != NULL, 0);
2898 ret = GST_HARNESS_THREAD_END (t);
2899 g_ptr_array_remove (t->h->priv->stress, t);
2904 * gst_harness_stress_custom_start: (skip)
2906 * @init: (allow-none): a #GFunc that is called initially and only once
2907 * @callback: a #GFunc that is called as often as possible
2908 * @data: a #gpointer with custom data to pass to the @callback function
2909 * @sleep: a #gulong specifying how long to sleep in (microseconds) for
2910 * each call to the @callback
2912 * Start a custom stress-thread that will call your @callback for every
2913 * iteration allowing you to do something nasty.
2917 * Returns: a #GstHarnessThread
2922 gst_harness_stress_custom_start (GstHarness * h,
2923 GFunc init, GFunc callback, gpointer data, gulong sleep)
2925 GstHarnessCustomThread *t = g_slice_new0 (GstHarnessCustomThread);
2926 gst_harness_thread_init (&t->t,
2927 (GDestroyNotify) gst_harness_custom_thread_free, h, sleep);
2930 t->callback = callback;
2933 GST_HARNESS_THREAD_START (custom, t);
2938 * gst_harness_stress_statechange_start_full: (skip)
2940 * @sleep: a #gulong specifying how long to sleep in (microseconds) for
2943 * Change the state of your harnessed #GstElement from NULL to PLAYING and
2944 * back again, only pausing for @sleep microseconds every time.
2948 * Returns: a #GstHarnessThread
2953 gst_harness_stress_statechange_start_full (GstHarness * h, gulong sleep)
2955 GstHarnessThread *t = g_slice_new0 (GstHarnessThread);
2956 gst_harness_thread_init (t,
2957 (GDestroyNotify) gst_harness_thread_free, h, sleep);
2958 GST_HARNESS_THREAD_START (statechange, t);
2963 gst_harness_ref_buffer (GstHarness * h, gpointer data)
2966 return gst_buffer_ref (GST_BUFFER_CAST (data));
2970 gst_harness_ref_event (GstHarness * h, gpointer data)
2973 return gst_event_ref (GST_EVENT_CAST (data));
2977 * gst_harness_stress_push_buffer_start_full: (skip)
2979 * @caps: a #GstCaps for the #GstBuffer
2980 * @segment: a #GstSegment
2981 * @buf: a #GstBuffer to push
2982 * @sleep: a #gulong specifying how long to sleep in (microseconds) for
2983 * each call to gst_pad_push
2985 * Push a #GstBuffer in intervals of @sleep microseconds.
2989 * Returns: a #GstHarnessThread
2994 gst_harness_stress_push_buffer_start_full (GstHarness * h,
2995 GstCaps * caps, const GstSegment * segment, GstBuffer * buf, gulong sleep)
2997 return gst_harness_stress_push_buffer_with_cb_start_full (h, caps, segment,
2998 gst_harness_ref_buffer, gst_buffer_ref (buf),
2999 (GDestroyNotify) gst_buffer_unref, sleep);
3003 * gst_harness_stress_push_buffer_with_cb_start_full: (skip)
3005 * @caps: a #GstCaps for the #GstBuffer
3006 * @segment: a #GstSegment
3007 * @func: a #GstHarnessPrepareBufferFunc function called before every iteration
3008 * to prepare / create a #GstBuffer for pushing
3009 * @data: a #gpointer with data to the #GstHarnessPrepareBufferFunc function
3010 * @notify: a #GDestroyNotify that is called when thread is stopped
3011 * @sleep: a #gulong specifying how long to sleep in (microseconds) for
3012 * each call to gst_pad_push
3014 * Push a #GstBuffer returned by @func in intervals of @sleep microseconds.
3018 * Returns: a #GstHarnessThread
3023 gst_harness_stress_push_buffer_with_cb_start_full (GstHarness * h,
3024 GstCaps * caps, const GstSegment * segment,
3025 GstHarnessPrepareBufferFunc func, gpointer data, GDestroyNotify notify,
3028 GstHarnessPushBufferThread *t = g_slice_new0 (GstHarnessPushBufferThread);
3029 gst_harness_thread_init (&t->t,
3030 (GDestroyNotify) gst_harness_push_buffer_thread_free, h, sleep);
3032 gst_caps_replace (&t->caps, caps);
3033 t->segment = *segment;
3038 GST_HARNESS_THREAD_START (buffer, t);
3043 * gst_harness_stress_push_event_start_full: (skip)
3045 * @event: a #GstEvent to push
3046 * @sleep: a #gulong specifying how long to sleep in (microseconds) for
3047 * each gst_event_push with @event
3049 * Push the @event onto the harnessed #GstElement sinkpad in intervals of
3050 * @sleep microseconds
3054 * Returns: a #GstHarnessThread
3059 gst_harness_stress_push_event_start_full (GstHarness * h,
3060 GstEvent * event, gulong sleep)
3062 return gst_harness_stress_push_event_with_cb_start_full (h,
3063 gst_harness_ref_event, gst_event_ref (event),
3064 (GDestroyNotify) gst_event_unref, sleep);
3068 * gst_harness_stress_push_event_with_cb_start_full: (skip)
3070 * @func: a #GstHarnessPrepareEventFunc function called before every iteration
3071 * to prepare / create a #GstEvent for pushing
3072 * @data: a #gpointer with data to the #GstHarnessPrepareEventFunc function
3073 * @notify: a #GDestroyNotify that is called when thread is stopped
3074 * @sleep: a #gulong specifying how long to sleep in (microseconds) for
3075 * each call to gst_pad_push
3077 * Push a #GstEvent returned by @func onto the harnessed #GstElement sinkpad
3078 * in intervals of @sleep microseconds.
3082 * Returns: a #GstHarnessThread
3087 gst_harness_stress_push_event_with_cb_start_full (GstHarness * h,
3088 GstHarnessPrepareEventFunc func, gpointer data, GDestroyNotify notify,
3091 GstHarnessPushEventThread *t = g_slice_new0 (GstHarnessPushEventThread);
3092 gst_harness_thread_init (&t->t,
3093 (GDestroyNotify) gst_harness_push_event_thread_free, h, sleep);
3099 GST_HARNESS_THREAD_START (event, t);
3104 * gst_harness_stress_push_upstream_event_start_full: (skip)
3106 * @event: a #GstEvent to push
3107 * @sleep: a #gulong specifying how long to sleep in (microseconds) for
3108 * each gst_event_push with @event
3110 * Push the @event onto the harnessed #GstElement srcpad in intervals of
3111 * @sleep microseconds.
3115 * Returns: a #GstHarnessThread
3120 gst_harness_stress_push_upstream_event_start_full (GstHarness * h,
3121 GstEvent * event, gulong sleep)
3123 return gst_harness_stress_push_upstream_event_with_cb_start_full (h,
3124 gst_harness_ref_event, gst_event_ref (event),
3125 (GDestroyNotify) gst_event_unref, sleep);
3129 * gst_harness_stress_push_upstream_event_with_cb_start_full: (skip)
3131 * @func: a #GstHarnessPrepareEventFunc function called before every iteration
3132 * to prepare / create a #GstEvent for pushing
3133 * @data: a #gpointer with data to the #GstHarnessPrepareEventFunc function
3134 * @notify: a #GDestroyNotify that is called when thread is stopped
3135 * @sleep: a #gulong specifying how long to sleep in (microseconds) for
3136 * each call to gst_pad_push
3138 * Push a #GstEvent returned by @func onto the harnessed #GstElement srcpad
3139 * in intervals of @sleep microseconds.
3143 * Returns: a #GstHarnessThread
3148 gst_harness_stress_push_upstream_event_with_cb_start_full (GstHarness * h,
3149 GstHarnessPrepareEventFunc func, gpointer data, GDestroyNotify notify,
3152 GstHarnessPushEventThread *t = g_slice_new0 (GstHarnessPushEventThread);
3153 gst_harness_thread_init (&t->t,
3154 (GDestroyNotify) gst_harness_push_event_thread_free, h, sleep);
3160 GST_HARNESS_THREAD_START (upstream_event, t);
3165 * gst_harness_stress_property_start_full: (skip)
3167 * @name: a #gchar specifying a property name
3168 * @value: a #GValue to set the property to
3169 * @sleep: a #gulong specifying how long to sleep in (microseconds) for
3170 * each g_object_set with @name and @value
3172 * Call g_object_set with @name and @value in intervals of @sleep microseconds
3176 * Returns: a #GstHarnessThread
3181 gst_harness_stress_property_start_full (GstHarness * h,
3182 const gchar * name, const GValue * value, gulong sleep)
3184 GstHarnessPropThread *t = g_slice_new0 (GstHarnessPropThread);
3185 gst_harness_thread_init (&t->t,
3186 (GDestroyNotify) gst_harness_property_thread_free, h, sleep);
3188 t->name = g_strdup (name);
3189 g_value_init (&t->value, G_VALUE_TYPE (value));
3190 g_value_copy (value, &t->value);
3192 GST_HARNESS_THREAD_START (property, t);
3197 * gst_harness_stress_requestpad_start_full: (skip)
3199 * @templ: a #GstPadTemplate
3202 * @release: a #gboolean
3203 * @sleep: a #gulong specifying how long to sleep in (microseconds) for
3204 * each gst_element_request_pad
3206 * Call gst_element_request_pad in intervals of @sleep microseconds
3210 * Returns: a #GstHarnessThread
3215 gst_harness_stress_requestpad_start_full (GstHarness * h,
3216 GstPadTemplate * templ, const gchar * name, GstCaps * caps,
3217 gboolean release, gulong sleep)
3219 GstHarnessReqPadThread *t = g_slice_new0 (GstHarnessReqPadThread);
3220 gst_harness_thread_init (&t->t,
3221 (GDestroyNotify) gst_harness_requestpad_thread_free, h, sleep);
3223 t->templ = gst_object_ref (templ);
3224 t->name = g_strdup (name);
3225 gst_caps_replace (&t->caps, caps);
3226 t->release = release;
3228 GST_HARNESS_THREAD_START (requestpad, t);