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, &current, 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