diff --git a/ChangeLog b/ChangeLog index 86f3534fb5..ca60622acc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2007-08-14 Wim Taymans + + * gst/gstbin.c: (gst_bin_element_set_state): + Always change the state of a NO_PREROLL element even if it has ASYNC + elements inside (in case of a bin). + + * tests/check/generic/sinks.c: (GST_START_TEST), (gst_sinks_suite): + Unit test for this case. + 2007-08-13 Stefan Kost * libs/gst/check/gstbufferstraw.c: diff --git a/gst/gstbin.c b/gst/gstbin.c index 1085e8c3e4..03ab44c235 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -1834,6 +1834,14 @@ gst_bin_element_set_state (GstBin * bin, GstElement * element, if (G_UNLIKELY (locked)) goto locked; + /* if the element was no preroll, just start changing the state regardless + * if it had async elements (in the case of a bin) because they won't preroll + * anyway. */ + if (G_UNLIKELY (ret == GST_STATE_CHANGE_NO_PREROLL)) { + GST_DEBUG_OBJECT (element, "element is NO_PREROLL, ignore async elements"); + goto no_preroll; + } + GST_OBJECT_LOCK (bin); /* the element was busy with an upwards async state change, we must wait for * an ASYNC_DONE message before we attemp to change the state. */ @@ -1864,6 +1872,7 @@ gst_bin_element_set_state (GstBin * bin, GstElement * element, no_latency: GST_OBJECT_UNLOCK (bin); +no_preroll: GST_DEBUG_OBJECT (bin, "setting element %s to %s, base_time %" GST_TIME_FORMAT, GST_ELEMENT_NAME (element), gst_element_state_get_name (next), diff --git a/tests/check/generic/sinks.c b/tests/check/generic/sinks.c index acfad82d46..9dab91941b 100644 --- a/tests/check/generic/sinks.c +++ b/tests/check/generic/sinks.c @@ -846,9 +846,59 @@ GST_START_TEST (test_add_live2) GST_END_TEST; +GST_START_TEST (test_bin_live) +{ + GstElement *sink, *src, *pipeline, *bin; + GstStateChangeReturn ret; + GstState current, pending; + GstPad *srcpad, *sinkpad; + + pipeline = gst_pipeline_new ("pipeline"); + bin = gst_bin_new ("bin"); + src = gst_element_factory_make ("fakesrc", "src"); + g_object_set (G_OBJECT (src), "is-live", TRUE, NULL); + sink = gst_element_factory_make ("fakesink", "sink"); + + gst_bin_add (GST_BIN (bin), src); + gst_bin_add (GST_BIN (bin), sink); + gst_bin_add (GST_BIN (pipeline), bin); + + srcpad = gst_element_get_pad (src, "src"); + sinkpad = gst_element_get_pad (sink, "sink"); + gst_pad_link (srcpad, sinkpad); + gst_object_unref (srcpad); + gst_object_unref (sinkpad); + + /* PAUSED returns NO_PREROLL because of the live source */ + ret = gst_element_set_state (pipeline, GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, + "no NO_PREROLL state return"); + ret = + gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_NO_PREROLL, "not NO_PREROLL"); + fail_unless (current == GST_STATE_PAUSED, "not paused"); + fail_unless (pending == GST_STATE_VOID_PENDING, "not void pending"); + + /* when going to PLAYING, the sink should go to PLAYING ASYNC */ + ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not ASYNC"); + + /* now wait for PLAYING to complete */ + ret = + gst_element_get_state (pipeline, ¤t, &pending, GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "not playing"); + fail_unless (current == GST_STATE_PLAYING, "not playing"); + fail_unless (pending == GST_STATE_VOID_PENDING, "not void pending"); + + ret = gst_element_set_state (pipeline, GST_STATE_NULL); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "cannot null pipeline"); + + gst_object_unref (pipeline); +} + +GST_END_TEST /* test: try changing state of sinks */ -Suite * -gst_sinks_suite (void) + Suite * gst_sinks_suite (void) { Suite *s = suite_create ("Sinks"); TCase *tc_chain = tcase_create ("general"); @@ -868,6 +918,7 @@ gst_sinks_suite (void) tcase_add_test (tc_chain, test_added_async2); tcase_add_test (tc_chain, test_add_live); tcase_add_test (tc_chain, test_add_live2); + tcase_add_test (tc_chain, test_bin_live); return s; }