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_SUCCESS);
267 gst_element_get_state (GST_ELEMENT (pipeline), ¤t, &pending, NULL);
268 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
269 fail_unless (current == GST_STATE_PAUSED);
270 fail_unless (pending == GST_STATE_VOID_PENDING);
272 /* each object is referenced by a message;
273 * base_sink_chain has taken a refcount on the sink, and is blocked on
275 ASSERT_OBJECT_REFCOUNT (src, "src", 2);
276 ASSERT_OBJECT_REFCOUNT (sink, "sink", 3);
277 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 2);
279 pop_messages (bus, 3);
280 fail_if ((gst_bus_pop (bus)) != NULL);
282 ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
283 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
284 ASSERT_OBJECT_REFCOUNT (sink, "sink", 2);
285 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
287 /* change state to PLAYING, spawning three messages */
288 GST_DEBUG ("setting pipeline to PLAYING");
289 ret = gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
290 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
292 gst_element_get_state (GST_ELEMENT (pipeline), ¤t, &pending, NULL);
293 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
294 fail_unless (current == GST_STATE_PLAYING);
295 fail_unless (pending == GST_STATE_VOID_PENDING);
297 /* each object is referenced by one message
298 * sink might have an extra reference if it's still blocked on preroll
299 * pipeline posted a new-clock message too. */
300 ASSERT_OBJECT_REFCOUNT (src, "src", 2);
301 ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 2, 3);
302 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 3);
304 pop_messages (bus, 3);
305 fail_if ((gst_bus_pop (bus)) != NULL);
307 ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
308 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
309 /* sink might have an extra reference if it's still blocked on preroll */
310 ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 1, 2);
311 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
313 /* go back to READY, spawning six messages */
314 GST_DEBUG ("setting pipeline to READY");
315 ret = gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_READY);
316 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
318 /* each object is referenced by two messages */
319 ASSERT_OBJECT_REFCOUNT (src, "src", 3);
320 ASSERT_OBJECT_REFCOUNT (sink, "sink", 3);
321 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 3);
323 pop_messages (bus, 6);
324 fail_if ((gst_bus_pop (bus)) != NULL);
326 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
327 ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
328 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
330 /* setting pipeline to NULL flushes the bus automatically */
331 ret = gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
332 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
334 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
335 ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
336 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
339 gst_object_unref (bus);
340 gst_object_unref (pipeline);
345 GST_START_TEST (test_watch_for_state_change)
347 GstElement *src, *sink, *bin;
349 GstStateChangeReturn ret;
351 bin = gst_element_factory_make ("bin", NULL);
352 fail_unless (bin != NULL, "Could not create bin");
354 bus = g_object_new (gst_bus_get_type (), NULL);
355 gst_element_set_bus (GST_ELEMENT_CAST (bin), bus);
357 src = gst_element_factory_make ("fakesrc", NULL);
358 fail_if (src == NULL, "Could not create fakesrc");
359 sink = gst_element_factory_make ("fakesink", NULL);
360 fail_if (sink == NULL, "Could not create fakesink");
362 gst_bin_add (GST_BIN (bin), sink);
363 gst_bin_add (GST_BIN (bin), src);
365 fail_unless (gst_element_link (src, sink), "could not link src and sink");
367 /* change state, spawning two times three messages, minus one async */
368 ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED);
369 fail_unless (ret == GST_STATE_CHANGE_ASYNC);
371 pop_messages (bus, 5);
373 fail_unless (gst_bus_have_pending (bus) == FALSE,
374 "Unexpected messages on bus");
376 gst_bin_watch_for_state_change (GST_BIN (bin));
378 /* should get the bin's state change message now */
379 pop_messages (bus, 1);
381 fail_unless (gst_bus_have_pending (bus) == FALSE,
382 "Unexpected messages on bus");
384 ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING);
385 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
387 pop_messages (bus, 3);
389 /* this one might return either SUCCESS or ASYNC, likely SUCCESS */
390 gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED);
392 gst_bin_watch_for_state_change (GST_BIN (bin));
394 pop_messages (bus, 3);
396 fail_unless (gst_bus_have_pending (bus) == FALSE,
397 "Unexpected messages on bus");
399 /* setting bin to NULL flushes the bus automatically */
400 ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
401 fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
404 gst_object_unref (bus);
405 gst_object_unref (bin);
410 /* adding an element with linked pads to a bin unlinks the
412 GST_START_TEST (test_add_linked)
414 GstElement *src, *sink;
415 GstPad *srcpad, *sinkpad;
416 GstElement *pipeline;
418 pipeline = gst_pipeline_new (NULL);
419 fail_unless (pipeline != NULL, "Could not create pipeline");
421 src = gst_element_factory_make ("fakesrc", NULL);
422 fail_if (src == NULL, "Could not create fakesrc");
423 sink = gst_element_factory_make ("fakesink", NULL);
424 fail_if (sink == NULL, "Could not create fakesink");
426 srcpad = gst_element_get_pad (src, "src");
427 fail_unless (srcpad != NULL);
428 sinkpad = gst_element_get_pad (sink, "sink");
429 fail_unless (sinkpad != NULL);
431 fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK);
433 /* pads are linked now */
434 fail_unless (gst_pad_is_linked (srcpad));
435 fail_unless (gst_pad_is_linked (sinkpad));
437 /* adding element to bin voids hierarchy so pads are unlinked */
438 gst_bin_add (GST_BIN (pipeline), src);
440 /* check if pads really are unlinked */
441 fail_unless (!gst_pad_is_linked (srcpad));
442 fail_unless (!gst_pad_is_linked (sinkpad));
444 /* cannot link pads in wrong hierarchy */
445 fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_WRONG_HIERARCHY);
447 /* adding other element to bin as well */
448 gst_bin_add (GST_BIN (pipeline), sink);
450 /* now we can link again */
451 fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK);
453 /* check if pads really are linked */
454 fail_unless (gst_pad_is_linked (srcpad));
455 fail_unless (gst_pad_is_linked (sinkpad));
457 gst_object_unref (srcpad);
458 gst_object_unref (sinkpad);
459 gst_object_unref (pipeline);
464 /* g_print ("%10s: %4d => %4d\n", GST_OBJECT_NAME (msg->src), old, new); */
466 #define ASSERT_STATE_CHANGE_MSG(bus,element,old_state,new_state,num) \
469 GstState old = 0, new = 0, pending = 0; \
470 msg = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND); \
471 fail_if (msg == NULL, "No state change message within 1 second (#" \
472 G_STRINGIFY (num) ")"); \
473 gst_message_parse_state_changed (msg, &old, &new, &pending); \
474 fail_if (msg->src != GST_OBJECT (element), G_STRINGIFY(element) \
475 " should have changed state next (#" G_STRINGIFY (num) ")"); \
476 fail_if (old != old_state || new != new_state, "state change is not " \
477 G_STRINGIFY (old_state) " => " G_STRINGIFY (new_state)); \
478 gst_message_unref (msg); \
481 GST_START_TEST (test_children_state_change_order_flagged_sink)
483 GstElement *src, *identity, *sink, *pipeline;
484 GstStateChangeReturn ret;
487 pipeline = gst_pipeline_new (NULL);
488 fail_unless (pipeline != NULL, "Could not create pipeline");
490 bus = gst_element_get_bus (pipeline);
491 fail_unless (bus != NULL, "Pipeline has no bus?!");
493 src = gst_element_factory_make ("fakesrc", NULL);
494 fail_if (src == NULL, "Could not create fakesrc");
496 identity = gst_element_factory_make ("identity", NULL);
497 fail_if (identity == NULL, "Could not create identity");
499 sink = gst_element_factory_make ("fakesink", NULL);
500 fail_if (sink == NULL, "Could not create fakesink");
502 gst_bin_add_many (GST_BIN (pipeline), src, identity, sink, NULL);
504 fail_unless (gst_element_link (src, identity) == TRUE);
505 fail_unless (gst_element_link (identity, sink) == TRUE);
507 /* (1) Test state change with fakesink being a regular sink */
508 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
509 fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to PLAYING failed");
512 ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_NULL, GST_STATE_READY, 101);
513 ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_NULL, GST_STATE_READY, 102);
514 ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_NULL, GST_STATE_READY, 103);
515 ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_NULL, GST_STATE_READY, 104);
517 /* READY => PAUSED */
518 /* because of pre-rolling, sink will return ASYNC on state
519 * change and change state later when it has a buffer */
520 ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_READY, GST_STATE_PAUSED,
523 /* From here on, all bets are off. Usually the source changes state next,
524 * but it might just as well be that the first buffer produced by the
525 * source reaches the sink before the source has finished its state change,
526 * in which case the sink will commit its new state before the source ... */
527 ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_READY, GST_STATE_PAUSED, 106);
528 ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_READY, GST_STATE_PAUSED, 107);
529 ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_READY, GST_STATE_PAUSED,
532 /* PAUSED => PLAYING */
533 ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_PAUSED, GST_STATE_PLAYING, 109);
534 ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_PAUSED, GST_STATE_PLAYING,
536 ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_PAUSED, GST_STATE_PLAYING, 111);
537 ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_PAUSED, GST_STATE_PLAYING,
540 pop_messages (bus, 3); /* pop remaining ready => paused messages off the bus */
541 pop_messages (bus, 4); /* pop paused => playing messages off the bus */
544 /* don't set to NULL that will set the bus flushing and kill our messages */
545 ret = gst_element_set_state (pipeline, GST_STATE_READY);
546 fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed");
547 ret = gst_element_get_state (pipeline, NULL, NULL, NULL);
548 fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed");
550 /* TODO: do we need to check downwards state change order as well? */
551 pop_messages (bus, 4); /* pop playing => paused messages off the bus */
552 pop_messages (bus, 4); /* pop paused => ready messages off the bus */
554 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
555 ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
556 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
558 ret = gst_element_set_state (pipeline, GST_STATE_NULL);
559 fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to NULL failed");
561 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
562 ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
563 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
565 gst_object_unref (bus);
566 gst_object_unref (pipeline);
572 GST_START_TEST (test_children_state_change_order_semi_sink)
574 GstElement *src, *identity, *sink, *pipeline;
575 GstStateChangeReturn ret;
576 GstState current, pending;
579 /* (2) Now again, but check other code path where we don't have
580 * a proper sink correctly flagged as such, but a 'semi-sink' */
581 pipeline = gst_pipeline_new (NULL);
582 fail_unless (pipeline != NULL, "Could not create pipeline");
584 bus = gst_element_get_bus (pipeline);
585 fail_unless (bus != NULL, "Pipeline has no bus?!");
587 src = gst_element_factory_make ("fakesrc", NULL);
588 fail_if (src == NULL, "Could not create fakesrc");
590 identity = gst_element_factory_make ("identity", NULL);
591 fail_if (identity == NULL, "Could not create identity");
593 sink = gst_element_factory_make ("fakesink", NULL);
594 fail_if (sink == NULL, "Could not create fakesink");
596 gst_bin_add_many (GST_BIN (pipeline), src, identity, sink, NULL);
598 fail_unless (gst_element_link (src, identity) == TRUE);
599 fail_unless (gst_element_link (identity, sink) == TRUE);
601 /* this is not very nice but should work just fine in this case. */
602 GST_FLAG_UNSET (sink, GST_ELEMENT_IS_SINK); /* <======== */
604 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
605 fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to PLAYING failed");
606 ret = gst_element_get_state (pipeline, ¤t, &pending, NULL);
607 fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to PLAYING failed");
608 fail_if (current != GST_STATE_PLAYING, "State change to PLAYING failed");
609 fail_if (pending != GST_STATE_VOID_PENDING, "State change to PLAYING failed");
612 ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_NULL, GST_STATE_READY, 201);
613 ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_NULL, GST_STATE_READY, 202);
614 ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_NULL, GST_STATE_READY, 203);
615 ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_NULL, GST_STATE_READY, 204);
617 /* READY => PAUSED */
618 /* because of pre-rolling, sink will return ASYNC on state
619 * change and change state later when it has a buffer */
620 ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_READY, GST_STATE_PAUSED,
623 /* From here on, all bets are off. Usually the source changes state next,
624 * but it might just as well be that the first buffer produced by the
625 * source reaches the sink before the source has finished its state change,
626 * in which case the sink will commit its new state before the source ... */
627 ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_READY, GST_STATE_PAUSED, 206);
628 ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_READY, GST_STATE_PAUSED, 207);
629 ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_READY, GST_STATE_PAUSED,
632 /* PAUSED => PLAYING */
633 ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_PAUSED, GST_STATE_PLAYING, 209);
634 ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_PAUSED, GST_STATE_PLAYING,
636 ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_PAUSED, GST_STATE_PLAYING, 211);
637 ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_PAUSED, GST_STATE_PLAYING,
640 pop_messages (bus, 3); /* pop remaining ready => paused messages off the bus */
641 pop_messages (bus, 4); /* pop paused => playing messages off the bus */
644 /* don't set to NULL that will set the bus flushing and kill our messages */
645 ret = gst_element_set_state (pipeline, GST_STATE_READY);
646 fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed");
648 /* TODO: do we need to check downwards state change order as well? */
649 pop_messages (bus, 4); /* pop playing => paused messages off the bus */
650 pop_messages (bus, 4); /* pop paused => ready messages off the bus */
652 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
653 ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
654 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
656 ret = gst_element_set_state (pipeline, GST_STATE_NULL);
657 fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to NULL failed");
659 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
660 ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
661 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
663 gst_object_unref (bus);
664 gst_object_unref (pipeline);
669 GST_START_TEST (test_children_state_change_order_two_sink)
671 GstElement *src, *tee, *identity, *sink1, *sink2, *pipeline;
672 GstStateChangeReturn ret;
675 pipeline = gst_pipeline_new (NULL);
676 fail_unless (pipeline != NULL, "Could not create pipeline");
678 bus = gst_element_get_bus (pipeline);
679 fail_unless (bus != NULL, "Pipeline has no bus?!");
681 src = gst_element_factory_make ("fakesrc", NULL);
682 fail_if (src == NULL, "Could not create fakesrc");
684 tee = gst_element_factory_make ("tee", NULL);
685 fail_if (tee == NULL, "Could not create tee");
687 identity = gst_element_factory_make ("identity", NULL);
688 fail_if (identity == NULL, "Could not create identity");
690 sink1 = gst_element_factory_make ("fakesink", NULL);
691 fail_if (sink1 == NULL, "Could not create fakesink1");
693 sink2 = gst_element_factory_make ("fakesink", NULL);
694 fail_if (sink2 == NULL, "Could not create fakesink2");
696 gst_bin_add_many (GST_BIN (pipeline), src, tee, identity, sink1, sink2, NULL);
698 fail_unless (gst_element_link (src, tee) == TRUE);
699 fail_unless (gst_element_link (tee, identity) == TRUE);
700 fail_unless (gst_element_link (identity, sink1) == TRUE);
701 fail_unless (gst_element_link (tee, sink2) == TRUE);
703 ret = gst_element_set_state (pipeline, GST_STATE_READY);
704 fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed");
709 GstState old = 0, new = 0, pending = 0;
710 GstObject *first, *second;
712 msg = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND);
713 fail_if (msg == NULL, "No state change message within 1 second (#201)");
715 gst_message_parse_state_changed (msg, &old, &new, &pending);
716 first = gst_object_ref (msg->src);
718 fail_if (first != GST_OBJECT (sink1) && first != GST_OBJECT (sink2),
719 "sink1 or sink2 should have changed state next #(202)");
720 gst_message_unref (msg);
722 msg = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND);
723 fail_if (msg == NULL, "No state change message within 1 second (#201)");
725 gst_message_parse_state_changed (msg, &old, &new, &pending);
726 second = gst_object_ref (msg->src);
728 fail_if (second != GST_OBJECT (sink1) && second != GST_OBJECT (sink2),
729 "sink1 or sink2 should have changed state next #(202)");
730 gst_message_unref (msg);
732 fail_if (second == first, "got state change from same object");
734 gst_object_unref (first);
735 gst_object_unref (second);
737 ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_NULL, GST_STATE_READY, 203);
738 ASSERT_STATE_CHANGE_MSG (bus, tee, GST_STATE_NULL, GST_STATE_READY, 204);
739 ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_NULL, GST_STATE_READY, 205);
740 ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_NULL, GST_STATE_READY, 206);
742 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
743 ASSERT_OBJECT_REFCOUNT (tee, "tee", 1);
744 ASSERT_OBJECT_REFCOUNT (identity, "identity", 1);
745 ASSERT_OBJECT_REFCOUNT (sink1, "sink1", 1);
746 ASSERT_OBJECT_REFCOUNT (sink2, "sink2", 1);
747 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
749 ret = gst_element_set_state (pipeline, GST_STATE_NULL);
750 fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to NULL failed");
752 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
753 ASSERT_OBJECT_REFCOUNT (tee, "tee", 1);
754 ASSERT_OBJECT_REFCOUNT (identity, "identity", 1);
755 ASSERT_OBJECT_REFCOUNT (sink1, "sink1", 1);
756 ASSERT_OBJECT_REFCOUNT (sink2, "sink2", 1);
757 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
759 gst_object_unref (bus);
760 gst_object_unref (pipeline);
768 Suite *s = suite_create ("GstBin");
769 TCase *tc_chain = tcase_create ("bin tests");
771 tcase_set_timeout (tc_chain, 0);
773 suite_add_tcase (s, tc_chain);
774 tcase_add_test (tc_chain, test_interface);
775 tcase_add_test (tc_chain, test_children_state_change_order_flagged_sink);
776 tcase_add_test (tc_chain, test_children_state_change_order_semi_sink);
777 tcase_add_test (tc_chain, test_children_state_change_order_two_sink);
778 tcase_add_test (tc_chain, test_message_state_changed);
779 tcase_add_test (tc_chain, test_message_state_changed_child);
780 tcase_add_test (tc_chain, test_message_state_changed_children);
781 tcase_add_test (tc_chain, test_watch_for_state_change);
782 tcase_add_test (tc_chain, test_add_linked);
788 main (int argc, char **argv)
792 Suite *s = gst_bin_suite ();
793 SRunner *sr = srunner_create (s);
795 gst_check_init (&argc, &argv);
797 srunner_run_all (sr, CK_NORMAL);
798 nf = srunner_ntests_failed (sr);