};
-/*
- * 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
*/
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);
);
-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*
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)) {
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;
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;
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;
}
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);
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);
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)
{
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));
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);
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)
{
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)
{
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++;
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 {
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);
}
}
}
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) {
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);
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;
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;
{
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);
}
#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
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;
}
disabled = FALSE;
do {
- GST_LOG ("scheduling upstream group %p to fill bufpen", group);
#ifdef USE_COTHREADS
schedule_group (group);
#else
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);
}
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;
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;
}
/* 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;
* 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;
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 */
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));
}
/* 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);
* 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");
* 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:
/* 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
osched->state = GST_OPT_SCHEDULER_STATE_RUNNING;
- GST_DEBUG_OBJECT (sched, "iterating");
+ GST_DEBUG ("iterating scheduler %p", sched);
while (iterations) {
gboolean scheduled = FALSE;
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;
}
osched->state = GST_OPT_SCHEDULER_STATE_RUNNING;
}
+ GST_LOG_OBJECT (sched, "iterate scheduled %p", chain);
+
chains = g_slist_next (chains);
unref_chain (chain);
}