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