mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-10 17:35:59 +00:00
gst/gstbin.c (gst_bin_remove): Debugging fixes.
Original commit message from CVS: 2004-03-07 Andy Wingo <wingo@pobox.com> * gst/gstbin.c (gst_bin_remove): Debugging fixes. * gst/schedulers/gstoptimalscheduler.c (destroy_group): Assert there are no links to other groups when a group is destroyed. (gst_opt_scheduler_pad_unlink): If the unlink means an element is removed from a group, make sure the link count to elements linked to other pads is appropriately decremented. This really fixes #135672. The 1.60->1.61 patch has been reapplied in light of this fix. * gst/gstelement.c (gst_element_dispose): Really protect against multiple invocations this time.
This commit is contained in:
parent
558ac743bb
commit
b6a5699ca6
5 changed files with 380 additions and 231 deletions
17
ChangeLog
17
ChangeLog
|
@ -1,3 +1,19 @@
|
|||
2004-03-07 Andy Wingo <wingo@pobox.com>
|
||||
|
||||
* gst/gstbin.c (gst_bin_remove): Debugging fixes.
|
||||
|
||||
* gst/schedulers/gstoptimalscheduler.c (destroy_group): Assert
|
||||
there are no links to other groups when a group is destroyed.
|
||||
(gst_opt_scheduler_pad_unlink): If the unlink means an element is
|
||||
removed from a group, make sure the link count to elements linked
|
||||
to other pads is appropriately decremented. This really fixes
|
||||
#135672.
|
||||
|
||||
The 1.60->1.61 patch has been reapplied in light of this fix.
|
||||
|
||||
* gst/gstelement.c (gst_element_dispose): Really protect against
|
||||
multiple invocations this time.
|
||||
|
||||
2004-03-06 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||
|
||||
* docs/gst/gstreamer-sections.txt:
|
||||
|
@ -272,6 +288,7 @@
|
|||
* docs/manual/debugging.xml:
|
||||
fix manual for new debugging system
|
||||
|
||||
>>>>>>> 1.292
|
||||
2004-02-25 Andy Wingo <wingo@pobox.com>
|
||||
|
||||
* gst/gstpad.c (gst_pad_link_prepare): Re-add
|
||||
|
|
|
@ -110,10 +110,6 @@ All GstElements can be serialized to an XML presentation and subsequently loaded
|
|||
|
||||
</para>
|
||||
|
||||
@:
|
||||
@:
|
||||
@:
|
||||
|
||||
@gstxml: the object which received the signal.
|
||||
@arg1:
|
||||
@arg2:
|
||||
|
@ -123,7 +119,7 @@ All GstElements can be serialized to an XML presentation and subsequently loaded
|
|||
|
||||
</para>
|
||||
|
||||
@gstxml: the object which received the signal.
|
||||
@arg1:
|
||||
@arg2:
|
||||
@:
|
||||
@:
|
||||
@:
|
||||
|
||||
|
|
|
@ -564,7 +564,8 @@ gst_bin_remove (GstBin *bin, GstElement *element)
|
|||
{
|
||||
GstBinClass *bclass;
|
||||
|
||||
GST_CAT_DEBUG (GST_CAT_PARENTAGE, "[%s]: trying to remove child %s", GST_ELEMENT_NAME (bin), GST_ELEMENT_NAME (element));
|
||||
GST_CAT_DEBUG (GST_CAT_PARENTAGE, "[%s]: trying to remove child %s",
|
||||
GST_ELEMENT_NAME (bin), GST_ELEMENT_NAME (element));
|
||||
|
||||
g_return_if_fail (GST_IS_BIN (bin));
|
||||
g_return_if_fail (GST_IS_ELEMENT (element));
|
||||
|
|
|
@ -2947,14 +2947,17 @@ gst_element_dispose (GObject *object)
|
|||
element->numpads = 0;
|
||||
if (element->state_mutex)
|
||||
g_mutex_free (element->state_mutex);
|
||||
element->state_mutex = NULL;
|
||||
if (element->state_cond)
|
||||
g_cond_free (element->state_cond);
|
||||
element->state_cond = NULL;
|
||||
|
||||
if (element->prop_value_queue)
|
||||
g_async_queue_unref (element->prop_value_queue);
|
||||
element->prop_value_queue = NULL;
|
||||
if (element->property_mutex)
|
||||
g_mutex_free (element->property_mutex);
|
||||
element->property_mutex = NULL;
|
||||
|
||||
gst_object_replace ((GstObject **)&element->sched, NULL);
|
||||
gst_object_replace ((GstObject **)&element->clock, NULL);
|
||||
|
|
|
@ -183,20 +183,81 @@ struct _GstOptSchedulerGroup {
|
|||
};
|
||||
|
||||
|
||||
/* some group operations */
|
||||
/*
|
||||
* A group is a set of elements through which data can flow without switching
|
||||
* cothreads or without invoking the scheduler's run queue.
|
||||
*/
|
||||
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);
|
||||
GstElement *element,
|
||||
gboolean enabled);
|
||||
static gboolean schedule_group (GstOptSchedulerGroup *group);
|
||||
|
||||
|
||||
/*
|
||||
* 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);
|
||||
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
|
||||
|
||||
|
||||
/*
|
||||
* Scheduler private data for an element
|
||||
*/
|
||||
|
@ -212,13 +273,16 @@ 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);
|
||||
|
@ -379,42 +443,6 @@ GST_PLUGIN_DEFINE (
|
|||
);
|
||||
|
||||
|
||||
static void
|
||||
destroy_chain (GstOptSchedulerChain *chain)
|
||||
{
|
||||
GstOptScheduler *osched;
|
||||
|
||||
GST_LOG ( "destroy chain %p", chain);
|
||||
|
||||
g_assert (chain->num_groups == 0);
|
||||
g_assert (chain->groups == NULL);
|
||||
|
||||
osched = chain->sched;
|
||||
osched->chains = g_slist_remove (osched->chains, chain);
|
||||
|
||||
gst_object_unref (GST_OBJECT (osched));
|
||||
|
||||
g_free (chain);
|
||||
}
|
||||
|
||||
static GstOptSchedulerChain*
|
||||
create_chain (GstOptScheduler *osched)
|
||||
{
|
||||
GstOptSchedulerChain *chain;
|
||||
|
||||
chain = g_new0 (GstOptSchedulerChain, 1);
|
||||
chain->sched = osched;
|
||||
chain->refcount = 1;
|
||||
chain->flags = GST_OPT_SCHEDULER_CHAIN_DISABLED;
|
||||
|
||||
gst_object_ref (GST_OBJECT (osched));
|
||||
osched->chains = g_slist_prepend (osched->chains, chain);
|
||||
|
||||
GST_LOG ( "new chain %p", chain);
|
||||
|
||||
return chain;
|
||||
}
|
||||
|
||||
static GstOptSchedulerChain*
|
||||
ref_chain (GstOptSchedulerChain *chain)
|
||||
{
|
||||
|
@ -439,17 +467,63 @@ unref_chain (GstOptSchedulerChain *chain)
|
|||
return chain;
|
||||
}
|
||||
|
||||
static GstOptSchedulerChain*
|
||||
create_chain (GstOptScheduler *osched)
|
||||
{
|
||||
GstOptSchedulerChain *chain;
|
||||
|
||||
chain = g_new0 (GstOptSchedulerChain, 1);
|
||||
chain->sched = osched;
|
||||
chain->refcount = 1;
|
||||
chain->flags = GST_OPT_SCHEDULER_CHAIN_DISABLED;
|
||||
|
||||
gst_object_ref (GST_OBJECT (osched));
|
||||
osched->chains = g_slist_prepend (osched->chains, chain);
|
||||
|
||||
GST_LOG ( "new chain %p", chain);
|
||||
|
||||
return chain;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_chain (GstOptSchedulerChain *chain)
|
||||
{
|
||||
GstOptScheduler *osched;
|
||||
|
||||
GST_LOG ( "destroy chain %p", chain);
|
||||
|
||||
g_assert (chain->num_groups == 0);
|
||||
g_assert (chain->groups == NULL);
|
||||
|
||||
osched = chain->sched;
|
||||
osched->chains = g_slist_remove (osched->chains, chain);
|
||||
|
||||
gst_object_unref (GST_OBJECT (osched));
|
||||
|
||||
g_free (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);
|
||||
chain->groups = g_slist_prepend (chain->groups, group);
|
||||
|
||||
/* 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->num_groups++;
|
||||
|
||||
if (GST_OPT_SCHEDULER_GROUP_IS_ENABLED (group)) {
|
||||
|
@ -462,7 +536,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;
|
||||
|
@ -491,10 +565,17 @@ 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;
|
||||
|
||||
ref_chain (chain2);
|
||||
/* switch if it's more efficient */
|
||||
if (chain1->num_groups < chain2->num_groups) {
|
||||
GstOptSchedulerChain *tmp = chain2;
|
||||
chain2 = chain1;
|
||||
chain1 = tmp;
|
||||
}
|
||||
|
||||
walk = chain2->groups;
|
||||
while (walk) {
|
||||
GstOptSchedulerGroup *group = (GstOptSchedulerGroup *) walk->data;
|
||||
|
@ -503,17 +584,15 @@ merge_chains (GstOptSchedulerChain *chain1, GstOptSchedulerChain *chain2)
|
|||
GST_LOG ("reparenting group %p from chain %p to %p",
|
||||
group, chain2, chain1);
|
||||
|
||||
group->chain = NULL;
|
||||
chain2->num_groups--;
|
||||
chain2 = unref_chain (chain2);
|
||||
ref_group (group);
|
||||
|
||||
remove_from_chain (chain2, group);
|
||||
add_to_chain (chain1, group);
|
||||
|
||||
group->chain = ref_chain (chain1);
|
||||
chain1->groups = g_slist_prepend (chain1->groups, group);
|
||||
chain1->num_groups++;
|
||||
unref_group (group);
|
||||
}
|
||||
g_slist_free (chain2->groups);
|
||||
chain2->groups = NULL;
|
||||
unref_chain (chain2);
|
||||
|
||||
/* chain2 is now freed, if nothing else was referencing it before */
|
||||
|
||||
return chain1;
|
||||
}
|
||||
|
@ -521,8 +600,8 @@ merge_chains (GstOptSchedulerChain *chain1, GstOptSchedulerChain *chain2)
|
|||
static void
|
||||
chain_group_set_enabled (GstOptSchedulerChain *chain, GstOptSchedulerGroup *group, gboolean enabled)
|
||||
{
|
||||
g_assert (chain != NULL);
|
||||
g_assert (group != NULL);
|
||||
g_assert (chain != 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);
|
||||
|
@ -539,6 +618,10 @@ 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);
|
||||
|
@ -594,28 +677,13 @@ ref_group (GstOptSchedulerGroup *group)
|
|||
return group;
|
||||
}
|
||||
|
||||
#ifndef USE_COTHREADS
|
||||
/* remove me
|
||||
static GstOptSchedulerGroup*
|
||||
ref_group_by_count (GstOptSchedulerGroup *group, gint count)
|
||||
{
|
||||
GST_LOG ("ref group %p %d->%d", group,
|
||||
group->refcount, group->refcount+count);
|
||||
|
||||
group->refcount += count;
|
||||
|
||||
return group;
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
|
||||
static GstOptSchedulerGroup*
|
||||
unref_group (GstOptSchedulerGroup *group)
|
||||
{
|
||||
GST_LOG ("unref group %p %d->%d", group,
|
||||
group->refcount, group->refcount-1);
|
||||
|
||||
if (--group->refcount == 1) {
|
||||
if (--group->refcount == 0) {
|
||||
destroy_group (group);
|
||||
group = NULL;
|
||||
}
|
||||
|
@ -623,6 +691,43 @@ unref_group (GstOptSchedulerGroup *group)
|
|||
return group;
|
||||
}
|
||||
|
||||
static GstOptSchedulerGroup*
|
||||
create_group (GstOptSchedulerChain *chain, GstElement *element,
|
||||
GstOptSchedulerGroupType type)
|
||||
{
|
||||
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;
|
||||
|
||||
add_to_group (group, element);
|
||||
add_to_chain (chain, group);
|
||||
group = unref_group (group); /* ...and sink. */
|
||||
|
||||
/* 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);
|
||||
g_assert (group->group_links == 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)
|
||||
{
|
||||
|
@ -639,6 +744,7 @@ 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));
|
||||
|
@ -649,28 +755,102 @@ add_to_group (GstOptSchedulerGroup *group, GstElement *element)
|
|||
group_element_set_enabled (group, element, TRUE);
|
||||
}
|
||||
|
||||
/* Ref the group... */
|
||||
ref_group (group);
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
/* if the element is linked to elements from other groups, you must decrement
|
||||
the link count prior to calling this function */
|
||||
static GstOptSchedulerGroup*
|
||||
create_group (GstOptSchedulerChain *chain, GstElement *element)
|
||||
remove_from_group (GstOptSchedulerGroup *group, GstElement *element)
|
||||
{
|
||||
GstOptSchedulerGroup *group;
|
||||
GST_DEBUG ("removing element \"%s\" from group %p", GST_ELEMENT_NAME (element), group);
|
||||
|
||||
group = g_new0 (GstOptSchedulerGroup, 1);
|
||||
GST_LOG ("new group %p", group);
|
||||
group->refcount = 1;
|
||||
group->flags = GST_OPT_SCHEDULER_GROUP_DISABLED;
|
||||
g_assert (group != NULL);
|
||||
g_assert (element != NULL);
|
||||
g_assert (GST_ELEMENT_SCHED_GROUP (element) == group);
|
||||
|
||||
group->elements = g_slist_remove (group->elements, element);
|
||||
group->num_elements--;
|
||||
|
||||
/* if the element was an entry point in the group, clear the group's
|
||||
* entry point */
|
||||
if (group->entry == element) {
|
||||
group->entry = NULL;
|
||||
}
|
||||
|
||||
GST_ELEMENT_SCHED_GROUP (element) = NULL;
|
||||
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);
|
||||
|
||||
add_to_group (group, element);
|
||||
add_to_chain (chain, 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)
|
||||
{
|
||||
g_assert (group1 != NULL);
|
||||
|
||||
GST_DEBUG ("merging groups %p and %p", group1, group2);
|
||||
|
||||
if (group1 == group2 || group2 == NULL)
|
||||
return group1;
|
||||
|
||||
while (group2 && group2->elements) {
|
||||
GstElement *element = (GstElement *)group2->elements->data;
|
||||
|
||||
group2 = remove_from_group (group2, element);
|
||||
add_to_group (group1, element);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -693,71 +873,6 @@ destroy_group_scheduler (GstOptSchedulerGroup *group)
|
|||
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);
|
||||
|
||||
g_assert (group != NULL);
|
||||
g_assert (element != NULL);
|
||||
g_assert (GST_ELEMENT_SCHED_GROUP (element) == group);
|
||||
|
||||
group->elements = g_slist_remove (group->elements, element);
|
||||
group->num_elements--;
|
||||
|
||||
/* if the element was an entry point in the group, clear the group's
|
||||
* entry point */
|
||||
if (group->entry == element) {
|
||||
group->entry = NULL;
|
||||
}
|
||||
|
||||
GST_ELEMENT_SCHED_GROUP (element) = NULL;
|
||||
gst_object_unref (GST_OBJECT (element));
|
||||
|
||||
if (group->num_elements == 0) {
|
||||
group = unref_group (group);
|
||||
}
|
||||
group = unref_group (group);
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
static GstOptSchedulerGroup*
|
||||
merge_groups (GstOptSchedulerGroup *group1, GstOptSchedulerGroup *group2)
|
||||
{
|
||||
g_assert (group1 != NULL);
|
||||
|
||||
GST_DEBUG ("merging groups %p and %p", group1, group2);
|
||||
|
||||
if (group1 == group2 || group2 == NULL)
|
||||
return group1;
|
||||
|
||||
while (group2 && group2->elements) {
|
||||
GstElement *element = (GstElement *)group2->elements->data;
|
||||
|
||||
group2 = remove_from_group (group2, element);
|
||||
add_to_group (group1, element);
|
||||
}
|
||||
|
||||
return group1;
|
||||
}
|
||||
|
||||
static void
|
||||
group_error_handler (GstOptSchedulerGroup *group)
|
||||
{
|
||||
|
@ -779,6 +894,11 @@ 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++;
|
||||
|
@ -787,8 +907,13 @@ 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) {
|
||||
GST_LOG ("enable group %p", group);
|
||||
chain_group_set_enabled (group->chain, group, TRUE);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -799,8 +924,13 @@ 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) {
|
||||
GST_LOG ("disable group %p", group);
|
||||
chain_group_set_enabled (group->chain, group, FALSE);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -855,8 +985,11 @@ schedule_group (GstOptSchedulerGroup *group)
|
|||
static void
|
||||
gst_opt_scheduler_schedule_run_queue (GstOptScheduler *osched)
|
||||
{
|
||||
GST_LOG_OBJECT (osched, "entering scheduler run queue recursion %d %d",
|
||||
osched->recursion, g_list_length (osched->runqueue));
|
||||
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) */
|
||||
|
||||
/* make sure we don't exceed max_recursion */
|
||||
if (osched->recursion > osched->max_recursion) {
|
||||
|
@ -872,7 +1005,7 @@ gst_opt_scheduler_schedule_run_queue (GstOptScheduler *osched)
|
|||
|
||||
group = (GstOptSchedulerGroup *) osched->runqueue->data;
|
||||
|
||||
/* runqueue hols refcount to group */
|
||||
/* runqueue holds refcount to group */
|
||||
osched->runqueue = g_list_remove (osched->runqueue, group);
|
||||
|
||||
GST_LOG_OBJECT (osched, "scheduling group %p", group);
|
||||
|
@ -945,7 +1078,7 @@ get_group_schedule_function (int argc, char *argv[])
|
|||
GstElement *entry = group->entry;
|
||||
const GList *pads = gst_element_get_pad_list (entry);
|
||||
|
||||
GST_LOG ("get wrapper of group %p", group);
|
||||
GST_LOG ("executing get-based group %p", group);
|
||||
|
||||
group->flags |= GST_OPT_SCHEDULER_GROUP_RUNNING;
|
||||
|
||||
|
@ -986,7 +1119,7 @@ loop_group_schedule_function (int argc, char *argv[])
|
|||
GstOptSchedulerGroup *group = (GstOptSchedulerGroup *) argv;
|
||||
GstElement *entry = group->entry;
|
||||
|
||||
GST_LOG ("loop wrapper of group %p", group);
|
||||
GST_LOG ("executing loop-based group %p", group);
|
||||
|
||||
group->flags |= GST_OPT_SCHEDULER_GROUP_RUNNING;
|
||||
|
||||
|
@ -1024,26 +1157,31 @@ gst_opt_scheduler_loop_wrapper (GstPad *sinkpad, GstData *data)
|
|||
{
|
||||
GstOptSchedulerGroup *group;
|
||||
GstOptScheduler *osched;
|
||||
|
||||
GST_LOG ("loop wrapper, putting buffer in bufpen");
|
||||
GstRealPad *peer;
|
||||
|
||||
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 (GST_RPAD_PEER (sinkpad))) {
|
||||
if (GST_PAD_BUFLIST (peer)) {
|
||||
g_warning ("deadlock detected, disabling group %p", group);
|
||||
group_error_handler (group);
|
||||
}
|
||||
else {
|
||||
GST_PAD_BUFLIST (GST_RPAD_PEER (sinkpad)) = g_list_append (GST_PAD_BUFLIST (GST_RPAD_PEER (sinkpad)), data);
|
||||
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);
|
||||
schedule_group (group);
|
||||
}
|
||||
#else
|
||||
GST_PAD_BUFLIST (GST_RPAD_PEER (sinkpad)) = g_list_append (GST_PAD_BUFLIST (GST_RPAD_PEER (sinkpad)), data);
|
||||
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);
|
||||
if (!(group->flags & GST_OPT_SCHEDULER_GROUP_RUNNING)) {
|
||||
GST_LOG ("adding %p to runqueue", group);
|
||||
GST_LOG ("adding group %p to runqueue", group);
|
||||
if (!g_list_find (osched->runqueue, group))
|
||||
{
|
||||
ref_group (group);
|
||||
|
@ -1052,8 +1190,8 @@ gst_opt_scheduler_loop_wrapper (GstPad *sinkpad, GstData *data)
|
|||
}
|
||||
#endif
|
||||
|
||||
GST_LOG ("after loop wrapper buflist %d",
|
||||
g_list_length (GST_PAD_BUFLIST (GST_RPAD_PEER (sinkpad))));
|
||||
GST_LOG ("%d buffers left on %s:%s's bufpen after chain handler",
|
||||
g_list_length (GST_PAD_BUFLIST (peer)));
|
||||
}
|
||||
|
||||
/* this function is called by a loop based element that performs a
|
||||
|
@ -1067,15 +1205,14 @@ gst_opt_scheduler_get_wrapper (GstPad *srcpad)
|
|||
GstOptScheduler *osched;
|
||||
gboolean disabled;
|
||||
|
||||
GST_LOG ("get wrapper, removing buffer from bufpen");
|
||||
GST_LOG ("get handler for %" GST_PTR_FORMAT, srcpad);
|
||||
|
||||
/* 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 ("get wrapper, returning queued data %d",
|
||||
g_list_length (GST_PAD_BUFLIST (srcpad)));
|
||||
GST_LOG ("returning popped queued data %p", data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
@ -1087,6 +1224,7 @@ 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
|
||||
|
@ -1099,9 +1237,9 @@ gst_opt_scheduler_get_wrapper (GstPad *srcpad)
|
|||
osched->runqueue = g_list_append (osched->runqueue, group);
|
||||
}
|
||||
|
||||
GST_LOG_OBJECT (osched, "recursing into scheduler group %p", group);
|
||||
GST_LOG ("recursing into scheduler group %p", group);
|
||||
gst_opt_scheduler_schedule_run_queue (osched);
|
||||
GST_LOG_OBJECT (osched, "return from recurse group %p", group);
|
||||
GST_LOG ("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);
|
||||
|
@ -1139,7 +1277,7 @@ gst_opt_scheduler_get_wrapper (GstPad *srcpad)
|
|||
}
|
||||
while (data == NULL);
|
||||
|
||||
GST_LOG ("get wrapper, returning data %p, queue length %d",
|
||||
GST_LOG ("get handler, returning data %p, queue length %d",
|
||||
data, g_list_length (GST_PAD_BUFLIST (srcpad)));
|
||||
|
||||
return data;
|
||||
|
@ -1207,44 +1345,9 @@ 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;
|
||||
|
||||
|
@ -1288,7 +1391,6 @@ 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;
|
||||
|
@ -1340,7 +1442,8 @@ get_group (GstElement *element, GstOptSchedulerGroup **group)
|
|||
* will also merge the chains.
|
||||
*/
|
||||
static GstOptSchedulerGroup*
|
||||
group_elements (GstOptScheduler *osched, GstElement *element1, GstElement *element2)
|
||||
group_elements (GstOptScheduler *osched, GstElement *element1, GstElement *element2,
|
||||
GstOptSchedulerGroupType type)
|
||||
{
|
||||
GstOptSchedulerGroup *group1, *group2, *group = NULL;
|
||||
|
||||
|
@ -1356,7 +1459,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);
|
||||
group = create_group (chain, element1, type);
|
||||
add_to_group (group, element2);
|
||||
}
|
||||
/* the first element has a group */
|
||||
|
@ -1548,9 +1651,8 @@ gst_opt_scheduler_add_element (GstScheduler *sched, GstElement *element)
|
|||
|
||||
chain = create_chain (osched);
|
||||
|
||||
group = create_group (chain, element);
|
||||
group = create_group (chain, element, GST_OPT_SCHEDULER_GROUP_LOOP);
|
||||
group->entry = element;
|
||||
group->type = GST_OPT_SCHEDULER_GROUP_LOOP;
|
||||
|
||||
GST_LOG ("added element \"%s\" as loop based entry", GST_ELEMENT_NAME (element));
|
||||
}
|
||||
|
@ -1733,13 +1835,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);
|
||||
group = group_elements (osched, element1, element2,
|
||||
GST_OPT_SCHEDULER_GROUP_GET);
|
||||
|
||||
/* 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);
|
||||
|
@ -1759,7 +1861,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);
|
||||
group_elements (osched, element1, element2, GST_OPT_SCHEDULER_GROUP_LOOP);
|
||||
break;
|
||||
case GST_OPT_GET_TO_LOOP:
|
||||
GST_LOG ("get to loop based link");
|
||||
|
@ -1770,7 +1872,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);
|
||||
group_elements (osched, element1, element2, GST_OPT_SCHEDULER_GROUP_LOOP);
|
||||
break;
|
||||
case GST_OPT_CHAIN_TO_LOOP:
|
||||
case GST_OPT_LOOP_TO_LOOP:
|
||||
|
@ -1796,7 +1898,8 @@ 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);
|
||||
group1 = create_group (group2->chain, element1,
|
||||
GST_OPT_SCHEDULER_GROUP_LOOP);
|
||||
}
|
||||
else {
|
||||
/* both elements are already in a group, make sure they are added to
|
||||
|
@ -2010,7 +2113,22 @@ gst_opt_scheduler_pad_unlink (GstScheduler *sched, GstPad *srcpad, GstPad *sinkp
|
|||
group->type == GST_OPT_SCHEDULER_GROUP_LOOP) &&
|
||||
!GST_ELEMENT_IS_DECOUPLED (element1))
|
||||
{
|
||||
GList *l;
|
||||
GstPad *pad;
|
||||
GstOptSchedulerGroup *peer_group;
|
||||
|
||||
GST_LOG ("element1 is separated from the group");
|
||||
|
||||
/* have to decrement links to other groups from other pads */
|
||||
for (l=element1->pads; l; l=l->next) {
|
||||
pad = (GstPad*)l->data;
|
||||
if (GST_IS_REAL_PAD (pad) && GST_PAD_PEER (pad)) {
|
||||
get_group (GST_PAD_PARENT (GST_PAD_PEER (pad)), &peer_group);
|
||||
if (peer_group && peer_group != group)
|
||||
group_dec_link (group, peer_group);
|
||||
}
|
||||
}
|
||||
|
||||
remove_from_group (group, element1);
|
||||
}
|
||||
else {
|
||||
|
@ -2024,7 +2142,22 @@ gst_opt_scheduler_pad_unlink (GstScheduler *sched, GstPad *srcpad, GstPad *sinkp
|
|||
group->type == GST_OPT_SCHEDULER_GROUP_LOOP) &&
|
||||
!GST_ELEMENT_IS_DECOUPLED (element2))
|
||||
{
|
||||
GList *l;
|
||||
GstPad *pad;
|
||||
GstOptSchedulerGroup *peer_group;
|
||||
|
||||
GST_LOG ("element2 is separated from the group");
|
||||
|
||||
/* have to decrement links to other groups from other pads */
|
||||
for (l=element2->pads; l; l=l->next) {
|
||||
pad = (GstPad*)l->data;
|
||||
if (GST_IS_REAL_PAD (pad) && GST_PAD_PEER (pad)) {
|
||||
get_group (GST_PAD_PARENT (GST_PAD_PEER (pad)), &peer_group);
|
||||
if (peer_group && peer_group != group)
|
||||
group_dec_link (group, peer_group);
|
||||
}
|
||||
}
|
||||
|
||||
remove_from_group (group, element2);
|
||||
}
|
||||
else {
|
||||
|
@ -2052,7 +2185,7 @@ gst_opt_scheduler_iterate (GstScheduler *sched)
|
|||
|
||||
osched->state = GST_OPT_SCHEDULER_STATE_RUNNING;
|
||||
|
||||
GST_DEBUG ("iterating scheduler %p", sched);
|
||||
GST_DEBUG_OBJECT (sched, "iterating");
|
||||
|
||||
while (iterations) {
|
||||
gboolean scheduled = FALSE;
|
||||
|
@ -2066,6 +2199,7 @@ 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;
|
||||
}
|
||||
|
@ -2080,8 +2214,6 @@ 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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue