check/states/sinks.c (test_livesrc_sink): Add checks that the state-changed messages...
[platform/upstream/gstreamer.git] / tests / check / generic / sinks.c
1 /* GStreamer
2  *
3  * unit test for sinks
4  *
5  * Copyright (C) <2005> Wim Taymans <wim at fluendo dot com>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include <gst/check/gstcheck.h>
24
25 static void
26 pop_state_change_message (GstBus * bus, GstElement * src, GstState old,
27     GstState new, GstState pending)
28 {
29   GstMessage *message = NULL;
30   GstState _old, _new, _pending;
31
32   message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND);
33   fail_unless (message != NULL,
34       "Expected state change message, but got nothing");
35
36   gst_message_parse_state_changed (message, &_old, &_new, &_pending);
37
38   fail_unless (GST_MESSAGE_SRC (message) == (GstObject *) src,
39       "Unexpected state change order");
40   fail_unless (old == _old, "Unexpected old state");
41   fail_unless (new == _new, "Unexpected new state");
42   fail_unless (pending == _pending, "Unexpected pending state");
43
44   gst_message_unref (message);
45 }
46
47 /* a sink should go ASYNC to PAUSE. forcing PLAYING is possible */
48 GST_START_TEST (test_sink)
49 {
50   GstElement *sink;
51   GstStateChangeReturn ret;
52   GstState current, pending;
53
54   sink = gst_element_factory_make ("fakesink", "sink");
55
56   ret = gst_element_set_state (sink, GST_STATE_PAUSED);
57   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no async state return");
58
59   ret = gst_element_set_state (sink, GST_STATE_PLAYING);
60   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no forced async state change");
61
62   ret = gst_element_get_state (sink, &current, &pending, 0);
63   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not changing state async");
64   fail_unless (current == GST_STATE_READY, "bad current state");
65   fail_unless (pending == GST_STATE_PLAYING, "bad pending state");
66
67   ret = gst_element_set_state (sink, GST_STATE_PAUSED);
68   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no async going back to paused");
69
70   ret = gst_element_set_state (sink, GST_STATE_READY);
71   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "failed to go to ready");
72
73   ret = gst_element_set_state (sink, GST_STATE_NULL);
74   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "failed to go to null");
75
76   gst_object_unref (sink);
77 }
78
79 GST_END_TEST
80 /* a sink should go ASYNC to PAUSE and PLAYING, when linking a src, it
81  * should complete the state change. */
82 GST_START_TEST (test_sink_completion)
83 {
84   GstElement *sink, *src;
85   GstStateChangeReturn ret;
86   GstState current, pending;
87
88   sink = gst_element_factory_make ("fakesink", "sink");
89
90   ret = gst_element_set_state (sink, GST_STATE_PLAYING);
91   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no async state return");
92
93   ret = gst_element_get_state (sink, &current, &pending, 0);
94   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not changing state async");
95   fail_unless (current == GST_STATE_READY, "bad current state");
96   fail_unless (pending == GST_STATE_PLAYING, "bad pending state");
97
98   src = gst_element_factory_make ("fakesrc", "src");
99   gst_element_link (src, sink);
100
101   ret = gst_element_set_state (src, GST_STATE_PLAYING);
102   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no success state return");
103
104   /* now wait for final state */
105   ret = gst_element_get_state (sink, &current, &pending, GST_CLOCK_TIME_NONE);
106   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "failed to change state");
107   fail_unless (current == GST_STATE_PLAYING, "bad current state");
108   fail_unless (pending == GST_STATE_VOID_PENDING, "bad pending state");
109
110   ret = gst_element_set_state (sink, GST_STATE_NULL);
111   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "failed to go to null");
112
113   ret = gst_element_set_state (src, GST_STATE_NULL);
114   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "failed to go to null");
115
116   gst_object_unref (sink);
117   gst_object_unref (src);
118 }
119
120 GST_END_TEST
121 /* a sink should go ASYNC to PAUSE. PAUSE should complete when
122  * prerolled. */
123 GST_START_TEST (test_src_sink)
124 {
125   GstElement *sink, *src, *pipeline;
126   GstStateChangeReturn ret;
127   GstState current, pending;
128   GstPad *srcpad, *sinkpad;
129
130   pipeline = gst_pipeline_new ("pipeline");
131   src = gst_element_factory_make ("fakesrc", "src");
132   sink = gst_element_factory_make ("fakesink", "sink");
133
134   gst_bin_add (GST_BIN (pipeline), src);
135   gst_bin_add (GST_BIN (pipeline), sink);
136
137   srcpad = gst_element_get_pad (src, "src");
138   sinkpad = gst_element_get_pad (sink, "sink");
139   gst_pad_link (srcpad, sinkpad);
140   gst_object_unref (srcpad);
141   gst_object_unref (sinkpad);
142
143   ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
144   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no async state return");
145   ret = gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
146   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no success state return");
147
148   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
149   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "cannot start play");
150
151   ret =
152       gst_element_get_state (pipeline, &current, &pending, GST_CLOCK_TIME_NONE);
153   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not playing");
154   fail_unless (current == GST_STATE_PLAYING, "not playing");
155   fail_unless (pending == GST_STATE_VOID_PENDING, "not playing");
156   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
157   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "cannot null pipeline");
158
159   gst_object_unref (pipeline);
160
161 }
162
163 GST_END_TEST
164 /* a pipeline with live source should return NO_PREROLL in
165  * PAUSE. When removing the live source it should return ASYNC
166  * from the sink */
167 GST_START_TEST (test_livesrc_remove)
168 {
169   GstElement *sink, *src, *pipeline;
170   GstStateChangeReturn ret;
171   GstState current, pending;
172   GstPad *srcpad, *sinkpad;
173
174   pipeline = gst_pipeline_new ("pipeline");
175   src = gst_element_factory_make ("fakesrc", "src");
176   g_object_set (G_OBJECT (src), "is-live", TRUE, NULL);
177   sink = gst_element_factory_make ("fakesink", "sink");
178
179   gst_bin_add (GST_BIN (pipeline), src);
180   gst_bin_add (GST_BIN (pipeline), sink);
181
182   srcpad = gst_element_get_pad (src, "src");
183   sinkpad = gst_element_get_pad (sink, "sink");
184   gst_pad_link (srcpad, sinkpad);
185   gst_object_unref (srcpad);
186   gst_object_unref (sinkpad);
187
188   ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
189   fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL,
190       "no no_preroll state return");
191
192   ret = gst_element_get_state (src, &current, &pending, GST_CLOCK_TIME_NONE);
193   fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not paused");
194   fail_unless (current == GST_STATE_PAUSED, "not paused");
195   fail_unless (pending == GST_STATE_VOID_PENDING, "not playing");
196
197   gst_bin_remove (GST_BIN (pipeline), src);
198
199   ret = gst_element_get_state (pipeline, &current, &pending, 0);
200   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not async");
201   fail_unless (current == GST_STATE_PAUSED, "not paused");
202   fail_unless (pending == GST_STATE_PAUSED, "not paused");
203 }
204
205 GST_END_TEST
206 /* the sink should go ASYNC to PAUSE. The live source should go
207  * NO_PREROLL to PAUSE. the pipeline returns NO_PREROLL. An
208  * attempt to go to PLAYING will return ASYNC. polling state
209  * completion should return SUCCESS when the sink is gone to
210  * PLAYING. */
211 GST_START_TEST (test_livesrc_sink)
212 {
213   GstElement *sink, *src, *pipeline;
214   GstStateChangeReturn ret;
215   GstState current, pending;
216   GstPad *srcpad, *sinkpad;
217   GstBus *bus;
218
219   pipeline = gst_pipeline_new ("pipeline");
220   src = gst_element_factory_make ("fakesrc", "src");
221   g_object_set (G_OBJECT (src), "is-live", TRUE, NULL);
222   sink = gst_element_factory_make ("fakesink", "sink");
223
224   gst_bin_add (GST_BIN (pipeline), src);
225   gst_bin_add (GST_BIN (pipeline), sink);
226
227   srcpad = gst_element_get_pad (src, "src");
228   sinkpad = gst_element_get_pad (sink, "sink");
229   gst_pad_link (srcpad, sinkpad);
230   gst_object_unref (srcpad);
231   gst_object_unref (sinkpad);
232
233   bus = gst_element_get_bus (pipeline);
234
235   ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
236   fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL,
237       "no no_preroll state return");
238
239   pop_state_change_message (bus, sink, GST_STATE_NULL, GST_STATE_READY,
240       GST_STATE_VOID_PENDING);
241   pop_state_change_message (bus, src, GST_STATE_NULL, GST_STATE_READY,
242       GST_STATE_VOID_PENDING);
243   pop_state_change_message (bus, pipeline, GST_STATE_NULL, GST_STATE_READY,
244       GST_STATE_PAUSED);
245
246   /* this order only holds true for live sources because they do not push
247      buffers in PAUSED */
248   pop_state_change_message (bus, src, GST_STATE_READY, GST_STATE_PAUSED,
249       GST_STATE_VOID_PENDING);
250   pop_state_change_message (bus, pipeline, GST_STATE_READY, GST_STATE_PAUSED,
251       GST_STATE_VOID_PENDING);
252
253   ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
254   fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL,
255       "no no_preroll state return the second time");
256
257   ret = gst_element_get_state (src, &current, &pending, GST_CLOCK_TIME_NONE);
258   fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not paused");
259   fail_unless (current == GST_STATE_PAUSED, "not paused");
260   fail_unless (pending == GST_STATE_VOID_PENDING, "not playing");
261
262   /* don't block here */
263   ret = gst_element_get_state (sink, &current, &pending, 0);
264   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not async");
265   fail_unless (current == GST_STATE_READY, "not ready");
266   fail_unless (pending == GST_STATE_PAUSED, "not paused");
267
268   ret =
269       gst_element_get_state (pipeline, &current, &pending, GST_CLOCK_TIME_NONE);
270   fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not paused");
271   fail_unless (current == GST_STATE_PAUSED, "not paused");
272   fail_unless (pending == GST_STATE_VOID_PENDING, "not playing");
273
274   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
275   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not async");
276   ret =
277       gst_element_get_state (pipeline, &current, &pending, GST_CLOCK_TIME_NONE);
278   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not playing");
279   fail_unless (current == GST_STATE_PLAYING, "not playing");
280   fail_unless (pending == GST_STATE_VOID_PENDING, "not playing");
281
282 #ifdef WIM_EARNS_HIS_KEEP
283   /* now we have four messages on the bus: src from paused to playing, sink from
284      ready to paused and paused to playing, and pipeline from paused to playing.
285      the pipeline message should be last, and the sink messages should go in
286      order, but the src message can be interleaved with the sink one. */
287   {
288     GstMessage *m;
289     GstState old, new, pending;
290     gint n_src = 1, n_sink = 2;
291
292     while (n_src + n_sink > 0) {
293       m = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND);
294       fail_unless (m != NULL, "expected state change message");
295       gst_message_parse_state_changed (m, &old, &new, &pending);
296       if (GST_MESSAGE_SRC (m) == (GstObject *) src) {
297         fail_unless (n_src == 1, "already got one message from the src");
298         n_src--;
299         fail_unless (old == GST_STATE_PAUSED, "unexpected old");
300         fail_unless (new == GST_STATE_PLAYING, "unexpected new (got %d)", new);
301         fail_unless (pending == GST_STATE_VOID_PENDING, "unexpected pending");
302       } else if (GST_MESSAGE_SRC (m) == (GstObject *) sink) {
303         if (n_sink == 2) {
304           fail_unless (old == GST_STATE_READY, "unexpected old");
305           fail_unless (new == GST_STATE_PAUSED, "unexpected new");
306           fail_unless (pending == GST_STATE_PLAYING, "unexpected pending");
307         } else if (n_sink == 1) {
308           fail_unless (old == GST_STATE_PAUSED, "unexpected old");
309           fail_unless (new == GST_STATE_PLAYING, "unexpected new");
310           fail_unless (pending == GST_STATE_VOID_PENDING, "unexpected pending");
311         } else {
312           g_assert_not_reached ();
313         }
314         n_sink--;
315       } else {
316         g_critical
317             ("Unexpected state change message src %s (%d src %d sink pending)",
318             GST_OBJECT_NAME (GST_MESSAGE_SRC (m)), n_src, n_sink);
319       }
320       gst_message_unref (m);
321     }
322   }
323
324   pop_state_change_message (bus, pipeline, GST_STATE_PAUSED, GST_STATE_PLAYING,
325       GST_STATE_VOID_PENDING);
326 #endif
327
328   gst_object_unref (bus);
329   gst_element_set_state (pipeline, GST_STATE_NULL);
330   gst_object_unref (pipeline);
331 }
332
333 GST_END_TEST;
334
335 /* The sink should go ASYNC to PLAYING. The source should go
336  * to PLAYING with SUCCESS. The pipeline returns ASYNC. */
337 GST_START_TEST (test_livesrc2_sink)
338 {
339   GstElement *sink, *src, *pipeline;
340   GstStateChangeReturn ret;
341   GstState current, pending;
342   GstPad *srcpad, *sinkpad;
343
344   pipeline = gst_pipeline_new ("pipeline");
345   src = gst_element_factory_make ("fakesrc", "src");
346   g_object_set (G_OBJECT (src), "is-live", TRUE, NULL);
347   sink = gst_element_factory_make ("fakesink", "sink");
348
349   gst_bin_add (GST_BIN (pipeline), src);
350   gst_bin_add (GST_BIN (pipeline), sink);
351
352   srcpad = gst_element_get_pad (src, "src");
353   sinkpad = gst_element_get_pad (sink, "sink");
354   gst_pad_link (srcpad, sinkpad);
355   gst_object_unref (srcpad);
356   gst_object_unref (sinkpad);
357
358   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
359   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no async state return");
360
361   ret = gst_element_get_state (src, &current, &pending, GST_CLOCK_TIME_NONE);
362   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not playing");
363   fail_unless (current == GST_STATE_PLAYING, "not playing");
364   fail_unless (pending == GST_STATE_VOID_PENDING, "not playing");
365
366   ret =
367       gst_element_get_state (pipeline, &current, &pending, GST_CLOCK_TIME_NONE);
368   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not playing");
369   fail_unless (current == GST_STATE_PLAYING, "not playing");
370   fail_unless (pending == GST_STATE_VOID_PENDING, "not playing");
371
372   /* and back down */
373   ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
374   fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL,
375       "no no_preroll state return");
376
377   ret = gst_element_get_state (src, &current, &pending, GST_CLOCK_TIME_NONE);
378   fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not no_preroll");
379   fail_unless (current == GST_STATE_PAUSED, "not paused");
380   fail_unless (pending == GST_STATE_VOID_PENDING, "not paused");
381
382   /* sink state is not known.. it might be prerolled or not */
383
384   /* and to READY */
385   ret = gst_element_set_state (pipeline, GST_STATE_READY);
386   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no success state return");
387
388   ret = gst_element_get_state (src, &current, &pending, GST_CLOCK_TIME_NONE);
389   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not success");
390   fail_unless (current == GST_STATE_READY, "not ready");
391   fail_unless (pending == GST_STATE_VOID_PENDING, "not ready");
392
393   ret = gst_element_get_state (sink, &current, &pending, GST_CLOCK_TIME_NONE);
394   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not success");
395   fail_unless (current == GST_STATE_READY, "not ready");
396   fail_unless (pending == GST_STATE_VOID_PENDING, "not ready");
397 }
398
399 GST_END_TEST;
400
401 GST_START_TEST (test_livesrc3_sink)
402 {
403   GstElement *sink, *src, *pipeline;
404   GstStateChangeReturn ret;
405   GstState current, pending;
406   GstPad *srcpad, *sinkpad;
407
408   pipeline = gst_pipeline_new ("pipeline");
409   src = gst_element_factory_make ("fakesrc", "src");
410   g_object_set (G_OBJECT (src), "is-live", TRUE, NULL);
411   sink = gst_element_factory_make ("fakesink", "sink");
412
413   gst_bin_add (GST_BIN (pipeline), src);
414   gst_bin_add (GST_BIN (pipeline), sink);
415
416   srcpad = gst_element_get_pad (src, "src");
417   sinkpad = gst_element_get_pad (sink, "sink");
418   gst_pad_link (srcpad, sinkpad);
419   gst_object_unref (srcpad);
420   gst_object_unref (sinkpad);
421
422   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
423   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no async state return");
424
425   ret =
426       gst_element_get_state (pipeline, &current, &pending, GST_CLOCK_TIME_NONE);
427   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not playing");
428   fail_unless (current == GST_STATE_PLAYING, "not playing");
429   fail_unless (pending == GST_STATE_VOID_PENDING, "not playing");
430
431   /* and back down */
432   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
433   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no success state return");
434 }
435
436 GST_END_TEST;
437
438 /* test: try changing state of sinks */
439 Suite *
440 gst_object_suite (void)
441 {
442   Suite *s = suite_create ("Sinks");
443   TCase *tc_chain = tcase_create ("general");
444
445   suite_add_tcase (s, tc_chain);
446   tcase_add_test (tc_chain, test_sink);
447   tcase_add_test (tc_chain, test_sink_completion);
448   tcase_add_test (tc_chain, test_src_sink);
449   tcase_add_test (tc_chain, test_livesrc_remove);
450   tcase_add_test (tc_chain, test_livesrc_sink);
451   tcase_add_test (tc_chain, test_livesrc2_sink);
452   tcase_add_test (tc_chain, test_livesrc3_sink);
453
454   return s;
455 }
456
457 int
458 main (int argc, char **argv)
459 {
460   int nf;
461
462   Suite *s = gst_object_suite ();
463   SRunner *sr = srunner_create (s);
464
465   gst_check_init (&argc, &argv);
466
467   srunner_run_all (sr, CK_NORMAL);
468   nf = srunner_ntests_failed (sr);
469   srunner_free (sr);
470
471   return nf;
472 }