2 * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
3 * Copyright (C) 2005 Thomas Vander Stichele <thomas at apestaart dot org>
5 * gstbin.c: Unit test for GstBin
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
23 #include <gst/check/gstcheck.h>
26 pop_messages (GstBus * bus, int count)
32 GST_DEBUG ("popping %d messages", count);
33 for (i = 0; i < count; ++i) {
34 message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1);
36 fail_unless (message && GST_MESSAGE_TYPE (message)
37 == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED");
39 gst_message_unref (message);
41 GST_DEBUG ("popped %d messages", count);
44 GST_START_TEST (test_interface)
51 bin = GST_BIN (gst_bin_new (NULL));
52 fail_unless (bin != NULL, "Could not create bin");
54 filesrc = gst_element_factory_make ("filesrc", NULL);
55 fail_unless (filesrc != NULL, "Could not create filesrc");
56 fail_unless (GST_IS_URI_HANDLER (filesrc), "Filesrc not a URI handler");
57 gst_bin_add (bin, filesrc);
59 fail_unless (gst_bin_get_by_interface (bin, GST_TYPE_URI_HANDLER) == filesrc);
60 it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
61 fail_unless (it != NULL);
62 fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
63 fail_unless (item == (gpointer) filesrc);
64 fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
65 gst_iterator_free (it);
67 gst_bin_add_many (bin,
68 gst_element_factory_make ("identity", NULL),
69 gst_element_factory_make ("identity", NULL),
70 gst_element_factory_make ("identity", NULL), NULL);
71 fail_unless (gst_bin_get_by_interface (bin, GST_TYPE_URI_HANDLER) == filesrc);
72 it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
73 fail_unless (it != NULL);
74 fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
75 fail_unless (item == (gpointer) filesrc);
76 fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
77 gst_iterator_free (it);
80 bin = GST_BIN (gst_bin_new (NULL));
81 fail_unless (bin != NULL);
82 gst_bin_add_many (bin,
83 gst_element_factory_make ("identity", NULL),
84 gst_element_factory_make ("identity", NULL),
85 GST_ELEMENT (bin2), gst_element_factory_make ("identity", NULL), NULL);
86 fail_unless (gst_bin_get_by_interface (bin, GST_TYPE_URI_HANDLER) == filesrc);
87 it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
88 fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
89 fail_unless (item == (gpointer) filesrc);
90 fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
91 gst_iterator_free (it);
93 gst_bin_add (bin, gst_element_factory_make ("filesrc", NULL));
94 gst_bin_add (bin2, gst_element_factory_make ("filesrc", NULL));
95 it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
96 fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
97 fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
98 fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
99 fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
100 gst_iterator_free (it);
102 gst_object_unref (bin);
107 GST_START_TEST (test_message_state_changed)
112 GstStateChangeReturn ret;
114 bin = GST_BIN (gst_bin_new (NULL));
115 fail_unless (bin != NULL, "Could not create bin");
116 ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
118 bus = g_object_new (gst_bus_get_type (), NULL);
119 gst_element_set_bus (GST_ELEMENT_CAST (bin), bus);
121 /* change state, spawning a message, causing an incref on the bin */
122 ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_READY);
123 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
125 ASSERT_OBJECT_REFCOUNT (bin, "bin", 2);
127 /* get and unref the message, causing a decref on the bin */
128 message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1);
130 fail_unless (message && GST_MESSAGE_TYPE (message)
131 == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED");
133 gst_message_unref (message);
135 ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
138 ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
139 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
141 gst_object_unref (bus);
142 gst_object_unref (bin);
147 GST_START_TEST (test_message_state_changed_child)
153 GstStateChangeReturn ret;
155 bin = GST_BIN (gst_bin_new (NULL));
156 fail_unless (bin != NULL, "Could not create bin");
157 ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
159 bus = g_object_new (gst_bus_get_type (), NULL);
160 gst_element_set_bus (GST_ELEMENT_CAST (bin), bus);
162 src = gst_element_factory_make ("fakesrc", NULL);
163 fail_if (src == NULL, "Could not create fakesrc");
164 gst_bin_add (bin, src);
165 ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
166 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
168 /* change state, spawning two messages:
169 * - first for fakesrc, forwarded to bin's bus, causing incref on fakesrc
170 * - second for bin, causing an incref on the bin */
171 GST_DEBUG ("setting bin to READY");
172 ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_READY);
173 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
175 ASSERT_OBJECT_REFCOUNT (src, "src", 2);
176 ASSERT_OBJECT_REFCOUNT (bin, "bin", 2);
178 /* get and unref the message, causing a decref on the src */
179 message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1);
180 fail_unless (message && GST_MESSAGE_TYPE (message)
181 == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED");
183 fail_unless (message->src == GST_OBJECT (src));
184 gst_message_unref (message);
186 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
187 ASSERT_OBJECT_REFCOUNT (bin, "bin", 2);
189 /* get and unref message 2, causing a decref on the bin */
190 message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1);
191 fail_unless (message && GST_MESSAGE_TYPE (message)
192 == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED");
194 fail_unless (message->src == GST_OBJECT (bin));
195 gst_message_unref (message);
197 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
198 ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
201 ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
202 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
203 gst_object_unref (bus);
204 gst_object_unref (bin);
209 GST_START_TEST (test_message_state_changed_children)
211 GstPipeline *pipeline;
212 GstElement *src, *sink;
214 GstStateChangeReturn ret;
215 GstState current, pending;
217 pipeline = GST_PIPELINE (gst_pipeline_new (NULL));
218 fail_unless (pipeline != NULL, "Could not create pipeline");
219 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
221 src = gst_element_factory_make ("fakesrc", NULL);
222 fail_if (src == NULL, "Could not create fakesrc");
223 /* need to silence the element as the deep_notify refcounts the
224 * parents while running */
225 g_object_set (G_OBJECT (src), "silent", TRUE, NULL);
226 gst_bin_add (GST_BIN (pipeline), src);
228 sink = gst_element_factory_make ("fakesink", NULL);
229 /* need to silence the element as the deep_notify refcounts the
230 * parents while running */
231 g_object_set (G_OBJECT (sink), "silent", TRUE, NULL);
232 fail_if (sink == NULL, "Could not create fakesink");
233 gst_bin_add (GST_BIN (pipeline), sink);
235 fail_unless (gst_element_link (src, sink), "could not link src and sink");
237 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
238 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
239 ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
241 bus = gst_pipeline_get_bus (pipeline);
243 /* change state to READY, spawning three messages */
244 GST_DEBUG ("setting pipeline to READY");
245 ret = gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_READY);
246 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
248 /* each object is referenced by a message */
249 ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
250 ASSERT_OBJECT_REFCOUNT (src, "src", 2);
251 ASSERT_OBJECT_REFCOUNT (sink, "sink", 2);
252 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 2);
254 pop_messages (bus, 3);
255 fail_if ((gst_bus_pop (bus)) != NULL);
257 ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
258 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
259 ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
260 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
262 /* change state to PAUSED, spawning three messages */
263 GST_DEBUG ("setting pipeline to PAUSED");
264 ret = gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED);
265 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
267 gst_element_get_state (GST_ELEMENT (pipeline), ¤t, &pending,
268 GST_CLOCK_TIME_NONE);
269 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
270 fail_unless (current == GST_STATE_PAUSED);
271 fail_unless (pending == GST_STATE_VOID_PENDING);
273 /* each object is referenced by a message;
274 * base_sink_chain has taken a refcount on the sink, and is blocked on
276 ASSERT_OBJECT_REFCOUNT (src, "src", 2);
277 ASSERT_OBJECT_REFCOUNT (sink, "sink", 3);
278 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 2);
280 pop_messages (bus, 3);
281 fail_if ((gst_bus_pop (bus)) != NULL);
283 ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
284 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
285 ASSERT_OBJECT_REFCOUNT (sink, "sink", 2);
286 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
288 /* change state to PLAYING, spawning three messages */
289 GST_DEBUG ("setting pipeline to PLAYING");
290 ret = gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
291 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
293 gst_element_get_state (GST_ELEMENT (pipeline), ¤t, &pending,
294 GST_CLOCK_TIME_NONE);
295 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
296 fail_unless (current == GST_STATE_PLAYING);
297 fail_unless (pending == GST_STATE_VOID_PENDING);
299 /* each object is referenced by one message
300 * sink might have an extra reference if it's still blocked on preroll
301 * pipeline posted a new-clock message too. */
302 ASSERT_OBJECT_REFCOUNT (src, "src", 2);
303 ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 2, 3);
304 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 3);
306 pop_messages (bus, 3);
307 fail_if ((gst_bus_pop (bus)) != NULL);
309 ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
310 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
311 /* sink might have an extra reference if it's still blocked on preroll */
312 ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 1, 2);
313 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
315 /* go back to READY, spawning six messages */
316 GST_DEBUG ("setting pipeline to READY");
317 ret = gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_READY);
318 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
320 /* each object is referenced by two messages */
321 ASSERT_OBJECT_REFCOUNT (src, "src", 3);
322 ASSERT_OBJECT_REFCOUNT (sink, "sink", 3);
323 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 3);
325 pop_messages (bus, 6);
326 fail_if ((gst_bus_pop (bus)) != NULL);
328 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
329 ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
330 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
332 /* setting pipeline to NULL flushes the bus automatically */
333 ret = gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
334 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
336 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
337 ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
338 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
341 gst_object_unref (bus);
342 gst_object_unref (pipeline);
347 GST_START_TEST (test_watch_for_state_change)
349 GstElement *src, *sink, *bin;
351 GstStateChangeReturn ret;
353 bin = gst_element_factory_make ("bin", NULL);
354 fail_unless (bin != NULL, "Could not create bin");
356 bus = g_object_new (gst_bus_get_type (), NULL);
357 gst_element_set_bus (GST_ELEMENT_CAST (bin), bus);
359 src = gst_element_factory_make ("fakesrc", NULL);
360 fail_if (src == NULL, "Could not create fakesrc");
361 sink = gst_element_factory_make ("fakesink", NULL);
362 fail_if (sink == NULL, "Could not create fakesink");
364 gst_bin_add (GST_BIN (bin), sink);
365 gst_bin_add (GST_BIN (bin), src);
367 fail_unless (gst_element_link (src, sink), "could not link src and sink");
369 /* change state, spawning two times three messages */
370 ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED);
371 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
373 gst_element_get_state (GST_ELEMENT (bin), NULL, NULL,
374 GST_CLOCK_TIME_NONE);
375 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
377 pop_messages (bus, 6);
379 fail_unless (gst_bus_have_pending (bus) == FALSE,
380 "Unexpected messages on bus");
382 ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING);
383 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
385 pop_messages (bus, 3);
387 /* this one might return either SUCCESS or ASYNC, likely SUCCESS */
388 gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED);
389 gst_element_get_state (GST_ELEMENT (bin), NULL, NULL, GST_CLOCK_TIME_NONE);
391 pop_messages (bus, 3);
393 fail_unless (gst_bus_have_pending (bus) == FALSE,
394 "Unexpected messages on bus");
396 /* setting bin to NULL flushes the bus automatically */
397 ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
398 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
401 gst_object_unref (bus);
402 gst_object_unref (bin);
407 /* adding an element with linked pads to a bin unlinks the
409 GST_START_TEST (test_add_linked)
411 GstElement *src, *sink;
412 GstPad *srcpad, *sinkpad;
413 GstElement *pipeline;
415 pipeline = gst_pipeline_new (NULL);
416 fail_unless (pipeline != NULL, "Could not create pipeline");
418 src = gst_element_factory_make ("fakesrc", NULL);
419 fail_if (src == NULL, "Could not create fakesrc");
420 sink = gst_element_factory_make ("fakesink", NULL);
421 fail_if (sink == NULL, "Could not create fakesink");
423 srcpad = gst_element_get_pad (src, "src");
424 fail_unless (srcpad != NULL);
425 sinkpad = gst_element_get_pad (sink, "sink");
426 fail_unless (sinkpad != NULL);
428 fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK);
430 /* pads are linked now */
431 fail_unless (gst_pad_is_linked (srcpad));
432 fail_unless (gst_pad_is_linked (sinkpad));
434 /* adding element to bin voids hierarchy so pads are unlinked */
435 gst_bin_add (GST_BIN (pipeline), src);
437 /* check if pads really are unlinked */
438 fail_unless (!gst_pad_is_linked (srcpad));
439 fail_unless (!gst_pad_is_linked (sinkpad));
441 /* cannot link pads in wrong hierarchy */
442 fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_WRONG_HIERARCHY);
444 /* adding other element to bin as well */
445 gst_bin_add (GST_BIN (pipeline), sink);
447 /* now we can link again */
448 fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK);
450 /* check if pads really are linked */
451 fail_unless (gst_pad_is_linked (srcpad));
452 fail_unless (gst_pad_is_linked (sinkpad));
454 gst_object_unref (srcpad);
455 gst_object_unref (sinkpad);
456 gst_object_unref (pipeline);
461 /* g_print ("%10s: %4d => %4d\n", GST_OBJECT_NAME (msg->src), old, new); */
463 #define ASSERT_STATE_CHANGE_MSG(bus,element,old_state,new_state,num) \
466 GstState old = 0, new = 0, pending = 0; \
467 msg = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND); \
468 fail_if (msg == NULL, "No state change message within 1 second (#" \
469 G_STRINGIFY (num) ")"); \
470 gst_message_parse_state_changed (msg, &old, &new, &pending); \
471 fail_if (msg->src != GST_OBJECT (element), G_STRINGIFY(element) \
472 " should have changed state next (#" G_STRINGIFY (num) ")"); \
473 fail_if (old != old_state || new != new_state, "state change is not " \
474 G_STRINGIFY (old_state) " => " G_STRINGIFY (new_state)); \
475 gst_message_unref (msg); \
478 GST_START_TEST (test_children_state_change_order_flagged_sink)
480 GstElement *src, *identity, *sink, *pipeline;
481 GstStateChangeReturn ret;
482 GstState current, pending;
485 pipeline = gst_pipeline_new (NULL);
486 fail_unless (pipeline != NULL, "Could not create pipeline");
488 bus = gst_element_get_bus (pipeline);
489 fail_unless (bus != NULL, "Pipeline has no bus?!");
491 src = gst_element_factory_make ("fakesrc", NULL);
492 fail_if (src == NULL, "Could not create fakesrc");
494 identity = gst_element_factory_make ("identity", NULL);
495 fail_if (identity == NULL, "Could not create identity");
497 sink = gst_element_factory_make ("fakesink", NULL);
498 fail_if (sink == NULL, "Could not create fakesink");
500 gst_bin_add_many (GST_BIN (pipeline), src, identity, sink, NULL);
502 fail_unless (gst_element_link (src, identity) == TRUE);
503 fail_unless (gst_element_link (identity, sink) == TRUE);
505 /* (1) Test state change with fakesink being a regular sink */
506 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
507 fail_if (ret != GST_STATE_CHANGE_ASYNC,
508 "State change to PLAYING did not return ASYNC");
510 gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE);
511 fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to PLAYING failed");
512 fail_if (current != GST_STATE_PLAYING, "State change to PLAYING failed");
513 fail_if (pending != GST_STATE_VOID_PENDING, "State change to PLAYING failed");
516 ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_NULL, GST_STATE_READY, 101);
517 ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_NULL, GST_STATE_READY, 102);
518 ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_NULL, GST_STATE_READY, 103);
519 ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_NULL, GST_STATE_READY, 104);
521 /* READY => PAUSED */
522 /* because of pre-rolling, sink will return ASYNC on state
523 * change and change state later when it has a buffer */
524 ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_READY, GST_STATE_PAUSED,
527 /* From here on, all bets are off. Usually the source changes state next,
528 * but it might just as well be that the first buffer produced by the
529 * source reaches the sink before the source has finished its state change,
530 * in which case the sink will commit its new state before the source ... */
531 ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_READY, GST_STATE_PAUSED, 106);
532 ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_READY, GST_STATE_PAUSED, 107);
533 ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_READY, GST_STATE_PAUSED,
536 /* PAUSED => PLAYING */
537 ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_PAUSED, GST_STATE_PLAYING, 109);
538 ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_PAUSED, GST_STATE_PLAYING,
540 ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_PAUSED, GST_STATE_PLAYING, 111);
541 ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_PAUSED, GST_STATE_PLAYING,
544 pop_messages (bus, 3); /* pop remaining ready => paused messages off the bus */
545 pop_messages (bus, 4); /* pop paused => playing messages off the bus */
548 /* don't set to NULL that will set the bus flushing and kill our messages */
549 ret = gst_element_set_state (pipeline, GST_STATE_READY);
550 fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed");
551 ret = gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
552 fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed");
554 /* TODO: do we need to check downwards state change order as well? */
555 pop_messages (bus, 4); /* pop playing => paused messages off the bus */
556 pop_messages (bus, 4); /* pop paused => ready messages off the bus */
558 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
559 ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
560 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
562 ret = gst_element_set_state (pipeline, GST_STATE_NULL);
563 fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to NULL failed");
565 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
566 ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
567 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
569 gst_object_unref (bus);
570 gst_object_unref (pipeline);
576 GST_START_TEST (test_children_state_change_order_semi_sink)
578 GstElement *src, *identity, *sink, *pipeline;
579 GstStateChangeReturn ret;
580 GstState current, pending;
583 /* (2) Now again, but check other code path where we don't have
584 * a proper sink correctly flagged as such, but a 'semi-sink' */
585 pipeline = gst_pipeline_new (NULL);
586 fail_unless (pipeline != NULL, "Could not create pipeline");
588 bus = gst_element_get_bus (pipeline);
589 fail_unless (bus != NULL, "Pipeline has no bus?!");
591 src = gst_element_factory_make ("fakesrc", NULL);
592 fail_if (src == NULL, "Could not create fakesrc");
594 identity = gst_element_factory_make ("identity", NULL);
595 fail_if (identity == NULL, "Could not create identity");
597 sink = gst_element_factory_make ("fakesink", NULL);
598 fail_if (sink == NULL, "Could not create fakesink");
600 gst_bin_add_many (GST_BIN (pipeline), src, identity, sink, NULL);
602 fail_unless (gst_element_link (src, identity) == TRUE);
603 fail_unless (gst_element_link (identity, sink) == TRUE);
605 /* this is not very nice but should work just fine in this case. */
606 GST_OBJECT_FLAG_UNSET (sink, GST_ELEMENT_IS_SINK); /* <======== */
608 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
609 fail_if (ret != GST_STATE_CHANGE_ASYNC, "State change to PLAYING not ASYNC");
611 gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE);
612 fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to PLAYING failed");
613 fail_if (current != GST_STATE_PLAYING, "State change to PLAYING failed");
614 fail_if (pending != GST_STATE_VOID_PENDING, "State change to PLAYING failed");
617 ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_NULL, GST_STATE_READY, 201);
618 ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_NULL, GST_STATE_READY, 202);
619 ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_NULL, GST_STATE_READY, 203);
620 ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_NULL, GST_STATE_READY, 204);
622 /* READY => PAUSED */
623 /* because of pre-rolling, sink will return ASYNC on state
624 * change and change state later when it has a buffer */
625 ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_READY, GST_STATE_PAUSED,
628 /* From here on, all bets are off. Usually the source changes state next,
629 * but it might just as well be that the first buffer produced by the
630 * source reaches the sink before the source has finished its state change,
631 * in which case the sink will commit its new state before the source ... */
632 ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_READY, GST_STATE_PAUSED, 206);
633 ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_READY, GST_STATE_PAUSED, 207);
634 ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_READY, GST_STATE_PAUSED,
637 /* PAUSED => PLAYING */
638 ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_PAUSED, GST_STATE_PLAYING, 209);
639 ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_PAUSED, GST_STATE_PLAYING,
641 ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_PAUSED, GST_STATE_PLAYING, 211);
642 ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_PAUSED, GST_STATE_PLAYING,
645 pop_messages (bus, 3); /* pop remaining ready => paused messages off the bus */
646 pop_messages (bus, 4); /* pop paused => playing messages off the bus */
649 /* don't set to NULL that will set the bus flushing and kill our messages */
650 ret = gst_element_set_state (pipeline, GST_STATE_READY);
651 fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed");
653 /* TODO: do we need to check downwards state change order as well? */
654 pop_messages (bus, 4); /* pop playing => paused messages off the bus */
655 pop_messages (bus, 4); /* pop paused => ready messages off the bus */
657 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
658 ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
659 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
661 ret = gst_element_set_state (pipeline, GST_STATE_NULL);
662 fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to NULL failed");
664 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
665 ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
666 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
668 gst_object_unref (bus);
669 gst_object_unref (pipeline);
674 GST_START_TEST (test_children_state_change_order_two_sink)
676 GstElement *src, *tee, *identity, *sink1, *sink2, *pipeline;
677 GstStateChangeReturn ret;
680 pipeline = gst_pipeline_new (NULL);
681 fail_unless (pipeline != NULL, "Could not create pipeline");
683 bus = gst_element_get_bus (pipeline);
684 fail_unless (bus != NULL, "Pipeline has no bus?!");
686 src = gst_element_factory_make ("fakesrc", NULL);
687 fail_if (src == NULL, "Could not create fakesrc");
689 tee = gst_element_factory_make ("tee", NULL);
690 fail_if (tee == NULL, "Could not create tee");
692 identity = gst_element_factory_make ("identity", NULL);
693 fail_if (identity == NULL, "Could not create identity");
695 sink1 = gst_element_factory_make ("fakesink", NULL);
696 fail_if (sink1 == NULL, "Could not create fakesink1");
698 sink2 = gst_element_factory_make ("fakesink", NULL);
699 fail_if (sink2 == NULL, "Could not create fakesink2");
701 gst_bin_add_many (GST_BIN (pipeline), src, tee, identity, sink1, sink2, NULL);
703 fail_unless (gst_element_link (src, tee) == TRUE);
704 fail_unless (gst_element_link (tee, identity) == TRUE);
705 fail_unless (gst_element_link (identity, sink1) == TRUE);
706 fail_unless (gst_element_link (tee, sink2) == TRUE);
708 ret = gst_element_set_state (pipeline, GST_STATE_READY);
709 fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed");
714 GstState old = 0, new = 0, pending = 0;
715 GstObject *first, *second;
717 msg = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND);
718 fail_if (msg == NULL, "No state change message within 1 second (#201)");
720 gst_message_parse_state_changed (msg, &old, &new, &pending);
721 first = gst_object_ref (msg->src);
723 fail_if (first != GST_OBJECT (sink1) && first != GST_OBJECT (sink2),
724 "sink1 or sink2 should have changed state next #(202)");
725 gst_message_unref (msg);
727 msg = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND);
728 fail_if (msg == NULL, "No state change message within 1 second (#201)");
730 gst_message_parse_state_changed (msg, &old, &new, &pending);
731 second = gst_object_ref (msg->src);
733 fail_if (second != GST_OBJECT (sink1) && second != GST_OBJECT (sink2),
734 "sink1 or sink2 should have changed state next #(202)");
735 gst_message_unref (msg);
737 fail_if (second == first, "got state change from same object");
739 gst_object_unref (first);
740 gst_object_unref (second);
742 ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_NULL, GST_STATE_READY, 203);
743 ASSERT_STATE_CHANGE_MSG (bus, tee, GST_STATE_NULL, GST_STATE_READY, 204);
744 ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_NULL, GST_STATE_READY, 205);
745 ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_NULL, GST_STATE_READY, 206);
747 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
748 ASSERT_OBJECT_REFCOUNT (tee, "tee", 1);
749 ASSERT_OBJECT_REFCOUNT (identity, "identity", 1);
750 ASSERT_OBJECT_REFCOUNT (sink1, "sink1", 1);
751 ASSERT_OBJECT_REFCOUNT (sink2, "sink2", 1);
752 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
754 ret = gst_element_set_state (pipeline, GST_STATE_NULL);
755 fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to NULL failed");
757 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
758 ASSERT_OBJECT_REFCOUNT (tee, "tee", 1);
759 ASSERT_OBJECT_REFCOUNT (identity, "identity", 1);
760 ASSERT_OBJECT_REFCOUNT (sink1, "sink1", 1);
761 ASSERT_OBJECT_REFCOUNT (sink2, "sink2", 1);
762 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
764 gst_object_unref (bus);
765 gst_object_unref (pipeline);
773 Suite *s = suite_create ("GstBin");
774 TCase *tc_chain = tcase_create ("bin tests");
776 tcase_set_timeout (tc_chain, 0);
778 suite_add_tcase (s, tc_chain);
779 tcase_add_test (tc_chain, test_interface);
780 tcase_add_test (tc_chain, test_children_state_change_order_flagged_sink);
781 tcase_add_test (tc_chain, test_children_state_change_order_semi_sink);
782 tcase_add_test (tc_chain, test_children_state_change_order_two_sink);
783 tcase_add_test (tc_chain, test_message_state_changed);
784 tcase_add_test (tc_chain, test_message_state_changed_child);
785 tcase_add_test (tc_chain, test_message_state_changed_children);
786 tcase_add_test (tc_chain, test_watch_for_state_change);
787 tcase_add_test (tc_chain, test_add_linked);
793 main (int argc, char **argv)
797 Suite *s = gst_bin_suite ();
798 SRunner *sr = srunner_create (s);
800 gst_check_init (&argc, &argv);
802 srunner_run_all (sr, CK_NORMAL);
803 nf = srunner_ntests_failed (sr);