mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 11:41:09 +00:00
gst/gstelement.c: virutalize gst_element_set_state, use set_state member in class struct that was already added in 0....
Original commit message from CVS: * gst/gstelement.c: (gst_element_class_init), (gst_element_set_state), (gst_element_set_state_func): virutalize gst_element_set_state, use set_state member in class struct that was already added in 0.7 for this. * gst/gstbin.c: (gst_bin_foreach), (set_kid_state_func), (gst_bin_change_state): make gst_bin_foreach works similar to other foreach functions, plug memleaks in it. Make functions using it work with the new approach. Document gst_bin_foreach, so it can be exported if we want to * gst/gstbin.c: (gst_bin_class_init), (gst_bin_set_state): use virtualized set_state to make set_state on bins set the state of all its children.
This commit is contained in:
parent
2ab9d39848
commit
d77dbaac2f
3 changed files with 115 additions and 80 deletions
15
ChangeLog
15
ChangeLog
|
@ -1,3 +1,18 @@
|
|||
2004-07-12 Benjamin Otte <otte@gnome.org>
|
||||
|
||||
* gst/gstelement.c: (gst_element_class_init),
|
||||
(gst_element_set_state), (gst_element_set_state_func):
|
||||
virutalize gst_element_set_state, use set_state member in class
|
||||
struct that was already added in 0.7 for this.
|
||||
* gst/gstbin.c: (gst_bin_foreach), (set_kid_state_func),
|
||||
(gst_bin_change_state):
|
||||
make gst_bin_foreach works similar to other foreach functions, plug
|
||||
memleaks in it. Make functions using it work with the new approach.
|
||||
Document gst_bin_foreach, so it can be exported if we want to
|
||||
* gst/gstbin.c: (gst_bin_class_init), (gst_bin_set_state):
|
||||
use virtualized set_state to make set_state on bins set the state of
|
||||
all its children.
|
||||
|
||||
2004-07-12 Benjamin Otte <otte@gnome.org>
|
||||
|
||||
* configure.ac:
|
||||
|
|
135
gst/gstbin.c
135
gst/gstbin.c
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include "gstscheduler.h"
|
||||
#include "gstindex.h"
|
||||
#include "gstutils.h"
|
||||
|
||||
static GstElementDetails gst_bin_details = GST_ELEMENT_DETAILS ("Generic bin",
|
||||
"Generic/Bin",
|
||||
|
@ -56,6 +57,8 @@ static void gst_bin_add_func (GstBin * bin, GstElement * element);
|
|||
static void gst_bin_remove_func (GstBin * bin, GstElement * element);
|
||||
static void gst_bin_child_state_change_func (GstBin * bin,
|
||||
GstElementState oldstate, GstElementState newstate, GstElement * child);
|
||||
GstElementStateReturn gst_bin_set_state (GstElement * element,
|
||||
GstElementState state);
|
||||
|
||||
static GstClock *gst_bin_get_clock_func (GstElement * element);
|
||||
static void gst_bin_set_clock_func (GstElement * element, GstClock * clock);
|
||||
|
@ -161,6 +164,7 @@ gst_bin_class_init (GstBinClass * klass)
|
|||
#endif
|
||||
|
||||
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_bin_change_state);
|
||||
gstelement_class->set_state = GST_DEBUG_FUNCPTR (gst_bin_set_state);
|
||||
#ifndef GST_DISABLE_INDEX
|
||||
gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_bin_set_index);
|
||||
#endif
|
||||
|
@ -707,57 +711,64 @@ gst_bin_child_state_change_func (GstBin * bin, GstElementState oldstate,
|
|||
GST_UNLOCK (bin);
|
||||
}
|
||||
|
||||
typedef gint (*GstBinForeachFunc) (GstBin * bin, GstElement * element,
|
||||
typedef gboolean (*GstBinForeachFunc) (GstBin * bin, GstElement * element,
|
||||
gpointer data);
|
||||
|
||||
/* Call FUNC on each child of BIN, in the order that they are in bin->children.
|
||||
|
||||
It is assumed that calling FUNC may alter the set of BIN's children. FUNC
|
||||
will only be called on children that were in BIN when the gst_bin_foreach was
|
||||
called, and that are still in BIN when the child is reached.
|
||||
|
||||
The return value semantics are a bit odd in this one:
|
||||
|
||||
If FUNC returns a nonnegative number, the number is added on to the eventual
|
||||
return value of gst_bin_foreach, which starts at 0.
|
||||
|
||||
If any FUNC returns a negative number, that value is immediately returned to
|
||||
the caller. In that case, the child list might only be partially traversed.
|
||||
*/
|
||||
static gint
|
||||
/*
|
||||
* gst_bin_foreach:
|
||||
* @bin: bin to traverse
|
||||
* @func: function to call on each child
|
||||
* @data: user data handed to each function call
|
||||
*
|
||||
* Calls @func on each child of the bin. If @func returns FALSE,
|
||||
* gst_bin_foreach() immediately returns.
|
||||
* It is assumed that calling @func may alter the set of @bin's children. @func
|
||||
* will only be called on children that were in @bin when gst_bin_foreach() was
|
||||
* called, and that are still in @bin when the child is reached.
|
||||
*
|
||||
* Returns: TRUE if @func always returned TRUE, FALSE otherwise
|
||||
**/
|
||||
static gboolean
|
||||
gst_bin_foreach (GstBin * bin, GstBinForeachFunc func, gpointer data)
|
||||
{
|
||||
gint sum = 0;
|
||||
GList *kids = g_list_copy (bin->children);
|
||||
GList *kids, *walk;
|
||||
|
||||
while (kids) {
|
||||
GstElement *element = (GstElement *) kids->data;
|
||||
gint res = 0;
|
||||
g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
|
||||
g_return_val_if_fail (func != NULL, FALSE);
|
||||
|
||||
if (g_list_find (bin->children, element))
|
||||
res = func (bin, element, data);
|
||||
kids = g_list_copy (bin->children);
|
||||
|
||||
if (res < 0)
|
||||
return res;
|
||||
for (walk = kids; walk; walk = g_list_next (walk)) {
|
||||
GstElement *element = (GstElement *) walk->data;
|
||||
|
||||
sum += res;
|
||||
if (g_list_find (bin->children, element)) {
|
||||
gboolean res = func (bin, element, data);
|
||||
|
||||
kids = kids->next;
|
||||
if (!res) {
|
||||
g_list_free (kids);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_list_free (kids);
|
||||
return sum;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
set_kid_state_func (GstBin * bin, GstElement * child, gpointer data)
|
||||
typedef struct
|
||||
{
|
||||
GstElementState old_child_state, pending;
|
||||
|
||||
pending = (GstElementState) (GPOINTER_TO_INT (data));
|
||||
GstElementState pending;
|
||||
GstElementStateReturn result;
|
||||
}
|
||||
SetKidStateData;
|
||||
static int
|
||||
set_kid_state_func (GstBin * bin, GstElement * child, gpointer user_data)
|
||||
{
|
||||
GstElementState old_child_state;
|
||||
SetKidStateData *data = user_data;
|
||||
|
||||
if (GST_FLAG_IS_SET (child, GST_ELEMENT_LOCKED_STATE)) {
|
||||
return 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
old_child_state = GST_STATE (child);
|
||||
|
@ -765,34 +776,35 @@ set_kid_state_func (GstBin * bin, GstElement * child, gpointer data)
|
|||
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
|
||||
"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_state_get_name (pending));
|
||||
gst_element_state_get_name (data->pending));
|
||||
|
||||
switch (gst_element_set_state (child, pending)) {
|
||||
switch (gst_element_set_state (child, data->pending)) {
|
||||
case GST_STATE_FAILURE:
|
||||
GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin,
|
||||
"child '%s' failed to go to state %d(%s)",
|
||||
GST_ELEMENT_NAME (child),
|
||||
pending, gst_element_state_get_name (pending));
|
||||
data->pending, gst_element_state_get_name (data->pending));
|
||||
|
||||
gst_element_set_state (child, old_child_state);
|
||||
return -1; /* error out to the caller */
|
||||
return FALSE; /* error out to the caller */
|
||||
|
||||
case GST_STATE_ASYNC:
|
||||
GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin,
|
||||
"child '%s' is changing state asynchronously",
|
||||
GST_ELEMENT_NAME (child));
|
||||
return 1;
|
||||
data->result = GST_STATE_ASYNC;
|
||||
return TRUE;
|
||||
|
||||
case GST_STATE_SUCCESS:
|
||||
GST_CAT_DEBUG (GST_CAT_STATES,
|
||||
"child '%s' changed state to %d(%s) successfully",
|
||||
GST_ELEMENT_NAME (child), pending,
|
||||
gst_element_state_get_name (pending));
|
||||
return 0;
|
||||
GST_ELEMENT_NAME (child), data->pending,
|
||||
gst_element_state_get_name (data->pending));
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return -1; /* satisfy gcc */
|
||||
return FALSE; /* satisfy gcc */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -802,8 +814,7 @@ gst_bin_change_state (GstElement * element)
|
|||
GstBin *bin;
|
||||
GstElementStateReturn ret;
|
||||
GstElementState old_state, pending;
|
||||
gint transition, kid_return;
|
||||
gboolean have_async = FALSE;
|
||||
SetKidStateData data;
|
||||
|
||||
g_return_val_if_fail (GST_IS_BIN (element), GST_STATE_FAILURE);
|
||||
|
||||
|
@ -811,7 +822,6 @@ gst_bin_change_state (GstElement * element)
|
|||
|
||||
old_state = GST_STATE (element);
|
||||
pending = GST_STATE_PENDING (element);
|
||||
transition = GST_STATE_TRANSITION (element);
|
||||
|
||||
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
|
||||
"changing state of children from %s to %s",
|
||||
|
@ -821,15 +831,11 @@ gst_bin_change_state (GstElement * element)
|
|||
if (pending == GST_STATE_VOID_PENDING)
|
||||
return GST_STATE_SUCCESS;
|
||||
|
||||
kid_return = gst_bin_foreach (bin, set_kid_state_func,
|
||||
GINT_TO_POINTER ((int) pending));
|
||||
|
||||
/* see gst_bin_foreach return value semantics above */
|
||||
if (kid_return < 0) {
|
||||
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;
|
||||
} else if (kid_return > 0) {
|
||||
have_async = TRUE;
|
||||
}
|
||||
|
||||
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
|
||||
|
@ -838,9 +844,10 @@ gst_bin_change_state (GstElement * element)
|
|||
gst_element_state_get_name (pending),
|
||||
gst_element_state_get_name (GST_STATE (element)));
|
||||
|
||||
if (have_async)
|
||||
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
|
||||
|
@ -849,6 +856,26 @@ gst_bin_change_state (GstElement * element)
|
|||
return ret;
|
||||
}
|
||||
|
||||
GstElementStateReturn
|
||||
gst_bin_set_state (GstElement * element, GstElementState state)
|
||||
{
|
||||
GstBin *bin = GST_BIN (element);
|
||||
|
||||
if (GST_STATE (bin) == state) {
|
||||
SetKidStateData data;
|
||||
|
||||
data.pending = state;
|
||||
data.result = GST_STATE_SUCCESS;
|
||||
if (!gst_bin_foreach (bin, set_kid_state_func, &data)) {
|
||||
return GST_STATE_FAILURE;
|
||||
} else {
|
||||
return data.result;
|
||||
}
|
||||
} else {
|
||||
return GST_CALL_PARENT_WITH_DEFAULT (GST_ELEMENT_CLASS, set_state, (element,
|
||||
state), GST_STATE_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
static GstElementStateReturn
|
||||
gst_bin_change_state_norecurse (GstBin * bin)
|
||||
|
|
|
@ -76,6 +76,8 @@ static void gst_element_error_func (GstElement * element, GstElement * source,
|
|||
GError * error, gchar * debug);
|
||||
static void gst_element_found_tag_func (GstElement * element,
|
||||
GstElement * source, const GstTagList * tag_list);
|
||||
GstElementStateReturn gst_element_set_state_func (GstElement * element,
|
||||
GstElementState state);
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
static xmlNodePtr gst_element_save_thyself (GstObject * object,
|
||||
|
@ -170,6 +172,7 @@ gst_element_class_init (GstElementClass * klass)
|
|||
klass->error = GST_DEBUG_FUNCPTR (gst_element_error_func);
|
||||
klass->found_tag = GST_DEBUG_FUNCPTR (gst_element_found_tag_func);
|
||||
klass->numpadtemplates = 0;
|
||||
klass->set_state = GST_DEBUG_FUNCPTR (gst_element_set_state_func);
|
||||
|
||||
klass->elementfactory = NULL;
|
||||
}
|
||||
|
@ -2719,43 +2722,33 @@ gst_element_wait_state_change (GstElement * element)
|
|||
*/
|
||||
GstElementStateReturn
|
||||
gst_element_set_state (GstElement * element, GstElementState state)
|
||||
{
|
||||
GstElementClass *klass = GST_ELEMENT_GET_CLASS (element);
|
||||
|
||||
g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
|
||||
klass = GST_ELEMENT_GET_CLASS (element);
|
||||
/* a set_state function is mandatory */
|
||||
g_return_val_if_fail (klass->set_state, GST_STATE_FAILURE);
|
||||
return klass->set_state (element, state);
|
||||
}
|
||||
|
||||
GstElementStateReturn
|
||||
gst_element_set_state_func (GstElement * element, GstElementState state)
|
||||
{
|
||||
GstElementClass *oclass;
|
||||
GstElementState curpending;
|
||||
GstElementStateReturn return_val = GST_STATE_SUCCESS;
|
||||
|
||||
g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
|
||||
oclass = GST_ELEMENT_GET_CLASS (element);
|
||||
|
||||
/* for bins, we allow calls to change_state where old == new
|
||||
* for elements, too many of them break with g_assert_not_reached(),
|
||||
* so weed those out first. This is done in gst-plugins CVS and can
|
||||
* be fixed here after a new plugins release.
|
||||
* FIXME: of course this file should not have ties to gstbin.h *at all*,
|
||||
* but someone else added a function at the bottom using it.
|
||||
* Fix this properly for 0.9 */
|
||||
|
||||
/* start with the current state */
|
||||
curpending = GST_STATE (element);
|
||||
|
||||
if (state == curpending) {
|
||||
if (GST_IS_BIN (element)) {
|
||||
/* set current state on it again */
|
||||
GST_STATE_PENDING (element) = curpending;
|
||||
GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
|
||||
"%s is a bin, calling class state change on it for %s -> %s",
|
||||
GST_OBJECT_NAME (element),
|
||||
gst_element_state_get_name (curpending),
|
||||
gst_element_state_get_name (state));
|
||||
if (oclass->change_state)
|
||||
return_val = (oclass->change_state) (element);
|
||||
return return_val;
|
||||
} else {
|
||||
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
|
||||
"non-bin element is already in requested state %s, returning",
|
||||
gst_element_state_get_name (state));
|
||||
return GST_STATE_SUCCESS;
|
||||
}
|
||||
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
|
||||
"element is already in requested state %s, returning",
|
||||
gst_element_state_get_name (state));
|
||||
return GST_STATE_SUCCESS;
|
||||
}
|
||||
|
||||
GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "setting state from %s to %s",
|
||||
|
|
Loading…
Reference in a new issue