1 /* GStreamer
2 * Copyright (C) 2005 Thomas Vander Stichele <thomas at apestaart dot org>
3 *
4 * gstpipeline.c: Unit test for GstPipeline
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <gst/check/gstcheck.h>
26 #include <gst/gst.h>
27 #include <gst/check/gsttestclock.h>
28
29 /* an empty pipeline can go to PLAYING in one go */
GST_START_TEST(test_async_state_change_empty)30 GST_START_TEST (test_async_state_change_empty)
31 {
32 GstPipeline *pipeline;
33
34 pipeline = GST_PIPELINE (gst_pipeline_new (NULL));
35 fail_unless (pipeline != NULL, "Could not create pipeline");
36
37 fail_unless_equals_int (gst_element_set_state (GST_ELEMENT (pipeline),
38 GST_STATE_PLAYING), GST_STATE_CHANGE_SUCCESS);
39
40 gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
41 gst_object_unref (pipeline);
42 }
43
44 GST_END_TEST;
45
GST_START_TEST(test_async_state_change_fake_ready)46 GST_START_TEST (test_async_state_change_fake_ready)
47 {
48 GstPipeline *pipeline;
49 GstElement *src, *sink;
50
51 pipeline = GST_PIPELINE (gst_pipeline_new (NULL));
52 fail_unless (pipeline != NULL, "Could not create pipeline");
53
54 src = gst_element_factory_make ("fakesrc", NULL);
55 sink = gst_element_factory_make ("fakesink", NULL);
56
57 gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);
58 gst_element_link (src, sink);
59
60 fail_unless_equals_int (gst_element_set_state (GST_ELEMENT (pipeline),
61 GST_STATE_READY), GST_STATE_CHANGE_SUCCESS);
62
63 gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
64 gst_object_unref (pipeline);
65 }
66
67 GST_END_TEST;
68
GST_START_TEST(test_async_state_change_fake)69 GST_START_TEST (test_async_state_change_fake)
70 {
71 GstPipeline *pipeline;
72 GstElement *src, *sink;
73 GstBus *bus;
74 gboolean done = FALSE;
75
76 pipeline = GST_PIPELINE (gst_pipeline_new (NULL));
77 fail_unless (pipeline != NULL, "Could not create pipeline");
78
79 src = gst_element_factory_make ("fakesrc", NULL);
80 sink = gst_element_factory_make ("fakesink", NULL);
81
82 gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);
83 gst_element_link (src, sink);
84
85 bus = gst_pipeline_get_bus (pipeline);
86
87 fail_unless_equals_int (gst_element_set_state (GST_ELEMENT (pipeline),
88 GST_STATE_PLAYING), GST_STATE_CHANGE_ASYNC);
89
90 while (!done) {
91 GstMessage *message;
92 GstState old, new, pending;
93
94 message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1);
95 if (message) {
96 gst_message_parse_state_changed (message, &old, &new, &pending);
97 GST_DEBUG_OBJECT (message->src, "state change from %d to %d", old, new);
98 if (message->src == GST_OBJECT (pipeline) && new == GST_STATE_PLAYING)
99 done = TRUE;
100 gst_message_unref (message);
101 }
102 }
103
104 fail_unless_equals_int (gst_element_set_state (GST_ELEMENT (pipeline),
105 GST_STATE_NULL), GST_STATE_CHANGE_SUCCESS);
106
107 /* here we don't get the state change messages, because of auto-flush in
108 * the bus */
109
110 gst_object_unref (bus);
111 gst_object_unref (pipeline);
112 }
113
114 GST_END_TEST;
115
GST_START_TEST(test_get_bus)116 GST_START_TEST (test_get_bus)
117 {
118 GstPipeline *pipeline;
119 GstBus *bus;
120
121 pipeline = GST_PIPELINE (gst_pipeline_new (NULL));
122 fail_unless (pipeline != NULL, "Could not create pipeline");
123 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
124
125 bus = gst_pipeline_get_bus (pipeline);
126 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline after get_bus", 1);
127 ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
128
129 /* bindings don't like the floating flag to be set here */
130 fail_if (g_object_is_floating (bus));
131
132 gst_object_unref (pipeline);
133
134 ASSERT_OBJECT_REFCOUNT (bus, "bus after unref pipeline", 1);
135 gst_object_unref (bus);
136 }
137
138 GST_END_TEST;
139
140 static GMainLoop *loop = NULL;
141
142 static gboolean
message_received(GstBus * bus,GstMessage * message,gpointer data)143 message_received (GstBus * bus, GstMessage * message, gpointer data)
144 {
145 GstElement *pipeline = GST_ELEMENT (data);
146 GstMessageType type = message->type;
147
148 GST_DEBUG ("message received");
149 switch (type) {
150 case GST_MESSAGE_STATE_CHANGED:
151 {
152 GstState old, new, pending;
153
154 GST_DEBUG ("state change message received");
155 gst_message_parse_state_changed (message, &old, &new, &pending);
156 GST_DEBUG ("new state %d", new);
157 if (message->src == GST_OBJECT (pipeline) && new == GST_STATE_PLAYING) {
158 GST_DEBUG ("quitting main loop");
159 g_main_loop_quit (loop);
160 }
161 }
162 break;
163 case GST_MESSAGE_ERROR:
164 {
165 g_print ("error\n");
166 }
167 break;
168 default:
169 break;
170 }
171
172 return TRUE;
173 }
174
GST_START_TEST(test_bus)175 GST_START_TEST (test_bus)
176 {
177 GstElement *pipeline;
178 GstElement *src, *sink;
179 GstBus *bus;
180 guint id;
181 GstState current;
182 GstStateChangeReturn ret;
183
184 pipeline = gst_pipeline_new (NULL);
185 fail_unless (pipeline != NULL, "Could not create pipeline");
186 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
187
188 src = gst_element_factory_make ("fakesrc", NULL);
189 fail_unless (src != NULL);
190 sink = gst_element_factory_make ("fakesink", NULL);
191 fail_unless (sink != NULL);
192
193 gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);
194 fail_unless (gst_element_link (src, sink));
195
196 bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
197 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline after get_bus", 1);
198 ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
199
200 id = gst_bus_add_watch (bus, message_received, pipeline);
201 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline after add_watch", 1);
202 ASSERT_OBJECT_REFCOUNT (bus, "bus after add_watch", 3);
203
204 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
205 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
206
207 loop = g_main_loop_new (NULL, FALSE);
208 GST_DEBUG ("going into main loop");
209 g_main_loop_run (loop);
210 GST_DEBUG ("left main loop");
211
212 /* PLAYING now */
213
214 ASSERT_OBJECT_REFCOUNT_BETWEEN (pipeline, "pipeline after gone to playing", 1,
215 3);
216
217 /* cleanup */
218 GST_DEBUG ("cleanup");
219
220 ret = gst_element_set_state (pipeline, GST_STATE_NULL);
221 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
222 ret = gst_element_get_state (pipeline, ¤t, NULL, GST_CLOCK_TIME_NONE);
223 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
224 fail_unless (current == GST_STATE_NULL, "state is not NULL but %d", current);
225
226 /* We have to ensure that all background threads from thread pools are shut
227 * down, or otherwise they might not have had a chance yet to drop
228 * their last reference to the pipeline and then the assertion below fails
229 */
230 gst_task_cleanup_all ();
231
232 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline at start of cleanup", 1);
233 ASSERT_OBJECT_REFCOUNT (bus, "bus at start of cleanup", 3);
234
235 fail_unless (g_source_remove (id));
236 ASSERT_OBJECT_REFCOUNT (bus, "bus after removing source", 2);
237
238 GST_DEBUG ("unreffing pipeline");
239 gst_object_unref (pipeline);
240
241 ASSERT_OBJECT_REFCOUNT (bus, "bus after unref pipeline", 1);
242 gst_object_unref (bus);
243 }
244
245 GST_END_TEST;
246
GST_START_TEST(test_base_time)247 GST_START_TEST (test_base_time)
248 {
249 GstElement *pipeline, *fakesrc, *fakesink;
250 GstClockTime base, start;
251 gint64 position;
252 GstClock *clock;
253
254 clock = gst_test_clock_new ();
255 gst_test_clock_set_time (GST_TEST_CLOCK (clock), 100 * GST_SECOND);
256
257 pipeline = gst_element_factory_make ("pipeline", "pipeline");
258 fakesrc = gst_element_factory_make ("fakesrc", "fakesrc");
259 fakesink = gst_element_factory_make ("fakesink", "fakesink");
260
261 gst_pipeline_use_clock (GST_PIPELINE (pipeline), clock);
262
263 fail_unless (pipeline && fakesrc && fakesink, "couldn't make elements");
264
265 g_object_set (fakesrc, "is-live", (gboolean) TRUE, "do-timestamp", TRUE,
266 "format", GST_FORMAT_TIME, "sizetype", 2, "sizemax", 4096, "datarate",
267 4096 * 100, NULL);
268 g_object_set (fakesink, "sync", TRUE, NULL);
269
270 gst_bin_add_many (GST_BIN (pipeline), fakesrc, fakesink, NULL);
271 gst_element_link (fakesrc, fakesink);
272
273 fail_unless (gst_element_set_state (pipeline, GST_STATE_PAUSED)
274 == GST_STATE_CHANGE_NO_PREROLL, "expected no-preroll from live pipeline");
275
276 fail_unless_equals_uint64 (gst_element_get_start_time (pipeline), 0);
277
278 /* test the first: that base time is being distributed correctly, timestamps
279 are correct relative to the running clock and base time */
280 {
281 gst_element_set_state (pipeline, GST_STATE_PLAYING);
282 fail_unless (gst_element_get_state (pipeline, NULL, NULL,
283 GST_CLOCK_TIME_NONE)
284 == GST_STATE_CHANGE_SUCCESS, "failed state change");
285
286 /* Wait for time for 1s to pass */
287 for (;;) {
288 gst_test_clock_wait_for_next_pending_id (GST_TEST_CLOCK (clock), NULL);
289 if (gst_test_clock_get_next_entry_time (GST_TEST_CLOCK (clock)) >
290 101 * GST_SECOND)
291 break;
292 gst_test_clock_crank (GST_TEST_CLOCK (clock));
293 }
294
295 /* Now the base time should be exactly the clock time when we start and the
296 * position should be at 1s because we waited 1s */
297 base = gst_element_get_base_time (pipeline);
298 fail_unless_equals_uint64 (base, 100 * GST_SECOND);
299
300 fail_unless (gst_element_query_position (fakesink, GST_FORMAT_TIME,
301 &position));
302 fail_unless_equals_uint64 (position, 1 * GST_SECOND);
303
304 /* wait for another 1s of buffers to pass */
305 for (;;) {
306 gst_test_clock_wait_for_next_pending_id (GST_TEST_CLOCK (clock), NULL);
307 if (gst_test_clock_get_next_entry_time (GST_TEST_CLOCK (clock)) >
308 102 * GST_SECOND)
309 break;
310 gst_test_clock_crank (GST_TEST_CLOCK (clock));
311 }
312
313 /* set start time by pausing */
314 gst_element_set_state (pipeline, GST_STATE_PAUSED);
315
316 fail_unless (gst_element_get_state (pipeline, NULL, NULL,
317 GST_CLOCK_TIME_NONE)
318 == GST_STATE_CHANGE_NO_PREROLL, "failed state change");
319
320 start = gst_element_get_start_time (pipeline);
321 /* start time should be exactly 2s as that much time advanced, it's
322 * the current running time */
323 fail_unless_equals_uint64 (start, 2 * GST_SECOND);
324
325 fail_unless (gst_element_query_position (fakesink, GST_FORMAT_TIME,
326 &position));
327 fail_unless_equals_uint64 (position, 2 * GST_SECOND);
328 }
329
330 /* test the second: that the base time is redistributed when we go to PLAYING
331 again */
332 {
333 /* Set time to 99s in the future */
334 gst_test_clock_set_time (GST_TEST_CLOCK (clock), 200 * GST_SECOND);
335
336 gst_element_set_state (pipeline, GST_STATE_PLAYING);
337 fail_unless (gst_element_get_state (pipeline, NULL, NULL,
338 GST_CLOCK_TIME_NONE)
339 == GST_STATE_CHANGE_SUCCESS, "failed state change");
340
341 /* wait for 1s of buffers to pass */
342 for (;;) {
343 gst_test_clock_wait_for_next_pending_id (GST_TEST_CLOCK (clock), NULL);
344 if (gst_test_clock_get_next_entry_time (GST_TEST_CLOCK (clock)) >
345 201 * GST_SECOND)
346 break;
347 gst_test_clock_crank (GST_TEST_CLOCK (clock));
348 }
349
350 /* now the base time should have advanced by 98s compared to what it was
351 * before (we played 2s between previous and current play and 100s passed) */
352 base = gst_element_get_base_time (pipeline);
353 fail_unless_equals_uint64 (base, 198 * GST_SECOND);
354
355 /* wait for 1s of buffers to pass */
356 for (;;) {
357 gst_test_clock_wait_for_next_pending_id (GST_TEST_CLOCK (clock), NULL);
358 if (gst_test_clock_get_next_entry_time (GST_TEST_CLOCK (clock)) >
359 202 * GST_SECOND)
360 break;
361 gst_test_clock_crank (GST_TEST_CLOCK (clock));
362 }
363
364 /* set start time by pausing */
365 gst_element_set_state (pipeline, GST_STATE_PAUSED);
366 fail_unless (gst_element_get_state (pipeline, NULL, NULL,
367 GST_CLOCK_TIME_NONE)
368 == GST_STATE_CHANGE_NO_PREROLL, "failed state change");
369
370 /* start time should now be 4s as that's the amount of time that has
371 * passed since we started until we paused above */
372 start = gst_element_get_start_time (pipeline);
373 fail_unless_equals_uint64 (start, 4 * GST_SECOND);
374
375 fail_unless (gst_element_query_position (fakesink, GST_FORMAT_TIME,
376 &position));
377 fail_unless_equals_uint64 (position, 4 * GST_SECOND);
378 }
379
380 /* test the third: that if I set CLOCK_TIME_NONE as the stream time, that the
381 base time is not changed */
382 {
383 GstClockTime oldbase;
384
385 /* bling */
386 oldbase = gst_element_get_base_time (pipeline);
387 gst_element_set_start_time (pipeline, GST_CLOCK_TIME_NONE);
388
389 gst_element_set_state (pipeline, GST_STATE_PLAYING);
390 fail_unless (gst_element_get_state (pipeline, NULL, NULL,
391 GST_CLOCK_TIME_NONE)
392 == GST_STATE_CHANGE_SUCCESS, "failed state change");
393
394 /* wait for 1s of buffers to pass */
395 for (;;) {
396 gst_test_clock_wait_for_next_pending_id (GST_TEST_CLOCK (clock), NULL);
397 if (gst_test_clock_get_next_entry_time (GST_TEST_CLOCK (clock)) >
398 203 * GST_SECOND)
399 break;
400 gst_test_clock_crank (GST_TEST_CLOCK (clock));
401 }
402
403 /* now the base time should be the same as it was */
404
405 base = gst_element_get_base_time (pipeline);
406
407 /* wait for 1s of buffers to pass */
408 for (;;) {
409 gst_test_clock_wait_for_next_pending_id (GST_TEST_CLOCK (clock), NULL);
410 if (gst_test_clock_get_next_entry_time (GST_TEST_CLOCK (clock)) >
411 204 * GST_SECOND)
412 break;
413 gst_test_clock_crank (GST_TEST_CLOCK (clock));
414 }
415
416 /* set start time by pausing */
417 gst_element_set_state (pipeline, GST_STATE_PAUSED);
418
419 fail_unless (gst_element_get_state (pipeline, NULL, NULL,
420 GST_CLOCK_TIME_NONE)
421 == GST_STATE_CHANGE_NO_PREROLL, "failed state change");
422
423 fail_unless (gst_element_get_start_time (pipeline)
424 == GST_CLOCK_TIME_NONE, "stream time was reset");
425
426 fail_unless (base == oldbase, "base time was reset");
427 }
428
429 gst_element_set_state (pipeline, GST_STATE_NULL);
430
431 gst_object_unref (pipeline);
432 gst_object_unref (clock);
433 }
434
435 GST_END_TEST;
436
437 static gpointer
pipeline_thread(gpointer data)438 pipeline_thread (gpointer data)
439 {
440 GstElement *pipeline, *src, *sink;
441
442 src = gst_element_factory_make ("fakesrc", NULL);
443 g_object_set (src, "num-buffers", 20, NULL);
444 sink = gst_element_factory_make ("fakesink", NULL);
445 g_object_set (sink, "sync", TRUE, NULL);
446 pipeline = gst_pipeline_new (NULL);
447 gst_bin_add (GST_BIN (pipeline), src);
448 gst_bin_add (GST_BIN (pipeline), sink);
449 gst_element_link (src, sink);
450 gst_element_set_state (pipeline, GST_STATE_PLAYING);
451 g_usleep (G_USEC_PER_SEC / 10);
452 gst_element_set_state (pipeline, GST_STATE_NULL);
453 gst_object_unref (pipeline);
454 return NULL;
455 }
456
GST_START_TEST(test_concurrent_create)457 GST_START_TEST (test_concurrent_create)
458 {
459 GThread *threads[30];
460 int i;
461
462 for (i = 0; i < G_N_ELEMENTS (threads); ++i) {
463 threads[i] = g_thread_try_new ("gst-check", pipeline_thread, NULL, NULL);
464 }
465 for (i = 0; i < G_N_ELEMENTS (threads); ++i) {
466 if (threads[i])
467 g_thread_join (threads[i]);
468 }
469 }
470
471 GST_END_TEST;
472
GST_START_TEST(test_pipeline_in_pipeline)473 GST_START_TEST (test_pipeline_in_pipeline)
474 {
475 GstElement *pipeline, *bin, *fakesrc, *fakesink;
476 GstMessage *msg;
477
478 pipeline = gst_element_factory_make ("pipeline", "pipeline");
479 bin = gst_element_factory_make ("pipeline", "pipeline-as-bin");
480 fakesrc = gst_element_factory_make ("fakesrc", "fakesrc");
481 fakesink = gst_element_factory_make ("fakesink", "fakesink");
482
483 fail_unless (pipeline && bin && fakesrc && fakesink);
484
485 g_object_set (fakesrc, "num-buffers", 100, NULL);
486
487 gst_bin_add (GST_BIN (pipeline), bin);
488 gst_bin_add_many (GST_BIN (bin), fakesrc, fakesink, NULL);
489 gst_element_link (fakesrc, fakesink);
490
491 fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING),
492 GST_STATE_CHANGE_ASYNC);
493
494 msg = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipeline), -1,
495 GST_MESSAGE_EOS);
496 gst_message_unref (msg);
497
498 gst_element_set_state (pipeline, GST_STATE_NULL);
499
500 gst_object_unref (pipeline);
501 }
502
503 GST_END_TEST;
504
GST_START_TEST(test_pipeline_reset_start_time)505 GST_START_TEST (test_pipeline_reset_start_time)
506 {
507 GstElement *pipeline, *fakesrc, *fakesink;
508 GstState state;
509 GstClock *clock;
510 gint64 position;
511
512 clock = gst_test_clock_new ();
513 pipeline = gst_element_factory_make ("pipeline", "pipeline");
514 fakesrc = gst_element_factory_make ("fakesrc", "fakesrc");
515 fakesink = gst_element_factory_make ("fakesink", "fakesink");
516
517 gst_pipeline_use_clock (GST_PIPELINE (pipeline), clock);
518
519 /* no more than 100 buffers per second */
520 g_object_set (fakesrc, "do-timestamp", TRUE, "format", GST_FORMAT_TIME,
521 "sizetype", 2, "sizemax", 4096, "datarate", 4096 * 100, NULL);
522
523 g_object_set (fakesink, "sync", TRUE, NULL);
524
525 fail_unless (pipeline && fakesrc && fakesink);
526
527 gst_bin_add_many (GST_BIN (pipeline), fakesrc, fakesink, NULL);
528 gst_element_link (fakesrc, fakesink);
529
530 fail_unless (gst_element_get_start_time (fakesink) == 0);
531
532 fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING),
533 GST_STATE_CHANGE_ASYNC);
534 fail_unless_equals_int (gst_element_get_state (pipeline, &state, NULL, -1),
535 GST_STATE_CHANGE_SUCCESS);
536 fail_unless_equals_int (state, GST_STATE_PLAYING);
537
538 /* We just started and never paused, start time must be 0 */
539 fail_unless (gst_element_get_start_time (fakesink) == 0);
540
541 /* Wait for time to reach 50 msecs */
542 for (;;) {
543 gst_test_clock_wait_for_next_pending_id (GST_TEST_CLOCK (clock), NULL);
544 if (gst_test_clock_get_next_entry_time (GST_TEST_CLOCK (clock)) >
545 50 * GST_MSECOND)
546 break;
547 gst_test_clock_crank (GST_TEST_CLOCK (clock));
548 }
549
550 /* We waited 50ms, so the position should be now == 50ms */
551 fail_unless (gst_element_query_position (fakesink, GST_FORMAT_TIME,
552 &position));
553 fail_unless_equals_uint64 (position, 50 * GST_MSECOND);
554
555 fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PAUSED),
556 GST_STATE_CHANGE_ASYNC);
557 fail_unless_equals_int (gst_element_get_state (pipeline, &state, NULL, -1),
558 GST_STATE_CHANGE_SUCCESS);
559 fail_unless_equals_int (state, GST_STATE_PAUSED);
560
561 /* And now after pausing the start time should be bigger than the last
562 * position */
563 fail_unless_equals_uint64 (gst_element_get_start_time (fakesink),
564 50 * GST_MSECOND);
565 fail_unless (gst_element_query_position (fakesink, GST_FORMAT_TIME,
566 &position));
567 fail_unless_equals_uint64 (position, 50 * GST_MSECOND);
568
569 fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_READY),
570 GST_STATE_CHANGE_SUCCESS);
571
572 /* When going back to ready the start time should be reset everywhere */
573 fail_unless (gst_element_get_start_time (fakesink) == 0);
574
575 fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PAUSED),
576 GST_STATE_CHANGE_ASYNC);
577 fail_unless_equals_int (gst_element_get_state (pipeline, &state, NULL, -1),
578 GST_STATE_CHANGE_SUCCESS);
579 fail_unless_equals_int (state, GST_STATE_PAUSED);
580
581 /* And the start time should still be set to 0 when we go to paused for the
582 * first time. Same goes for the position */
583 fail_unless (gst_element_query_position (fakesink, GST_FORMAT_TIME,
584 &position));
585 fail_unless_equals_uint64 (position, 0 * GST_MSECOND);
586
587 fail_unless (gst_element_get_start_time (fakesink) == 0);
588
589 gst_element_set_state (pipeline, GST_STATE_NULL);
590
591 gst_object_unref (pipeline);
592 gst_object_unref (clock);
593 }
594
595 GST_END_TEST;
596
GST_START_TEST(test_pipeline_processing_deadline)597 GST_START_TEST (test_pipeline_processing_deadline)
598 {
599 GstElement *pipeline, *fakesrc, *queue, *fakesink;
600 GstState state;
601 GstClock *clock;
602 gint64 position;
603 GstQuery *q;
604 gboolean live;
605 GstClockTime min, max;
606 GstBus *bus;
607 GstMessage *msg;
608
609 clock = gst_test_clock_new ();
610 pipeline = gst_element_factory_make ("pipeline", "pipeline");
611 fakesrc = gst_element_factory_make ("fakesrc", "fakesrc");
612 queue = gst_element_factory_make ("queue", "queue");
613 fakesink = gst_element_factory_make ("fakesink", "fakesink");
614
615 gst_pipeline_use_clock (GST_PIPELINE (pipeline), clock);
616
617 /* no more than 100 buffers per second */
618 g_object_set (fakesrc, "do-timestamp", TRUE, "format", GST_FORMAT_TIME,
619 "sizetype", 2, "sizemax", 4096, "datarate", 4096 * 100, "is-live", TRUE,
620 NULL);
621
622 g_object_set (fakesink, "sync", TRUE, NULL);
623
624 fail_unless (pipeline && fakesrc && queue && fakesink);
625
626 gst_bin_add_many (GST_BIN (pipeline), fakesrc, queue, fakesink, NULL);
627 gst_element_link_many (fakesrc, queue, fakesink, NULL);
628
629 gst_element_set_state (pipeline, GST_STATE_PLAYING);
630 fail_unless_equals_int (gst_element_get_state (pipeline, &state, NULL, -1),
631 GST_STATE_CHANGE_SUCCESS);
632 fail_unless_equals_int (state, GST_STATE_PLAYING);
633
634 q = gst_query_new_latency ();
635 fail_unless (gst_element_query (pipeline, q));
636 gst_query_parse_latency (q, &live, &min, &max);
637 fail_unless (live == TRUE);
638 fail_unless (min == 20 * GST_MSECOND);
639 fail_unless (max >= min);
640 gst_query_unref (q);
641
642 /* Wait for time to reach 50 msecs */
643 for (;;) {
644 gst_test_clock_wait_for_next_pending_id (GST_TEST_CLOCK (clock), NULL);
645 if (gst_test_clock_get_next_entry_time (GST_TEST_CLOCK (clock)) >
646 50 * GST_MSECOND)
647 break;
648 gst_test_clock_crank (GST_TEST_CLOCK (clock));
649 }
650
651 /* We waited 50ms, but the position should be 50ms - 20ms latency == 30ms */
652 fail_unless (gst_element_query_position (fakesink, GST_FORMAT_TIME,
653 &position));
654 fail_unless_equals_uint64 (position, 30 * GST_MSECOND);
655
656 fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PAUSED),
657 GST_STATE_CHANGE_NO_PREROLL);
658 fail_unless_equals_int (gst_element_get_state (pipeline, &state, NULL, -1),
659 GST_STATE_CHANGE_NO_PREROLL);
660 fail_unless_equals_int (state, GST_STATE_PAUSED);
661
662 /* And now after pausing the start time should be exactly 50ms */
663 fail_unless_equals_uint64 (gst_element_get_start_time (fakesink),
664 50 * GST_MSECOND);
665 fail_unless (gst_element_query_position (fakesink, GST_FORMAT_TIME,
666 &position));
667 /* but position should still be exactly 50ms - 20ms latency == 30ms */
668 fail_unless_equals_uint64 (position, 30 * GST_MSECOND);
669
670 fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_READY),
671 GST_STATE_CHANGE_SUCCESS);
672
673 fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PAUSED),
674 GST_STATE_CHANGE_NO_PREROLL);
675 fail_unless_equals_int (gst_element_get_state (pipeline, &state, NULL, -1),
676 GST_STATE_CHANGE_NO_PREROLL);
677 fail_unless_equals_int (state, GST_STATE_PAUSED);
678
679 bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
680 msg = gst_bus_pop_filtered (bus, GST_MESSAGE_WARNING);
681 fail_unless (msg == NULL);
682 gst_object_unref (bus);
683
684 gst_element_set_state (pipeline, GST_STATE_NULL);
685
686 gst_object_unref (pipeline);
687 gst_object_unref (clock);
688 }
689
690 GST_END_TEST;
691
692
GST_START_TEST(test_pipeline_processing_deadline_no_queue)693 GST_START_TEST (test_pipeline_processing_deadline_no_queue)
694 {
695 GstElement *pipeline, *fakesrc, *fakesink;
696 GstState state;
697 GstBus *bus;
698 GstMessage *msg;
699 GError *gerror = NULL;
700
701 pipeline = gst_element_factory_make ("pipeline", "pipeline");
702 fakesrc = gst_element_factory_make ("fakesrc", "fakesrc");
703 fakesink = gst_element_factory_make ("fakesink", "fakesink");
704
705 /* no more than 100 buffers per second */
706 g_object_set (fakesrc, "do-timestamp", TRUE, "format", GST_FORMAT_TIME,
707 "sizetype", 2, "sizemax", 4096, "datarate", 4096 * 100, "is-live", TRUE,
708 NULL);
709
710 g_object_set (fakesink, "sync", TRUE, "processing-deadline", 60 * GST_MSECOND,
711 NULL);
712
713 fail_unless (pipeline && fakesrc && fakesink);
714
715 gst_bin_add_many (GST_BIN (pipeline), fakesrc, fakesink, NULL);
716 gst_element_link (fakesrc, fakesink);
717
718 fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING),
719 GST_STATE_CHANGE_ASYNC);
720 fail_unless_equals_int (gst_element_get_state (pipeline, &state, NULL, -1),
721 GST_STATE_CHANGE_SUCCESS);
722
723 bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
724 msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
725 GST_MESSAGE_WARNING);
726 fail_unless (msg != NULL);
727 gst_message_parse_warning (msg, &gerror, NULL);
728 fail_unless (g_error_matches (gerror, GST_CORE_ERROR, GST_CORE_ERROR_CLOCK));
729 gst_message_unref (msg);
730 gst_object_unref (bus);
731 g_clear_error (&gerror);
732
733 gst_element_set_state (pipeline, GST_STATE_NULL);
734
735 gst_object_unref (pipeline);
736 }
737
738 GST_END_TEST;
739
740
741 static Suite *
gst_pipeline_suite(void)742 gst_pipeline_suite (void)
743 {
744 Suite *s = suite_create ("GstPipeline");
745 TCase *tc_chain = tcase_create ("pipeline tests");
746
747 tcase_set_timeout (tc_chain, 0);
748
749 suite_add_tcase (s, tc_chain);
750 tcase_add_test (tc_chain, test_async_state_change_empty);
751 tcase_add_test (tc_chain, test_async_state_change_fake_ready);
752 tcase_add_test (tc_chain, test_async_state_change_fake);
753 tcase_add_test (tc_chain, test_get_bus);
754 tcase_add_test (tc_chain, test_bus);
755 tcase_add_test (tc_chain, test_base_time);
756 tcase_add_test (tc_chain, test_concurrent_create);
757 tcase_add_test (tc_chain, test_pipeline_in_pipeline);
758 tcase_add_test (tc_chain, test_pipeline_reset_start_time);
759 tcase_add_test (tc_chain, test_pipeline_processing_deadline);
760 tcase_add_test (tc_chain, test_pipeline_processing_deadline_no_queue);
761
762 return s;
763 }
764
765 GST_CHECK_MAIN (gst_pipeline);
766