mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-07 07:58:51 +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>
|
2004-07-12 Benjamin Otte <otte@gnome.org>
|
||||||
|
|
||||||
* configure.ac:
|
* configure.ac:
|
||||||
|
|
135
gst/gstbin.c
135
gst/gstbin.c
|
@ -32,6 +32,7 @@
|
||||||
|
|
||||||
#include "gstscheduler.h"
|
#include "gstscheduler.h"
|
||||||
#include "gstindex.h"
|
#include "gstindex.h"
|
||||||
|
#include "gstutils.h"
|
||||||
|
|
||||||
static GstElementDetails gst_bin_details = GST_ELEMENT_DETAILS ("Generic bin",
|
static GstElementDetails gst_bin_details = GST_ELEMENT_DETAILS ("Generic bin",
|
||||||
"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_remove_func (GstBin * bin, GstElement * element);
|
||||||
static void gst_bin_child_state_change_func (GstBin * bin,
|
static void gst_bin_child_state_change_func (GstBin * bin,
|
||||||
GstElementState oldstate, GstElementState newstate, GstElement * child);
|
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 GstClock *gst_bin_get_clock_func (GstElement * element);
|
||||||
static void gst_bin_set_clock_func (GstElement * element, GstClock * clock);
|
static void gst_bin_set_clock_func (GstElement * element, GstClock * clock);
|
||||||
|
@ -161,6 +164,7 @@ gst_bin_class_init (GstBinClass * klass)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_bin_change_state);
|
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
|
#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);
|
||||||
#endif
|
#endif
|
||||||
|
@ -707,57 +711,64 @@ gst_bin_child_state_change_func (GstBin * bin, GstElementState oldstate,
|
||||||
GST_UNLOCK (bin);
|
GST_UNLOCK (bin);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef gint (*GstBinForeachFunc) (GstBin * bin, GstElement * element,
|
typedef gboolean (*GstBinForeachFunc) (GstBin * bin, GstElement * element,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
|
|
||||||
/* Call FUNC on each child of BIN, in the order that they are in bin->children.
|
/*
|
||||||
|
* gst_bin_foreach:
|
||||||
It is assumed that calling FUNC may alter the set of BIN's children. FUNC
|
* @bin: bin to traverse
|
||||||
will only be called on children that were in BIN when the gst_bin_foreach was
|
* @func: function to call on each child
|
||||||
called, and that are still in BIN when the child is reached.
|
* @data: user data handed to each function call
|
||||||
|
*
|
||||||
The return value semantics are a bit odd in this one:
|
* Calls @func on each child of the bin. If @func returns FALSE,
|
||||||
|
* gst_bin_foreach() immediately returns.
|
||||||
If FUNC returns a nonnegative number, the number is added on to the eventual
|
* It is assumed that calling @func may alter the set of @bin's children. @func
|
||||||
return value of gst_bin_foreach, which starts at 0.
|
* 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.
|
||||||
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.
|
* Returns: TRUE if @func always returned TRUE, FALSE otherwise
|
||||||
*/
|
**/
|
||||||
static gint
|
static gboolean
|
||||||
gst_bin_foreach (GstBin * bin, GstBinForeachFunc func, gpointer data)
|
gst_bin_foreach (GstBin * bin, GstBinForeachFunc func, gpointer data)
|
||||||
{
|
{
|
||||||
gint sum = 0;
|
GList *kids, *walk;
|
||||||
GList *kids = g_list_copy (bin->children);
|
|
||||||
|
|
||||||
while (kids) {
|
g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
|
||||||
GstElement *element = (GstElement *) kids->data;
|
g_return_val_if_fail (func != NULL, FALSE);
|
||||||
gint res = 0;
|
|
||||||
|
|
||||||
if (g_list_find (bin->children, element))
|
kids = g_list_copy (bin->children);
|
||||||
res = func (bin, element, data);
|
|
||||||
|
|
||||||
if (res < 0)
|
for (walk = kids; walk; walk = g_list_next (walk)) {
|
||||||
return res;
|
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);
|
g_list_free (kids);
|
||||||
return sum;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
typedef struct
|
||||||
set_kid_state_func (GstBin * bin, GstElement * child, gpointer data)
|
|
||||||
{
|
{
|
||||||
GstElementState old_child_state, pending;
|
GstElementState pending;
|
||||||
|
GstElementStateReturn result;
|
||||||
pending = (GstElementState) (GPOINTER_TO_INT (data));
|
}
|
||||||
|
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)) {
|
if (GST_FLAG_IS_SET (child, GST_ELEMENT_LOCKED_STATE)) {
|
||||||
return 0;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
old_child_state = GST_STATE (child);
|
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,
|
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
|
||||||
"changing state of child %s from current %s to pending %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 (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:
|
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),
|
||||||
pending, gst_element_state_get_name (pending));
|
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 -1; /* error out to the caller */
|
return FALSE; /* error out to the caller */
|
||||||
|
|
||||||
case GST_STATE_ASYNC:
|
case GST_STATE_ASYNC:
|
||||||
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));
|
||||||
return 1;
|
data->result = GST_STATE_ASYNC;
|
||||||
|
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), pending,
|
GST_ELEMENT_NAME (child), data->pending,
|
||||||
gst_element_state_get_name (pending));
|
gst_element_state_get_name (data->pending));
|
||||||
return 0;
|
return TRUE;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
return -1; /* satisfy gcc */
|
return FALSE; /* satisfy gcc */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -802,8 +814,7 @@ gst_bin_change_state (GstElement * element)
|
||||||
GstBin *bin;
|
GstBin *bin;
|
||||||
GstElementStateReturn ret;
|
GstElementStateReturn ret;
|
||||||
GstElementState old_state, pending;
|
GstElementState old_state, pending;
|
||||||
gint transition, kid_return;
|
SetKidStateData data;
|
||||||
gboolean have_async = FALSE;
|
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_BIN (element), GST_STATE_FAILURE);
|
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);
|
old_state = GST_STATE (element);
|
||||||
pending = GST_STATE_PENDING (element);
|
pending = GST_STATE_PENDING (element);
|
||||||
transition = GST_STATE_TRANSITION (element);
|
|
||||||
|
|
||||||
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
|
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
|
||||||
"changing state of children from %s to %s",
|
"changing state of children from %s to %s",
|
||||||
|
@ -821,15 +831,11 @@ gst_bin_change_state (GstElement * element)
|
||||||
if (pending == GST_STATE_VOID_PENDING)
|
if (pending == GST_STATE_VOID_PENDING)
|
||||||
return GST_STATE_SUCCESS;
|
return GST_STATE_SUCCESS;
|
||||||
|
|
||||||
kid_return = gst_bin_foreach (bin, set_kid_state_func,
|
data.pending = pending;
|
||||||
GINT_TO_POINTER ((int) pending));
|
data.result = GST_STATE_SUCCESS;
|
||||||
|
if (!gst_bin_foreach (bin, set_kid_state_func, &data)) {
|
||||||
/* see gst_bin_foreach return value semantics above */
|
|
||||||
if (kid_return < 0) {
|
|
||||||
GST_STATE_PENDING (element) = old_state;
|
GST_STATE_PENDING (element) = old_state;
|
||||||
return GST_STATE_FAILURE;
|
return GST_STATE_FAILURE;
|
||||||
} else if (kid_return > 0) {
|
|
||||||
have_async = TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
|
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 (pending),
|
||||||
gst_element_state_get_name (GST_STATE (element)));
|
gst_element_state_get_name (GST_STATE (element)));
|
||||||
|
|
||||||
if (have_async)
|
if (data.result == GST_STATE_ASYNC)
|
||||||
ret = GST_STATE_ASYNC;
|
ret = GST_STATE_ASYNC;
|
||||||
else {
|
else {
|
||||||
|
/* FIXME: this should have been done by the children already, no? */
|
||||||
if (parent_class->change_state) {
|
if (parent_class->change_state) {
|
||||||
ret = parent_class->change_state (element);
|
ret = parent_class->change_state (element);
|
||||||
} else
|
} else
|
||||||
|
@ -849,6 +856,26 @@ gst_bin_change_state (GstElement * element)
|
||||||
return ret;
|
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
|
static GstElementStateReturn
|
||||||
gst_bin_change_state_norecurse (GstBin * bin)
|
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);
|
GError * error, gchar * debug);
|
||||||
static void gst_element_found_tag_func (GstElement * element,
|
static void gst_element_found_tag_func (GstElement * element,
|
||||||
GstElement * source, const GstTagList * tag_list);
|
GstElement * source, const GstTagList * tag_list);
|
||||||
|
GstElementStateReturn gst_element_set_state_func (GstElement * element,
|
||||||
|
GstElementState state);
|
||||||
|
|
||||||
#ifndef GST_DISABLE_LOADSAVE
|
#ifndef GST_DISABLE_LOADSAVE
|
||||||
static xmlNodePtr gst_element_save_thyself (GstObject * object,
|
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->error = GST_DEBUG_FUNCPTR (gst_element_error_func);
|
||||||
klass->found_tag = GST_DEBUG_FUNCPTR (gst_element_found_tag_func);
|
klass->found_tag = GST_DEBUG_FUNCPTR (gst_element_found_tag_func);
|
||||||
klass->numpadtemplates = 0;
|
klass->numpadtemplates = 0;
|
||||||
|
klass->set_state = GST_DEBUG_FUNCPTR (gst_element_set_state_func);
|
||||||
|
|
||||||
klass->elementfactory = NULL;
|
klass->elementfactory = NULL;
|
||||||
}
|
}
|
||||||
|
@ -2719,43 +2722,33 @@ gst_element_wait_state_change (GstElement * element)
|
||||||
*/
|
*/
|
||||||
GstElementStateReturn
|
GstElementStateReturn
|
||||||
gst_element_set_state (GstElement * element, GstElementState state)
|
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;
|
GstElementClass *oclass;
|
||||||
GstElementState curpending;
|
GstElementState curpending;
|
||||||
GstElementStateReturn return_val = GST_STATE_SUCCESS;
|
GstElementStateReturn return_val = GST_STATE_SUCCESS;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
|
|
||||||
oclass = GST_ELEMENT_GET_CLASS (element);
|
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 */
|
/* start with the current state */
|
||||||
curpending = GST_STATE (element);
|
curpending = GST_STATE (element);
|
||||||
|
|
||||||
if (state == curpending) {
|
if (state == curpending) {
|
||||||
if (GST_IS_BIN (element)) {
|
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
|
||||||
/* set current state on it again */
|
"element is already in requested state %s, returning",
|
||||||
GST_STATE_PENDING (element) = curpending;
|
gst_element_state_get_name (state));
|
||||||
GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
|
return GST_STATE_SUCCESS;
|
||||||
"%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_INFO_OBJECT (GST_CAT_STATES, element, "setting state from %s to %s",
|
GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "setting state from %s to %s",
|
||||||
|
|
Loading…
Reference in a new issue