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