caps: improve _do_simplify
[platform/upstream/gstreamer.git] / tests / check / gst / gstpipeline.c
1 /* GStreamer
2  * Copyright (C) 2005 Thomas Vander Stichele <thomas at apestaart dot org>
3  *
4  * gstpipeline.c: Unit test for GstPipeline
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <gst/check/gstcheck.h>
26 #include <gst/gst.h>
27
28 #define WAIT_TIME (300 * GST_MSECOND)
29
30 /* an empty pipeline can go to PLAYING in one go */
31 GST_START_TEST (test_async_state_change_empty)
32 {
33   GstPipeline *pipeline;
34
35   pipeline = GST_PIPELINE (gst_pipeline_new (NULL));
36   fail_unless (pipeline != NULL, "Could not create pipeline");
37
38   fail_unless_equals_int (gst_element_set_state (GST_ELEMENT (pipeline),
39           GST_STATE_PLAYING), GST_STATE_CHANGE_SUCCESS);
40
41   gst_object_unref (pipeline);
42 }
43
44 GST_END_TEST;
45
46 GST_START_TEST (test_async_state_change_fake_ready)
47 {
48   GstPipeline *pipeline;
49   GstElement *src, *sink;
50
51   pipeline = GST_PIPELINE (gst_pipeline_new (NULL));
52   fail_unless (pipeline != NULL, "Could not create pipeline");
53
54   src = gst_element_factory_make ("fakesrc", NULL);
55   sink = gst_element_factory_make ("fakesink", NULL);
56
57   gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);
58   gst_element_link (src, sink);
59
60   fail_unless_equals_int (gst_element_set_state (GST_ELEMENT (pipeline),
61           GST_STATE_READY), GST_STATE_CHANGE_SUCCESS);
62
63   gst_object_unref (pipeline);
64 }
65
66 GST_END_TEST;
67
68 GST_START_TEST (test_async_state_change_fake)
69 {
70   GstPipeline *pipeline;
71   GstElement *src, *sink;
72   GstBus *bus;
73   gboolean done = FALSE;
74
75   pipeline = GST_PIPELINE (gst_pipeline_new (NULL));
76   fail_unless (pipeline != NULL, "Could not create pipeline");
77
78   src = gst_element_factory_make ("fakesrc", NULL);
79   sink = gst_element_factory_make ("fakesink", NULL);
80
81   gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);
82   gst_element_link (src, sink);
83
84   bus = gst_pipeline_get_bus (pipeline);
85
86   fail_unless_equals_int (gst_element_set_state (GST_ELEMENT (pipeline),
87           GST_STATE_PLAYING), GST_STATE_CHANGE_ASYNC);
88
89   while (!done) {
90     GstMessage *message;
91     GstState old, new, pending;
92
93     message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1);
94     if (message) {
95       gst_message_parse_state_changed (message, &old, &new, &pending);
96       GST_DEBUG_OBJECT (message->src, "state change from %d to %d", old, new);
97       if (message->src == GST_OBJECT (pipeline) && new == GST_STATE_PLAYING)
98         done = TRUE;
99       gst_message_unref (message);
100     }
101   }
102
103   fail_unless_equals_int (gst_element_set_state (GST_ELEMENT (pipeline),
104           GST_STATE_NULL), GST_STATE_CHANGE_SUCCESS);
105
106   /* here we don't get the state change messages, because of auto-flush in 
107    * the bus */
108
109   gst_object_unref (bus);
110   gst_object_unref (pipeline);
111 }
112
113 GST_END_TEST;
114
115 GST_START_TEST (test_get_bus)
116 {
117   GstPipeline *pipeline;
118   GstBus *bus;
119
120   pipeline = GST_PIPELINE (gst_pipeline_new (NULL));
121   fail_unless (pipeline != NULL, "Could not create pipeline");
122   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
123
124   bus = gst_pipeline_get_bus (pipeline);
125   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline after get_bus", 1);
126   ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
127
128   gst_object_unref (pipeline);
129
130   ASSERT_OBJECT_REFCOUNT (bus, "bus after unref pipeline", 1);
131   gst_object_unref (bus);
132 }
133
134 GST_END_TEST;
135
136 static GMainLoop *loop = NULL;
137
138 static gboolean
139 message_received (GstBus * bus, GstMessage * message, gpointer data)
140 {
141   GstElement *pipeline = GST_ELEMENT (data);
142   GstMessageType type = message->type;
143
144   GST_DEBUG ("message received");
145   switch (type) {
146     case GST_MESSAGE_STATE_CHANGED:
147     {
148       GstState old, new, pending;
149
150       GST_DEBUG ("state change message received");
151       gst_message_parse_state_changed (message, &old, &new, &pending);
152       GST_DEBUG ("new state %d", new);
153       if (message->src == GST_OBJECT (pipeline) && new == GST_STATE_PLAYING) {
154         GST_DEBUG ("quitting main loop");
155         g_main_loop_quit (loop);
156       }
157     }
158       break;
159     case GST_MESSAGE_ERROR:
160     {
161       g_print ("error\n");
162     }
163       break;
164     default:
165       break;
166   }
167
168   return TRUE;
169 }
170
171 GST_START_TEST (test_bus)
172 {
173   GstElement *pipeline;
174   GstElement *src, *sink;
175   GstBus *bus;
176   guint id;
177   GstState current;
178   GstStateChangeReturn ret;
179
180   pipeline = gst_pipeline_new (NULL);
181   fail_unless (pipeline != NULL, "Could not create pipeline");
182   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
183
184   src = gst_element_factory_make ("fakesrc", NULL);
185   fail_unless (src != NULL);
186   sink = gst_element_factory_make ("fakesink", NULL);
187   fail_unless (sink != NULL);
188
189   gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);
190   fail_unless (gst_element_link (src, sink));
191
192   bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
193   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline after get_bus", 1);
194   ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
195
196   id = gst_bus_add_watch (bus, message_received, pipeline);
197   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline after add_watch", 1);
198   ASSERT_OBJECT_REFCOUNT (bus, "bus after add_watch", 3);
199
200   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
201   fail_unless (ret == GST_STATE_CHANGE_ASYNC);
202
203   loop = g_main_loop_new (NULL, FALSE);
204   GST_DEBUG ("going into main loop");
205   g_main_loop_run (loop);
206   GST_DEBUG ("left main loop");
207
208   /* PLAYING now */
209
210   ASSERT_OBJECT_REFCOUNT_BETWEEN (pipeline, "pipeline after gone to playing", 1,
211       3);
212
213   /* cleanup */
214   GST_DEBUG ("cleanup");
215
216   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
217   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
218   ret = gst_element_get_state (pipeline, &current, NULL, GST_CLOCK_TIME_NONE);
219   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
220   fail_unless (current == GST_STATE_NULL, "state is not NULL but %d", current);
221
222   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline at start of cleanup", 1);
223   ASSERT_OBJECT_REFCOUNT (bus, "bus at start of cleanup", 3);
224
225   fail_unless (g_source_remove (id));
226   ASSERT_OBJECT_REFCOUNT (bus, "bus after removing source", 2);
227
228   GST_DEBUG ("unreffing pipeline");
229   gst_object_unref (pipeline);
230
231   ASSERT_OBJECT_REFCOUNT (bus, "bus after unref pipeline", 1);
232   gst_object_unref (bus);
233 }
234
235 GST_END_TEST;
236
237 static GMutex *probe_lock;
238 static GCond *probe_cond;
239
240 static gboolean
241 sink_pad_probe (GstPad * pad, GstPadProbeType type, GstBuffer * buffer,
242     GstClockTime * first_timestamp)
243 {
244   fail_if (GST_BUFFER_TIMESTAMP (buffer) == GST_CLOCK_TIME_NONE,
245       "testing if buffer timestamps are right, but got CLOCK_TIME_NONE");
246
247   if (*first_timestamp == GST_CLOCK_TIME_NONE) {
248     *first_timestamp = GST_BUFFER_TIMESTAMP (buffer);
249   }
250
251   g_mutex_lock (probe_lock);
252   g_cond_signal (probe_cond);
253   g_mutex_unlock (probe_lock);
254
255   return TRUE;
256 }
257
258 GST_START_TEST (test_base_time)
259 {
260   GstElement *pipeline, *fakesrc, *fakesink;
261   GstPad *sink;
262   GstClockTime observed, lower, upper, base, stream;
263   GstClock *clock;
264
265   pipeline = gst_element_factory_make ("pipeline", "pipeline");
266   fakesrc = gst_element_factory_make ("fakesrc", "fakesrc");
267   fakesink = gst_element_factory_make ("fakesink", "fakesink");
268
269   fail_unless (pipeline && fakesrc && fakesink, "couldn't make elements");
270
271   g_object_set (fakesrc, "is-live", (gboolean) TRUE, NULL);
272
273   gst_bin_add_many (GST_BIN (pipeline), fakesrc, fakesink, NULL);
274   gst_element_link (fakesrc, fakesink);
275
276   sink = gst_element_get_static_pad (fakesink, "sink");
277   gst_pad_add_probe (sink, GST_PAD_PROBE_TYPE_BUFFER,
278       (GstPadProbeCallback) sink_pad_probe, &observed, NULL);
279
280   fail_unless (gst_element_set_state (pipeline, GST_STATE_PAUSED)
281       == GST_STATE_CHANGE_NO_PREROLL, "expected no-preroll from live pipeline");
282
283   clock = gst_system_clock_obtain ();
284   fail_unless (clock && GST_IS_CLOCK (clock), "i want a clock dammit");
285   gst_pipeline_use_clock (GST_PIPELINE (pipeline), clock);
286
287   fail_unless (gst_element_get_start_time (pipeline) == 0,
288       "stream time doesn't start off at 0");
289
290   probe_lock = g_mutex_new ();
291   probe_cond = g_cond_new ();
292
293   /* test the first: that base time is being distributed correctly, timestamps
294      are correct relative to the running clock and base time */
295   {
296     lower = gst_clock_get_time (clock);
297
298     observed = GST_CLOCK_TIME_NONE;
299
300     gst_element_set_state (pipeline, GST_STATE_PLAYING);
301     fail_unless (gst_element_get_state (pipeline, NULL, NULL,
302             GST_CLOCK_TIME_NONE)
303         == GST_STATE_CHANGE_SUCCESS, "failed state change");
304
305     g_mutex_lock (probe_lock);
306     while (observed == GST_CLOCK_TIME_NONE)
307       g_cond_wait (probe_cond, probe_lock);
308     g_mutex_unlock (probe_lock);
309
310     /* now something a little more than lower was distributed as the base time,
311      * and the buffer was timestamped between 0 and upper-base
312      */
313
314     base = gst_element_get_base_time (pipeline);
315     fail_if (base == GST_CLOCK_TIME_NONE);
316
317     /* set stream time */
318     gst_element_set_state (pipeline, GST_STATE_PAUSED);
319
320     /* pulling upper here makes sure that the pipeline's new stream time has
321        already been computed */
322     upper = gst_clock_get_time (clock);
323
324     fail_unless (gst_element_get_state (pipeline, NULL, NULL,
325             GST_CLOCK_TIME_NONE)
326         == GST_STATE_CHANGE_NO_PREROLL, "failed state change");
327
328     fail_if (observed == GST_CLOCK_TIME_NONE, "no timestamp recorded");
329
330     fail_unless (base >= lower, "early base time: %" GST_TIME_FORMAT " < %"
331         GST_TIME_FORMAT, GST_TIME_ARGS (base), GST_TIME_ARGS (lower));
332     fail_unless (upper >= base, "bogus base time: %" GST_TIME_FORMAT " > %"
333         GST_TIME_FORMAT, GST_TIME_ARGS (base), GST_TIME_ARGS (upper));
334
335     stream = gst_element_get_start_time (pipeline);
336
337     fail_unless (stream > 0, "bogus new stream time: %" GST_TIME_FORMAT " > %"
338         GST_TIME_FORMAT, GST_TIME_ARGS (stream), GST_TIME_ARGS (0));
339     fail_unless (stream <= upper,
340         "bogus new stream time: %" GST_TIME_FORMAT " > %" GST_TIME_FORMAT,
341         GST_TIME_ARGS (stream), GST_TIME_ARGS (upper));
342
343     fail_unless (observed <= stream, "timestamps outrun stream time: %"
344         GST_TIME_FORMAT " > %" GST_TIME_FORMAT,
345         GST_TIME_ARGS (observed), GST_TIME_ARGS (stream));
346     fail_unless (observed != GST_CLOCK_TIME_NONE, "early timestamp: %"
347         GST_TIME_FORMAT " < %" GST_TIME_FORMAT, GST_TIME_ARGS (observed),
348         GST_TIME_ARGS (lower - base));
349     fail_unless (observed <= upper - base,
350         "late timestamp: %" GST_TIME_FORMAT " > %" GST_TIME_FORMAT,
351         GST_TIME_ARGS (observed), GST_TIME_ARGS (upper - base));
352   }
353
354   /* test the second: that the base time is redistributed when we go to PLAYING
355      again */
356   {
357     GstClockID clock_id;
358     GstClockTime oldbase = base, oldstream = stream;
359
360     /* let some time pass */
361     clock_id = gst_clock_new_single_shot_id (clock, upper + WAIT_TIME);
362     fail_unless (gst_clock_id_wait (clock_id, NULL) == GST_CLOCK_OK,
363         "unexpected clock_id_wait return");
364     gst_clock_id_unref (clock_id);
365
366     lower = gst_clock_get_time (clock);
367     fail_if (lower == GST_CLOCK_TIME_NONE);
368
369     observed = GST_CLOCK_TIME_NONE;
370
371     fail_unless (lower >= upper + WAIT_TIME, "clock did not advance?");
372
373     gst_element_set_state (pipeline, GST_STATE_PLAYING);
374     fail_unless (gst_element_get_state (pipeline, NULL, NULL,
375             GST_CLOCK_TIME_NONE)
376         == GST_STATE_CHANGE_SUCCESS, "failed state change");
377
378     g_mutex_lock (probe_lock);
379     while (observed == GST_CLOCK_TIME_NONE)
380       g_cond_wait (probe_cond, probe_lock);
381     g_mutex_unlock (probe_lock);
382
383     /* now the base time should have advanced by more than WAIT_TIME compared
384      * to what it was. The buffer will be timestamped between the last stream
385      * time and upper minus base.
386      */
387
388     base = gst_element_get_base_time (pipeline);
389     fail_if (base == GST_CLOCK_TIME_NONE);
390
391     /* set stream time */
392     gst_element_set_state (pipeline, GST_STATE_PAUSED);
393
394     /* new stream time already set */
395     upper = gst_clock_get_time (clock);
396
397     fail_unless (gst_element_get_state (pipeline, NULL, NULL,
398             GST_CLOCK_TIME_NONE)
399         == GST_STATE_CHANGE_NO_PREROLL, "failed state change");
400
401     fail_if (observed == GST_CLOCK_TIME_NONE, "no timestamp recorded");
402
403     stream = gst_element_get_start_time (pipeline);
404
405     fail_unless (base >= oldbase + WAIT_TIME, "base time not reset");
406     fail_unless (upper >= base + stream, "bogus base time: %"
407         GST_TIME_FORMAT " > %" GST_TIME_FORMAT, GST_TIME_ARGS (base),
408         GST_TIME_ARGS (upper));
409
410     fail_unless (lower >= base);
411     fail_unless (observed >= lower - base, "early timestamp: %"
412         GST_TIME_FORMAT " < %" GST_TIME_FORMAT,
413         GST_TIME_ARGS (observed), GST_TIME_ARGS (lower - base));
414     fail_unless (observed <= upper - base, "late timestamp: %"
415         GST_TIME_FORMAT " > %" GST_TIME_FORMAT,
416         GST_TIME_ARGS (observed), GST_TIME_ARGS (upper - base));
417     fail_unless (stream - oldstream <= upper - lower,
418         "insufficient stream time: %" GST_TIME_FORMAT " > %" GST_TIME_FORMAT,
419         GST_TIME_ARGS (observed), GST_TIME_ARGS (upper));
420   }
421
422   /* test the third: that if I set CLOCK_TIME_NONE as the stream time, that the
423      base time is not changed */
424   {
425     GstClockID clock_id;
426     GstClockTime oldbase = base, oldobserved = observed;
427     GstClockReturn ret;
428
429     /* let some time pass */
430     clock_id = gst_clock_new_single_shot_id (clock, upper + WAIT_TIME);
431     ret = gst_clock_id_wait (clock_id, NULL);
432     fail_unless (ret == GST_CLOCK_OK,
433         "unexpected clock_id_wait return %d", ret);
434     gst_clock_id_unref (clock_id);
435
436     lower = gst_clock_get_time (clock);
437
438     observed = GST_CLOCK_TIME_NONE;
439
440     fail_unless (lower >= upper + WAIT_TIME, "clock did not advance?");
441
442     /* bling */
443     gst_element_set_start_time (pipeline, GST_CLOCK_TIME_NONE);
444
445     gst_element_set_state (pipeline, GST_STATE_PLAYING);
446     fail_unless (gst_element_get_state (pipeline, NULL, NULL,
447             GST_CLOCK_TIME_NONE)
448         == GST_STATE_CHANGE_SUCCESS, "failed state change");
449
450     g_mutex_lock (probe_lock);
451     while (observed == GST_CLOCK_TIME_NONE)
452       g_cond_wait (probe_cond, probe_lock);
453     g_mutex_unlock (probe_lock);
454
455     /* now the base time should be the same as it was, and the timestamp should
456      * be more than WAIT_TIME past what it was.
457      */
458
459     base = gst_element_get_base_time (pipeline);
460
461     /* set stream time */
462     gst_element_set_state (pipeline, GST_STATE_PAUSED);
463
464     /* new stream time already set */
465     upper = gst_clock_get_time (clock);
466
467     fail_unless (gst_element_get_state (pipeline, NULL, NULL,
468             GST_CLOCK_TIME_NONE)
469         == GST_STATE_CHANGE_NO_PREROLL, "failed state change");
470
471     fail_if (observed == GST_CLOCK_TIME_NONE, "no timestamp recorded");
472
473     fail_unless (gst_element_get_start_time (pipeline)
474         == GST_CLOCK_TIME_NONE, "stream time was reset");
475
476     fail_unless (base == oldbase, "base time was reset");
477
478     fail_unless (observed >= lower - base, "early timestamp: %"
479         GST_TIME_FORMAT " < %" GST_TIME_FORMAT,
480         GST_TIME_ARGS (observed), GST_TIME_ARGS (lower - base));
481     fail_unless (observed <= upper - base, "late timestamp: %"
482         GST_TIME_FORMAT " > %" GST_TIME_FORMAT,
483         GST_TIME_ARGS (observed), GST_TIME_ARGS (upper - base));
484     fail_unless (observed - oldobserved >= WAIT_TIME,
485         "insufficient tstamp delta: %" GST_TIME_FORMAT " > %" GST_TIME_FORMAT,
486         GST_TIME_ARGS (observed), GST_TIME_ARGS (oldobserved));
487   }
488
489   gst_object_unref (sink);
490   gst_object_unref (clock);
491   gst_object_unref (pipeline);
492 }
493
494 GST_END_TEST;
495
496 static gpointer
497 pipeline_thread (gpointer data)
498 {
499   GstElement *pipeline, *src, *sink;
500
501   src = gst_element_factory_make ("fakesrc", NULL);
502   g_object_set (src, "num-buffers", 20, NULL);
503   sink = gst_element_factory_make ("fakesink", NULL);
504   g_object_set (sink, "sync", TRUE, NULL);
505   pipeline = gst_pipeline_new (NULL);
506   gst_bin_add (GST_BIN (pipeline), src);
507   gst_bin_add (GST_BIN (pipeline), sink);
508   gst_element_link (src, sink);
509   gst_element_set_state (pipeline, GST_STATE_PLAYING);
510   g_usleep (G_USEC_PER_SEC / 10);
511   gst_element_set_state (pipeline, GST_STATE_NULL);
512   gst_object_unref (pipeline);
513   return NULL;
514 }
515
516 GST_START_TEST (test_concurrent_create)
517 {
518   GThread *threads[30];
519   int i;
520
521   for (i = 0; i < G_N_ELEMENTS (threads); ++i) {
522     threads[i] = g_thread_create (pipeline_thread, NULL, TRUE, NULL);
523   }
524   for (i = 0; i < G_N_ELEMENTS (threads); ++i) {
525     if (threads[i])
526       g_thread_join (threads[i]);
527   }
528 }
529
530 GST_END_TEST;
531
532 GST_START_TEST (test_pipeline_in_pipeline)
533 {
534   GstElement *pipeline, *bin, *fakesrc, *fakesink;
535   GstMessage *msg;
536
537   pipeline = gst_element_factory_make ("pipeline", "pipeline");
538   bin = gst_element_factory_make ("pipeline", "pipeline-as-bin");
539   fakesrc = gst_element_factory_make ("fakesrc", "fakesrc");
540   fakesink = gst_element_factory_make ("fakesink", "fakesink");
541
542   fail_unless (pipeline && bin && fakesrc && fakesink);
543
544   g_object_set (fakesrc, "num-buffers", 100, NULL);
545
546   gst_bin_add (GST_BIN (pipeline), bin);
547   gst_bin_add_many (GST_BIN (bin), fakesrc, fakesink, NULL);
548   gst_element_link (fakesrc, fakesink);
549
550   fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING),
551       GST_STATE_CHANGE_ASYNC);
552
553   msg = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipeline), -1,
554       GST_MESSAGE_EOS);
555   gst_message_unref (msg);
556
557   gst_element_set_state (pipeline, GST_STATE_NULL);
558
559   gst_object_unref (pipeline);
560 }
561
562 GST_END_TEST;
563
564 static Suite *
565 gst_pipeline_suite (void)
566 {
567   Suite *s = suite_create ("GstPipeline");
568   TCase *tc_chain = tcase_create ("pipeline tests");
569
570   tcase_set_timeout (tc_chain, 0);
571
572   suite_add_tcase (s, tc_chain);
573   tcase_add_test (tc_chain, test_async_state_change_empty);
574   tcase_add_test (tc_chain, test_async_state_change_fake_ready);
575   tcase_add_test (tc_chain, test_async_state_change_fake);
576   tcase_add_test (tc_chain, test_get_bus);
577   tcase_add_test (tc_chain, test_bus);
578   tcase_add_test (tc_chain, test_base_time);
579   tcase_add_test (tc_chain, test_concurrent_create);
580   tcase_add_test (tc_chain, test_pipeline_in_pipeline);
581
582   return s;
583 }
584
585 GST_CHECK_MAIN (gst_pipeline);