docs: remove stray ',\' from doc comment
[platform/upstream/gstreamer.git] / libs / gst / check / gstharness.c
1 /* GstHarness - A test-harness for GStreamer testing
2  *
3  * Copyright (C) 2012-2015 Pexip <pexip.com>
4  *
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.
9  *
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.
14  *
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.
19  */
20
21 /**
22  * SECTION:gstharness
23  * @title: GstHarness
24  * @short_description: A test-harness for writing GStreamer unit tests
25  * @see_also: #GstTestClock
26  *
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.
30  *
31  * The basic structure of #GstHarness is two "floating" #GstPads that connect
32  * to the harnessed #GstElement src and sink #GstPads like so:
33  *
34  * |[
35  *           __________________________
36  *  _____   |  _____            _____  |   _____
37  * |     |  | |     |          |     | |  |     |
38  * | src |--+-| sink|  Element | src |-+--| sink|
39  * |_____|  | |_____|          |_____| |  |_____|
40  *          |__________________________|
41  *
42  * ]|
43  *
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.
48  *
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.
52  *
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().
57  *
58  * ## A simple buffer-in buffer-out example
59  *
60  * |[<!-- language="C" -->
61  *   #include <gst/gst.h>
62  *   #include <gst/check/gstharness.h>
63  *   GstHarness *h;
64  *   GstBuffer *in_buf;
65  *   GstBuffer *out_buf;
66  *
67  *   // attach the harness to the src and sink pad of GstQueue
68  *   h = gst_harness_new ("queue");
69  *
70  *   // we must specify a caps before pushing buffers
71  *   gst_harness_set_src_caps_str (h, "mycaps");
72  *
73  *   // create a buffer of size 42
74  *   in_buf = gst_harness_create_buffer (h, 42);
75  *
76  *   // push the buffer into the queue
77  *   gst_harness_push (h, in_buf);
78  *
79  *   // pull the buffer from the queue
80  *   out_buf = gst_harness_pull (h);
81  *
82  *   // validate the buffer in is the same as buffer out
83  *   fail_unless (in_buf == out_buf);
84  *
85  *   // cleanup
86  *   gst_buffer_unref (out_buf);
87  *   gst_harness_teardown (h);
88  *
89  *   ]|
90  *
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().
96  *
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:
106  *
107  * |[<!-- language="C" -->
108  *   GstHarness * h = gst_harness_new (h, "vp8dec");
109  *   gst_harness_add_src_parse (h, "videotestsrc is-live=1 ! vp8enc", TRUE);
110  * ]|
111  *
112  * and then feeding it data with:
113  *
114  * |[<!-- language="C" -->
115  * gst_harness_push_from_src (h);
116  * ]|
117  *
118  */
119 #ifdef HAVE_CONFIG_H
120 #include "config.h"
121 #endif
122
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"
126 #endif
127
128 #include "gstharness.h"
129
130 #include <stdio.h>
131 #include <string.h>
132 #include <math.h>
133
134 static void gst_harness_stress_free (GstHarnessThread * t);
135
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)
140
141 static GstStaticPadTemplate hsrctemplate = GST_STATIC_PAD_TEMPLATE ("src",
142     GST_PAD_SRC,
143     GST_PAD_ALWAYS,
144     GST_STATIC_CAPS_ANY);
145 static GstStaticPadTemplate hsinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
146     GST_PAD_SINK,
147     GST_PAD_ALWAYS,
148     GST_STATIC_CAPS_ANY);
149
150 struct _GstHarnessPrivate
151 {
152   gchar *element_sinkpad_name;
153   gchar *element_srcpad_name;
154
155   GstCaps *src_caps;
156   GstCaps *sink_caps;
157
158   gboolean forwarding;
159   GstPad *sink_forward_pad;
160   GstTestClock *testclock;
161
162   volatile gint recv_buffers;
163   volatile gint recv_events;
164   volatile gint recv_upstream_events;
165
166   GAsyncQueue *buffer_queue;
167   GAsyncQueue *src_event_queue;
168   GAsyncQueue *sink_event_queue;
169
170   GstClockTime latency_min;
171   GstClockTime latency_max;
172   gboolean has_clock_wait;
173   gboolean drop_buffers;
174   GstClockTime last_push_ts;
175
176   GstBufferPool *pool;
177   GstAllocator *allocator;
178   GstAllocationParams allocation_params;
179   GstAllocator *propose_allocator;
180   GstAllocationParams propose_allocation_params;
181
182   gboolean blocking_push_mode;
183   GCond blocking_push_cond;
184   GMutex blocking_push_mutex;
185   GMutex priv_mutex;
186
187   GPtrArray *stress;
188 };
189
190 static GstFlowReturn
191 gst_harness_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
192 {
193   GstHarness *h = g_object_get_data (G_OBJECT (pad), HARNESS_KEY);
194   GstHarnessPrivate *priv = h->priv;
195   (void) parent;
196   g_assert (h != NULL);
197   g_mutex_lock (&priv->blocking_push_mutex);
198   g_atomic_int_inc (&priv->recv_buffers);
199
200   if (priv->drop_buffers)
201     gst_buffer_unref (buffer);
202   else
203     g_async_queue_push (priv->buffer_queue, buffer);
204
205   if (priv->blocking_push_mode) {
206     g_cond_wait (&priv->blocking_push_cond, &priv->blocking_push_mutex);
207   }
208   g_mutex_unlock (&priv->blocking_push_mutex);
209
210   return GST_FLOW_OK;
211 }
212
213 static gboolean
214 gst_harness_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
215 {
216   GstHarness *h = g_object_get_data (G_OBJECT (pad), HARNESS_KEY);
217   GstHarnessPrivate *priv = h->priv;
218   (void) parent;
219   g_assert (h != NULL);
220   g_atomic_int_inc (&priv->recv_upstream_events);
221   g_async_queue_push (priv->src_event_queue, event);
222   return TRUE;
223 }
224
225 static gboolean
226 gst_harness_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
227 {
228   GstHarness *h = g_object_get_data (G_OBJECT (pad), HARNESS_KEY);
229   GstHarnessPrivate *priv = h->priv;
230   gboolean ret = TRUE;
231   gboolean forward;
232
233   g_assert (h != NULL);
234   (void) parent;
235   g_atomic_int_inc (&priv->recv_events);
236
237   switch (GST_EVENT_TYPE (event)) {
238     case GST_EVENT_STREAM_START:
239     case GST_EVENT_CAPS:
240     case GST_EVENT_SEGMENT:
241       forward = TRUE;
242       break;
243     default:
244       forward = FALSE;
245       break;
246   }
247
248   HARNESS_LOCK (h);
249   if (priv->forwarding && forward && priv->sink_forward_pad) {
250     GstPad *fwdpad = gst_object_ref (priv->sink_forward_pad);
251     HARNESS_UNLOCK (h);
252     ret = gst_pad_push_event (fwdpad, event);
253     gst_object_unref (fwdpad);
254     HARNESS_LOCK (h);
255   } else {
256     g_async_queue_push (priv->sink_event_queue, event);
257   }
258   HARNESS_UNLOCK (h);
259
260   return ret;
261 }
262
263 static void
264 gst_harness_decide_allocation (GstHarness * h, GstCaps * caps)
265 {
266   GstHarnessPrivate *priv = h->priv;
267   GstQuery *query;
268   GstAllocator *allocator;
269   GstAllocationParams params;
270   GstBufferPool *pool = NULL;
271   guint size, min, max;
272
273   query = gst_query_new_allocation (caps, FALSE);
274   gst_pad_peer_query (h->srcpad, query);
275
276   if (gst_query_get_n_allocation_params (query) > 0) {
277     gst_query_parse_nth_allocation_param (query, 0, &allocator, &params);
278   } else {
279     allocator = NULL;
280     gst_allocation_params_init (&params);
281   }
282
283   if (gst_query_get_n_allocation_pools (query) > 0) {
284     gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
285 #if 0
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. */
290     if (pool == NULL)
291       pool = gst_buffer_pool_new ();
292 #endif
293   } else {
294     pool = NULL;
295     size = min = max = 0;
296   }
297   gst_query_unref (query);
298
299   if (pool) {
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, &params);
303     gst_buffer_pool_set_config (pool, config);
304   }
305
306   if (pool != priv->pool) {
307     if (priv->pool != NULL)
308       gst_buffer_pool_set_active (priv->pool, FALSE);
309     if (pool)
310       gst_buffer_pool_set_active (pool, TRUE);
311   }
312
313   priv->allocation_params = params;
314   if (priv->allocator)
315     gst_object_unref (priv->allocator);
316   priv->allocator = allocator;
317   if (priv->pool)
318     gst_object_unref (priv->pool);
319   priv->pool = pool;
320 }
321
322 static void
323 gst_harness_negotiate (GstHarness * h)
324 {
325   GstCaps *caps;
326
327   caps = gst_pad_get_current_caps (h->srcpad);
328   if (caps != NULL) {
329     gst_harness_decide_allocation (h, caps);
330     gst_caps_unref (caps);
331   } else {
332     GST_FIXME_OBJECT (h, "Cannot negotiate allocation because caps is not set");
333   }
334 }
335
336 static gboolean
337 gst_harness_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
338 {
339   GstHarness *h = g_object_get_data (G_OBJECT (pad), HARNESS_KEY);
340   GstHarnessPrivate *priv = h->priv;
341   gboolean res = TRUE;
342   g_assert (h != NULL);
343
344   // FIXME: forward all queries?
345
346   switch (GST_QUERY_TYPE (query)) {
347     case GST_QUERY_LATENCY:
348       gst_query_set_latency (query, TRUE, priv->latency_min, priv->latency_max);
349       break;
350     case GST_QUERY_CAPS:
351     {
352       GstCaps *caps, *filter = NULL;
353
354       if (priv->sink_caps) {
355         caps = gst_caps_ref (priv->sink_caps);
356       } else {
357         caps = gst_pad_get_pad_template_caps (pad);
358       }
359
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));
364       }
365
366       gst_query_set_caps_result (query, caps);
367       gst_caps_unref (caps);
368     }
369       break;
370     case GST_QUERY_ALLOCATION:
371     {
372       HARNESS_LOCK (h);
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);
376         HARNESS_UNLOCK (h);
377         res = gst_pad_query (peer, query);
378         gst_object_unref (peer);
379         HARNESS_LOCK (h);
380       } else {
381         GstCaps *caps;
382         gboolean need_pool;
383         guint size;
384
385         gst_query_parse_allocation (query, &caps, &need_pool);
386
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);
392
393         GST_DEBUG_OBJECT (pad, "proposing allocation %" GST_PTR_FORMAT,
394             priv->propose_allocator);
395       }
396       HARNESS_UNLOCK (h);
397       break;
398     }
399     default:
400       res = gst_pad_query_default (pad, parent, query);
401   }
402
403   return res;
404 }
405
406 static gboolean
407 gst_harness_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
408 {
409   GstHarness *h = g_object_get_data (G_OBJECT (pad), HARNESS_KEY);
410   GstHarnessPrivate *priv = h->priv;
411   gboolean res = TRUE;
412   g_assert (h != NULL);
413
414   switch (GST_QUERY_TYPE (query)) {
415     case GST_QUERY_LATENCY:
416       gst_query_set_latency (query, TRUE, priv->latency_min, priv->latency_max);
417       break;
418     case GST_QUERY_CAPS:
419     {
420       GstCaps *caps, *filter = NULL;
421
422       if (priv->src_caps) {
423         caps = gst_caps_ref (priv->src_caps);
424       } else {
425         caps = gst_pad_get_pad_template_caps (pad);
426       }
427
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));
432       }
433
434       gst_query_set_caps_result (query, caps);
435       gst_caps_unref (caps);
436     }
437       break;
438     default:
439       res = gst_pad_query_default (pad, parent, query);
440   }
441   return res;
442 }
443
444 static void
445 gst_harness_element_ref (GstHarness * h)
446 {
447   guint *data;
448
449   GST_OBJECT_LOCK (h->element);
450   data = g_object_get_data (G_OBJECT (h->element), HARNESS_REF);
451   if (data == NULL) {
452     data = g_new0 (guint, 1);
453     *data = 1;
454     g_object_set_data_full (G_OBJECT (h->element), HARNESS_REF, data, g_free);
455   } else {
456     (*data)++;
457   }
458   GST_OBJECT_UNLOCK (h->element);
459 }
460
461 static guint
462 gst_harness_element_unref (GstHarness * h)
463 {
464   guint *data;
465   guint ret;
466
467   GST_OBJECT_LOCK (h->element);
468   data = g_object_get_data (G_OBJECT (h->element), HARNESS_REF);
469   g_assert (data != NULL);
470   (*data)--;
471   ret = *data;
472   GST_OBJECT_UNLOCK (h->element);
473
474   return ret;
475 }
476
477 static void
478 gst_harness_link_element_srcpad (GstHarness * h,
479     const gchar * element_srcpad_name)
480 {
481   GstHarnessPrivate *priv = h->priv;
482   GstPad *srcpad = gst_element_get_static_pad (h->element,
483       element_srcpad_name);
484   GstPadLinkReturn link;
485   if (srcpad == NULL)
486     srcpad = gst_element_get_request_pad (h->element, element_srcpad_name);
487   g_assert (srcpad);
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);
492
493   gst_object_unref (srcpad);
494 }
495
496 static void
497 gst_harness_link_element_sinkpad (GstHarness * h,
498     const gchar * element_sinkpad_name)
499 {
500   GstHarnessPrivate *priv = h->priv;
501   GstPad *sinkpad = gst_element_get_static_pad (h->element,
502       element_sinkpad_name);
503   GstPadLinkReturn link;
504   if (sinkpad == NULL)
505     sinkpad = gst_element_get_request_pad (h->element, element_sinkpad_name);
506   g_assert (sinkpad);
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);
511
512   gst_object_unref (sinkpad);
513 }
514
515 static void
516 gst_harness_setup_src_pad (GstHarness * h,
517     GstStaticPadTemplate * src_tmpl, const gchar * element_sinkpad_name)
518 {
519   GstHarnessPrivate *priv = h->priv;
520   g_assert (src_tmpl);
521   g_assert (h->srcpad == NULL);
522
523   priv->src_event_queue =
524       g_async_queue_new_full ((GDestroyNotify) gst_event_unref);
525
526   /* sending pad */
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);
530
531   gst_pad_set_query_function (h->srcpad, gst_harness_src_query);
532   gst_pad_set_event_function (h->srcpad, gst_harness_src_event);
533
534   gst_pad_set_active (h->srcpad, TRUE);
535
536   if (element_sinkpad_name)
537     gst_harness_link_element_sinkpad (h, element_sinkpad_name);
538 }
539
540 static void
541 gst_harness_setup_sink_pad (GstHarness * h,
542     GstStaticPadTemplate * sink_tmpl, const gchar * element_srcpad_name)
543 {
544   GstHarnessPrivate *priv = h->priv;
545   g_assert (sink_tmpl);
546   g_assert (h->sinkpad == NULL);
547
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);
552
553   /* receiving pad */
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);
557
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);
561
562   gst_pad_set_active (h->sinkpad, TRUE);
563
564   if (element_srcpad_name)
565     gst_harness_link_element_srcpad (h, element_srcpad_name);
566 }
567
568 static void
569 check_element_type (GstElement * element, gboolean * has_sinkpad,
570     gboolean * has_srcpad)
571 {
572   GstElementClass *element_class = GST_ELEMENT_GET_CLASS (element);
573   const GList *tmpl_list;
574
575   *has_srcpad = element->numsrcpads > 0;
576   *has_sinkpad = element->numsinkpads > 0;
577
578   tmpl_list = gst_element_class_get_pad_template_list (element_class);
579
580   while (tmpl_list) {
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)
584       *has_srcpad |= TRUE;
585     if (GST_PAD_TEMPLATE_DIRECTION (pad_tmpl) == GST_PAD_SINK)
586       *has_sinkpad |= TRUE;
587   }
588 }
589
590 static void
591 turn_async_and_sync_off (GstElement * element)
592 {
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);
598 }
599
600 static gboolean
601 gst_pad_is_request_pad (GstPad * pad)
602 {
603   GstPadTemplate *temp;
604   gboolean is_request;
605
606   if (pad == NULL)
607     return FALSE;
608   temp = gst_pad_get_pad_template (pad);
609   if (temp == NULL)
610     return FALSE;
611   is_request = GST_PAD_TEMPLATE_PRESENCE (temp) == GST_PAD_REQUEST;
612   gst_object_unref (temp);
613   return is_request;
614 }
615
616 /**
617  * gst_harness_new_empty: (skip)
618  *
619  * Creates a new empty harness. Use gst_harness_add_element_full() to add
620  * an #GstElement to it.
621  *
622  * MT safe.
623  *
624  * Returns: (transfer full): a #GstHarness, or %NULL if the harness could
625  * not be created
626  *
627  * Since: 1.8
628  */
629 GstHarness *
630 gst_harness_new_empty (void)
631 {
632   GstHarness *h;
633   GstHarnessPrivate *priv;
634
635   h = g_new0 (GstHarness, 1);
636   g_assert (h != NULL);
637   h->priv = g_new0 (GstHarnessPrivate, 1);
638   priv = h->priv;
639
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 ());
646
647   priv->propose_allocator = NULL;
648   gst_allocation_params_init (&priv->propose_allocation_params);
649
650   g_mutex_init (&priv->blocking_push_mutex);
651   g_cond_init (&priv->blocking_push_cond);
652   g_mutex_init (&priv->priv_mutex);
653
654   priv->stress = g_ptr_array_new_with_free_func (
655       (GDestroyNotify) gst_harness_stress_free);
656
657   /* we have forwarding on as a default */
658   gst_harness_set_forwarding (h, TRUE);
659
660   return h;
661 }
662
663 /**
664  * gst_harness_add_element_full: (skip)
665  * @h: a #GstHarness
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.
678  *
679  * Adds a #GstElement to an empty #GstHarness
680  *
681  * MT safe.
682  *
683  * Since: 1.6
684  */
685 void
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)
689 {
690   GstClock *element_clock;
691   gboolean has_sinkpad, has_srcpad;
692
693   g_return_if_fail (element != NULL);
694   g_return_if_fail (h->element == NULL);
695
696   element_clock = GST_ELEMENT_CLOCK (element);
697   h->element = gst_object_ref (element);
698   check_element_type (element, &has_sinkpad, &has_srcpad);
699
700   /* setup the loose srcpad linked to the element sinkpad */
701   if (has_sinkpad)
702     gst_harness_setup_src_pad (h, hsrc, element_sinkpad_name);
703
704   /* setup the loose sinkpad linked to the element srcpad */
705   if (has_srcpad)
706     gst_harness_setup_sink_pad (h, hsink, element_srcpad_name);
707
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);
711
712   if (h->srcpad != NULL) {
713     gboolean handled;
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));
718     g_assert (handled);
719     g_free (stream_id);
720   }
721
722   /* if the element already has a testclock attached,
723      we replace our own with it, if no clock we attach the testclock */
724   if (element_clock) {
725     if (GST_IS_TEST_CLOCK (element_clock)) {
726       gst_object_replace ((GstObject **) & h->priv->testclock,
727           (GstObject *) GST_ELEMENT_CLOCK (element));
728     }
729   } else {
730     gst_harness_use_testclock (h);
731   }
732
733   /* don't start sources, they start producing data! */
734   if (has_sinkpad)
735     gst_harness_play (h);
736
737   gst_harness_element_ref (h);
738
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));
743 }
744
745 /**
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.
759  *
760  * Creates a new harness.
761  *
762  * MT safe.
763  *
764  * Returns: (transfer full): a #GstHarness, or %NULL if the harness could
765  * not be created
766  *
767  * Since: 1.6
768  */
769 GstHarness *
770 gst_harness_new_full (GstElement * element,
771     GstStaticPadTemplate * hsrc, const gchar * element_sinkpad_name,
772     GstStaticPadTemplate * hsink, const gchar * element_srcpad_name)
773 {
774   GstHarness *h;
775   h = gst_harness_new_empty ();
776   gst_harness_add_element_full (h, element,
777       hsrc, element_sinkpad_name, hsink, element_srcpad_name);
778   return h;
779 }
780
781 /**
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
786  * sinkpad
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
789  * srcpad
790  *
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.
794  *
795  * MT safe.
796  *
797  * Returns: (transfer full): a #GstHarness, or %NULL if the harness could
798  * not be created
799  *
800  * Since: 1.6
801  */
802 GstHarness *
803 gst_harness_new_with_element (GstElement * element,
804     const gchar * element_sinkpad_name, const gchar * element_srcpad_name)
805 {
806   return gst_harness_new_full (element,
807       &hsrctemplate, element_sinkpad_name, &hsinktemplate, element_srcpad_name);
808 }
809
810 /**
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
815  * sinkpad
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
818  * srcpad
819  *
820  * Creates a new harness. Works like gst_harness_new_with_element(),
821  * except you specify the factoryname of the #GstElement
822  *
823  * MT safe.
824  *
825  * Returns: (transfer full): a #GstHarness, or %NULL if the harness could
826  * not be created
827  *
828  * Since: 1.6
829  */
830 GstHarness *
831 gst_harness_new_with_padnames (const gchar * element_name,
832     const gchar * element_sinkpad_name, const gchar * element_srcpad_name)
833 {
834   GstHarness *h;
835   GstElement *element = gst_element_factory_make (element_name, NULL);
836   g_assert (element != NULL);
837
838   h = gst_harness_new_with_element (element, element_sinkpad_name,
839       element_srcpad_name);
840   gst_object_unref (element);
841   return h;
842 }
843
844 /**
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.
851  *
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"
854  *
855  * MT safe.
856  *
857  * Returns: (transfer full): a #GstHarness, or %NULL if the harness could
858  * not be created
859  *
860  * Since: 1.6
861  */
862 GstHarness *
863 gst_harness_new_with_templates (const gchar * element_name,
864     GstStaticPadTemplate * hsrc, GstStaticPadTemplate * hsink)
865 {
866   GstHarness *h;
867   GstElement *element = gst_element_factory_make (element_name, NULL);
868   g_assert (element != NULL);
869
870   h = gst_harness_new_full (element, hsrc, "sink", hsink, "src");
871   gst_object_unref (element);
872   return h;
873 }
874
875 /**
876  * gst_harness_new: (skip)
877  * @element_name: a #gchar describing the #GstElement name
878  *
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"
881  *
882  * MT safe.
883  *
884  * Returns: (transfer full): a #GstHarness, or %NULL if the harness could
885  * not be created
886  *
887  * Since: 1.6
888  */
889 GstHarness *
890 gst_harness_new (const gchar * element_name)
891 {
892   return gst_harness_new_with_padnames (element_name, "sink", "src");
893 }
894
895 /**
896  * gst_harness_add_parse: (skip)
897  * @h: a #GstHarness
898  * @launchline: a #gchar describing a gst-launch type line
899  *
900  * Parses the @launchline and puts that in a #GstBin,
901  * and then attches the supplied #GstHarness to the bin.
902  *
903  * MT safe.
904  *
905  * Since: 1.6
906  */
907 void
908 gst_harness_add_parse (GstHarness * h, const gchar * launchline)
909 {
910   GstBin *bin;
911   gchar *desc;
912   GstPad *pad;
913   GstIterator *iter;
914   gboolean done = FALSE;
915   GError *error = NULL;
916
917   g_return_if_fail (launchline != NULL);
918
919   desc = g_strdup_printf ("bin.( %s )", launchline);
920   bin =
921       (GstBin *) gst_parse_launch_full (desc, NULL, GST_PARSE_FLAG_FATAL_ERRORS,
922       &error);
923
924   if (G_UNLIKELY (error != NULL)) {
925     g_error ("Unable to create pipeline '%s': %s", desc, error->message);
926   }
927   g_free (desc);
928
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);
933   }
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);
937   }
938
939   iter = gst_bin_iterate_sinks (bin);
940   while (!done) {
941     GValue item = { 0, };
942
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);
947         break;
948       case GST_ITERATOR_DONE:
949         done = TRUE;
950         break;
951       case GST_ITERATOR_RESYNC:
952         gst_iterator_resync (iter);
953         break;
954       case GST_ITERATOR_ERROR:
955         gst_object_unref (bin);
956         gst_iterator_free (iter);
957         g_return_if_reached ();
958         break;
959     }
960   }
961   gst_iterator_free (iter);
962
963   gst_harness_add_element_full (h, GST_ELEMENT_CAST (bin),
964       &hsrctemplate, "sink", &hsinktemplate, "src");
965   gst_object_unref (bin);
966 }
967
968 /**
969  * gst_harness_new_parse: (skip)
970  * @launchline: a #gchar describing a gst-launch type line
971  *
972  * Creates a new harness, parsing the @launchline and putting that in a #GstBin,
973  * and then attches the harness to the bin.
974  *
975  * MT safe.
976  *
977  * Returns: (transfer full): a #GstHarness, or %NULL if the harness could
978  * not be created
979  *
980  * Since: 1.6
981  */
982 GstHarness *
983 gst_harness_new_parse (const gchar * launchline)
984 {
985   GstHarness *h;
986   h = gst_harness_new_empty ();
987   gst_harness_add_parse (h, launchline);
988   return h;
989 }
990
991 /**
992  * gst_harness_teardown:
993  * @h: a #GstHarness
994  *
995  * Tears down a @GstHarness, freeing all resources allocated using it.
996  *
997  * MT safe.
998  *
999  * Since: 1.6
1000  */
1001 void
1002 gst_harness_teardown (GstHarness * h)
1003 {
1004   GstHarnessPrivate *priv = h->priv;
1005
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);
1011   }
1012
1013   if (h->src_harness) {
1014     gst_harness_teardown (h->src_harness);
1015   }
1016
1017   gst_object_replace ((GstObject **) & priv->sink_forward_pad, NULL);
1018   if (h->sink_harness) {
1019     gst_harness_teardown (h->sink_harness);
1020   }
1021
1022   if (priv->src_caps)
1023     gst_caps_unref (priv->src_caps);
1024
1025   if (priv->sink_caps)
1026     gst_caps_unref (priv->sink_caps);
1027
1028   if (h->srcpad) {
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);
1032
1033     gst_pad_set_active (h->srcpad, FALSE);
1034     gst_object_unref (h->srcpad);
1035
1036     g_async_queue_unref (priv->src_event_queue);
1037   }
1038
1039   if (h->sinkpad) {
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);
1043
1044     gst_pad_set_active (h->sinkpad, FALSE);
1045     gst_object_unref (h->sinkpad);
1046
1047     g_async_queue_unref (priv->buffer_queue);
1048     g_async_queue_unref (priv->sink_event_queue);
1049   }
1050
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);
1054
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);
1064   }
1065
1066   g_cond_clear (&priv->blocking_push_cond);
1067   g_mutex_clear (&priv->blocking_push_mutex);
1068   g_mutex_clear (&priv->priv_mutex);
1069
1070   g_ptr_array_unref (priv->stress);
1071
1072   gst_object_unref (h->element);
1073
1074   gst_object_replace ((GstObject **) & priv->testclock, NULL);
1075
1076   g_free (h->priv);
1077   g_free (h);
1078 }
1079
1080 /**
1081  * gst_harness_add_element_src_pad:
1082  * @h: a #GstHarness
1083  * @srcpad: a #GstPad to link to the harness sinkpad
1084  *
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.
1088  *
1089  * MT safe.
1090  *
1091  * Since: 1.6
1092  */
1093 void
1094 gst_harness_add_element_src_pad (GstHarness * h, GstPad * srcpad)
1095 {
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);
1104 }
1105
1106 /**
1107  * gst_harness_add_element_sink_pad:
1108  * @h: a #GstHarness
1109  * @sinkpad: a #GstPad to link to the harness srcpad
1110  *
1111  * Links the specifed #GstPad the @GstHarness srcpad.
1112  *
1113  * MT safe.
1114  *
1115  * Since: 1.6
1116  */
1117 void
1118 gst_harness_add_element_sink_pad (GstHarness * h, GstPad * sinkpad)
1119 {
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);
1128 }
1129
1130 /**
1131  * gst_harness_set_src_caps:
1132  * @h: a #GstHarness
1133  * @caps: (transfer full): a #GstCaps to set on the harness srcpad
1134  *
1135  * Sets the @GstHarness srcpad caps. This must be done before any buffers
1136  * can legally be pushed from the harness to the element.
1137  *
1138  * MT safe.
1139  *
1140  * Since: 1.6
1141  */
1142 void
1143 gst_harness_set_src_caps (GstHarness * h, GstCaps * caps)
1144 {
1145   GstHarnessPrivate *priv = h->priv;
1146   GstSegment segment;
1147   gboolean handled;
1148
1149   handled = gst_pad_push_event (h->srcpad, gst_event_new_caps (caps));
1150   g_assert (handled);
1151   gst_caps_take (&priv->src_caps, caps);
1152
1153   gst_segment_init (&segment, GST_FORMAT_TIME);
1154   handled = gst_pad_push_event (h->srcpad, gst_event_new_segment (&segment));
1155 }
1156
1157 /**
1158  * gst_harness_set_sink_caps:
1159  * @h: a #GstHarness
1160  * @caps: (transfer full): a #GstCaps to set on the harness sinkpad
1161  *
1162  * Sets the @GstHarness sinkpad caps.
1163  *
1164  * MT safe.
1165  *
1166  * Since: 1.6
1167  */
1168 void
1169 gst_harness_set_sink_caps (GstHarness * h, GstCaps * caps)
1170 {
1171   GstHarnessPrivate *priv = h->priv;
1172
1173   gst_caps_take (&priv->sink_caps, caps);
1174   gst_pad_push_event (h->sinkpad, gst_event_new_reconfigure ());
1175 }
1176
1177 /**
1178  * gst_harness_set_caps:
1179  * @h: a #GstHarness
1180  * @in: (transfer full): a #GstCaps to set on the harness srcpad
1181  * @out: (transfer full): a #GstCaps to set on the harness sinkpad
1182  *
1183  * Sets the @GstHarness srcpad and sinkpad caps.
1184  *
1185  * MT safe.
1186  *
1187  * Since: 1.6
1188  */
1189 void
1190 gst_harness_set_caps (GstHarness * h, GstCaps * in, GstCaps * out)
1191 {
1192   gst_harness_set_sink_caps (h, out);
1193   gst_harness_set_src_caps (h, in);
1194 }
1195
1196 /**
1197  * gst_harness_set_src_caps_str:
1198  * @h: a #GstHarness
1199  * @str: a @gchar describing a #GstCaps to set on the harness srcpad
1200  *
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.
1203  *
1204  * MT safe.
1205  *
1206  * Since: 1.6
1207  */
1208 void
1209 gst_harness_set_src_caps_str (GstHarness * h, const gchar * str)
1210 {
1211   gst_harness_set_src_caps (h, gst_caps_from_string (str));
1212 }
1213
1214 /**
1215  * gst_harness_set_sink_caps_str:
1216  * @h: a #GstHarness
1217  * @str: a @gchar describing a #GstCaps to set on the harness sinkpad
1218  *
1219  * Sets the @GstHarness sinkpad caps using a string.
1220  *
1221  * MT safe.
1222  *
1223  * Since: 1.6
1224  */
1225 void
1226 gst_harness_set_sink_caps_str (GstHarness * h, const gchar * str)
1227 {
1228   gst_harness_set_sink_caps (h, gst_caps_from_string (str));
1229 }
1230
1231 /**
1232  * gst_harness_set_caps_str:
1233  * @h: a #GstHarness
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
1236  *
1237  * Sets the @GstHarness srcpad and sinkpad caps using strings.
1238  *
1239  * MT safe.
1240  *
1241  * Since: 1.6
1242  */
1243 void
1244 gst_harness_set_caps_str (GstHarness * h, const gchar * in, const gchar * out)
1245 {
1246   gst_harness_set_sink_caps_str (h, out);
1247   gst_harness_set_src_caps_str (h, in);
1248 }
1249
1250 /**
1251  * gst_harness_use_systemclock:
1252  * @h: a #GstHarness
1253  *
1254  * Sets the system #GstClock on the @GstHarness #GstElement
1255  *
1256  * MT safe.
1257  *
1258  * Since: 1.6
1259  */
1260 void
1261 gst_harness_use_systemclock (GstHarness * h)
1262 {
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);
1267 }
1268
1269 /**
1270  * gst_harness_use_testclock:
1271  * @h: a #GstHarness
1272  *
1273  * Sets the #GstTestClock on the #GstHarness #GstElement
1274  *
1275  * MT safe.
1276  *
1277  * Since: 1.6
1278  */
1279 void
1280 gst_harness_use_testclock (GstHarness * h)
1281 {
1282   gst_element_set_clock (h->element, GST_CLOCK_CAST (h->priv->testclock));
1283 }
1284
1285 /**
1286  * gst_harness_get_testclock:
1287  * @h: a #GstHarness
1288  *
1289  * Get the #GstTestClock. Useful if specific operations on the testclock is
1290  * needed.
1291  *
1292  * MT safe.
1293  *
1294  * Returns: (transfer full): a #GstTestClock, or %NULL if the testclock is not
1295  * present.
1296  *
1297  * Since: 1.6
1298  */
1299 GstTestClock *
1300 gst_harness_get_testclock (GstHarness * h)
1301 {
1302   return gst_object_ref (h->priv->testclock);
1303 }
1304
1305 /**
1306  * gst_harness_set_time:
1307  * @h: a #GstHarness
1308  * @time: a #GstClockTime to advance the clock to
1309  *
1310  * Advance the #GstTestClock to a specific time.
1311  *
1312  * MT safe.
1313  *
1314  * Returns: a @gboolean %TRUE if the time could be set. %FALSE if not.
1315  *
1316  * Since: 1.6
1317  */
1318 gboolean
1319 gst_harness_set_time (GstHarness * h, GstClockTime time)
1320 {
1321   gst_test_clock_set_time (h->priv->testclock, time);
1322   return TRUE;
1323 }
1324
1325 /**
1326  * gst_harness_wait_for_clock_id_waits:
1327  * @h: a #GstHarness
1328  * @waits: a #guint describing the numbers of #GstClockID registered with
1329  * the #GstTestClock
1330  * @timeout: a #guint describing how many seconds to wait for @waits to be true
1331  *
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
1335  * reached.
1336  *
1337  * MT safe.
1338  *
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)
1341  *
1342  * Since: 1.6
1343  */
1344 gboolean
1345 gst_harness_wait_for_clock_id_waits (GstHarness * h, guint waits, guint timeout)
1346 {
1347   GstTestClock *testclock = h->priv->testclock;
1348   gint64 start_time;
1349   gboolean ret;
1350
1351   start_time = g_get_monotonic_time ();
1352   while (gst_test_clock_peek_id_count (testclock) < waits) {
1353     gint64 time_spent;
1354
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)
1358       break;
1359   }
1360
1361   ret = (waits == gst_test_clock_peek_id_count (testclock));
1362
1363   return ret;
1364 }
1365
1366 /**
1367  * gst_harness_crank_single_clock_wait:
1368  * @h: a #GstHarness
1369  *
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.
1378  *
1379  * MT safe.
1380  *
1381  * Returns: a @gboolean %TRUE if the "crank" was successful, %FALSE if not.
1382  *
1383  * Since: 1.6
1384  */
1385 gboolean
1386 gst_harness_crank_single_clock_wait (GstHarness * h)
1387 {
1388   return gst_test_clock_crank (h->priv->testclock);
1389 }
1390
1391 /**
1392  * gst_harness_crank_multiple_clock_waits:
1393  * @h: a #GstHarness
1394  * @waits: a #guint describing the number of #GstClockIDs to crank
1395  *
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.
1402  *
1403  * MT safe.
1404  *
1405  * Returns: a @gboolean %TRUE if the "crank" was successful, %FALSE if not.
1406  *
1407  * Since: 1.6
1408  */
1409 gboolean
1410 gst_harness_crank_multiple_clock_waits (GstHarness * h, guint waits)
1411 {
1412   GstTestClock *testclock = h->priv->testclock;
1413   GList *pending;
1414   guint processed;
1415
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);
1419
1420   g_list_free_full (pending, gst_clock_id_unref);
1421   return processed == waits;
1422 }
1423
1424 /**
1425  * gst_harness_play:
1426  * @h: a #GstHarness
1427  *
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.
1435  *
1436  * MT safe.
1437  *
1438  * Since: 1.6
1439  */
1440 void
1441 gst_harness_play (GstHarness * h)
1442 {
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);
1450 }
1451
1452 /**
1453  * gst_harness_set_blocking_push_mode:
1454  * @h: a #GstHarness
1455  *
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.
1461  *
1462  * MT safe.
1463  *
1464  * Since: 1.6
1465  */
1466 void
1467 gst_harness_set_blocking_push_mode (GstHarness * h)
1468 {
1469   GstHarnessPrivate *priv = h->priv;
1470   priv->blocking_push_mode = TRUE;
1471 }
1472
1473 /**
1474  * gst_harness_set_forwarding:
1475  * @h: a #GstHarness
1476  * @forwarding: a #gboolean to enable/disable forwarding
1477  *
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.
1482  *
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.
1489  *
1490  * Forwarding is enabled by default.
1491  *
1492  * MT safe.
1493  *
1494  * Since: 1.6
1495  */
1496 void
1497 gst_harness_set_forwarding (GstHarness * h, gboolean forwarding)
1498 {
1499   GstHarnessPrivate *priv = h->priv;
1500   priv->forwarding = forwarding;
1501   if (h->src_harness)
1502     gst_harness_set_forwarding (h->src_harness, forwarding);
1503   if (h->sink_harness)
1504     gst_harness_set_forwarding (h->sink_harness, forwarding);
1505 }
1506
1507 static void
1508 gst_harness_set_forward_pad (GstHarness * h, GstPad * fwdpad)
1509 {
1510   HARNESS_LOCK (h);
1511   gst_object_replace ((GstObject **) & h->priv->sink_forward_pad,
1512       (GstObject *) fwdpad);
1513   HARNESS_UNLOCK (h);
1514 }
1515
1516 /**
1517  * gst_harness_create_buffer:
1518  * @h: a #GstHarness
1519  * @size: a #gsize specifying the size of the buffer
1520  *
1521  * Allocates a buffer using a #GstBufferPool if present, or else using the
1522  * configured #GstAllocator and #GstAllocationParams
1523  *
1524  * MT safe.
1525  *
1526  * Returns: a #GstBuffer of size @size
1527  *
1528  * Since: 1.6
1529  */
1530 GstBuffer *
1531 gst_harness_create_buffer (GstHarness * h, gsize size)
1532 {
1533   GstHarnessPrivate *priv = h->priv;
1534   GstBuffer *ret = NULL;
1535   GstFlowReturn flow;
1536
1537   if (gst_pad_check_reconfigure (h->srcpad))
1538     gst_harness_negotiate (h);
1539
1540   if (priv->pool) {
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);
1548       ret = NULL;
1549     }
1550   }
1551
1552   if (!ret)
1553     ret =
1554         gst_buffer_new_allocate (priv->allocator, size,
1555         &priv->allocation_params);
1556
1557   g_assert (ret != NULL);
1558   return ret;
1559 }
1560
1561 /**
1562  * gst_harness_push:
1563  * @h: a #GstHarness
1564  * @buffer: a #GstBuffer to push
1565  *
1566  * Pushes a #GstBuffer on the #GstHarness srcpad. The standard way of
1567  * interacting with an harnessed element.
1568  *
1569  * MT safe.
1570  *
1571  * Returns: a #GstFlowReturn with the result from the push
1572  *
1573  * Since: 1.6
1574  */
1575 GstFlowReturn
1576 gst_harness_push (GstHarness * h, GstBuffer * buffer)
1577 {
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);
1582 }
1583
1584 /**
1585  * gst_harness_pull:
1586  * @h: a #GstHarness
1587  *
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.
1591  *
1592  * MT safe.
1593  *
1594  * Returns: a #GstBuffer or %NULL if timed out.
1595  *
1596  * Since: 1.6
1597  */
1598 GstBuffer *
1599 gst_harness_pull (GstHarness * h)
1600 {
1601   GstHarnessPrivate *priv = h->priv;
1602   GstBuffer *buf = (GstBuffer *) g_async_queue_timeout_pop (priv->buffer_queue,
1603       G_USEC_PER_SEC * 60);
1604
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);
1609   }
1610
1611   return buf;
1612 }
1613
1614 /**
1615  * gst_harness_try_pull:
1616  * @h: a #GstHarness
1617  *
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.
1621  *
1622  * MT safe.
1623  *
1624  * Returns: a #GstBuffer or %NULL if no buffers are present in the #GAsyncQueue
1625  *
1626  * Since: 1.6
1627  */
1628 GstBuffer *
1629 gst_harness_try_pull (GstHarness * h)
1630 {
1631   GstHarnessPrivate *priv = h->priv;
1632   GstBuffer *buf = (GstBuffer *) g_async_queue_try_pop (priv->buffer_queue);
1633
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);
1638   }
1639
1640   return buf;
1641 }
1642
1643 /**
1644  * gst_harness_push_and_pull:
1645  * @h: a #GstHarness
1646  * @buffer: a #GstBuffer to push
1647  *
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.
1651  *
1652  * MT safe.
1653  *
1654  * Returns: a #GstBuffer or %NULL if timed out.
1655  *
1656  * Since: 1.6
1657  */
1658 GstBuffer *
1659 gst_harness_push_and_pull (GstHarness * h, GstBuffer * buffer)
1660 {
1661   gst_harness_push (h, buffer);
1662   return gst_harness_pull (h);
1663 }
1664
1665 /**
1666  * gst_harness_buffers_received:
1667  * @h: a #GstHarness
1668  *
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.
1672  *
1673  * MT safe.
1674  *
1675  * Returns: a #guint number of buffers received
1676  *
1677  * Since: 1.6
1678  */
1679 guint
1680 gst_harness_buffers_received (GstHarness * h)
1681 {
1682   GstHarnessPrivate *priv = h->priv;
1683   return g_atomic_int_get (&priv->recv_buffers);
1684 }
1685
1686 /**
1687  * gst_harness_buffers_in_queue:
1688  * @h: a #GstHarness
1689  *
1690  * The number of #GstBuffers currently in the #GstHarness sinkpad #GAsyncQueue
1691  *
1692  * MT safe.
1693  *
1694  * Returns: a #guint number of buffers in the queue
1695  *
1696  * Since: 1.6
1697  */
1698 guint
1699 gst_harness_buffers_in_queue (GstHarness * h)
1700 {
1701   GstHarnessPrivate *priv = h->priv;
1702   return g_async_queue_length (priv->buffer_queue);
1703 }
1704
1705 /**
1706  * gst_harness_set_drop_buffers:
1707  * @h: a #GstHarness
1708  * @drop_buffers: a #gboolean specifying to drop outgoing buffers or not
1709  *
1710  * When set to %TRUE, instead of placing the buffers arriving from the harnessed
1711  * #GstElement inside the sinkpads #GAsyncQueue, they are instead unreffed.
1712  *
1713  * MT safe.
1714  *
1715  * Since: 1.6
1716  */
1717 void
1718 gst_harness_set_drop_buffers (GstHarness * h, gboolean drop_buffers)
1719 {
1720   GstHarnessPrivate *priv = h->priv;
1721   priv->drop_buffers = drop_buffers;
1722 }
1723
1724 /**
1725  * gst_harness_dump_to_file:
1726  * @h: a #GstHarness
1727  * @filename: a #gchar with a the name of a file
1728  *
1729  * Allows you to dump the #GstBuffers the #GstHarness sinkpad #GAsyncQueue
1730  * to a file.
1731  *
1732  * MT safe.
1733  *
1734  * Since: 1.6
1735  */
1736 void
1737 gst_harness_dump_to_file (GstHarness * h, const gchar * filename)
1738 {
1739   GstHarnessPrivate *priv = h->priv;
1740   FILE *fd;
1741   GstBuffer *buf;
1742   fd = fopen (filename, "wb");
1743   g_assert (fd);
1744
1745   while ((buf = g_async_queue_try_pop (priv->buffer_queue))) {
1746     GstMapInfo info;
1747     if (gst_buffer_map (buf, &info, GST_MAP_READ)) {
1748       fwrite (info.data, 1, info.size, fd);
1749       gst_buffer_unmap (buf, &info);
1750     } else {
1751       GST_ERROR ("failed to map buffer %p", buf);
1752     }
1753     gst_buffer_unref (buf);
1754   }
1755
1756   fflush (fd);
1757   fclose (fd);
1758 }
1759
1760 /**
1761  * gst_harness_get_last_pushed_timestamp:
1762  * @h: a #GstHarness
1763  *
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.
1766  *
1767  * MT safe.
1768  *
1769  * Returns: a #GstClockTime with the timestamp or %GST_CLOCK_TIME_NONE if no
1770  * #GstBuffer has been pushed on the #GstHarness srcpad
1771  *
1772  * Since: 1.6
1773  */
1774 GstClockTime
1775 gst_harness_get_last_pushed_timestamp (GstHarness * h)
1776 {
1777   GstHarnessPrivate *priv = h->priv;
1778   return priv->last_push_ts;
1779 }
1780
1781 /**
1782  * gst_harness_push_event:
1783  * @h: a #GstHarness
1784  * @event: a #GstEvent to push
1785  *
1786  * Pushes an #GstEvent on the #GstHarness srcpad.
1787  *
1788  * MT safe.
1789  *
1790  * Returns: a #gboolean with the result from the push
1791  *
1792  * Since: 1.6
1793  */
1794 gboolean
1795 gst_harness_push_event (GstHarness * h, GstEvent * event)
1796 {
1797   return gst_pad_push_event (h->srcpad, event);
1798 }
1799
1800 /**
1801  * gst_harness_pull_event:
1802  * @h: a #GstHarness
1803  *
1804  * Pulls an #GstEvent from the #GAsyncQueue on the #GstHarness sinkpad.
1805  * Timeouts after 60 seconds similar to gst_harness_pull.
1806  *
1807  * MT safe.
1808  *
1809  * Returns: a #GstEvent or %NULL if timed out.
1810  *
1811  * Since: 1.6
1812  */
1813 GstEvent *
1814 gst_harness_pull_event (GstHarness * h)
1815 {
1816   GstHarnessPrivate *priv = h->priv;
1817   return (GstEvent *) g_async_queue_timeout_pop (priv->sink_event_queue,
1818       G_USEC_PER_SEC * 60);
1819 }
1820
1821 /**
1822  * gst_harness_try_pull_event:
1823  * @h: a #GstHarness
1824  *
1825  * Pulls an #GstEvent from the #GAsyncQueue on the #GstHarness sinkpad.
1826  * See gst_harness_try_pull for details.
1827  *
1828  * MT safe.
1829  *
1830  * Returns: a #GstEvent or %NULL if no buffers are present in the #GAsyncQueue
1831  *
1832  * Since: 1.6
1833  */
1834 GstEvent *
1835 gst_harness_try_pull_event (GstHarness * h)
1836 {
1837   GstHarnessPrivate *priv = h->priv;
1838   return (GstEvent *) g_async_queue_try_pop (priv->sink_event_queue);
1839 }
1840
1841 /**
1842  * gst_harness_events_received:
1843  * @h: a #GstHarness
1844  *
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.
1848  *
1849  * MT safe.
1850  *
1851  * Returns: a #guint number of events received
1852  *
1853  * Since: 1.6
1854  */
1855 guint
1856 gst_harness_events_received (GstHarness * h)
1857 {
1858   GstHarnessPrivate *priv = h->priv;
1859   return g_atomic_int_get (&priv->recv_events);
1860 }
1861
1862 /**
1863  * gst_harness_events_in_queue:
1864  * @h: a #GstHarness
1865  *
1866  * The number of #GstEvents currently in the #GstHarness sinkpad #GAsyncQueue
1867  *
1868  * MT safe.
1869  *
1870  * Returns: a #guint number of events in the queue
1871  *
1872  * Since: 1.6
1873  */
1874 guint
1875 gst_harness_events_in_queue (GstHarness * h)
1876 {
1877   GstHarnessPrivate *priv = h->priv;
1878   return g_async_queue_length (priv->sink_event_queue);
1879 }
1880
1881 /**
1882  * gst_harness_push_upstream_event:
1883  * @h: a #GstHarness
1884  * @event: a #GstEvent to push
1885  *
1886  * Pushes an #GstEvent on the #GstHarness sinkpad.
1887  *
1888  * MT safe.
1889  *
1890  * Returns: a #gboolean with the result from the push
1891  *
1892  * Since: 1.6
1893  */
1894 gboolean
1895 gst_harness_push_upstream_event (GstHarness * h, GstEvent * event)
1896 {
1897   g_return_val_if_fail (event != NULL, FALSE);
1898   g_return_val_if_fail (GST_EVENT_IS_UPSTREAM (event), FALSE);
1899
1900   return gst_pad_push_event (h->sinkpad, event);
1901 }
1902
1903 /**
1904  * gst_harness_pull_upstream_event:
1905  * @h: a #GstHarness
1906  *
1907  * Pulls an #GstEvent from the #GAsyncQueue on the #GstHarness srcpad.
1908  * Timeouts after 60 seconds similar to gst_harness_pull.
1909  *
1910  * MT safe.
1911  *
1912  * Returns: a #GstEvent or %NULL if timed out.
1913  *
1914  * Since: 1.6
1915  */
1916 GstEvent *
1917 gst_harness_pull_upstream_event (GstHarness * h)
1918 {
1919   GstHarnessPrivate *priv = h->priv;
1920   return (GstEvent *) g_async_queue_timeout_pop (priv->src_event_queue,
1921       G_USEC_PER_SEC * 60);
1922 }
1923
1924 /**
1925  * gst_harness_try_pull_upstream_event:
1926  * @h: a #GstHarness
1927  *
1928  * Pulls an #GstEvent from the #GAsyncQueue on the #GstHarness srcpad.
1929  * See gst_harness_try_pull for details.
1930  *
1931  * MT safe.
1932  *
1933  * Returns: a #GstEvent or %NULL if no buffers are present in the #GAsyncQueue
1934  *
1935  * Since: 1.6
1936  */
1937 GstEvent *
1938 gst_harness_try_pull_upstream_event (GstHarness * h)
1939 {
1940   GstHarnessPrivate *priv = h->priv;
1941   return (GstEvent *) g_async_queue_try_pop (priv->src_event_queue);
1942 }
1943
1944 /**
1945  * gst_harness_upstream_events_received:
1946  * @h: a #GstHarness
1947  *
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.
1951  *
1952  * MT safe.
1953  *
1954  * Returns: a #guint number of events received
1955  *
1956  * Since: 1.6
1957  */
1958 guint
1959 gst_harness_upstream_events_received (GstHarness * h)
1960 {
1961   GstHarnessPrivate *priv = h->priv;
1962   return g_atomic_int_get (&priv->recv_upstream_events);
1963 }
1964
1965 /**
1966  * gst_harness_upstream_events_in_queue:
1967  * @h: a #GstHarness
1968  *
1969  * The number of #GstEvents currently in the #GstHarness srcpad #GAsyncQueue
1970  *
1971  * MT safe.
1972  *
1973  * Returns: a #guint number of events in the queue
1974  *
1975  * Since: 1.6
1976  */
1977 guint
1978 gst_harness_upstream_events_in_queue (GstHarness * h)
1979 {
1980   GstHarnessPrivate *priv = h->priv;
1981   return g_async_queue_length (priv->src_event_queue);
1982 }
1983
1984 /**
1985  * gst_harness_query_latency:
1986  * @h: a #GstHarness
1987  *
1988  * Get the min latency reported by any harnessed #GstElement.
1989  *
1990  * MT safe.
1991  *
1992  * Returns: a #GstClockTime with min latency
1993  *
1994  * Since: 1.6
1995  */
1996 GstClockTime
1997 gst_harness_query_latency (GstHarness * h)
1998 {
1999   GstQuery *query;
2000   gboolean is_live;
2001   GstClockTime min = GST_CLOCK_TIME_NONE;
2002   GstClockTime max;
2003
2004   query = gst_query_new_latency ();
2005
2006   if (gst_pad_peer_query (h->sinkpad, query)) {
2007     gst_query_parse_latency (query, &is_live, &min, &max);
2008   }
2009   gst_query_unref (query);
2010
2011   return min;
2012 }
2013
2014 /**
2015  * gst_harness_set_upstream_latency:
2016  * @h: a #GstHarness
2017  * @latency: a #GstClockTime specifying the latency
2018  *
2019  * Sets the min latency reported by #GstHarness when receiving a latency-query
2020  *
2021  * Since: 1.6
2022  */
2023 void
2024 gst_harness_set_upstream_latency (GstHarness * h, GstClockTime latency)
2025 {
2026   GstHarnessPrivate *priv = h->priv;
2027   priv->latency_min = latency;
2028 }
2029
2030 /**
2031  * gst_harness_get_allocator:
2032  * @h: a #GstHarness
2033  * @allocator: (out) (allow-none) (transfer none): the #GstAllocator used
2034  * @params: (out) (allow-none) (transfer full): the #GstAllocationParams of
2035  *   @allocator
2036  *
2037  * Gets the @allocator and its @params that has been decided to use after an
2038  * allocation query.
2039  *
2040  * MT safe.
2041  *
2042  * Since: 1.6
2043  */
2044 void
2045 gst_harness_get_allocator (GstHarness * h, GstAllocator ** allocator,
2046     GstAllocationParams * params)
2047 {
2048   GstHarnessPrivate *priv = h->priv;
2049   if (allocator)
2050     *allocator = priv->allocator;
2051   if (params)
2052     *params = priv->allocation_params;
2053 }
2054
2055
2056 /**
2057  * gst_harness_set_propose_allocator:
2058  * @h: a #GstHarness
2059  * @allocator: (allow-none) (transfer full): a #GstAllocator
2060  * @params: (allow-none) (transfer none): a #GstAllocationParams
2061  *
2062  * Sets the @allocator and @params to propose when receiving an allocation
2063  * query.
2064  *
2065  * MT safe.
2066  *
2067  * Since: 1.6
2068  */
2069 void
2070 gst_harness_set_propose_allocator (GstHarness * h, GstAllocator * allocator,
2071     const GstAllocationParams * params)
2072 {
2073   GstHarnessPrivate *priv = h->priv;
2074   if (allocator)
2075     priv->propose_allocator = allocator;
2076   if (params)
2077     priv->propose_allocation_params = *params;
2078 }
2079
2080 /**
2081  * gst_harness_add_src_harness:
2082  * @h: a #GstHarness
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.
2086  *
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.
2094  *
2095  * If a src-harness already exists it will be replaced.
2096  *
2097  * MT safe.
2098  *
2099  * Since: 1.6
2100  */
2101 void
2102 gst_harness_add_src_harness (GstHarness * h,
2103     GstHarness * src_harness, gboolean has_clock_wait)
2104 {
2105   if (h->src_harness)
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);
2111 }
2112
2113 /**
2114  * gst_harness_add_src:
2115  * @h: a #GstHarness
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.
2119  *
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.
2122  *
2123  * MT safe.
2124  *
2125  * Since: 1.6
2126  */
2127 void
2128 gst_harness_add_src (GstHarness * h,
2129     const gchar * src_element_name, gboolean has_clock_wait)
2130 {
2131   GstHarness *src_harness = gst_harness_new (src_element_name);
2132   gst_harness_add_src_harness (h, src_harness, has_clock_wait);
2133 }
2134
2135 /**
2136  * gst_harness_add_src_parse:
2137  * @h: a #GstHarness
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.
2141  *
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
2146  * the elements.
2147  *
2148  * MT safe.
2149  *
2150  * Since: 1.6
2151  */
2152 void
2153 gst_harness_add_src_parse (GstHarness * h,
2154     const gchar * launchline, gboolean has_clock_wait)
2155 {
2156   GstHarness *src_harness = gst_harness_new_parse (launchline);
2157   gst_harness_add_src_harness (h, src_harness, has_clock_wait);
2158 }
2159
2160 /**
2161  * gst_harness_push_from_src:
2162  * @h: a #GstHarness
2163  *
2164  * Transfer data from the src-#GstHarness to the main-#GstHarness. It consists
2165  * of 4 steps:
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)
2170  *
2171  * MT safe.
2172  *
2173  * Returns: a #GstFlowReturn with the result of the push
2174  *
2175  * Since: 1.6
2176  */
2177 GstFlowReturn
2178 gst_harness_push_from_src (GstHarness * h)
2179 {
2180   GstBuffer *buf;
2181   gboolean crank;
2182
2183   g_assert (h->src_harness);
2184
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);
2188
2189   if (h->src_harness->priv->has_clock_wait) {
2190     crank = gst_harness_crank_single_clock_wait (h->src_harness);
2191     g_assert (crank);
2192   }
2193
2194   buf = gst_harness_pull (h->src_harness);
2195   g_assert (buf != NULL);
2196   return gst_harness_push (h, buf);
2197 }
2198
2199 /**
2200  * gst_harness_src_crank_and_push_many:
2201  * @h: a #GstHarness
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
2204  *
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.
2210  *
2211  * MT safe.
2212  *
2213  * Returns: a #GstFlowReturn with the result of the push
2214  *
2215  * Since: 1.6
2216  */
2217 GstFlowReturn
2218 gst_harness_src_crank_and_push_many (GstHarness * h, gint cranks, gint pushes)
2219 {
2220   GstFlowReturn ret = GST_FLOW_OK;
2221   gboolean crank;
2222   int i;
2223
2224   g_assert (h->src_harness);
2225   gst_harness_play (h->src_harness);
2226
2227   for (i = 0; i < cranks; i++) {
2228     crank = gst_harness_crank_single_clock_wait (h->src_harness);
2229     g_assert (crank);
2230   }
2231
2232   for (i = 0; i < pushes; i++) {
2233     GstBuffer *buf;
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)
2238       break;
2239   }
2240
2241   return ret;
2242 }
2243
2244 /**
2245  * gst_harness_src_push_event:
2246  * @h: a #GstHarness
2247  *
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
2251  * for details.
2252  *
2253  * MT safe.
2254  *
2255  * Returns: a #gboolean with the result of the push
2256  *
2257  * Since: 1.6
2258  */
2259 gboolean
2260 gst_harness_src_push_event (GstHarness * h)
2261 {
2262   return gst_harness_push_event (h, gst_harness_pull_event (h->src_harness));
2263 }
2264
2265
2266 static gboolean
2267 forward_sticky_events (GstPad * pad, GstEvent ** ev, gpointer user_data)
2268 {
2269   GstHarness *h = user_data;
2270   return gst_pad_push_event (h->priv->sink_forward_pad, gst_event_ref (*ev));
2271 }
2272
2273 /**
2274  * gst_harness_add_sink_harness:
2275  * @h: a #GstHarness
2276  * @sink_harness: (transfer full): a #GstHarness to be added as a sink-harness.
2277  *
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.
2284  *
2285  * If a sink-harness already exists it will be replaced.
2286  *
2287  * MT safe.
2288  *
2289  * Since: 1.6
2290  */
2291 void
2292 gst_harness_add_sink_harness (GstHarness * h, GstHarness * sink_harness)
2293 {
2294   GstHarnessPrivate *priv = h->priv;
2295
2296   if (h->sink_harness) {
2297     gst_harness_set_forward_pad (h, NULL);
2298     gst_harness_teardown (h->sink_harness);
2299   }
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);
2305 }
2306
2307 /**
2308  * gst_harness_add_sink:
2309  * @h: a #GstHarness
2310  * @sink_element_name: a #gchar with the name of a #GstElement
2311  *
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.
2314  *
2315  * MT safe.
2316  *
2317  * Since: 1.6
2318  */
2319 void
2320 gst_harness_add_sink (GstHarness * h, const gchar * sink_element_name)
2321 {
2322   GstHarness *sink_harness = gst_harness_new (sink_element_name);
2323   gst_harness_add_sink_harness (h, sink_harness);
2324 }
2325
2326 /**
2327  * gst_harness_add_sink_parse:
2328  * @h: a #GstHarness
2329  * @launchline: a #gchar with the name of a #GstElement
2330  *
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.
2333  *
2334  * MT safe.
2335  *
2336  * Since: 1.6
2337  */
2338 void
2339 gst_harness_add_sink_parse (GstHarness * h, const gchar * launchline)
2340 {
2341   GstHarness *sink_harness = gst_harness_new_parse (launchline);
2342   gst_harness_add_sink_harness (h, sink_harness);
2343 }
2344
2345 /**
2346  * gst_harness_push_to_sink:
2347  * @h: a #GstHarness
2348  *
2349  * Transfer one #GstBuffer from the main-#GstHarness to the sink-#GstHarness.
2350  * See gst_harness_push_from_src for details.
2351  *
2352  * MT safe.
2353  *
2354  * Returns: a #GstFlowReturn with the result of the push
2355  *
2356  * Since: 1.6
2357  */
2358 GstFlowReturn
2359 gst_harness_push_to_sink (GstHarness * h)
2360 {
2361   GstBuffer *buf;
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);
2366 }
2367
2368 /**
2369  * gst_harness_sink_push_many:
2370  * @h: a #GstHarness
2371  * @pushes: a #gint with the number of calls to gst_harness_push_to_sink
2372  *
2373  * Convenience that calls gst_harness_push_to_sink @pushes number of times.
2374  * Will abort the pushing if any one push fails.
2375  *
2376  * MT safe.
2377  *
2378  * Returns: a #GstFlowReturn with the result of the push
2379  *
2380  * Since: 1.6
2381  */
2382 GstFlowReturn
2383 gst_harness_sink_push_many (GstHarness * h, gint pushes)
2384 {
2385   GstFlowReturn ret = GST_FLOW_OK;
2386   int i;
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)
2391       break;
2392   }
2393   return ret;
2394 }
2395
2396 /**
2397  * gst_harness_find_element:
2398  * @h: a #GstHarness
2399  * @element_name: a #gchar with a #GstElementFactory name
2400  *
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.
2405  *
2406  * MT safe.
2407  *
2408  * Returns: (transfer full) (allow-none): a #GstElement or %NULL if not found
2409  *
2410  * Since: 1.6
2411  */
2412 GstElement *
2413 gst_harness_find_element (GstHarness * h, const gchar * element_name)
2414 {
2415   gboolean done = FALSE;
2416   GstIterator *iter;
2417   GValue data = G_VALUE_INIT;
2418
2419   iter = gst_bin_iterate_elements (GST_BIN (h->element));
2420   done = FALSE;
2421
2422   while (!done) {
2423     switch (gst_iterator_next (iter, &data)) {
2424       case GST_ITERATOR_OK:
2425       {
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);
2431           return element;
2432         }
2433         g_value_reset (&data);
2434         break;
2435       }
2436       case GST_ITERATOR_RESYNC:
2437         gst_iterator_resync (iter);
2438         break;
2439       case GST_ITERATOR_ERROR:
2440       case GST_ITERATOR_DONE:
2441         done = TRUE;
2442         break;
2443     }
2444   }
2445   gst_iterator_free (iter);
2446
2447   return NULL;
2448 }
2449
2450 /**
2451  * gst_harness_set:
2452  * @h: a #GstHarness
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
2457  *
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
2460  * syntax.
2461  *
2462  * MT safe.
2463  *
2464  * Since: 1.6
2465  */
2466 void
2467 gst_harness_set (GstHarness * h,
2468     const gchar * element_name, const gchar * first_property_name, ...)
2469 {
2470   va_list var_args;
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);
2474   va_end (var_args);
2475   gst_object_unref (element);
2476 }
2477
2478 /**
2479  * gst_harness_get:
2480  * @h: a #GstHarness
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
2485  *
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
2488  * syntax.
2489  *
2490  * MT safe.
2491  *
2492  * Since: 1.6
2493  */
2494 void
2495 gst_harness_get (GstHarness * h,
2496     const gchar * element_name, const gchar * first_property_name, ...)
2497 {
2498   va_list var_args;
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);
2502   va_end (var_args);
2503   gst_object_unref (element);
2504 }
2505
2506 /**
2507  * gst_harness_add_probe:
2508  * @h: a #GstHarness
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)
2515  *
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
2519  *
2520  * MT safe.
2521  *
2522  * Since: 1.6
2523  */
2524 void
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)
2529 {
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);
2535 }
2536
2537 /******************************************************************************/
2538 /*       STRESS                                                               */
2539 /******************************************************************************/
2540 struct _GstHarnessThread
2541 {
2542   GstHarness *h;
2543   GThread *thread;
2544   gboolean running;
2545
2546   gulong sleep;
2547
2548   GDestroyNotify freefunc;
2549 };
2550
2551 typedef struct
2552 {
2553   GstHarnessThread t;
2554
2555   GFunc init;
2556   GFunc callback;
2557   gpointer data;
2558 } GstHarnessCustomThread;
2559
2560 typedef struct
2561 {
2562   GstHarnessThread t;
2563
2564   GstCaps *caps;
2565   GstSegment segment;
2566   GstHarnessPrepareBufferFunc func;
2567   gpointer data;
2568   GDestroyNotify notify;
2569 } GstHarnessPushBufferThread;
2570
2571 typedef struct
2572 {
2573   GstHarnessThread t;
2574
2575   GstHarnessPrepareEventFunc func;
2576   gpointer data;
2577   GDestroyNotify notify;
2578 } GstHarnessPushEventThread;
2579
2580 typedef struct
2581 {
2582   GstHarnessThread t;
2583
2584   gchar *name;
2585   GValue value;
2586 } GstHarnessPropThread;
2587
2588 typedef struct
2589 {
2590   GstHarnessThread t;
2591
2592   GstPadTemplate *templ;
2593   gchar *name;
2594   GstCaps *caps;
2595   gboolean release;
2596
2597   GSList *pads;
2598 } GstHarnessReqPadThread;
2599
2600 static void
2601 gst_harness_thread_init (GstHarnessThread * t, GDestroyNotify freefunc,
2602     GstHarness * h, gulong sleep)
2603 {
2604   t->freefunc = freefunc;
2605   t->h = h;
2606   t->sleep = sleep;
2607
2608   g_ptr_array_add (h->priv->stress, t);
2609 }
2610
2611 static void
2612 gst_harness_thread_free (GstHarnessThread * t)
2613 {
2614   g_slice_free (GstHarnessThread, t);
2615 }
2616
2617 static void
2618 gst_harness_custom_thread_free (GstHarnessCustomThread * t)
2619 {
2620   g_slice_free (GstHarnessCustomThread, t);
2621 }
2622
2623 static void
2624 gst_harness_push_buffer_thread_free (GstHarnessPushBufferThread * t)
2625 {
2626   if (t != NULL) {
2627     gst_caps_replace (&t->caps, NULL);
2628     if (t->notify != NULL)
2629       t->notify (t->data);
2630     g_slice_free (GstHarnessPushBufferThread, t);
2631   }
2632 }
2633
2634 static void
2635 gst_harness_push_event_thread_free (GstHarnessPushEventThread * t)
2636 {
2637   if (t != NULL) {
2638     if (t->notify != NULL)
2639       t->notify (t->data);
2640     g_slice_free (GstHarnessPushEventThread, t);
2641   }
2642 }
2643
2644 static void
2645 gst_harness_property_thread_free (GstHarnessPropThread * t)
2646 {
2647   if (t != NULL) {
2648     g_free (t->name);
2649     g_value_unset (&t->value);
2650     g_slice_free (GstHarnessPropThread, t);
2651   }
2652 }
2653
2654 static void
2655 gst_harness_requestpad_release (GstPad * pad, GstElement * element)
2656 {
2657   gst_element_release_request_pad (element, pad);
2658   gst_object_unref (pad);
2659 }
2660
2661 static void
2662 gst_harness_requestpad_release_pads (GstHarnessReqPadThread * rpt)
2663 {
2664   g_slist_foreach (rpt->pads, (GFunc) gst_harness_requestpad_release,
2665       rpt->t.h->element);
2666   g_slist_free (rpt->pads);
2667   rpt->pads = NULL;
2668 }
2669
2670 static void
2671 gst_harness_requestpad_thread_free (GstHarnessReqPadThread * t)
2672 {
2673   if (t != NULL) {
2674     gst_object_replace ((GstObject **) & t->templ, NULL);
2675     g_free (t->name);
2676     gst_caps_replace (&t->caps, NULL);
2677
2678     gst_harness_requestpad_release_pads (t);
2679     g_slice_free (GstHarnessReqPadThread, t);
2680   }
2681 }
2682
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)))
2691
2692 static void
2693 gst_harness_stress_free (GstHarnessThread * t)
2694 {
2695   if (t != NULL && t->freefunc != NULL)
2696     t->freefunc (t);
2697 }
2698
2699 static gpointer
2700 gst_harness_stress_custom_func (GstHarnessThread * t)
2701 {
2702   GstHarnessCustomThread *ct = (GstHarnessCustomThread *) t;
2703   guint count = 0;
2704
2705   if (ct->init != NULL)
2706     ct->init (ct, ct->data);
2707
2708   while (t->running) {
2709     ct->callback (ct, ct->data);
2710
2711     count++;
2712     g_usleep (t->sleep);
2713   }
2714   return GUINT_TO_POINTER (count);
2715 }
2716
2717
2718 static gpointer
2719 gst_harness_stress_statechange_func (GstHarnessThread * t)
2720 {
2721   guint count = 0;
2722
2723   while (t->running) {
2724     GstClock *clock = gst_element_get_clock (t->h->element);
2725     GstIterator *it;
2726     gboolean done = FALSE;
2727     gboolean change;
2728
2729     change = gst_element_set_state (t->h->element, GST_STATE_NULL);
2730     g_assert (change == GST_STATE_CHANGE_SUCCESS);
2731     g_thread_yield ();
2732
2733     it = gst_element_iterate_sink_pads (t->h->element);
2734     while (!done) {
2735       GValue item = G_VALUE_INIT;
2736       switch (gst_iterator_next (it, &item)) {
2737         case GST_ITERATOR_OK:
2738         {
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);
2745           }
2746           g_value_reset (&item);
2747           break;
2748         }
2749         case GST_ITERATOR_RESYNC:
2750           gst_iterator_resync (it);
2751           break;
2752         case GST_ITERATOR_ERROR:
2753           g_assert_not_reached ();
2754         case GST_ITERATOR_DONE:
2755           done = TRUE;
2756           break;
2757       }
2758       g_value_unset (&item);
2759     }
2760     gst_iterator_free (it);
2761
2762     if (clock != NULL) {
2763       gst_element_set_clock (t->h->element, clock);
2764       gst_object_unref (clock);
2765     }
2766     change = gst_element_set_state (t->h->element, GST_STATE_PLAYING);
2767     g_assert (change == GST_STATE_CHANGE_SUCCESS);
2768
2769     count++;
2770     g_usleep (t->sleep);
2771   }
2772   return GUINT_TO_POINTER (count);
2773 }
2774
2775 static gpointer
2776 gst_harness_stress_buffer_func (GstHarnessThread * t)
2777 {
2778   GstHarnessPushBufferThread *pt = (GstHarnessPushBufferThread *) t;
2779   guint count = 0;
2780   gchar *sid;
2781   gboolean handled;
2782
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));
2786   g_assert (handled);
2787   g_free (sid);
2788   handled = gst_pad_push_event (t->h->srcpad, gst_event_new_caps (pt->caps));
2789   g_assert (handled);
2790   handled = gst_pad_push_event (t->h->srcpad,
2791       gst_event_new_segment (&pt->segment));
2792   g_assert (handled);
2793
2794   while (t->running) {
2795     gst_harness_push (t->h, pt->func (t->h, pt->data));
2796
2797     count++;
2798     g_usleep (t->sleep);
2799   }
2800   return GUINT_TO_POINTER (count);
2801 }
2802
2803 static gpointer
2804 gst_harness_stress_event_func (GstHarnessThread * t)
2805 {
2806   GstHarnessPushEventThread *pet = (GstHarnessPushEventThread *) t;
2807   guint count = 0;
2808
2809   while (t->running) {
2810     gst_harness_push_event (t->h, pet->func (t->h, pet->data));
2811
2812     count++;
2813     g_usleep (t->sleep);
2814   }
2815   return GUINT_TO_POINTER (count);
2816 }
2817
2818 static gpointer
2819 gst_harness_stress_upstream_event_func (GstHarnessThread * t)
2820 {
2821   GstHarnessPushEventThread *pet = (GstHarnessPushEventThread *) t;
2822   guint count = 0;
2823
2824   while (t->running) {
2825     gst_harness_push_upstream_event (t->h, pet->func (t->h, pet->data));
2826
2827     count++;
2828     g_usleep (t->sleep);
2829   }
2830   return GUINT_TO_POINTER (count);
2831 }
2832
2833 static gpointer
2834 gst_harness_stress_property_func (GstHarnessThread * t)
2835 {
2836   GstHarnessPropThread *pt = (GstHarnessPropThread *) t;
2837   guint count = 0;
2838
2839   while (t->running) {
2840     GValue value = G_VALUE_INIT;
2841
2842     g_object_set_property (G_OBJECT (t->h->element), pt->name, &pt->value);
2843
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);
2847
2848     count++;
2849     g_usleep (t->sleep);
2850   }
2851   return GUINT_TO_POINTER (count);
2852 }
2853
2854 static gpointer
2855 gst_harness_stress_requestpad_func (GstHarnessThread * t)
2856 {
2857   GstHarnessReqPadThread *rpt = (GstHarnessReqPadThread *) t;
2858   guint count = 0;
2859
2860   while (t->running) {
2861     GstPad *reqpad;
2862
2863     if (rpt->release)
2864       gst_harness_requestpad_release_pads (rpt);
2865
2866     g_thread_yield ();
2867
2868     reqpad = gst_element_request_pad (t->h->element,
2869         rpt->templ, rpt->name, rpt->caps);
2870
2871     g_assert (reqpad != NULL);
2872
2873     rpt->pads = g_slist_prepend (rpt->pads, reqpad);
2874
2875     count++;
2876     g_usleep (t->sleep);
2877   }
2878   return GUINT_TO_POINTER (count);
2879 }
2880
2881 /**
2882  * gst_harness_stress_thread_stop:
2883  * @t: a #GstHarnessThread
2884  *
2885  * Stop the running #GstHarnessThread
2886  *
2887  * MT safe.
2888  *
2889  * Since: 1.6
2890  */
2891 guint
2892 gst_harness_stress_thread_stop (GstHarnessThread * t)
2893 {
2894   guint ret;
2895
2896   g_return_val_if_fail (t != NULL, 0);
2897
2898   ret = GST_HARNESS_THREAD_END (t);
2899   g_ptr_array_remove (t->h->priv->stress, t);
2900   return ret;
2901 }
2902
2903 /**
2904  * gst_harness_stress_custom_start: (skip)
2905  * @h: a #GstHarness
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
2911  *
2912  * Start a custom stress-thread that will call your @callback for every
2913  * iteration allowing you to do something nasty.
2914  *
2915  * MT safe.
2916  *
2917  * Returns: a #GstHarnessThread
2918  *
2919  * Since: 1.6
2920  */
2921 GstHarnessThread *
2922 gst_harness_stress_custom_start (GstHarness * h,
2923     GFunc init, GFunc callback, gpointer data, gulong sleep)
2924 {
2925   GstHarnessCustomThread *t = g_slice_new0 (GstHarnessCustomThread);
2926   gst_harness_thread_init (&t->t,
2927       (GDestroyNotify) gst_harness_custom_thread_free, h, sleep);
2928
2929   t->init = init;
2930   t->callback = callback;
2931   t->data = data;
2932
2933   GST_HARNESS_THREAD_START (custom, t);
2934   return &t->t;
2935 }
2936
2937 /**
2938  * gst_harness_stress_statechange_start_full: (skip)
2939  * @h: a #GstHarness
2940  * @sleep: a #gulong specifying how long to sleep in (microseconds) for
2941  * each state-change
2942  *
2943  * Change the state of your harnessed #GstElement from NULL to PLAYING and
2944  * back again, only pausing for @sleep microseconds every time.
2945  *
2946  * MT safe.
2947  *
2948  * Returns: a #GstHarnessThread
2949  *
2950  * Since: 1.6
2951  */
2952 GstHarnessThread *
2953 gst_harness_stress_statechange_start_full (GstHarness * h, gulong sleep)
2954 {
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);
2959   return t;
2960 }
2961
2962 static GstBuffer *
2963 gst_harness_ref_buffer (GstHarness * h, gpointer data)
2964 {
2965   (void) h;
2966   return gst_buffer_ref (GST_BUFFER_CAST (data));
2967 }
2968
2969 static GstEvent *
2970 gst_harness_ref_event (GstHarness * h, gpointer data)
2971 {
2972   (void) h;
2973   return gst_event_ref (GST_EVENT_CAST (data));
2974 }
2975
2976 /**
2977  * gst_harness_stress_push_buffer_start_full: (skip)
2978  * @h: a #GstHarness
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
2984  *
2985  * Push a #GstBuffer in intervals of @sleep microseconds.
2986  *
2987  * MT safe.
2988  *
2989  * Returns: a #GstHarnessThread
2990  *
2991  * Since: 1.6
2992  */
2993 GstHarnessThread *
2994 gst_harness_stress_push_buffer_start_full (GstHarness * h,
2995     GstCaps * caps, const GstSegment * segment, GstBuffer * buf, gulong sleep)
2996 {
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);
3000 }
3001
3002 /**
3003  * gst_harness_stress_push_buffer_with_cb_start_full: (skip)
3004  * @h: a #GstHarness
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
3013  *
3014  * Push a #GstBuffer returned by @func in intervals of @sleep microseconds.
3015  *
3016  * MT safe.
3017  *
3018  * Returns: a #GstHarnessThread
3019  *
3020  * Since: 1.6
3021  */
3022 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,
3026     gulong sleep)
3027 {
3028   GstHarnessPushBufferThread *t = g_slice_new0 (GstHarnessPushBufferThread);
3029   gst_harness_thread_init (&t->t,
3030       (GDestroyNotify) gst_harness_push_buffer_thread_free, h, sleep);
3031
3032   gst_caps_replace (&t->caps, caps);
3033   t->segment = *segment;
3034   t->func = func;
3035   t->data = data;
3036   t->notify = notify;
3037
3038   GST_HARNESS_THREAD_START (buffer, t);
3039   return &t->t;
3040 }
3041
3042 /**
3043  * gst_harness_stress_push_event_start_full: (skip)
3044  * @h: a #GstHarness
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
3048  *
3049  * Push the @event onto the harnessed #GstElement sinkpad in intervals of
3050  * @sleep microseconds
3051  *
3052  * MT safe.
3053  *
3054  * Returns: a #GstHarnessThread
3055  *
3056  * Since: 1.6
3057  */
3058 GstHarnessThread *
3059 gst_harness_stress_push_event_start_full (GstHarness * h,
3060     GstEvent * event, gulong sleep)
3061 {
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);
3065 }
3066
3067 /**
3068  * gst_harness_stress_push_event_with_cb_start_full: (skip)
3069  * @h: a #GstHarness
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
3076  *
3077  * Push a #GstEvent returned by @func onto the harnessed #GstElement sinkpad
3078  * in intervals of @sleep microseconds.
3079  *
3080  * MT safe.
3081  *
3082  * Returns: a #GstHarnessThread
3083  *
3084  * Since: 1.8
3085  */
3086 GstHarnessThread *
3087 gst_harness_stress_push_event_with_cb_start_full (GstHarness * h,
3088     GstHarnessPrepareEventFunc func, gpointer data, GDestroyNotify notify,
3089     gulong sleep)
3090 {
3091   GstHarnessPushEventThread *t = g_slice_new0 (GstHarnessPushEventThread);
3092   gst_harness_thread_init (&t->t,
3093       (GDestroyNotify) gst_harness_push_event_thread_free, h, sleep);
3094
3095   t->func = func;
3096   t->data = data;
3097   t->notify = notify;
3098
3099   GST_HARNESS_THREAD_START (event, t);
3100   return &t->t;
3101 }
3102
3103 /**
3104  * gst_harness_stress_push_upstream_event_start_full: (skip)
3105  * @h: a #GstHarness
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
3109  *
3110  * Push the @event onto the harnessed #GstElement srcpad in intervals of
3111  * @sleep microseconds.
3112  *
3113  * MT safe.
3114  *
3115  * Returns: a #GstHarnessThread
3116  *
3117  * Since: 1.6
3118  */
3119 GstHarnessThread *
3120 gst_harness_stress_push_upstream_event_start_full (GstHarness * h,
3121     GstEvent * event, gulong sleep)
3122 {
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);
3126 }
3127
3128 /**
3129  * gst_harness_stress_push_upstream_event_with_cb_start_full: (skip)
3130  * @h: a #GstHarness
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
3137  *
3138  * Push a #GstEvent returned by @func onto the harnessed #GstElement srcpad
3139  * in intervals of @sleep microseconds.
3140  *
3141  * MT safe.
3142  *
3143  * Returns: a #GstHarnessThread
3144  *
3145  * Since: 1.8
3146  */
3147 GstHarnessThread *
3148 gst_harness_stress_push_upstream_event_with_cb_start_full (GstHarness * h,
3149     GstHarnessPrepareEventFunc func, gpointer data, GDestroyNotify notify,
3150     gulong sleep)
3151 {
3152   GstHarnessPushEventThread *t = g_slice_new0 (GstHarnessPushEventThread);
3153   gst_harness_thread_init (&t->t,
3154       (GDestroyNotify) gst_harness_push_event_thread_free, h, sleep);
3155
3156   t->func = func;
3157   t->data = data;
3158   t->notify = notify;
3159
3160   GST_HARNESS_THREAD_START (upstream_event, t);
3161   return &t->t;
3162 }
3163
3164 /**
3165  * gst_harness_stress_property_start_full: (skip)
3166  * @h: a #GstHarness
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
3171  *
3172  * Call g_object_set with @name and @value in intervals of @sleep microseconds
3173  *
3174  * MT safe.
3175  *
3176  * Returns: a #GstHarnessThread
3177  *
3178  * Since: 1.6
3179  */
3180 GstHarnessThread *
3181 gst_harness_stress_property_start_full (GstHarness * h,
3182     const gchar * name, const GValue * value, gulong sleep)
3183 {
3184   GstHarnessPropThread *t = g_slice_new0 (GstHarnessPropThread);
3185   gst_harness_thread_init (&t->t,
3186       (GDestroyNotify) gst_harness_property_thread_free, h, sleep);
3187
3188   t->name = g_strdup (name);
3189   g_value_init (&t->value, G_VALUE_TYPE (value));
3190   g_value_copy (value, &t->value);
3191
3192   GST_HARNESS_THREAD_START (property, t);
3193   return &t->t;
3194 }
3195
3196 /**
3197  * gst_harness_stress_requestpad_start_full: (skip)
3198  * @h: a #GstHarness
3199  * @templ: a #GstPadTemplate
3200  * @name: a #gchar
3201  * @caps: a #GstCaps
3202  * @release: a #gboolean
3203  * @sleep: a #gulong specifying how long to sleep in (microseconds) for
3204  * each gst_element_request_pad
3205  *
3206  * Call gst_element_request_pad in intervals of @sleep microseconds
3207  *
3208  * MT safe.
3209  *
3210  * Returns: a #GstHarnessThread
3211  *
3212  * Since: 1.6
3213  */
3214 GstHarnessThread *
3215 gst_harness_stress_requestpad_start_full (GstHarness * h,
3216     GstPadTemplate * templ, const gchar * name, GstCaps * caps,
3217     gboolean release, gulong sleep)
3218 {
3219   GstHarnessReqPadThread *t = g_slice_new0 (GstHarnessReqPadThread);
3220   gst_harness_thread_init (&t->t,
3221       (GDestroyNotify) gst_harness_requestpad_thread_free, h, sleep);
3222
3223   t->templ = gst_object_ref (templ);
3224   t->name = g_strdup (name);
3225   gst_caps_replace (&t->caps, caps);
3226   t->release = release;
3227
3228   GST_HARNESS_THREAD_START (requestpad, t);
3229   return &t->t;
3230 }