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