• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 
26 #include <gst/check/gstcheck.h>
27 
28 static void
pop_state_change_message(GstBus * bus,GstElement * src,GstState old,GstState new,GstState pending)29 pop_state_change_message (GstBus * bus, GstElement * src, GstState old,
30     GstState new, GstState pending)
31 {
32   GstMessage *message = NULL;
33   GstState _old, _new, _pending;
34 
35   message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND);
36   fail_unless (message != NULL,
37       "Expected state change message, but got nothing");
38 
39   gst_message_parse_state_changed (message, &_old, &_new, &_pending);
40 
41   fail_unless (GST_MESSAGE_SRC (message) == (GstObject *) src,
42       "Unexpected state change order");
43   fail_unless (old == _old, "Unexpected old state");
44   fail_unless (new == _new, "Unexpected new state");
45   fail_unless (pending == _pending, "Unexpected pending state");
46 
47   gst_message_unref (message);
48 }
49 
50 /* a sink should go ASYNC to PAUSE. forcing PLAYING is possible */
GST_START_TEST(test_sink)51 GST_START_TEST (test_sink)
52 {
53   GstElement *sink;
54   GstStateChangeReturn ret;
55   GstState current, pending;
56 
57   sink = gst_element_factory_make ("fakesink", "sink");
58 
59   ret = gst_element_set_state (sink, GST_STATE_PAUSED);
60   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no async state return");
61 
62   ret = gst_element_set_state (sink, GST_STATE_PLAYING);
63   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no forced async state change");
64 
65   ret = gst_element_get_state (sink, &current, &pending, 0);
66   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not changing state async");
67   fail_unless (current == GST_STATE_READY, "bad current state");
68   fail_unless (pending == GST_STATE_PLAYING, "bad pending state");
69 
70   ret = gst_element_set_state (sink, GST_STATE_PAUSED);
71   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no async going back to paused");
72 
73   ret = gst_element_set_state (sink, GST_STATE_READY);
74   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "failed to go to ready");
75 
76   ret = gst_element_set_state (sink, GST_STATE_NULL);
77   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "failed to go to null");
78 
79   gst_object_unref (sink);
80 }
81 
82 GST_END_TEST
83 /* a sink should go ASYNC to PAUSE and PLAYING, when linking a src, it
84  * should complete the state change. */
GST_START_TEST(test_sink_completion)85 GST_START_TEST (test_sink_completion)
86 {
87   GstElement *sink, *src;
88   GstStateChangeReturn ret;
89   GstState current, pending;
90 
91   sink = gst_element_factory_make ("fakesink", "sink");
92   g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
93 
94   ret = gst_element_set_state (sink, GST_STATE_PLAYING);
95   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no async state return");
96 
97   ret = gst_element_get_state (sink, &current, &pending, 0);
98   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not changing state async");
99   fail_unless (current == GST_STATE_READY, "bad current state");
100   fail_unless (pending == GST_STATE_PLAYING, "bad pending state");
101 
102   src = gst_element_factory_make ("fakesrc", "src");
103   g_object_set (G_OBJECT (src), "datarate", 200, "sizetype", 2, NULL);
104   gst_element_link (src, sink);
105 
106   ret = gst_element_set_state (src, GST_STATE_PLAYING);
107   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no success state return");
108 
109   /* now wait for final state */
110   ret = gst_element_get_state (sink, &current, &pending, GST_CLOCK_TIME_NONE);
111   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "failed to change state");
112   fail_unless (current == GST_STATE_PLAYING, "bad current state");
113   fail_unless (pending == GST_STATE_VOID_PENDING, "bad pending state");
114 
115   ret = gst_element_set_state (sink, GST_STATE_NULL);
116   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "failed to go to null");
117 
118   ret = gst_element_set_state (src, GST_STATE_NULL);
119   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "failed to go to null");
120 
121   gst_object_unref (sink);
122   gst_object_unref (src);
123 }
124 
125 GST_END_TEST
126 /* a sink should go ASYNC to PAUSE. PAUSE should complete when
127  * prerolled. */
GST_START_TEST(test_src_sink)128 GST_START_TEST (test_src_sink)
129 {
130   GstElement *sink, *src, *pipeline;
131   GstStateChangeReturn ret;
132   GstState current, pending;
133   GstPad *srcpad, *sinkpad;
134 
135   pipeline = gst_pipeline_new ("pipeline");
136   src = gst_element_factory_make ("fakesrc", "src");
137   sink = gst_element_factory_make ("fakesink", "sink");
138 
139   gst_bin_add (GST_BIN (pipeline), src);
140   gst_bin_add (GST_BIN (pipeline), sink);
141 
142   srcpad = gst_element_get_static_pad (src, "src");
143   sinkpad = gst_element_get_static_pad (sink, "sink");
144   gst_pad_link (srcpad, sinkpad);
145   gst_object_unref (srcpad);
146   gst_object_unref (sinkpad);
147 
148   ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
149   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no async state return");
150   ret = gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
151   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no success state return");
152 
153   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
154   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "cannot start play");
155 
156   ret =
157       gst_element_get_state (pipeline, &current, &pending, GST_CLOCK_TIME_NONE);
158   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not playing");
159   fail_unless (current == GST_STATE_PLAYING, "not playing");
160   fail_unless (pending == GST_STATE_VOID_PENDING, "not playing");
161   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
162   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "cannot null pipeline");
163 
164   gst_object_unref (pipeline);
165 
166 }
167 
168 GST_END_TEST
169 /* a pipeline with live source should return NO_PREROLL in
170  * PAUSE. When removing the live source it should return ASYNC
171  * from the sink */
GST_START_TEST(test_livesrc_remove)172 GST_START_TEST (test_livesrc_remove)
173 {
174   GstElement *sink, *src, *pipeline;
175   GstStateChangeReturn ret;
176   GstState current, pending;
177   GstPad *srcpad, *sinkpad;
178 
179   pipeline = gst_pipeline_new ("pipeline");
180   src = gst_element_factory_make ("fakesrc", "src");
181   g_object_set (G_OBJECT (src), "is-live", TRUE, NULL);
182   sink = gst_element_factory_make ("fakesink", "sink");
183 
184   gst_object_ref (src);
185   gst_bin_add (GST_BIN (pipeline), src);
186   gst_bin_add (GST_BIN (pipeline), sink);
187 
188   srcpad = gst_element_get_static_pad (src, "src");
189   sinkpad = gst_element_get_static_pad (sink, "sink");
190   gst_pad_link (srcpad, sinkpad);
191   gst_object_unref (srcpad);
192   gst_object_unref (sinkpad);
193 
194   ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
195   fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL,
196       "no no_preroll state return");
197 
198   ret = gst_element_get_state (src, &current, &pending, GST_CLOCK_TIME_NONE);
199   fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not paused");
200   fail_unless (current == GST_STATE_PAUSED, "not paused");
201   fail_unless (pending == GST_STATE_VOID_PENDING, "not playing");
202 
203   gst_bin_remove (GST_BIN (pipeline), src);
204 
205   ret = gst_element_set_state (src, GST_STATE_NULL);
206   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "async going to null");
207   gst_object_unref (src);
208 
209   ret = gst_element_get_state (pipeline, &current, &pending, 0);
210   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not async");
211   fail_unless (current == GST_STATE_PAUSED, "not paused");
212   fail_unless (pending == GST_STATE_PAUSED, "not paused");
213 
214   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
215   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "async going to null");
216   gst_object_unref (pipeline);
217 }
218 
219 GST_END_TEST
220 /* the sink should go ASYNC to PAUSE. The live source should go
221  * NO_PREROLL to PAUSE. the pipeline returns NO_PREROLL. An
222  * attempt to go to PLAYING will return ASYNC. polling state
223  * completion should return SUCCESS when the sink is gone to
224  * PLAYING. */
GST_START_TEST(test_livesrc_sink)225 GST_START_TEST (test_livesrc_sink)
226 {
227   GstElement *sink, *src, *pipeline;
228   GstStateChangeReturn ret;
229   GstState current, pending;
230   GstPad *srcpad, *sinkpad;
231   GstBus *bus;
232 
233   pipeline = gst_pipeline_new ("pipeline");
234   src = gst_element_factory_make ("fakesrc", "src");
235   g_object_set (G_OBJECT (src), "is-live", TRUE, NULL);
236   sink = gst_element_factory_make ("fakesink", "sink");
237 
238   gst_bin_add (GST_BIN (pipeline), src);
239   gst_bin_add (GST_BIN (pipeline), sink);
240 
241   srcpad = gst_element_get_static_pad (src, "src");
242   sinkpad = gst_element_get_static_pad (sink, "sink");
243   gst_pad_link (srcpad, sinkpad);
244   gst_object_unref (srcpad);
245   gst_object_unref (sinkpad);
246 
247   bus = gst_element_get_bus (pipeline);
248 
249   ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
250   fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL,
251       "no no_preroll state return");
252 
253   pop_state_change_message (bus, sink, GST_STATE_NULL, GST_STATE_READY,
254       GST_STATE_VOID_PENDING);
255   pop_state_change_message (bus, src, GST_STATE_NULL, GST_STATE_READY,
256       GST_STATE_VOID_PENDING);
257   pop_state_change_message (bus, pipeline, GST_STATE_NULL, GST_STATE_READY,
258       GST_STATE_PAUSED);
259 
260   /* this order only holds true for live sources because they do not push
261      buffers in PAUSED */
262   pop_state_change_message (bus, src, GST_STATE_READY, GST_STATE_PAUSED,
263       GST_STATE_VOID_PENDING);
264   pop_state_change_message (bus, pipeline, GST_STATE_READY, GST_STATE_PAUSED,
265       GST_STATE_VOID_PENDING);
266 
267   ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
268   fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL,
269       "no no_preroll state return the second time");
270 
271   ret = gst_element_get_state (src, &current, &pending, GST_CLOCK_TIME_NONE);
272   fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not paused");
273   fail_unless (current == GST_STATE_PAUSED, "not paused");
274   fail_unless (pending == GST_STATE_VOID_PENDING, "not playing");
275 
276   /* don't block here */
277   ret = gst_element_get_state (sink, &current, &pending, 0);
278   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not async");
279   fail_unless (current == GST_STATE_READY, "not ready");
280   fail_unless (pending == GST_STATE_PAUSED, "not paused");
281 
282   ret =
283       gst_element_get_state (pipeline, &current, &pending, GST_CLOCK_TIME_NONE);
284   fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not paused");
285   fail_unless (current == GST_STATE_PAUSED, "not paused");
286   fail_unless (pending == GST_STATE_VOID_PENDING, "not playing");
287 
288   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
289   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not async");
290   ret =
291       gst_element_get_state (pipeline, &current, &pending, GST_CLOCK_TIME_NONE);
292   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not playing");
293   fail_unless (current == GST_STATE_PLAYING, "not playing");
294   fail_unless (pending == GST_STATE_VOID_PENDING, "not playing");
295 
296   /* now we have four messages on the bus: src from paused to playing, sink from
297      ready to paused and paused to playing, and pipeline from paused to playing.
298      the pipeline message should be last, and the sink messages should go in
299      order, but the src message can be interleaved with the sink one. */
300   {
301     GstMessage *m;
302     GstState old, new, pending;
303     gint n_src = 1, n_sink = 2;
304 
305     while (n_src + n_sink > 0) {
306       m = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND);
307       fail_unless (m != NULL, "expected state change message");
308       gst_message_parse_state_changed (m, &old, &new, &pending);
309       if (GST_MESSAGE_SRC (m) == (GstObject *) src) {
310         fail_unless (n_src == 1, "already got one message from the src");
311         n_src--;
312         fail_unless (old == GST_STATE_PAUSED, "unexpected old");
313         fail_unless (new == GST_STATE_PLAYING, "unexpected new (got %d)", new);
314         fail_unless (pending == GST_STATE_VOID_PENDING, "unexpected pending");
315       } else if (GST_MESSAGE_SRC (m) == (GstObject *) sink) {
316         if (n_sink == 2) {
317           fail_unless (old == GST_STATE_READY, "unexpected old");
318           fail_unless (new == GST_STATE_PAUSED, "unexpected new");
319           fail_unless (pending == GST_STATE_VOID_PENDING, "unexpected pending");
320         } else if (n_sink == 1) {
321           fail_unless (old == GST_STATE_PAUSED, "unexpected old");
322           fail_unless (new == GST_STATE_PLAYING, "unexpected new");
323           fail_unless (pending == GST_STATE_VOID_PENDING, "unexpected pending");
324         } else {
325           g_assert_not_reached ();
326         }
327         n_sink--;
328       } else {
329         g_critical
330             ("Unexpected state change message src %s (%d src %d sink pending)",
331             GST_OBJECT_NAME (GST_MESSAGE_SRC (m)), n_src, n_sink);
332       }
333       gst_message_unref (m);
334     }
335   }
336 
337   pop_state_change_message (bus, pipeline, GST_STATE_PAUSED, GST_STATE_PLAYING,
338       GST_STATE_VOID_PENDING);
339 
340   gst_object_unref (bus);
341   gst_element_set_state (pipeline, GST_STATE_NULL);
342   gst_object_unref (pipeline);
343 }
344 
345 GST_END_TEST;
346 
347 /* The sink should go ASYNC to PLAYING. The source should go
348  * to PLAYING with SUCCESS. The pipeline returns ASYNC. */
GST_START_TEST(test_livesrc2_sink)349 GST_START_TEST (test_livesrc2_sink)
350 {
351   GstElement *sink, *src, *pipeline;
352   GstStateChangeReturn ret;
353   GstState current, pending;
354   GstPad *srcpad, *sinkpad;
355 
356   pipeline = gst_pipeline_new ("pipeline");
357   src = gst_element_factory_make ("fakesrc", "src");
358   g_object_set (G_OBJECT (src), "is-live", TRUE, NULL);
359   sink = gst_element_factory_make ("fakesink", "sink");
360 
361   gst_bin_add (GST_BIN (pipeline), src);
362   gst_bin_add (GST_BIN (pipeline), sink);
363 
364   srcpad = gst_element_get_static_pad (src, "src");
365   sinkpad = gst_element_get_static_pad (sink, "sink");
366   gst_pad_link (srcpad, sinkpad);
367   gst_object_unref (srcpad);
368   gst_object_unref (sinkpad);
369 
370   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
371   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no async state return");
372 
373   ret = gst_element_get_state (src, &current, &pending, GST_CLOCK_TIME_NONE);
374   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not playing");
375   fail_unless (current == GST_STATE_PLAYING, "not playing");
376   fail_unless (pending == GST_STATE_VOID_PENDING, "not playing");
377 
378   ret =
379       gst_element_get_state (pipeline, &current, &pending, GST_CLOCK_TIME_NONE);
380   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not playing");
381   fail_unless (current == GST_STATE_PLAYING, "not playing");
382   fail_unless (pending == GST_STATE_VOID_PENDING, "not playing");
383 
384   /* and back down */
385   ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
386   fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL,
387       "no no_preroll state return");
388 
389   ret = gst_element_get_state (src, &current, &pending, GST_CLOCK_TIME_NONE);
390   fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not no_preroll");
391   fail_unless (current == GST_STATE_PAUSED, "not paused");
392   fail_unless (pending == GST_STATE_VOID_PENDING, "not paused");
393 
394   /* sink state is not known.. it might be prerolled or not */
395 
396   /* and to READY */
397   ret = gst_element_set_state (pipeline, GST_STATE_READY);
398   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no success state return");
399 
400   ret = gst_element_get_state (src, &current, &pending, GST_CLOCK_TIME_NONE);
401   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not success");
402   fail_unless (current == GST_STATE_READY, "not ready");
403   fail_unless (pending == GST_STATE_VOID_PENDING, "not ready");
404 
405   ret = gst_element_get_state (sink, &current, &pending, GST_CLOCK_TIME_NONE);
406   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not success");
407   fail_unless (current == GST_STATE_READY, "not ready");
408   fail_unless (pending == GST_STATE_VOID_PENDING, "not ready");
409 
410   /* And destroy. Must be NULL */
411   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
412   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no success state return");
413   gst_object_unref (pipeline);
414 }
415 
416 GST_END_TEST;
417 
GST_START_TEST(test_livesrc3_sink)418 GST_START_TEST (test_livesrc3_sink)
419 {
420   GstElement *sink, *src, *pipeline;
421   GstStateChangeReturn ret;
422   GstState current, pending;
423   GstPad *srcpad, *sinkpad;
424 
425   pipeline = gst_pipeline_new ("pipeline");
426   src = gst_element_factory_make ("fakesrc", "src");
427   g_object_set (G_OBJECT (src), "is-live", TRUE, NULL);
428   sink = gst_element_factory_make ("fakesink", "sink");
429 
430   gst_bin_add (GST_BIN (pipeline), src);
431   gst_bin_add (GST_BIN (pipeline), sink);
432 
433   srcpad = gst_element_get_static_pad (src, "src");
434   sinkpad = gst_element_get_static_pad (sink, "sink");
435   gst_pad_link (srcpad, sinkpad);
436   gst_object_unref (srcpad);
437   gst_object_unref (sinkpad);
438 
439   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
440   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no async state return");
441 
442   ret =
443       gst_element_get_state (pipeline, &current, &pending, GST_CLOCK_TIME_NONE);
444   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not playing");
445   fail_unless (current == GST_STATE_PLAYING, "not playing");
446   fail_unless (pending == GST_STATE_VOID_PENDING, "not playing");
447 
448   /* and back down */
449   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
450   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no success state return");
451   gst_object_unref (pipeline);
452 }
453 
454 GST_END_TEST;
455 
GST_START_TEST(test_locked_sink)456 GST_START_TEST (test_locked_sink)
457 {
458   GstElement *sink, *src, *pipeline;
459   GstStateChangeReturn ret;
460   GstState current, pending;
461 
462   pipeline = gst_pipeline_new ("pipeline");
463   src = gst_element_factory_make ("fakesrc", "src");
464   g_object_set (G_OBJECT (src), "is-live", TRUE, NULL);
465   sink = gst_element_factory_make ("fakesink", "sink");
466 
467   gst_bin_add (GST_BIN (pipeline), src);
468   gst_bin_add (GST_BIN (pipeline), sink);
469 
470   /* we don't link the elements */
471 
472   ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
473   fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL,
474       "no NO_PREROLL state return");
475 
476   ret =
477       gst_element_get_state (pipeline, &current, &pending, GST_CLOCK_TIME_NONE);
478   fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not no_preroll");
479   fail_unless (current == GST_STATE_PAUSED, "not paused");
480   fail_unless (pending == GST_STATE_VOID_PENDING, "have pending");
481 
482   /* the sink is now async going from ready to paused */
483   ret = gst_element_get_state (sink, &current, &pending, 0);
484   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not async");
485   fail_unless (current == GST_STATE_READY, "not ready");
486   fail_unless (pending == GST_STATE_PAUSED, "not paused");
487 
488   /* lock the sink */
489   gst_element_set_locked_state (sink, TRUE);
490 
491   /* move to PlAYING, the sink should remain ASYNC. The pipeline
492    * returns ASYNC */
493   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
494   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return");
495 
496   /* back to PAUSED, we should get NO_PREROLL again */
497   ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
498   fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL,
499       "no NO_PREROLL state return");
500 
501   /* unlock the sink */
502   gst_element_set_locked_state (sink, FALSE);
503 
504   /* and now everything back down */
505   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
506   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no success state return");
507   gst_object_unref (pipeline);
508 }
509 
510 GST_END_TEST;
511 
GST_START_TEST(test_unlinked_live)512 GST_START_TEST (test_unlinked_live)
513 {
514   GstElement *sink, *src, *lsrc, *pipeline;
515   GstStateChangeReturn ret;
516   GstState current, pending;
517   GstPad *srcpad, *sinkpad;
518 
519   pipeline = gst_pipeline_new ("pipeline");
520   src = gst_element_factory_make ("fakesrc", "src");
521   lsrc = gst_element_factory_make ("fakesrc", "lsrc");
522   g_object_set (G_OBJECT (lsrc), "is-live", TRUE, NULL);
523   sink = gst_element_factory_make ("fakesink", "sink");
524 
525   gst_bin_add (GST_BIN (pipeline), src);
526   gst_bin_add (GST_BIN (pipeline), lsrc);
527   gst_bin_add (GST_BIN (pipeline), sink);
528 
529   /* link non live source to sink */
530   srcpad = gst_element_get_static_pad (src, "src");
531   sinkpad = gst_element_get_static_pad (sink, "sink");
532   gst_pad_link (srcpad, sinkpad);
533   gst_object_unref (srcpad);
534   gst_object_unref (sinkpad);
535 
536   /* we don't link the srcpad of the live source, it will not contribute to the
537    * NO_PREROLL. */
538 
539   /* set state to PAUSED, this should return NO_PREROLL because there is a live
540    * source. since the only sink in this pipeline is linked to a non-live
541    * source, it will preroll eventually. */
542   ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
543   fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL,
544       "no NO_PREROLL state return");
545 
546   /* wait till the sink is prerolled */
547   ret = gst_element_get_state (sink, &current, &pending, GST_CLOCK_TIME_NONE);
548   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not success");
549   fail_unless (current == GST_STATE_PAUSED, "not paused");
550   fail_unless (pending == GST_STATE_VOID_PENDING, "have playing");
551 
552   /* the pipeline should still return NO_PREROLL */
553   ret =
554       gst_element_get_state (pipeline, &current, &pending, GST_CLOCK_TIME_NONE);
555   fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not no_preroll");
556   fail_unless (current == GST_STATE_PAUSED, "not paused");
557   fail_unless (pending == GST_STATE_VOID_PENDING, "have playing");
558 
559   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
560   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not SUCCESS");
561 
562   gst_object_unref (pipeline);
563 }
564 
565 GST_END_TEST;
566 
GST_START_TEST(test_delayed_async)567 GST_START_TEST (test_delayed_async)
568 {
569   GstElement *sink, *src, *pipeline;
570   GstStateChangeReturn ret;
571   GstState current, pending;
572   GstPad *srcpad, *sinkpad;
573 
574   pipeline = gst_pipeline_new ("pipeline");
575   src = gst_element_factory_make ("fakesrc", "src");
576   g_object_set (G_OBJECT (src), "is-live", TRUE, NULL);
577   sink = gst_element_factory_make ("fakesink", "sink");
578 
579   /* add source, don't add sink yet */
580   gst_bin_add (GST_BIN (pipeline), src);
581 
582   ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
583   fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL,
584       "no NO_PREROLL state return");
585 
586   /* add sink now and set to PAUSED */
587   gst_bin_add (GST_BIN (pipeline), sink);
588 
589   /* This will make the bin notice an ASYNC element. */
590   ret = gst_element_set_state (sink, GST_STATE_PAUSED);
591   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return");
592 
593   /* we should still be NO_PREROLL now although there is an async element in the
594    * pipeline. */
595   ret =
596       gst_element_get_state (pipeline, &current, &pending, GST_CLOCK_TIME_NONE);
597   fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not NO_PREROLL");
598   fail_unless (current == GST_STATE_PAUSED, "not paused");
599   fail_unless (pending == GST_STATE_VOID_PENDING, "have pending");
600 
601   /* link live source to sink */
602   srcpad = gst_element_get_static_pad (src, "src");
603   sinkpad = gst_element_get_static_pad (sink, "sink");
604   gst_pad_link (srcpad, sinkpad);
605   gst_object_unref (srcpad);
606   gst_object_unref (sinkpad);
607 
608   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
609   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return");
610 
611   /* we should get SUCCESS now */
612   ret =
613       gst_element_get_state (pipeline, &current, &pending, GST_CLOCK_TIME_NONE);
614   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not NO_PREROLL");
615   fail_unless (current == GST_STATE_PLAYING, "not PLAYING");
616   fail_unless (pending == GST_STATE_VOID_PENDING, "have pending");
617 
618   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
619   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not SUCCESS");
620 
621   gst_object_unref (pipeline);
622 }
623 
624 GST_END_TEST;
625 
GST_START_TEST(test_added_async)626 GST_START_TEST (test_added_async)
627 {
628   GstElement *sink, *src, *pipeline;
629   GstStateChangeReturn ret;
630   GstState current, pending;
631   GstPad *srcpad, *sinkpad;
632 
633   pipeline = gst_pipeline_new ("pipeline");
634   src = gst_element_factory_make ("fakesrc", "src");
635   g_object_set (G_OBJECT (src), "is-live", TRUE, NULL);
636   sink = gst_element_factory_make ("fakesink", "sink");
637 
638   /* add source, don't add sink yet */
639   gst_bin_add (GST_BIN (pipeline), src);
640 
641   ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
642   fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL,
643       "no NO_PREROLL state return");
644 
645   /* set sink to PAUSED without adding it to the pipeline */
646   ret = gst_element_set_state (sink, GST_STATE_PAUSED);
647   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return");
648 
649   /* add sink now, pipeline should notice the async element */
650   gst_bin_add (GST_BIN (pipeline), sink);
651 
652   /* we should still be NO_PREROLL now although there is an async element in the
653    * pipeline. */
654   ret =
655       gst_element_get_state (pipeline, &current, &pending, GST_CLOCK_TIME_NONE);
656   fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not NO_PREROLL");
657   fail_unless (current == GST_STATE_PAUSED, "not paused");
658   fail_unless (pending == GST_STATE_VOID_PENDING, "have pending");
659 
660   /* link live source to sink */
661   srcpad = gst_element_get_static_pad (src, "src");
662   sinkpad = gst_element_get_static_pad (sink, "sink");
663   gst_pad_link (srcpad, sinkpad);
664   gst_object_unref (srcpad);
665   gst_object_unref (sinkpad);
666 
667   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
668   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return");
669 
670   /* we should get SUCCESS now */
671   ret =
672       gst_element_get_state (pipeline, &current, &pending, GST_CLOCK_TIME_NONE);
673   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not NO_PREROLL");
674   fail_unless (current == GST_STATE_PLAYING, "not PLAYING");
675   fail_unless (pending == GST_STATE_VOID_PENDING, "have pending");
676 
677   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
678   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not SUCCESS");
679 
680   gst_object_unref (pipeline);
681 }
682 
683 GST_END_TEST;
684 
GST_START_TEST(test_added_async2)685 GST_START_TEST (test_added_async2)
686 {
687   GstElement *sink, *src, *pipeline;
688   GstStateChangeReturn ret;
689   GstState current, pending;
690 
691   pipeline = gst_pipeline_new ("pipeline");
692   src = gst_element_factory_make ("fakesrc", "src");
693   sink = gst_element_factory_make ("fakesink", "sink");
694 
695   /* add source, don't add sink yet */
696   gst_bin_add (GST_BIN (pipeline), src);
697   /* need to lock state here or the pipeline might go in error */
698   gst_element_set_locked_state (src, TRUE);
699 
700   ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
701   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no SUCCESS state return");
702 
703   /* set sink to PAUSED without adding it to the pipeline */
704   ret = gst_element_set_state (sink, GST_STATE_PAUSED);
705   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return");
706 
707   /* add sink now, pipeline should notice the async element */
708   gst_bin_add (GST_BIN (pipeline), sink);
709 
710   /* we should be ASYNC now because there is an async element in the
711    * pipeline. */
712   ret = gst_element_get_state (pipeline, &current, &pending, 0);
713   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not ASYNC");
714   fail_unless (current == GST_STATE_PAUSED, "not paused");
715   fail_unless (pending == GST_STATE_PAUSED, "not paused");
716 
717   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
718   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not SUCCESS");
719 
720   gst_object_unref (pipeline);
721 }
722 
723 GST_END_TEST;
724 
GST_START_TEST(test_add_live)725 GST_START_TEST (test_add_live)
726 {
727   GstElement *sink, *src, *pipeline;
728   GstStateChangeReturn ret;
729   GstState current, pending;
730 
731   pipeline = gst_pipeline_new ("pipeline");
732   src = gst_element_factory_make ("fakesrc", "src");
733   g_object_set (G_OBJECT (src), "is-live", TRUE, NULL);
734   sink = gst_element_factory_make ("fakesink", "sink");
735 
736   /* add sink, don't add sourc3 yet */
737   gst_bin_add (GST_BIN (pipeline), sink);
738 
739   ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
740   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return");
741 
742   /* set source to PAUSED without adding it to the pipeline */
743   ret = gst_element_set_state (src, GST_STATE_PAUSED);
744   fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL,
745       "no NO_PREROLL state return");
746 
747   /* add source now, pipeline should notice the NO_PREROLL element */
748   gst_bin_add (GST_BIN (pipeline), src);
749 
750   /* we should be NO_PREROLL now because there is a NO_PREROLL element in the
751    * pipeline. */
752   ret =
753       gst_element_get_state (pipeline, &current, &pending, GST_CLOCK_TIME_NONE);
754   fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not NO_PREROLL");
755   fail_unless (current == GST_STATE_PAUSED, "not paused");
756   fail_unless (pending == GST_STATE_VOID_PENDING, "have pending");
757 
758   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
759   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not SUCCESS");
760 
761   gst_object_unref (pipeline);
762 }
763 
764 GST_END_TEST;
765 
766 static GMutex blocked_lock;
767 static GCond blocked_cond;
768 
769 static GstPadProbeReturn
pad_blocked_cb(GstPad * pad,GstPadProbeInfo * info,gpointer user_data)770 pad_blocked_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
771 {
772   g_mutex_lock (&blocked_lock);
773   GST_DEBUG ("srcpad blocked: %d, sending signal", info->type);
774   g_cond_signal (&blocked_cond);
775   g_mutex_unlock (&blocked_lock);
776 
777   return GST_PAD_PROBE_OK;
778 }
779 
GST_START_TEST(test_add_live2)780 GST_START_TEST (test_add_live2)
781 {
782   GstElement *sink, *src, *pipeline;
783   GstStateChangeReturn ret;
784   GstState current, pending;
785   GstPad *srcpad, *sinkpad;
786   gulong id;
787 
788   pipeline = gst_pipeline_new ("pipeline");
789   src = gst_element_factory_make ("fakesrc", "src");
790   g_object_set (G_OBJECT (src), "is-live", TRUE, NULL);
791   sink = gst_element_factory_make ("fakesink", "sink");
792 
793   /* add sink, don't add source yet */
794   gst_bin_add (GST_BIN (pipeline), sink);
795 
796   /* set the pipeline to PLAYING. This will return ASYNC on READY->PAUSED */
797   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
798   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return");
799 
800   g_mutex_lock (&blocked_lock);
801 
802   GST_DEBUG ("blocking srcpad");
803   /* block source pad */
804   srcpad = gst_element_get_static_pad (src, "src");
805   id = gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
806       pad_blocked_cb, NULL, NULL);
807 
808   /* set source to PAUSED without adding it to the pipeline */
809   ret = gst_element_set_state (src, GST_STATE_PAUSED);
810   fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL,
811       "no NO_PREROLL state return");
812 
813   /* add source now, pipeline should notice the NO_PREROLL element. This
814    * should trigger as commit of the ASYNC pipeline and make it continue
815    * to PLAYING. We blocked the source pad so that we don't get an unlinked
816    * error. */
817   gst_bin_add (GST_BIN (pipeline), src);
818 
819   /* wait for pad blocked, this means the source is now PLAYING. */
820   g_cond_wait (&blocked_cond, &blocked_lock);
821   g_mutex_unlock (&blocked_lock);
822 
823   GST_DEBUG ("linking pads");
824 
825   /* link to sink */
826   sinkpad = gst_element_get_static_pad (sink, "sink");
827   gst_pad_link (srcpad, sinkpad);
828   gst_object_unref (srcpad);
829   gst_object_unref (sinkpad);
830 
831   GST_DEBUG ("unblocking srcpad");
832 
833   /* and unblock */
834   gst_pad_remove_probe (srcpad, id);
835 
836   GST_DEBUG ("getting state");
837 
838   /* we should be SUCCESS now and PLAYING */
839   ret =
840       gst_element_get_state (pipeline, &current, &pending, GST_CLOCK_TIME_NONE);
841   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not SUCCESS");
842   fail_unless (current == GST_STATE_PLAYING, "not PLAYING");
843   fail_unless (pending == GST_STATE_VOID_PENDING, "have pending");
844 
845   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
846   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not SUCCESS");
847 
848   gst_object_unref (pipeline);
849 }
850 
851 GST_END_TEST;
852 
GST_START_TEST(test_bin_live)853 GST_START_TEST (test_bin_live)
854 {
855   GstElement *sink, *src, *pipeline, *bin;
856   GstStateChangeReturn ret;
857   GstState current, pending;
858   GstPad *srcpad, *sinkpad;
859 
860   pipeline = gst_pipeline_new ("pipeline");
861   bin = gst_bin_new ("bin");
862   src = gst_element_factory_make ("fakesrc", "src");
863   g_object_set (G_OBJECT (src), "is-live", TRUE, NULL);
864   sink = gst_element_factory_make ("fakesink", "sink");
865 
866   gst_bin_add (GST_BIN (bin), src);
867   gst_bin_add (GST_BIN (bin), sink);
868   gst_bin_add (GST_BIN (pipeline), bin);
869 
870   srcpad = gst_element_get_static_pad (src, "src");
871   sinkpad = gst_element_get_static_pad (sink, "sink");
872   gst_pad_link (srcpad, sinkpad);
873   gst_object_unref (srcpad);
874   gst_object_unref (sinkpad);
875 
876   /* PAUSED returns NO_PREROLL because of the live source */
877   ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
878   fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL,
879       "no NO_PREROLL state return");
880   ret =
881       gst_element_get_state (pipeline, &current, &pending, GST_CLOCK_TIME_NONE);
882   fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not NO_PREROLL");
883   fail_unless (current == GST_STATE_PAUSED, "not paused");
884   fail_unless (pending == GST_STATE_VOID_PENDING, "not void pending");
885 
886   /* when going to PLAYING, the sink should go to PLAYING ASYNC */
887   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
888   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not ASYNC");
889 
890   /* now wait for PLAYING to complete */
891   ret =
892       gst_element_get_state (pipeline, &current, &pending, GST_CLOCK_TIME_NONE);
893   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not playing");
894   fail_unless (current == GST_STATE_PLAYING, "not playing");
895   fail_unless (pending == GST_STATE_VOID_PENDING, "not void pending");
896 
897   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
898   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "cannot null pipeline");
899 
900   gst_object_unref (pipeline);
901 }
902 
903 GST_END_TEST static gpointer
send_eos(GstPad * sinkpad)904 send_eos (GstPad * sinkpad)
905 {
906   gboolean ret;
907 
908   ret = gst_pad_send_event (sinkpad, gst_event_new_eos ());
909 
910   return GINT_TO_POINTER (ret);
911 }
912 
913 /* push a buffer with a very long duration in a fakesink, then push an EOS
914  * event. fakesink should emit EOS after the duration of the buffer expired.
915  * Going to PAUSED, however should not return ASYNC while processing the
916  * buffer. */
GST_START_TEST(test_fake_eos)917 GST_START_TEST (test_fake_eos)
918 {
919   GstElement *sink, *pipeline;
920   GstBuffer *buffer;
921   GstStateChangeReturn ret;
922   GstPad *sinkpad;
923   GstFlowReturn res;
924   GThread *thread;
925   GstSegment segment;
926 
927   pipeline = gst_pipeline_new ("pipeline");
928 
929   sink = gst_element_factory_make ("fakesink", "sink");
930   g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
931 
932   sinkpad = gst_element_get_static_pad (sink, "sink");
933 
934   gst_bin_add (GST_BIN_CAST (pipeline), sink);
935 
936   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
937   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return");
938 
939   gst_segment_init (&segment, GST_FORMAT_BYTES);
940   gst_pad_send_event (sinkpad, gst_event_new_stream_start ("test"));
941   gst_pad_send_event (sinkpad, gst_event_new_segment (&segment));
942 
943   /* push buffer of 100 seconds, since it has a timestamp of 0, it should be
944    * rendered immediately and the chain function should return immediately */
945   buffer = gst_buffer_new_and_alloc (10);
946   GST_BUFFER_TIMESTAMP (buffer) = 0;
947   GST_BUFFER_DURATION (buffer) = 100 * GST_SECOND;
948   res = gst_pad_chain (sinkpad, buffer);
949   fail_unless (res == GST_FLOW_OK, "no OK flow return");
950 
951   /* wait for preroll, this should happen really soon. */
952   ret = gst_element_get_state (pipeline, NULL, NULL, -1);
953   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no SUCCESS state return");
954 
955   /* push EOS, this will block for up to 100 seconds, until the previous
956    * buffer has finished. We therefore push it in another thread so we can do
957    * something else while it blocks. */
958   thread =
959       g_thread_try_new ("gst-check", (GThreadFunc) send_eos, sinkpad, NULL);
960   fail_if (thread == NULL, "no thread");
961 
962   /* wait a while so that the thread manages to start and push the EOS */
963   g_usleep (G_USEC_PER_SEC);
964 
965   /* this should cancel rendering of the EOS event and should return SUCCESS
966    * because the sink is now prerolled on the EOS. */
967   ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
968   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no SUCCESS state return");
969 
970   /* we can unref the sinkpad now, we're done with it */
971   gst_object_unref (sinkpad);
972 
973   /* wait for a second, use the debug log to see that basesink does not discard
974    * the EOS */
975   g_usleep (G_USEC_PER_SEC);
976 
977   /* go back to PLAYING, which means waiting some more in EOS, check debug log
978    * to see this happen. */
979   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
980   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no SUCCESS state return");
981   g_usleep (G_USEC_PER_SEC);
982 
983   /* teardown and cleanup */
984   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
985   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no SUCCESS state return");
986 
987   /* we can join now */
988   g_thread_join (thread);
989 
990   gst_object_unref (pipeline);
991 }
992 
993 GST_END_TEST;
994 
995 /* this variable is updated in the same thread, first it is set by the
996  * handoff-preroll signal, then it is checked when the ASYNC_DONE is posted on
997  * the bus */
998 static gboolean have_preroll = FALSE;
999 
1000 static void
async_done_handoff(GstElement * element,GstBuffer * buf,GstPad * pad,GstElement * sink)1001 async_done_handoff (GstElement * element, GstBuffer * buf, GstPad * pad,
1002     GstElement * sink)
1003 {
1004   GST_DEBUG ("we have the preroll buffer");
1005   have_preroll = TRUE;
1006 }
1007 
1008 /* when we get the ASYNC_DONE, query the position */
1009 static GstBusSyncReply
async_done_func(GstBus * bus,GstMessage * msg,GstElement * sink)1010 async_done_func (GstBus * bus, GstMessage * msg, GstElement * sink)
1011 {
1012   if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ASYNC_DONE) {
1013     gint64 position;
1014 
1015     GST_DEBUG ("we have ASYNC_DONE now");
1016     fail_unless (have_preroll == TRUE, "no preroll buffer received");
1017 
1018     /* get the position now */
1019     gst_element_query_position (sink, GST_FORMAT_TIME, &position);
1020 
1021     GST_DEBUG ("we have position %" GST_TIME_FORMAT, GST_TIME_ARGS (position));
1022 
1023     fail_unless (position == 10 * GST_SECOND, "position is wrong");
1024   }
1025 
1026   /* we must unref the message if we return DROP */
1027   gst_message_unref (msg);
1028 
1029   /* we can drop the message, nothing is listening for it. */
1030   return GST_BUS_DROP;
1031 }
1032 
1033 static void
send_buffer(GstPad * sinkpad)1034 send_buffer (GstPad * sinkpad)
1035 {
1036   GstBuffer *buffer;
1037   GstFlowReturn ret;
1038 
1039   /* push a second buffer */
1040   GST_DEBUG ("pushing last buffer");
1041   buffer = gst_buffer_new_and_alloc (10);
1042   GST_BUFFER_TIMESTAMP (buffer) = 200 * GST_SECOND;
1043   GST_BUFFER_DURATION (buffer) = 100 * GST_SECOND;
1044 
1045   /* this function will initially block */
1046   ret = gst_pad_chain (sinkpad, buffer);
1047   fail_unless (ret == GST_FLOW_OK, "no OK flow return");
1048 }
1049 
1050 /* when we get the ASYNC_DONE message from a sink, we want the sink to be able
1051  * to report the duration and position. The sink should also have called the
1052  * render method. */
GST_START_TEST(test_async_done)1053 GST_START_TEST (test_async_done)
1054 {
1055   GstElement *sink;
1056   GstEvent *event;
1057   GstStateChangeReturn ret;
1058   GstPad *sinkpad;
1059   gboolean res;
1060   GstBus *bus;
1061   GThread *thread;
1062   gint64 position;
1063   gboolean qret;
1064   GstSegment segment;
1065 
1066   sink = gst_element_factory_make ("fakesink", "sink");
1067   g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
1068   g_object_set (G_OBJECT (sink), "signal-handoffs", TRUE, NULL);
1069 
1070   g_signal_connect (sink, "preroll-handoff", (GCallback) async_done_handoff,
1071       sink);
1072 
1073   sinkpad = gst_element_get_static_pad (sink, "sink");
1074 
1075   ret = gst_element_set_state (sink, GST_STATE_PAUSED);
1076   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return");
1077 
1078   /* set bus on element synchronously listen for ASYNC_DONE */
1079   bus = gst_bus_new ();
1080   gst_element_set_bus (sink, bus);
1081   gst_bus_set_sync_handler (bus, (GstBusSyncHandler) async_done_func, sink,
1082       NULL);
1083 
1084   gst_pad_send_event (sinkpad, gst_event_new_stream_start ("test"));
1085 
1086   /* make newsegment, this sets the position to 10sec when the buffer prerolls */
1087   GST_DEBUG ("sending segment");
1088   gst_segment_init (&segment, GST_FORMAT_TIME);
1089   segment.time = 10 * GST_SECOND;
1090 
1091   event = gst_event_new_segment (&segment);
1092   res = gst_pad_send_event (sinkpad, event);
1093   fail_unless (res == TRUE);
1094 
1095   /* We have not yet received any buffers so we are still in the READY state,
1096    * the position is therefore still not queryable. */
1097   position = -1;
1098   qret = gst_element_query_position (sink, GST_FORMAT_TIME, &position);
1099   fail_unless (qret == TRUE, "position wrong");
1100   fail_unless (position == 10 * GST_SECOND, "position is wrong");
1101 
1102   /* last buffer, blocks because preroll queue is filled. Start the push in a
1103    * new thread so that we can check the position */
1104   GST_DEBUG ("starting thread");
1105   thread =
1106       g_thread_try_new ("gst-check", (GThreadFunc) send_buffer, sinkpad, NULL);
1107   fail_if (thread == NULL, "no thread");
1108 
1109   GST_DEBUG ("waiting 1 second");
1110   g_usleep (G_USEC_PER_SEC);
1111   GST_DEBUG ("waiting done");
1112 
1113   /* check if position is still 10 seconds. This is racy because  the above
1114    * thread might not yet have started the push, because of the above sleep,
1115    * this is very unlikely, though. */
1116   gst_element_query_position (sink, GST_FORMAT_TIME, &position);
1117   GST_DEBUG ("second buffer position %" GST_TIME_FORMAT,
1118       GST_TIME_ARGS (position));
1119   fail_unless (position == 10 * GST_SECOND, "position is wrong");
1120 
1121   /* now we go to playing. This should unlock and stop the above thread. */
1122   GST_DEBUG ("going to PLAYING");
1123   ret = gst_element_set_state (sink, GST_STATE_PLAYING);
1124 
1125   /* join the thread. At this point we know the sink processed the last buffer
1126    * and the position should now be 210 seconds; the time of the last buffer we
1127    * pushed. The element has no clock or base-time so it only reports the
1128    * last seen timestamp of the buffer, it does not know how much of the buffer
1129    * is consumed. */
1130   GST_DEBUG ("joining thread");
1131   g_thread_join (thread);
1132 
1133   gst_element_query_position (sink, GST_FORMAT_TIME, &position);
1134   GST_DEBUG ("last buffer position %" GST_TIME_FORMAT,
1135       GST_TIME_ARGS (position));
1136   fail_unless (position == 210 * GST_SECOND, "position is wrong");
1137 
1138   gst_object_unref (sinkpad);
1139 
1140   gst_element_set_state (sink, GST_STATE_NULL);
1141   gst_object_unref (sink);
1142   gst_object_unref (bus);
1143 }
1144 
1145 GST_END_TEST;
1146 
1147 /* when we get the ASYNC_DONE, query the position */
1148 static GstBusSyncReply
async_done_eos_func(GstBus * bus,GstMessage * msg,GstElement * sink)1149 async_done_eos_func (GstBus * bus, GstMessage * msg, GstElement * sink)
1150 {
1151   if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ASYNC_DONE) {
1152     gint64 position;
1153 
1154     GST_DEBUG ("we have ASYNC_DONE now");
1155 
1156     /* get the position now */
1157     gst_element_query_position (sink, GST_FORMAT_TIME, &position);
1158 
1159     GST_DEBUG ("we have position %" GST_TIME_FORMAT, GST_TIME_ARGS (position));
1160 
1161     fail_unless (position == 10 * GST_SECOND, "position is wrong");
1162   }
1163   /* we must unref the message if we return DROP */
1164   gst_message_unref (msg);
1165   /* we can drop the message, nothing is listening for it. */
1166   return GST_BUS_DROP;
1167 }
1168 
1169 /* when we get the ASYNC_DONE message from a sink, we want the sink to be able
1170  * to report the duration and position. The sink should also have called the
1171  * render method. */
GST_START_TEST(test_async_done_eos)1172 GST_START_TEST (test_async_done_eos)
1173 {
1174   GstElement *sink;
1175   GstEvent *event;
1176   GstStateChangeReturn ret;
1177   GstPad *sinkpad;
1178   gboolean res;
1179   GstBus *bus;
1180   gboolean qret;
1181   GstSegment segment;
1182   gint64 position;
1183   GThread *thread;
1184 
1185   sink = gst_element_factory_make ("fakesink", "sink");
1186   g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
1187 
1188   sinkpad = gst_element_get_static_pad (sink, "sink");
1189 
1190   ret = gst_element_set_state (sink, GST_STATE_PAUSED);
1191   fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return");
1192 
1193   /* set bus on element synchronously listen for ASYNC_DONE */
1194   bus = gst_bus_new ();
1195   gst_element_set_bus (sink, bus);
1196   gst_bus_set_sync_handler (bus, (GstBusSyncHandler) async_done_eos_func, sink,
1197       NULL);
1198 
1199   /* make newsegment, this sets the position to 10sec when the buffer prerolls */
1200   GST_DEBUG ("sending segment");
1201   gst_segment_init (&segment, GST_FORMAT_TIME);
1202   segment.time = 10 * GST_SECOND;
1203   event = gst_event_new_segment (&segment);
1204   res = gst_pad_send_event (sinkpad, event);
1205   fail_unless (res == TRUE);
1206 
1207   /* We have not yet received any buffers so we are still in the READY state,
1208    * the position is therefore still not queryable. */
1209   position = -1;
1210   qret = gst_element_query_position (sink, GST_FORMAT_TIME, &position);
1211   fail_unless (qret == TRUE, "position wrong");
1212   fail_unless (position == 10 * GST_SECOND, "position is wrong");
1213 
1214   /* Since we are paused and the preroll queue has a length of 1, this function
1215    * will return immediately. The EOS will complete the preroll and the
1216    * position should now be 10 seconds. */
1217   GST_DEBUG ("pushing EOS");
1218   GST_DEBUG ("starting thread");
1219   thread =
1220       g_thread_try_new ("gst-check", (GThreadFunc) send_eos, sinkpad, NULL);
1221   fail_if (thread == NULL, "no thread");
1222 
1223   /* wait for preroll */
1224   gst_element_get_state (sink, NULL, NULL, -1);
1225 
1226   /* check if position is still 10 seconds */
1227   gst_element_query_position (sink, GST_FORMAT_TIME, &position);
1228   GST_DEBUG ("EOS position %" GST_TIME_FORMAT, GST_TIME_ARGS (position));
1229   fail_unless (position == 10 * GST_SECOND, "position is wrong");
1230 
1231   gst_element_set_state (sink, GST_STATE_NULL);
1232   g_thread_join (thread);
1233 
1234   gst_object_unref (sinkpad);
1235   gst_object_unref (sink);
1236   gst_object_unref (bus);
1237 }
1238 
1239 GST_END_TEST;
1240 
1241 static GMutex preroll_lock;
1242 static GCond preroll_cond;
1243 
1244 static void
test_async_false_seek_preroll(GstElement * elem,GstBuffer * buf,GstPad * pad,gpointer data)1245 test_async_false_seek_preroll (GstElement * elem, GstBuffer * buf,
1246     GstPad * pad, gpointer data)
1247 {
1248   g_mutex_lock (&preroll_lock);
1249   GST_DEBUG ("Got preroll buffer %p", buf);
1250   g_cond_signal (&preroll_cond);
1251   g_mutex_unlock (&preroll_lock);
1252 }
1253 
1254 static void
test_async_false_seek_handoff(GstElement * elem,GstBuffer * buf,GstPad * pad,gpointer data)1255 test_async_false_seek_handoff (GstElement * elem, GstBuffer * buf,
1256     GstPad * pad, gpointer data)
1257 {
1258   /* should never be reached, we never go to PLAYING */
1259   GST_DEBUG ("Got handoff buffer %p", buf);
1260   fail_unless (FALSE);
1261 }
1262 
GST_START_TEST(test_async_false_seek)1263 GST_START_TEST (test_async_false_seek)
1264 {
1265   GstElement *pipeline, *source, *sink;
1266 
1267   /* Create gstreamer elements */
1268   pipeline = gst_pipeline_new ("test-pipeline");
1269   source = gst_element_factory_make ("fakesrc", "file-source");
1270   sink = gst_element_factory_make ("fakesink", "audio-output");
1271 
1272   g_object_set (G_OBJECT (sink), "async", FALSE, NULL);
1273   g_object_set (G_OBJECT (sink), "num-buffers", 10, NULL);
1274   g_object_set (G_OBJECT (sink), "signal-handoffs", TRUE, NULL);
1275 
1276   g_signal_connect (sink, "handoff", G_CALLBACK (test_async_false_seek_handoff),
1277       NULL);
1278   g_signal_connect (sink, "preroll-handoff",
1279       G_CALLBACK (test_async_false_seek_preroll), NULL);
1280 
1281   /* we add all elements into the pipeline */
1282   gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL);
1283 
1284   /* we link the elements together */
1285   gst_element_link (source, sink);
1286 
1287   GST_DEBUG ("Now pausing");
1288   g_mutex_lock (&preroll_lock);
1289   gst_element_set_state (pipeline, GST_STATE_PAUSED);
1290 
1291   /* wait for preroll */
1292   GST_DEBUG ("wait for preroll");
1293   g_cond_wait (&preroll_cond, &preroll_lock);
1294   g_mutex_unlock (&preroll_lock);
1295 
1296   g_mutex_lock (&preroll_lock);
1297   GST_DEBUG ("Seeking");
1298   fail_unless (gst_element_seek (pipeline, 1.0, GST_FORMAT_BYTES,
1299           GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, -1));
1300 
1301   GST_DEBUG ("wait for new preroll");
1302   /* this either prerolls or fails */
1303   g_cond_wait (&preroll_cond, &preroll_lock);
1304   g_mutex_unlock (&preroll_lock);
1305 
1306   GST_DEBUG ("bring pipe to state NULL");
1307   gst_element_set_state (pipeline, GST_STATE_NULL);
1308 
1309   GST_DEBUG ("Deleting pipeline");
1310   gst_object_unref (GST_OBJECT (pipeline));
1311 }
1312 
1313 GST_END_TEST;
1314 
1315 static GMutex handoff_lock;
1316 static GCond handoff_cond;
1317 
1318 static void
test_async_false_seek_in_playing_handoff(GstElement * elem,GstBuffer * buf,GstPad * pad,gpointer data)1319 test_async_false_seek_in_playing_handoff (GstElement * elem, GstBuffer * buf,
1320     GstPad * pad, gpointer data)
1321 {
1322   g_mutex_lock (&handoff_lock);
1323   GST_DEBUG ("Got handoff buffer %p", buf);
1324   g_cond_signal (&handoff_cond);
1325   g_mutex_unlock (&handoff_lock);
1326 }
1327 
GST_START_TEST(test_async_false_seek_in_playing)1328 GST_START_TEST (test_async_false_seek_in_playing)
1329 {
1330   GstElement *pipeline, *source, *sink;
1331 
1332   /* Create gstreamer elements */
1333   pipeline = gst_pipeline_new ("test-pipeline");
1334   source = gst_element_factory_make ("fakesrc", "fake-source");
1335   sink = gst_element_factory_make ("fakesink", "fake-output");
1336 
1337   g_object_set (G_OBJECT (sink), "async", FALSE, NULL);
1338   g_object_set (G_OBJECT (sink), "signal-handoffs", TRUE, NULL);
1339 
1340   g_signal_connect (sink, "handoff",
1341       G_CALLBACK (test_async_false_seek_in_playing_handoff), NULL);
1342 
1343   /* we add all elements into the pipeline */
1344   gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL);
1345 
1346   /* we link the elements together */
1347   gst_element_link (source, sink);
1348 
1349   GST_DEBUG ("Now playing");
1350   gst_element_set_state (pipeline, GST_STATE_PLAYING);
1351 
1352   g_mutex_lock (&handoff_lock);
1353   GST_DEBUG ("wait for handoff buffer");
1354   g_cond_wait (&handoff_cond, &handoff_lock);
1355   g_mutex_unlock (&handoff_lock);
1356 
1357   GST_DEBUG ("Seeking");
1358   fail_unless (gst_element_seek (source, 1.0, GST_FORMAT_BYTES,
1359           GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, -1));
1360 
1361   g_mutex_lock (&handoff_lock);
1362   GST_DEBUG ("wait for handoff buffer");
1363   g_cond_wait (&handoff_cond, &handoff_lock);
1364   g_mutex_unlock (&handoff_lock);
1365 
1366   GST_DEBUG ("bring pipe to state NULL");
1367   gst_element_set_state (pipeline, GST_STATE_NULL);
1368 
1369   GST_DEBUG ("Deleting pipeline");
1370   gst_object_unref (GST_OBJECT (pipeline));
1371 }
1372 
1373 GST_END_TEST;
1374 
1375 /* test: try changing state of sinks */
1376 static Suite *
gst_sinks_suite(void)1377 gst_sinks_suite (void)
1378 {
1379   Suite *s = suite_create ("Sinks");
1380   TCase *tc_chain = tcase_create ("general");
1381   guint timeout = 10;
1382 
1383   /* time out after 10s, not the default 3, we need this for the last test.
1384    * We need a longer timeout when running under valgrind though. */
1385   if (g_getenv ("CK_DEFAULT_TIMEOUT") != NULL)
1386     timeout = MAX (10, atoi (g_getenv ("CK_DEFAULT_TIMEOUT")));
1387   tcase_set_timeout (tc_chain, timeout);
1388 
1389   suite_add_tcase (s, tc_chain);
1390   tcase_add_test (tc_chain, test_sink);
1391   tcase_add_test (tc_chain, test_sink_completion);
1392   tcase_add_test (tc_chain, test_src_sink);
1393   tcase_add_test (tc_chain, test_livesrc_remove);
1394   tcase_add_test (tc_chain, test_livesrc_sink);
1395   tcase_add_test (tc_chain, test_livesrc2_sink);
1396   tcase_add_test (tc_chain, test_livesrc3_sink);
1397   tcase_add_test (tc_chain, test_locked_sink);
1398   tcase_add_test (tc_chain, test_unlinked_live);
1399   tcase_add_test (tc_chain, test_delayed_async);
1400   tcase_add_test (tc_chain, test_added_async);
1401   tcase_add_test (tc_chain, test_added_async2);
1402   tcase_add_test (tc_chain, test_add_live);
1403   tcase_add_test (tc_chain, test_add_live2);
1404   tcase_add_test (tc_chain, test_bin_live);
1405   tcase_add_test (tc_chain, test_fake_eos);
1406   tcase_add_test (tc_chain, test_async_done);
1407   tcase_add_test (tc_chain, test_async_done_eos);
1408   tcase_add_test (tc_chain, test_async_false_seek);
1409   tcase_add_test (tc_chain, test_async_false_seek_in_playing);
1410 
1411   return s;
1412 }
1413 
1414 GST_CHECK_MAIN (gst_sinks);
1415