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