mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-25 19:21:06 +00:00
revert state change changes as agreed so we can rework them gradually
Original commit message from CVS: revert state change changes as agreed so we can rework them gradually
This commit is contained in:
parent
2ed6c06492
commit
8f0fda26d0
6 changed files with 167 additions and 189 deletions
15
ChangeLog
15
ChangeLog
|
@ -1,3 +1,18 @@
|
||||||
|
2004-07-29 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||||
|
|
||||||
|
* gst/gstbin.c: (gst_bin_get_type), (gst_bin_class_init),
|
||||||
|
(gst_bin_add_func), (gst_bin_remove_func),
|
||||||
|
(gst_bin_child_state_change), (gst_bin_child_state_change_func),
|
||||||
|
(set_kid_state_func), (gst_bin_change_state), (gst_bin_set_state),
|
||||||
|
(gst_bin_change_state_norecurse), (gst_bin_dispose),
|
||||||
|
(gst_bin_sync_children_state):
|
||||||
|
* gst/gstbin.h:
|
||||||
|
* gst/gstthread.c: (gst_thread_class_init), (gst_thread_release),
|
||||||
|
(gst_thread_change_state):
|
||||||
|
* testsuite/states/Makefile.am:
|
||||||
|
revert state change patches as agreed so we can rework them
|
||||||
|
gradually
|
||||||
|
|
||||||
2004-07-29 Benjamin Otte <otte@gnome.org>
|
2004-07-29 Benjamin Otte <otte@gnome.org>
|
||||||
|
|
||||||
* libs/gst/control/Makefile.am:
|
* libs/gst/control/Makefile.am:
|
||||||
|
|
286
gst/gstbin.c
286
gst/gstbin.c
|
@ -34,14 +34,6 @@
|
||||||
#include "gstindex.h"
|
#include "gstindex.h"
|
||||||
#include "gstutils.h"
|
#include "gstutils.h"
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_STATIC (bin_debug);
|
|
||||||
#define GST_CAT_DEFAULT bin_debug
|
|
||||||
#define GST_LOG_BIN_CONTENTS(bin, text) GST_LOG_OBJECT ((bin), \
|
|
||||||
text ": %d elements: %u PLAYING, %u PAUSED, %u READY, %u NULL, own state: %s", \
|
|
||||||
(bin)->numchildren, (guint) (bin)->child_states[3], \
|
|
||||||
(guint) (bin)->child_states[2], (bin)->child_states[1], \
|
|
||||||
(bin)->child_states[0], gst_element_state_get_name (GST_STATE (bin)))
|
|
||||||
|
|
||||||
static GstElementDetails gst_bin_details = GST_ELEMENT_DETAILS ("Generic bin",
|
static GstElementDetails gst_bin_details = GST_ELEMENT_DETAILS ("Generic bin",
|
||||||
"Generic/Bin",
|
"Generic/Bin",
|
||||||
"Simple container object",
|
"Simple container object",
|
||||||
|
@ -54,6 +46,7 @@ static gboolean _gst_boolean_did_something_accumulator (GSignalInvocationHint *
|
||||||
|
|
||||||
static void gst_bin_dispose (GObject * object);
|
static void gst_bin_dispose (GObject * object);
|
||||||
|
|
||||||
|
static GstElementStateReturn gst_bin_change_state (GstElement * element);
|
||||||
static GstElementStateReturn gst_bin_change_state_norecurse (GstBin * bin);
|
static GstElementStateReturn gst_bin_change_state_norecurse (GstBin * bin);
|
||||||
|
|
||||||
#ifndef GST_DISABLE_INDEX
|
#ifndef GST_DISABLE_INDEX
|
||||||
|
@ -123,8 +116,6 @@ gst_bin_get_type (void)
|
||||||
|
|
||||||
_gst_bin_type =
|
_gst_bin_type =
|
||||||
g_type_register_static (GST_TYPE_ELEMENT, "GstBin", &bin_info, 0);
|
g_type_register_static (GST_TYPE_ELEMENT, "GstBin", &bin_info, 0);
|
||||||
GST_DEBUG_CATEGORY_INIT (bin_debug, "bin", GST_DEBUG_BOLD,
|
|
||||||
"debugging info for the 'bin' container element");
|
|
||||||
}
|
}
|
||||||
return _gst_bin_type;
|
return _gst_bin_type;
|
||||||
}
|
}
|
||||||
|
@ -172,6 +163,7 @@ gst_bin_class_init (GstBinClass * klass)
|
||||||
GST_DEBUG_FUNCPTR (gst_bin_restore_thyself);
|
GST_DEBUG_FUNCPTR (gst_bin_restore_thyself);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_bin_change_state);
|
||||||
gstelement_class->set_state = GST_DEBUG_FUNCPTR (gst_bin_set_state);
|
gstelement_class->set_state = GST_DEBUG_FUNCPTR (gst_bin_set_state);
|
||||||
#ifndef GST_DISABLE_INDEX
|
#ifndef GST_DISABLE_INDEX
|
||||||
gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_bin_set_index);
|
gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_bin_set_index);
|
||||||
|
@ -449,34 +441,6 @@ gst_bin_add_many (GstBin * bin, GstElement * element_1, ...)
|
||||||
va_end (args);
|
va_end (args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* after adding or removing elements, we need to fix the state of the bin
|
|
||||||
* in a reentrant way. This is done here */
|
|
||||||
static void
|
|
||||||
gst_bin_fix_state (GstBin * bin)
|
|
||||||
{
|
|
||||||
gint i;
|
|
||||||
GstElementState desired;
|
|
||||||
|
|
||||||
while (TRUE) {
|
|
||||||
/* find the highest child state */
|
|
||||||
for (i = GST_NUM_STATES - 1; i > 0; i--) {
|
|
||||||
if (bin->child_states[i] > 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
g_assert (i < GST_NUM_STATES && i >= 0);
|
|
||||||
desired = 1 << i;
|
|
||||||
if (desired == GST_STATE (bin)) {
|
|
||||||
break;
|
|
||||||
} else if (desired < GST_STATE (bin)) {
|
|
||||||
GST_STATE_PENDING (bin) = GST_STATE (bin) >> 1;
|
|
||||||
} else { /* if (desired > GST_STATE (bin)) */
|
|
||||||
GST_STATE_PENDING (bin) = GST_STATE (bin) << 1;
|
|
||||||
}
|
|
||||||
/* this part is reentrant */
|
|
||||||
gst_bin_change_state_norecurse (bin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_bin_add_func (GstBin * bin, GstElement * element)
|
gst_bin_add_func (GstBin * bin, GstElement * element)
|
||||||
{
|
{
|
||||||
|
@ -495,14 +459,15 @@ gst_bin_add_func (GstBin * bin, GstElement * element)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ref to guard unrefs in callbacks */
|
if (GST_STATE (element) > GST_STATE (bin)) {
|
||||||
gst_object_ref (GST_OBJECT (bin));
|
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
|
||||||
gst_object_ref (GST_OBJECT (element));
|
"setting state to receive element \"%s\"", GST_OBJECT_NAME (element));
|
||||||
|
gst_element_set_state ((GstElement *) bin, GST_STATE (element));
|
||||||
|
}
|
||||||
|
|
||||||
/* set the element's parent and add the element to the bin's list of children */
|
/* set the element's parent and add the element to the bin's list of children */
|
||||||
gst_object_set_parent (GST_OBJECT (element), GST_OBJECT (bin));
|
gst_object_set_parent (GST_OBJECT (element), GST_OBJECT (bin));
|
||||||
|
|
||||||
GST_LOG_BIN_CONTENTS (bin, "before adding element");
|
|
||||||
bin->children = g_list_append (bin->children, element);
|
bin->children = g_list_append (bin->children, element);
|
||||||
bin->numchildren++;
|
bin->numchildren++;
|
||||||
|
|
||||||
|
@ -520,16 +485,10 @@ gst_bin_add_func (GstBin * bin, GstElement * element)
|
||||||
gst_bin_set_element_sched (element, sched);
|
gst_bin_set_element_sched (element, sched);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check if we need to bump state because a high state element was added */
|
|
||||||
gst_bin_fix_state (bin);
|
|
||||||
GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, bin, "added element \"%s\"",
|
GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, bin, "added element \"%s\"",
|
||||||
GST_OBJECT_NAME (element));
|
GST_OBJECT_NAME (element));
|
||||||
GST_LOG_BIN_CONTENTS (bin, "after adding element");
|
|
||||||
|
|
||||||
g_signal_emit (G_OBJECT (bin), gst_bin_signals[ELEMENT_ADDED], 0, element);
|
g_signal_emit (G_OBJECT (bin), gst_bin_signals[ELEMENT_ADDED], 0, element);
|
||||||
/* we reffed above */
|
|
||||||
gst_object_unref (GST_OBJECT (element));
|
|
||||||
gst_object_unref (GST_OBJECT (bin));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -578,13 +537,9 @@ gst_bin_remove_func (GstBin * bin, GstElement * element)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ref to guard unrefs in callbacks */
|
|
||||||
gst_object_ref (GST_OBJECT (bin));
|
|
||||||
|
|
||||||
/* remove this element from the list of managed elements */
|
/* remove this element from the list of managed elements */
|
||||||
gst_bin_unset_element_sched (element, GST_ELEMENT_SCHED (bin));
|
gst_bin_unset_element_sched (element, GST_ELEMENT_SCHED (bin));
|
||||||
|
|
||||||
GST_LOG_BIN_CONTENTS (bin, "before removing element");
|
|
||||||
/* now remove the element from the list of elements */
|
/* now remove the element from the list of elements */
|
||||||
bin->children = g_list_remove (bin->children, element);
|
bin->children = g_list_remove (bin->children, element);
|
||||||
bin->numchildren--;
|
bin->numchildren--;
|
||||||
|
@ -595,22 +550,30 @@ gst_bin_remove_func (GstBin * bin, GstElement * element)
|
||||||
state_idx++;
|
state_idx++;
|
||||||
bin->child_states[state_idx]--;
|
bin->child_states[state_idx]--;
|
||||||
|
|
||||||
GST_CAT_INFO_OBJECT (GST_CAT_PARENTAGE, bin,
|
GST_CAT_INFO_OBJECT (GST_CAT_PARENTAGE, bin, "removed child \"%s\"",
|
||||||
"removed child \"%s\", %d children left", GST_OBJECT_NAME (element),
|
GST_OBJECT_NAME (element));
|
||||||
bin->numchildren);
|
|
||||||
|
|
||||||
/* ref as we're going to emit a signal */
|
/* ref as we're going to emit a signal */
|
||||||
gst_object_ref (GST_OBJECT (element));
|
gst_object_ref (GST_OBJECT (element));
|
||||||
gst_object_unparent (GST_OBJECT (element));
|
gst_object_unparent (GST_OBJECT (element));
|
||||||
|
|
||||||
/* check the state */
|
/* if we're down to zero children, force state to NULL */
|
||||||
gst_bin_fix_state (bin);
|
while (bin->numchildren == 0 && GST_ELEMENT_SCHED (bin) != NULL &&
|
||||||
GST_LOG_BIN_CONTENTS (bin, "after removing element");
|
GST_STATE (bin) > GST_STATE_NULL) {
|
||||||
|
GstElementState next = GST_STATE (bin) >> 1;
|
||||||
|
|
||||||
|
GST_STATE_PENDING (bin) = next;
|
||||||
|
gst_bin_change_state_norecurse (bin);
|
||||||
|
if (!GST_STATE (bin) == next) {
|
||||||
|
g_warning ("bin %s failed state change to %d", GST_ELEMENT_NAME (bin),
|
||||||
|
next);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
g_signal_emit (G_OBJECT (bin), gst_bin_signals[ELEMENT_REMOVED], 0, element);
|
g_signal_emit (G_OBJECT (bin), gst_bin_signals[ELEMENT_REMOVED], 0, element);
|
||||||
|
|
||||||
/* element is really out of our control now */
|
/* element is really out of our control now */
|
||||||
gst_object_unref (GST_OBJECT (element));
|
gst_object_unref (GST_OBJECT (element));
|
||||||
gst_object_unref (GST_OBJECT (bin));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -693,8 +656,7 @@ gst_bin_child_state_change (GstBin * bin, GstElementState oldstate,
|
||||||
g_return_if_fail (GST_IS_ELEMENT (child));
|
g_return_if_fail (GST_IS_ELEMENT (child));
|
||||||
|
|
||||||
GST_CAT_LOG (GST_CAT_STATES, "child %s changed state in bin %s from %s to %s",
|
GST_CAT_LOG (GST_CAT_STATES, "child %s changed state in bin %s from %s to %s",
|
||||||
GST_ELEMENT_NAME (child) ? GST_ELEMENT_NAME (child) : "(null)",
|
GST_ELEMENT_NAME (child), GST_ELEMENT_NAME (bin),
|
||||||
GST_ELEMENT_NAME (bin) ? GST_ELEMENT_NAME (bin) : "(null)",
|
|
||||||
gst_element_state_get_name (oldstate),
|
gst_element_state_get_name (oldstate),
|
||||||
gst_element_state_get_name (newstate));
|
gst_element_state_get_name (newstate));
|
||||||
|
|
||||||
|
@ -722,7 +684,7 @@ gst_bin_child_state_change_func (GstBin * bin, GstElementState oldstate,
|
||||||
while (new >>= 1)
|
while (new >>= 1)
|
||||||
new_idx++;
|
new_idx++;
|
||||||
|
|
||||||
GST_LOG_BIN_CONTENTS (bin, "before child state change");
|
GST_LOCK (bin);
|
||||||
bin->child_states[old_idx]--;
|
bin->child_states[old_idx]--;
|
||||||
bin->child_states[new_idx]++;
|
bin->child_states[new_idx]++;
|
||||||
|
|
||||||
|
@ -735,17 +697,18 @@ gst_bin_child_state_change_func (GstBin * bin, GstElementState oldstate,
|
||||||
"highest child state is %s, changing bin state accordingly",
|
"highest child state is %s, changing bin state accordingly",
|
||||||
gst_element_state_get_name (state));
|
gst_element_state_get_name (state));
|
||||||
GST_STATE_PENDING (bin) = state;
|
GST_STATE_PENDING (bin) = state;
|
||||||
|
GST_UNLOCK (bin);
|
||||||
gst_bin_change_state_norecurse (bin);
|
gst_bin_change_state_norecurse (bin);
|
||||||
if (state != GST_STATE (bin)) {
|
if (state != GST_STATE (bin)) {
|
||||||
GST_INFO_OBJECT (bin, "state change in callback %d %d",
|
g_warning ("%s: state change in callback %d %d",
|
||||||
state, GST_STATE (bin));
|
GST_ELEMENT_NAME (bin), state, GST_STATE (bin));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GST_LOG_BIN_CONTENTS (bin, "after child state change");
|
GST_UNLOCK (bin);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef gboolean (*GstBinForeachFunc) (GstBin * bin, GstElement * element,
|
typedef gboolean (*GstBinForeachFunc) (GstBin * bin, GstElement * element,
|
||||||
|
@ -794,12 +757,10 @@ gst_bin_foreach (GstBin * bin, GstBinForeachFunc func, gpointer data)
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
GstElementState intermediate;
|
|
||||||
GstElementState pending;
|
GstElementState pending;
|
||||||
GstElementStateReturn result;
|
GstElementStateReturn result;
|
||||||
}
|
}
|
||||||
SetKidStateData;
|
SetKidStateData;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
set_kid_state_func (GstBin * bin, GstElement * child, gpointer user_data)
|
set_kid_state_func (GstBin * bin, GstElement * child, gpointer user_data)
|
||||||
{
|
{
|
||||||
|
@ -812,49 +773,17 @@ set_kid_state_func (GstBin * bin, GstElement * child, gpointer user_data)
|
||||||
|
|
||||||
old_child_state = GST_STATE (child);
|
old_child_state = GST_STATE (child);
|
||||||
|
|
||||||
/* are we moving up or down? */
|
|
||||||
if (data->intermediate < data->pending) {
|
|
||||||
/* up, check if we are already closer to target */
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
|
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
|
||||||
"changing state of child %s from current %s to intermediate %s",
|
"changing state of child %s from current %s to pending %s",
|
||||||
GST_ELEMENT_NAME (child), gst_element_state_get_name (old_child_state),
|
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));
|
||||||
|
|
||||||
switch (gst_element_set_state (child, data->intermediate)) {
|
switch (gst_element_set_state (child, data->pending)) {
|
||||||
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->intermediate, gst_element_state_get_name (data->intermediate));
|
data->pending, gst_element_state_get_name (data->pending));
|
||||||
|
|
||||||
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 */
|
||||||
|
@ -863,14 +792,14 @@ set_kid_state_func (GstBin * bin, GstElement * child, gpointer user_data)
|
||||||
GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin,
|
GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin,
|
||||||
"child '%s' is changing state asynchronously",
|
"child '%s' is changing state asynchronously",
|
||||||
GST_ELEMENT_NAME (child));
|
GST_ELEMENT_NAME (child));
|
||||||
|
data->result = GST_STATE_ASYNC;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
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->intermediate,
|
GST_ELEMENT_NAME (child), data->pending,
|
||||||
gst_element_state_get_name (data->intermediate));
|
gst_element_state_get_name (data->pending));
|
||||||
data->result = GST_STATE_SUCCESS;
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -879,66 +808,87 @@ set_kid_state_func (GstBin * bin, GstElement * child, gpointer user_data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstElementStateReturn
|
||||||
|
gst_bin_change_state (GstElement * element)
|
||||||
|
{
|
||||||
|
GstBin *bin;
|
||||||
|
GstElementStateReturn ret;
|
||||||
|
GstElementState old_state, pending;
|
||||||
|
SetKidStateData data;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GST_IS_BIN (element), GST_STATE_FAILURE);
|
||||||
|
|
||||||
|
bin = GST_BIN (element);
|
||||||
|
|
||||||
|
old_state = GST_STATE (element);
|
||||||
|
pending = GST_STATE_PENDING (element);
|
||||||
|
|
||||||
|
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
|
||||||
|
"changing state of children from %s to %s",
|
||||||
|
gst_element_state_get_name (old_state),
|
||||||
|
gst_element_state_get_name (pending));
|
||||||
|
|
||||||
|
if (pending == GST_STATE_VOID_PENDING)
|
||||||
|
return GST_STATE_SUCCESS;
|
||||||
|
|
||||||
|
data.pending = pending;
|
||||||
|
data.result = GST_STATE_SUCCESS;
|
||||||
|
if (!gst_bin_foreach (bin, set_kid_state_func, &data)) {
|
||||||
|
GST_STATE_PENDING (element) = old_state;
|
||||||
|
return GST_STATE_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
|
||||||
|
"done changing bin's state from %s to %s, now in %s",
|
||||||
|
gst_element_state_get_name (old_state),
|
||||||
|
gst_element_state_get_name (pending),
|
||||||
|
gst_element_state_get_name (GST_STATE (element)));
|
||||||
|
|
||||||
|
if (data.result == GST_STATE_ASYNC)
|
||||||
|
ret = GST_STATE_ASYNC;
|
||||||
|
else {
|
||||||
|
/* FIXME: this should have been done by the children already, no? */
|
||||||
|
if (parent_class->change_state) {
|
||||||
|
ret = parent_class->change_state (element);
|
||||||
|
} else
|
||||||
|
ret = GST_STATE_SUCCESS;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
GstElementStateReturn
|
GstElementStateReturn
|
||||||
gst_bin_set_state (GstElement * element, GstElementState state)
|
gst_bin_set_state (GstElement * element, GstElementState state)
|
||||||
{
|
{
|
||||||
GstBin *bin = GST_BIN (element);
|
GstBin *bin = GST_BIN (element);
|
||||||
SetKidStateData data;
|
|
||||||
GstElementStateReturn ret = GST_STATE_FAILURE;
|
|
||||||
GstElementState intermediate;
|
|
||||||
GstElementState pending;
|
|
||||||
|
|
||||||
/* we start with the state of the bin */
|
if (GST_STATE (bin) == state) {
|
||||||
intermediate = GST_STATE (element);
|
SetKidStateData data;
|
||||||
pending = state;
|
|
||||||
|
|
||||||
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
|
|
||||||
"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));
|
|
||||||
|
|
||||||
|
data.pending = state;
|
||||||
|
data.result = GST_STATE_SUCCESS;
|
||||||
if (!gst_bin_foreach (bin, set_kid_state_func, &data)) {
|
if (!gst_bin_foreach (bin, set_kid_state_func, &data)) {
|
||||||
ret = GST_STATE_FAILURE;
|
return GST_STATE_FAILURE;
|
||||||
/* break out of the loop after failure */
|
|
||||||
break;
|
|
||||||
} else {
|
} else {
|
||||||
ret = data.result;
|
return data.result;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
/* if we have reached the target state, we can stop */
|
return GST_CALL_PARENT_WITH_DEFAULT (GST_ELEMENT_CLASS, set_state, (element,
|
||||||
if (intermediate == pending)
|
state), GST_STATE_FAILURE);
|
||||||
break;
|
|
||||||
|
|
||||||
/* move intermediate state closer to target state */
|
|
||||||
if (intermediate < pending)
|
|
||||||
intermediate <<= 1;
|
|
||||||
else
|
|
||||||
intermediate >>= 1;
|
|
||||||
}
|
}
|
||||||
while (TRUE);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstElementStateReturn
|
static GstElementStateReturn
|
||||||
gst_bin_change_state_norecurse (GstBin * bin)
|
gst_bin_change_state_norecurse (GstBin * bin)
|
||||||
{
|
{
|
||||||
GstElementClass *klass;
|
GstElementStateReturn ret;
|
||||||
|
|
||||||
klass = GST_ELEMENT_GET_CLASS (bin);
|
if (parent_class->change_state) {
|
||||||
g_return_val_if_fail (klass->change_state, GST_STATE_FAILURE);
|
GST_CAT_LOG_OBJECT (GST_CAT_STATES, bin, "setting bin's own state");
|
||||||
|
ret = parent_class->change_state (GST_ELEMENT (bin));
|
||||||
|
|
||||||
GST_CAT_LOG_OBJECT (GST_CAT_STATES, bin, "setting bin's own state");
|
return ret;
|
||||||
return klass->change_state (GST_ELEMENT (bin));
|
} else
|
||||||
|
return GST_STATE_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -955,10 +905,6 @@ gst_bin_dispose (GObject * object)
|
||||||
}
|
}
|
||||||
g_assert (bin->children == NULL);
|
g_assert (bin->children == NULL);
|
||||||
g_assert (bin->numchildren == 0);
|
g_assert (bin->numchildren == 0);
|
||||||
g_assert (bin->child_states[3] == 0); /* playing */
|
|
||||||
g_assert (bin->child_states[2] == 0); /* paused */
|
|
||||||
g_assert (bin->child_states[1] == 0); /* ready */
|
|
||||||
g_assert (bin->child_states[0] == 0); /* null */
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
|
@ -1141,10 +1087,40 @@ gst_bin_get_all_by_interface (GstBin * bin, GType interface)
|
||||||
GstElementStateReturn
|
GstElementStateReturn
|
||||||
gst_bin_sync_children_state (GstBin * bin)
|
gst_bin_sync_children_state (GstBin * bin)
|
||||||
{
|
{
|
||||||
|
GList *children;
|
||||||
|
GstElement *element;
|
||||||
|
GstElementState state;
|
||||||
|
GstElementStateReturn ret = GST_STATE_SUCCESS;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_BIN (bin), GST_STATE_FAILURE);
|
g_return_val_if_fail (GST_IS_BIN (bin), GST_STATE_FAILURE);
|
||||||
|
|
||||||
return gst_element_set_state (GST_ELEMENT (bin),
|
state = GST_STATE (bin);
|
||||||
gst_element_get_state (GST_ELEMENT (bin)));
|
children = bin->children;
|
||||||
|
GST_CAT_INFO (GST_CAT_STATES,
|
||||||
|
"syncing state of children with bin \"%s\"'s state %s",
|
||||||
|
GST_ELEMENT_NAME (bin), gst_element_state_get_name (state));
|
||||||
|
|
||||||
|
while (children) {
|
||||||
|
element = GST_ELEMENT (children->data);
|
||||||
|
children = children->next;
|
||||||
|
if (GST_STATE (element) != state) {
|
||||||
|
switch (gst_element_set_state (element, state)) {
|
||||||
|
case GST_STATE_SUCCESS:
|
||||||
|
break;
|
||||||
|
case GST_STATE_ASYNC:
|
||||||
|
if (ret == GST_STATE_SUCCESS)
|
||||||
|
ret = GST_STATE_ASYNC;
|
||||||
|
break;
|
||||||
|
case GST_STATE_FAILURE:
|
||||||
|
ret = GST_STATE_FAILURE;
|
||||||
|
default:
|
||||||
|
/* make sure gst_element_set_state never returns this */
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef GST_DISABLE_LOADSAVE
|
#ifndef GST_DISABLE_LOADSAVE
|
||||||
|
|
|
@ -63,7 +63,6 @@ struct _GstBin {
|
||||||
gint numchildren;
|
gint numchildren;
|
||||||
GList *children;
|
GList *children;
|
||||||
|
|
||||||
/* FIXME 0.9: important!! make this guint instead of GstElementState */
|
|
||||||
GstElementState child_states[GST_NUM_STATES];
|
GstElementState child_states[GST_NUM_STATES];
|
||||||
|
|
||||||
gpointer _gst_reserved[GST_PADDING];
|
gpointer _gst_reserved[GST_PADDING];
|
||||||
|
@ -111,9 +110,7 @@ void gst_bin_use_clock (GstBin *bin, GstClock *clock);
|
||||||
GstClock* gst_bin_get_clock (GstBin *bin);
|
GstClock* gst_bin_get_clock (GstBin *bin);
|
||||||
void gst_bin_auto_clock (GstBin *bin);
|
void gst_bin_auto_clock (GstBin *bin);
|
||||||
|
|
||||||
#ifndef GST_DISABLE_DEPRECATED
|
|
||||||
GstElementStateReturn gst_bin_sync_children_state (GstBin *bin);
|
GstElementStateReturn gst_bin_sync_children_state (GstBin *bin);
|
||||||
#endif
|
|
||||||
|
|
||||||
/* internal */
|
/* internal */
|
||||||
/* one of our childs signaled a state change */
|
/* one of our childs signaled a state change */
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
#include "gstmarshal.h"
|
#include "gstmarshal.h"
|
||||||
#include "gstscheduler.h"
|
#include "gstscheduler.h"
|
||||||
#include "gstinfo.h"
|
#include "gstinfo.h"
|
||||||
#include "gstutils.h"
|
|
||||||
|
|
||||||
#define GST_CAT_DEFAULT GST_CAT_THREAD
|
#define GST_CAT_DEFAULT GST_CAT_THREAD
|
||||||
#define STACK_SIZE 0x200000
|
#define STACK_SIZE 0x200000
|
||||||
|
@ -72,8 +71,6 @@ static void gst_thread_set_property (GObject * object, guint prop_id,
|
||||||
static void gst_thread_get_property (GObject * object, guint prop_id,
|
static void gst_thread_get_property (GObject * object, guint prop_id,
|
||||||
GValue * value, GParamSpec * pspec);
|
GValue * value, GParamSpec * pspec);
|
||||||
static GstElementStateReturn gst_thread_change_state (GstElement * element);
|
static GstElementStateReturn gst_thread_change_state (GstElement * element);
|
||||||
static GstElementStateReturn gst_thread_set_state (GstElement * element,
|
|
||||||
GstElementState state);
|
|
||||||
static void gst_thread_child_state_change (GstBin * bin,
|
static void gst_thread_child_state_change (GstBin * bin,
|
||||||
GstElementState oldstate, GstElementState newstate, GstElement * element);
|
GstElementState oldstate, GstElementState newstate, GstElement * element);
|
||||||
|
|
||||||
|
@ -184,7 +181,6 @@ gst_thread_class_init (gpointer g_class, gpointer class_data)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_thread_change_state);
|
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_thread_change_state);
|
||||||
gstelement_class->set_state = GST_DEBUG_FUNCPTR (gst_thread_set_state);
|
|
||||||
|
|
||||||
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_thread_set_property);
|
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_thread_set_property);
|
||||||
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_thread_get_property);
|
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_thread_get_property);
|
||||||
|
@ -406,34 +402,11 @@ 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstElementStateReturn
|
|
||||||
gst_thread_set_state (GstElement * element, GstElementState state)
|
|
||||||
{
|
|
||||||
GstElementStateReturn result;
|
|
||||||
GstThread *thread = GST_THREAD (element);
|
|
||||||
|
|
||||||
if (thread != gst_thread_get_current ()) {
|
|
||||||
gst_thread_catch (thread);
|
|
||||||
GST_DEBUG_OBJECT (thread, "releasing lock");
|
|
||||||
g_mutex_unlock (thread->lock);
|
|
||||||
}
|
|
||||||
result =
|
|
||||||
GST_CALL_PARENT_WITH_DEFAULT (GST_ELEMENT_CLASS, set_state, (element,
|
|
||||||
state), GST_STATE_FAILURE);
|
|
||||||
if (thread != gst_thread_get_current ()) {
|
|
||||||
GST_DEBUG_OBJECT (thread, "grabbing lock");
|
|
||||||
g_mutex_lock (thread->lock);
|
|
||||||
gst_thread_release (thread);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GstElementStateReturn
|
static GstElementStateReturn
|
||||||
gst_thread_change_state (GstElement * element)
|
gst_thread_change_state (GstElement * element)
|
||||||
{
|
{
|
||||||
|
@ -478,13 +451,30 @@ gst_thread_change_state (GstElement * element)
|
||||||
break;
|
break;
|
||||||
case GST_STATE_PAUSED_TO_PLAYING:
|
case GST_STATE_PAUSED_TO_PLAYING:
|
||||||
{
|
{
|
||||||
|
/* FIXME: recurse into sub-bins */
|
||||||
|
GList *elements = (GList *) gst_bin_get_list (GST_BIN (thread));
|
||||||
|
|
||||||
|
while (elements) {
|
||||||
|
gst_element_enable_threadsafe_properties ((GstElement *) elements->
|
||||||
|
data);
|
||||||
|
elements = g_list_next (elements);
|
||||||
|
}
|
||||||
/* reset self to spinning */
|
/* reset self to spinning */
|
||||||
if (thread == gst_thread_get_current ())
|
if (thread == gst_thread_get_current ())
|
||||||
GST_FLAG_SET (thread, GST_THREAD_STATE_SPINNING);
|
GST_FLAG_SET (thread, GST_THREAD_STATE_SPINNING);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GST_STATE_PLAYING_TO_PAUSED:
|
case GST_STATE_PLAYING_TO_PAUSED:
|
||||||
|
{
|
||||||
|
GList *elements = (GList *) gst_bin_get_list (GST_BIN (thread));
|
||||||
|
|
||||||
|
while (elements) {
|
||||||
|
gst_element_disable_threadsafe_properties ((GstElement *) elements->
|
||||||
|
data);
|
||||||
|
elements = g_list_next (elements);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case GST_STATE_PAUSED_TO_READY:
|
case GST_STATE_PAUSED_TO_READY:
|
||||||
break;
|
break;
|
||||||
case GST_STATE_READY_TO_NULL:
|
case GST_STATE_READY_TO_NULL:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
include ../Rules
|
include ../Rules
|
||||||
|
|
||||||
tests_pass = locked parent bin
|
tests_pass = locked parent
|
||||||
tests_fail =
|
tests_fail =
|
||||||
tests_ignore =
|
tests_ignore = bin
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
include ../Rules
|
include ../Rules
|
||||||
|
|
||||||
tests_pass = locked parent bin
|
tests_pass = locked parent
|
||||||
tests_fail =
|
tests_fail =
|
||||||
tests_ignore =
|
tests_ignore = bin
|
||||||
|
|
Loading…
Reference in a new issue