c7bedcdab2ff1bf0a9e56042ceee52d59af4c8cb
1 /* GStreamer
2 * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
3 * Copyright (C) 2005 Thomas Vander Stichele <thomas at apestaart dot org>
4 *
5 * gstbin.c: Unit test for GstBin
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
23 #include <gst/check/gstcheck.h>
25 static void
26 pop_messages (GstBus * bus, int count)
27 {
28 GstMessage *message;
30 int i;
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);
40 }
41 GST_DEBUG ("popped %d messages", count);
42 }
44 GST_START_TEST (test_interface)
45 {
46 GstBin *bin, *bin2;
47 GstElement *filesrc;
48 GstIterator *it;
49 gpointer item;
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);
79 bin2 = bin;
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);
103 }
105 GST_END_TEST;
107 GST_START_TEST (test_message_state_changed)
108 {
109 GstBin *bin;
110 GstBus *bus;
111 GstMessage *message;
113 bin = GST_BIN (gst_bin_new (NULL));
114 fail_unless (bin != NULL, "Could not create bin");
115 ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
117 bus = g_object_new (gst_bus_get_type (), NULL);
118 gst_element_set_bus (GST_ELEMENT_CAST (bin), bus);
120 /* change state, spawning a message, causing an incref on the bin */
121 gst_element_set_state (GST_ELEMENT (bin), GST_STATE_READY);
123 ASSERT_OBJECT_REFCOUNT (bin, "bin", 2);
125 /* get and unref the message, causing a decref on the bin */
126 message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1);
128 fail_unless (message && GST_MESSAGE_TYPE (message)
129 == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED");
131 gst_message_unref (message);
133 ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
135 /* clean up */
136 gst_object_unref (bus);
137 gst_object_unref (bin);
138 }
140 GST_END_TEST;
142 GST_START_TEST (test_message_state_changed_child)
143 {
144 GstBin *bin;
145 GstElement *src;
146 GstBus *bus;
147 GstMessage *message;
149 bin = GST_BIN (gst_bin_new (NULL));
150 fail_unless (bin != NULL, "Could not create bin");
151 ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
153 bus = g_object_new (gst_bus_get_type (), NULL);
154 gst_element_set_bus (GST_ELEMENT_CAST (bin), bus);
156 src = gst_element_factory_make ("fakesrc", NULL);
157 fail_if (src == NULL, "Could not create fakesrc");
158 gst_bin_add (bin, src);
159 ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
160 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
162 /* change state, spawning two messages:
163 * - first for fakesrc, forwarded to bin's bus, causing incref on fakesrc
164 * - second for bin, causing an incref on the bin */
165 GST_DEBUG ("setting bin to READY");
166 fail_unless (gst_element_set_state (GST_ELEMENT (bin), GST_STATE_READY)
167 == GST_STATE_CHANGE_SUCCESS);
169 ASSERT_OBJECT_REFCOUNT (src, "src", 2);
170 ASSERT_OBJECT_REFCOUNT (bin, "bin", 2);
172 /* get and unref the message, causing a decref on the src */
173 message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1);
174 fail_unless (message && GST_MESSAGE_TYPE (message)
175 == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED");
177 fail_unless (message->src == GST_OBJECT (src));
178 gst_message_unref (message);
180 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
181 ASSERT_OBJECT_REFCOUNT (bin, "bin", 2);
183 /* get and unref message 2, causing a decref on the bin */
184 message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1);
185 fail_unless (message && GST_MESSAGE_TYPE (message)
186 == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED");
188 fail_unless (message->src == GST_OBJECT (bin));
189 gst_message_unref (message);
191 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
192 ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
194 /* clean up */
195 gst_object_unref (bus);
196 gst_object_unref (bin);
197 }
199 GST_END_TEST;
201 GST_START_TEST (test_message_state_changed_children)
202 {
203 GstPipeline *pipeline;
204 GstElement *src, *sink;
205 GstBus *bus;
207 pipeline = GST_PIPELINE (gst_pipeline_new (NULL));
208 fail_unless (pipeline != NULL, "Could not create pipeline");
209 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
211 src = gst_element_factory_make ("fakesrc", NULL);
212 fail_if (src == NULL, "Could not create fakesrc");
213 /* need to silence the element as the deep_notify refcounts the
214 * parents while running */
215 g_object_set (G_OBJECT (src), "silent", TRUE, NULL);
216 gst_bin_add (GST_BIN (pipeline), src);
218 sink = gst_element_factory_make ("fakesink", NULL);
219 /* need to silence the element as the deep_notify refcounts the
220 * parents while running */
221 g_object_set (G_OBJECT (sink), "silent", TRUE, NULL);
222 fail_if (sink == NULL, "Could not create fakesink");
223 gst_bin_add (GST_BIN (pipeline), sink);
225 fail_unless (gst_element_link (src, sink), "could not link src and sink");
227 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
228 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
229 ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
231 bus = gst_pipeline_get_bus (pipeline);
233 /* change state to READY, spawning three messages */
234 GST_DEBUG ("setting pipeline to READY");
235 fail_unless (gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_READY)
236 == GST_STATE_CHANGE_SUCCESS);
238 /* each object is referenced by a message */
239 ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
240 ASSERT_OBJECT_REFCOUNT (src, "src", 2);
241 ASSERT_OBJECT_REFCOUNT (sink, "sink", 2);
242 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 2);
244 pop_messages (bus, 3);
245 fail_if ((gst_bus_pop (bus)) != NULL);
247 ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
248 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
249 ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
250 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
252 /* change state to PAUSED, spawning three messages */
253 GST_DEBUG ("setting pipeline to PAUSED");
254 fail_unless (gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED)
255 == GST_STATE_CHANGE_SUCCESS);
257 /* each object is referenced by a message;
258 * base_sink_chain has taken a refcount on the sink, and is blocked on
259 * preroll */
260 ASSERT_OBJECT_REFCOUNT (src, "src", 2);
261 ASSERT_OBJECT_REFCOUNT (sink, "sink", 3);
262 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 2);
264 pop_messages (bus, 3);
265 fail_if ((gst_bus_pop (bus)) != NULL);
267 ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
268 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
269 ASSERT_OBJECT_REFCOUNT (sink, "sink", 2);
270 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
272 /* change state to PLAYING, spawning three messages */
273 GST_DEBUG ("setting pipeline to PLAYING");
274 fail_unless (gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING)
275 == GST_STATE_CHANGE_SUCCESS);
277 /* each object is referenced by one message
278 * sink might have an extra reference if it's still blocked on preroll */
279 ASSERT_OBJECT_REFCOUNT (src, "src", 2);
280 ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 2, 3);
281 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 2);
283 pop_messages (bus, 3);
284 fail_if ((gst_bus_pop (bus)) != NULL);
286 ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
287 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
288 /* sink might have an extra reference if it's still blocked on preroll */
289 ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 1, 2);
290 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
292 /* go back to READY, spawning six messages */
293 GST_DEBUG ("setting pipeline to READY");
294 fail_unless (gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_READY)
295 == GST_STATE_CHANGE_SUCCESS);
297 /* each object is referenced by two messages */
298 ASSERT_OBJECT_REFCOUNT (src, "src", 3);
299 ASSERT_OBJECT_REFCOUNT (sink, "sink", 3);
300 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 3);
302 pop_messages (bus, 6);
303 fail_if ((gst_bus_pop (bus)) != NULL);
305 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
306 ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
307 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
309 /* setting pipeline to NULL flushes the bus automatically */
310 fail_unless (gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL)
311 == GST_STATE_CHANGE_SUCCESS);
313 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
314 ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
315 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
317 /* clean up */
318 gst_object_unref (bus);
319 gst_object_unref (pipeline);
320 }
322 GST_END_TEST;
324 GST_START_TEST (test_watch_for_state_change)
325 {
326 GstElement *src, *sink, *bin;
327 GstBus *bus;
329 bin = gst_element_factory_make ("bin", NULL);
330 fail_unless (bin != NULL, "Could not create bin");
332 bus = g_object_new (gst_bus_get_type (), NULL);
333 gst_element_set_bus (GST_ELEMENT_CAST (bin), bus);
335 src = gst_element_factory_make ("fakesrc", NULL);
336 fail_if (src == NULL, "Could not create fakesrc");
337 sink = gst_element_factory_make ("fakesink", NULL);
338 fail_if (sink == NULL, "Could not create fakesink");
340 gst_bin_add (GST_BIN (bin), sink);
341 gst_bin_add (GST_BIN (bin), src);
343 fail_unless (gst_element_link (src, sink), "could not link src and sink");
345 /* change state, spawning two times three messages, minus one async */
346 fail_unless (gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED)
347 == GST_STATE_CHANGE_ASYNC);
349 pop_messages (bus, 5);
351 fail_unless (gst_bus_have_pending (bus) == FALSE,
352 "Unexpected messages on bus");
354 gst_bin_watch_for_state_change (GST_BIN (bin));
356 /* should get the bin's state change message now */
357 pop_messages (bus, 1);
359 fail_unless (gst_bus_have_pending (bus) == FALSE,
360 "Unexpected messages on bus");
362 fail_unless (gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING)
363 == GST_STATE_CHANGE_SUCCESS);
365 pop_messages (bus, 3);
367 /* this one might return either SUCCESS or ASYNC, likely SUCCESS */
368 gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED);
370 gst_bin_watch_for_state_change (GST_BIN (bin));
372 pop_messages (bus, 3);
374 fail_unless (gst_bus_have_pending (bus) == FALSE,
375 "Unexpected messages on bus");
377 /* setting bin to NULL flushes the bus automatically */
378 fail_unless (gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL)
379 == GST_STATE_CHANGE_SUCCESS);
381 /* clean up */
382 gst_object_unref (bus);
383 gst_object_unref (bin);
384 }
386 GST_END_TEST;
388 /* adding an element with linked pads to a bin unlinks the
389 * pads */
390 GST_START_TEST (test_add_linked)
391 {
392 GstElement *src, *sink;
393 GstPad *srcpad, *sinkpad;
394 GstElement *pipeline;
396 pipeline = gst_pipeline_new (NULL);
397 fail_unless (pipeline != NULL, "Could not create pipeline");
399 src = gst_element_factory_make ("fakesrc", NULL);
400 fail_if (src == NULL, "Could not create fakesrc");
401 sink = gst_element_factory_make ("fakesink", NULL);
402 fail_if (sink == NULL, "Could not create fakesink");
404 srcpad = gst_element_get_pad (src, "src");
405 fail_unless (srcpad != NULL);
406 sinkpad = gst_element_get_pad (sink, "sink");
407 fail_unless (sinkpad != NULL);
409 fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK);
411 /* pads are linked now */
412 fail_unless (gst_pad_is_linked (srcpad));
413 fail_unless (gst_pad_is_linked (sinkpad));
415 /* adding element to bin voids hierarchy so pads are unlinked */
416 gst_bin_add (GST_BIN (pipeline), src);
418 /* check if pads really are unlinked */
419 fail_unless (!gst_pad_is_linked (srcpad));
420 fail_unless (!gst_pad_is_linked (sinkpad));
422 /* cannot link pads in wrong hierarchy */
423 fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_WRONG_HIERARCHY);
425 /* adding other element to bin as well */
426 gst_bin_add (GST_BIN (pipeline), sink);
428 /* now we can link again */
429 fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK);
431 /* check if pads really are linked */
432 fail_unless (gst_pad_is_linked (srcpad));
433 fail_unless (gst_pad_is_linked (sinkpad));
435 gst_object_unref (srcpad);
436 gst_object_unref (sinkpad);
437 gst_object_unref (pipeline);
438 }
440 GST_END_TEST;
442 /* g_print ("%10s: %4d => %4d\n", GST_OBJECT_NAME (msg->src), old, new); */
444 #define ASSERT_STATE_CHANGE_MSG(bus,element,old_state,new_state,num) \
445 { \
446 GstMessage *msg; \
447 GstState old = 0, new = 0; \
448 msg = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND); \
449 fail_if (msg == NULL, "No state change message within 1 second (#" \
450 G_STRINGIFY (num) ")"); \
451 gst_message_parse_state_changed (msg, &old, &new); \
452 fail_if (msg->src != GST_OBJECT (element), G_STRINGIFY(element) \
453 " should have changed state next (#" G_STRINGIFY (num) ")"); \
454 fail_if (old != old_state || new != new_state, "state change is not " \
455 G_STRINGIFY (old_state) " => " G_STRINGIFY (new_state)); \
456 gst_message_unref (msg); \
457 }
459 GST_START_TEST (test_children_state_change_order_flagged_sink)
460 {
461 GstElement *src, *identity, *sink, *pipeline;
462 GstStateChangeReturn ret;
463 GstBus *bus;
465 pipeline = gst_pipeline_new (NULL);
466 fail_unless (pipeline != NULL, "Could not create pipeline");
468 bus = gst_element_get_bus (pipeline);
469 fail_unless (bus != NULL, "Pipeline has no bus?!");
471 src = gst_element_factory_make ("fakesrc", NULL);
472 fail_if (src == NULL, "Could not create fakesrc");
474 identity = gst_element_factory_make ("identity", NULL);
475 fail_if (identity == NULL, "Could not create identity");
477 sink = gst_element_factory_make ("fakesink", NULL);
478 fail_if (sink == NULL, "Could not create fakesink");
480 gst_bin_add_many (GST_BIN (pipeline), src, identity, sink, NULL);
482 fail_unless (gst_element_link (src, identity) == TRUE);
483 fail_unless (gst_element_link (identity, sink) == TRUE);
485 /* (1) Test state change with fakesink being a regular sink */
486 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
487 fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to PLAYING failed");
489 /* NULL => READY */
490 ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_NULL, GST_STATE_READY, 101);
491 ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_NULL, GST_STATE_READY, 102);
492 ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_NULL, GST_STATE_READY, 103);
493 ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_NULL, GST_STATE_READY, 104);
495 /* READY => PAUSED */
496 /* because of pre-rolling, sink will return ASYNC on state
497 * change and change state later when it has a buffer */
498 ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_READY, GST_STATE_PAUSED,
499 105);
500 #if 0
501 /* From here on, all bets are off. Usually the source changes state next,
502 * but it might just as well be that the first buffer produced by the
503 * source reaches the sink before the source has finished its state change,
504 * in which case the sink will commit its new state before the source ... */
505 ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_READY, GST_STATE_PAUSED, 106);
506 ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_READY, GST_STATE_PAUSED, 107);
507 ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_READY, GST_STATE_PAUSED,
508 108);
510 /* PAUSED => PLAYING */
511 ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_PAUSED, GST_STATE_PLAYING, 109);
512 ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_PAUSED, GST_STATE_PLAYING,
513 110);
514 ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_PAUSED, GST_STATE_PLAYING, 111);
515 ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_PAUSED, GST_STATE_PLAYING,
516 112);
517 #else
518 pop_messages (bus, 3); /* pop remaining ready => paused messages off the bus */
519 pop_messages (bus, 4); /* pop paused => playing messages off the bus */
520 #endif
522 /* don't set to NULL that will set the bus flushing and kill our messages */
523 ret = gst_element_set_state (pipeline, GST_STATE_READY);
524 fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed");
526 /* TODO: do we need to check downwards state change order as well? */
527 pop_messages (bus, 4); /* pop playing => paused messages off the bus */
528 pop_messages (bus, 4); /* pop paused => ready messages off the bus */
530 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
531 ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
532 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
534 ret = gst_element_set_state (pipeline, GST_STATE_NULL);
535 fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to NULL failed");
537 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
538 ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
539 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
541 gst_object_unref (bus);
542 gst_object_unref (pipeline);
543 }
545 GST_END_TEST;
548 GST_START_TEST (test_children_state_change_order_semi_sink)
549 {
550 GstElement *src, *identity, *sink, *pipeline;
551 GstStateChangeReturn ret;
552 GstBus *bus;
554 /* (2) Now again, but check other code path where we don't have
555 * a proper sink correctly flagged as such, but a 'semi-sink' */
556 pipeline = gst_pipeline_new (NULL);
557 fail_unless (pipeline != NULL, "Could not create pipeline");
559 bus = gst_element_get_bus (pipeline);
560 fail_unless (bus != NULL, "Pipeline has no bus?!");
562 src = gst_element_factory_make ("fakesrc", NULL);
563 fail_if (src == NULL, "Could not create fakesrc");
565 identity = gst_element_factory_make ("identity", NULL);
566 fail_if (identity == NULL, "Could not create identity");
568 sink = gst_element_factory_make ("fakesink", NULL);
569 fail_if (sink == NULL, "Could not create fakesink");
571 gst_bin_add_many (GST_BIN (pipeline), src, identity, sink, NULL);
573 fail_unless (gst_element_link (src, identity) == TRUE);
574 fail_unless (gst_element_link (identity, sink) == TRUE);
576 /* this is not very nice but should work just fine in this case. */
577 GST_FLAG_UNSET (sink, GST_ELEMENT_IS_SINK); /* <======== */
579 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
580 fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to PLAYING failed");
582 /* NULL => READY */
583 ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_NULL, GST_STATE_READY, 201);
584 ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_NULL, GST_STATE_READY, 202);
585 ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_NULL, GST_STATE_READY, 203);
586 ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_NULL, GST_STATE_READY, 204);
588 /* READY => PAUSED */
589 /* because of pre-rolling, sink will return ASYNC on state
590 * change and change state later when it has a buffer */
591 ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_READY, GST_STATE_PAUSED,
592 205);
593 #if 0
594 /* From here on, all bets are off. Usually the source changes state next,
595 * but it might just as well be that the first buffer produced by the
596 * source reaches the sink before the source has finished its state change,
597 * in which case the sink will commit its new state before the source ... */
598 ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_READY, GST_STATE_PAUSED, 206);
599 ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_READY, GST_STATE_PAUSED, 207);
600 ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_READY, GST_STATE_PAUSED,
601 208);
603 /* PAUSED => PLAYING */
604 ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_PAUSED, GST_STATE_PLAYING, 209);
605 ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_PAUSED, GST_STATE_PLAYING,
606 210);
607 ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_PAUSED, GST_STATE_PLAYING, 211);
608 ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_PAUSED, GST_STATE_PLAYING,
609 212);
610 #else
611 pop_messages (bus, 3); /* pop remaining ready => paused messages off the bus */
612 pop_messages (bus, 4); /* pop paused => playing messages off the bus */
613 #endif
615 /* don't set to NULL that will set the bus flushing and kill our messages */
616 ret = gst_element_set_state (pipeline, GST_STATE_READY);
617 fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed");
619 /* TODO: do we need to check downwards state change order as well? */
620 pop_messages (bus, 4); /* pop playing => paused messages off the bus */
621 pop_messages (bus, 4); /* pop paused => ready messages off the bus */
623 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
624 ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
625 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
627 ret = gst_element_set_state (pipeline, GST_STATE_NULL);
628 fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to NULL failed");
630 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
631 ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
632 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
634 gst_object_unref (bus);
635 gst_object_unref (pipeline);
636 }
638 GST_END_TEST;
640 GST_START_TEST (test_children_state_change_order_two_sink)
641 {
642 GstElement *src, *tee, *identity, *sink1, *sink2, *pipeline;
643 GstStateChangeReturn ret;
644 GstBus *bus;
646 pipeline = gst_pipeline_new (NULL);
647 fail_unless (pipeline != NULL, "Could not create pipeline");
649 bus = gst_element_get_bus (pipeline);
650 fail_unless (bus != NULL, "Pipeline has no bus?!");
652 src = gst_element_factory_make ("fakesrc", NULL);
653 fail_if (src == NULL, "Could not create fakesrc");
655 tee = gst_element_factory_make ("tee", NULL);
656 fail_if (tee == NULL, "Could not create tee");
658 identity = gst_element_factory_make ("identity", NULL);
659 fail_if (identity == NULL, "Could not create identity");
661 sink1 = gst_element_factory_make ("fakesink", NULL);
662 fail_if (sink1 == NULL, "Could not create fakesink1");
664 sink2 = gst_element_factory_make ("fakesink", NULL);
665 fail_if (sink2 == NULL, "Could not create fakesink2");
667 gst_bin_add_many (GST_BIN (pipeline), src, tee, identity, sink1, sink2, NULL);
669 fail_unless (gst_element_link (src, tee) == TRUE);
670 fail_unless (gst_element_link (tee, identity) == TRUE);
671 fail_unless (gst_element_link (identity, sink1) == TRUE);
672 fail_unless (gst_element_link (tee, sink2) == TRUE);
674 ret = gst_element_set_state (pipeline, GST_STATE_READY);
675 fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed");
677 /* NULL => READY */
678 {
679 GstMessage *msg;
680 GstState old = 0, new = 0;
681 GstObject *first, *second;
683 msg = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND);
684 fail_if (msg == NULL, "No state change message within 1 second (#201)");
686 gst_message_parse_state_changed (msg, &old, &new);
687 first = gst_object_ref (msg->src);
689 fail_if (first != GST_OBJECT (sink1) && first != GST_OBJECT (sink2),
690 "sink1 or sink2 should have changed state next #(202)");
691 gst_message_unref (msg);
693 msg = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND);
694 fail_if (msg == NULL, "No state change message within 1 second (#201)");
696 gst_message_parse_state_changed (msg, &old, &new);
697 second = gst_object_ref (msg->src);
699 fail_if (second != GST_OBJECT (sink1) && second != GST_OBJECT (sink2),
700 "sink1 or sink2 should have changed state next #(202)");
701 gst_message_unref (msg);
703 fail_if (second == first, "got state change from same object");
705 gst_object_unref (first);
706 gst_object_unref (second);
707 }
708 ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_NULL, GST_STATE_READY, 203);
709 ASSERT_STATE_CHANGE_MSG (bus, tee, GST_STATE_NULL, GST_STATE_READY, 204);
710 ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_NULL, GST_STATE_READY, 205);
711 ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_NULL, GST_STATE_READY, 206);
713 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
714 ASSERT_OBJECT_REFCOUNT (tee, "tee", 1);
715 ASSERT_OBJECT_REFCOUNT (identity, "identity", 1);
716 ASSERT_OBJECT_REFCOUNT (sink1, "sink1", 1);
717 ASSERT_OBJECT_REFCOUNT (sink2, "sink2", 1);
718 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
720 ret = gst_element_set_state (pipeline, GST_STATE_NULL);
721 fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to NULL failed");
723 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
724 ASSERT_OBJECT_REFCOUNT (tee, "tee", 1);
725 ASSERT_OBJECT_REFCOUNT (identity, "identity", 1);
726 ASSERT_OBJECT_REFCOUNT (sink1, "sink1", 1);
727 ASSERT_OBJECT_REFCOUNT (sink2, "sink2", 1);
728 ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
730 gst_object_unref (bus);
731 gst_object_unref (pipeline);
732 }
734 GST_END_TEST;
736 Suite *
737 gst_bin_suite (void)
738 {
739 Suite *s = suite_create ("GstBin");
740 TCase *tc_chain = tcase_create ("bin tests");
742 suite_add_tcase (s, tc_chain);
743 tcase_add_test (tc_chain, test_interface);
744 tcase_add_test (tc_chain, test_children_state_change_order_flagged_sink);
745 tcase_add_test (tc_chain, test_children_state_change_order_semi_sink);
746 tcase_add_test (tc_chain, test_children_state_change_order_two_sink);
747 tcase_add_test (tc_chain, test_message_state_changed);
748 tcase_add_test (tc_chain, test_message_state_changed_child);
749 tcase_add_test (tc_chain, test_message_state_changed_children);
750 tcase_add_test (tc_chain, test_watch_for_state_change);
751 tcase_add_test (tc_chain, test_add_linked);
753 return s;
754 }
756 int
757 main (int argc, char **argv)
758 {
759 int nf;
761 Suite *s = gst_bin_suite ();
762 SRunner *sr = srunner_create (s);
764 gst_check_init (&argc, &argv);
766 srunner_run_all (sr, CK_NORMAL);
767 nf = srunner_ntests_failed (sr);
768 srunner_free (sr);
770 return nf;
771 }