tests/check/: use the new macro
[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
22 #include <gst/check/gstcheck.h>
23
24 #define WAIT_TIME (300 * GST_MSECOND)
25
26 /* an empty pipeline can go to PLAYING in one go */
27 GST_START_TEST (test_async_state_change_empty)
28 {
29   GstPipeline *pipeline;
30
31   pipeline = GST_PIPELINE (gst_pipeline_new (NULL));
32   fail_unless (pipeline != NULL, "Could not create pipeline");
33
34   fail_unless_equals_int (gst_element_set_state (GST_ELEMENT (pipeline),
35           GST_STATE_PLAYING), GST_STATE_CHANGE_SUCCESS);
36
37   gst_object_unref (pipeline);
38 }
39
40 GST_END_TEST;
41
42 GST_START_TEST (test_async_state_change_fake_ready)
43 {
44   GstPipeline *pipeline;
45   GstElement *src, *sink;
46
47   pipeline = GST_PIPELINE (gst_pipeline_new (NULL));
48   fail_unless (pipeline != NULL, "Could not create pipeline");
49
50   src = gst_element_factory_make ("fakesrc", NULL);
51   sink = gst_element_factory_make ("fakesink", NULL);
52
53   gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);
54   gst_element_link (src, sink);
55
56   fail_unless_equals_int (gst_element_set_state (GST_ELEMENT (pipeline),
57           GST_STATE_READY), GST_STATE_CHANGE_SUCCESS);
58
59   gst_object_unref (pipeline);
60 }
61
62 GST_END_TEST;
63
64
65 GST_START_TEST (test_async_state_change_fake)
66 {
67   GstPipeline *pipeline;
68   GstElement *src, *sink;
69   GstBus *bus;
70   gboolean done = FALSE;
71
72   pipeline = GST_PIPELINE (gst_pipeline_new (NULL));
73   fail_unless (pipeline != NULL, "Could not create pipeline");
74
75   src = gst_element_factory_make ("fakesrc", NULL);
76   sink = gst_element_factory_make ("fakesink", NULL);
77
78   gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);
79   gst_element_link (src, sink);
80
81   bus = gst_pipeline_get_bus (pipeline);
82
83   fail_unless_equals_int (gst_element_set_state (GST_ELEMENT (pipeline),
84           GST_STATE_PLAYING), GST_STATE_CHANGE_ASYNC);
85
86   while (!done) {
87     GstMessage *message;
88     GstState old, new, pending;
89
90     message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1);
91     if (message) {
92       gst_message_parse_state_changed (message, &old, &new, &pending);
93       GST_DEBUG_OBJECT (message->src, "state change from %d to %d", old, new);
94       if (message->src == GST_OBJECT (pipeline) && new == GST_STATE_PLAYING)
95         done = TRUE;
96       gst_message_unref (message);
97     }
98   }
99
100   fail_unless_equals_int (gst_element_set_state (GST_ELEMENT (pipeline),
101           GST_STATE_NULL), GST_STATE_CHANGE_SUCCESS);
102
103   gst_object_unref (bus);
104   gst_object_unref (pipeline);
105 }
106
107 GST_END_TEST;
108
109 GST_START_TEST (test_get_bus)
110 {
111   GstPipeline *pipeline;
112   GstBus *bus;
113
114   pipeline = GST_PIPELINE (gst_pipeline_new (NULL));
115   fail_unless (pipeline != NULL, "Could not create pipeline");
116   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
117
118   bus = gst_pipeline_get_bus (pipeline);
119   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline after get_bus", 1);
120   ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
121
122   gst_object_unref (pipeline);
123
124   ASSERT_OBJECT_REFCOUNT (bus, "bus after unref pipeline", 1);
125   gst_object_unref (bus);
126 }
127
128 GST_END_TEST;
129
130 GMainLoop *loop = NULL;
131
132 gboolean
133 message_received (GstBus * bus, GstMessage * message, gpointer data)
134 {
135   GstElement *pipeline = GST_ELEMENT (data);
136   GstMessageType type = message->type;
137
138   GST_DEBUG ("message received");
139   switch (type) {
140     case GST_MESSAGE_STATE_CHANGED:
141     {
142       GstState old, new, pending;
143
144       GST_DEBUG ("state change message received");
145       gst_message_parse_state_changed (message, &old, &new, &pending);
146       GST_DEBUG ("new state %d", new);
147       if (message->src == GST_OBJECT (pipeline) && new == GST_STATE_PLAYING) {
148         GST_DEBUG ("quitting main loop");
149         g_main_loop_quit (loop);
150       }
151     }
152       break;
153     case GST_MESSAGE_ERROR:
154     {
155       g_print ("error\n");
156     }
157       break;
158     default:
159       break;
160   }
161
162   return TRUE;
163 }
164
165 GST_START_TEST (test_bus)
166 {
167   GstElement *pipeline;
168   GstElement *src, *sink;
169   GstBus *bus;
170   guint id;
171   GstState current;
172   GstStateChangeReturn ret;
173
174   pipeline = gst_pipeline_new (NULL);
175   fail_unless (pipeline != NULL, "Could not create pipeline");
176   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
177
178   src = gst_element_factory_make ("fakesrc", NULL);
179   fail_unless (src != NULL);
180   sink = gst_element_factory_make ("fakesink", NULL);
181   fail_unless (sink != NULL);
182
183   gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);
184   fail_unless (gst_element_link (src, sink));
185
186   bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
187   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline after get_bus", 1);
188   ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
189
190   id = gst_bus_add_watch (bus, message_received, pipeline);
191   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline after add_watch", 1);
192   ASSERT_OBJECT_REFCOUNT (bus, "bus after add_watch", 3);
193
194   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
195   fail_unless (ret == GST_STATE_CHANGE_ASYNC);
196
197   loop = g_main_loop_new (NULL, FALSE);
198   GST_DEBUG ("going into main loop");
199   g_main_loop_run (loop);
200   GST_DEBUG ("left main loop");
201
202   /* PLAYING now */
203
204   ASSERT_OBJECT_REFCOUNT_BETWEEN (pipeline, "pipeline after gone to playing", 1,
205       3);
206
207   /* cleanup */
208   GST_DEBUG ("cleanup");
209
210   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
211   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
212   ret = gst_element_get_state (pipeline, &current, NULL, GST_CLOCK_TIME_NONE);
213   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
214   fail_unless (current == GST_STATE_NULL, "state is not NULL but %d", current);
215
216   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline at start of cleanup", 1);
217   ASSERT_OBJECT_REFCOUNT (bus, "bus at start of cleanup", 3);
218
219   fail_unless (g_source_remove (id));
220   ASSERT_OBJECT_REFCOUNT (bus, "bus after removing source", 2);
221
222   GST_DEBUG ("unreffing pipeline");
223   gst_object_unref (pipeline);
224
225   ASSERT_OBJECT_REFCOUNT (bus, "bus after unref pipeline", 1);
226   gst_object_unref (bus);
227 }
228
229 GST_END_TEST;
230
231 static GMutex *probe_lock;
232 static GCond *probe_cond;
233
234 static gboolean
235 sink_pad_probe (GstPad * pad, GstBuffer * buffer,
236     GstClockTime * first_timestamp)
237 {
238   fail_if (GST_BUFFER_TIMESTAMP (buffer) == GST_CLOCK_TIME_NONE,
239       "testing if buffer timestamps are right, but got CLOCK_TIME_NONE");
240
241   if (*first_timestamp == GST_CLOCK_TIME_NONE) {
242     *first_timestamp = GST_BUFFER_TIMESTAMP (buffer);
243   }
244
245   g_mutex_lock (probe_lock);
246   g_cond_signal (probe_cond);
247   g_mutex_unlock (probe_lock);
248
249   return TRUE;
250 }
251
252 GST_START_TEST (test_base_time)
253 {
254   GstElement *pipeline, *fakesrc, *fakesink;
255   GstPad *sink;
256   GstClockTime observed, lower, upper, base, stream;
257   GstClock *clock;
258
259   pipeline = gst_element_factory_make ("pipeline", "pipeline");
260   fakesrc = gst_element_factory_make ("fakesrc", "fakesrc");
261   fakesink = gst_element_factory_make ("fakesink", "fakesink");
262
263   fail_unless (pipeline && fakesrc && fakesink, "couldn't make elements");
264
265   g_object_set (fakesrc, "is-live", (gboolean) TRUE, NULL);
266
267   gst_bin_add_many (GST_BIN (pipeline), fakesrc, fakesink, NULL);
268   gst_element_link (fakesrc, fakesink);
269
270   sink = gst_element_get_pad (fakesink, "sink");
271   gst_pad_add_buffer_probe (sink, G_CALLBACK (sink_pad_probe), &observed);
272
273   fail_unless (gst_element_set_state (pipeline, GST_STATE_PAUSED)
274       == GST_STATE_CHANGE_NO_PREROLL, "expected no-preroll from live pipeline");
275
276   clock = gst_system_clock_obtain ();
277   fail_unless (clock && GST_IS_CLOCK (clock), "i want a clock dammit");
278   gst_pipeline_use_clock (GST_PIPELINE (pipeline), clock);
279
280   fail_unless (gst_pipeline_get_last_stream_time (GST_PIPELINE (pipeline)) == 0,
281       "stream time doesn't start off at 0");
282
283   probe_lock = g_mutex_new ();
284   probe_cond = g_cond_new ();
285
286   /* test the first: that base time is being distributed correctly, timestamps
287      are correct relative to the running clock and base time */
288   {
289     lower = gst_clock_get_time (clock);
290
291     observed = GST_CLOCK_TIME_NONE;
292
293     gst_element_set_state (pipeline, GST_STATE_PLAYING);
294     fail_unless (gst_element_get_state (pipeline, NULL, NULL,
295             GST_CLOCK_TIME_NONE)
296         == GST_STATE_CHANGE_SUCCESS, "failed state change");
297
298     g_mutex_lock (probe_lock);
299     while (observed == GST_CLOCK_TIME_NONE)
300       g_cond_wait (probe_cond, probe_lock);
301     g_mutex_unlock (probe_lock);
302
303     /* now something a little more than lower was distributed as the base time,
304      * and the buffer was timestamped between 0 and upper-base
305      */
306
307     base = gst_element_get_base_time (pipeline);
308     fail_if (base == GST_CLOCK_TIME_NONE);
309
310     /* set stream time */
311     gst_element_set_state (pipeline, GST_STATE_PAUSED);
312
313     /* pulling upper here makes sure that the pipeline's new stream time has
314        already been computed */
315     upper = gst_clock_get_time (clock);
316
317     fail_unless (gst_element_get_state (pipeline, NULL, NULL,
318             GST_CLOCK_TIME_NONE)
319         == GST_STATE_CHANGE_NO_PREROLL, "failed state change");
320
321     fail_if (observed == GST_CLOCK_TIME_NONE, "no timestamp recorded");
322
323     fail_unless (base >= lower, "early base time: %" GST_TIME_FORMAT " < %"
324         GST_TIME_FORMAT, GST_TIME_ARGS (base), GST_TIME_ARGS (lower));
325     fail_unless (upper >= base, "bogus base time: %" GST_TIME_FORMAT " > %"
326         GST_TIME_FORMAT, GST_TIME_ARGS (base), GST_TIME_ARGS (upper));
327
328     stream = gst_pipeline_get_last_stream_time (GST_PIPELINE (pipeline));
329
330     fail_unless (stream > 0, "bogus new stream time: %" GST_TIME_FORMAT " > %"
331         GST_TIME_FORMAT, GST_TIME_ARGS (stream), GST_TIME_ARGS (0));
332     fail_unless (stream <= upper,
333         "bogus new stream time: %" GST_TIME_FORMAT " > %" GST_TIME_FORMAT,
334         GST_TIME_ARGS (stream), GST_TIME_ARGS (upper));
335
336     fail_unless (observed <= stream, "timestamps outrun stream time: %"
337         GST_TIME_FORMAT " > %" GST_TIME_FORMAT,
338         GST_TIME_ARGS (observed), GST_TIME_ARGS (stream));
339     fail_unless (observed >= 0, "early timestamp: %" GST_TIME_FORMAT " < %"
340         GST_TIME_FORMAT, GST_TIME_ARGS (observed),
341         GST_TIME_ARGS (lower - base));
342     fail_unless (observed <= upper - base,
343         "late timestamp: %" GST_TIME_FORMAT " > %" GST_TIME_FORMAT,
344         GST_TIME_ARGS (observed), GST_TIME_ARGS (upper - base));
345   }
346
347   /* test the second: that the base time is redistributed when we go to PLAYING
348      again */
349   {
350     GstClockID clock_id;
351     GstClockTime oldbase = base, oldstream = stream;
352
353     /* let some time pass */
354     clock_id = gst_clock_new_single_shot_id (clock, upper + WAIT_TIME);
355     fail_unless (gst_clock_id_wait (clock_id, NULL) == GST_CLOCK_OK,
356         "unexpected clock_id_wait return");
357     gst_clock_id_unref (clock_id);
358
359     lower = gst_clock_get_time (clock);
360     fail_if (lower == GST_CLOCK_TIME_NONE);
361
362     observed = GST_CLOCK_TIME_NONE;
363
364     fail_unless (lower >= upper + WAIT_TIME, "clock did not advance?");
365
366     gst_element_set_state (pipeline, GST_STATE_PLAYING);
367     fail_unless (gst_element_get_state (pipeline, NULL, NULL,
368             GST_CLOCK_TIME_NONE)
369         == GST_STATE_CHANGE_SUCCESS, "failed state change");
370
371     g_mutex_lock (probe_lock);
372     while (observed == GST_CLOCK_TIME_NONE)
373       g_cond_wait (probe_cond, probe_lock);
374     g_mutex_unlock (probe_lock);
375
376     /* now the base time should have advanced by more than WAIT_TIME compared
377      * to what it was. The buffer will be timestamped between the last stream
378      * time and upper minus base.
379      */
380
381     base = gst_element_get_base_time (pipeline);
382     fail_if (base == GST_CLOCK_TIME_NONE);
383
384     /* set stream time */
385     gst_element_set_state (pipeline, GST_STATE_PAUSED);
386
387     /* new stream time already set */
388     upper = gst_clock_get_time (clock);
389
390     fail_unless (gst_element_get_state (pipeline, NULL, NULL,
391             GST_CLOCK_TIME_NONE)
392         == GST_STATE_CHANGE_NO_PREROLL, "failed state change");
393
394     fail_if (observed == GST_CLOCK_TIME_NONE, "no timestamp recorded");
395
396     stream = gst_pipeline_get_last_stream_time (GST_PIPELINE (pipeline));
397
398     fail_unless (base >= oldbase + WAIT_TIME, "base time not reset");
399     fail_unless (upper >= base + stream, "bogus base time: %"
400         GST_TIME_FORMAT " > %" GST_TIME_FORMAT, GST_TIME_ARGS (base),
401         GST_TIME_ARGS (upper));
402
403     fail_unless (lower >= base);
404     fail_unless (observed >= lower - base, "early timestamp: %"
405         GST_TIME_FORMAT " < %" GST_TIME_FORMAT,
406         GST_TIME_ARGS (observed), GST_TIME_ARGS (lower - base));
407     fail_unless (observed <= upper - base, "late timestamp: %"
408         GST_TIME_FORMAT " > %" GST_TIME_FORMAT,
409         GST_TIME_ARGS (observed), GST_TIME_ARGS (upper - base));
410     fail_unless (stream - oldstream <= upper - lower,
411         "insufficient stream time: %" GST_TIME_FORMAT " > %" GST_TIME_FORMAT,
412         GST_TIME_ARGS (observed), GST_TIME_ARGS (upper));
413   }
414
415   /* test the third: that if I set CLOCK_TIME_NONE as the stream time, that the
416      base time is not changed */
417   {
418     GstClockID clock_id;
419     GstClockTime oldbase = base, oldobserved = observed;
420     GstClockReturn ret;
421
422     /* let some time pass */
423     clock_id = gst_clock_new_single_shot_id (clock, upper + WAIT_TIME);
424     ret = gst_clock_id_wait (clock_id, NULL);
425     fail_unless (ret == GST_CLOCK_OK,
426         "unexpected clock_id_wait return %d", ret);
427     gst_clock_id_unref (clock_id);
428
429     lower = gst_clock_get_time (clock);
430
431     observed = GST_CLOCK_TIME_NONE;
432
433     fail_unless (lower >= upper + WAIT_TIME, "clock did not advance?");
434
435     /* bling */
436     gst_pipeline_set_new_stream_time (GST_PIPELINE (pipeline),
437         GST_CLOCK_TIME_NONE);
438
439     gst_element_set_state (pipeline, GST_STATE_PLAYING);
440     fail_unless (gst_element_get_state (pipeline, NULL, NULL,
441             GST_CLOCK_TIME_NONE)
442         == GST_STATE_CHANGE_SUCCESS, "failed state change");
443
444     g_mutex_lock (probe_lock);
445     while (observed == GST_CLOCK_TIME_NONE)
446       g_cond_wait (probe_cond, probe_lock);
447     g_mutex_unlock (probe_lock);
448
449     /* now the base time should be the same as it was, and the timestamp should
450      * be more than WAIT_TIME past what it was.
451      */
452
453     base = gst_element_get_base_time (pipeline);
454
455     /* set stream time */
456     gst_element_set_state (pipeline, GST_STATE_PAUSED);
457
458     /* new stream time already set */
459     upper = gst_clock_get_time (clock);
460
461     fail_unless (gst_element_get_state (pipeline, NULL, NULL,
462             GST_CLOCK_TIME_NONE)
463         == GST_STATE_CHANGE_NO_PREROLL, "failed state change");
464
465     fail_if (observed == GST_CLOCK_TIME_NONE, "no timestamp recorded");
466
467     fail_unless (gst_pipeline_get_last_stream_time (GST_PIPELINE (pipeline))
468         == GST_CLOCK_TIME_NONE, "stream time was reset");
469
470     fail_unless (base == oldbase, "base time was reset");
471
472     fail_unless (observed >= lower - base, "early timestamp: %"
473         GST_TIME_FORMAT " < %" GST_TIME_FORMAT,
474         GST_TIME_ARGS (observed), GST_TIME_ARGS (lower - base));
475     fail_unless (observed <= upper - base, "late timestamp: %"
476         GST_TIME_FORMAT " > %" GST_TIME_FORMAT,
477         GST_TIME_ARGS (observed), GST_TIME_ARGS (upper - base));
478     fail_unless (observed - oldobserved >= WAIT_TIME,
479         "insufficient tstamp delta: %" GST_TIME_FORMAT " > %" GST_TIME_FORMAT,
480         GST_TIME_ARGS (observed), GST_TIME_ARGS (oldobserved));
481   }
482
483   gst_object_unref (sink);
484   gst_object_unref (clock);
485   gst_object_unref (pipeline);
486 }
487
488 GST_END_TEST;
489
490 Suite *
491 gst_pipeline_suite (void)
492 {
493   Suite *s = suite_create ("GstPipeline");
494   TCase *tc_chain = tcase_create ("pipeline tests");
495
496   tcase_set_timeout (tc_chain, 0);
497
498   suite_add_tcase (s, tc_chain);
499   tcase_add_test (tc_chain, test_async_state_change_empty);
500   tcase_add_test (tc_chain, test_async_state_change_fake_ready);
501   tcase_add_test (tc_chain, test_async_state_change_fake);
502   tcase_add_test (tc_chain, test_get_bus);
503   tcase_add_test (tc_chain, test_bus);
504   tcase_add_test (tc_chain, test_base_time);
505
506   return s;
507 }
508
509 GST_CHECK_MAIN (gst_pipeline);