]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/gstreamer0-10.git/blob - check/gst/gstbin.c
015c51bcc7299c1061029fced1094de91d37f926
[glsdk/gstreamer0-10.git] / check / gst / gstbin.c
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);
105 GST_END_TEST;
107 GST_START_TEST (test_message_state_changed)
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);
140 GST_END_TEST;
142 GST_START_TEST (test_message_state_changed_child)
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);
199 GST_END_TEST;
201 GST_START_TEST (test_message_state_changed_children)
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);
322 GST_END_TEST;
324 GST_START_TEST (test_watch_for_state_change)
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, GST_MESSAGE_ANY) == 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, GST_MESSAGE_ANY) == 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, GST_MESSAGE_ANY) == 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);
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)
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);
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)
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);
545 GST_END_TEST;
548 GST_START_TEST (test_children_state_change_order_semi_sink)
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);
638 GST_END_TEST;
640 GST_START_TEST (test_children_state_change_order_two_sink)
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);
734 GST_END_TEST;
736 Suite *
737 gst_bin_suite (void)
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;
756 int
757 main (int argc, char **argv)
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;