5 * Copyright (C) <2005> Wim Taymans <wim at fluendo dot com>
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.
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.
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.
23 #include <gst/check/gstcheck.h>
26 pop_state_change_message (GstBus * bus, GstElement * src, GstState old,
27 GstState new, GstState pending)
29 GstMessage *message = NULL;
30 GstState _old, _new, _pending;
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");
36 gst_message_parse_state_changed (message, &_old, &_new, &_pending);
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");
44 gst_message_unref (message);
47 /* a sink should go ASYNC to PAUSE. forcing PLAYING is possible */
48 GST_START_TEST (test_sink)
51 GstStateChangeReturn ret;
52 GstState current, pending;
54 sink = gst_element_factory_make ("fakesink", "sink");
56 ret = gst_element_set_state (sink, GST_STATE_PAUSED);
57 fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no async state return");
59 ret = gst_element_set_state (sink, GST_STATE_PLAYING);
60 fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no forced async state change");
62 ret = gst_element_get_state (sink, ¤t, &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");
67 ret = gst_element_set_state (sink, GST_STATE_PAUSED);
68 fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no async going back to paused");
70 ret = gst_element_set_state (sink, GST_STATE_READY);
71 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "failed to go to ready");
73 ret = gst_element_set_state (sink, GST_STATE_NULL);
74 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "failed to go to null");
76 gst_object_unref (sink);
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)
84 GstElement *sink, *src;
85 GstStateChangeReturn ret;
86 GstState current, pending;
88 sink = gst_element_factory_make ("fakesink", "sink");
89 g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
91 ret = gst_element_set_state (sink, GST_STATE_PLAYING);
92 fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no async state return");
94 ret = gst_element_get_state (sink, ¤t, &pending, 0);
95 fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not changing state async");
96 fail_unless (current == GST_STATE_READY, "bad current state");
97 fail_unless (pending == GST_STATE_PLAYING, "bad pending state");
99 src = gst_element_factory_make ("fakesrc", "src");
100 g_object_set (G_OBJECT (src), "datarate", 200, "sizetype", 2, NULL);
101 gst_element_link (src, sink);
103 ret = gst_element_set_state (src, GST_STATE_PLAYING);
104 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no success state return");
106 /* now wait for final state */
107 ret = gst_element_get_state (sink, ¤t, &pending, GST_CLOCK_TIME_NONE);
108 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "failed to change state");
109 fail_unless (current == GST_STATE_PLAYING, "bad current state");
110 fail_unless (pending == GST_STATE_VOID_PENDING, "bad pending state");
112 ret = gst_element_set_state (sink, GST_STATE_NULL);
113 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "failed to go to null");
115 ret = gst_element_set_state (src, GST_STATE_NULL);
116 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "failed to go to null");
118 gst_object_unref (sink);
119 gst_object_unref (src);
123 /* a sink should go ASYNC to PAUSE. PAUSE should complete when
125 GST_START_TEST (test_src_sink)
127 GstElement *sink, *src, *pipeline;
128 GstStateChangeReturn ret;
129 GstState current, pending;
130 GstPad *srcpad, *sinkpad;
132 pipeline = gst_pipeline_new ("pipeline");
133 src = gst_element_factory_make ("fakesrc", "src");
134 sink = gst_element_factory_make ("fakesink", "sink");
136 gst_bin_add (GST_BIN (pipeline), src);
137 gst_bin_add (GST_BIN (pipeline), sink);
139 srcpad = gst_element_get_pad (src, "src");
140 sinkpad = gst_element_get_pad (sink, "sink");
141 gst_pad_link (srcpad, sinkpad);
142 gst_object_unref (srcpad);
143 gst_object_unref (sinkpad);
145 ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
146 fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no async state return");
147 ret = gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
148 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no success state return");
150 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
151 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "cannot start play");
154 gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE);
155 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not playing");
156 fail_unless (current == GST_STATE_PLAYING, "not playing");
157 fail_unless (pending == GST_STATE_VOID_PENDING, "not playing");
158 ret = gst_element_set_state (pipeline, GST_STATE_NULL);
159 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "cannot null pipeline");
161 gst_object_unref (pipeline);
166 /* a pipeline with live source should return NO_PREROLL in
167 * PAUSE. When removing the live source it should return ASYNC
169 GST_START_TEST (test_livesrc_remove)
171 GstElement *sink, *src, *pipeline;
172 GstStateChangeReturn ret;
173 GstState current, pending;
174 GstPad *srcpad, *sinkpad;
176 pipeline = gst_pipeline_new ("pipeline");
177 src = gst_element_factory_make ("fakesrc", "src");
178 g_object_set (G_OBJECT (src), "is-live", TRUE, NULL);
179 sink = gst_element_factory_make ("fakesink", "sink");
181 gst_object_ref (src);
182 gst_bin_add (GST_BIN (pipeline), src);
183 gst_bin_add (GST_BIN (pipeline), sink);
185 srcpad = gst_element_get_pad (src, "src");
186 sinkpad = gst_element_get_pad (sink, "sink");
187 gst_pad_link (srcpad, sinkpad);
188 gst_object_unref (srcpad);
189 gst_object_unref (sinkpad);
191 ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
192 fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL,
193 "no no_preroll state return");
195 ret = gst_element_get_state (src, ¤t, &pending, GST_CLOCK_TIME_NONE);
196 fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not paused");
197 fail_unless (current == GST_STATE_PAUSED, "not paused");
198 fail_unless (pending == GST_STATE_VOID_PENDING, "not playing");
200 gst_bin_remove (GST_BIN (pipeline), src);
202 ret = gst_element_set_state (src, GST_STATE_NULL);
203 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "async going to null");
204 gst_object_unref (src);
206 ret = gst_element_get_state (pipeline, ¤t, &pending, 0);
207 fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not async");
208 fail_unless (current == GST_STATE_PAUSED, "not paused");
209 fail_unless (pending == GST_STATE_PAUSED, "not paused");
211 ret = gst_element_set_state (pipeline, GST_STATE_NULL);
212 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "async going to null");
213 gst_object_unref (pipeline);
217 /* the sink should go ASYNC to PAUSE. The live source should go
218 * NO_PREROLL to PAUSE. the pipeline returns NO_PREROLL. An
219 * attempt to go to PLAYING will return ASYNC. polling state
220 * completion should return SUCCESS when the sink is gone to
222 GST_START_TEST (test_livesrc_sink)
224 GstElement *sink, *src, *pipeline;
225 GstStateChangeReturn ret;
226 GstState current, pending;
227 GstPad *srcpad, *sinkpad;
230 pipeline = gst_pipeline_new ("pipeline");
231 src = gst_element_factory_make ("fakesrc", "src");
232 g_object_set (G_OBJECT (src), "is-live", TRUE, NULL);
233 sink = gst_element_factory_make ("fakesink", "sink");
235 gst_bin_add (GST_BIN (pipeline), src);
236 gst_bin_add (GST_BIN (pipeline), sink);
238 srcpad = gst_element_get_pad (src, "src");
239 sinkpad = gst_element_get_pad (sink, "sink");
240 gst_pad_link (srcpad, sinkpad);
241 gst_object_unref (srcpad);
242 gst_object_unref (sinkpad);
244 bus = gst_element_get_bus (pipeline);
246 ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
247 fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL,
248 "no no_preroll state return");
250 pop_state_change_message (bus, sink, GST_STATE_NULL, GST_STATE_READY,
251 GST_STATE_VOID_PENDING);
252 pop_state_change_message (bus, src, GST_STATE_NULL, GST_STATE_READY,
253 GST_STATE_VOID_PENDING);
254 pop_state_change_message (bus, pipeline, GST_STATE_NULL, GST_STATE_READY,
257 /* this order only holds true for live sources because they do not push
259 pop_state_change_message (bus, src, GST_STATE_READY, GST_STATE_PAUSED,
260 GST_STATE_VOID_PENDING);
261 pop_state_change_message (bus, pipeline, GST_STATE_READY, GST_STATE_PAUSED,
262 GST_STATE_VOID_PENDING);
264 ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
265 fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL,
266 "no no_preroll state return the second time");
268 ret = gst_element_get_state (src, ¤t, &pending, GST_CLOCK_TIME_NONE);
269 fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not paused");
270 fail_unless (current == GST_STATE_PAUSED, "not paused");
271 fail_unless (pending == GST_STATE_VOID_PENDING, "not playing");
273 /* don't block here */
274 ret = gst_element_get_state (sink, ¤t, &pending, 0);
275 fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not async");
276 fail_unless (current == GST_STATE_READY, "not ready");
277 fail_unless (pending == GST_STATE_PAUSED, "not paused");
280 gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE);
281 fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not paused");
282 fail_unless (current == GST_STATE_PAUSED, "not paused");
283 fail_unless (pending == GST_STATE_VOID_PENDING, "not playing");
285 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
286 fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not async");
288 gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE);
289 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not playing");
290 fail_unless (current == GST_STATE_PLAYING, "not playing");
291 fail_unless (pending == GST_STATE_VOID_PENDING, "not playing");
293 /* now we have four messages on the bus: src from paused to playing, sink from
294 ready to paused and paused to playing, and pipeline from paused to playing.
295 the pipeline message should be last, and the sink messages should go in
296 order, but the src message can be interleaved with the sink one. */
299 GstState old, new, pending;
300 gint n_src = 1, n_sink = 2;
302 while (n_src + n_sink > 0) {
303 m = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND);
304 fail_unless (m != NULL, "expected state change message");
305 gst_message_parse_state_changed (m, &old, &new, &pending);
306 if (GST_MESSAGE_SRC (m) == (GstObject *) src) {
307 fail_unless (n_src == 1, "already got one message from the src");
309 fail_unless (old == GST_STATE_PAUSED, "unexpected old");
310 fail_unless (new == GST_STATE_PLAYING, "unexpected new (got %d)", new);
311 fail_unless (pending == GST_STATE_VOID_PENDING, "unexpected pending");
312 } else if (GST_MESSAGE_SRC (m) == (GstObject *) sink) {
314 fail_unless (old == GST_STATE_READY, "unexpected old");
315 fail_unless (new == GST_STATE_PAUSED, "unexpected new");
316 fail_unless (pending == GST_STATE_VOID_PENDING, "unexpected pending");
317 } else if (n_sink == 1) {
318 fail_unless (old == GST_STATE_PAUSED, "unexpected old");
319 fail_unless (new == GST_STATE_PLAYING, "unexpected new");
320 fail_unless (pending == GST_STATE_VOID_PENDING, "unexpected pending");
322 g_assert_not_reached ();
327 ("Unexpected state change message src %s (%d src %d sink pending)",
328 GST_OBJECT_NAME (GST_MESSAGE_SRC (m)), n_src, n_sink);
330 gst_message_unref (m);
334 pop_state_change_message (bus, pipeline, GST_STATE_PAUSED, GST_STATE_PLAYING,
335 GST_STATE_VOID_PENDING);
337 gst_object_unref (bus);
338 gst_element_set_state (pipeline, GST_STATE_NULL);
339 gst_object_unref (pipeline);
344 /* The sink should go ASYNC to PLAYING. The source should go
345 * to PLAYING with SUCCESS. The pipeline returns ASYNC. */
346 GST_START_TEST (test_livesrc2_sink)
348 GstElement *sink, *src, *pipeline;
349 GstStateChangeReturn ret;
350 GstState current, pending;
351 GstPad *srcpad, *sinkpad;
353 pipeline = gst_pipeline_new ("pipeline");
354 src = gst_element_factory_make ("fakesrc", "src");
355 g_object_set (G_OBJECT (src), "is-live", TRUE, NULL);
356 sink = gst_element_factory_make ("fakesink", "sink");
358 gst_bin_add (GST_BIN (pipeline), src);
359 gst_bin_add (GST_BIN (pipeline), sink);
361 srcpad = gst_element_get_pad (src, "src");
362 sinkpad = gst_element_get_pad (sink, "sink");
363 gst_pad_link (srcpad, sinkpad);
364 gst_object_unref (srcpad);
365 gst_object_unref (sinkpad);
367 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
368 fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no async state return");
370 ret = gst_element_get_state (src, ¤t, &pending, GST_CLOCK_TIME_NONE);
371 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not playing");
372 fail_unless (current == GST_STATE_PLAYING, "not playing");
373 fail_unless (pending == GST_STATE_VOID_PENDING, "not playing");
376 gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE);
377 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not playing");
378 fail_unless (current == GST_STATE_PLAYING, "not playing");
379 fail_unless (pending == GST_STATE_VOID_PENDING, "not playing");
382 ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
383 fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL,
384 "no no_preroll state return");
386 ret = gst_element_get_state (src, ¤t, &pending, GST_CLOCK_TIME_NONE);
387 fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not no_preroll");
388 fail_unless (current == GST_STATE_PAUSED, "not paused");
389 fail_unless (pending == GST_STATE_VOID_PENDING, "not paused");
391 /* sink state is not known.. it might be prerolled or not */
394 ret = gst_element_set_state (pipeline, GST_STATE_READY);
395 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no success state return");
397 ret = gst_element_get_state (src, ¤t, &pending, GST_CLOCK_TIME_NONE);
398 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not success");
399 fail_unless (current == GST_STATE_READY, "not ready");
400 fail_unless (pending == GST_STATE_VOID_PENDING, "not ready");
402 ret = gst_element_get_state (sink, ¤t, &pending, GST_CLOCK_TIME_NONE);
403 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not success");
404 fail_unless (current == GST_STATE_READY, "not ready");
405 fail_unless (pending == GST_STATE_VOID_PENDING, "not ready");
407 /* And destroy. Must be NULL */
408 ret = gst_element_set_state (pipeline, GST_STATE_NULL);
409 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no success state return");
410 gst_object_unref (pipeline);
415 GST_START_TEST (test_livesrc3_sink)
417 GstElement *sink, *src, *pipeline;
418 GstStateChangeReturn ret;
419 GstState current, pending;
420 GstPad *srcpad, *sinkpad;
422 pipeline = gst_pipeline_new ("pipeline");
423 src = gst_element_factory_make ("fakesrc", "src");
424 g_object_set (G_OBJECT (src), "is-live", TRUE, NULL);
425 sink = gst_element_factory_make ("fakesink", "sink");
427 gst_bin_add (GST_BIN (pipeline), src);
428 gst_bin_add (GST_BIN (pipeline), sink);
430 srcpad = gst_element_get_pad (src, "src");
431 sinkpad = gst_element_get_pad (sink, "sink");
432 gst_pad_link (srcpad, sinkpad);
433 gst_object_unref (srcpad);
434 gst_object_unref (sinkpad);
436 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
437 fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no async state return");
440 gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE);
441 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not playing");
442 fail_unless (current == GST_STATE_PLAYING, "not playing");
443 fail_unless (pending == GST_STATE_VOID_PENDING, "not playing");
446 ret = gst_element_set_state (pipeline, GST_STATE_NULL);
447 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no success state return");
448 gst_object_unref (pipeline);
453 GST_START_TEST (test_locked_sink)
455 GstElement *sink, *src, *pipeline;
456 GstStateChangeReturn ret;
457 GstState current, pending;
459 pipeline = gst_pipeline_new ("pipeline");
460 src = gst_element_factory_make ("fakesrc", "src");
461 g_object_set (G_OBJECT (src), "is-live", TRUE, NULL);
462 sink = gst_element_factory_make ("fakesink", "sink");
464 gst_bin_add (GST_BIN (pipeline), src);
465 gst_bin_add (GST_BIN (pipeline), sink);
467 /* we don't link the elements */
469 ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
470 fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL,
471 "no NO_PREROLL state return");
474 gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE);
475 fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not no_preroll");
476 fail_unless (current == GST_STATE_PAUSED, "not paused");
477 fail_unless (pending == GST_STATE_VOID_PENDING, "have pending");
479 /* the sink is now async going from ready to paused */
480 ret = gst_element_get_state (sink, ¤t, &pending, 0);
481 fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not async");
482 fail_unless (current == GST_STATE_READY, "not ready");
483 fail_unless (pending == GST_STATE_PAUSED, "not paused");
486 gst_element_set_locked_state (sink, TRUE);
488 /* move to PlAYING, the sink should remain ASYNC. The pipeline
490 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
491 fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return");
493 /* back to PAUSED, we should get NO_PREROLL again */
494 ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
495 fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL,
496 "no NO_PREROLL state return");
498 /* unlock the sink */
499 gst_element_set_locked_state (sink, FALSE);
501 /* and now everything back down */
502 ret = gst_element_set_state (pipeline, GST_STATE_NULL);
503 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no success state return");
504 gst_object_unref (pipeline);
509 GST_START_TEST (test_unlinked_live)
511 GstElement *sink, *src, *lsrc, *pipeline;
512 GstStateChangeReturn ret;
513 GstState current, pending;
514 GstPad *srcpad, *sinkpad;
516 pipeline = gst_pipeline_new ("pipeline");
517 src = gst_element_factory_make ("fakesrc", "src");
518 lsrc = gst_element_factory_make ("fakesrc", "lsrc");
519 g_object_set (G_OBJECT (lsrc), "is-live", TRUE, NULL);
520 sink = gst_element_factory_make ("fakesink", "sink");
522 gst_bin_add (GST_BIN (pipeline), src);
523 gst_bin_add (GST_BIN (pipeline), lsrc);
524 gst_bin_add (GST_BIN (pipeline), sink);
526 /* link non live source to sink */
527 srcpad = gst_element_get_pad (src, "src");
528 sinkpad = gst_element_get_pad (sink, "sink");
529 gst_pad_link (srcpad, sinkpad);
530 gst_object_unref (srcpad);
531 gst_object_unref (sinkpad);
533 /* we don't link the srcpad of the live source, it will not contribute to the
536 /* set state to PAUSED, this should return NO_PREROLL because there is a live
537 * source. since the only sink in this pipeline is linked to a non-live
538 * source, it will preroll eventually. */
539 ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
540 fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL,
541 "no NO_PREROLL state return");
543 /* wait till the sink is prerolled */
544 ret = gst_element_get_state (sink, ¤t, &pending, GST_CLOCK_TIME_NONE);
545 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not success");
546 fail_unless (current == GST_STATE_PAUSED, "not paused");
547 fail_unless (pending == GST_STATE_VOID_PENDING, "have playing");
549 /* the pipeline should still return NO_PREROLL */
551 gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE);
552 fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not no_preroll");
553 fail_unless (current == GST_STATE_PAUSED, "not paused");
554 fail_unless (pending == GST_STATE_VOID_PENDING, "have playing");
556 ret = gst_element_set_state (pipeline, GST_STATE_NULL);
557 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not SUCCESS");
559 gst_object_unref (pipeline);
564 GST_START_TEST (test_delayed_async)
566 GstElement *sink, *src, *pipeline;
567 GstStateChangeReturn ret;
568 GstState current, pending;
569 GstPad *srcpad, *sinkpad;
571 pipeline = gst_pipeline_new ("pipeline");
572 src = gst_element_factory_make ("fakesrc", "src");
573 g_object_set (G_OBJECT (src), "is-live", TRUE, NULL);
574 sink = gst_element_factory_make ("fakesink", "sink");
576 /* add source, don't add sink yet */
577 gst_bin_add (GST_BIN (pipeline), src);
579 ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
580 fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL,
581 "no NO_PREROLL state return");
583 /* add sink now and set to PAUSED */
584 gst_bin_add (GST_BIN (pipeline), sink);
586 /* This will make the bin notice an ASYNC element. */
587 ret = gst_element_set_state (sink, GST_STATE_PAUSED);
588 fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return");
590 /* we should still be NO_PREROLL now although there is an async element in the
593 gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE);
594 fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not NO_PREROLL");
595 fail_unless (current == GST_STATE_PAUSED, "not paused");
596 fail_unless (pending == GST_STATE_VOID_PENDING, "have pending");
598 /* link live source to sink */
599 srcpad = gst_element_get_pad (src, "src");
600 sinkpad = gst_element_get_pad (sink, "sink");
601 gst_pad_link (srcpad, sinkpad);
602 gst_object_unref (srcpad);
603 gst_object_unref (sinkpad);
605 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
606 fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return");
608 /* we should get SUCCESS now */
610 gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE);
611 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not NO_PREROLL");
612 fail_unless (current == GST_STATE_PLAYING, "not PLAYING");
613 fail_unless (pending == GST_STATE_VOID_PENDING, "have pending");
615 ret = gst_element_set_state (pipeline, GST_STATE_NULL);
616 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not SUCCESS");
618 gst_object_unref (pipeline);
623 GST_START_TEST (test_added_async)
625 GstElement *sink, *src, *pipeline;
626 GstStateChangeReturn ret;
627 GstState current, pending;
628 GstPad *srcpad, *sinkpad;
630 pipeline = gst_pipeline_new ("pipeline");
631 src = gst_element_factory_make ("fakesrc", "src");
632 g_object_set (G_OBJECT (src), "is-live", TRUE, NULL);
633 sink = gst_element_factory_make ("fakesink", "sink");
635 /* add source, don't add sink yet */
636 gst_bin_add (GST_BIN (pipeline), src);
638 ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
639 fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL,
640 "no NO_PREROLL state return");
642 /* set sink to PAUSED without adding it to the pipeline */
643 ret = gst_element_set_state (sink, GST_STATE_PAUSED);
644 fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return");
646 /* add sink now, pipeline should notice the async element */
647 gst_bin_add (GST_BIN (pipeline), sink);
649 /* we should still be NO_PREROLL now although there is an async element in the
652 gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE);
653 fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not NO_PREROLL");
654 fail_unless (current == GST_STATE_PAUSED, "not paused");
655 fail_unless (pending == GST_STATE_VOID_PENDING, "have pending");
657 /* link live source to sink */
658 srcpad = gst_element_get_pad (src, "src");
659 sinkpad = gst_element_get_pad (sink, "sink");
660 gst_pad_link (srcpad, sinkpad);
661 gst_object_unref (srcpad);
662 gst_object_unref (sinkpad);
664 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
665 fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return");
667 /* we should get SUCCESS now */
669 gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE);
670 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not NO_PREROLL");
671 fail_unless (current == GST_STATE_PLAYING, "not PLAYING");
672 fail_unless (pending == GST_STATE_VOID_PENDING, "have pending");
674 ret = gst_element_set_state (pipeline, GST_STATE_NULL);
675 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not SUCCESS");
677 gst_object_unref (pipeline);
682 GST_START_TEST (test_added_async2)
684 GstElement *sink, *src, *pipeline;
685 GstStateChangeReturn ret;
686 GstState current, pending;
688 pipeline = gst_pipeline_new ("pipeline");
689 src = gst_element_factory_make ("fakesrc", "src");
690 sink = gst_element_factory_make ("fakesink", "sink");
692 /* add source, don't add sink yet */
693 gst_bin_add (GST_BIN (pipeline), src);
695 ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
696 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no SUCCESS state return");
698 /* set sink to PAUSED without adding it to the pipeline */
699 ret = gst_element_set_state (sink, GST_STATE_PAUSED);
700 fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return");
702 /* add sink now, pipeline should notice the async element */
703 gst_bin_add (GST_BIN (pipeline), sink);
705 /* we should be ASYNC now because there is an async element in the
707 ret = gst_element_get_state (pipeline, ¤t, &pending, 0);
708 fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not ASYNC");
709 fail_unless (current == GST_STATE_PAUSED, "not paused");
710 fail_unless (pending == GST_STATE_PAUSED, "not paused");
712 ret = gst_element_set_state (pipeline, GST_STATE_NULL);
713 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not SUCCESS");
715 gst_object_unref (pipeline);
720 GST_START_TEST (test_add_live)
722 GstElement *sink, *src, *pipeline;
723 GstStateChangeReturn ret;
724 GstState current, pending;
726 pipeline = gst_pipeline_new ("pipeline");
727 src = gst_element_factory_make ("fakesrc", "src");
728 g_object_set (G_OBJECT (src), "is-live", TRUE, NULL);
729 sink = gst_element_factory_make ("fakesink", "sink");
731 /* add sink, don't add sourc3 yet */
732 gst_bin_add (GST_BIN (pipeline), sink);
734 ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
735 fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return");
737 /* set source to PAUSED without adding it to the pipeline */
738 ret = gst_element_set_state (src, GST_STATE_PAUSED);
739 fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL,
740 "no NO_PREROLL state return");
742 /* add source now, pipeline should notice the NO_PREROLL element */
743 gst_bin_add (GST_BIN (pipeline), src);
745 /* we should be NO_PREROLL now because there is a NO_PREROLL element in the
748 gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE);
749 fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not NO_PREROLL");
750 fail_unless (current == GST_STATE_PAUSED, "not paused");
751 fail_unless (pending == GST_STATE_VOID_PENDING, "have pending");
753 ret = gst_element_set_state (pipeline, GST_STATE_NULL);
754 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not SUCCESS");
756 gst_object_unref (pipeline);
761 static GMutex *blocked_lock;
762 static GCond *blocked_cond;
765 pad_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data)
767 g_mutex_lock (blocked_lock);
768 GST_DEBUG ("srcpad blocked: %d, sending signal", blocked);
769 g_cond_signal (blocked_cond);
770 g_mutex_unlock (blocked_lock);
773 GST_START_TEST (test_add_live2)
775 GstElement *sink, *src, *pipeline;
776 GstStateChangeReturn ret;
777 GstState current, pending;
778 GstPad *srcpad, *sinkpad;
780 blocked_lock = g_mutex_new ();
781 blocked_cond = g_cond_new ();
783 pipeline = gst_pipeline_new ("pipeline");
784 src = gst_element_factory_make ("fakesrc", "src");
785 g_object_set (G_OBJECT (src), "is-live", TRUE, NULL);
786 sink = gst_element_factory_make ("fakesink", "sink");
788 /* add sink, don't add source yet */
789 gst_bin_add (GST_BIN (pipeline), sink);
791 /* set the pipeline to PLAYING. This will return ASYNC on READY->PAUSED */
792 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
793 fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return");
795 g_mutex_lock (blocked_lock);
797 GST_DEBUG ("blocking srcpad");
798 /* block source pad */
799 srcpad = gst_element_get_pad (src, "src");
800 gst_pad_set_blocked_async (srcpad, TRUE, pad_blocked_cb, NULL);
802 /* set source to PAUSED without adding it to the pipeline */
803 ret = gst_element_set_state (src, GST_STATE_PAUSED);
804 fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL,
805 "no NO_PREROLL state return");
807 /* add source now, pipeline should notice the NO_PREROLL element. This
808 * should trigger as commit of the ASYNC pipeline and make it continue
809 * to PLAYING. We blocked the source pad so that we don't get an unlinked
811 gst_bin_add (GST_BIN (pipeline), src);
813 /* wait for pad blocked, this means the source is now PLAYING. */
814 g_cond_wait (blocked_cond, blocked_lock);
815 g_mutex_unlock (blocked_lock);
817 GST_DEBUG ("linking pads");
820 sinkpad = gst_element_get_pad (sink, "sink");
821 gst_pad_link (srcpad, sinkpad);
822 gst_object_unref (srcpad);
823 gst_object_unref (sinkpad);
825 GST_DEBUG ("unblocking srcpad");
828 gst_pad_set_blocked_async (srcpad, FALSE, pad_blocked_cb, NULL);
830 GST_DEBUG ("getting state");
832 /* we should be SUCCESS now and PLAYING */
834 gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE);
835 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not SUCCESS");
836 fail_unless (current == GST_STATE_PLAYING, "not PLAYING");
837 fail_unless (pending == GST_STATE_VOID_PENDING, "have pending");
839 ret = gst_element_set_state (pipeline, GST_STATE_NULL);
840 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not SUCCESS");
842 g_cond_free (blocked_cond);
843 g_mutex_free (blocked_lock);
844 gst_object_unref (pipeline);
849 GST_START_TEST (test_bin_live)
851 GstElement *sink, *src, *pipeline, *bin;
852 GstStateChangeReturn ret;
853 GstState current, pending;
854 GstPad *srcpad, *sinkpad;
856 pipeline = gst_pipeline_new ("pipeline");
857 bin = gst_bin_new ("bin");
858 src = gst_element_factory_make ("fakesrc", "src");
859 g_object_set (G_OBJECT (src), "is-live", TRUE, NULL);
860 sink = gst_element_factory_make ("fakesink", "sink");
862 gst_bin_add (GST_BIN (bin), src);
863 gst_bin_add (GST_BIN (bin), sink);
864 gst_bin_add (GST_BIN (pipeline), bin);
866 srcpad = gst_element_get_pad (src, "src");
867 sinkpad = gst_element_get_pad (sink, "sink");
868 gst_pad_link (srcpad, sinkpad);
869 gst_object_unref (srcpad);
870 gst_object_unref (sinkpad);
872 /* PAUSED returns NO_PREROLL because of the live source */
873 ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
874 fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL,
875 "no NO_PREROLL state return");
877 gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE);
878 fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not NO_PREROLL");
879 fail_unless (current == GST_STATE_PAUSED, "not paused");
880 fail_unless (pending == GST_STATE_VOID_PENDING, "not void pending");
882 /* when going to PLAYING, the sink should go to PLAYING ASYNC */
883 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
884 fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not ASYNC");
886 /* now wait for PLAYING to complete */
888 gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE);
889 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not playing");
890 fail_unless (current == GST_STATE_PLAYING, "not playing");
891 fail_unless (pending == GST_STATE_VOID_PENDING, "not void pending");
893 ret = gst_element_set_state (pipeline, GST_STATE_NULL);
894 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "cannot null pipeline");
896 gst_object_unref (pipeline);
899 GST_END_TEST static void
900 send_eos (GstPad * sinkpad)
902 gst_pad_send_event (sinkpad, gst_event_new_eos ());
905 /* push a buffer with a very long duration in a fakesink, then push an EOS
906 * event. fakesink should emit EOS after the duration of the buffer expired.
907 * Going to PAUSED, however should not return ASYNC while processing the
909 GST_START_TEST (test_fake_eos)
911 GstElement *sink, *pipeline;
913 GstStateChangeReturn ret;
918 pipeline = gst_pipeline_new ("pipeline");
920 sink = gst_element_factory_make ("fakesink", "sink");
921 g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
923 sinkpad = gst_element_get_pad (sink, "sink");
925 gst_bin_add (GST_BIN_CAST (pipeline), sink);
927 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
928 fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return");
930 /* push buffer of 100 seconds, since it has a timestamp of 0, it should be
931 * rendered immediatly and the chain function should return immediatly */
932 buffer = gst_buffer_new_and_alloc (10);
933 GST_BUFFER_TIMESTAMP (buffer) = 0;
934 GST_BUFFER_DURATION (buffer) = 100 * GST_SECOND;
935 res = gst_pad_chain (sinkpad, buffer);
936 fail_unless (res == GST_FLOW_OK, "no OK flow return");
938 /* wait for preroll, this should happen really soon. */
939 ret = gst_element_get_state (pipeline, NULL, NULL, -1);
940 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no SUCCESS state return");
942 /* push EOS, this will block for up to 100 seconds, until the previous
943 * buffer has finished. We therefore push it in another thread so we can do
944 * something else while it blocks. */
945 thread = g_thread_create ((GThreadFunc) send_eos, sinkpad, TRUE, NULL);
946 fail_if (thread == NULL, "no thread");
948 /* wait a while so that the thread manages to start and push the EOS */
949 g_usleep (G_USEC_PER_SEC);
951 /* this should cancel rendering of the EOS event and should return SUCCESS
952 * because the sink is now prerolled on the EOS. */
953 ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
954 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no SUCCESS state return");
956 /* we can unref the sinkpad now, we're done with it */
957 gst_object_unref (sinkpad);
959 /* wait for a second, use the debug log to see that basesink does not discard
961 g_usleep (G_USEC_PER_SEC);
963 /* go back to PLAYING, which means waiting some more in EOS, check debug log
964 * to see this happen. */
965 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
966 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no SUCCESS state return");
967 g_usleep (G_USEC_PER_SEC);
969 /* teardown and cleanup */
970 ret = gst_element_set_state (pipeline, GST_STATE_NULL);
971 fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no SUCCESS state return");
973 gst_object_unref (pipeline);
978 /* this variable is updated in the same thread, first it is set by the
979 * handoff-preroll signal, then it is checked when the ASYNC_DONE is posted on
981 static gboolean have_preroll = FALSE;
984 async_done_handoff (GstElement * element, GstBuffer * buf, GstPad * pad,
987 GST_DEBUG ("we have the preroll buffer");
991 /* when we get the ASYNC_DONE, query the position */
992 static GstBusSyncReply
993 async_done_func (GstBus * bus, GstMessage * msg, GstElement * sink)
995 if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ASYNC_DONE) {
999 GST_DEBUG ("we have ASYNC_DONE now");
1000 fail_unless (have_preroll == TRUE, "no preroll buffer received");
1002 /* get the position now */
1003 format = GST_FORMAT_TIME;
1004 gst_element_query_position (sink, &format, &position);
1006 GST_DEBUG ("we have position %" GST_TIME_FORMAT, GST_TIME_ARGS (position));
1008 fail_unless (position == 10 * GST_SECOND, "position is wrong");
1011 /* we must unref the message if we return DROP */
1012 gst_message_unref (msg);
1014 /* we can drop the message, nothing is listening for it. */
1015 return GST_BUS_DROP;
1019 send_buffer (GstPad * sinkpad)
1022 GstStateChangeReturn ret;
1024 /* push a second buffer */
1025 GST_DEBUG ("pushing last buffer");
1026 buffer = gst_buffer_new_and_alloc (10);
1027 GST_BUFFER_TIMESTAMP (buffer) = 200 * GST_SECOND;
1028 GST_BUFFER_DURATION (buffer) = 100 * GST_SECOND;
1030 /* this function will initially block */
1031 ret = gst_pad_chain (sinkpad, buffer);
1032 fail_unless (ret == GST_FLOW_OK, "no OK flow return");
1035 /* when we get the ASYNC_DONE message from a sink, we want the sink to be able
1036 * to report the duration and position. The sink should also have called the
1038 GST_START_TEST (test_async_done)
1043 GstStateChangeReturn ret;
1052 sink = gst_element_factory_make ("fakesink", "sink");
1053 g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
1054 g_object_set (G_OBJECT (sink), "preroll-queue-len", 2, NULL);
1055 g_object_set (G_OBJECT (sink), "signal-handoffs", TRUE, NULL);
1057 g_signal_connect (sink, "preroll-handoff", (GCallback) async_done_handoff,
1060 sinkpad = gst_element_get_pad (sink, "sink");
1062 ret = gst_element_set_state (sink, GST_STATE_PAUSED);
1063 fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return");
1065 /* set bus on element synchronously listen for ASYNC_DONE */
1066 bus = gst_bus_new ();
1067 gst_element_set_bus (sink, bus);
1068 gst_bus_set_sync_handler (bus, (GstBusSyncHandler) async_done_func, sink);
1070 /* make newsegment, this sets the position to 10sec when the buffer prerolls */
1071 GST_DEBUG ("sending segment");
1073 gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, -1,
1075 res = gst_pad_send_event (sinkpad, event);
1077 /* We have not yet received any buffers so we are still in the READY state,
1078 * the position is therefore still not queryable. */
1079 format = GST_FORMAT_TIME;
1081 qret = gst_element_query_position (sink, &format, &position);
1082 fail_unless (qret == FALSE, "position wrong");
1083 fail_unless (position == -1, "position is wrong");
1085 /* Since we are paused and the preroll queue has a length of 2, this function
1086 * will return immediatly, the preroll handoff will be called and the stream
1087 * position should now be 10 seconds. */
1088 GST_DEBUG ("pushing first buffer");
1089 buffer = gst_buffer_new_and_alloc (10);
1090 GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
1091 GST_BUFFER_DURATION (buffer) = 100 * GST_SECOND;
1092 res = gst_pad_chain (sinkpad, buffer);
1093 fail_unless (res == GST_FLOW_OK, "no OK flow return");
1095 /* scond buffer, will not block either but position should still be 10
1097 GST_DEBUG ("pushing second buffer");
1098 buffer = gst_buffer_new_and_alloc (10);
1099 GST_BUFFER_TIMESTAMP (buffer) = 100 * GST_SECOND;
1100 GST_BUFFER_DURATION (buffer) = 100 * GST_SECOND;
1101 res = gst_pad_chain (sinkpad, buffer);
1102 fail_unless (res == GST_FLOW_OK, "no OK flow return");
1104 /* check if position is still 10 seconds */
1105 format = GST_FORMAT_TIME;
1106 gst_element_query_position (sink, &format, &position);
1107 GST_DEBUG ("first buffer position %" GST_TIME_FORMAT,
1108 GST_TIME_ARGS (position));
1109 fail_unless (position == 10 * GST_SECOND, "position is wrong");
1111 /* last buffer, blocks because preroll queue is filled. Start the push in a
1112 * new thread so that we can check the position */
1113 GST_DEBUG ("starting thread");
1114 thread = g_thread_create ((GThreadFunc) send_buffer, sinkpad, TRUE, NULL);
1115 fail_if (thread == NULL, "no thread");
1117 GST_DEBUG ("waiting 1 second");
1118 g_usleep (G_USEC_PER_SEC);
1119 GST_DEBUG ("waiting done");
1121 /* check if position is still 10 seconds. This is racy because the above
1122 * thread might not yet have started the push, because of the above sleep,
1123 * this is very unlikely, though. */
1124 format = GST_FORMAT_TIME;
1125 gst_element_query_position (sink, &format, &position);
1126 GST_DEBUG ("second buffer position %" GST_TIME_FORMAT,
1127 GST_TIME_ARGS (position));
1128 fail_unless (position == 10 * GST_SECOND, "position is wrong");
1130 /* now we go to playing. This should unlock and stop the above thread. */
1131 GST_DEBUG ("going to PLAYING");
1132 ret = gst_element_set_state (sink, GST_STATE_PLAYING);
1134 /* join the thread. At this point we know the sink processed the last buffer
1135 * and the position should now be 210 seconds; the time of the last buffer we
1137 GST_DEBUG ("joining thread");
1138 g_thread_join (thread);
1140 format = GST_FORMAT_TIME;
1141 gst_element_query_position (sink, &format, &position);
1142 GST_DEBUG ("last buffer position %" GST_TIME_FORMAT,
1143 GST_TIME_ARGS (position));
1144 fail_unless (position == 210 * GST_SECOND, "position is wrong");
1146 gst_object_unref (sinkpad);
1148 gst_element_set_state (sink, GST_STATE_NULL);
1149 gst_object_unref (sink);
1150 gst_object_unref (bus);
1155 /* when we get the ASYNC_DONE, query the position */
1156 static GstBusSyncReply
1157 async_done_eos_func (GstBus * bus, GstMessage * msg, GstElement * sink)
1159 if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ASYNC_DONE) {
1163 GST_DEBUG ("we have ASYNC_DONE now");
1165 /* get the position now */
1166 format = GST_FORMAT_TIME;
1167 gst_element_query_position (sink, &format, &position);
1169 GST_DEBUG ("we have position %" GST_TIME_FORMAT, GST_TIME_ARGS (position));
1171 fail_unless (position == 10 * GST_SECOND, "position is wrong");
1173 /* we must unref the message if we return DROP */
1174 gst_message_unref (msg);
1175 /* we can drop the message, nothing is listening for it. */
1176 return GST_BUS_DROP;
1179 /* when we get the ASYNC_DONE message from a sink, we want the sink to be able
1180 * to report the duration and position. The sink should also have called the
1182 GST_START_TEST (test_async_done_eos)
1186 GstStateChangeReturn ret;
1194 sink = gst_element_factory_make ("fakesink", "sink");
1195 g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
1196 g_object_set (G_OBJECT (sink), "preroll-queue-len", 1, NULL);
1198 sinkpad = gst_element_get_pad (sink, "sink");
1200 ret = gst_element_set_state (sink, GST_STATE_PAUSED);
1201 fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no ASYNC state return");
1203 /* set bus on element synchronously listen for ASYNC_DONE */
1204 bus = gst_bus_new ();
1205 gst_element_set_bus (sink, bus);
1206 gst_bus_set_sync_handler (bus, (GstBusSyncHandler) async_done_eos_func, sink);
1208 /* make newsegment, this sets the position to 10sec when the buffer prerolls */
1209 GST_DEBUG ("sending segment");
1211 gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, -1,
1213 res = gst_pad_send_event (sinkpad, event);
1215 /* We have not yet received any buffers so we are still in the READY state,
1216 * the position is therefore still not queryable. */
1217 format = GST_FORMAT_TIME;
1219 qret = gst_element_query_position (sink, &format, &position);
1220 fail_unless (qret == FALSE, "position wrong");
1221 fail_unless (position == -1, "position is wrong");
1223 /* Since we are paused and the preroll queue has a length of 1, this function
1224 * will return immediatly. The EOS will complete the preroll and the
1225 * position should now be 10 seconds. */
1226 GST_DEBUG ("pushing EOS");
1227 event = gst_event_new_eos ();
1228 res = gst_pad_send_event (sinkpad, event);
1229 fail_unless (res == TRUE, "no TRUE return");
1231 /* check if position is still 10 seconds */
1232 format = GST_FORMAT_TIME;
1233 gst_element_query_position (sink, &format, &position);
1234 GST_DEBUG ("EOS position %" GST_TIME_FORMAT, GST_TIME_ARGS (position));
1235 fail_unless (position == 10 * GST_SECOND, "position is wrong");
1237 gst_object_unref (sinkpad);
1239 gst_element_set_state (sink, GST_STATE_NULL);
1240 gst_object_unref (sink);
1241 gst_object_unref (bus);
1246 /* test: try changing state of sinks */
1248 gst_sinks_suite (void)
1250 Suite *s = suite_create ("Sinks");
1251 TCase *tc_chain = tcase_create ("general");
1253 suite_add_tcase (s, tc_chain);
1254 tcase_add_test (tc_chain, test_sink);
1255 tcase_add_test (tc_chain, test_sink_completion);
1256 tcase_add_test (tc_chain, test_src_sink);
1257 tcase_add_test (tc_chain, test_livesrc_remove);
1258 tcase_add_test (tc_chain, test_livesrc_sink);
1259 tcase_add_test (tc_chain, test_livesrc2_sink);
1260 tcase_add_test (tc_chain, test_livesrc3_sink);
1261 tcase_add_test (tc_chain, test_locked_sink);
1262 tcase_add_test (tc_chain, test_unlinked_live);
1263 tcase_add_test (tc_chain, test_delayed_async);
1264 tcase_add_test (tc_chain, test_added_async);
1265 tcase_add_test (tc_chain, test_added_async2);
1266 tcase_add_test (tc_chain, test_add_live);
1267 tcase_add_test (tc_chain, test_add_live2);
1268 tcase_add_test (tc_chain, test_bin_live);
1269 tcase_add_test (tc_chain, test_fake_eos);
1270 tcase_add_test (tc_chain, test_async_done);
1271 tcase_add_test (tc_chain, test_async_done_eos);
1276 GST_CHECK_MAIN (gst_sinks);