From 29642c454809a7078ce5966ab23c33e515217cff Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Tue, 2 Mar 2004 23:04:50 +0000 Subject: [PATCH] gst/schedulers/gstoptimalscheduler.c: revert last commit by Andy Wingo. It causes segfaults on unreffing in Rhythmbox... Original commit message from CVS: 2004-03-03 Benjamin Otte * gst/schedulers/gstoptimalscheduler.c: revert last commit by Andy Wingo. It causes segfaults on unreffing in Rhythmbox. (see bug #135672) --- ChangeLog | 6 + gst/schedulers/gstoptimalscheduler.c | 489 ++++++++++++++--------------------- 2 files changed, 201 insertions(+), 294 deletions(-) diff --git a/ChangeLog b/ChangeLog index bdcadcb..9446219 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2004-03-03 Benjamin Otte + + * gst/schedulers/gstoptimalscheduler.c: + revert last commit by Andy Wingo. It causes segfaults on unreffing + in Rhythmbox. (see bug #135672) + 2004-03-02 Christophe Fergeau * po/fr.po: fix typo diff --git a/gst/schedulers/gstoptimalscheduler.c b/gst/schedulers/gstoptimalscheduler.c index 0076139..187d3cc 100644 --- a/gst/schedulers/gstoptimalscheduler.c +++ b/gst/schedulers/gstoptimalscheduler.c @@ -183,81 +183,20 @@ struct _GstOptSchedulerGroup { }; -/* - * A group is a set of elements through which data can flow without switching - * cothreads or without invoking the scheduler's run queue. - */ +/* some group operations */ static GstOptSchedulerGroup* ref_group (GstOptSchedulerGroup *group); +#ifndef USE_COTHREADS +/* +static GstOptSchedulerGroup* ref_group_by_count (GstOptSchedulerGroup *group, gint count); +*/ +#endif static GstOptSchedulerGroup* unref_group (GstOptSchedulerGroup *group); -static GstOptSchedulerGroup* create_group (GstOptSchedulerChain *chain, - GstElement *element, - GstOptSchedulerGroupType type); static void destroy_group (GstOptSchedulerGroup *group); -static GstOptSchedulerGroup* add_to_group (GstOptSchedulerGroup *group, - GstElement *element); -static GstOptSchedulerGroup* remove_from_group (GstOptSchedulerGroup *group, - GstElement *element); -static GstOptSchedulerGroup* merge_groups (GstOptSchedulerGroup *group1, - GstOptSchedulerGroup *group2); -static void setup_group_scheduler (GstOptScheduler *osched, - GstOptSchedulerGroup *group); -static void destroy_group_scheduler (GstOptSchedulerGroup *group); -static void group_error_handler (GstOptSchedulerGroup *group); static void group_element_set_enabled (GstOptSchedulerGroup *group, - GstElement *element, - gboolean enabled); -static gboolean schedule_group (GstOptSchedulerGroup *group); + GstElement *element, gboolean enabled); - -/* - * A chain is a set of groups that are linked to each other. - */ -static void destroy_chain (GstOptSchedulerChain *chain); -static GstOptSchedulerChain* create_chain (GstOptScheduler *osched); -static GstOptSchedulerChain* ref_chain (GstOptSchedulerChain *chain); -static GstOptSchedulerChain* unref_chain (GstOptSchedulerChain *chain); -static GstOptSchedulerChain* add_to_chain (GstOptSchedulerChain *chain, - GstOptSchedulerGroup *group); -static GstOptSchedulerChain* remove_from_chain (GstOptSchedulerChain *chain, - GstOptSchedulerGroup *group); -static GstOptSchedulerChain* merge_chains (GstOptSchedulerChain *chain1, - GstOptSchedulerChain *chain2); -static void chain_recursively_migrate_group (GstOptSchedulerChain *chain, - GstOptSchedulerGroup *group); static void chain_group_set_enabled (GstOptSchedulerChain *chain, - GstOptSchedulerGroup *group, - gboolean enabled); -static void schedule_chain (GstOptSchedulerChain *chain); - - -/* - * The schedule functions are the entry points for cothreads, or called directly - * by gst_opt_scheduler_schedule_run_queue - */ -static int get_group_schedule_function (int argc, char *argv[]); -static int loop_group_schedule_function (int argc, char *argv[]); -static int unknown_group_schedule_function (int argc, char *argv[]); - - -/* - * These wrappers are set on the pads as the chain handler (what happens when - * gst_pad_push is called) or get handler (for gst_pad_pull). - */ -static void gst_opt_scheduler_loop_wrapper (GstPad *sinkpad, GstData *data); -static GstData* gst_opt_scheduler_get_wrapper (GstPad *srcpad); -static void gst_opt_scheduler_chain_wrapper (GstPad *sinkpad, GstData *data); - - -/* - * Without cothreads, gst_pad_push or gst_pad_pull on a loop-based group will - * just queue the peer element on a list. We need to actually run the queue - * instead of relying on cothreads to do the switch for us. - */ -#ifndef USE_COTHREADS -static void gst_opt_scheduler_schedule_run_queue (GstOptScheduler *osched); -#endif - - + GstOptSchedulerGroup *group, gboolean enabled); /* * Scheduler private data for an element */ @@ -273,16 +212,13 @@ struct _GstOptSchedulerCtx { GstOptSchedulerCtxFlags flags; /* flags for this element */ }; - -/* - * Implementation of GstScheduler - */ enum { ARG_0, ARG_ITERATIONS, ARG_MAX_RECURSION, }; + static void gst_opt_scheduler_class_init (GstOptSchedulerClass *klass); static void gst_opt_scheduler_init (GstOptScheduler *scheduler); @@ -443,28 +379,22 @@ GST_PLUGIN_DEFINE ( ); -static GstOptSchedulerChain* -ref_chain (GstOptSchedulerChain *chain) +static void +destroy_chain (GstOptSchedulerChain *chain) { - GST_LOG ("ref chain %p %d->%d", chain, - chain->refcount, chain->refcount+1); - chain->refcount++; + GstOptScheduler *osched; + + GST_LOG ( "destroy chain %p", chain); - return chain; -} + g_assert (chain->num_groups == 0); + g_assert (chain->groups == NULL); -static GstOptSchedulerChain* -unref_chain (GstOptSchedulerChain *chain) -{ - GST_LOG ("unref chain %p %d->%d", chain, - chain->refcount, chain->refcount-1); + osched = chain->sched; + osched->chains = g_slist_remove (osched->chains, chain); - if (--chain->refcount == 0) { - destroy_chain (chain); - chain = NULL; - } + gst_object_unref (GST_OBJECT (osched)); - return chain; + g_free (chain); } static GstOptSchedulerChain* @@ -485,45 +415,41 @@ create_chain (GstOptScheduler *osched) return chain; } -static void -destroy_chain (GstOptSchedulerChain *chain) +static GstOptSchedulerChain* +ref_chain (GstOptSchedulerChain *chain) { - GstOptScheduler *osched; - - GST_LOG ( "destroy chain %p", chain); + GST_LOG ("ref chain %p %d->%d", chain, + chain->refcount, chain->refcount+1); + chain->refcount++; - g_assert (chain->num_groups == 0); - g_assert (chain->groups == NULL); + return chain; +} - osched = chain->sched; - osched->chains = g_slist_remove (osched->chains, chain); +static GstOptSchedulerChain* +unref_chain (GstOptSchedulerChain *chain) +{ + GST_LOG ("unref chain %p %d->%d", chain, + chain->refcount, chain->refcount-1); - gst_object_unref (GST_OBJECT (osched)); + if (--chain->refcount == 0) { + destroy_chain (chain); + chain = NULL; + } - g_free (chain); + return chain; } static GstOptSchedulerChain* add_to_chain (GstOptSchedulerChain *chain, GstOptSchedulerGroup *group) { - GST_LOG ("adding group %p to chain %p", group, chain); + GST_LOG ( "adding group %p to chain %p", group, chain); g_assert (group->chain == NULL); group = ref_group (group); group->chain = ref_chain (chain); - - /* The first non-disabled group in the chain's group list will be the entry - point for the chain. Because buffers can accumulate in loop elements' peer - bufpens, we preferentially schedule loop groups before get groups to avoid - unnecessary execution of get-based groups when the bufpens are already - full. */ - if (group->type == GST_OPT_SCHEDULER_GROUP_LOOP) - chain->groups = g_slist_prepend (chain->groups, group); - else - chain->groups = g_slist_append (chain->groups, group); - + chain->groups = g_slist_prepend (chain->groups, group); chain->num_groups++; if (GST_OPT_SCHEDULER_GROUP_IS_ENABLED (group)) { @@ -536,7 +462,7 @@ add_to_chain (GstOptSchedulerChain *chain, GstOptSchedulerGroup *group) static GstOptSchedulerChain* remove_from_chain (GstOptSchedulerChain *chain, GstOptSchedulerGroup *group) { - GST_LOG ("removing group %p from chain %p", group, chain); + GST_LOG ( "removing group %p from chain %p", group, chain); if (!chain) return NULL; @@ -565,17 +491,10 @@ merge_chains (GstOptSchedulerChain *chain1, GstOptSchedulerChain *chain2) GST_LOG ("merging chain %p and %p", chain1, chain2); - /* FIXME: document how chain2 can be NULL */ if (chain1 == chain2 || chain2 == NULL) return chain1; - /* switch if it's more efficient */ - if (chain1->num_groups < chain2->num_groups) { - GstOptSchedulerChain *tmp = chain2; - chain2 = chain1; - chain1 = tmp; - } - + ref_chain (chain2); walk = chain2->groups; while (walk) { GstOptSchedulerGroup *group = (GstOptSchedulerGroup *) walk->data; @@ -584,15 +503,17 @@ merge_chains (GstOptSchedulerChain *chain1, GstOptSchedulerChain *chain2) GST_LOG ("reparenting group %p from chain %p to %p", group, chain2, chain1); - ref_group (group); - - remove_from_chain (chain2, group); - add_to_chain (chain1, group); + group->chain = NULL; + chain2->num_groups--; + chain2 = unref_chain (chain2); - unref_group (group); + group->chain = ref_chain (chain1); + chain1->groups = g_slist_prepend (chain1->groups, group); + chain1->num_groups++; } - - /* chain2 is now freed, if nothing else was referencing it before */ + g_slist_free (chain2->groups); + chain2->groups = NULL; + unref_chain (chain2); return chain1; } @@ -600,8 +521,8 @@ merge_chains (GstOptSchedulerChain *chain1, GstOptSchedulerChain *chain2) static void chain_group_set_enabled (GstOptSchedulerChain *chain, GstOptSchedulerGroup *group, gboolean enabled) { - g_assert (group != NULL); g_assert (chain != NULL); + g_assert (group != NULL); GST_LOG ("request to %d group %p in chain %p, have %d groups enabled out of %d", enabled, group, chain, chain->num_enabled, chain->num_groups); @@ -618,10 +539,6 @@ chain_group_set_enabled (GstOptSchedulerChain *chain, GstOptSchedulerGroup *grou GST_DEBUG ("enable group %p in chain %p, now %d groups enabled out of %d", group, chain, chain->num_enabled, chain->num_groups); - /* OK to call even if the scheduler (cothread context / schedulerfunc) was - setup already -- will get destroyed when the group is destroyed */ - setup_group_scheduler (chain->sched, group); - if (chain->num_enabled == chain->num_groups) { GST_DEBUG ("enable chain %p", chain); GST_OPT_SCHEDULER_CHAIN_ENABLE (chain); @@ -677,56 +594,35 @@ ref_group (GstOptSchedulerGroup *group) return group; } +#ifndef USE_COTHREADS +/* remove me static GstOptSchedulerGroup* -unref_group (GstOptSchedulerGroup *group) +ref_group_by_count (GstOptSchedulerGroup *group, gint count) { - GST_LOG ("unref group %p %d->%d", group, - group->refcount, group->refcount-1); + GST_LOG ("ref group %p %d->%d", group, + group->refcount, group->refcount+count); - if (--group->refcount == 0) { - destroy_group (group); - group = NULL; - } + group->refcount += count; return group; } +*/ +#endif static GstOptSchedulerGroup* -create_group (GstOptSchedulerChain *chain, GstElement *element, - GstOptSchedulerGroupType type) +unref_group (GstOptSchedulerGroup *group) { - GstOptSchedulerGroup *group; - - group = g_new0 (GstOptSchedulerGroup, 1); - GST_LOG ("new group %p", group); - group->refcount = 1; /* float... */ - group->flags = GST_OPT_SCHEDULER_GROUP_DISABLED; - group->type = type; + GST_LOG ("unref group %p %d->%d", group, + group->refcount, group->refcount-1); - add_to_group (group, element); - add_to_chain (chain, group); - group = unref_group (group); /* ...and sink. */ + if (--group->refcount == 1) { + destroy_group (group); + group = NULL; + } - /* group's refcount is now 2 (one for the element, one for the chain) */ - return group; } -static void -destroy_group (GstOptSchedulerGroup *group) -{ - GST_LOG ("destroy group %p", group); - - g_assert (group != NULL); - g_assert (group->elements == NULL); - g_assert (group->chain == NULL); - - if (group->flags & GST_OPT_SCHEDULER_GROUP_SCHEDULABLE) - destroy_group_scheduler (group); - - g_free (group); -} - static GstOptSchedulerGroup* add_to_group (GstOptSchedulerGroup *group, GstElement *element) { @@ -743,7 +639,6 @@ add_to_group (GstOptSchedulerGroup *group, GstElement *element) g_assert (GST_ELEMENT_SCHED_GROUP (element) == NULL); - /* Ref the group... */ GST_ELEMENT_SCHED_GROUP (element) = ref_group (group); gst_object_ref (GST_OBJECT (element)); @@ -754,10 +649,67 @@ add_to_group (GstOptSchedulerGroup *group, GstElement *element) group_element_set_enabled (group, element, TRUE); } + /* Ref the group... */ + ref_group (group); + return group; } static GstOptSchedulerGroup* +create_group (GstOptSchedulerChain *chain, GstElement *element) +{ + GstOptSchedulerGroup *group; + + group = g_new0 (GstOptSchedulerGroup, 1); + GST_LOG ("new group %p", group); + group->refcount = 1; + group->flags = GST_OPT_SCHEDULER_GROUP_DISABLED; + + add_to_group (group, element); + add_to_chain (chain, group); + + return group; +} + +static void +destroy_group_scheduler (GstOptSchedulerGroup *group) +{ + g_assert (group); + + if (group->flags & GST_OPT_SCHEDULER_GROUP_RUNNING) + g_warning ("destroying running group scheduler"); + +#ifdef USE_COTHREADS + if (group->cothread) { + do_cothread_destroy (group->cothread); + group->cothread = NULL; + } +#else + group->schedulefunc = NULL; + group->argc = 0; + group->argv = NULL; +#endif + + group->flags &= ~GST_OPT_SCHEDULER_GROUP_SCHEDULABLE; +} + +static void +destroy_group (GstOptSchedulerGroup *group) +{ + GST_LOG ("destroy group %p", group); + + g_assert (group != NULL); + g_assert (group->elements == NULL); + + remove_from_chain (group->chain, group); + + if (group->flags & GST_OPT_SCHEDULER_GROUP_SCHEDULABLE) + destroy_group_scheduler (group); + + g_free (group); +} + +static GstOptSchedulerGroup* remove_from_group (GstOptSchedulerGroup *group, GstElement *element) { GST_DEBUG ("removing element \"%s\" from group %p", GST_ELEMENT_NAME (element), group); @@ -779,22 +731,13 @@ remove_from_group (GstOptSchedulerGroup *group, GstElement *element) gst_object_unref (GST_OBJECT (element)); if (group->num_elements == 0) { - GST_LOG ("group %p is now empty", group); - /* don't know in what case group->chain would be NULL, but putting this here - in deference to 0.8 -- remove me in 0.9 */ - if (group->chain) { - GST_LOG ("removing group %p from its chain", group); - chain_group_set_enabled (group->chain, group, FALSE); - remove_from_chain (group->chain, group); - } + group = unref_group (group); } group = unref_group (group); return group; } -/* FIXME need to check if the groups are of the same type -- otherwise need to - setup the scheduler again, if it is setup */ static GstOptSchedulerGroup* merge_groups (GstOptSchedulerGroup *group1, GstOptSchedulerGroup *group2) { @@ -815,61 +758,6 @@ merge_groups (GstOptSchedulerGroup *group1, GstOptSchedulerGroup *group2) return group1; } -/* setup the scheduler context for a group. The right schedule function - * is selected based on the group type and cothreads are created if - * needed */ -static void -setup_group_scheduler (GstOptScheduler *osched, GstOptSchedulerGroup *group) -{ - GroupScheduleFunction wrapper; - - wrapper = unknown_group_schedule_function; - - /* figure out the wrapper function for this group */ - if (group->type == GST_OPT_SCHEDULER_GROUP_GET) - wrapper = get_group_schedule_function; - else if (group->type == GST_OPT_SCHEDULER_GROUP_LOOP) - wrapper = loop_group_schedule_function; - -#ifdef USE_COTHREADS - if (!(group->flags & GST_OPT_SCHEDULER_GROUP_SCHEDULABLE)) { - do_cothread_create (group->cothread, osched->context, - (cothread_func) wrapper, 0, (char **) group); - } - else { - do_cothread_setfunc (group->cothread, osched->context, - (cothread_func) wrapper, 0, (char **) group); - } -#else - group->schedulefunc = wrapper; - group->argc = 0; - group->argv = (char **) group; -#endif - group->flags |= GST_OPT_SCHEDULER_GROUP_SCHEDULABLE; -} - -static void -destroy_group_scheduler (GstOptSchedulerGroup *group) -{ - g_assert (group); - - if (group->flags & GST_OPT_SCHEDULER_GROUP_RUNNING) - g_warning ("destroying running group scheduler"); - -#ifdef USE_COTHREADS - if (group->cothread) { - do_cothread_destroy (group->cothread); - group->cothread = NULL; - } -#else - group->schedulefunc = NULL; - group->argc = 0; - group->argv = NULL; -#endif - - group->flags &= ~GST_OPT_SCHEDULER_GROUP_SCHEDULABLE; -} - static void group_error_handler (GstOptSchedulerGroup *group) { @@ -891,11 +779,6 @@ group_element_set_enabled (GstOptSchedulerGroup *group, GstElement *element, gbo GST_LOG ("request to %d element %s in group %p, have %d elements enabled out of %d", enabled, GST_ELEMENT_NAME (element), group, group->num_enabled, group->num_elements); - /* Note that if an unlinked PLAYING element is added to a bin, we have to - create a new group to hold the element, and this function will be called - before the group is added to the chain. Thus we have a valid case for - group->chain==NULL. */ - if (enabled) { if (group->num_enabled < group->num_elements) group->num_enabled++; @@ -904,13 +787,8 @@ group_element_set_enabled (GstOptSchedulerGroup *group, GstElement *element, gbo GST_ELEMENT_NAME (element), group, group->num_enabled, group->num_elements); if (group->num_enabled == group->num_elements) { - if (!group->chain) { - GST_DEBUG ("enable chainless group %p", group); - GST_OPT_SCHEDULER_GROUP_ENABLE (group); - } else { - GST_LOG ("enable group %p", group); - chain_group_set_enabled (group->chain, group, TRUE); - } + GST_LOG ("enable group %p", group); + chain_group_set_enabled (group->chain, group, TRUE); } } else { @@ -921,13 +799,8 @@ group_element_set_enabled (GstOptSchedulerGroup *group, GstElement *element, gbo GST_ELEMENT_NAME (element), group, group->num_enabled, group->num_elements); if (group->num_enabled == 0) { - if (!group->chain) { - GST_DEBUG ("disable chainless group %p", group); - GST_OPT_SCHEDULER_GROUP_DISABLE (group); - } else { - GST_LOG ("disable group %p", group); - chain_group_set_enabled (group->chain, group, FALSE); - } + GST_LOG ("disable group %p", group); + chain_group_set_enabled (group->chain, group, FALSE); } } } @@ -982,11 +855,8 @@ schedule_group (GstOptSchedulerGroup *group) static void gst_opt_scheduler_schedule_run_queue (GstOptScheduler *osched) { - GST_LOG_OBJECT (osched, "running queue: %d groups, recursed %d times", - g_list_length (osched->runqueue), - osched->recursion, g_list_length (osched->runqueue)); - - /* note that we have a ref on each group on the queue (unref after running) */ + GST_LOG_OBJECT (osched, "entering scheduler run queue recursion %d %d", + osched->recursion, g_list_length (osched->runqueue)); /* make sure we don't exceed max_recursion */ if (osched->recursion > osched->max_recursion) { @@ -1002,7 +872,7 @@ gst_opt_scheduler_schedule_run_queue (GstOptScheduler *osched) group = (GstOptSchedulerGroup *) osched->runqueue->data; - /* runqueue holds refcount to group */ + /* runqueue hols refcount to group */ osched->runqueue = g_list_remove (osched->runqueue, group); GST_LOG_OBJECT (osched, "scheduling group %p", group); @@ -1075,7 +945,7 @@ get_group_schedule_function (int argc, char *argv[]) GstElement *entry = group->entry; const GList *pads = gst_element_get_pad_list (entry); - GST_LOG ("executing get-based group %p", group); + GST_LOG ("get wrapper of group %p", group); group->flags |= GST_OPT_SCHEDULER_GROUP_RUNNING; @@ -1116,7 +986,7 @@ loop_group_schedule_function (int argc, char *argv[]) GstOptSchedulerGroup *group = (GstOptSchedulerGroup *) argv; GstElement *entry = group->entry; - GST_LOG ("executing loop-based group %p", group); + GST_LOG ("loop wrapper of group %p", group); group->flags |= GST_OPT_SCHEDULER_GROUP_RUNNING; @@ -1154,31 +1024,26 @@ gst_opt_scheduler_loop_wrapper (GstPad *sinkpad, GstData *data) { GstOptSchedulerGroup *group; GstOptScheduler *osched; - GstRealPad *peer; + + GST_LOG ("loop wrapper, putting buffer in bufpen"); group = GST_ELEMENT_SCHED_GROUP (GST_PAD_PARENT (sinkpad)); osched = group->chain->sched; - peer = GST_RPAD_PEER (sinkpad); - GST_LOG ("chain handler for loop-based pad %" GST_PTR_FORMAT, sinkpad); #ifdef USE_COTHREADS - if (GST_PAD_BUFLIST (peer)) { + if (GST_PAD_BUFLIST (GST_RPAD_PEER (sinkpad))) { g_warning ("deadlock detected, disabling group %p", group); group_error_handler (group); } else { - GST_LOG ("queueing data %p on %s:%s's bufpen", data, - GST_DEBUG_PAD_NAME (peer)); - GST_PAD_BUFLIST (peer) = g_list_append (GST_PAD_BUFLIST (peer), data); + GST_PAD_BUFLIST (GST_RPAD_PEER (sinkpad)) = g_list_append (GST_PAD_BUFLIST (GST_RPAD_PEER (sinkpad)), data); schedule_group (group); } #else - GST_LOG ("queueing data %p on %s:%s's bufpen", data, - GST_DEBUG_PAD_NAME (peer)); - GST_PAD_BUFLIST (peer) = g_list_append (GST_PAD_BUFLIST (peer), data); + GST_PAD_BUFLIST (GST_RPAD_PEER (sinkpad)) = g_list_append (GST_PAD_BUFLIST (GST_RPAD_PEER (sinkpad)), data); if (!(group->flags & GST_OPT_SCHEDULER_GROUP_RUNNING)) { - GST_LOG ("adding group %p to runqueue", group); + GST_LOG ("adding %p to runqueue", group); if (!g_list_find (osched->runqueue, group)) { ref_group (group); @@ -1187,8 +1052,8 @@ gst_opt_scheduler_loop_wrapper (GstPad *sinkpad, GstData *data) } #endif - GST_LOG ("%d buffers left on %s:%s's bufpen after chain handler", - g_list_length (GST_PAD_BUFLIST (peer))); + GST_LOG ("after loop wrapper buflist %d", + g_list_length (GST_PAD_BUFLIST (GST_RPAD_PEER (sinkpad)))); } /* this function is called by a loop based element that performs a @@ -1202,14 +1067,15 @@ gst_opt_scheduler_get_wrapper (GstPad *srcpad) GstOptScheduler *osched; gboolean disabled; - GST_LOG ("get handler for %" GST_PTR_FORMAT, srcpad); + GST_LOG ("get wrapper, removing buffer from bufpen"); /* first try to grab a queued buffer */ if (GST_PAD_BUFLIST (srcpad)) { data = GST_PAD_BUFLIST (srcpad)->data; GST_PAD_BUFLIST (srcpad) = g_list_remove (GST_PAD_BUFLIST (srcpad), data); - GST_LOG ("returning popped queued data %p", data); + GST_LOG ("get wrapper, returning queued data %d", + g_list_length (GST_PAD_BUFLIST (srcpad))); return data; } @@ -1221,7 +1087,6 @@ gst_opt_scheduler_get_wrapper (GstPad *srcpad) disabled = FALSE; do { - GST_LOG ("scheduling upstream group %p to fill bufpen", group); #ifdef USE_COTHREADS schedule_group (group); #else @@ -1234,9 +1099,9 @@ gst_opt_scheduler_get_wrapper (GstPad *srcpad) osched->runqueue = g_list_append (osched->runqueue, group); } - GST_LOG ("recursing into scheduler group %p", group); + GST_LOG_OBJECT (osched, "recursing into scheduler group %p", group); gst_opt_scheduler_schedule_run_queue (osched); - GST_LOG ("return from recurse group %p", group); + GST_LOG_OBJECT (osched, "return from recurse group %p", group); /* if the other group was disabled we might have to break out of the loop */ disabled = GST_OPT_SCHEDULER_GROUP_IS_DISABLED (group); @@ -1274,7 +1139,7 @@ gst_opt_scheduler_get_wrapper (GstPad *srcpad) } while (data == NULL); - GST_LOG ("get handler, returning data %p, queue length %d", + GST_LOG ("get wrapper, returning data %p, queue length %d", data, g_list_length (GST_PAD_BUFLIST (srcpad))); return data; @@ -1342,9 +1207,44 @@ gst_opt_scheduler_event_wrapper (GstPad *srcpad, GstEvent *event) return GST_RPAD_EVENTFUNC (srcpad) (srcpad, event); } + +/* setup the scheduler context for a group. The right schedule function + * is selected based on the group type and cothreads are created if + * needed */ +static void +setup_group_scheduler (GstOptScheduler *osched, GstOptSchedulerGroup *group) +{ + GroupScheduleFunction wrapper; + + wrapper = unknown_group_schedule_function; + + /* figure out the wrapper function for this group */ + if (group->type == GST_OPT_SCHEDULER_GROUP_GET) + wrapper = get_group_schedule_function; + else if (group->type == GST_OPT_SCHEDULER_GROUP_LOOP) + wrapper = loop_group_schedule_function; + +#ifdef USE_COTHREADS + if (!(group->flags & GST_OPT_SCHEDULER_GROUP_SCHEDULABLE)) { + do_cothread_create (group->cothread, osched->context, + (cothread_func) wrapper, 0, (char **) group); + } + else { + do_cothread_setfunc (group->cothread, osched->context, + (cothread_func) wrapper, 0, (char **) group); + } +#else + group->schedulefunc = wrapper; + group->argc = 0; + group->argv = (char **) group; +#endif + group->flags |= GST_OPT_SCHEDULER_GROUP_SCHEDULABLE; +} + static GstElementStateReturn gst_opt_scheduler_state_transition (GstScheduler *sched, GstElement *element, gint transition) { + GstOptScheduler *osched = GST_OPT_SCHEDULER (sched); GstOptSchedulerGroup *group; GstElementStateReturn res = GST_STATE_SUCCESS; @@ -1388,6 +1288,7 @@ gst_opt_scheduler_state_transition (GstScheduler *sched, GstElement *element, gi } /* else construct the scheduling context of this group and enable it */ else { + setup_group_scheduler (osched, group); group_element_set_enabled (group, element, TRUE); } break; @@ -1439,8 +1340,7 @@ get_group (GstElement *element, GstOptSchedulerGroup **group) * will also merge the chains. */ static GstOptSchedulerGroup* -group_elements (GstOptScheduler *osched, GstElement *element1, GstElement *element2, - GstOptSchedulerGroupType type) +group_elements (GstOptScheduler *osched, GstElement *element1, GstElement *element2) { GstOptSchedulerGroup *group1, *group2, *group = NULL; @@ -1456,7 +1356,7 @@ group_elements (GstOptScheduler *osched, GstElement *element1, GstElement *eleme GST_ELEMENT_NAME (element1), GST_ELEMENT_NAME (element2)); chain = create_chain (osched); - group = create_group (chain, element1, type); + group = create_group (chain, element1); add_to_group (group, element2); } /* the first element has a group */ @@ -1648,8 +1548,9 @@ gst_opt_scheduler_add_element (GstScheduler *sched, GstElement *element) chain = create_chain (osched); - group = create_group (chain, element, GST_OPT_SCHEDULER_GROUP_LOOP); + group = create_group (chain, element); group->entry = element; + group->type = GST_OPT_SCHEDULER_GROUP_LOOP; GST_LOG ("added element \"%s\" as loop based entry", GST_ELEMENT_NAME (element)); } @@ -1832,13 +1733,13 @@ gst_opt_scheduler_pad_link (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad /* the two elements should be put into the same group, * this also means that they are in the same chain automatically */ - group = group_elements (osched, element1, element2, - GST_OPT_SCHEDULER_GROUP_GET); + group = group_elements (osched, element1, element2); /* if there is not yet an entry in the group, select the source * element as the entry point */ if (!group->entry) { group->entry = element1; + group->type = GST_OPT_SCHEDULER_GROUP_GET; GST_DEBUG ("setting \"%s\" as entry point of _get-based group %p", GST_ELEMENT_NAME (element1), group); @@ -1858,7 +1759,7 @@ gst_opt_scheduler_pad_link (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad * this also means that they are in the same chain automatically, * in case of a loop-based element1, there will be a group for element1 and * element2 will be added to it. */ - group_elements (osched, element1, element2, GST_OPT_SCHEDULER_GROUP_LOOP); + group_elements (osched, element1, element2); break; case GST_OPT_GET_TO_LOOP: GST_LOG ("get to loop based link"); @@ -1869,7 +1770,7 @@ gst_opt_scheduler_pad_link (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad * this also means that they are in the same chain automatically, * element2 is loop-based so it already has a group where element1 * will be added to */ - group_elements (osched, element1, element2, GST_OPT_SCHEDULER_GROUP_LOOP); + group_elements (osched, element1, element2); break; case GST_OPT_CHAIN_TO_LOOP: case GST_OPT_LOOP_TO_LOOP: @@ -1895,8 +1796,7 @@ gst_opt_scheduler_pad_link (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad /* create a new group for element1 as it cannot be merged into another group * here. we create the group in the same chain as the loop-based element. */ GST_DEBUG ("creating new group for element %s", GST_ELEMENT_NAME (element1)); - group1 = create_group (group2->chain, element1, - GST_OPT_SCHEDULER_GROUP_LOOP); + group1 = create_group (group2->chain, element1); } else { /* both elements are already in a group, make sure they are added to @@ -2152,7 +2052,7 @@ gst_opt_scheduler_iterate (GstScheduler *sched) osched->state = GST_OPT_SCHEDULER_STATE_RUNNING; - GST_DEBUG_OBJECT (sched, "iterating"); + GST_DEBUG ("iterating scheduler %p", sched); while (iterations) { gboolean scheduled = FALSE; @@ -2166,7 +2066,6 @@ gst_opt_scheduler_iterate (GstScheduler *sched) ref_chain (chain); /* if the chain is not disabled, schedule it */ if (!GST_OPT_SCHEDULER_CHAIN_IS_DISABLED (chain)) { - GST_LOG ("scheduling chain %p", chain); schedule_chain (chain); scheduled = TRUE; } @@ -2181,6 +2080,8 @@ gst_opt_scheduler_iterate (GstScheduler *sched) osched->state = GST_OPT_SCHEDULER_STATE_RUNNING; } + GST_LOG_OBJECT (sched, "iterate scheduled %p", chain); + chains = g_slist_next (chains); unref_chain (chain); } -- 2.7.4