summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntoine Tremblay <hexa00@gmail.com>2009-08-18 11:36:36 +0200
committerSebastian Dröge <sebastian.droege@collabora.co.uk>2009-08-18 11:36:36 +0200
commitc87d55170512153d3025f32275f198e9b86f1172 (patch)
treebdf140576fc0ae8a8a0bd04624dcd41da53db447
parenta0ed1a44a54604a4efae7f926d70e00021db09b6 (diff)
gstbin: Don't try to change children's state if they're already in the state we want
Fixes bug #368536.
-rw-r--r--gst/gstbin.c30
1 files changed, 27 insertions, 3 deletions
diff --git a/gst/gstbin.c b/gst/gstbin.c
index 5c80d25d9c..533dca8ef7 100644
--- a/gst/gstbin.c
+++ b/gst/gstbin.c
@@ -1979,6 +1979,7 @@ gst_bin_element_set_state (GstBin * bin, GstElement * element,
GstState next)
{
GstStateChangeReturn ret;
+ GstState pending, child_current, child_pending;
gboolean locked;
GList *found;
@@ -1990,8 +1991,10 @@ gst_bin_element_set_state (GstBin * bin, GstElement * element,
element->base_time = base_time;
/* peel off the locked flag */
locked = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
- /* get previous state return */
+ /* Get the previous set_state result to preserve NO_PREROLL and ASYNC */
ret = GST_STATE_RETURN (element);
+ child_current = GST_STATE (element);
+ child_pending = GST_STATE_PENDING (element);
GST_OBJECT_UNLOCK (element);
/* skip locked elements */
@@ -2007,6 +2010,16 @@ gst_bin_element_set_state (GstBin * bin, GstElement * element,
}
GST_OBJECT_LOCK (bin);
+ pending = GST_STATE_PENDING (bin);
+
+ /* Try not to change the state of elements that are already in the state we're
+ * going to */
+ if (!(child_pending != GST_STATE_VOID_PENDING ||
+ (child_pending == GST_STATE_VOID_PENDING &&
+ ((pending > child_current && next > child_current) ||
+ (pending < child_current && next < child_current)))))
+ goto unneeded;
+
/* 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. */
if ((found =
@@ -2064,6 +2077,18 @@ was_busy:
GST_STATE_UNLOCK (element);
return GST_STATE_CHANGE_ASYNC;
}
+unneeded:
+ {
+ GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
+ "skipping transition from %s to %s, since bin pending"
+ " is %s : last change state return follows",
+ gst_element_state_get_name (child_current),
+ gst_element_state_get_name (next),
+ gst_element_state_get_name (pending));
+ GST_OBJECT_UNLOCK (bin);
+ GST_STATE_UNLOCK (element);
+ return ret;
+ }
}
/* gst_iterator_fold functions for pads_activate
@@ -2330,8 +2355,7 @@ restart:
child = GST_ELEMENT_CAST (data);
/* set state and base_time now */
- ret =
- gst_bin_element_set_state (bin, child, base_time, start_time,
+ ret = gst_bin_element_set_state (bin, child, base_time, start_time,
current, next);
switch (ret) {