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, ¤t, &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, ¤t, &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, ¤t, &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, ¤t, &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, ¤t, &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, ¤t, &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, ¤t, &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, ¤t, &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, ¤t, &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, ¤t, &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, ¤t, &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, ¤t, &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, ¤t, &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, ¤t, &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, ¤t, &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, ¤t, &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, ¤t, &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, ¤t, &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, ¤t, &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, ¤t, &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, ¤t, &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, ¤t, &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, ¤t, &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, ¤t, &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, ¤t, &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, ¤t, &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, ¤t, &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, ¤t, &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, ¤t, &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