From: Wim Taymans Date: Mon, 24 Dec 2001 15:14:03 +0000 (+0000) Subject: Better, cleaner state management of the scheduler by adding scheduler state flags. X-Git-Tag: RELEASE-0_3_1-BELGIANBEER~106 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7ec6702121ee228670e6680d40e6f62e0a696b74;p=platform%2Fupstream%2Fgstreamer.git Better, cleaner state management of the scheduler by adding scheduler state flags. Original commit message from CVS: Better, cleaner state management of the scheduler by adding scheduler state flags. typefind has to interrupt instead of yield. Fix a leak in the queue when it's dropping buffers. --- diff --git a/gst/gstbin.c b/gst/gstbin.c index 7a0b845..cda319a 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -717,7 +717,16 @@ gst_bin_iterate_func (GstBin * bin) { /* only iterate if this is the manager bin */ if (GST_ELEMENT_SCHED (bin)->parent == GST_ELEMENT (bin)) { - return gst_scheduler_iterate (GST_ELEMENT_SCHED (bin)); + GstSchedulerState state; + + state = gst_scheduler_iterate (GST_ELEMENT_SCHED (bin)); + + if (state == GST_SCHEDULER_STATE_RUNNING) { + return TRUE; + } + else if (state == GST_SCHEDULER_STATE_ERROR) { + gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED); + } } else { g_warning ("bin \"%d\" can't be iterated on!\n", GST_ELEMENT_NAME (bin)); diff --git a/gst/gstpad.c b/gst/gstpad.c index e6fcc5a..952534e 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -1478,7 +1478,7 @@ gst_pad_push (GstPad *pad, GstBuffer *buf) if (GST_IS_BUFFER (buf)) gst_buffer_unref (buf); else - gst_pad_event_default (pad, GST_EVENT (buf)); + gst_event_free (GST_EVENT (buf)); } } #endif @@ -2018,7 +2018,7 @@ gst_pad_event_default (GstPad *pad, GstEvent *event) } } gst_event_free (event); - /* we have to try to schedule another element because this one is deisabled */ + /* we have to try to schedule another element because this one is disabled */ gst_element_yield (element); break; default: diff --git a/gst/gstqueue.c b/gst/gstqueue.c index 0a00fb8..140562e 100644 --- a/gst/gstqueue.c +++ b/gst/gstqueue.c @@ -360,6 +360,8 @@ restart: /* this means the other end is shut down */ /* try to signal to resolve the error */ if (!queue->may_deadlock) { + if (GST_IS_BUFFER (buf)) gst_buffer_unref (buf); + else gst_event_free (GST_EVENT (buf)); g_mutex_unlock (queue->qlock); gst_element_error (GST_ELEMENT (queue), "deadlock found, source pad elements are shut down"); return; diff --git a/gst/gstscheduler.h b/gst/gstscheduler.h index 31e5b5a..a3b8af2 100644 --- a/gst/gstscheduler.h +++ b/gst/gstscheduler.h @@ -45,38 +45,46 @@ extern "C" { (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SCHEDULER)) -#define GST_SCHED_PARENT(sched) ((sched)->parent) +#define GST_SCHEDULER_PARENT(sched) ((sched)->parent) +#define GST_SCHEDULER_STATE(sched) ((sched)->state) /*typedef struct _GstScheduler GstScheduler; */ /*typedef struct _GstSchedulerClass GstSchedulerClass; */ +typedef enum { + GST_SCHEDULER_STATE_NONE, + GST_SCHEDULER_STATE_RUNNING, + GST_SCHEDULER_STATE_STOPPED, + GST_SCHEDULER_STATE_ERROR, +} GstSchedulerState; struct _GstScheduler { GstObject object; GstElement *parent; + + GstSchedulerState state; }; struct _GstSchedulerClass { GstObjectClass parent_class; /* virtual methods */ - void (*setup) (GstScheduler *sched); - void (*reset) (GstScheduler *sched); - void (*add_element) (GstScheduler *sched, GstElement *element); - void (*remove_element) (GstScheduler *sched, GstElement *element); - GstElementStateReturn - (*state_transition) (GstScheduler *sched, GstElement *element, gint transition); - void (*lock_element) (GstScheduler *sched, GstElement *element); - void (*unlock_element) (GstScheduler *sched, GstElement *element); - void (*yield) (GstScheduler *sched, GstElement *element); - void (*interrupt) (GstScheduler *sched, GstElement *element); - void (*error) (GstScheduler *sched, GstElement *element); - void (*pad_connect) (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad); - void (*pad_disconnect) (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad); - void (*pad_select) (GstScheduler *sched, GList *padlist); - gboolean (*iterate) (GstScheduler *sched); + void (*setup) (GstScheduler *sched); + void (*reset) (GstScheduler *sched); + void (*add_element) (GstScheduler *sched, GstElement *element); + void (*remove_element) (GstScheduler *sched, GstElement *element); + GstElementStateReturn (*state_transition) (GstScheduler *sched, GstElement *element, gint transition); + void (*lock_element) (GstScheduler *sched, GstElement *element); + void (*unlock_element) (GstScheduler *sched, GstElement *element); + void (*yield) (GstScheduler *sched, GstElement *element); + void (*interrupt) (GstScheduler *sched, GstElement *element); + void (*error) (GstScheduler *sched, GstElement *element); + void (*pad_connect) (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad); + void (*pad_disconnect) (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad); + void (*pad_select) (GstScheduler *sched, GList *padlist); + GstSchedulerState (*iterate) (GstScheduler *sched); /* for debugging */ - void (*show) (GstScheduler *sched); + void (*show) (GstScheduler *sched); /* signals go here */ }; diff --git a/gst/gsttypefind.c b/gst/gsttypefind.c index 250a898..e667a75 100644 --- a/gst/gsttypefind.c +++ b/gst/gsttypefind.c @@ -196,7 +196,7 @@ gst_typefind_chain (GstPad *pad, GstBuffer *buf) typefind->caps); if (GST_STATE(typefind) != oldstate) { GST_DEBUG(0, "state changed during signal, aborting\n"); - gst_element_yield (GST_ELEMENT (typefind)); + gst_element_interrupt (GST_ELEMENT (typefind)); } gst_object_unref (GST_OBJECT (typefind)); diff --git a/gst/schedulers/gstbasicscheduler.c b/gst/schedulers/gstbasicscheduler.c index be83954..289522c 100644 --- a/gst/schedulers/gstbasicscheduler.c +++ b/gst/schedulers/gstbasicscheduler.c @@ -62,6 +62,13 @@ struct _GstSchedulerChain { #define GST_BASIC_SCHEDULER_CAST(sched) ((GstBasicScheduler *)(sched)) +typedef enum { + GST_BASIC_SCHEDULER_STATE_NONE, + GST_BASIC_SCHEDULER_STATE_STOPPED, + GST_BASIC_SCHEDULER_STATE_ERROR, + GST_BASIC_SCHEDULER_STATE_RUNNING, +} GstBasicSchedulerState; + struct _GstBasicScheduler { GstScheduler parent; @@ -70,6 +77,8 @@ struct _GstBasicScheduler { GList *chains; gint num_chains; + + GstBasicSchedulerState state; }; struct _GstBasicSchedulerClass { @@ -78,28 +87,29 @@ struct _GstBasicSchedulerClass { static GType _gst_basic_scheduler_type = 0; -static void gst_basic_scheduler_class_init (GstBasicSchedulerClass * klass); -static void gst_basic_scheduler_init (GstBasicScheduler * scheduler); +static void gst_basic_scheduler_class_init (GstBasicSchedulerClass * klass); +static void gst_basic_scheduler_init (GstBasicScheduler * scheduler); -static void gst_basic_scheduler_dispose (GObject *object); +static void gst_basic_scheduler_dispose (GObject *object); -static void gst_basic_scheduler_setup (GstScheduler *sched); -static void gst_basic_scheduler_reset (GstScheduler *sched); -static void gst_basic_scheduler_add_element (GstScheduler *sched, GstElement *element); -static void gst_basic_scheduler_remove_element (GstScheduler *sched, GstElement *element); +static void gst_basic_scheduler_setup (GstScheduler *sched); +static void gst_basic_scheduler_reset (GstScheduler *sched); +static void gst_basic_scheduler_add_element (GstScheduler *sched, GstElement *element); +static void gst_basic_scheduler_remove_element (GstScheduler *sched, GstElement *element); static GstElementStateReturn - gst_basic_scheduler_state_transition (GstScheduler *sched, GstElement *element, gint transition); -static void gst_basic_scheduler_lock_element (GstScheduler *sched, GstElement *element); -static void gst_basic_scheduler_unlock_element (GstScheduler *sched, GstElement *element); -static void gst_basic_scheduler_yield (GstScheduler *sched, GstElement *element); -static void gst_basic_scheduler_interrupt (GstScheduler *sched, GstElement *element); -static void gst_basic_scheduler_error (GstScheduler *sched, GstElement *element); -static void gst_basic_scheduler_pad_connect (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad); -static void gst_basic_scheduler_pad_disconnect (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad); -static GstPad* gst_basic_scheduler_pad_select (GstScheduler *sched, GList *padlist); -static gboolean gst_basic_scheduler_iterate (GstScheduler *sched); - -static void gst_basic_scheduler_show (GstScheduler *sched); + gst_basic_scheduler_state_transition (GstScheduler *sched, GstElement *element, gint transition); +static void gst_basic_scheduler_lock_element (GstScheduler *sched, GstElement *element); +static void gst_basic_scheduler_unlock_element (GstScheduler *sched, GstElement *element); +static void gst_basic_scheduler_yield (GstScheduler *sched, GstElement *element); +static void gst_basic_scheduler_interrupt (GstScheduler *sched, GstElement *element); +static void gst_basic_scheduler_error (GstScheduler *sched, GstElement *element); +static void gst_basic_scheduler_pad_connect (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad); +static void gst_basic_scheduler_pad_disconnect (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad); +static GstPad* gst_basic_scheduler_pad_select (GstScheduler *sched, GList *padlist); +static GstSchedulerState + gst_basic_scheduler_iterate (GstScheduler *sched); + +static void gst_basic_scheduler_show (GstScheduler *sched); static GstSchedulerClass *parent_class = NULL; @@ -877,7 +887,7 @@ static void gst_basic_scheduler_reset (GstScheduler *sched) { cothread_context *ctx; - GstBin *bin = GST_BIN (GST_SCHED_PARENT (sched)); + GstBin *bin = GST_BIN (GST_SCHEDULER_PARENT (sched)); GList *elements = GST_BASIC_SCHEDULER_CAST (sched)->elements; while (elements) { @@ -885,11 +895,11 @@ gst_basic_scheduler_reset (GstScheduler *sched) elements = g_list_next (elements); } - ctx = GST_BIN_THREADCONTEXT (GST_SCHED_PARENT (sched)); + ctx = GST_BIN_THREADCONTEXT (GST_SCHEDULER_PARENT (sched)); cothread_context_free (ctx); - GST_BIN_THREADCONTEXT (GST_SCHED_PARENT (sched)) = NULL; + GST_BIN_THREADCONTEXT (GST_SCHEDULER_PARENT (sched)) = NULL; } static void @@ -984,21 +994,41 @@ gst_basic_scheduler_state_transition (GstScheduler *sched, GstElement *element, GstSchedulerChain *chain; GstBasicScheduler *bsched = GST_BASIC_SCHEDULER (sched); - /* find the chain the element is in */ - chain = gst_basic_scheduler_find_chain (bsched, element); + /* check if our parent changed state */ + if (GST_SCHEDULER_PARENT (sched) == element) { + GST_INFO (GST_CAT_SCHEDULING, "parent \"%s\" changed state", GST_ELEMENT_NAME (element)); + if (transition == GST_STATE_PLAYING_TO_PAUSED) { + GST_INFO (GST_CAT_SCHEDULING, "setting scheduler state to stopped"); + GST_SCHEDULER_STATE (sched) = GST_SCHEDULER_STATE_STOPPED; + } + else if (transition == GST_STATE_PAUSED_TO_PLAYING) { + GST_INFO (GST_CAT_SCHEDULING, "setting scheduler state to running"); + GST_SCHEDULER_STATE (sched) = GST_SCHEDULER_STATE_RUNNING; + } + else { + GST_INFO (GST_CAT_SCHEDULING, "no interesting state change, doing nothing"); + } + } + else if (transition == GST_STATE_PLAYING_TO_PAUSED || + transition == GST_STATE_PAUSED_TO_PLAYING) { + /* find the chain the element is in */ + chain = gst_basic_scheduler_find_chain (bsched, element); - /* remove it from the chain */ - if (chain) { - if (transition == GST_STATE_PLAYING_TO_PAUSED) - gst_basic_scheduler_chain_disable_element (chain, element); - if (transition == GST_STATE_PAUSED_TO_PLAYING) - if (!gst_basic_scheduler_chain_enable_element (chain, element)) { - GST_INFO (GST_CAT_SCHEDULING, "could not enable element \"%s\"", GST_ELEMENT_NAME (element)); - return GST_STATE_FAILURE; + /* remove it from the chain */ + if (chain) { + if (transition == GST_STATE_PLAYING_TO_PAUSED) { + gst_basic_scheduler_chain_disable_element (chain, element); } - } - else { - GST_INFO (GST_CAT_SCHEDULING, "element \"%s\" not found in any chain, no state change", GST_ELEMENT_NAME (element)); + else if (transition == GST_STATE_PAUSED_TO_PLAYING) { + if (!gst_basic_scheduler_chain_enable_element (chain, element)) { + GST_INFO (GST_CAT_SCHEDULING, "could not enable element \"%s\"", GST_ELEMENT_NAME (element)); + return GST_STATE_FAILURE; + } + } + } + else { + GST_INFO (GST_CAT_SCHEDULING, "element \"%s\" not found in any chain, no state change", GST_ELEMENT_NAME (element)); + } } return GST_STATE_SUCCESS; @@ -1044,7 +1074,7 @@ gst_basic_scheduler_error (GstScheduler *sched, GstElement *element) if (chain) gst_basic_scheduler_chain_disable_element (chain, element); - GST_STATE_PENDING (GST_SCHEDULER (sched)->parent) = GST_STATE_PAUSED; + GST_SCHEDULER_STATE (sched) = GST_SCHEDULER_STATE_ERROR; cothread_switch (cothread_current_main ()); } @@ -1161,14 +1191,13 @@ gst_basic_scheduler_pad_select (GstScheduler * sched, GList * padlist) return pad; } -static gboolean +static GstSchedulerState gst_basic_scheduler_iterate (GstScheduler * sched) { GstBin *bin = GST_BIN (sched->parent); GList *chains; GstSchedulerChain *chain; GstElement *entry; - gboolean eos = FALSE; GList *elements; gint scheduled = 0; GstBasicScheduler *bsched = GST_BASIC_SCHEDULER (sched); @@ -1179,7 +1208,7 @@ gst_basic_scheduler_iterate (GstScheduler * sched) chains = bsched->chains; if (chains == NULL) - return FALSE; + return GST_SCHEDULER_STATE_STOPPED; while (chains) { chain = (GstSchedulerChain *) (chains->data); @@ -1210,7 +1239,10 @@ gst_basic_scheduler_iterate (GstScheduler * sched) break; } if (entry) { + GstSchedulerState state; + GST_FLAG_SET (entry, GST_ELEMENT_COTHREAD_STOPPING); + GST_DEBUG (GST_CAT_DATAFLOW, "set COTHREAD_STOPPING flag on \"%s\"(@%p)\n", GST_ELEMENT_NAME (entry), entry); if (GST_ELEMENT_THREADSTATE (entry)) { @@ -1218,9 +1250,11 @@ gst_basic_scheduler_iterate (GstScheduler * sched) } else { GST_DEBUG (GST_CAT_DATAFLOW, "cothread switch not possible, element has no threadstate\n"); - return FALSE; + return GST_SCHEDULER_STATE_ERROR; } + state = GST_SCHEDULER_STATE (sched); + /* following is a check to see if the chain was interrupted due to a * top-half state_change(). (i.e., if there's a pending state.) * @@ -1228,28 +1262,32 @@ gst_basic_scheduler_iterate (GstScheduler * sched) * execute the state change. */ GST_DEBUG (GST_CAT_DATAFLOW, "cothread switch ended or interrupted\n"); - if (GST_STATE_PENDING (GST_SCHEDULER (sched)->parent) != GST_STATE_VOID_PENDING) { - GST_DEBUG (GST_CAT_DATAFLOW, "handle pending state %d\n", - GST_STATE_PENDING (GST_SCHEDULER (sched)->parent)); - return FALSE; + + if (state != GST_SCHEDULER_STATE_RUNNING) { + GST_INFO (GST_CAT_DATAFLOW, "scheduler is not running, in state %d", state); + return state; } + scheduled++; } else { - GST_INFO (GST_CAT_DATAFLOW, "NO ENTRY INTO CHAIN!"); - if (scheduled == 0) - eos = TRUE; + GST_INFO (GST_CAT_DATAFLOW, "no entry in this chain, trying the next one"); } } else { - GST_INFO (GST_CAT_DATAFLOW, "NO ENABLED ELEMENTS IN CHAIN!!"); - if (scheduled == 0) - eos = TRUE; + GST_INFO (GST_CAT_DATAFLOW, "no enabled elements in this chain, trying the next one"); } } GST_DEBUG (GST_CAT_DATAFLOW, "leaving (%s)\n", GST_ELEMENT_NAME (bin)); - return !eos; + if (scheduled == 0) { + GST_INFO (GST_CAT_DATAFLOW, "nothing was scheduled, return STOPPED"); + return GST_SCHEDULER_STATE_STOPPED; + } + else { + GST_INFO (GST_CAT_DATAFLOW, "scheduler still running, return RUNNING"); + return GST_SCHEDULER_STATE_RUNNING; + } } diff --git a/plugins/elements/gstqueue.c b/plugins/elements/gstqueue.c index 0a00fb8..140562e 100644 --- a/plugins/elements/gstqueue.c +++ b/plugins/elements/gstqueue.c @@ -360,6 +360,8 @@ restart: /* this means the other end is shut down */ /* try to signal to resolve the error */ if (!queue->may_deadlock) { + if (GST_IS_BUFFER (buf)) gst_buffer_unref (buf); + else gst_event_free (GST_EVENT (buf)); g_mutex_unlock (queue->qlock); gst_element_error (GST_ELEMENT (queue), "deadlock found, source pad elements are shut down"); return;