mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-09 08:55:33 +00:00
gst/: Make sure that a bin state change tries to keep the children in sync.
Original commit message from CVS: * gst/gstbin.c: (set_kid_state_func), (gst_bin_set_state): * gst/gstthread.c: (gst_thread_release), (gst_thread_set_state): Make sure that a bin state change tries to keep the children in sync. Added debug logging to the thread.
This commit is contained in:
parent
a98e57cb8e
commit
f200c14dff
3 changed files with 93 additions and 14 deletions
|
@ -1,3 +1,11 @@
|
||||||
|
2004-07-28 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
|
* gst/gstbin.c: (set_kid_state_func), (gst_bin_set_state):
|
||||||
|
* gst/gstthread.c: (gst_thread_release), (gst_thread_set_state):
|
||||||
|
Make sure that a bin state change tries to keep the children
|
||||||
|
in sync.
|
||||||
|
Added debug logging to the thread.
|
||||||
|
|
||||||
2004-07-27 Steve Lhomme <steve.lhomme@free.fr>
|
2004-07-27 Steve Lhomme <steve.lhomme@free.fr>
|
||||||
|
|
||||||
* win32/GStreamer.vcproj:
|
* win32/GStreamer.vcproj:
|
||||||
|
|
96
gst/gstbin.c
96
gst/gstbin.c
|
@ -793,6 +793,7 @@ gst_bin_foreach (GstBin * bin, GstBinForeachFunc func, gpointer data)
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
GstElementState intermediate;
|
||||||
GstElementState pending;
|
GstElementState pending;
|
||||||
GstElementStateReturn result;
|
GstElementStateReturn result;
|
||||||
}
|
}
|
||||||
|
@ -810,17 +811,49 @@ set_kid_state_func (GstBin * bin, GstElement * child, gpointer user_data)
|
||||||
|
|
||||||
old_child_state = GST_STATE (child);
|
old_child_state = GST_STATE (child);
|
||||||
|
|
||||||
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
|
/* are we moving up or down? */
|
||||||
"changing state of child %s from current %s to pending %s",
|
if (data->intermediate < data->pending) {
|
||||||
GST_ELEMENT_NAME (child), gst_element_state_get_name (old_child_state),
|
/* up, check if we are already closer to target */
|
||||||
gst_element_state_get_name (data->pending));
|
if (old_child_state >= data->intermediate &&
|
||||||
|
old_child_state < data->pending) {
|
||||||
|
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
|
||||||
|
"state of child %s is %s, inbetween intermediate %s and pending %s",
|
||||||
|
GST_ELEMENT_NAME (child),
|
||||||
|
gst_element_state_get_name (old_child_state),
|
||||||
|
gst_element_state_get_name (data->intermediate),
|
||||||
|
gst_element_state_get_name (data->pending));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
} else if (data->intermediate > data->pending) {
|
||||||
|
/* down, check if we are already closer to target */
|
||||||
|
if (old_child_state < data->intermediate) {
|
||||||
|
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
|
||||||
|
"state of child %s is %s, inbetween intermediate %s and pending %s",
|
||||||
|
GST_ELEMENT_NAME (child),
|
||||||
|
gst_element_state_get_name (old_child_state),
|
||||||
|
gst_element_state_get_name (data->intermediate),
|
||||||
|
gst_element_state_get_name (data->pending));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* same state */
|
||||||
|
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
|
||||||
|
"setting final state on child %s, now in %s, going to %s",
|
||||||
|
GST_ELEMENT_NAME (child), gst_element_state_get_name (old_child_state),
|
||||||
|
gst_element_state_get_name (data->intermediate));
|
||||||
|
}
|
||||||
|
|
||||||
switch (gst_element_set_state (child, data->pending)) {
|
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
|
||||||
|
"changing state of child %s from current %s to intermediate %s",
|
||||||
|
GST_ELEMENT_NAME (child), gst_element_state_get_name (old_child_state),
|
||||||
|
gst_element_state_get_name (data->intermediate));
|
||||||
|
|
||||||
|
switch (gst_element_set_state (child, data->intermediate)) {
|
||||||
case GST_STATE_FAILURE:
|
case GST_STATE_FAILURE:
|
||||||
GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin,
|
GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin,
|
||||||
"child '%s' failed to go to state %d(%s)",
|
"child '%s' failed to go to state %d(%s)",
|
||||||
GST_ELEMENT_NAME (child),
|
GST_ELEMENT_NAME (child),
|
||||||
data->pending, gst_element_state_get_name (data->pending));
|
data->intermediate, gst_element_state_get_name (data->intermediate));
|
||||||
|
|
||||||
gst_element_set_state (child, old_child_state);
|
gst_element_set_state (child, old_child_state);
|
||||||
return FALSE; /* error out to the caller */
|
return FALSE; /* error out to the caller */
|
||||||
|
@ -834,8 +867,8 @@ set_kid_state_func (GstBin * bin, GstElement * child, gpointer user_data)
|
||||||
case GST_STATE_SUCCESS:
|
case GST_STATE_SUCCESS:
|
||||||
GST_CAT_DEBUG (GST_CAT_STATES,
|
GST_CAT_DEBUG (GST_CAT_STATES,
|
||||||
"child '%s' changed state to %d(%s) successfully",
|
"child '%s' changed state to %d(%s) successfully",
|
||||||
GST_ELEMENT_NAME (child), data->pending,
|
GST_ELEMENT_NAME (child), data->intermediate,
|
||||||
gst_element_state_get_name (data->pending));
|
gst_element_state_get_name (data->intermediate));
|
||||||
data->result = GST_STATE_SUCCESS;
|
data->result = GST_STATE_SUCCESS;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
@ -850,14 +883,49 @@ gst_bin_set_state (GstElement * element, GstElementState state)
|
||||||
{
|
{
|
||||||
GstBin *bin = GST_BIN (element);
|
GstBin *bin = GST_BIN (element);
|
||||||
SetKidStateData data;
|
SetKidStateData data;
|
||||||
|
GstElementStateReturn ret = GST_STATE_FAILURE;
|
||||||
|
GstElementState intermediate;
|
||||||
|
GstElementState pending;
|
||||||
|
|
||||||
data.pending = state;
|
/* we start with the state of the bin */
|
||||||
data.result = GST_STATE_ASYNC;
|
intermediate = GST_STATE (element);
|
||||||
if (!gst_bin_foreach (bin, set_kid_state_func, &data)) {
|
pending = state;
|
||||||
return GST_STATE_FAILURE;
|
|
||||||
} else {
|
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
|
||||||
return data.result;
|
"setting state of bin %s from current %s to pending %s",
|
||||||
|
GST_ELEMENT_NAME (element), gst_element_state_get_name (intermediate),
|
||||||
|
gst_element_state_get_name (pending));
|
||||||
|
|
||||||
|
do {
|
||||||
|
data.intermediate = intermediate;
|
||||||
|
data.pending = pending;
|
||||||
|
data.result = GST_STATE_ASYNC;
|
||||||
|
|
||||||
|
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
|
||||||
|
"setting state of children to intermediate %s",
|
||||||
|
gst_element_state_get_name (intermediate));
|
||||||
|
|
||||||
|
if (!gst_bin_foreach (bin, set_kid_state_func, &data)) {
|
||||||
|
ret = GST_STATE_FAILURE;
|
||||||
|
/* break out of the loop after failure */
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
ret = data.result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if we have reached the target state, we can stop */
|
||||||
|
if (intermediate == pending)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* move intermediate state closer to target state */
|
||||||
|
if (intermediate < pending)
|
||||||
|
intermediate <<= 1;
|
||||||
|
else
|
||||||
|
intermediate >>= 1;
|
||||||
}
|
}
|
||||||
|
while (TRUE);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstElementStateReturn
|
static GstElementStateReturn
|
||||||
|
|
|
@ -406,6 +406,7 @@ static void
|
||||||
gst_thread_release (GstThread * thread)
|
gst_thread_release (GstThread * thread)
|
||||||
{
|
{
|
||||||
if (thread != gst_thread_get_current ()) {
|
if (thread != gst_thread_get_current ()) {
|
||||||
|
GST_DEBUG_OBJECT (thread, "releasing lock");
|
||||||
g_cond_signal (thread->cond);
|
g_cond_signal (thread->cond);
|
||||||
g_mutex_unlock (thread->lock);
|
g_mutex_unlock (thread->lock);
|
||||||
}
|
}
|
||||||
|
@ -419,12 +420,14 @@ gst_thread_set_state (GstElement * element, GstElementState state)
|
||||||
|
|
||||||
if (thread != gst_thread_get_current ()) {
|
if (thread != gst_thread_get_current ()) {
|
||||||
gst_thread_catch (thread);
|
gst_thread_catch (thread);
|
||||||
|
GST_DEBUG_OBJECT (thread, "releasing lock");
|
||||||
g_mutex_unlock (thread->lock);
|
g_mutex_unlock (thread->lock);
|
||||||
}
|
}
|
||||||
result =
|
result =
|
||||||
GST_CALL_PARENT_WITH_DEFAULT (GST_ELEMENT_CLASS, set_state, (element,
|
GST_CALL_PARENT_WITH_DEFAULT (GST_ELEMENT_CLASS, set_state, (element,
|
||||||
state), GST_STATE_FAILURE);
|
state), GST_STATE_FAILURE);
|
||||||
if (thread != gst_thread_get_current ()) {
|
if (thread != gst_thread_get_current ()) {
|
||||||
|
GST_DEBUG_OBJECT (thread, "grabbing lock");
|
||||||
g_mutex_lock (thread->lock);
|
g_mutex_lock (thread->lock);
|
||||||
gst_thread_release (thread);
|
gst_thread_release (thread);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue