2002-09-08 17:58:00 +00:00
|
|
|
/* GStreamer
|
|
|
|
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
|
|
|
|
* 2000 Wim Taymans <wtay@chello.be>
|
|
|
|
*
|
|
|
|
* gstscheduler.c: Default scheduling code for most cases
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Library General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Library General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Library General Public
|
|
|
|
* License along with this library; if not, write to the
|
|
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
|
|
* Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
2003-06-29 14:05:49 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2002-09-08 17:58:00 +00:00
|
|
|
#include <gst/gst.h>
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_DEBUG_CATEGORY_STATIC (debug_scheduler);
|
2003-06-29 14:05:49 +00:00
|
|
|
#define GST_CAT_DEFAULT debug_scheduler
|
|
|
|
|
2002-12-15 18:21:43 +00:00
|
|
|
#ifdef USE_COTHREADS
|
|
|
|
# include "cothreads_compat.h"
|
|
|
|
#else
|
|
|
|
# define COTHREADS_NAME_CAPITAL ""
|
|
|
|
# define COTHREADS_NAME ""
|
|
|
|
#endif
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2003-12-13 16:58:29 +00:00
|
|
|
#define GST_ELEMENT_SCHED_CONTEXT(elem) ((GstOptSchedulerCtx*) (GST_ELEMENT (elem)->sched_private))
|
2002-09-08 17:58:00 +00:00
|
|
|
#define GST_ELEMENT_SCHED_GROUP(elem) (GST_ELEMENT_SCHED_CONTEXT (elem)->group)
|
2004-03-24 14:06:48 +00:00
|
|
|
/* need this first macro to not run into lvalue casts */
|
gst/autoplug/gstspideridentity.c: extra debugging
Original commit message from CVS:
* gst/autoplug/gstspideridentity.c: (gst_spider_identity_chain):
extra debugging
* gst/gstevent.h:
* gst/gstinfo.c: (gst_debug_log_default):
print time nicely. add thread pointer until someone figures out
a completely portable way of getting at thread id's.
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_try),
(_invent_event), (gst_pad_pull), (gst_pad_event_default_dispatch),
(gst_pad_call_chain_function):
extra debugging
* gst/schedulers/gstoptimalscheduler.c:
(get_group_schedule_function), (loop_group_schedule_function),
(gst_opt_scheduler_loop_wrapper), (gst_opt_scheduler_get_wrapper),
(pad_clear_queued), (gst_opt_scheduler_iterate):
rename BUFPEN and friends to DATAPEN since that's what they are.
2004-07-08 13:49:14 +00:00
|
|
|
#define GST_PAD_DATAPEN(pad) (GST_REAL_PAD(pad)->sched_private)
|
|
|
|
#define GST_PAD_DATALIST(pad) ((GList*) GST_PAD_DATAPEN(pad))
|
2002-09-08 17:58:00 +00:00
|
|
|
|
|
|
|
#define GST_ELEMENT_COTHREAD_STOPPING GST_ELEMENT_SCHEDULER_PRIVATE1
|
|
|
|
#define GST_ELEMENT_IS_COTHREAD_STOPPING(element) GST_FLAG_IS_SET((element), GST_ELEMENT_COTHREAD_STOPPING)
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
#define GST_ELEMENT_VISITED GST_ELEMENT_SCHEDULER_PRIVATE2
|
|
|
|
#define GST_ELEMENT_IS_VISITED(element) GST_FLAG_IS_SET((element), GST_ELEMENT_VISITED)
|
|
|
|
#define GST_ELEMENT_SET_VISITED(element) GST_FLAG_SET((element), GST_ELEMENT_VISITED)
|
|
|
|
#define GST_ELEMENT_UNSET_VISITED(element) GST_FLAG_UNSET((element), GST_ELEMENT_VISITED)
|
2002-09-08 17:58:00 +00:00
|
|
|
|
|
|
|
typedef struct _GstOptScheduler GstOptScheduler;
|
|
|
|
typedef struct _GstOptSchedulerClass GstOptSchedulerClass;
|
|
|
|
|
|
|
|
#define GST_TYPE_OPT_SCHEDULER \
|
|
|
|
(gst_opt_scheduler_get_type())
|
|
|
|
#define GST_OPT_SCHEDULER(obj) \
|
|
|
|
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OPT_SCHEDULER,GstOptScheduler))
|
|
|
|
#define GST_OPT_SCHEDULER_CLASS(klass) \
|
|
|
|
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OPT_SCHEDULER,GstOptSchedulerClass))
|
|
|
|
#define GST_IS_OPT_SCHEDULER(obj) \
|
|
|
|
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OPT_SCHEDULER))
|
|
|
|
#define GST_IS_OPT_SCHEDULER_CLASS(obj) \
|
|
|
|
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OPT_SCHEDULER))
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
typedef enum
|
|
|
|
{
|
2002-09-08 17:58:00 +00:00
|
|
|
GST_OPT_SCHEDULER_STATE_NONE,
|
|
|
|
GST_OPT_SCHEDULER_STATE_STOPPED,
|
|
|
|
GST_OPT_SCHEDULER_STATE_ERROR,
|
|
|
|
GST_OPT_SCHEDULER_STATE_RUNNING,
|
2003-01-08 21:33:20 +00:00
|
|
|
GST_OPT_SCHEDULER_STATE_INTERRUPTED
|
2004-03-15 19:24:35 +00:00
|
|
|
}
|
|
|
|
GstOptSchedulerState;
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
struct _GstOptScheduler
|
|
|
|
{
|
|
|
|
GstScheduler parent;
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
GstOptSchedulerState state;
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2002-12-15 18:21:43 +00:00
|
|
|
#ifdef USE_COTHREADS
|
2004-03-13 15:27:01 +00:00
|
|
|
cothread_context *context;
|
2002-12-15 18:21:43 +00:00
|
|
|
#endif
|
2004-03-13 15:27:01 +00:00
|
|
|
gint iterations;
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
GSList *elements;
|
|
|
|
GSList *chains;
|
2002-09-12 19:22:03 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
GList *runqueue;
|
|
|
|
gint recursion;
|
2003-01-01 04:28:33 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
gint max_recursion;
|
gst/schedulers/gstoptimalscheduler.c: Call group_inc_link with the proper src->sink ordering -- break this, and we br...
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (gst_opt_scheduler_init),
(create_chain), (destroy_chain), (create_group), (destroy_group),
(add_to_group), (merge_groups), (group_elements), (group_inc_link),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_inc_links_for_element), (group_migrate_connected):
Call group_inc_link with the proper src->sink ordering --
break this, and we break sort_chain. patch from wingo for bug
147713.
Partially revert patch 1.89. When adding a loop based element to
the scheduler, the links to other groups are automatically followed
and incremented. This should not happen because the bin will call
pad_link explicitly for those connection, resulting in them counted
twice. Results in assertion failure on pipeline cleanup.
2004-07-16 16:02:12 +00:00
|
|
|
gint live_groups;
|
|
|
|
gint live_chains;
|
|
|
|
gint live_links;
|
2002-09-08 17:58:00 +00:00
|
|
|
};
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
struct _GstOptSchedulerClass
|
|
|
|
{
|
2002-09-08 17:58:00 +00:00
|
|
|
GstSchedulerClass parent_class;
|
|
|
|
};
|
|
|
|
|
|
|
|
static GType _gst_opt_scheduler_type = 0;
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
GST_OPT_SCHEDULER_CHAIN_DIRTY = (1 << 1),
|
|
|
|
GST_OPT_SCHEDULER_CHAIN_DISABLED = (1 << 2),
|
2004-05-28 05:01:05 +00:00
|
|
|
GST_OPT_SCHEDULER_CHAIN_RUNNING = (1 << 3)
|
2004-03-15 19:24:35 +00:00
|
|
|
}
|
|
|
|
GstOptSchedulerChainFlags;
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-04-03 13:24:07 +00:00
|
|
|
#define GST_OPT_SCHEDULER_CHAIN_SET_DIRTY(chain) ((chain)->flags |= GST_OPT_SCHEDULER_CHAIN_DIRTY)
|
|
|
|
#define GST_OPT_SCHEDULER_CHAIN_SET_CLEAN(chain) ((chain)->flags &= ~GST_OPT_SCHEDULER_CHAIN_DIRTY)
|
|
|
|
#define GST_OPT_SCHEDULER_CHAIN_IS_DIRTY(chain) ((chain)->flags & GST_OPT_SCHEDULER_CHAIN_DIRTY)
|
|
|
|
|
2002-09-08 17:58:00 +00:00
|
|
|
#define GST_OPT_SCHEDULER_CHAIN_DISABLE(chain) ((chain)->flags |= GST_OPT_SCHEDULER_CHAIN_DISABLED)
|
|
|
|
#define GST_OPT_SCHEDULER_CHAIN_ENABLE(chain) ((chain)->flags &= ~GST_OPT_SCHEDULER_CHAIN_DISABLED)
|
|
|
|
#define GST_OPT_SCHEDULER_CHAIN_IS_DISABLED(chain) ((chain)->flags & GST_OPT_SCHEDULER_CHAIN_DISABLED)
|
|
|
|
|
|
|
|
typedef struct _GstOptSchedulerChain GstOptSchedulerChain;
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
struct _GstOptSchedulerChain
|
|
|
|
{
|
|
|
|
gint refcount;
|
|
|
|
|
|
|
|
GstOptScheduler *sched;
|
|
|
|
|
|
|
|
GstOptSchedulerChainFlags flags;
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-03-15 19:24:35 +00:00
|
|
|
GSList *groups; /* the groups in this chain */
|
2004-03-13 15:27:01 +00:00
|
|
|
gint num_groups;
|
|
|
|
gint num_enabled;
|
2002-09-08 17:58:00 +00:00
|
|
|
};
|
2003-10-08 16:06:02 +00:00
|
|
|
|
2002-09-08 17:58:00 +00:00
|
|
|
/*
|
|
|
|
* elements that are scheduled in one cothread
|
|
|
|
*/
|
2004-03-13 15:27:01 +00:00
|
|
|
typedef enum
|
|
|
|
{
|
2004-03-15 19:24:35 +00:00
|
|
|
GST_OPT_SCHEDULER_GROUP_DIRTY = (1 << 1), /* this group has been modified */
|
|
|
|
GST_OPT_SCHEDULER_GROUP_COTHREAD_STOPPING = (1 << 2), /* the group's cothread stops after one iteration */
|
|
|
|
GST_OPT_SCHEDULER_GROUP_DISABLED = (1 << 3), /* this group is disabled */
|
|
|
|
GST_OPT_SCHEDULER_GROUP_RUNNING = (1 << 4), /* this group is running */
|
|
|
|
GST_OPT_SCHEDULER_GROUP_SCHEDULABLE = (1 << 5), /* this group is schedulable */
|
2004-05-28 05:01:05 +00:00
|
|
|
GST_OPT_SCHEDULER_GROUP_VISITED = (1 << 6) /* this group is visited when finding links */
|
2004-03-15 19:24:35 +00:00
|
|
|
}
|
|
|
|
GstOptSchedulerGroupFlags;
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
typedef enum
|
|
|
|
{
|
2004-05-18 16:44:44 +00:00
|
|
|
GST_OPT_SCHEDULER_GROUP_UNKNOWN = 3,
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_OPT_SCHEDULER_GROUP_GET = 1,
|
2004-05-28 05:01:05 +00:00
|
|
|
GST_OPT_SCHEDULER_GROUP_LOOP = 2
|
2004-03-15 19:24:35 +00:00
|
|
|
}
|
|
|
|
GstOptSchedulerGroupType;
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2002-12-16 21:21:02 +00:00
|
|
|
#define GST_OPT_SCHEDULER_GROUP_SET_FLAG(group,flag) ((group)->flags |= (flag))
|
2003-06-07 11:36:42 +00:00
|
|
|
#define GST_OPT_SCHEDULER_GROUP_UNSET_FLAG(group,flag) ((group)->flags &= ~(flag))
|
2002-12-16 21:21:02 +00:00
|
|
|
#define GST_OPT_SCHEDULER_GROUP_IS_FLAG_SET(group,flag) ((group)->flags & (flag))
|
|
|
|
|
2002-09-08 17:58:00 +00:00
|
|
|
#define GST_OPT_SCHEDULER_GROUP_DISABLE(group) ((group)->flags |= GST_OPT_SCHEDULER_GROUP_DISABLED)
|
|
|
|
#define GST_OPT_SCHEDULER_GROUP_ENABLE(group) ((group)->flags &= ~GST_OPT_SCHEDULER_GROUP_DISABLED)
|
2002-09-13 23:02:54 +00:00
|
|
|
#define GST_OPT_SCHEDULER_GROUP_IS_ENABLED(group) (!((group)->flags & GST_OPT_SCHEDULER_GROUP_DISABLED))
|
2002-09-08 17:58:00 +00:00
|
|
|
#define GST_OPT_SCHEDULER_GROUP_IS_DISABLED(group) ((group)->flags & GST_OPT_SCHEDULER_GROUP_DISABLED)
|
|
|
|
|
2003-06-07 11:36:42 +00:00
|
|
|
|
2002-09-08 17:58:00 +00:00
|
|
|
typedef struct _GstOptSchedulerGroup GstOptSchedulerGroup;
|
2003-06-07 11:36:42 +00:00
|
|
|
typedef struct _GstOptSchedulerGroupLink GstOptSchedulerGroupLink;
|
|
|
|
|
|
|
|
/* used to keep track of links with other groups */
|
2004-03-13 15:27:01 +00:00
|
|
|
struct _GstOptSchedulerGroupLink
|
|
|
|
{
|
2004-04-03 13:24:07 +00:00
|
|
|
GstOptSchedulerGroup *src; /* the group we are linked with */
|
|
|
|
GstOptSchedulerGroup *sink; /* the group we are linked with */
|
2004-03-15 19:24:35 +00:00
|
|
|
gint count; /* the number of links with the group */
|
2003-06-07 11:36:42 +00:00
|
|
|
};
|
|
|
|
|
2004-04-03 13:24:07 +00:00
|
|
|
#define IS_GROUP_LINK(link, srcg, sinkg) ((link->src == srcg && link->sink == sinkg) || \
|
|
|
|
(link->sink == srcg && link->src == sinkg))
|
|
|
|
#define OTHER_GROUP_LINK(link, group) (link->src == group ? link->sink : link->src)
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
typedef int (*GroupScheduleFunction) (int argc, char *argv[]);
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
struct _GstOptSchedulerGroup
|
|
|
|
{
|
2004-03-15 19:24:35 +00:00
|
|
|
GstOptSchedulerChain *chain; /* the chain this group belongs to */
|
|
|
|
GstOptSchedulerGroupFlags flags; /* flags for this group */
|
|
|
|
GstOptSchedulerGroupType type; /* flags for this group */
|
gst/schedulers/gstoptimalscheduler.c: Call group_inc_link with the proper src->sink ordering -- break this, and we br...
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (gst_opt_scheduler_init),
(create_chain), (destroy_chain), (create_group), (destroy_group),
(add_to_group), (merge_groups), (group_elements), (group_inc_link),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_inc_links_for_element), (group_migrate_connected):
Call group_inc_link with the proper src->sink ordering --
break this, and we break sort_chain. patch from wingo for bug
147713.
Partially revert patch 1.89. When adding a loop based element to
the scheduler, the links to other groups are automatically followed
and incremented. This should not happen because the bin will call
pad_link explicitly for those connection, resulting in them counted
twice. Results in assertion failure on pipeline cleanup.
2004-07-16 16:02:12 +00:00
|
|
|
GstOptScheduler *sched; /* the scheduler */
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
gint refcount;
|
2003-02-27 18:21:34 +00:00
|
|
|
|
2004-03-15 19:24:35 +00:00
|
|
|
GSList *elements; /* elements of this group */
|
2004-03-13 15:27:01 +00:00
|
|
|
gint num_elements;
|
|
|
|
gint num_enabled;
|
2004-03-15 19:24:35 +00:00
|
|
|
GstElement *entry; /* the group's entry point */
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-03-15 19:24:35 +00:00
|
|
|
GSList *group_links; /* other groups that are linked with this group */
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2002-12-15 18:21:43 +00:00
|
|
|
#ifdef USE_COTHREADS
|
2004-03-15 19:24:35 +00:00
|
|
|
cothread *cothread; /* the cothread of this group */
|
2003-03-11 23:26:18 +00:00
|
|
|
#else
|
2004-03-13 15:27:01 +00:00
|
|
|
GroupScheduleFunction schedulefunc;
|
2003-03-11 23:26:18 +00:00
|
|
|
#endif
|
2004-03-13 15:27:01 +00:00
|
|
|
int argc;
|
|
|
|
char **argv;
|
2002-09-08 17:58:00 +00:00
|
|
|
};
|
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
/*
|
|
|
|
* A group is a set of elements through which data can flow without switching
|
|
|
|
* cothreads or without invoking the scheduler's run queue.
|
|
|
|
*/
|
2004-03-13 15:27:01 +00:00
|
|
|
static GstOptSchedulerGroup *ref_group (GstOptSchedulerGroup * group);
|
|
|
|
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,
|
gst/schedulers/gstoptimalscheduler.c: Call group_inc_link with the proper src->sink ordering -- break this, and we br...
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (gst_opt_scheduler_init),
(create_chain), (destroy_chain), (create_group), (destroy_group),
(add_to_group), (merge_groups), (group_elements), (group_inc_link),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_inc_links_for_element), (group_migrate_connected):
Call group_inc_link with the proper src->sink ordering --
break this, and we break sort_chain. patch from wingo for bug
147713.
Partially revert patch 1.89. When adding a loop based element to
the scheduler, the links to other groups are automatically followed
and incremented. This should not happen because the bin will call
pad_link explicitly for those connection, resulting in them counted
twice. Results in assertion failure on pipeline cleanup.
2004-07-16 16:02:12 +00:00
|
|
|
GstElement * element, gboolean with_links);
|
2004-03-13 15:27:01 +00:00
|
|
|
static GstOptSchedulerGroup *remove_from_group (GstOptSchedulerGroup * group,
|
|
|
|
GstElement * element);
|
2004-05-04 16:43:49 +00:00
|
|
|
static void group_dec_links_for_element (GstOptSchedulerGroup * group,
|
|
|
|
GstElement * element);
|
2004-05-27 09:33:29 +00:00
|
|
|
static void group_inc_links_for_element (GstOptSchedulerGroup * group,
|
|
|
|
GstElement * element);
|
2004-03-13 15:27:01 +00:00
|
|
|
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);
|
2004-07-20 10:40:09 +00:00
|
|
|
static void get_group (GstElement * element, GstOptSchedulerGroup ** group);
|
2003-02-27 18:21:34 +00:00
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* A chain is a set of groups that are linked to each other.
|
|
|
|
*/
|
2004-03-13 15:27:01 +00:00
|
|
|
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);
|
2004-03-07 14:33:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The schedule functions are the entry points for cothreads, or called directly
|
|
|
|
* by gst_opt_scheduler_schedule_run_queue
|
|
|
|
*/
|
2004-03-13 15:27:01 +00:00
|
|
|
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[]);
|
2004-03-07 14:33:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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).
|
|
|
|
*/
|
2004-03-13 15:27:01 +00:00
|
|
|
static void gst_opt_scheduler_loop_wrapper (GstPad * sinkpad, GstData * data);
|
|
|
|
static GstData *gst_opt_scheduler_get_wrapper (GstPad * srcpad);
|
2004-03-07 14:33:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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
|
2004-03-13 15:27:01 +00:00
|
|
|
static void gst_opt_scheduler_schedule_run_queue (GstOptScheduler * osched);
|
2004-03-07 14:33:13 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2002-09-08 17:58:00 +00:00
|
|
|
/*
|
|
|
|
* Scheduler private data for an element
|
|
|
|
*/
|
|
|
|
typedef struct _GstOptSchedulerCtx GstOptSchedulerCtx;
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
typedef enum
|
|
|
|
{
|
2004-05-28 05:01:05 +00:00
|
|
|
GST_OPT_SCHEDULER_CTX_DISABLED = (1 << 1) /* the element is disabled */
|
2004-03-15 19:24:35 +00:00
|
|
|
}
|
|
|
|
GstOptSchedulerCtxFlags;
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
struct _GstOptSchedulerCtx
|
|
|
|
{
|
2004-03-15 19:24:35 +00:00
|
|
|
GstOptSchedulerGroup *group; /* the group this element belongs to */
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-03-15 19:24:35 +00:00
|
|
|
GstOptSchedulerCtxFlags flags; /* flags for this element */
|
2002-09-08 17:58:00 +00:00
|
|
|
};
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
/*
|
|
|
|
* Implementation of GstScheduler
|
|
|
|
*/
|
2002-09-12 19:22:03 +00:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
ARG_0,
|
|
|
|
ARG_ITERATIONS,
|
2004-05-28 05:01:05 +00:00
|
|
|
ARG_MAX_RECURSION
|
2002-09-12 19:22:03 +00:00
|
|
|
};
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
static void gst_opt_scheduler_class_init (GstOptSchedulerClass * klass);
|
|
|
|
static void gst_opt_scheduler_init (GstOptScheduler * scheduler);
|
|
|
|
|
|
|
|
static void gst_opt_scheduler_set_property (GObject * object, guint prop_id,
|
|
|
|
const GValue * value, GParamSpec * pspec);
|
|
|
|
static void gst_opt_scheduler_get_property (GObject * object, guint prop_id,
|
|
|
|
GValue * value, GParamSpec * pspec);
|
|
|
|
|
|
|
|
static void gst_opt_scheduler_dispose (GObject * object);
|
|
|
|
|
|
|
|
static void gst_opt_scheduler_setup (GstScheduler * sched);
|
|
|
|
static void gst_opt_scheduler_reset (GstScheduler * sched);
|
|
|
|
static void gst_opt_scheduler_add_element (GstScheduler * sched,
|
|
|
|
GstElement * element);
|
|
|
|
static void gst_opt_scheduler_remove_element (GstScheduler * sched,
|
|
|
|
GstElement * element);
|
|
|
|
static GstElementStateReturn gst_opt_scheduler_state_transition (GstScheduler *
|
|
|
|
sched, GstElement * element, gint transition);
|
|
|
|
static void gst_opt_scheduler_scheduling_change (GstScheduler * sched,
|
|
|
|
GstElement * element);
|
|
|
|
static gboolean gst_opt_scheduler_yield (GstScheduler * sched,
|
|
|
|
GstElement * element);
|
|
|
|
static gboolean gst_opt_scheduler_interrupt (GstScheduler * sched,
|
|
|
|
GstElement * element);
|
|
|
|
static void gst_opt_scheduler_error (GstScheduler * sched,
|
|
|
|
GstElement * element);
|
|
|
|
static void gst_opt_scheduler_pad_link (GstScheduler * sched, GstPad * srcpad,
|
|
|
|
GstPad * sinkpad);
|
|
|
|
static void gst_opt_scheduler_pad_unlink (GstScheduler * sched, GstPad * srcpad,
|
|
|
|
GstPad * sinkpad);
|
|
|
|
static GstSchedulerState gst_opt_scheduler_iterate (GstScheduler * sched);
|
|
|
|
|
|
|
|
static void gst_opt_scheduler_show (GstScheduler * sched);
|
2002-09-08 17:58:00 +00:00
|
|
|
|
|
|
|
static GstSchedulerClass *parent_class = NULL;
|
|
|
|
|
|
|
|
static GType
|
|
|
|
gst_opt_scheduler_get_type (void)
|
|
|
|
{
|
|
|
|
if (!_gst_opt_scheduler_type) {
|
|
|
|
static const GTypeInfo scheduler_info = {
|
|
|
|
sizeof (GstOptSchedulerClass),
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
(GClassInitFunc) gst_opt_scheduler_class_init,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
sizeof (GstOptScheduler),
|
|
|
|
0,
|
|
|
|
(GInstanceInitFunc) gst_opt_scheduler_init,
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
_gst_opt_scheduler_type = g_type_register_static (GST_TYPE_SCHEDULER,
|
2004-03-15 19:24:35 +00:00
|
|
|
"GstOpt" COTHREADS_NAME_CAPITAL "Scheduler", &scheduler_info, 0);
|
2002-09-08 17:58:00 +00:00
|
|
|
}
|
|
|
|
return _gst_opt_scheduler_type;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
gst_opt_scheduler_class_init (GstOptSchedulerClass * klass)
|
2002-09-08 17:58:00 +00:00
|
|
|
{
|
|
|
|
GObjectClass *gobject_class;
|
|
|
|
GstObjectClass *gstobject_class;
|
|
|
|
GstSchedulerClass *gstscheduler_class;
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
gobject_class = (GObjectClass *) klass;
|
|
|
|
gstobject_class = (GstObjectClass *) klass;
|
|
|
|
gstscheduler_class = (GstSchedulerClass *) klass;
|
2002-09-08 17:58:00 +00:00
|
|
|
|
|
|
|
parent_class = g_type_class_ref (GST_TYPE_SCHEDULER);
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
gobject_class->set_property =
|
|
|
|
GST_DEBUG_FUNCPTR (gst_opt_scheduler_set_property);
|
|
|
|
gobject_class->get_property =
|
|
|
|
GST_DEBUG_FUNCPTR (gst_opt_scheduler_get_property);
|
|
|
|
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_opt_scheduler_dispose);
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2002-12-15 18:21:43 +00:00
|
|
|
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ITERATIONS,
|
2004-03-13 15:27:01 +00:00
|
|
|
g_param_spec_int ("iterations", "Iterations",
|
2004-03-15 19:24:35 +00:00
|
|
|
"Number of groups to schedule in one iteration (-1 == until EOS/error)",
|
|
|
|
-1, G_MAXINT, 1, G_PARAM_READWRITE));
|
2003-01-01 04:28:33 +00:00
|
|
|
#ifndef USE_COTHREADS
|
|
|
|
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAX_RECURSION,
|
2004-03-13 15:27:01 +00:00
|
|
|
g_param_spec_int ("max_recursion", "Max recursion",
|
2004-03-15 19:24:35 +00:00
|
|
|
"Maximum number of recursions", 1, G_MAXINT, 100, G_PARAM_READWRITE));
|
2003-01-01 04:28:33 +00:00
|
|
|
#endif
|
2002-09-12 19:22:03 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
gstscheduler_class->setup = GST_DEBUG_FUNCPTR (gst_opt_scheduler_setup);
|
|
|
|
gstscheduler_class->reset = GST_DEBUG_FUNCPTR (gst_opt_scheduler_reset);
|
|
|
|
gstscheduler_class->add_element =
|
|
|
|
GST_DEBUG_FUNCPTR (gst_opt_scheduler_add_element);
|
|
|
|
gstscheduler_class->remove_element =
|
|
|
|
GST_DEBUG_FUNCPTR (gst_opt_scheduler_remove_element);
|
|
|
|
gstscheduler_class->state_transition =
|
|
|
|
GST_DEBUG_FUNCPTR (gst_opt_scheduler_state_transition);
|
|
|
|
gstscheduler_class->scheduling_change =
|
|
|
|
GST_DEBUG_FUNCPTR (gst_opt_scheduler_scheduling_change);
|
|
|
|
gstscheduler_class->yield = GST_DEBUG_FUNCPTR (gst_opt_scheduler_yield);
|
|
|
|
gstscheduler_class->interrupt =
|
|
|
|
GST_DEBUG_FUNCPTR (gst_opt_scheduler_interrupt);
|
|
|
|
gstscheduler_class->error = GST_DEBUG_FUNCPTR (gst_opt_scheduler_error);
|
|
|
|
gstscheduler_class->pad_link = GST_DEBUG_FUNCPTR (gst_opt_scheduler_pad_link);
|
|
|
|
gstscheduler_class->pad_unlink =
|
|
|
|
GST_DEBUG_FUNCPTR (gst_opt_scheduler_pad_unlink);
|
|
|
|
gstscheduler_class->clock_wait = NULL;
|
|
|
|
gstscheduler_class->iterate = GST_DEBUG_FUNCPTR (gst_opt_scheduler_iterate);
|
|
|
|
gstscheduler_class->show = GST_DEBUG_FUNCPTR (gst_opt_scheduler_show);
|
|
|
|
|
2003-03-11 21:01:31 +00:00
|
|
|
#ifdef USE_COTHREADS
|
2004-03-13 15:27:01 +00:00
|
|
|
do_cothreads_init (NULL);
|
2003-03-11 21:01:31 +00:00
|
|
|
#endif
|
2002-09-08 17:58:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
gst_opt_scheduler_init (GstOptScheduler * scheduler)
|
2002-09-08 17:58:00 +00:00
|
|
|
{
|
|
|
|
scheduler->elements = NULL;
|
2002-09-12 19:22:03 +00:00
|
|
|
scheduler->iterations = 1;
|
2003-01-01 04:28:33 +00:00
|
|
|
scheduler->max_recursion = 100;
|
gst/schedulers/gstoptimalscheduler.c: Call group_inc_link with the proper src->sink ordering -- break this, and we br...
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (gst_opt_scheduler_init),
(create_chain), (destroy_chain), (create_group), (destroy_group),
(add_to_group), (merge_groups), (group_elements), (group_inc_link),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_inc_links_for_element), (group_migrate_connected):
Call group_inc_link with the proper src->sink ordering --
break this, and we break sort_chain. patch from wingo for bug
147713.
Partially revert patch 1.89. When adding a loop based element to
the scheduler, the links to other groups are automatically followed
and incremented. This should not happen because the bin will call
pad_link explicitly for those connection, resulting in them counted
twice. Results in assertion failure on pipeline cleanup.
2004-07-16 16:02:12 +00:00
|
|
|
scheduler->live_groups = 0;
|
|
|
|
scheduler->live_chains = 0;
|
|
|
|
scheduler->live_links = 0;
|
2002-09-08 17:58:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
gst_opt_scheduler_dispose (GObject * object)
|
2002-09-08 17:58:00 +00:00
|
|
|
{
|
|
|
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2004-03-13 15:27:01 +00:00
|
|
|
plugin_init (GstPlugin * plugin)
|
2002-09-08 17:58:00 +00:00
|
|
|
{
|
|
|
|
GstSchedulerFactory *factory;
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_DEBUG_CATEGORY_INIT (debug_scheduler, "scheduler", 0,
|
|
|
|
"optimal scheduler");
|
2003-06-29 14:05:49 +00:00
|
|
|
|
2003-02-10 20:11:14 +00:00
|
|
|
#ifdef USE_COTHREADS
|
2004-03-13 15:27:01 +00:00
|
|
|
factory = gst_scheduler_factory_new ("opt" COTHREADS_NAME,
|
|
|
|
"An optimal scheduler using " COTHREADS_NAME " cothreads",
|
|
|
|
gst_opt_scheduler_get_type ());
|
2003-02-10 20:11:14 +00:00
|
|
|
#else
|
|
|
|
factory = gst_scheduler_factory_new ("opt",
|
2004-03-13 15:27:01 +00:00
|
|
|
"An optimal scheduler using no cothreads", gst_opt_scheduler_get_type ());
|
2003-02-10 20:11:14 +00:00
|
|
|
#endif
|
2002-09-08 17:58:00 +00:00
|
|
|
|
|
|
|
if (factory != NULL) {
|
|
|
|
gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
|
2004-03-13 15:27:01 +00:00
|
|
|
} else {
|
2002-09-08 17:58:00 +00:00
|
|
|
g_warning ("could not register scheduler: optimal");
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
|
|
|
|
GST_VERSION_MINOR,
|
|
|
|
"gstopt" COTHREADS_NAME "scheduler",
|
|
|
|
"An optimal scheduler using " COTHREADS_NAME " cothreads",
|
|
|
|
plugin_init, VERSION, GST_LICENSE, GST_PACKAGE, GST_ORIGIN);
|
2002-09-08 17:58:00 +00:00
|
|
|
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
static GstOptSchedulerChain *
|
|
|
|
ref_chain (GstOptSchedulerChain * chain)
|
2002-09-08 17:58:00 +00:00
|
|
|
{
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_LOG ("ref chain %p %d->%d", chain, chain->refcount, chain->refcount + 1);
|
2004-03-07 14:33:13 +00:00
|
|
|
chain->refcount++;
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
return chain;
|
|
|
|
}
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
static GstOptSchedulerChain *
|
|
|
|
unref_chain (GstOptSchedulerChain * chain)
|
2004-03-07 14:33:13 +00:00
|
|
|
{
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_LOG ("unref chain %p %d->%d", chain,
|
|
|
|
chain->refcount, chain->refcount - 1);
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
if (--chain->refcount == 0) {
|
|
|
|
destroy_chain (chain);
|
|
|
|
chain = NULL;
|
|
|
|
}
|
2002-11-07 18:50:06 +00:00
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
return chain;
|
2002-09-08 17:58:00 +00:00
|
|
|
}
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
static GstOptSchedulerChain *
|
|
|
|
create_chain (GstOptScheduler * osched)
|
2002-09-08 17:58:00 +00:00
|
|
|
{
|
2003-02-27 18:21:34 +00:00
|
|
|
GstOptSchedulerChain *chain;
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2003-02-27 18:21:34 +00:00
|
|
|
chain = g_new0 (GstOptSchedulerChain, 1);
|
|
|
|
chain->sched = osched;
|
|
|
|
chain->refcount = 1;
|
2003-03-25 19:34:30 +00:00
|
|
|
chain->flags = GST_OPT_SCHEDULER_CHAIN_DISABLED;
|
gst/schedulers/gstoptimalscheduler.c: Call group_inc_link with the proper src->sink ordering -- break this, and we br...
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (gst_opt_scheduler_init),
(create_chain), (destroy_chain), (create_group), (destroy_group),
(add_to_group), (merge_groups), (group_elements), (group_inc_link),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_inc_links_for_element), (group_migrate_connected):
Call group_inc_link with the proper src->sink ordering --
break this, and we break sort_chain. patch from wingo for bug
147713.
Partially revert patch 1.89. When adding a loop based element to
the scheduler, the links to other groups are automatically followed
and incremented. This should not happen because the bin will call
pad_link explicitly for those connection, resulting in them counted
twice. Results in assertion failure on pipeline cleanup.
2004-07-16 16:02:12 +00:00
|
|
|
osched->live_chains++;
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2003-02-27 18:21:34 +00:00
|
|
|
gst_object_ref (GST_OBJECT (osched));
|
|
|
|
osched->chains = g_slist_prepend (osched->chains, chain);
|
|
|
|
|
gst/schedulers/gstoptimalscheduler.c: Call group_inc_link with the proper src->sink ordering -- break this, and we br...
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (gst_opt_scheduler_init),
(create_chain), (destroy_chain), (create_group), (destroy_group),
(add_to_group), (merge_groups), (group_elements), (group_inc_link),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_inc_links_for_element), (group_migrate_connected):
Call group_inc_link with the proper src->sink ordering --
break this, and we break sort_chain. patch from wingo for bug
147713.
Partially revert patch 1.89. When adding a loop based element to
the scheduler, the links to other groups are automatically followed
and incremented. This should not happen because the bin will call
pad_link explicitly for those connection, resulting in them counted
twice. Results in assertion failure on pipeline cleanup.
2004-07-16 16:02:12 +00:00
|
|
|
GST_LOG ("new chain %p, %d live chains now", chain, osched->live_chains);
|
2002-12-15 12:18:04 +00:00
|
|
|
|
|
|
|
return chain;
|
2002-09-08 17:58:00 +00:00
|
|
|
}
|
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
destroy_chain (GstOptSchedulerChain * chain)
|
2002-09-08 17:58:00 +00:00
|
|
|
{
|
2004-03-07 14:33:13 +00:00
|
|
|
GstOptScheduler *osched;
|
2004-03-13 15:27:01 +00:00
|
|
|
|
|
|
|
GST_LOG ("destroy chain %p", chain);
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
g_assert (chain->num_groups == 0);
|
|
|
|
g_assert (chain->groups == NULL);
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
osched = chain->sched;
|
|
|
|
osched->chains = g_slist_remove (osched->chains, chain);
|
gst/schedulers/gstoptimalscheduler.c: Call group_inc_link with the proper src->sink ordering -- break this, and we br...
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (gst_opt_scheduler_init),
(create_chain), (destroy_chain), (create_group), (destroy_group),
(add_to_group), (merge_groups), (group_elements), (group_inc_link),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_inc_links_for_element), (group_migrate_connected):
Call group_inc_link with the proper src->sink ordering --
break this, and we break sort_chain. patch from wingo for bug
147713.
Partially revert patch 1.89. When adding a loop based element to
the scheduler, the links to other groups are automatically followed
and incremented. This should not happen because the bin will call
pad_link explicitly for those connection, resulting in them counted
twice. Results in assertion failure on pipeline cleanup.
2004-07-16 16:02:12 +00:00
|
|
|
osched->live_chains--;
|
|
|
|
|
|
|
|
GST_LOG ("%d live chains now", osched->live_chains);
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
gst_object_unref (GST_OBJECT (osched));
|
2003-02-27 18:21:34 +00:00
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
g_free (chain);
|
2003-02-27 18:21:34 +00:00
|
|
|
}
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
static GstOptSchedulerChain *
|
|
|
|
add_to_chain (GstOptSchedulerChain * chain, GstOptSchedulerGroup * group)
|
2003-02-27 18:21:34 +00:00
|
|
|
{
|
2004-05-27 09:33:29 +00:00
|
|
|
gboolean enabled;
|
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
GST_LOG ("adding group %p to chain %p", group, chain);
|
2003-02-27 18:21:34 +00:00
|
|
|
|
|
|
|
g_assert (group->chain == NULL);
|
|
|
|
|
|
|
|
group = ref_group (group);
|
|
|
|
|
|
|
|
group->chain = ref_chain (chain);
|
2004-04-03 13:24:07 +00:00
|
|
|
chain->groups = g_slist_prepend (chain->groups, group);
|
2003-02-27 18:21:34 +00:00
|
|
|
chain->num_groups++;
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-05-27 09:33:29 +00:00
|
|
|
enabled = GST_OPT_SCHEDULER_GROUP_IS_ENABLED (group);
|
|
|
|
|
|
|
|
if (enabled) {
|
2004-05-27 11:29:18 +00:00
|
|
|
/* we can now setup the scheduling of the group */
|
|
|
|
setup_group_scheduler (chain->sched, group);
|
|
|
|
|
2004-05-27 09:33:29 +00:00
|
|
|
chain->num_enabled++;
|
|
|
|
if (chain->num_enabled == chain->num_groups) {
|
|
|
|
GST_LOG ("enabling chain %p after adding of enabled group", chain);
|
|
|
|
GST_OPT_SCHEDULER_CHAIN_ENABLE (chain);
|
|
|
|
}
|
2003-03-28 17:29:57 +00:00
|
|
|
}
|
|
|
|
|
2004-04-03 13:24:07 +00:00
|
|
|
/* queue a resort of the group list, which determines which group will be run
|
|
|
|
* first. */
|
|
|
|
GST_OPT_SCHEDULER_CHAIN_SET_DIRTY (chain);
|
|
|
|
|
2002-09-08 17:58:00 +00:00
|
|
|
return chain;
|
|
|
|
}
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
static GstOptSchedulerChain *
|
|
|
|
remove_from_chain (GstOptSchedulerChain * chain, GstOptSchedulerGroup * group)
|
2002-09-08 17:58:00 +00:00
|
|
|
{
|
2004-05-27 09:33:29 +00:00
|
|
|
gboolean enabled;
|
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
GST_LOG ("removing group %p from chain %p", group, chain);
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2002-12-15 12:18:04 +00:00
|
|
|
if (!chain)
|
|
|
|
return NULL;
|
|
|
|
|
2002-12-15 18:21:43 +00:00
|
|
|
g_assert (group);
|
2002-09-08 17:58:00 +00:00
|
|
|
g_assert (group->chain == chain);
|
|
|
|
|
2004-05-27 09:33:29 +00:00
|
|
|
enabled = GST_OPT_SCHEDULER_GROUP_IS_ENABLED (group);
|
|
|
|
|
2003-02-27 18:21:34 +00:00
|
|
|
group->chain = NULL;
|
2002-09-08 22:42:29 +00:00
|
|
|
chain->groups = g_slist_remove (chain->groups, group);
|
2002-09-08 17:58:00 +00:00
|
|
|
chain->num_groups--;
|
2003-02-27 18:21:34 +00:00
|
|
|
unref_group (group);
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
if (chain->num_groups == 0)
|
2003-02-27 18:21:34 +00:00
|
|
|
chain = unref_chain (chain);
|
2004-05-27 09:33:29 +00:00
|
|
|
else {
|
|
|
|
/* removing an enabled group from the chain decrements the
|
|
|
|
* enabled counter */
|
|
|
|
if (enabled) {
|
|
|
|
chain->num_enabled--;
|
|
|
|
if (chain->num_enabled == 0) {
|
|
|
|
GST_LOG ("disabling chain %p after removal of the only enabled group",
|
|
|
|
chain);
|
|
|
|
GST_OPT_SCHEDULER_CHAIN_DISABLE (chain);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (chain->num_enabled == chain->num_groups) {
|
|
|
|
GST_LOG ("enabling chain %p after removal of the only disabled group",
|
|
|
|
chain);
|
|
|
|
GST_OPT_SCHEDULER_CHAIN_ENABLE (chain);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2002-12-15 12:18:04 +00:00
|
|
|
|
2004-04-03 13:24:07 +00:00
|
|
|
GST_OPT_SCHEDULER_CHAIN_SET_DIRTY (chain);
|
|
|
|
|
2003-02-27 18:21:34 +00:00
|
|
|
chain = unref_chain (chain);
|
2002-12-15 12:18:04 +00:00
|
|
|
return chain;
|
2002-09-08 17:58:00 +00:00
|
|
|
}
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
static GstOptSchedulerChain *
|
|
|
|
merge_chains (GstOptSchedulerChain * chain1, GstOptSchedulerChain * chain2)
|
2002-09-08 17:58:00 +00:00
|
|
|
{
|
2002-09-08 22:42:29 +00:00
|
|
|
GSList *walk;
|
2002-12-15 12:18:04 +00:00
|
|
|
|
|
|
|
g_assert (chain1 != NULL);
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2004-02-20 13:18:32 +00:00
|
|
|
GST_LOG ("merging chain %p and %p", chain1, chain2);
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
/* FIXME: document how chain2 can be NULL */
|
2002-12-15 12:18:04 +00:00
|
|
|
if (chain1 == chain2 || chain2 == NULL)
|
|
|
|
return chain1;
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
/* switch if it's more efficient */
|
|
|
|
if (chain1->num_groups < chain2->num_groups) {
|
|
|
|
GstOptSchedulerChain *tmp = chain2;
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
chain2 = chain1;
|
|
|
|
chain1 = tmp;
|
|
|
|
}
|
|
|
|
|
2002-09-08 17:58:00 +00:00
|
|
|
walk = chain2->groups;
|
|
|
|
while (walk) {
|
|
|
|
GstOptSchedulerGroup *group = (GstOptSchedulerGroup *) walk->data;
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2002-12-19 19:45:13 +00:00
|
|
|
walk = g_slist_next (walk);
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_LOG ("reparenting group %p from chain %p to %p", group, chain2, chain1);
|
2003-02-27 23:07:30 +00:00
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
ref_group (group);
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
remove_from_chain (chain2, group);
|
|
|
|
add_to_chain (chain1, group);
|
2003-02-27 18:21:34 +00:00
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
unref_group (group);
|
2002-09-08 17:58:00 +00:00
|
|
|
}
|
2004-03-07 14:33:13 +00:00
|
|
|
|
|
|
|
/* chain2 is now freed, if nothing else was referencing it before */
|
2003-02-27 18:21:34 +00:00
|
|
|
|
2002-12-15 12:18:04 +00:00
|
|
|
return chain1;
|
2002-09-08 17:58:00 +00:00
|
|
|
}
|
|
|
|
|
2004-04-03 13:24:07 +00:00
|
|
|
/* sorts the group list so that terminal sinks come first -- prevents pileup of
|
gst/autoplug/gstspideridentity.c: extra debugging
Original commit message from CVS:
* gst/autoplug/gstspideridentity.c: (gst_spider_identity_chain):
extra debugging
* gst/gstevent.h:
* gst/gstinfo.c: (gst_debug_log_default):
print time nicely. add thread pointer until someone figures out
a completely portable way of getting at thread id's.
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_try),
(_invent_event), (gst_pad_pull), (gst_pad_event_default_dispatch),
(gst_pad_call_chain_function):
extra debugging
* gst/schedulers/gstoptimalscheduler.c:
(get_group_schedule_function), (loop_group_schedule_function),
(gst_opt_scheduler_loop_wrapper), (gst_opt_scheduler_get_wrapper),
(pad_clear_queued), (gst_opt_scheduler_iterate):
rename BUFPEN and friends to DATAPEN since that's what they are.
2004-07-08 13:49:14 +00:00
|
|
|
* datas in datapens */
|
2004-04-03 13:24:07 +00:00
|
|
|
static void
|
|
|
|
sort_chain (GstOptSchedulerChain * chain)
|
|
|
|
{
|
|
|
|
GSList *original = chain->groups;
|
|
|
|
GSList *new = NULL;
|
|
|
|
GSList *walk, *links, *this;
|
|
|
|
|
|
|
|
/* if there's only one group, just return */
|
|
|
|
if (!original->next)
|
|
|
|
return;
|
|
|
|
/* otherwise, we know that all groups are somehow linked together */
|
|
|
|
|
|
|
|
GST_LOG ("sorting chain %p (%d groups)", chain, g_slist_length (original));
|
|
|
|
|
|
|
|
/* first find the terminal sinks */
|
|
|
|
for (walk = original; walk;) {
|
|
|
|
GstOptSchedulerGroup *group = (GstOptSchedulerGroup *) walk->data;
|
|
|
|
|
|
|
|
this = walk;
|
|
|
|
walk = walk->next;
|
|
|
|
if (group->group_links) {
|
|
|
|
gboolean is_sink = TRUE;
|
|
|
|
|
|
|
|
for (links = group->group_links; links; links = links->next)
|
|
|
|
if (((GstOptSchedulerGroupLink *) links->data)->src == group)
|
|
|
|
is_sink = FALSE;
|
|
|
|
if (is_sink) {
|
|
|
|
/* found one */
|
|
|
|
original = g_slist_remove_link (original, this);
|
|
|
|
new = g_slist_concat (new, this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
g_assert (new != NULL);
|
|
|
|
|
|
|
|
/* now look for the elements that are linked to the terminal sinks */
|
|
|
|
for (walk = new; walk; walk = walk->next) {
|
|
|
|
GstOptSchedulerGroup *group = (GstOptSchedulerGroup *) walk->data;
|
|
|
|
|
|
|
|
for (links = group->group_links; links; links = links->next) {
|
|
|
|
this =
|
|
|
|
g_slist_find (original,
|
|
|
|
((GstOptSchedulerGroupLink *) links->data)->src);
|
|
|
|
if (this) {
|
|
|
|
original = g_slist_remove_link (original, this);
|
|
|
|
new = g_slist_concat (new, this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
g_assert (original == NULL);
|
|
|
|
|
|
|
|
chain->groups = new;
|
|
|
|
}
|
|
|
|
|
2002-09-08 17:58:00 +00:00
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
chain_group_set_enabled (GstOptSchedulerChain * chain,
|
|
|
|
GstOptSchedulerGroup * group, gboolean enabled)
|
2002-09-08 17:58:00 +00:00
|
|
|
{
|
2004-05-27 09:33:29 +00:00
|
|
|
gboolean oldstate;
|
|
|
|
|
2004-03-02 23:04:50 +00:00
|
|
|
g_assert (group != NULL);
|
2004-03-07 14:33:13 +00:00
|
|
|
g_assert (chain != NULL);
|
2002-12-15 12:18:04 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
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);
|
2003-01-01 04:28:33 +00:00
|
|
|
|
2004-05-27 09:33:29 +00:00
|
|
|
oldstate = (GST_OPT_SCHEDULER_GROUP_IS_ENABLED (group) ? TRUE : FALSE);
|
|
|
|
if (oldstate == enabled) {
|
|
|
|
GST_LOG ("group %p in chain %p was in correct state", group, chain);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-01-01 04:28:33 +00:00
|
|
|
if (enabled)
|
|
|
|
GST_OPT_SCHEDULER_GROUP_ENABLE (group);
|
2004-03-13 15:27:01 +00:00
|
|
|
else
|
2003-01-01 04:28:33 +00:00
|
|
|
GST_OPT_SCHEDULER_GROUP_DISABLE (group);
|
|
|
|
|
2002-09-08 17:58:00 +00:00
|
|
|
if (enabled) {
|
2004-05-27 09:33:29 +00:00
|
|
|
g_assert (chain->num_enabled < chain->num_groups);
|
|
|
|
|
|
|
|
chain->num_enabled++;
|
2003-01-01 04:28:33 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_DEBUG ("enable group %p in chain %p, now %d groups enabled out of %d",
|
2004-03-15 19:24:35 +00:00
|
|
|
group, chain, chain->num_enabled, chain->num_groups);
|
2003-01-01 04:28:33 +00:00
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
/* 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);
|
|
|
|
|
2002-09-08 17:58:00 +00:00
|
|
|
if (chain->num_enabled == chain->num_groups) {
|
2004-02-20 13:18:32 +00:00
|
|
|
GST_DEBUG ("enable chain %p", chain);
|
2002-09-08 17:58:00 +00:00
|
|
|
GST_OPT_SCHEDULER_CHAIN_ENABLE (chain);
|
|
|
|
}
|
2004-03-13 15:27:01 +00:00
|
|
|
} else {
|
2004-05-27 09:33:29 +00:00
|
|
|
g_assert (chain->num_enabled > 0);
|
2003-01-01 04:28:33 +00:00
|
|
|
|
2004-05-27 09:33:29 +00:00
|
|
|
chain->num_enabled--;
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_DEBUG ("disable group %p in chain %p, now %d groups enabled out of %d",
|
2004-03-15 19:24:35 +00:00
|
|
|
group, chain, chain->num_enabled, chain->num_groups);
|
2003-01-01 04:28:33 +00:00
|
|
|
|
2002-09-08 17:58:00 +00:00
|
|
|
if (chain->num_enabled == 0) {
|
2004-02-20 13:18:32 +00:00
|
|
|
GST_DEBUG ("disable chain %p", chain);
|
2002-09-08 17:58:00 +00:00
|
|
|
GST_OPT_SCHEDULER_CHAIN_DISABLE (chain);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-06-07 11:36:42 +00:00
|
|
|
/* recursively migrate the group and all connected groups into the new chain */
|
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
chain_recursively_migrate_group (GstOptSchedulerChain * chain,
|
|
|
|
GstOptSchedulerGroup * group)
|
2003-06-07 11:36:42 +00:00
|
|
|
{
|
|
|
|
GSList *links;
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2003-06-07 11:36:42 +00:00
|
|
|
/* group already in chain */
|
|
|
|
if (group->chain == chain)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* first remove the group from its old chain */
|
|
|
|
remove_from_chain (group->chain, group);
|
|
|
|
/* add to new chain */
|
|
|
|
add_to_chain (chain, group);
|
|
|
|
|
|
|
|
/* then follow all links */
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
for (links = group->group_links; links; links = g_slist_next (links)) {
|
2003-06-07 11:36:42 +00:00
|
|
|
GstOptSchedulerGroupLink *link = (GstOptSchedulerGroupLink *) links->data;
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2004-04-03 13:24:07 +00:00
|
|
|
chain_recursively_migrate_group (chain, OTHER_GROUP_LINK (link, group));
|
2003-06-07 11:36:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
static GstOptSchedulerGroup *
|
|
|
|
ref_group (GstOptSchedulerGroup * group)
|
2003-02-27 18:21:34 +00:00
|
|
|
{
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_LOG ("ref group %p %d->%d", group, group->refcount, group->refcount + 1);
|
2003-02-27 18:21:34 +00:00
|
|
|
|
|
|
|
group->refcount++;
|
|
|
|
|
|
|
|
return group;
|
|
|
|
}
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
static GstOptSchedulerGroup *
|
|
|
|
unref_group (GstOptSchedulerGroup * group)
|
2003-02-27 23:07:30 +00:00
|
|
|
{
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_LOG ("unref group %p %d->%d", group,
|
|
|
|
group->refcount, group->refcount - 1);
|
2003-02-27 23:07:30 +00:00
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
if (--group->refcount == 0) {
|
|
|
|
destroy_group (group);
|
|
|
|
group = NULL;
|
|
|
|
}
|
2003-02-27 23:07:30 +00:00
|
|
|
|
|
|
|
return group;
|
|
|
|
}
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
static GstOptSchedulerGroup *
|
|
|
|
create_group (GstOptSchedulerChain * chain, GstElement * element,
|
|
|
|
GstOptSchedulerGroupType type)
|
2003-02-27 18:21:34 +00:00
|
|
|
{
|
2004-03-07 14:33:13 +00:00
|
|
|
GstOptSchedulerGroup *group;
|
gst/gstelement.c (gst_element_dispose): Protect against multiple invocations.
Original commit message from CVS:
2004-02-24 Andy Wingo <wingo@pobox.com>
* gst/gstelement.c (gst_element_dispose): Protect against multiple
invocations.
* gst/schedulers/gstoptimalscheduler.c
I added a mess of prototypes at the top of the file by way of
documentation. Some of the operations on chains and groups were
re-organized.
(create_group): Added a type argument so if the group is enabled,
the setup_group_scheduler knows what to do.
(group_elements): Added a type argument here, too, to be passed on
to create_group.
(group_element_set_enabled): 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. Instead
of calling chain_group_set_enabled, just set the flag on the group
(the chain's status will be set when the group is added to it).
(gst_opt_scheduler_state_transition, chain_group_set_enabled):
Setup the group scheduler when the group is enabled, not
specifically when an element goes PAUSED->PLAYING. This means
PLAYING elements can be added, linked, and scheduled into a
PLAYING pipeline, as was intended.
(add_to_group): Don't ref the group twice. I don't know when this
double-ref got in here. Removing it has the potential to cause
segfaults if other parts of the scheduler are buggy. If you find
that the scheduler is segfaulting for you, put in an extra ref
here and see if that hacks over the underlying issue. Of course,
then find out what code is unreffing a group it doesn't own...
(create_group): Make the extra refcount floating, and remove it
after adding the element. This means that...
(unref_group): Destroy when the refcount reaches 0, not 1, like
every other refcounted object in the known universe.
(remove_from_group): When a group becomes empty, set it to be not
active, and remove it from its chain. Don't unref it again,
there's no floating reference any more.
(destroy_group): We have to remove the group from the chain in
remove_from_group (rather than here) to break refcounting cycles
(the chain always has a ref on the group). So assert that
group->chain==NULL.
(ref_group_by_count): Removed, it was commented out anyway.
(merge_chains): Use the remove_from_chain and add_to_chain
primitives to do the reparenting, instead of rolling our own
implementation.
(add_to_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.
(gst_opt_scheduler_schedule_run_queue): Debug fixes.
(get_group_schedule_function): Ditto.
(loop_group_schedule_function): Ditto.
(gst_opt_scheduler_loop_wrapper): Ditto.
(gst_opt_scheduler_iterate): Ditto.
I understand the opt scheduler now, yippee!
* gst/gstpad.c: All throughout, added FIXMEs to look at for 0.9.
(gst_pad_get_name, gst_pad_set_chain_function)
(gst_pad_set_get_function, gst_pad_set_event_function)
(gst_pad_set_event_mask_function, gst_pad_get_event_masks)
(gst_pad_get_event_masks_default, gst_pad_set_convert_function)
(gst_pad_set_query_function, gst_pad_get_query_types)
(gst_pad_get_query_types_default)
(gst_pad_set_internal_link_function)
(gst_pad_set_formats_function, gst_pad_set_link_function)
(gst_pad_set_fixate_function, gst_pad_set_getcaps_function)
(gst_pad_set_bufferalloc_function, gst_pad_unlink)
(gst_pad_renegotiate, gst_pad_set_parent, gst_pad_get_parent)
(gst_pad_add_ghost_pad, gst_pad_proxy_getcaps)
(gst_pad_proxy_pad_link, gst_pad_proxy_fixate)
(gst_pad_get_pad_template_caps, gst_pad_check_compatibility)
(gst_pad_get_peer, gst_pad_get_allowed_caps)
(gst_pad_alloc_buffer, gst_pad_push, gst_pad_pull)
(gst_pad_selectv, gst_pad_select, gst_pad_template_get_caps)
(gst_pad_event_default_dispatch, gst_pad_event_default)
(gst_pad_dispatcher, gst_pad_send_event, gst_pad_convert_default)
(gst_pad_convert, gst_pad_query_default, gst_pad_query)
(gst_pad_get_formats_default, gst_pad_get_formats): Better
argument checks, and some doc fixes.
(gst_pad_custom_new_from_template): Um, does anyone
use these functions? Actually make a custom pad instead of a
normal one.
(gst_pad_try_set_caps): Transpose some checks.
(gst_pad_try_set_caps_nonfixed): Same, and use a macro to check if
the pad is in negotiation.
(gst_pad_try_relink_filtered): Use pad_link_prepare.
* gst/gstelement.c: Remove prototypes also defined in gstclock.h.
* gst/gstelement.h:
* gst/gstclock.h: Un-deprecate the old clocking API, as discussed
on the list.
2004-02-25 13:16:12 +00:00
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
group = g_new0 (GstOptSchedulerGroup, 1);
|
2004-05-18 16:44:44 +00:00
|
|
|
GST_LOG ("new group %p, type %d", group, type);
|
2004-03-15 19:24:35 +00:00
|
|
|
group->refcount = 1; /* float... */
|
2004-03-07 14:33:13 +00:00
|
|
|
group->flags = GST_OPT_SCHEDULER_GROUP_DISABLED;
|
|
|
|
group->type = type;
|
gst/schedulers/gstoptimalscheduler.c: Call group_inc_link with the proper src->sink ordering -- break this, and we br...
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (gst_opt_scheduler_init),
(create_chain), (destroy_chain), (create_group), (destroy_group),
(add_to_group), (merge_groups), (group_elements), (group_inc_link),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_inc_links_for_element), (group_migrate_connected):
Call group_inc_link with the proper src->sink ordering --
break this, and we break sort_chain. patch from wingo for bug
147713.
Partially revert patch 1.89. When adding a loop based element to
the scheduler, the links to other groups are automatically followed
and incremented. This should not happen because the bin will call
pad_link explicitly for those connection, resulting in them counted
twice. Results in assertion failure on pipeline cleanup.
2004-07-16 16:02:12 +00:00
|
|
|
group->sched = chain->sched;
|
|
|
|
group->sched->live_groups++;
|
2003-02-27 18:21:34 +00:00
|
|
|
|
gst/schedulers/gstoptimalscheduler.c: Call group_inc_link with the proper src->sink ordering -- break this, and we br...
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (gst_opt_scheduler_init),
(create_chain), (destroy_chain), (create_group), (destroy_group),
(add_to_group), (merge_groups), (group_elements), (group_inc_link),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_inc_links_for_element), (group_migrate_connected):
Call group_inc_link with the proper src->sink ordering --
break this, and we break sort_chain. patch from wingo for bug
147713.
Partially revert patch 1.89. When adding a loop based element to
the scheduler, the links to other groups are automatically followed
and incremented. This should not happen because the bin will call
pad_link explicitly for those connection, resulting in them counted
twice. Results in assertion failure on pipeline cleanup.
2004-07-16 16:02:12 +00:00
|
|
|
add_to_group (group, element, FALSE);
|
2004-03-07 14:33:13 +00:00
|
|
|
add_to_chain (chain, group);
|
2004-03-15 19:24:35 +00:00
|
|
|
group = unref_group (group); /* ...and sink. */
|
2004-03-07 14:33:13 +00:00
|
|
|
|
gst/schedulers/gstoptimalscheduler.c: Call group_inc_link with the proper src->sink ordering -- break this, and we br...
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (gst_opt_scheduler_init),
(create_chain), (destroy_chain), (create_group), (destroy_group),
(add_to_group), (merge_groups), (group_elements), (group_inc_link),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_inc_links_for_element), (group_migrate_connected):
Call group_inc_link with the proper src->sink ordering --
break this, and we break sort_chain. patch from wingo for bug
147713.
Partially revert patch 1.89. When adding a loop based element to
the scheduler, the links to other groups are automatically followed
and incremented. This should not happen because the bin will call
pad_link explicitly for those connection, resulting in them counted
twice. Results in assertion failure on pipeline cleanup.
2004-07-16 16:02:12 +00:00
|
|
|
GST_LOG ("%d live groups now", group->sched->live_groups);
|
2004-03-07 14:33:13 +00:00
|
|
|
/* group's refcount is now 2 (one for the element, one for the chain) */
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2003-02-27 18:21:34 +00:00
|
|
|
return group;
|
|
|
|
}
|
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
destroy_group (GstOptSchedulerGroup * group)
|
2004-03-07 14:33:13 +00:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
|
gst/schedulers/gstoptimalscheduler.c: Call group_inc_link with the proper src->sink ordering -- break this, and we br...
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (gst_opt_scheduler_init),
(create_chain), (destroy_chain), (create_group), (destroy_group),
(add_to_group), (merge_groups), (group_elements), (group_inc_link),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_inc_links_for_element), (group_migrate_connected):
Call group_inc_link with the proper src->sink ordering --
break this, and we break sort_chain. patch from wingo for bug
147713.
Partially revert patch 1.89. When adding a loop based element to
the scheduler, the links to other groups are automatically followed
and incremented. This should not happen because the bin will call
pad_link explicitly for those connection, resulting in them counted
twice. Results in assertion failure on pipeline cleanup.
2004-07-16 16:02:12 +00:00
|
|
|
group->sched->live_groups--;
|
|
|
|
GST_LOG ("%d live groups now", group->sched->live_groups);
|
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
g_free (group);
|
|
|
|
}
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
static GstOptSchedulerGroup *
|
gst/schedulers/gstoptimalscheduler.c: Call group_inc_link with the proper src->sink ordering -- break this, and we br...
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (gst_opt_scheduler_init),
(create_chain), (destroy_chain), (create_group), (destroy_group),
(add_to_group), (merge_groups), (group_elements), (group_inc_link),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_inc_links_for_element), (group_migrate_connected):
Call group_inc_link with the proper src->sink ordering --
break this, and we break sort_chain. patch from wingo for bug
147713.
Partially revert patch 1.89. When adding a loop based element to
the scheduler, the links to other groups are automatically followed
and incremented. This should not happen because the bin will call
pad_link explicitly for those connection, resulting in them counted
twice. Results in assertion failure on pipeline cleanup.
2004-07-16 16:02:12 +00:00
|
|
|
add_to_group (GstOptSchedulerGroup * group, GstElement * element,
|
|
|
|
gboolean with_links)
|
2002-09-08 17:58:00 +00:00
|
|
|
{
|
2002-12-15 12:18:04 +00:00
|
|
|
g_assert (group != NULL);
|
|
|
|
g_assert (element != NULL);
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_DEBUG ("adding element \"%s\" to group %p", GST_ELEMENT_NAME (element),
|
|
|
|
group);
|
2002-09-08 17:58:00 +00:00
|
|
|
|
|
|
|
if (GST_ELEMENT_IS_DECOUPLED (element)) {
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_DEBUG ("element \"%s\" is decoupled, not adding to group %p",
|
2004-03-15 19:24:35 +00:00
|
|
|
GST_ELEMENT_NAME (element), group);
|
2002-12-15 12:18:04 +00:00
|
|
|
return group;
|
2002-09-08 17:58:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
g_assert (GST_ELEMENT_SCHED_GROUP (element) == NULL);
|
|
|
|
|
2004-05-27 09:33:29 +00:00
|
|
|
/* first increment the links that this group has with other groups through
|
|
|
|
* this element */
|
gst/schedulers/gstoptimalscheduler.c: Call group_inc_link with the proper src->sink ordering -- break this, and we br...
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (gst_opt_scheduler_init),
(create_chain), (destroy_chain), (create_group), (destroy_group),
(add_to_group), (merge_groups), (group_elements), (group_inc_link),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_inc_links_for_element), (group_migrate_connected):
Call group_inc_link with the proper src->sink ordering --
break this, and we break sort_chain. patch from wingo for bug
147713.
Partially revert patch 1.89. When adding a loop based element to
the scheduler, the links to other groups are automatically followed
and incremented. This should not happen because the bin will call
pad_link explicitly for those connection, resulting in them counted
twice. Results in assertion failure on pipeline cleanup.
2004-07-16 16:02:12 +00:00
|
|
|
if (with_links)
|
|
|
|
group_inc_links_for_element (group, element);
|
2004-05-27 09:33:29 +00:00
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
/* Ref the group... */
|
2003-02-27 18:21:34 +00:00
|
|
|
GST_ELEMENT_SCHED_GROUP (element) = ref_group (group);
|
|
|
|
|
|
|
|
gst_object_ref (GST_OBJECT (element));
|
2002-09-08 22:42:29 +00:00
|
|
|
group->elements = g_slist_prepend (group->elements, element);
|
2002-09-08 17:58:00 +00:00
|
|
|
group->num_elements++;
|
|
|
|
|
2003-03-28 17:29:57 +00:00
|
|
|
if (gst_element_get_state (element) == GST_STATE_PLAYING) {
|
|
|
|
group_element_set_enabled (group, element, TRUE);
|
|
|
|
}
|
|
|
|
|
2002-12-15 12:18:04 +00:00
|
|
|
return group;
|
2002-09-08 17:58:00 +00:00
|
|
|
}
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
static GstOptSchedulerGroup *
|
|
|
|
remove_from_group (GstOptSchedulerGroup * group, GstElement * element)
|
2002-09-08 17:58:00 +00:00
|
|
|
{
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_DEBUG ("removing element \"%s\" from group %p",
|
|
|
|
GST_ELEMENT_NAME (element), group);
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2002-12-15 18:21:43 +00:00
|
|
|
g_assert (group != NULL);
|
|
|
|
g_assert (element != NULL);
|
2003-03-13 18:46:21 +00:00
|
|
|
g_assert (GST_ELEMENT_SCHED_GROUP (element) == group);
|
2002-12-15 18:21:43 +00:00
|
|
|
|
2004-05-04 16:43:49 +00:00
|
|
|
/* first decrement the links that this group has with other groups through
|
|
|
|
* this element */
|
|
|
|
group_dec_links_for_element (group, element);
|
|
|
|
|
2004-07-22 09:43:40 +00:00
|
|
|
if (gst_element_get_state (element) == GST_STATE_PLAYING) {
|
|
|
|
group_element_set_enabled (group, element, FALSE);
|
|
|
|
}
|
|
|
|
|
2002-09-08 22:42:29 +00:00
|
|
|
group->elements = g_slist_remove (group->elements, element);
|
2002-09-08 17:58:00 +00:00
|
|
|
group->num_elements--;
|
|
|
|
|
2003-03-13 18:46:21 +00:00
|
|
|
/* if the element was an entry point in the group, clear the group's
|
2004-05-18 17:03:41 +00:00
|
|
|
* entry point, and mark it as unknown */
|
2003-03-13 18:46:21 +00:00
|
|
|
if (group->entry == element) {
|
|
|
|
group->entry = NULL;
|
2004-05-18 17:03:41 +00:00
|
|
|
group->type = GST_OPT_SCHEDULER_GROUP_UNKNOWN;
|
2003-03-13 18:46:21 +00:00
|
|
|
}
|
|
|
|
|
2002-09-08 17:58:00 +00:00
|
|
|
GST_ELEMENT_SCHED_GROUP (element) = NULL;
|
2003-02-27 18:21:34 +00:00
|
|
|
gst_object_unref (GST_OBJECT (element));
|
2002-12-15 12:18:04 +00:00
|
|
|
|
|
|
|
if (group->num_elements == 0) {
|
2004-03-07 14:33:13 +00:00
|
|
|
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);
|
|
|
|
}
|
2002-12-15 12:18:04 +00:00
|
|
|
}
|
2003-02-27 18:21:34 +00:00
|
|
|
group = unref_group (group);
|
|
|
|
|
2002-12-26 22:11:04 +00:00
|
|
|
return group;
|
|
|
|
}
|
|
|
|
|
2004-07-20 09:55:13 +00:00
|
|
|
/* count number of elements in the group. Have to be careful because
|
|
|
|
* decoupled elements are added as entry point but are not added to
|
|
|
|
* the elements list */
|
|
|
|
static gint
|
|
|
|
group_num_elements (GstOptSchedulerGroup * group)
|
|
|
|
{
|
|
|
|
gint num;
|
|
|
|
|
|
|
|
num = group->num_elements;
|
|
|
|
/* decoupled elements are not added to the group but are
|
|
|
|
* added as an entry */
|
|
|
|
if (group->entry) {
|
|
|
|
if (GST_ELEMENT_IS_DECOUPLED (group->entry)) {
|
|
|
|
num++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return num;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check if an element is part of the given group. We have to be carefull
|
|
|
|
* as decoupled elements are added as entry but are not added to the elements
|
|
|
|
* list */
|
|
|
|
static gboolean
|
|
|
|
group_has_element (GstOptSchedulerGroup * group, GstElement * element)
|
|
|
|
{
|
|
|
|
if (group->entry == element)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
return (g_slist_find (group->elements, element) != NULL);
|
|
|
|
}
|
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
/* FIXME need to check if the groups are of the same type -- otherwise need to
|
|
|
|
setup the scheduler again, if it is setup */
|
2004-03-13 15:27:01 +00:00
|
|
|
static GstOptSchedulerGroup *
|
|
|
|
merge_groups (GstOptSchedulerGroup * group1, GstOptSchedulerGroup * group2)
|
2002-12-26 22:11:04 +00:00
|
|
|
{
|
|
|
|
g_assert (group1 != NULL);
|
|
|
|
|
2004-02-20 13:18:32 +00:00
|
|
|
GST_DEBUG ("merging groups %p and %p", group1, group2);
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2002-12-26 22:11:04 +00:00
|
|
|
if (group1 == group2 || group2 == NULL)
|
|
|
|
return group1;
|
|
|
|
|
2004-05-27 09:33:29 +00:00
|
|
|
/* make sure they end up in the same chain */
|
|
|
|
merge_chains (group1->chain, group2->chain);
|
|
|
|
|
2003-03-13 18:46:21 +00:00
|
|
|
while (group2 && group2->elements) {
|
2004-03-13 15:27:01 +00:00
|
|
|
GstElement *element = (GstElement *) group2->elements->data;
|
2003-03-13 18:46:21 +00:00
|
|
|
|
2002-12-26 22:11:04 +00:00
|
|
|
group2 = remove_from_group (group2, element);
|
gst/schedulers/gstoptimalscheduler.c: Call group_inc_link with the proper src->sink ordering -- break this, and we br...
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (gst_opt_scheduler_init),
(create_chain), (destroy_chain), (create_group), (destroy_group),
(add_to_group), (merge_groups), (group_elements), (group_inc_link),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_inc_links_for_element), (group_migrate_connected):
Call group_inc_link with the proper src->sink ordering --
break this, and we break sort_chain. patch from wingo for bug
147713.
Partially revert patch 1.89. When adding a loop based element to
the scheduler, the links to other groups are automatically followed
and incremented. This should not happen because the bin will call
pad_link explicitly for those connection, resulting in them counted
twice. Results in assertion failure on pipeline cleanup.
2004-07-16 16:02:12 +00:00
|
|
|
add_to_group (group1, element, TRUE);
|
2002-12-26 22:11:04 +00:00
|
|
|
}
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2002-12-26 22:11:04 +00:00
|
|
|
return group1;
|
2002-09-08 17:58:00 +00:00
|
|
|
}
|
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
/* setup the scheduler context for a group. The right schedule function
|
|
|
|
* is selected based on the group type and cothreads are created if
|
|
|
|
* needed */
|
2004-03-13 15:27:01 +00:00
|
|
|
static void
|
|
|
|
setup_group_scheduler (GstOptScheduler * osched, GstOptSchedulerGroup * group)
|
2004-03-07 14:33:13 +00:00
|
|
|
{
|
|
|
|
GroupScheduleFunction wrapper;
|
|
|
|
|
2004-05-18 16:44:44 +00:00
|
|
|
GST_DEBUG ("setup group %p scheduler, type %d", group, group->type);
|
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
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;
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
#ifdef USE_COTHREADS
|
|
|
|
if (!(group->flags & GST_OPT_SCHEDULER_GROUP_SCHEDULABLE)) {
|
|
|
|
do_cothread_create (group->cothread, osched->context,
|
2004-03-15 19:24:35 +00:00
|
|
|
(cothread_func) wrapper, 0, (char **) group);
|
2004-03-13 15:27:01 +00:00
|
|
|
} else {
|
2004-03-07 14:33:13 +00:00
|
|
|
do_cothread_setfunc (group->cothread, osched->context,
|
2004-03-15 19:24:35 +00:00
|
|
|
(cothread_func) wrapper, 0, (char **) group);
|
2004-03-07 14:33:13 +00:00
|
|
|
}
|
|
|
|
#else
|
|
|
|
group->schedulefunc = wrapper;
|
|
|
|
group->argc = 0;
|
|
|
|
group->argv = (char **) group;
|
|
|
|
#endif
|
|
|
|
group->flags |= GST_OPT_SCHEDULER_GROUP_SCHEDULABLE;
|
|
|
|
}
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
static void
|
|
|
|
destroy_group_scheduler (GstOptSchedulerGroup * group)
|
2004-03-07 14:33:13 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2002-12-16 21:21:02 +00:00
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
group_error_handler (GstOptSchedulerGroup * group)
|
2002-12-16 21:21:02 +00:00
|
|
|
{
|
2004-02-20 13:18:32 +00:00
|
|
|
GST_DEBUG ("group %p has errored", group);
|
2003-01-20 23:11:51 +00:00
|
|
|
|
2002-12-16 21:21:02 +00:00
|
|
|
chain_group_set_enabled (group->chain, group, FALSE);
|
|
|
|
group->chain->sched->state = GST_OPT_SCHEDULER_STATE_ERROR;
|
|
|
|
}
|
|
|
|
|
2002-09-12 19:22:03 +00:00
|
|
|
/* this function enables/disables an element, it will set/clear a flag on the element
|
|
|
|
* and tells the chain that the group is enabled if all elements inside the group are
|
|
|
|
* enabled */
|
2002-09-08 17:58:00 +00:00
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
group_element_set_enabled (GstOptSchedulerGroup * group, GstElement * element,
|
|
|
|
gboolean enabled)
|
2002-09-08 17:58:00 +00:00
|
|
|
{
|
2002-12-15 18:21:43 +00:00
|
|
|
g_assert (group != NULL);
|
|
|
|
g_assert (element != NULL);
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
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);
|
2003-01-01 04:28:33 +00:00
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
/* 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. */
|
|
|
|
|
2002-09-08 17:58:00 +00:00
|
|
|
if (enabled) {
|
2004-05-27 11:29:18 +00:00
|
|
|
g_assert (group->num_enabled < group->num_elements);
|
|
|
|
|
|
|
|
group->num_enabled++;
|
2003-01-01 04:28:33 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_DEBUG
|
2004-03-15 19:24:35 +00:00
|
|
|
("enable element %s in group %p, now %d elements enabled out of %d",
|
|
|
|
GST_ELEMENT_NAME (element), group, group->num_enabled,
|
|
|
|
group->num_elements);
|
2003-01-01 04:28:33 +00:00
|
|
|
|
2002-09-08 17:58:00 +00:00
|
|
|
if (group->num_enabled == group->num_elements) {
|
2004-03-07 14:33:13 +00:00
|
|
|
if (!group->chain) {
|
2004-03-15 19:24:35 +00:00
|
|
|
GST_DEBUG ("enable chainless group %p", group);
|
|
|
|
GST_OPT_SCHEDULER_GROUP_ENABLE (group);
|
2004-03-07 14:33:13 +00:00
|
|
|
} else {
|
2004-03-15 19:24:35 +00:00
|
|
|
GST_LOG ("enable group %p", group);
|
|
|
|
chain_group_set_enabled (group->chain, group, TRUE);
|
2004-03-07 14:33:13 +00:00
|
|
|
}
|
2002-09-08 17:58:00 +00:00
|
|
|
}
|
2004-03-13 15:27:01 +00:00
|
|
|
} else {
|
2004-05-27 11:29:18 +00:00
|
|
|
g_assert (group->num_enabled > 0);
|
|
|
|
|
|
|
|
group->num_enabled--;
|
2003-01-01 04:28:33 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_DEBUG
|
2004-03-15 19:24:35 +00:00
|
|
|
("disable element %s in group %p, now %d elements enabled out of %d",
|
|
|
|
GST_ELEMENT_NAME (element), group, group->num_enabled,
|
|
|
|
group->num_elements);
|
2003-01-01 04:28:33 +00:00
|
|
|
|
2002-09-08 17:58:00 +00:00
|
|
|
if (group->num_enabled == 0) {
|
2004-03-07 14:33:13 +00:00
|
|
|
if (!group->chain) {
|
2004-03-15 19:24:35 +00:00
|
|
|
GST_DEBUG ("disable chainless group %p", group);
|
|
|
|
GST_OPT_SCHEDULER_GROUP_DISABLE (group);
|
2004-03-07 14:33:13 +00:00
|
|
|
} else {
|
2004-03-15 19:24:35 +00:00
|
|
|
GST_LOG ("disable group %p", group);
|
|
|
|
chain_group_set_enabled (group->chain, group, FALSE);
|
2004-03-07 14:33:13 +00:00
|
|
|
}
|
2002-09-08 17:58:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-09-12 19:22:03 +00:00
|
|
|
/* a group is scheduled by doing a cothread switch to it or
|
|
|
|
* by calling the schedule function. In the non-cothread case
|
|
|
|
* we cannot run already running groups so we return FALSE here
|
|
|
|
* to indicate this to the caller */
|
2004-03-13 15:27:01 +00:00
|
|
|
static gboolean
|
|
|
|
schedule_group (GstOptSchedulerGroup * group)
|
2002-09-08 17:58:00 +00:00
|
|
|
{
|
2003-03-11 23:26:18 +00:00
|
|
|
if (!group->entry) {
|
2004-02-20 13:18:32 +00:00
|
|
|
GST_INFO ("not scheduling group %p without entry", group);
|
gst/schedulers/gstoptimalscheduler.c: move isolated groups to a new chain.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (create_group),
(add_to_group), (merge_groups), (schedule_group),
(gst_opt_scheduler_get_wrapper), (group_elements),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_migrate_connected), (gst_opt_scheduler_pad_unlink),
(gst_opt_scheduler_iterate):
move isolated groups to a new chain.
Emit a warning instead of segfaulting in some error cases.
Fix a bug where the link count between groups was not calculated
correctly. Fixes #144510.
2004-07-14 14:25:04 +00:00
|
|
|
/* FIXME, we return true here, while the group is actually
|
|
|
|
* not schedulable. We might want to disable the element that caused
|
|
|
|
* this group to be scheduled instead */
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
return TRUE;
|
2003-03-11 23:26:18 +00:00
|
|
|
}
|
2002-12-15 18:21:43 +00:00
|
|
|
#ifdef USE_COTHREADS
|
|
|
|
if (group->cothread)
|
|
|
|
do_cothread_switch (group->cothread);
|
2002-12-15 22:02:20 +00:00
|
|
|
else
|
|
|
|
g_warning ("(internal error): trying to schedule group without cothread");
|
2002-12-15 18:21:43 +00:00
|
|
|
return TRUE;
|
|
|
|
#else
|
2003-07-16 15:39:46 +00:00
|
|
|
/* cothreads automatically call the pre- and post-run functions for us;
|
|
|
|
* without cothreads we need to call them manually */
|
2003-03-11 23:26:18 +00:00
|
|
|
if (group->schedulefunc == NULL) {
|
2004-02-20 13:18:32 +00:00
|
|
|
GST_INFO ("not scheduling group %p without schedulefunc", group);
|
2003-03-11 23:26:18 +00:00
|
|
|
return FALSE;
|
2003-07-16 15:39:46 +00:00
|
|
|
} else {
|
2004-07-20 10:57:38 +00:00
|
|
|
GSList *l, *lcopy;
|
2003-07-16 15:39:46 +00:00
|
|
|
|
2004-07-20 10:57:38 +00:00
|
|
|
lcopy = g_slist_copy (group->elements);
|
|
|
|
for (l = lcopy; l; l = l->next) {
|
2004-03-13 15:27:01 +00:00
|
|
|
GstElement *e = (GstElement *) l->data;
|
|
|
|
|
2004-07-20 10:57:38 +00:00
|
|
|
gst_object_ref (GST_OBJECT (e));
|
2003-07-16 15:39:46 +00:00
|
|
|
if (e->pre_run_func)
|
2004-03-15 19:24:35 +00:00
|
|
|
e->pre_run_func (e);
|
2003-07-16 15:39:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
group->schedulefunc (group->argc, group->argv);
|
|
|
|
|
2004-07-20 10:57:38 +00:00
|
|
|
for (l = lcopy; l; l = l->next) {
|
2004-03-13 15:27:01 +00:00
|
|
|
GstElement *e = (GstElement *) l->data;
|
|
|
|
|
2003-07-16 15:39:46 +00:00
|
|
|
if (e->post_run_func)
|
2004-03-15 19:24:35 +00:00
|
|
|
e->post_run_func (e);
|
2004-07-20 10:57:38 +00:00
|
|
|
|
|
|
|
gst_object_unref (GST_OBJECT (e));
|
2003-07-16 15:39:46 +00:00
|
|
|
}
|
2004-07-20 10:57:38 +00:00
|
|
|
g_slist_free (lcopy);
|
2003-07-16 15:39:46 +00:00
|
|
|
|
2003-03-11 23:26:18 +00:00
|
|
|
}
|
2002-12-15 18:21:43 +00:00
|
|
|
return TRUE;
|
|
|
|
#endif
|
2002-09-08 17:58:00 +00:00
|
|
|
}
|
|
|
|
|
2002-12-15 18:21:43 +00:00
|
|
|
#ifndef USE_COTHREADS
|
2002-09-12 19:22:03 +00:00
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
gst_opt_scheduler_schedule_run_queue (GstOptScheduler * osched)
|
2002-09-08 17:58:00 +00:00
|
|
|
{
|
2004-03-07 14:33:13 +00:00
|
|
|
GST_LOG_OBJECT (osched, "running queue: %d groups, recursed %d times",
|
2004-03-13 15:27:01 +00:00
|
|
|
g_list_length (osched->runqueue),
|
|
|
|
osched->recursion, g_list_length (osched->runqueue));
|
2004-03-07 14:33:13 +00:00
|
|
|
|
|
|
|
/* note that we have a ref on each group on the queue (unref after running) */
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2003-01-01 04:28:33 +00:00
|
|
|
/* make sure we don't exceed max_recursion */
|
|
|
|
if (osched->recursion > osched->max_recursion) {
|
|
|
|
osched->state = GST_OPT_SCHEDULER_STATE_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-09-12 19:22:03 +00:00
|
|
|
osched->recursion++;
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2002-09-12 19:22:03 +00:00
|
|
|
while (osched->runqueue) {
|
|
|
|
GstOptSchedulerGroup *group;
|
2003-02-27 23:07:30 +00:00
|
|
|
gboolean res;
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2002-09-12 19:22:03 +00:00
|
|
|
group = (GstOptSchedulerGroup *) osched->runqueue->data;
|
2003-02-27 23:07:30 +00:00
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
/* runqueue holds refcount to group */
|
2002-09-12 19:22:03 +00:00
|
|
|
osched->runqueue = g_list_remove (osched->runqueue, group);
|
2003-10-08 16:06:02 +00:00
|
|
|
|
2003-06-29 14:05:49 +00:00
|
|
|
GST_LOG_OBJECT (osched, "scheduling group %p", group);
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-07-20 10:40:09 +00:00
|
|
|
if (GST_OPT_SCHEDULER_GROUP_IS_ENABLED (group)) {
|
|
|
|
res = schedule_group (group);
|
|
|
|
} else {
|
|
|
|
GST_INFO_OBJECT (osched,
|
|
|
|
"group was disabled while it was on the queue, not scheduling");
|
|
|
|
res = TRUE;
|
|
|
|
}
|
2003-02-27 23:07:30 +00:00
|
|
|
if (!res) {
|
2004-03-13 15:27:01 +00:00
|
|
|
g_warning ("error scheduling group %p", group);
|
2002-12-16 21:21:02 +00:00
|
|
|
group_error_handler (group);
|
2004-03-13 15:27:01 +00:00
|
|
|
} else {
|
2003-06-29 14:05:49 +00:00
|
|
|
GST_LOG_OBJECT (osched, "done scheduling group %p", group);
|
2003-02-27 23:07:30 +00:00
|
|
|
}
|
|
|
|
unref_group (group);
|
2002-09-12 19:22:03 +00:00
|
|
|
}
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_LOG_OBJECT (osched, "run queue length after scheduling %d",
|
|
|
|
g_list_length (osched->runqueue));
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2002-09-12 19:22:03 +00:00
|
|
|
osched->recursion--;
|
|
|
|
}
|
2002-12-15 18:21:43 +00:00
|
|
|
#endif
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2002-09-12 19:22:03 +00:00
|
|
|
/* a chain is scheduled by picking the first active group and scheduling it */
|
2003-02-27 18:21:34 +00:00
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
schedule_chain (GstOptSchedulerChain * chain)
|
2002-09-12 19:22:03 +00:00
|
|
|
{
|
2002-12-15 22:02:20 +00:00
|
|
|
GSList *groups;
|
|
|
|
GstOptScheduler *osched;
|
|
|
|
|
|
|
|
osched = chain->sched;
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-04-03 13:24:07 +00:00
|
|
|
/* if the chain has changed, we need to resort the groups so we enter in the
|
|
|
|
proper place */
|
|
|
|
if (GST_OPT_SCHEDULER_CHAIN_IS_DIRTY (chain))
|
|
|
|
sort_chain (chain);
|
|
|
|
GST_OPT_SCHEDULER_CHAIN_SET_CLEAN (chain);
|
|
|
|
|
|
|
|
groups = chain->groups;
|
2002-09-12 19:22:03 +00:00
|
|
|
while (groups) {
|
|
|
|
GstOptSchedulerGroup *group = (GstOptSchedulerGroup *) groups->data;
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2002-09-12 19:22:03 +00:00
|
|
|
if (!GST_OPT_SCHEDULER_GROUP_IS_DISABLED (group)) {
|
2003-02-27 23:07:30 +00:00
|
|
|
ref_group (group);
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_LOG ("scheduling group %p in chain %p", group, chain);
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2002-12-15 18:21:43 +00:00
|
|
|
#ifdef USE_COTHREADS
|
|
|
|
schedule_group (group);
|
|
|
|
#else
|
|
|
|
osched->recursion = 0;
|
2004-03-13 15:27:01 +00:00
|
|
|
if (!g_list_find (osched->runqueue, group)) {
|
2004-03-15 19:24:35 +00:00
|
|
|
ref_group (group);
|
|
|
|
osched->runqueue = g_list_append (osched->runqueue, group);
|
2003-09-27 14:13:41 +00:00
|
|
|
}
|
2003-02-28 17:50:04 +00:00
|
|
|
gst_opt_scheduler_schedule_run_queue (osched);
|
2002-12-15 18:21:43 +00:00
|
|
|
#endif
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_LOG ("done scheduling group %p in chain %p", group, chain);
|
2003-02-27 18:21:34 +00:00
|
|
|
unref_group (group);
|
2002-09-12 19:22:03 +00:00
|
|
|
break;
|
|
|
|
}
|
2003-02-27 23:07:30 +00:00
|
|
|
|
|
|
|
groups = g_slist_next (groups);
|
2002-09-12 19:22:03 +00:00
|
|
|
}
|
2002-09-08 17:58:00 +00:00
|
|
|
}
|
|
|
|
|
2002-09-12 19:22:03 +00:00
|
|
|
/* a get-based group is scheduled by getting a buffer from the get based
|
|
|
|
* entry point and by pushing the buffer to the peer.
|
|
|
|
* We also set the running flag on this group for as long as this
|
|
|
|
* function is running. */
|
2002-09-08 17:58:00 +00:00
|
|
|
static int
|
2002-09-12 19:22:03 +00:00
|
|
|
get_group_schedule_function (int argc, char *argv[])
|
2002-09-08 17:58:00 +00:00
|
|
|
{
|
|
|
|
GstOptSchedulerGroup *group = (GstOptSchedulerGroup *) argv;
|
2003-07-16 15:39:46 +00:00
|
|
|
GstElement *entry = group->entry;
|
|
|
|
const GList *pads = gst_element_get_pad_list (entry);
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
GST_LOG ("executing get-based group %p", group);
|
2002-09-08 17:58:00 +00:00
|
|
|
|
|
|
|
group->flags |= GST_OPT_SCHEDULER_GROUP_RUNNING;
|
|
|
|
|
2002-09-08 22:42:29 +00:00
|
|
|
while (pads) {
|
2003-10-08 16:06:02 +00:00
|
|
|
GstData *data;
|
2003-12-13 16:58:29 +00:00
|
|
|
GstPad *pad = GST_PAD (pads->data);
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2002-09-08 22:42:29 +00:00
|
|
|
pads = g_list_next (pads);
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2002-09-08 22:42:29 +00:00
|
|
|
/* skip sinks and ghostpads */
|
|
|
|
if (!GST_PAD_IS_SRC (pad) || !GST_IS_REAL_PAD (pad))
|
|
|
|
continue;
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_DEBUG ("doing get and push on pad \"%s:%s\" in group %p",
|
2004-03-15 19:24:35 +00:00
|
|
|
GST_DEBUG_PAD_NAME (pad), group);
|
2002-09-08 17:58:00 +00:00
|
|
|
|
gst/gstpad.c: implement enforcing discont events before buffers are passed. This allows state changes of only some el...
Original commit message from CVS:
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_new),
(gst_pad_link_free), (gst_pad_link_try), (_invent_event),
(gst_pad_pull):
implement enforcing discont events before buffers are passed. This
allows state changes of only some elements and later correctly going
on where they left off (or in short: you can now set audio sinks to
NULL to release the device when the pipeline is paused)
* gst/gstpad.c: (gst_pad_call_chain_function),
(gst_pad_call_get_function):
* gst/gstpad.h:
add gst_pad_call_chain_function and gst_pad_call_get_function for
scheduler interaction. They are required because of the changes
above.
* gst/schedulers/entryscheduler.c: (get_buffer),
(gst_entry_scheduler_chain_wrapper),
(gst_entry_scheduler_get_wrapper),
(gst_entry_scheduler_state_transition),
(gst_entry_scheduler_pad_link):
* gst/schedulers/gstbasicscheduler.c:
(gst_basic_scheduler_chain_wrapper),
(gst_basic_scheduler_src_wrapper),
(gst_basic_scheduler_chainhandler_proxy),
(gst_basic_scheduler_gethandler_proxy),
(gst_basic_scheduler_cothreaded_chain),
(gst_basic_scheduler_chain_elements):
* gst/schedulers/gstoptimalscheduler.c:
(get_group_schedule_function), (pad_clear_queued),
(gst_opt_scheduler_pad_link):
use the new functions instead of calling get/chain-functions
directly.
2004-04-16 01:36:37 +00:00
|
|
|
data = gst_pad_call_get_function (pad);
|
2003-10-08 16:06:02 +00:00
|
|
|
if (data) {
|
|
|
|
if (GST_EVENT_IS_INTERRUPT (data)) {
|
gst/autoplug/gstspideridentity.c: extra debugging
Original commit message from CVS:
* gst/autoplug/gstspideridentity.c: (gst_spider_identity_chain):
extra debugging
* gst/gstevent.h:
* gst/gstinfo.c: (gst_debug_log_default):
print time nicely. add thread pointer until someone figures out
a completely portable way of getting at thread id's.
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_try),
(_invent_event), (gst_pad_pull), (gst_pad_event_default_dispatch),
(gst_pad_call_chain_function):
extra debugging
* gst/schedulers/gstoptimalscheduler.c:
(get_group_schedule_function), (loop_group_schedule_function),
(gst_opt_scheduler_loop_wrapper), (gst_opt_scheduler_get_wrapper),
(pad_clear_queued), (gst_opt_scheduler_iterate):
rename BUFPEN and friends to DATAPEN since that's what they are.
2004-07-08 13:49:14 +00:00
|
|
|
GST_DEBUG ("unreffing interrupt event %p", data);
|
2004-03-15 19:24:35 +00:00
|
|
|
gst_event_unref (GST_EVENT (data));
|
|
|
|
break;
|
2003-01-08 21:33:20 +00:00
|
|
|
}
|
2003-10-08 16:06:02 +00:00
|
|
|
gst_pad_push (pad, data);
|
2003-01-08 21:33:20 +00:00
|
|
|
}
|
2002-09-08 22:42:29 +00:00
|
|
|
}
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2002-09-08 22:42:29 +00:00
|
|
|
group->flags &= ~GST_OPT_SCHEDULER_GROUP_RUNNING;
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2002-09-08 22:42:29 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2002-09-12 19:22:03 +00:00
|
|
|
/* a loop-based group is scheduled by calling the loop function
|
|
|
|
* on the entry point.
|
|
|
|
* We also set the running flag on this group for as long as this
|
|
|
|
* function is running. */
|
2002-09-08 22:42:29 +00:00
|
|
|
static int
|
2002-09-12 19:22:03 +00:00
|
|
|
loop_group_schedule_function (int argc, char *argv[])
|
2002-09-08 22:42:29 +00:00
|
|
|
{
|
|
|
|
GstOptSchedulerGroup *group = (GstOptSchedulerGroup *) argv;
|
|
|
|
GstElement *entry = group->entry;
|
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
GST_LOG ("executing loop-based group %p", group);
|
2002-09-08 22:42:29 +00:00
|
|
|
|
|
|
|
group->flags |= GST_OPT_SCHEDULER_GROUP_RUNNING;
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_DEBUG ("calling loopfunc of element %s in group %p",
|
|
|
|
GST_ELEMENT_NAME (entry), group);
|
2002-09-08 22:42:29 +00:00
|
|
|
|
2004-05-18 16:44:44 +00:00
|
|
|
if (entry->loopfunc)
|
|
|
|
entry->loopfunc (entry);
|
|
|
|
else
|
|
|
|
group_error_handler (group);
|
2002-09-08 17:58:00 +00:00
|
|
|
|
gst/autoplug/gstspideridentity.c: extra debugging
Original commit message from CVS:
* gst/autoplug/gstspideridentity.c: (gst_spider_identity_chain):
extra debugging
* gst/gstevent.h:
* gst/gstinfo.c: (gst_debug_log_default):
print time nicely. add thread pointer until someone figures out
a completely portable way of getting at thread id's.
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_try),
(_invent_event), (gst_pad_pull), (gst_pad_event_default_dispatch),
(gst_pad_call_chain_function):
extra debugging
* gst/schedulers/gstoptimalscheduler.c:
(get_group_schedule_function), (loop_group_schedule_function),
(gst_opt_scheduler_loop_wrapper), (gst_opt_scheduler_get_wrapper),
(pad_clear_queued), (gst_opt_scheduler_iterate):
rename BUFPEN and friends to DATAPEN since that's what they are.
2004-07-08 13:49:14 +00:00
|
|
|
GST_LOG ("returned from loopfunc of element %s in group %p",
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_ELEMENT_NAME (entry), group);
|
2003-02-28 17:50:04 +00:00
|
|
|
|
2002-09-08 17:58:00 +00:00
|
|
|
group->flags &= ~GST_OPT_SCHEDULER_GROUP_RUNNING;
|
|
|
|
|
2002-09-08 22:42:29 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2003-07-16 15:39:46 +00:00
|
|
|
/* the function to schedule an unknown group, which just gives an error */
|
2002-09-08 22:42:29 +00:00
|
|
|
static int
|
2003-07-16 15:39:46 +00:00
|
|
|
unknown_group_schedule_function (int argc, char *argv[])
|
2002-09-08 22:42:29 +00:00
|
|
|
{
|
|
|
|
GstOptSchedulerGroup *group = (GstOptSchedulerGroup *) argv;
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
g_warning ("(internal error) unknown group type %d, disabling\n",
|
|
|
|
group->type);
|
2002-12-16 21:21:02 +00:00
|
|
|
group_error_handler (group);
|
2002-09-08 22:42:29 +00:00
|
|
|
|
2002-09-08 17:58:00 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-09-12 19:22:03 +00:00
|
|
|
/* this function is called when the first element of a chain-loop or a loop-loop
|
2003-01-09 14:15:37 +00:00
|
|
|
* link performs a push to the loop element. We then schedule the
|
gst/autoplug/gstspideridentity.c: extra debugging
Original commit message from CVS:
* gst/autoplug/gstspideridentity.c: (gst_spider_identity_chain):
extra debugging
* gst/gstevent.h:
* gst/gstinfo.c: (gst_debug_log_default):
print time nicely. add thread pointer until someone figures out
a completely portable way of getting at thread id's.
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_try),
(_invent_event), (gst_pad_pull), (gst_pad_event_default_dispatch),
(gst_pad_call_chain_function):
extra debugging
* gst/schedulers/gstoptimalscheduler.c:
(get_group_schedule_function), (loop_group_schedule_function),
(gst_opt_scheduler_loop_wrapper), (gst_opt_scheduler_get_wrapper),
(pad_clear_queued), (gst_opt_scheduler_iterate):
rename BUFPEN and friends to DATAPEN since that's what they are.
2004-07-08 13:49:14 +00:00
|
|
|
* group with the loop-based element until the datapen is empty */
|
2002-09-08 17:58:00 +00:00
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
gst_opt_scheduler_loop_wrapper (GstPad * sinkpad, GstData * data)
|
2002-09-08 17:58:00 +00:00
|
|
|
{
|
|
|
|
GstOptSchedulerGroup *group;
|
2002-09-12 19:22:03 +00:00
|
|
|
GstOptScheduler *osched;
|
2004-03-07 14:33:13 +00:00
|
|
|
GstRealPad *peer;
|
2002-09-08 17:58:00 +00:00
|
|
|
|
|
|
|
group = GST_ELEMENT_SCHED_GROUP (GST_PAD_PARENT (sinkpad));
|
2002-09-12 19:22:03 +00:00
|
|
|
osched = group->chain->sched;
|
2004-03-07 14:33:13 +00:00
|
|
|
peer = GST_RPAD_PEER (sinkpad);
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
GST_LOG ("chain handler for loop-based pad %" GST_PTR_FORMAT, sinkpad);
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2002-12-15 18:21:43 +00:00
|
|
|
#ifdef USE_COTHREADS
|
gst/autoplug/gstspideridentity.c: extra debugging
Original commit message from CVS:
* gst/autoplug/gstspideridentity.c: (gst_spider_identity_chain):
extra debugging
* gst/gstevent.h:
* gst/gstinfo.c: (gst_debug_log_default):
print time nicely. add thread pointer until someone figures out
a completely portable way of getting at thread id's.
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_try),
(_invent_event), (gst_pad_pull), (gst_pad_event_default_dispatch),
(gst_pad_call_chain_function):
extra debugging
* gst/schedulers/gstoptimalscheduler.c:
(get_group_schedule_function), (loop_group_schedule_function),
(gst_opt_scheduler_loop_wrapper), (gst_opt_scheduler_get_wrapper),
(pad_clear_queued), (gst_opt_scheduler_iterate):
rename BUFPEN and friends to DATAPEN since that's what they are.
2004-07-08 13:49:14 +00:00
|
|
|
if (GST_PAD_DATALIST (peer)) {
|
2002-12-15 18:21:43 +00:00
|
|
|
g_warning ("deadlock detected, disabling group %p", group);
|
2002-12-16 21:21:02 +00:00
|
|
|
group_error_handler (group);
|
2004-03-13 15:27:01 +00:00
|
|
|
} else {
|
gst/autoplug/gstspideridentity.c: extra debugging
Original commit message from CVS:
* gst/autoplug/gstspideridentity.c: (gst_spider_identity_chain):
extra debugging
* gst/gstevent.h:
* gst/gstinfo.c: (gst_debug_log_default):
print time nicely. add thread pointer until someone figures out
a completely portable way of getting at thread id's.
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_try),
(_invent_event), (gst_pad_pull), (gst_pad_event_default_dispatch),
(gst_pad_call_chain_function):
extra debugging
* gst/schedulers/gstoptimalscheduler.c:
(get_group_schedule_function), (loop_group_schedule_function),
(gst_opt_scheduler_loop_wrapper), (gst_opt_scheduler_get_wrapper),
(pad_clear_queued), (gst_opt_scheduler_iterate):
rename BUFPEN and friends to DATAPEN since that's what they are.
2004-07-08 13:49:14 +00:00
|
|
|
GST_LOG ("queueing data %p on %s:%s's datapen", data,
|
2004-03-15 19:24:35 +00:00
|
|
|
GST_DEBUG_PAD_NAME (peer));
|
gst/autoplug/gstspideridentity.c: extra debugging
Original commit message from CVS:
* gst/autoplug/gstspideridentity.c: (gst_spider_identity_chain):
extra debugging
* gst/gstevent.h:
* gst/gstinfo.c: (gst_debug_log_default):
print time nicely. add thread pointer until someone figures out
a completely portable way of getting at thread id's.
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_try),
(_invent_event), (gst_pad_pull), (gst_pad_event_default_dispatch),
(gst_pad_call_chain_function):
extra debugging
* gst/schedulers/gstoptimalscheduler.c:
(get_group_schedule_function), (loop_group_schedule_function),
(gst_opt_scheduler_loop_wrapper), (gst_opt_scheduler_get_wrapper),
(pad_clear_queued), (gst_opt_scheduler_iterate):
rename BUFPEN and friends to DATAPEN since that's what they are.
2004-07-08 13:49:14 +00:00
|
|
|
GST_PAD_DATAPEN (peer) = g_list_append (GST_PAD_DATALIST (peer), data);
|
2002-12-15 18:21:43 +00:00
|
|
|
schedule_group (group);
|
2002-09-12 19:22:03 +00:00
|
|
|
}
|
2002-12-15 18:21:43 +00:00
|
|
|
#else
|
gst/autoplug/gstspideridentity.c: extra debugging
Original commit message from CVS:
* gst/autoplug/gstspideridentity.c: (gst_spider_identity_chain):
extra debugging
* gst/gstevent.h:
* gst/gstinfo.c: (gst_debug_log_default):
print time nicely. add thread pointer until someone figures out
a completely portable way of getting at thread id's.
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_try),
(_invent_event), (gst_pad_pull), (gst_pad_event_default_dispatch),
(gst_pad_call_chain_function):
extra debugging
* gst/schedulers/gstoptimalscheduler.c:
(get_group_schedule_function), (loop_group_schedule_function),
(gst_opt_scheduler_loop_wrapper), (gst_opt_scheduler_get_wrapper),
(pad_clear_queued), (gst_opt_scheduler_iterate):
rename BUFPEN and friends to DATAPEN since that's what they are.
2004-07-08 13:49:14 +00:00
|
|
|
GST_LOG ("queueing data %p on %s:%s's datapen", data,
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_DEBUG_PAD_NAME (peer));
|
gst/autoplug/gstspideridentity.c: extra debugging
Original commit message from CVS:
* gst/autoplug/gstspideridentity.c: (gst_spider_identity_chain):
extra debugging
* gst/gstevent.h:
* gst/gstinfo.c: (gst_debug_log_default):
print time nicely. add thread pointer until someone figures out
a completely portable way of getting at thread id's.
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_try),
(_invent_event), (gst_pad_pull), (gst_pad_event_default_dispatch),
(gst_pad_call_chain_function):
extra debugging
* gst/schedulers/gstoptimalscheduler.c:
(get_group_schedule_function), (loop_group_schedule_function),
(gst_opt_scheduler_loop_wrapper), (gst_opt_scheduler_get_wrapper),
(pad_clear_queued), (gst_opt_scheduler_iterate):
rename BUFPEN and friends to DATAPEN since that's what they are.
2004-07-08 13:49:14 +00:00
|
|
|
GST_PAD_DATAPEN (peer) = g_list_append (GST_PAD_DATALIST (peer), data);
|
2002-12-15 18:21:43 +00:00
|
|
|
if (!(group->flags & GST_OPT_SCHEDULER_GROUP_RUNNING)) {
|
2004-03-07 14:33:13 +00:00
|
|
|
GST_LOG ("adding group %p to runqueue", group);
|
2004-03-13 15:27:01 +00:00
|
|
|
if (!g_list_find (osched->runqueue, group)) {
|
2003-09-27 14:13:41 +00:00
|
|
|
ref_group (group);
|
|
|
|
osched->runqueue = g_list_append (osched->runqueue, group);
|
2003-10-08 16:06:02 +00:00
|
|
|
}
|
2002-12-15 18:21:43 +00:00
|
|
|
}
|
|
|
|
#endif
|
2004-03-13 15:27:01 +00:00
|
|
|
|
gst/autoplug/gstspideridentity.c: extra debugging
Original commit message from CVS:
* gst/autoplug/gstspideridentity.c: (gst_spider_identity_chain):
extra debugging
* gst/gstevent.h:
* gst/gstinfo.c: (gst_debug_log_default):
print time nicely. add thread pointer until someone figures out
a completely portable way of getting at thread id's.
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_try),
(_invent_event), (gst_pad_pull), (gst_pad_event_default_dispatch),
(gst_pad_call_chain_function):
extra debugging
* gst/schedulers/gstoptimalscheduler.c:
(get_group_schedule_function), (loop_group_schedule_function),
(gst_opt_scheduler_loop_wrapper), (gst_opt_scheduler_get_wrapper),
(pad_clear_queued), (gst_opt_scheduler_iterate):
rename BUFPEN and friends to DATAPEN since that's what they are.
2004-07-08 13:49:14 +00:00
|
|
|
GST_LOG ("%d datas left on %s:%s's datapen after chain handler",
|
|
|
|
g_list_length (GST_PAD_DATALIST (peer)), GST_DEBUG_PAD_NAME (peer));
|
2002-09-08 17:58:00 +00:00
|
|
|
}
|
|
|
|
|
2002-09-12 19:22:03 +00:00
|
|
|
/* this function is called by a loop based element that performs a
|
gst/autoplug/gstspideridentity.c: extra debugging
Original commit message from CVS:
* gst/autoplug/gstspideridentity.c: (gst_spider_identity_chain):
extra debugging
* gst/gstevent.h:
* gst/gstinfo.c: (gst_debug_log_default):
print time nicely. add thread pointer until someone figures out
a completely portable way of getting at thread id's.
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_try),
(_invent_event), (gst_pad_pull), (gst_pad_event_default_dispatch),
(gst_pad_call_chain_function):
extra debugging
* gst/schedulers/gstoptimalscheduler.c:
(get_group_schedule_function), (loop_group_schedule_function),
(gst_opt_scheduler_loop_wrapper), (gst_opt_scheduler_get_wrapper),
(pad_clear_queued), (gst_opt_scheduler_iterate):
rename BUFPEN and friends to DATAPEN since that's what they are.
2004-07-08 13:49:14 +00:00
|
|
|
* pull on a sinkpad. We schedule the peer group until the datapen
|
|
|
|
* is filled with the data so that this function can return */
|
2004-03-13 15:27:01 +00:00
|
|
|
static GstData *
|
|
|
|
gst_opt_scheduler_get_wrapper (GstPad * srcpad)
|
2002-09-08 17:58:00 +00:00
|
|
|
{
|
2003-10-08 16:06:02 +00:00
|
|
|
GstData *data;
|
|
|
|
GstOptSchedulerGroup *group;
|
2003-02-28 23:14:50 +00:00
|
|
|
GstOptScheduler *osched;
|
|
|
|
gboolean disabled;
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
GST_LOG ("get handler for %" GST_PTR_FORMAT, srcpad);
|
2002-09-08 17:58:00 +00:00
|
|
|
|
gst/autoplug/gstspideridentity.c: extra debugging
Original commit message from CVS:
* gst/autoplug/gstspideridentity.c: (gst_spider_identity_chain):
extra debugging
* gst/gstevent.h:
* gst/gstinfo.c: (gst_debug_log_default):
print time nicely. add thread pointer until someone figures out
a completely portable way of getting at thread id's.
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_try),
(_invent_event), (gst_pad_pull), (gst_pad_event_default_dispatch),
(gst_pad_call_chain_function):
extra debugging
* gst/schedulers/gstoptimalscheduler.c:
(get_group_schedule_function), (loop_group_schedule_function),
(gst_opt_scheduler_loop_wrapper), (gst_opt_scheduler_get_wrapper),
(pad_clear_queued), (gst_opt_scheduler_iterate):
rename BUFPEN and friends to DATAPEN since that's what they are.
2004-07-08 13:49:14 +00:00
|
|
|
/* first try to grab a queued data */
|
|
|
|
if (GST_PAD_DATALIST (srcpad)) {
|
|
|
|
data = GST_PAD_DATALIST (srcpad)->data;
|
|
|
|
GST_PAD_DATAPEN (srcpad) = g_list_remove (GST_PAD_DATALIST (srcpad), data);
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
GST_LOG ("returning popped queued data %p", data);
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2003-10-08 16:06:02 +00:00
|
|
|
return data;
|
2003-02-28 23:14:50 +00:00
|
|
|
}
|
gst/schedulers/gstoptimalscheduler.c: move isolated groups to a new chain.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (create_group),
(add_to_group), (merge_groups), (schedule_group),
(gst_opt_scheduler_get_wrapper), (group_elements),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_migrate_connected), (gst_opt_scheduler_pad_unlink),
(gst_opt_scheduler_iterate):
move isolated groups to a new chain.
Emit a warning instead of segfaulting in some error cases.
Fix a bug where the link count between groups was not calculated
correctly. Fixes #144510.
2004-07-14 14:25:04 +00:00
|
|
|
GST_LOG ("need to schedule the peer element");
|
2003-02-28 23:14:50 +00:00
|
|
|
|
|
|
|
/* else we need to schedule the peer element */
|
2004-07-20 10:40:09 +00:00
|
|
|
get_group (GST_PAD_PARENT (srcpad), &group);
|
gst/schedulers/gstoptimalscheduler.c: move isolated groups to a new chain.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (create_group),
(add_to_group), (merge_groups), (schedule_group),
(gst_opt_scheduler_get_wrapper), (group_elements),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_migrate_connected), (gst_opt_scheduler_pad_unlink),
(gst_opt_scheduler_iterate):
move isolated groups to a new chain.
Emit a warning instead of segfaulting in some error cases.
Fix a bug where the link count between groups was not calculated
correctly. Fixes #144510.
2004-07-14 14:25:04 +00:00
|
|
|
if (group == NULL) {
|
|
|
|
/* wow, peer has no group */
|
2004-07-20 10:40:09 +00:00
|
|
|
GST_LOG ("peer without group detected");
|
gst/schedulers/gstoptimalscheduler.c: move isolated groups to a new chain.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (create_group),
(add_to_group), (merge_groups), (schedule_group),
(gst_opt_scheduler_get_wrapper), (group_elements),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_migrate_connected), (gst_opt_scheduler_pad_unlink),
(gst_opt_scheduler_iterate):
move isolated groups to a new chain.
Emit a warning instead of segfaulting in some error cases.
Fix a bug where the link count between groups was not calculated
correctly. Fixes #144510.
2004-07-14 14:25:04 +00:00
|
|
|
//group_error_handler (group);
|
|
|
|
return GST_DATA (gst_event_new (GST_EVENT_INTERRUPT));
|
|
|
|
}
|
2003-02-28 23:14:50 +00:00
|
|
|
osched = group->chain->sched;
|
2003-10-08 16:06:02 +00:00
|
|
|
data = NULL;
|
2003-02-28 23:14:50 +00:00
|
|
|
disabled = FALSE;
|
|
|
|
|
|
|
|
do {
|
gst/autoplug/gstspideridentity.c: extra debugging
Original commit message from CVS:
* gst/autoplug/gstspideridentity.c: (gst_spider_identity_chain):
extra debugging
* gst/gstevent.h:
* gst/gstinfo.c: (gst_debug_log_default):
print time nicely. add thread pointer until someone figures out
a completely portable way of getting at thread id's.
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_try),
(_invent_event), (gst_pad_pull), (gst_pad_event_default_dispatch),
(gst_pad_call_chain_function):
extra debugging
* gst/schedulers/gstoptimalscheduler.c:
(get_group_schedule_function), (loop_group_schedule_function),
(gst_opt_scheduler_loop_wrapper), (gst_opt_scheduler_get_wrapper),
(pad_clear_queued), (gst_opt_scheduler_iterate):
rename BUFPEN and friends to DATAPEN since that's what they are.
2004-07-08 13:49:14 +00:00
|
|
|
GST_LOG ("scheduling upstream group %p to fill datapen", group);
|
2002-12-15 18:21:43 +00:00
|
|
|
#ifdef USE_COTHREADS
|
|
|
|
schedule_group (group);
|
|
|
|
#else
|
|
|
|
if (!(group->flags & GST_OPT_SCHEDULER_GROUP_RUNNING)) {
|
2003-10-08 16:06:02 +00:00
|
|
|
ref_group (group);
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
if (!g_list_find (osched->runqueue, group)) {
|
2004-03-15 19:24:35 +00:00
|
|
|
ref_group (group);
|
|
|
|
osched->runqueue = g_list_append (osched->runqueue, group);
|
2003-10-08 16:06:02 +00:00
|
|
|
}
|
2003-02-28 23:14:50 +00:00
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
GST_LOG ("recursing into scheduler group %p", group);
|
2002-09-12 19:22:03 +00:00
|
|
|
gst_opt_scheduler_schedule_run_queue (osched);
|
2004-03-07 14:33:13 +00:00
|
|
|
GST_LOG ("return from recurse group %p", group);
|
2003-02-28 23:14:50 +00:00
|
|
|
|
|
|
|
/* if the other group was disabled we might have to break out of the loop */
|
|
|
|
disabled = GST_OPT_SCHEDULER_GROUP_IS_DISABLED (group);
|
2003-02-27 18:21:34 +00:00
|
|
|
group = unref_group (group);
|
|
|
|
/* group is gone */
|
|
|
|
if (group == NULL) {
|
2004-03-15 19:24:35 +00:00
|
|
|
/* if the group was gone we also might have to break out of the loop */
|
|
|
|
disabled = TRUE;
|
2003-02-27 18:21:34 +00:00
|
|
|
}
|
2004-03-13 15:27:01 +00:00
|
|
|
} else {
|
2003-10-08 16:06:02 +00:00
|
|
|
/* in this case, the group was running and we wanted to swtich to it,
|
2003-02-28 23:14:50 +00:00
|
|
|
* this is not allowed in the optimal scheduler (yet) */
|
2002-09-08 22:42:29 +00:00
|
|
|
g_warning ("deadlock detected, disabling group %p", group);
|
2002-12-16 21:21:02 +00:00
|
|
|
group_error_handler (group);
|
2003-10-08 16:06:02 +00:00
|
|
|
return GST_DATA (gst_event_new (GST_EVENT_INTERRUPT));
|
2002-09-08 22:42:29 +00:00
|
|
|
}
|
2002-12-15 18:21:43 +00:00
|
|
|
#endif
|
gst/autoplug/gstspideridentity.c: extra debugging
Original commit message from CVS:
* gst/autoplug/gstspideridentity.c: (gst_spider_identity_chain):
extra debugging
* gst/gstevent.h:
* gst/gstinfo.c: (gst_debug_log_default):
print time nicely. add thread pointer until someone figures out
a completely portable way of getting at thread id's.
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_try),
(_invent_event), (gst_pad_pull), (gst_pad_event_default_dispatch),
(gst_pad_call_chain_function):
extra debugging
* gst/schedulers/gstoptimalscheduler.c:
(get_group_schedule_function), (loop_group_schedule_function),
(gst_opt_scheduler_loop_wrapper), (gst_opt_scheduler_get_wrapper),
(pad_clear_queued), (gst_opt_scheduler_iterate):
rename BUFPEN and friends to DATAPEN since that's what they are.
2004-07-08 13:49:14 +00:00
|
|
|
/* if the scheduler interrupted, make sure we send an INTERRUPTED event
|
|
|
|
* to the loop based element */
|
2003-01-08 21:33:20 +00:00
|
|
|
if (osched->state == GST_OPT_SCHEDULER_STATE_INTERRUPTED) {
|
2004-02-20 13:18:32 +00:00
|
|
|
GST_INFO ("scheduler interrupted, return interrupt event");
|
2003-10-08 16:06:02 +00:00
|
|
|
data = GST_DATA (gst_event_new (GST_EVENT_INTERRUPT));
|
2004-03-13 15:27:01 +00:00
|
|
|
} else {
|
gst/autoplug/gstspideridentity.c: extra debugging
Original commit message from CVS:
* gst/autoplug/gstspideridentity.c: (gst_spider_identity_chain):
extra debugging
* gst/gstevent.h:
* gst/gstinfo.c: (gst_debug_log_default):
print time nicely. add thread pointer until someone figures out
a completely portable way of getting at thread id's.
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_try),
(_invent_event), (gst_pad_pull), (gst_pad_event_default_dispatch),
(gst_pad_call_chain_function):
extra debugging
* gst/schedulers/gstoptimalscheduler.c:
(get_group_schedule_function), (loop_group_schedule_function),
(gst_opt_scheduler_loop_wrapper), (gst_opt_scheduler_get_wrapper),
(pad_clear_queued), (gst_opt_scheduler_iterate):
rename BUFPEN and friends to DATAPEN since that's what they are.
2004-07-08 13:49:14 +00:00
|
|
|
if (GST_PAD_DATALIST (srcpad)) {
|
|
|
|
data = GST_PAD_DATALIST (srcpad)->data;
|
|
|
|
GST_PAD_DATAPEN (srcpad) =
|
|
|
|
g_list_remove (GST_PAD_DATALIST (srcpad), data);
|
2004-03-13 15:27:01 +00:00
|
|
|
} else if (disabled) {
|
gst/autoplug/gstspideridentity.c: extra debugging
Original commit message from CVS:
* gst/autoplug/gstspideridentity.c: (gst_spider_identity_chain):
extra debugging
* gst/gstevent.h:
* gst/gstinfo.c: (gst_debug_log_default):
print time nicely. add thread pointer until someone figures out
a completely portable way of getting at thread id's.
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_try),
(_invent_event), (gst_pad_pull), (gst_pad_event_default_dispatch),
(gst_pad_call_chain_function):
extra debugging
* gst/schedulers/gstoptimalscheduler.c:
(get_group_schedule_function), (loop_group_schedule_function),
(gst_opt_scheduler_loop_wrapper), (gst_opt_scheduler_get_wrapper),
(pad_clear_queued), (gst_opt_scheduler_iterate):
rename BUFPEN and friends to DATAPEN since that's what they are.
2004-07-08 13:49:14 +00:00
|
|
|
/* no data in queue and peer group was disabled */
|
2004-03-15 19:24:35 +00:00
|
|
|
data = GST_DATA (gst_event_new (GST_EVENT_INTERRUPT));
|
2003-02-28 23:14:50 +00:00
|
|
|
}
|
2002-09-12 19:22:03 +00:00
|
|
|
}
|
2002-09-08 17:58:00 +00:00
|
|
|
}
|
2003-10-08 16:06:02 +00:00
|
|
|
while (data == NULL);
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
GST_LOG ("get handler, returning data %p, queue length %d",
|
gst/autoplug/gstspideridentity.c: extra debugging
Original commit message from CVS:
* gst/autoplug/gstspideridentity.c: (gst_spider_identity_chain):
extra debugging
* gst/gstevent.h:
* gst/gstinfo.c: (gst_debug_log_default):
print time nicely. add thread pointer until someone figures out
a completely portable way of getting at thread id's.
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_try),
(_invent_event), (gst_pad_pull), (gst_pad_event_default_dispatch),
(gst_pad_call_chain_function):
extra debugging
* gst/schedulers/gstoptimalscheduler.c:
(get_group_schedule_function), (loop_group_schedule_function),
(gst_opt_scheduler_loop_wrapper), (gst_opt_scheduler_get_wrapper),
(pad_clear_queued), (gst_opt_scheduler_iterate):
rename BUFPEN and friends to DATAPEN since that's what they are.
2004-07-08 13:49:14 +00:00
|
|
|
data, g_list_length (GST_PAD_DATALIST (srcpad)));
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2003-10-08 16:06:02 +00:00
|
|
|
return data;
|
2002-09-08 17:58:00 +00:00
|
|
|
}
|
|
|
|
|
2003-02-06 20:22:34 +00:00
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
pad_clear_queued (GstPad * srcpad, gpointer user_data)
|
2003-02-06 20:22:34 +00:00
|
|
|
{
|
gst/autoplug/gstspideridentity.c: extra debugging
Original commit message from CVS:
* gst/autoplug/gstspideridentity.c: (gst_spider_identity_chain):
extra debugging
* gst/gstevent.h:
* gst/gstinfo.c: (gst_debug_log_default):
print time nicely. add thread pointer until someone figures out
a completely portable way of getting at thread id's.
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_try),
(_invent_event), (gst_pad_pull), (gst_pad_event_default_dispatch),
(gst_pad_call_chain_function):
extra debugging
* gst/schedulers/gstoptimalscheduler.c:
(get_group_schedule_function), (loop_group_schedule_function),
(gst_opt_scheduler_loop_wrapper), (gst_opt_scheduler_get_wrapper),
(pad_clear_queued), (gst_opt_scheduler_iterate):
rename BUFPEN and friends to DATAPEN since that's what they are.
2004-07-08 13:49:14 +00:00
|
|
|
GList *datalist = GST_PAD_DATALIST (srcpad);
|
2003-02-06 20:22:34 +00:00
|
|
|
|
gst/autoplug/gstspideridentity.c: extra debugging
Original commit message from CVS:
* gst/autoplug/gstspideridentity.c: (gst_spider_identity_chain):
extra debugging
* gst/gstevent.h:
* gst/gstinfo.c: (gst_debug_log_default):
print time nicely. add thread pointer until someone figures out
a completely portable way of getting at thread id's.
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_try),
(_invent_event), (gst_pad_pull), (gst_pad_event_default_dispatch),
(gst_pad_call_chain_function):
extra debugging
* gst/schedulers/gstoptimalscheduler.c:
(get_group_schedule_function), (loop_group_schedule_function),
(gst_opt_scheduler_loop_wrapper), (gst_opt_scheduler_get_wrapper),
(pad_clear_queued), (gst_opt_scheduler_iterate):
rename BUFPEN and friends to DATAPEN since that's what they are.
2004-07-08 13:49:14 +00:00
|
|
|
if (datalist) {
|
|
|
|
GST_LOG ("need to clear some datas");
|
|
|
|
g_list_foreach (datalist, (GFunc) gst_data_unref, NULL);
|
|
|
|
g_list_free (datalist);
|
|
|
|
GST_PAD_DATAPEN (srcpad) = NULL;
|
2003-02-06 20:22:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-02-03 22:50:55 +00:00
|
|
|
static gboolean
|
2004-03-13 15:27:01 +00:00
|
|
|
gst_opt_scheduler_event_wrapper (GstPad * srcpad, GstEvent * event)
|
2003-02-03 22:50:55 +00:00
|
|
|
{
|
|
|
|
gboolean flush;
|
|
|
|
|
2004-07-07 16:50:30 +00:00
|
|
|
GST_DEBUG ("intercepting event type %d on pad %s:%s",
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_EVENT_TYPE (event), GST_DEBUG_PAD_NAME (srcpad));
|
|
|
|
|
2003-02-03 22:50:55 +00:00
|
|
|
/* figure out if this is a flush event */
|
|
|
|
switch (GST_EVENT_TYPE (event)) {
|
|
|
|
case GST_EVENT_FLUSH:
|
|
|
|
flush = TRUE;
|
|
|
|
break;
|
|
|
|
case GST_EVENT_SEEK:
|
|
|
|
case GST_EVENT_SEEK_SEGMENT:
|
|
|
|
flush = GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
flush = FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flush) {
|
2004-07-07 16:50:30 +00:00
|
|
|
GST_LOG ("event triggers a flush");
|
2003-02-05 17:09:50 +00:00
|
|
|
|
2003-02-06 20:22:34 +00:00
|
|
|
pad_clear_queued (srcpad, NULL);
|
2003-02-03 22:50:55 +00:00
|
|
|
}
|
|
|
|
return GST_RPAD_EVENTFUNC (srcpad) (srcpad, event);
|
|
|
|
}
|
|
|
|
|
2002-09-08 17:58:00 +00:00
|
|
|
static GstElementStateReturn
|
2004-03-13 15:27:01 +00:00
|
|
|
gst_opt_scheduler_state_transition (GstScheduler * sched, GstElement * element,
|
|
|
|
gint transition)
|
2002-09-08 17:58:00 +00:00
|
|
|
{
|
|
|
|
GstOptSchedulerGroup *group;
|
2002-09-12 19:22:03 +00:00
|
|
|
GstElementStateReturn res = GST_STATE_SUCCESS;
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2004-07-28 20:12:49 +00:00
|
|
|
GST_DEBUG ("element \"%s\" state change (%04x)",
|
|
|
|
GST_ELEMENT_NAME (element) ? GST_ELEMENT_NAME (element) : "(null)",
|
2004-03-13 15:27:01 +00:00
|
|
|
transition);
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2002-09-12 19:22:03 +00:00
|
|
|
/* we check the state of the managing pipeline here */
|
2002-09-08 17:58:00 +00:00
|
|
|
if (GST_IS_BIN (element)) {
|
|
|
|
if (GST_SCHEDULER_PARENT (sched) == element) {
|
2004-07-28 20:12:49 +00:00
|
|
|
GST_LOG ("parent \"%s\" changed state",
|
|
|
|
GST_ELEMENT_NAME (element) ? GST_ELEMENT_NAME (element) : "(null)");
|
2002-09-08 17:58:00 +00:00
|
|
|
|
|
|
|
switch (transition) {
|
2004-03-15 19:24:35 +00:00
|
|
|
case GST_STATE_PLAYING_TO_PAUSED:
|
|
|
|
GST_INFO ("setting scheduler state to stopped");
|
|
|
|
GST_SCHEDULER_STATE (sched) = GST_SCHEDULER_STATE_STOPPED;
|
|
|
|
break;
|
|
|
|
case GST_STATE_PAUSED_TO_PLAYING:
|
|
|
|
GST_INFO ("setting scheduler state to running");
|
|
|
|
GST_SCHEDULER_STATE (sched) = GST_SCHEDULER_STATE_RUNNING;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
GST_LOG ("no interesting state change, doing nothing");
|
2002-09-08 17:58:00 +00:00
|
|
|
}
|
|
|
|
}
|
2002-09-12 19:22:03 +00:00
|
|
|
return res;
|
2002-09-08 17:58:00 +00:00
|
|
|
}
|
|
|
|
|
2002-09-12 19:22:03 +00:00
|
|
|
/* we don't care about decoupled elements after this */
|
2002-09-08 17:58:00 +00:00
|
|
|
if (GST_ELEMENT_IS_DECOUPLED (element))
|
|
|
|
return GST_STATE_SUCCESS;
|
|
|
|
|
2002-09-12 19:22:03 +00:00
|
|
|
/* get the group of the element */
|
2002-09-08 17:58:00 +00:00
|
|
|
group = GST_ELEMENT_SCHED_GROUP (element);
|
|
|
|
|
|
|
|
switch (transition) {
|
|
|
|
case GST_STATE_PAUSED_TO_PLAYING:
|
2004-05-27 11:29:18 +00:00
|
|
|
/* an element without a group has to be an unlinked src, sink
|
2002-09-12 19:22:03 +00:00
|
|
|
* filter element */
|
2003-01-20 23:11:51 +00:00
|
|
|
if (!group) {
|
2004-03-15 19:24:35 +00:00
|
|
|
GST_INFO ("element \"%s\" has no group", GST_ELEMENT_NAME (element));
|
2003-01-20 23:11:51 +00:00
|
|
|
}
|
2002-09-12 19:22:03 +00:00
|
|
|
/* else construct the scheduling context of this group and enable it */
|
|
|
|
else {
|
2004-03-15 19:24:35 +00:00
|
|
|
group_element_set_enabled (group, element, TRUE);
|
2002-09-12 19:22:03 +00:00
|
|
|
}
|
2002-09-08 17:58:00 +00:00
|
|
|
break;
|
|
|
|
case GST_STATE_PLAYING_TO_PAUSED:
|
2002-09-12 19:22:03 +00:00
|
|
|
/* if the element still has a group, we disable it */
|
2004-03-13 15:27:01 +00:00
|
|
|
if (group)
|
2004-03-15 19:24:35 +00:00
|
|
|
group_element_set_enabled (group, element, FALSE);
|
2002-09-08 17:58:00 +00:00
|
|
|
break;
|
2003-02-06 20:22:34 +00:00
|
|
|
case GST_STATE_PAUSED_TO_READY:
|
2004-03-13 15:27:01 +00:00
|
|
|
{
|
2003-02-06 20:22:34 +00:00
|
|
|
GList *pads = (GList *) gst_element_get_pad_list (element);
|
|
|
|
|
|
|
|
g_list_foreach (pads, (GFunc) pad_clear_queued, NULL);
|
|
|
|
break;
|
|
|
|
}
|
2002-09-08 17:58:00 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2002-09-12 19:22:03 +00:00
|
|
|
return res;
|
2002-09-08 17:58:00 +00:00
|
|
|
}
|
|
|
|
|
2002-12-15 12:18:04 +00:00
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
gst_opt_scheduler_scheduling_change (GstScheduler * sched, GstElement * element)
|
2002-12-15 12:18:04 +00:00
|
|
|
{
|
|
|
|
g_warning ("scheduling change, implement me");
|
|
|
|
}
|
|
|
|
|
2002-11-02 13:54:34 +00:00
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
get_group (GstElement * element, GstOptSchedulerGroup ** group)
|
2002-11-02 13:54:34 +00:00
|
|
|
{
|
|
|
|
GstOptSchedulerCtx *ctx;
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2002-11-02 13:54:34 +00:00
|
|
|
ctx = GST_ELEMENT_SCHED_CONTEXT (element);
|
2004-03-13 15:27:01 +00:00
|
|
|
if (ctx)
|
2002-11-02 13:54:34 +00:00
|
|
|
*group = ctx->group;
|
|
|
|
else
|
|
|
|
*group = NULL;
|
|
|
|
}
|
|
|
|
|
2002-09-08 22:42:29 +00:00
|
|
|
/*
|
|
|
|
* the idea is to put the two elements into the same group.
|
|
|
|
* - When no element is inside a group, we create a new group and add
|
|
|
|
* the elements to it.
|
|
|
|
* - When one of the elements has a group, add the other element to
|
|
|
|
* that group
|
|
|
|
* - if both of the elements have a group, we merge the groups, which
|
|
|
|
* will also merge the chains.
|
2004-04-03 13:24:07 +00:00
|
|
|
* Group links must be managed by the caller.
|
2002-09-08 22:42:29 +00:00
|
|
|
*/
|
2004-03-13 15:27:01 +00:00
|
|
|
static GstOptSchedulerGroup *
|
|
|
|
group_elements (GstOptScheduler * osched, GstElement * element1,
|
|
|
|
GstElement * element2, GstOptSchedulerGroupType type)
|
2002-09-08 17:58:00 +00:00
|
|
|
{
|
2002-11-02 13:54:34 +00:00
|
|
|
GstOptSchedulerGroup *group1, *group2, *group = NULL;
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2002-11-02 13:54:34 +00:00
|
|
|
get_group (element1, &group1);
|
|
|
|
get_group (element2, &group2);
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2002-09-08 22:42:29 +00:00
|
|
|
/* none of the elements is added to a group, create a new group
|
|
|
|
* and chain to add the elements to */
|
2002-09-08 17:58:00 +00:00
|
|
|
if (!group1 && !group2) {
|
|
|
|
GstOptSchedulerChain *chain;
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_DEBUG ("creating new group to hold \"%s\" and \"%s\"",
|
2004-03-15 19:24:35 +00:00
|
|
|
GST_ELEMENT_NAME (element1), GST_ELEMENT_NAME (element2));
|
2002-09-08 17:58:00 +00:00
|
|
|
|
|
|
|
chain = create_chain (osched);
|
2004-03-07 14:33:13 +00:00
|
|
|
group = create_group (chain, element1, type);
|
gst/schedulers/gstoptimalscheduler.c: Call group_inc_link with the proper src->sink ordering -- break this, and we br...
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (gst_opt_scheduler_init),
(create_chain), (destroy_chain), (create_group), (destroy_group),
(add_to_group), (merge_groups), (group_elements), (group_inc_link),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_inc_links_for_element), (group_migrate_connected):
Call group_inc_link with the proper src->sink ordering --
break this, and we break sort_chain. patch from wingo for bug
147713.
Partially revert patch 1.89. When adding a loop based element to
the scheduler, the links to other groups are automatically followed
and incremented. This should not happen because the bin will call
pad_link explicitly for those connection, resulting in them counted
twice. Results in assertion failure on pipeline cleanup.
2004-07-16 16:02:12 +00:00
|
|
|
add_to_group (group, element2, TRUE);
|
2002-09-08 17:58:00 +00:00
|
|
|
}
|
2002-09-08 22:42:29 +00:00
|
|
|
/* the first element has a group */
|
2002-09-08 17:58:00 +00:00
|
|
|
else if (group1) {
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_DEBUG ("adding \"%s\" to \"%s\"'s group",
|
2004-03-15 19:24:35 +00:00
|
|
|
GST_ELEMENT_NAME (element2), GST_ELEMENT_NAME (element1));
|
2002-09-08 22:42:29 +00:00
|
|
|
|
|
|
|
/* the second element also has a group, merge */
|
2002-09-08 17:58:00 +00:00
|
|
|
if (group2)
|
|
|
|
merge_groups (group1, group2);
|
2002-09-08 22:42:29 +00:00
|
|
|
/* the second element has no group, add it to the group
|
|
|
|
* of the first element */
|
2002-09-08 17:58:00 +00:00
|
|
|
else
|
gst/schedulers/gstoptimalscheduler.c: Call group_inc_link with the proper src->sink ordering -- break this, and we br...
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (gst_opt_scheduler_init),
(create_chain), (destroy_chain), (create_group), (destroy_group),
(add_to_group), (merge_groups), (group_elements), (group_inc_link),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_inc_links_for_element), (group_migrate_connected):
Call group_inc_link with the proper src->sink ordering --
break this, and we break sort_chain. patch from wingo for bug
147713.
Partially revert patch 1.89. When adding a loop based element to
the scheduler, the links to other groups are automatically followed
and incremented. This should not happen because the bin will call
pad_link explicitly for those connection, resulting in them counted
twice. Results in assertion failure on pipeline cleanup.
2004-07-16 16:02:12 +00:00
|
|
|
add_to_group (group1, element2, TRUE);
|
2002-09-08 17:58:00 +00:00
|
|
|
|
|
|
|
group = group1;
|
|
|
|
}
|
2002-09-08 22:42:29 +00:00
|
|
|
/* element1 has no group, element2 does. Add element1 to the
|
|
|
|
* group of element2 */
|
2002-09-08 17:58:00 +00:00
|
|
|
else {
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_DEBUG ("adding \"%s\" to \"%s\"'s group",
|
2004-03-15 19:24:35 +00:00
|
|
|
GST_ELEMENT_NAME (element1), GST_ELEMENT_NAME (element2));
|
gst/schedulers/gstoptimalscheduler.c: Call group_inc_link with the proper src->sink ordering -- break this, and we br...
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (gst_opt_scheduler_init),
(create_chain), (destroy_chain), (create_group), (destroy_group),
(add_to_group), (merge_groups), (group_elements), (group_inc_link),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_inc_links_for_element), (group_migrate_connected):
Call group_inc_link with the proper src->sink ordering --
break this, and we break sort_chain. patch from wingo for bug
147713.
Partially revert patch 1.89. When adding a loop based element to
the scheduler, the links to other groups are automatically followed
and incremented. This should not happen because the bin will call
pad_link explicitly for those connection, resulting in them counted
twice. Results in assertion failure on pipeline cleanup.
2004-07-16 16:02:12 +00:00
|
|
|
add_to_group (group2, element1, TRUE);
|
2002-09-08 17:58:00 +00:00
|
|
|
group = group2;
|
|
|
|
}
|
|
|
|
return group;
|
|
|
|
}
|
|
|
|
|
2003-06-07 11:36:42 +00:00
|
|
|
/*
|
2004-04-03 13:24:07 +00:00
|
|
|
* increment link counts between groups -- it's important that src is actually
|
|
|
|
* the src group, so we can introspect the topology later
|
2003-06-07 11:36:42 +00:00
|
|
|
*/
|
|
|
|
static void
|
2004-04-03 13:24:07 +00:00
|
|
|
group_inc_link (GstOptSchedulerGroup * src, GstOptSchedulerGroup * sink)
|
2003-06-07 11:36:42 +00:00
|
|
|
{
|
2004-04-03 13:24:07 +00:00
|
|
|
GSList *links = src->group_links;
|
2003-06-07 11:36:42 +00:00
|
|
|
gboolean done = FALSE;
|
|
|
|
GstOptSchedulerGroupLink *link;
|
|
|
|
|
|
|
|
/* first try to find a previous link */
|
|
|
|
while (links && !done) {
|
|
|
|
link = (GstOptSchedulerGroupLink *) links->data;
|
|
|
|
links = g_slist_next (links);
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2004-04-03 13:24:07 +00:00
|
|
|
if (IS_GROUP_LINK (link, src, sink)) {
|
2003-06-07 11:36:42 +00:00
|
|
|
/* we found a link to this group, increment the link count */
|
|
|
|
link->count++;
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_LOG ("incremented group link count between %p and %p to %d",
|
2004-04-03 13:24:07 +00:00
|
|
|
src, sink, link->count);
|
2003-06-07 11:36:42 +00:00
|
|
|
done = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!done) {
|
|
|
|
/* no link was found, create a new one */
|
|
|
|
link = g_new0 (GstOptSchedulerGroupLink, 1);
|
|
|
|
|
2004-04-03 13:24:07 +00:00
|
|
|
link->src = src;
|
|
|
|
link->sink = sink;
|
2003-06-07 11:36:42 +00:00
|
|
|
link->count = 1;
|
|
|
|
|
2004-04-03 13:24:07 +00:00
|
|
|
src->group_links = g_slist_prepend (src->group_links, link);
|
|
|
|
sink->group_links = g_slist_prepend (sink->group_links, link);
|
2003-06-07 11:36:42 +00:00
|
|
|
|
gst/schedulers/gstoptimalscheduler.c: Call group_inc_link with the proper src->sink ordering -- break this, and we br...
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (gst_opt_scheduler_init),
(create_chain), (destroy_chain), (create_group), (destroy_group),
(add_to_group), (merge_groups), (group_elements), (group_inc_link),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_inc_links_for_element), (group_migrate_connected):
Call group_inc_link with the proper src->sink ordering --
break this, and we break sort_chain. patch from wingo for bug
147713.
Partially revert patch 1.89. When adding a loop based element to
the scheduler, the links to other groups are automatically followed
and incremented. This should not happen because the bin will call
pad_link explicitly for those connection, resulting in them counted
twice. Results in assertion failure on pipeline cleanup.
2004-07-16 16:02:12 +00:00
|
|
|
src->sched->live_links++;
|
|
|
|
|
|
|
|
GST_DEBUG ("added group link between %p and %p, %d live links now",
|
|
|
|
src, sink, src->sched->live_links);
|
2003-06-07 11:36:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2004-04-03 13:24:07 +00:00
|
|
|
* decrement link counts between groups, returns TRUE if the link count reaches
|
|
|
|
* 0 -- note that the groups are not necessarily ordered as (src, sink) like
|
|
|
|
* inc_link requires
|
2003-06-07 11:36:42 +00:00
|
|
|
*/
|
|
|
|
static gboolean
|
2004-03-13 15:27:01 +00:00
|
|
|
group_dec_link (GstOptSchedulerGroup * group1, GstOptSchedulerGroup * group2)
|
2003-06-07 11:36:42 +00:00
|
|
|
{
|
|
|
|
GSList *links = group1->group_links;
|
|
|
|
gboolean res = FALSE;
|
|
|
|
GstOptSchedulerGroupLink *link;
|
|
|
|
|
|
|
|
while (links) {
|
|
|
|
link = (GstOptSchedulerGroupLink *) links->data;
|
|
|
|
links = g_slist_next (links);
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2003-06-07 11:36:42 +00:00
|
|
|
if (IS_GROUP_LINK (link, group1, group2)) {
|
2004-05-04 16:43:49 +00:00
|
|
|
g_assert (link->count > 0);
|
2003-06-07 11:36:42 +00:00
|
|
|
link->count--;
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_LOG ("link count between %p and %p is now %d",
|
2004-03-15 19:24:35 +00:00
|
|
|
group1, group2, link->count);
|
2003-06-07 11:36:42 +00:00
|
|
|
if (link->count == 0) {
|
gst/schedulers/gstoptimalscheduler.c: move isolated groups to a new chain.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (create_group),
(add_to_group), (merge_groups), (schedule_group),
(gst_opt_scheduler_get_wrapper), (group_elements),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_migrate_connected), (gst_opt_scheduler_pad_unlink),
(gst_opt_scheduler_iterate):
move isolated groups to a new chain.
Emit a warning instead of segfaulting in some error cases.
Fix a bug where the link count between groups was not calculated
correctly. Fixes #144510.
2004-07-14 14:25:04 +00:00
|
|
|
GstOptSchedulerGroup *iso_group = NULL;
|
|
|
|
|
2004-03-15 19:24:35 +00:00
|
|
|
group1->group_links = g_slist_remove (group1->group_links, link);
|
|
|
|
group2->group_links = g_slist_remove (group2->group_links, link);
|
gst/schedulers/gstoptimalscheduler.c: Call group_inc_link with the proper src->sink ordering -- break this, and we br...
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (gst_opt_scheduler_init),
(create_chain), (destroy_chain), (create_group), (destroy_group),
(add_to_group), (merge_groups), (group_elements), (group_inc_link),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_inc_links_for_element), (group_migrate_connected):
Call group_inc_link with the proper src->sink ordering --
break this, and we break sort_chain. patch from wingo for bug
147713.
Partially revert patch 1.89. When adding a loop based element to
the scheduler, the links to other groups are automatically followed
and incremented. This should not happen because the bin will call
pad_link explicitly for those connection, resulting in them counted
twice. Results in assertion failure on pipeline cleanup.
2004-07-16 16:02:12 +00:00
|
|
|
group1->sched->live_links--;
|
|
|
|
|
|
|
|
GST_LOG ("%d live links now", group1->sched->live_links);
|
|
|
|
|
2004-03-15 19:24:35 +00:00
|
|
|
g_free (link);
|
|
|
|
GST_DEBUG ("removed group link between %p and %p", group1, group2);
|
gst/schedulers/gstoptimalscheduler.c: move isolated groups to a new chain.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (create_group),
(add_to_group), (merge_groups), (schedule_group),
(gst_opt_scheduler_get_wrapper), (group_elements),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_migrate_connected), (gst_opt_scheduler_pad_unlink),
(gst_opt_scheduler_iterate):
move isolated groups to a new chain.
Emit a warning instead of segfaulting in some error cases.
Fix a bug where the link count between groups was not calculated
correctly. Fixes #144510.
2004-07-14 14:25:04 +00:00
|
|
|
if (group1->group_links == NULL) {
|
|
|
|
/* group1 has no more links with other groups */
|
|
|
|
iso_group = group1;
|
|
|
|
} else if (group2->group_links == NULL) {
|
|
|
|
/* group2 has no more links with other groups */
|
|
|
|
iso_group = group2;
|
|
|
|
}
|
|
|
|
if (iso_group) {
|
|
|
|
GstOptSchedulerChain *chain;
|
|
|
|
|
|
|
|
GST_DEBUG ("group %p has become isolated, moving to new chain",
|
|
|
|
iso_group);
|
|
|
|
|
|
|
|
chain = create_chain (iso_group->chain->sched);
|
|
|
|
remove_from_chain (iso_group->chain, iso_group);
|
|
|
|
add_to_chain (chain, iso_group);
|
|
|
|
}
|
2004-03-15 19:24:35 +00:00
|
|
|
res = TRUE;
|
2003-06-07 11:36:42 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
typedef enum
|
|
|
|
{
|
2002-09-08 17:58:00 +00:00
|
|
|
GST_OPT_INVALID,
|
|
|
|
GST_OPT_GET_TO_CHAIN,
|
|
|
|
GST_OPT_LOOP_TO_CHAIN,
|
|
|
|
GST_OPT_GET_TO_LOOP,
|
|
|
|
GST_OPT_CHAIN_TO_CHAIN,
|
|
|
|
GST_OPT_CHAIN_TO_LOOP,
|
2004-05-28 05:01:05 +00:00
|
|
|
GST_OPT_LOOP_TO_LOOP
|
2004-03-15 19:24:35 +00:00
|
|
|
}
|
|
|
|
LinkType;
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2002-09-12 19:22:03 +00:00
|
|
|
/*
|
|
|
|
* Entry points for this scheduler.
|
|
|
|
*/
|
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
gst_opt_scheduler_setup (GstScheduler * sched)
|
|
|
|
{
|
2002-12-15 18:21:43 +00:00
|
|
|
#ifdef USE_COTHREADS
|
2003-12-13 16:58:29 +00:00
|
|
|
GstOptScheduler *osched = GST_OPT_SCHEDULER (sched);
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2002-09-12 19:22:03 +00:00
|
|
|
/* first create thread context */
|
2002-12-15 18:21:43 +00:00
|
|
|
if (osched->context == NULL) {
|
2004-02-20 13:18:32 +00:00
|
|
|
GST_DEBUG ("initializing cothread context");
|
2002-09-12 19:22:03 +00:00
|
|
|
osched->context = do_cothread_context_init ();
|
|
|
|
}
|
2002-12-15 18:21:43 +00:00
|
|
|
#endif
|
2004-03-13 15:27:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gst_opt_scheduler_reset (GstScheduler * sched)
|
|
|
|
{
|
2002-12-15 18:21:43 +00:00
|
|
|
#ifdef USE_COTHREADS
|
2003-12-13 16:58:29 +00:00
|
|
|
GstOptScheduler *osched = GST_OPT_SCHEDULER (sched);
|
2002-12-20 18:49:17 +00:00
|
|
|
GSList *chains = osched->chains;
|
|
|
|
|
|
|
|
while (chains) {
|
|
|
|
GstOptSchedulerChain *chain = (GstOptSchedulerChain *) chains->data;
|
|
|
|
GSList *groups = chain->groups;
|
|
|
|
|
|
|
|
while (groups) {
|
|
|
|
GstOptSchedulerGroup *group = (GstOptSchedulerGroup *) groups->data;
|
|
|
|
|
|
|
|
destroy_group_scheduler (group);
|
|
|
|
groups = groups->next;
|
|
|
|
}
|
|
|
|
chains = chains->next;
|
|
|
|
}
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2002-12-15 18:21:43 +00:00
|
|
|
if (osched->context) {
|
2002-09-12 19:22:03 +00:00
|
|
|
do_cothread_context_destroy (osched->context);
|
2004-03-13 15:27:01 +00:00
|
|
|
osched->context = NULL;
|
2002-09-12 19:22:03 +00:00
|
|
|
}
|
2002-12-15 18:21:43 +00:00
|
|
|
#endif
|
2004-03-13 15:27:01 +00:00
|
|
|
}
|
2004-04-03 13:24:07 +00:00
|
|
|
|
2002-09-12 19:22:03 +00:00
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
gst_opt_scheduler_add_element (GstScheduler * sched, GstElement * element)
|
2002-09-12 19:22:03 +00:00
|
|
|
{
|
2003-12-13 16:58:29 +00:00
|
|
|
GstOptScheduler *osched = GST_OPT_SCHEDULER (sched);
|
2002-09-12 19:22:03 +00:00
|
|
|
GstOptSchedulerCtx *ctx;
|
2004-03-13 15:27:01 +00:00
|
|
|
const GList *pads;
|
2002-09-12 19:22:03 +00:00
|
|
|
|
2004-02-20 13:18:32 +00:00
|
|
|
GST_DEBUG_OBJECT (sched, "adding element \"%s\"", GST_OBJECT_NAME (element));
|
2002-09-12 19:22:03 +00:00
|
|
|
|
|
|
|
/* decoupled elements are not added to the scheduler lists */
|
|
|
|
if (GST_ELEMENT_IS_DECOUPLED (element))
|
|
|
|
return;
|
|
|
|
|
|
|
|
ctx = g_new0 (GstOptSchedulerCtx, 1);
|
2004-03-24 14:06:48 +00:00
|
|
|
GST_ELEMENT (element)->sched_private = ctx;
|
2003-03-25 19:34:30 +00:00
|
|
|
ctx->flags = GST_OPT_SCHEDULER_CTX_DISABLED;
|
2002-09-12 19:22:03 +00:00
|
|
|
|
2003-08-26 10:50:35 +00:00
|
|
|
/* set event handler on all pads here so events work unconnected too;
|
|
|
|
* in _link, it can be overruled if need be */
|
|
|
|
/* FIXME: we should also do this when new pads on the element are created;
|
|
|
|
but there are no hooks, so we do it again in _link */
|
|
|
|
pads = gst_element_get_pad_list (element);
|
|
|
|
while (pads) {
|
|
|
|
GstPad *pad = GST_PAD (pads->data);
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2003-08-26 10:50:35 +00:00
|
|
|
pads = g_list_next (pads);
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
if (!GST_IS_REAL_PAD (pad))
|
|
|
|
continue;
|
2003-08-26 10:50:35 +00:00
|
|
|
GST_RPAD_EVENTHANDLER (pad) = GST_RPAD_EVENTFUNC (pad);
|
|
|
|
}
|
|
|
|
|
2002-09-12 19:22:03 +00:00
|
|
|
/* loop based elements *always* end up in their own group. It can eventually
|
2003-01-09 14:15:37 +00:00
|
|
|
* be merged with another group when a link is made */
|
2002-09-12 19:22:03 +00:00
|
|
|
if (element->loopfunc) {
|
|
|
|
GstOptSchedulerGroup *group;
|
|
|
|
GstOptSchedulerChain *chain;
|
|
|
|
|
|
|
|
chain = create_chain (osched);
|
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
group = create_group (chain, element, GST_OPT_SCHEDULER_GROUP_LOOP);
|
2002-09-12 19:22:03 +00:00
|
|
|
group->entry = element;
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_LOG ("added element \"%s\" as loop based entry",
|
2004-03-15 19:24:35 +00:00
|
|
|
GST_ELEMENT_NAME (element));
|
2002-09-12 19:22:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
gst_opt_scheduler_remove_element (GstScheduler * sched, GstElement * element)
|
2002-09-12 19:22:03 +00:00
|
|
|
{
|
2002-11-02 13:54:34 +00:00
|
|
|
GstOptSchedulerGroup *group;
|
2002-09-12 19:22:03 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_DEBUG_OBJECT (sched, "removing element \"%s\"",
|
|
|
|
GST_OBJECT_NAME (element));
|
2002-09-12 19:22:03 +00:00
|
|
|
|
2002-12-09 22:31:16 +00:00
|
|
|
/* decoupled elements are not added to the scheduler lists and should therefore
|
2004-04-03 13:24:07 +00:00
|
|
|
* not be removed */
|
2002-11-02 13:54:34 +00:00
|
|
|
if (GST_ELEMENT_IS_DECOUPLED (element))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* the element is guaranteed to live in it's own group/chain now */
|
|
|
|
get_group (element, &group);
|
|
|
|
if (group) {
|
2003-02-27 18:21:34 +00:00
|
|
|
remove_from_group (group, element);
|
2002-11-02 13:54:34 +00:00
|
|
|
}
|
|
|
|
|
2004-03-24 14:06:48 +00:00
|
|
|
g_free (GST_ELEMENT (element)->sched_private);
|
|
|
|
GST_ELEMENT (element)->sched_private = NULL;
|
2002-09-12 19:22:03 +00:00
|
|
|
}
|
|
|
|
|
2003-01-11 16:27:45 +00:00
|
|
|
static gboolean
|
2004-03-13 15:27:01 +00:00
|
|
|
gst_opt_scheduler_yield (GstScheduler * sched, GstElement * element)
|
2002-09-12 19:22:03 +00:00
|
|
|
{
|
2002-12-21 02:25:54 +00:00
|
|
|
#ifdef USE_COTHREADS
|
|
|
|
/* yield hands control to the main cothread context if the requesting
|
|
|
|
* element is the entry point of the group */
|
|
|
|
GstOptSchedulerGroup *group;
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2002-12-21 02:25:54 +00:00
|
|
|
get_group (element, &group);
|
|
|
|
if (group && group->entry == element)
|
2004-03-13 15:27:01 +00:00
|
|
|
do_cothread_switch (do_cothread_get_main (((GstOptScheduler *) sched)->
|
2004-03-15 19:24:35 +00:00
|
|
|
context));
|
2003-01-11 16:27:45 +00:00
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
#else
|
2004-03-13 15:27:01 +00:00
|
|
|
g_warning ("element %s performs a yield, please fix the element",
|
|
|
|
GST_ELEMENT_NAME (element));
|
2003-01-11 16:27:45 +00:00
|
|
|
return TRUE;
|
2002-12-21 02:25:54 +00:00
|
|
|
#endif
|
2002-09-12 19:22:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2004-03-13 15:27:01 +00:00
|
|
|
gst_opt_scheduler_interrupt (GstScheduler * sched, GstElement * element)
|
2002-09-12 19:22:03 +00:00
|
|
|
{
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_INFO ("interrupt from \"%s\"", GST_OBJECT_NAME (element));
|
2003-01-08 21:33:20 +00:00
|
|
|
|
2002-12-21 02:25:54 +00:00
|
|
|
#ifdef USE_COTHREADS
|
2004-03-13 15:27:01 +00:00
|
|
|
do_cothread_switch (do_cothread_get_main (((GstOptScheduler *) sched)->
|
2004-03-15 19:24:35 +00:00
|
|
|
context));
|
2002-12-21 02:25:54 +00:00
|
|
|
return FALSE;
|
|
|
|
#else
|
2003-01-08 21:33:20 +00:00
|
|
|
{
|
2003-12-13 16:58:29 +00:00
|
|
|
GstOptScheduler *osched = GST_OPT_SCHEDULER (sched);
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2004-02-20 13:18:32 +00:00
|
|
|
GST_INFO ("scheduler set interrupted state");
|
2003-01-08 21:33:20 +00:00
|
|
|
osched->state = GST_OPT_SCHEDULER_STATE_INTERRUPTED;
|
|
|
|
}
|
2002-09-12 19:22:03 +00:00
|
|
|
return TRUE;
|
2002-12-21 02:25:54 +00:00
|
|
|
#endif
|
2002-09-12 19:22:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
gst_opt_scheduler_error (GstScheduler * sched, GstElement * element)
|
2002-09-12 19:22:03 +00:00
|
|
|
{
|
2003-12-13 16:58:29 +00:00
|
|
|
GstOptScheduler *osched = GST_OPT_SCHEDULER (sched);
|
2002-12-16 21:21:02 +00:00
|
|
|
GstOptSchedulerGroup *group;
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2002-12-16 21:21:02 +00:00
|
|
|
get_group (element, &group);
|
|
|
|
if (group)
|
|
|
|
group_error_handler (group);
|
2002-09-12 19:22:03 +00:00
|
|
|
|
|
|
|
osched->state = GST_OPT_SCHEDULER_STATE_ERROR;
|
|
|
|
}
|
|
|
|
|
2003-01-09 14:15:37 +00:00
|
|
|
/* link pads, merge groups and chains */
|
2002-09-08 17:58:00 +00:00
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
gst_opt_scheduler_pad_link (GstScheduler * sched, GstPad * srcpad,
|
|
|
|
GstPad * sinkpad)
|
2002-09-08 17:58:00 +00:00
|
|
|
{
|
2003-12-13 16:58:29 +00:00
|
|
|
GstOptScheduler *osched = GST_OPT_SCHEDULER (sched);
|
2003-01-09 22:59:37 +00:00
|
|
|
LinkType type = GST_OPT_INVALID;
|
2004-04-03 13:24:07 +00:00
|
|
|
GstElement *src_element, *sink_element;
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_INFO ("scheduling link between %s:%s and %s:%s",
|
|
|
|
GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-04-03 13:24:07 +00:00
|
|
|
src_element = GST_PAD_PARENT (srcpad);
|
|
|
|
sink_element = GST_PAD_PARENT (sinkpad);
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2003-01-09 14:15:37 +00:00
|
|
|
/* first we need to figure out what type of link we're dealing
|
2002-09-08 22:42:29 +00:00
|
|
|
* with */
|
2004-04-03 13:24:07 +00:00
|
|
|
if (src_element->loopfunc && sink_element->loopfunc)
|
2002-09-08 17:58:00 +00:00
|
|
|
type = GST_OPT_LOOP_TO_LOOP;
|
|
|
|
else {
|
2004-04-03 13:24:07 +00:00
|
|
|
if (src_element->loopfunc) {
|
2002-09-08 17:58:00 +00:00
|
|
|
if (GST_RPAD_CHAINFUNC (sinkpad))
|
2004-03-15 19:24:35 +00:00
|
|
|
type = GST_OPT_LOOP_TO_CHAIN;
|
2004-04-03 13:24:07 +00:00
|
|
|
} else if (sink_element->loopfunc) {
|
2002-11-02 13:54:34 +00:00
|
|
|
if (GST_RPAD_GETFUNC (srcpad)) {
|
2004-03-15 19:24:35 +00:00
|
|
|
type = GST_OPT_GET_TO_LOOP;
|
|
|
|
/* this could be tricky, the get based source could
|
|
|
|
* already be part of a loop based group in another pad,
|
|
|
|
* we assert on that for now */
|
2004-04-03 13:24:07 +00:00
|
|
|
if (GST_ELEMENT_SCHED_CONTEXT (src_element) != NULL &&
|
|
|
|
GST_ELEMENT_SCHED_GROUP (src_element) != NULL) {
|
|
|
|
GstOptSchedulerGroup *group = GST_ELEMENT_SCHED_GROUP (src_element);
|
2004-03-15 19:24:35 +00:00
|
|
|
|
|
|
|
/* if the loop based element is the entry point we're ok, if it
|
|
|
|
* isn't then we have multiple loop based elements in this group */
|
2004-04-03 13:24:07 +00:00
|
|
|
if (group->entry != sink_element) {
|
2004-03-15 19:24:35 +00:00
|
|
|
g_error
|
|
|
|
("internal error: cannot schedule get to loop in multi-loop based group");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2004-03-13 15:27:01 +00:00
|
|
|
} else
|
2004-03-15 19:24:35 +00:00
|
|
|
type = GST_OPT_CHAIN_TO_LOOP;
|
2004-03-13 15:27:01 +00:00
|
|
|
} else {
|
2002-11-02 13:54:34 +00:00
|
|
|
if (GST_RPAD_GETFUNC (srcpad) && GST_RPAD_CHAINFUNC (sinkpad)) {
|
2004-03-15 19:24:35 +00:00
|
|
|
type = GST_OPT_GET_TO_CHAIN;
|
|
|
|
/* the get based source could already be part of a loop
|
|
|
|
* based group in another pad, we assert on that for now */
|
2004-04-03 13:24:07 +00:00
|
|
|
if (GST_ELEMENT_SCHED_CONTEXT (src_element) != NULL &&
|
|
|
|
GST_ELEMENT_SCHED_GROUP (src_element) != NULL) {
|
|
|
|
GstOptSchedulerGroup *group = GST_ELEMENT_SCHED_GROUP (src_element);
|
2004-03-15 19:24:35 +00:00
|
|
|
|
|
|
|
/* if the get based element is the entry point we're ok, if it
|
|
|
|
* isn't then we have a mixed loop/chain based group */
|
2004-04-03 13:24:07 +00:00
|
|
|
if (group->entry != src_element) {
|
|
|
|
g_error ("internal error: cannot schedule get to chain "
|
|
|
|
"with mixed loop/chain based group");
|
2004-03-15 19:24:35 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2004-03-13 15:27:01 +00:00
|
|
|
} else
|
2004-03-15 19:24:35 +00:00
|
|
|
type = GST_OPT_CHAIN_TO_CHAIN;
|
2002-09-08 17:58:00 +00:00
|
|
|
}
|
|
|
|
}
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2003-08-26 10:50:35 +00:00
|
|
|
/* since we can't set event handlers on pad creation after addition, it is
|
|
|
|
* best we set all of them again to the default before linking */
|
|
|
|
GST_RPAD_EVENTHANDLER (srcpad) = GST_RPAD_EVENTFUNC (srcpad);
|
|
|
|
GST_RPAD_EVENTHANDLER (sinkpad) = GST_RPAD_EVENTFUNC (sinkpad);
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2003-01-09 14:15:37 +00:00
|
|
|
/* for each link type, perform specific actions */
|
2002-09-08 17:58:00 +00:00
|
|
|
switch (type) {
|
|
|
|
case GST_OPT_GET_TO_CHAIN:
|
|
|
|
{
|
|
|
|
GstOptSchedulerGroup *group = NULL;
|
|
|
|
|
2004-02-20 13:18:32 +00:00
|
|
|
GST_LOG ("get to chain based link");
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2002-09-08 22:42:29 +00:00
|
|
|
/* setup get/chain handlers */
|
gst/gstpad.c: implement enforcing discont events before buffers are passed. This allows state changes of only some el...
Original commit message from CVS:
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_new),
(gst_pad_link_free), (gst_pad_link_try), (_invent_event),
(gst_pad_pull):
implement enforcing discont events before buffers are passed. This
allows state changes of only some elements and later correctly going
on where they left off (or in short: you can now set audio sinks to
NULL to release the device when the pipeline is paused)
* gst/gstpad.c: (gst_pad_call_chain_function),
(gst_pad_call_get_function):
* gst/gstpad.h:
add gst_pad_call_chain_function and gst_pad_call_get_function for
scheduler interaction. They are required because of the changes
above.
* gst/schedulers/entryscheduler.c: (get_buffer),
(gst_entry_scheduler_chain_wrapper),
(gst_entry_scheduler_get_wrapper),
(gst_entry_scheduler_state_transition),
(gst_entry_scheduler_pad_link):
* gst/schedulers/gstbasicscheduler.c:
(gst_basic_scheduler_chain_wrapper),
(gst_basic_scheduler_src_wrapper),
(gst_basic_scheduler_chainhandler_proxy),
(gst_basic_scheduler_gethandler_proxy),
(gst_basic_scheduler_cothreaded_chain),
(gst_basic_scheduler_chain_elements):
* gst/schedulers/gstoptimalscheduler.c:
(get_group_schedule_function), (pad_clear_queued),
(gst_opt_scheduler_pad_link):
use the new functions instead of calling get/chain-functions
directly.
2004-04-16 01:36:37 +00:00
|
|
|
GST_RPAD_GETHANDLER (srcpad) = gst_pad_call_get_function;
|
|
|
|
GST_RPAD_CHAINHANDLER (sinkpad) = gst_pad_call_chain_function;
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2002-09-08 22:42:29 +00:00
|
|
|
/* the two elements should be put into the same group,
|
|
|
|
* this also means that they are in the same chain automatically */
|
2004-04-03 13:24:07 +00:00
|
|
|
group = group_elements (osched, src_element, sink_element,
|
2004-03-15 19:24:35 +00:00
|
|
|
GST_OPT_SCHEDULER_GROUP_GET);
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2002-09-08 22:42:29 +00:00
|
|
|
/* if there is not yet an entry in the group, select the source
|
2004-05-18 17:03:41 +00:00
|
|
|
* element as the entry point and mark the group as a get based
|
|
|
|
* group */
|
2002-09-08 17:58:00 +00:00
|
|
|
if (!group->entry) {
|
2004-04-03 13:24:07 +00:00
|
|
|
group->entry = src_element;
|
2004-05-18 17:03:41 +00:00
|
|
|
group->type = GST_OPT_SCHEDULER_GROUP_GET;
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-03-15 19:24:35 +00:00
|
|
|
GST_DEBUG ("setting \"%s\" as entry point of _get-based group %p",
|
2004-04-03 13:24:07 +00:00
|
|
|
GST_ELEMENT_NAME (src_element), group);
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
|
|
|
|
setup_group_scheduler (osched, group);
|
2002-09-08 17:58:00 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case GST_OPT_LOOP_TO_CHAIN:
|
|
|
|
case GST_OPT_CHAIN_TO_CHAIN:
|
2004-02-20 13:18:32 +00:00
|
|
|
GST_LOG ("loop/chain to chain based link");
|
2002-09-08 17:58:00 +00:00
|
|
|
|
gst/gstpad.c: implement enforcing discont events before buffers are passed. This allows state changes of only some el...
Original commit message from CVS:
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_new),
(gst_pad_link_free), (gst_pad_link_try), (_invent_event),
(gst_pad_pull):
implement enforcing discont events before buffers are passed. This
allows state changes of only some elements and later correctly going
on where they left off (or in short: you can now set audio sinks to
NULL to release the device when the pipeline is paused)
* gst/gstpad.c: (gst_pad_call_chain_function),
(gst_pad_call_get_function):
* gst/gstpad.h:
add gst_pad_call_chain_function and gst_pad_call_get_function for
scheduler interaction. They are required because of the changes
above.
* gst/schedulers/entryscheduler.c: (get_buffer),
(gst_entry_scheduler_chain_wrapper),
(gst_entry_scheduler_get_wrapper),
(gst_entry_scheduler_state_transition),
(gst_entry_scheduler_pad_link):
* gst/schedulers/gstbasicscheduler.c:
(gst_basic_scheduler_chain_wrapper),
(gst_basic_scheduler_src_wrapper),
(gst_basic_scheduler_chainhandler_proxy),
(gst_basic_scheduler_gethandler_proxy),
(gst_basic_scheduler_cothreaded_chain),
(gst_basic_scheduler_chain_elements):
* gst/schedulers/gstoptimalscheduler.c:
(get_group_schedule_function), (pad_clear_queued),
(gst_opt_scheduler_pad_link):
use the new functions instead of calling get/chain-functions
directly.
2004-04-16 01:36:37 +00:00
|
|
|
GST_RPAD_CHAINHANDLER (sinkpad) = gst_pad_call_chain_function;
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-04-03 13:24:07 +00:00
|
|
|
/* the two elements should be put into the same group, this also means
|
|
|
|
* that they are in the same chain automatically, in case of a loop-based
|
|
|
|
* src_element, there will be a group for src_element and sink_element
|
2004-05-18 16:44:44 +00:00
|
|
|
* will be added to it. In the case a new group is created, we can't know
|
|
|
|
* the type so we pass UNKNOWN as an arg */
|
2004-04-03 13:24:07 +00:00
|
|
|
group_elements (osched, src_element, sink_element,
|
2004-05-18 16:44:44 +00:00
|
|
|
GST_OPT_SCHEDULER_GROUP_UNKNOWN);
|
2002-09-08 17:58:00 +00:00
|
|
|
break;
|
|
|
|
case GST_OPT_GET_TO_LOOP:
|
2004-02-20 13:18:32 +00:00
|
|
|
GST_LOG ("get to loop based link");
|
2002-09-08 17:58:00 +00:00
|
|
|
|
gst/gstpad.c: implement enforcing discont events before buffers are passed. This allows state changes of only some el...
Original commit message from CVS:
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_new),
(gst_pad_link_free), (gst_pad_link_try), (_invent_event),
(gst_pad_pull):
implement enforcing discont events before buffers are passed. This
allows state changes of only some elements and later correctly going
on where they left off (or in short: you can now set audio sinks to
NULL to release the device when the pipeline is paused)
* gst/gstpad.c: (gst_pad_call_chain_function),
(gst_pad_call_get_function):
* gst/gstpad.h:
add gst_pad_call_chain_function and gst_pad_call_get_function for
scheduler interaction. They are required because of the changes
above.
* gst/schedulers/entryscheduler.c: (get_buffer),
(gst_entry_scheduler_chain_wrapper),
(gst_entry_scheduler_get_wrapper),
(gst_entry_scheduler_state_transition),
(gst_entry_scheduler_pad_link):
* gst/schedulers/gstbasicscheduler.c:
(gst_basic_scheduler_chain_wrapper),
(gst_basic_scheduler_src_wrapper),
(gst_basic_scheduler_chainhandler_proxy),
(gst_basic_scheduler_gethandler_proxy),
(gst_basic_scheduler_cothreaded_chain),
(gst_basic_scheduler_chain_elements):
* gst/schedulers/gstoptimalscheduler.c:
(get_group_schedule_function), (pad_clear_queued),
(gst_opt_scheduler_pad_link):
use the new functions instead of calling get/chain-functions
directly.
2004-04-16 01:36:37 +00:00
|
|
|
GST_RPAD_GETHANDLER (srcpad) = gst_pad_call_get_function;
|
2002-09-08 22:42:29 +00:00
|
|
|
|
2004-04-03 13:24:07 +00:00
|
|
|
/* the two elements should be put into the same group, this also means
|
|
|
|
* that they are in the same chain automatically, sink_element is
|
|
|
|
* loop-based so it already has a group where src_element will be added
|
|
|
|
* to */
|
|
|
|
group_elements (osched, src_element, sink_element,
|
|
|
|
GST_OPT_SCHEDULER_GROUP_LOOP);
|
2002-09-08 17:58:00 +00:00
|
|
|
break;
|
|
|
|
case GST_OPT_CHAIN_TO_LOOP:
|
|
|
|
case GST_OPT_LOOP_TO_LOOP:
|
|
|
|
{
|
|
|
|
GstOptSchedulerGroup *group1, *group2;
|
|
|
|
|
2004-02-20 13:18:32 +00:00
|
|
|
GST_LOG ("chain/loop to loop based link");
|
2002-09-08 17:58:00 +00:00
|
|
|
|
|
|
|
GST_RPAD_CHAINHANDLER (sinkpad) = gst_opt_scheduler_loop_wrapper;
|
|
|
|
GST_RPAD_GETHANDLER (srcpad) = gst_opt_scheduler_get_wrapper;
|
2003-02-03 22:50:55 +00:00
|
|
|
/* events on the srcpad have to be intercepted as we might need to
|
2003-08-26 10:50:35 +00:00
|
|
|
* flush the buffer lists, so override the given eventfunc */
|
2003-02-03 22:50:55 +00:00
|
|
|
GST_RPAD_EVENTHANDLER (srcpad) = gst_opt_scheduler_event_wrapper;
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-04-03 13:24:07 +00:00
|
|
|
group1 = GST_ELEMENT_SCHED_GROUP (src_element);
|
|
|
|
group2 = GST_ELEMENT_SCHED_GROUP (sink_element);
|
2002-12-15 12:18:04 +00:00
|
|
|
|
2002-12-26 22:11:04 +00:00
|
|
|
g_assert (group2 != NULL);
|
2002-12-15 12:18:04 +00:00
|
|
|
|
2002-09-08 22:42:29 +00:00
|
|
|
/* group2 is guaranteed to exist as it contains a loop-based element.
|
2004-04-03 13:24:07 +00:00
|
|
|
* group1 only exists if src_element is linked to some other element */
|
2002-09-08 17:58:00 +00:00
|
|
|
if (!group1) {
|
2004-04-03 13:24:07 +00:00
|
|
|
/* create a new group for src_element as it cannot be merged into another group
|
gst/schedulers/gstoptimalscheduler.c: move isolated groups to a new chain.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (create_group),
(add_to_group), (merge_groups), (schedule_group),
(gst_opt_scheduler_get_wrapper), (group_elements),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_migrate_connected), (gst_opt_scheduler_pad_unlink),
(gst_opt_scheduler_iterate):
move isolated groups to a new chain.
Emit a warning instead of segfaulting in some error cases.
Fix a bug where the link count between groups was not calculated
correctly. Fixes #144510.
2004-07-14 14:25:04 +00:00
|
|
|
* here. we create the group in the same chain as the loop-based element. note
|
2004-07-22 09:43:40 +00:00
|
|
|
* that creating a new group will not increment the links with other groups */
|
2004-03-15 19:24:35 +00:00
|
|
|
GST_DEBUG ("creating new group for element %s",
|
2004-04-03 13:24:07 +00:00
|
|
|
GST_ELEMENT_NAME (src_element));
|
2004-03-15 19:24:35 +00:00
|
|
|
group1 =
|
2004-04-03 13:24:07 +00:00
|
|
|
create_group (group2->chain, src_element,
|
2004-03-15 19:24:35 +00:00
|
|
|
GST_OPT_SCHEDULER_GROUP_LOOP);
|
2004-03-13 15:27:01 +00:00
|
|
|
} else {
|
2004-03-15 19:24:35 +00:00
|
|
|
/* both elements are already in a group, make sure they are added to
|
|
|
|
* the same chain */
|
|
|
|
merge_chains (group1->chain, group2->chain);
|
2002-09-08 17:58:00 +00:00
|
|
|
}
|
2004-07-22 09:43:40 +00:00
|
|
|
/* increment the group link counters */
|
|
|
|
group_inc_link (group1, group2);
|
2002-09-08 17:58:00 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case GST_OPT_INVALID:
|
2003-01-09 14:15:37 +00:00
|
|
|
g_error ("(internal error) invalid element link, what are you doing?");
|
2002-09-08 17:58:00 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
static void
|
|
|
|
group_elements_set_visited (GstOptSchedulerGroup * group, gboolean visited)
|
|
|
|
{
|
|
|
|
GSList *elements;
|
|
|
|
|
|
|
|
for (elements = group->elements; elements; elements = g_slist_next (elements)) {
|
|
|
|
GstElement *element = GST_ELEMENT (elements->data);
|
|
|
|
|
|
|
|
if (visited) {
|
|
|
|
GST_ELEMENT_SET_VISITED (element);
|
|
|
|
} else {
|
|
|
|
GST_ELEMENT_UNSET_VISITED (element);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static GList *
|
|
|
|
element_get_reachables_func (GstElement * element, GstOptSchedulerGroup * group,
|
2004-03-13 15:27:01 +00:00
|
|
|
GstPad * brokenpad)
|
2002-11-02 13:54:34 +00:00
|
|
|
{
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
GList *result = NULL;
|
2002-11-02 13:54:34 +00:00
|
|
|
const GList *pads;
|
|
|
|
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
/* if no element or element not in group or been there, return NULL */
|
2004-07-20 09:55:13 +00:00
|
|
|
if (element == NULL || !group_has_element (group, element) ||
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
GST_ELEMENT_IS_VISITED (element))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
GST_ELEMENT_SET_VISITED (element);
|
|
|
|
|
|
|
|
result = g_list_prepend (result, element);
|
|
|
|
|
2002-11-02 13:54:34 +00:00
|
|
|
pads = gst_element_get_pad_list (element);
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
while (pads) {
|
2003-12-13 16:58:29 +00:00
|
|
|
GstPad *pad = GST_PAD (pads->data);
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
GstPad *peer;
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2002-11-02 13:54:34 +00:00
|
|
|
pads = g_list_next (pads);
|
|
|
|
|
2002-12-15 12:18:04 +00:00
|
|
|
/* we only operate on real pads and on the pad that is not broken */
|
|
|
|
if (!GST_IS_REAL_PAD (pad) || pad == brokenpad)
|
2002-11-02 13:54:34 +00:00
|
|
|
continue;
|
|
|
|
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
peer = GST_PAD_PEER (pad);
|
|
|
|
if (!GST_IS_REAL_PAD (peer) || peer == brokenpad)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (peer) {
|
2002-12-15 12:18:04 +00:00
|
|
|
GstElement *parent;
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
GList *res;
|
2002-12-15 12:18:04 +00:00
|
|
|
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
parent = GST_PAD_PARENT (peer);
|
2002-12-15 12:18:04 +00:00
|
|
|
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
res = element_get_reachables_func (parent, group, brokenpad);
|
2002-12-15 22:52:48 +00:00
|
|
|
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
result = g_list_concat (result, res);
|
2004-03-13 15:27:01 +00:00
|
|
|
}
|
2002-11-02 13:54:34 +00:00
|
|
|
}
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GList *
|
|
|
|
element_get_reachables (GstElement * element, GstOptSchedulerGroup * group,
|
|
|
|
GstPad * brokenpad)
|
|
|
|
{
|
|
|
|
GList *result;
|
|
|
|
|
|
|
|
/* reset visited flags */
|
|
|
|
group_elements_set_visited (group, FALSE);
|
|
|
|
|
|
|
|
result = element_get_reachables_func (element, group, brokenpad);
|
|
|
|
|
|
|
|
/* and reset visited flags again */
|
|
|
|
group_elements_set_visited (group, FALSE);
|
|
|
|
|
|
|
|
return result;
|
2002-11-02 13:54:34 +00:00
|
|
|
}
|
|
|
|
|
2003-06-07 11:36:42 +00:00
|
|
|
/*
|
|
|
|
* checks if a target group is still reachable from the group without taking the broken
|
|
|
|
* group link into account.
|
|
|
|
*/
|
|
|
|
static gboolean
|
2004-03-13 15:27:01 +00:00
|
|
|
group_can_reach_group (GstOptSchedulerGroup * group,
|
|
|
|
GstOptSchedulerGroup * target)
|
2003-06-07 11:36:42 +00:00
|
|
|
{
|
|
|
|
gboolean reachable = FALSE;
|
|
|
|
const GSList *links = group->group_links;
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_LOG ("checking if group %p can reach %p", group, target);
|
2003-06-07 11:36:42 +00:00
|
|
|
|
|
|
|
/* seems like we found the target element */
|
|
|
|
if (group == target) {
|
2004-02-20 13:18:32 +00:00
|
|
|
GST_LOG ("found way to reach %p", target);
|
2003-06-07 11:36:42 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if the group is marked as visited, we don't need to check here */
|
2004-03-13 15:27:01 +00:00
|
|
|
if (GST_OPT_SCHEDULER_GROUP_IS_FLAG_SET (group,
|
2004-03-15 19:24:35 +00:00
|
|
|
GST_OPT_SCHEDULER_GROUP_VISITED)) {
|
2004-02-20 13:18:32 +00:00
|
|
|
GST_LOG ("already visited %p", group);
|
2003-06-07 11:36:42 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* mark group as visited */
|
|
|
|
GST_OPT_SCHEDULER_GROUP_SET_FLAG (group, GST_OPT_SCHEDULER_GROUP_VISITED);
|
|
|
|
|
|
|
|
while (links && !reachable) {
|
|
|
|
GstOptSchedulerGroupLink *link = (GstOptSchedulerGroupLink *) links->data;
|
|
|
|
GstOptSchedulerGroup *other;
|
|
|
|
|
|
|
|
links = g_slist_next (links);
|
|
|
|
|
|
|
|
/* find other group in this link */
|
|
|
|
other = OTHER_GROUP_LINK (link, group);
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_LOG ("found link from %p to %p, count %d", group, other, link->count);
|
2003-06-07 11:36:42 +00:00
|
|
|
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
/* check if we can reach the target recursively */
|
2003-06-07 11:36:42 +00:00
|
|
|
reachable = group_can_reach_group (other, target);
|
|
|
|
}
|
|
|
|
/* unset the visited flag, note that this is not optimal as we might be checking
|
|
|
|
* groups several times when they are reachable with a loop. An alternative would be
|
|
|
|
* to not clear the group flag at this stage but clear all flags in the chain when
|
|
|
|
* all groups are checked. */
|
|
|
|
GST_OPT_SCHEDULER_GROUP_UNSET_FLAG (group, GST_OPT_SCHEDULER_GROUP_VISITED);
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_LOG ("leaving group %p with %s", group, (reachable ? "TRUE" : "FALSE"));
|
2003-06-07 11:36:42 +00:00
|
|
|
|
|
|
|
return reachable;
|
|
|
|
}
|
|
|
|
|
2004-05-04 16:43:49 +00:00
|
|
|
/*
|
|
|
|
* Go through all the pads of the given element and decrement the links that
|
2004-05-27 09:33:29 +00:00
|
|
|
* this group has with the group of the peer element. This function is mainly used
|
|
|
|
* to update the group connections before we remove the element from the group.
|
2004-05-04 16:43:49 +00:00
|
|
|
*/
|
2004-03-10 16:47:06 +00:00
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
group_dec_links_for_element (GstOptSchedulerGroup * group, GstElement * element)
|
2004-03-10 16:47:06 +00:00
|
|
|
{
|
|
|
|
GList *l;
|
|
|
|
GstPad *pad;
|
|
|
|
GstOptSchedulerGroup *peer_group;
|
2004-03-13 15:27:01 +00:00
|
|
|
|
|
|
|
for (l = GST_ELEMENT_PADS (element); l; l = l->next) {
|
|
|
|
pad = (GstPad *) l->data;
|
2004-03-10 16:47:06 +00:00
|
|
|
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)
|
2004-03-15 19:24:35 +00:00
|
|
|
group_dec_link (group, peer_group);
|
2004-03-10 16:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-05-27 09:33:29 +00:00
|
|
|
/*
|
|
|
|
* Go through all the pads of the given element and increment the links that
|
|
|
|
* this group has with the group of the peer element. This function is mainly used
|
|
|
|
* to update the group connections before we add the element to the group.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
group_inc_links_for_element (GstOptSchedulerGroup * group, GstElement * element)
|
|
|
|
{
|
|
|
|
GList *l;
|
|
|
|
GstPad *pad;
|
|
|
|
GstOptSchedulerGroup *peer_group;
|
|
|
|
|
gst/schedulers/gstoptimalscheduler.c: Call group_inc_link with the proper src->sink ordering -- break this, and we br...
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (gst_opt_scheduler_init),
(create_chain), (destroy_chain), (create_group), (destroy_group),
(add_to_group), (merge_groups), (group_elements), (group_inc_link),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_inc_links_for_element), (group_migrate_connected):
Call group_inc_link with the proper src->sink ordering --
break this, and we break sort_chain. patch from wingo for bug
147713.
Partially revert patch 1.89. When adding a loop based element to
the scheduler, the links to other groups are automatically followed
and incremented. This should not happen because the bin will call
pad_link explicitly for those connection, resulting in them counted
twice. Results in assertion failure on pipeline cleanup.
2004-07-16 16:02:12 +00:00
|
|
|
GST_DEBUG ("group %p, element %s ", group, gst_element_get_name (element));
|
|
|
|
|
2004-05-27 09:33:29 +00:00
|
|
|
for (l = GST_ELEMENT_PADS (element); 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)
|
gst/schedulers/gstoptimalscheduler.c: Call group_inc_link with the proper src->sink ordering -- break this, and we br...
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (gst_opt_scheduler_init),
(create_chain), (destroy_chain), (create_group), (destroy_group),
(add_to_group), (merge_groups), (group_elements), (group_inc_link),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_inc_links_for_element), (group_migrate_connected):
Call group_inc_link with the proper src->sink ordering --
break this, and we break sort_chain. patch from wingo for bug
147713.
Partially revert patch 1.89. When adding a loop based element to
the scheduler, the links to other groups are automatically followed
and incremented. This should not happen because the bin will call
pad_link explicitly for those connection, resulting in them counted
twice. Results in assertion failure on pipeline cleanup.
2004-07-16 16:02:12 +00:00
|
|
|
if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC)
|
|
|
|
group_inc_link (group, peer_group);
|
|
|
|
else
|
|
|
|
group_inc_link (peer_group, group);
|
2004-05-27 09:33:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
static void
|
|
|
|
debug_element (GstElement * element, GstOptScheduler * osched)
|
|
|
|
{
|
|
|
|
GST_LOG ("element %s", gst_element_get_name (element));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* move this group in the chain of the groups it has links with */
|
|
|
|
static void
|
|
|
|
rechain_group (GstOptSchedulerGroup * group)
|
|
|
|
{
|
|
|
|
GstOptSchedulerChain *chain = NULL;
|
|
|
|
GSList *links;
|
|
|
|
|
|
|
|
GST_LOG ("checking if this group needs rechaining");
|
|
|
|
|
|
|
|
/* follow all links */
|
|
|
|
for (links = group->group_links; links; links = g_slist_next (links)) {
|
|
|
|
GstOptSchedulerGroupLink *link = (GstOptSchedulerGroupLink *) links->data;
|
|
|
|
GstOptSchedulerGroup *other;
|
|
|
|
|
|
|
|
other = OTHER_GROUP_LINK (link, group);
|
|
|
|
GST_LOG ("found link with other group %p with chain %p", other,
|
|
|
|
other->chain);
|
|
|
|
|
|
|
|
/* first time, take chain */
|
|
|
|
if (chain == NULL) {
|
|
|
|
chain = other->chain;
|
|
|
|
}
|
|
|
|
/* second time, chain should be the same */
|
|
|
|
else if (other->chain != chain) {
|
|
|
|
g_warning ("(internal error): chain inconsistency");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!chain) {
|
|
|
|
GST_LOG ("no new chain found, not rechaining");
|
|
|
|
} else if (chain != group->chain) {
|
|
|
|
GST_LOG ("need to move group %p to chain %p", group, chain);
|
|
|
|
/* remove from old chain */
|
|
|
|
remove_from_chain (group->chain, group);
|
|
|
|
/* and move to new chain */
|
|
|
|
add_to_chain (chain, group);
|
|
|
|
} else {
|
|
|
|
GST_LOG ("group %p is in correct chain %p", group, chain);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* migrate the element and all connected elements to a new group without looking at
|
|
|
|
* the brokenpad */
|
|
|
|
static GstOptSchedulerGroup *
|
|
|
|
group_migrate_connected (GstOptScheduler * osched, GstElement * element,
|
|
|
|
GstOptSchedulerGroup * group, GstPad * brokenpad)
|
|
|
|
{
|
|
|
|
GList *connected, *c;
|
2004-07-14 15:10:09 +00:00
|
|
|
GstOptSchedulerGroup *new_group = NULL, *tst;
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
GstOptSchedulerChain *chain;
|
2004-07-09 08:25:42 +00:00
|
|
|
gint len;
|
|
|
|
|
|
|
|
if (GST_ELEMENT_IS_DECOUPLED (element)) {
|
2004-07-20 09:55:13 +00:00
|
|
|
GST_LOG ("element is decoupled and thus not in the group");
|
2004-07-09 08:25:42 +00:00
|
|
|
/* the element is decoupled and is therefore not in the group */
|
|
|
|
return NULL;
|
|
|
|
}
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
|
2004-07-14 15:10:09 +00:00
|
|
|
get_group (element, &tst);
|
|
|
|
if (tst == NULL) {
|
|
|
|
GST_LOG ("element has no group, not interesting");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
GST_LOG ("migrate connected elements to new group");
|
|
|
|
connected = element_get_reachables (element, group, brokenpad);
|
|
|
|
GST_LOG ("elements to move to new group:");
|
|
|
|
g_list_foreach (connected, (GFunc) debug_element, NULL);
|
|
|
|
|
2004-07-09 08:25:42 +00:00
|
|
|
len = g_list_length (connected);
|
|
|
|
|
|
|
|
if (len == 0) {
|
|
|
|
g_warning ("(internal error) found lost element %s",
|
|
|
|
gst_element_get_name (element));
|
|
|
|
return NULL;
|
|
|
|
} else if (len == 1) {
|
2004-07-20 09:55:13 +00:00
|
|
|
group = remove_from_group (group, GST_ELEMENT (connected->data));
|
2004-07-14 14:52:49 +00:00
|
|
|
GST_LOG
|
|
|
|
("not migrating to new group as the group would only contain 1 element");
|
2004-07-09 08:25:42 +00:00
|
|
|
g_list_free (connected);
|
2004-07-14 14:52:49 +00:00
|
|
|
GST_LOG ("new group is old group now");
|
|
|
|
new_group = group;
|
|
|
|
} else {
|
|
|
|
/* we create a new chain to hold the new group */
|
|
|
|
chain = create_chain (osched);
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
|
2004-07-14 14:52:49 +00:00
|
|
|
for (c = connected; c; c = g_list_next (c)) {
|
|
|
|
GstElement *element = GST_ELEMENT (c->data);
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
|
2004-07-14 14:52:49 +00:00
|
|
|
group = remove_from_group (group, element);
|
|
|
|
if (new_group == NULL) {
|
|
|
|
new_group =
|
|
|
|
create_group (chain, element, GST_OPT_SCHEDULER_GROUP_UNKNOWN);
|
|
|
|
} else {
|
gst/schedulers/gstoptimalscheduler.c: Call group_inc_link with the proper src->sink ordering -- break this, and we br...
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (gst_opt_scheduler_init),
(create_chain), (destroy_chain), (create_group), (destroy_group),
(add_to_group), (merge_groups), (group_elements), (group_inc_link),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_inc_links_for_element), (group_migrate_connected):
Call group_inc_link with the proper src->sink ordering --
break this, and we break sort_chain. patch from wingo for bug
147713.
Partially revert patch 1.89. When adding a loop based element to
the scheduler, the links to other groups are automatically followed
and incremented. This should not happen because the bin will call
pad_link explicitly for those connection, resulting in them counted
twice. Results in assertion failure on pipeline cleanup.
2004-07-16 16:02:12 +00:00
|
|
|
add_to_group (new_group, element, TRUE);
|
2004-07-14 14:52:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
g_list_free (connected);
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
|
2004-07-14 14:52:49 +00:00
|
|
|
/* remove last element from the group if any. Make sure not to remove
|
|
|
|
* the loop based entry point of a group as this always needs one group */
|
|
|
|
if (group != NULL) {
|
2004-07-20 09:55:13 +00:00
|
|
|
if (group_num_elements (group) == 1 &&
|
2004-07-14 14:52:49 +00:00
|
|
|
group->type != GST_OPT_SCHEDULER_GROUP_LOOP) {
|
|
|
|
GST_LOG ("removing last element from old group");
|
|
|
|
group = remove_from_group (group, GST_ELEMENT (group->elements->data));
|
|
|
|
}
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-07-20 09:55:13 +00:00
|
|
|
if (new_group != NULL) {
|
|
|
|
if (group_num_elements (new_group) == 1 &&
|
|
|
|
new_group->type != GST_OPT_SCHEDULER_GROUP_LOOP) {
|
|
|
|
GST_LOG ("removing last element from new group");
|
|
|
|
new_group =
|
|
|
|
remove_from_group (new_group,
|
|
|
|
GST_ELEMENT (new_group->elements->data));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
/* at this point the new group lives in its own chain but might
|
|
|
|
* have to be merged with another chain, this happens when the new
|
|
|
|
* group has a link with another group in another chain */
|
|
|
|
rechain_group (new_group);
|
gst/schedulers/gstoptimalscheduler.c: move isolated groups to a new chain.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (create_group),
(add_to_group), (merge_groups), (schedule_group),
(gst_opt_scheduler_get_wrapper), (group_elements),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_migrate_connected), (gst_opt_scheduler_pad_unlink),
(gst_opt_scheduler_iterate):
move isolated groups to a new chain.
Emit a warning instead of segfaulting in some error cases.
Fix a bug where the link count between groups was not calculated
correctly. Fixes #144510.
2004-07-14 14:25:04 +00:00
|
|
|
}
|
|
|
|
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
|
|
|
|
return new_group;
|
|
|
|
}
|
|
|
|
|
2002-09-08 17:58:00 +00:00
|
|
|
static void
|
2004-03-15 19:24:35 +00:00
|
|
|
gst_opt_scheduler_pad_unlink (GstScheduler * sched,
|
|
|
|
GstPad * srcpad, GstPad * sinkpad)
|
2002-09-08 17:58:00 +00:00
|
|
|
{
|
2003-12-13 16:58:29 +00:00
|
|
|
GstOptScheduler *osched = GST_OPT_SCHEDULER (sched);
|
2004-04-03 13:24:07 +00:00
|
|
|
GstElement *src_element, *sink_element;
|
2002-11-02 13:54:34 +00:00
|
|
|
GstOptSchedulerGroup *group1, *group2;
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_INFO ("unscheduling link between %s:%s and %s:%s",
|
|
|
|
GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2004-04-03 13:24:07 +00:00
|
|
|
src_element = GST_PAD_PARENT (srcpad);
|
|
|
|
sink_element = GST_PAD_PARENT (sinkpad);
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2004-04-03 13:24:07 +00:00
|
|
|
get_group (src_element, &group1);
|
|
|
|
get_group (sink_element, &group2);
|
2002-11-02 13:54:34 +00:00
|
|
|
|
2003-03-13 18:46:21 +00:00
|
|
|
/* for decoupled elements (that are never put into a group) we use the
|
|
|
|
* group of the peer element for the remainder of the algorithm */
|
2004-04-03 13:24:07 +00:00
|
|
|
if (GST_ELEMENT_IS_DECOUPLED (src_element)) {
|
2003-03-13 18:46:21 +00:00
|
|
|
group1 = group2;
|
|
|
|
}
|
2004-04-03 13:24:07 +00:00
|
|
|
if (GST_ELEMENT_IS_DECOUPLED (sink_element)) {
|
2003-03-13 18:46:21 +00:00
|
|
|
group2 = group1;
|
|
|
|
}
|
|
|
|
|
2002-12-15 12:18:04 +00:00
|
|
|
/* if one the elements has no group (anymore) we don't really care
|
2003-01-09 14:15:37 +00:00
|
|
|
* about the link */
|
2002-12-15 12:18:04 +00:00
|
|
|
if (!group1 || !group2) {
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_LOG
|
2004-03-15 19:24:35 +00:00
|
|
|
("one (or both) of the elements is not in a group, not interesting");
|
2002-11-02 13:54:34 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-12-15 12:18:04 +00:00
|
|
|
/* easy part, groups are different */
|
|
|
|
if (group1 != group2) {
|
2003-06-07 11:36:42 +00:00
|
|
|
gboolean zero;
|
|
|
|
|
2004-02-20 13:18:32 +00:00
|
|
|
GST_LOG ("elements are in different groups");
|
2002-12-15 22:02:20 +00:00
|
|
|
|
2003-06-07 11:36:42 +00:00
|
|
|
/* we can remove the links between the groups now */
|
|
|
|
zero = group_dec_link (group1, group2);
|
|
|
|
|
2004-04-03 13:24:07 +00:00
|
|
|
/* if the groups are not directly connected anymore, we have to perform a
|
|
|
|
* recursive check to see if they are really unlinked */
|
2003-06-07 11:36:42 +00:00
|
|
|
if (zero) {
|
|
|
|
gboolean still_link;
|
|
|
|
GstOptSchedulerChain *chain;
|
|
|
|
|
|
|
|
/* see if group1 and group2 are still connected in any indirect way */
|
|
|
|
still_link = group_can_reach_group (group1, group2);
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_DEBUG ("group %p %s reach group %p", group1,
|
2004-03-15 19:24:35 +00:00
|
|
|
(still_link ? "can" : "can't"), group2);
|
2003-06-07 11:36:42 +00:00
|
|
|
if (!still_link) {
|
2004-03-15 19:24:35 +00:00
|
|
|
/* groups are really disconnected, migrate one group to a new chain */
|
|
|
|
chain = create_chain (osched);
|
|
|
|
chain_recursively_migrate_group (chain, group1);
|
2003-06-07 11:36:42 +00:00
|
|
|
|
2004-03-15 19:24:35 +00:00
|
|
|
GST_DEBUG ("migrated group %p to new chain %p", group1, chain);
|
2003-06-07 11:36:42 +00:00
|
|
|
}
|
2004-03-13 15:27:01 +00:00
|
|
|
} else {
|
|
|
|
GST_DEBUG ("group %p still has direct link with group %p", group1,
|
2004-03-15 19:24:35 +00:00
|
|
|
group2);
|
2003-06-07 11:36:42 +00:00
|
|
|
}
|
2002-11-02 13:54:34 +00:00
|
|
|
}
|
2002-12-15 12:18:04 +00:00
|
|
|
/* hard part, groups are equal */
|
2002-11-02 13:54:34 +00:00
|
|
|
else {
|
2002-12-15 22:02:20 +00:00
|
|
|
GstOptSchedulerGroup *group;
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2002-12-15 22:02:20 +00:00
|
|
|
/* since group1 == group2, it doesn't matter which group we take */
|
|
|
|
group = group1;
|
2002-12-15 12:18:04 +00:00
|
|
|
|
2004-02-20 13:18:32 +00:00
|
|
|
GST_LOG ("elements are in the same group %p", group);
|
2002-12-15 12:18:04 +00:00
|
|
|
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
if (group->entry == NULL) {
|
|
|
|
/* it doesn't really matter, we just have to make sure that both
|
|
|
|
* elements end up in another group if they are not connected */
|
|
|
|
GST_LOG ("group %p has no entry, moving source element to new group",
|
|
|
|
group);
|
|
|
|
group_migrate_connected (osched, src_element, group, srcpad);
|
|
|
|
} else {
|
|
|
|
GList *reachables;
|
2004-03-15 19:24:35 +00:00
|
|
|
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
GST_LOG ("group %p has entry %p", group, group->entry);
|
2002-12-15 12:18:04 +00:00
|
|
|
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
/* get of a list of all elements that are still managed by the old
|
|
|
|
* entry element */
|
|
|
|
reachables = element_get_reachables (group->entry, group, srcpad);
|
|
|
|
GST_LOG ("elements still reachable from the entry:");
|
|
|
|
g_list_foreach (reachables, (GFunc) debug_element, sched);
|
2004-03-15 19:24:35 +00:00
|
|
|
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
/* if the source is reachable from the entry, we can leave it in the group */
|
|
|
|
if (g_list_find (reachables, src_element)) {
|
|
|
|
GST_LOG
|
|
|
|
("source element still reachable from the entry, leaving in group");
|
2004-03-15 19:24:35 +00:00
|
|
|
} else {
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
GST_LOG
|
|
|
|
("source element not reachable from the entry, moving to new group");
|
|
|
|
group_migrate_connected (osched, src_element, group, srcpad);
|
2004-03-15 19:24:35 +00:00
|
|
|
}
|
|
|
|
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
/* if the sink is reachable from the entry, we can leave it in the group */
|
|
|
|
if (g_list_find (reachables, sink_element)) {
|
|
|
|
GST_LOG
|
|
|
|
("sink element still reachable from the entry, leaving in group");
|
2004-03-15 19:24:35 +00:00
|
|
|
} else {
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
GST_LOG
|
|
|
|
("sink element not reachable from the entry, moving to new group");
|
|
|
|
group_migrate_connected (osched, sink_element, group, srcpad);
|
2004-03-15 19:24:35 +00:00
|
|
|
}
|
Implemented group splitting and rechaining.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c:
(chain_recursively_migrate_group), (create_group),
(schedule_group), (gst_opt_scheduler_pad_link),
(group_elements_set_visited), (element_get_reachables_func),
(element_get_reachables), (group_can_reach_group), (debug_element),
(rechain_group), (group_migrate_connected),
(gst_opt_scheduler_pad_unlink):
* testsuite/schedulers/Makefile.am:
Implemented group splitting and rechaining.
Fixes 143777 and 143777-2 in the testsuite.
2004-07-08 15:24:20 +00:00
|
|
|
g_list_free (reachables);
|
|
|
|
}
|
gst/schedulers/gstoptimalscheduler.c: move isolated groups to a new chain.
Original commit message from CVS:
* gst/schedulers/gstoptimalscheduler.c: (create_group),
(add_to_group), (merge_groups), (schedule_group),
(gst_opt_scheduler_get_wrapper), (group_elements),
(group_dec_link), (gst_opt_scheduler_pad_link),
(group_migrate_connected), (gst_opt_scheduler_pad_unlink),
(gst_opt_scheduler_iterate):
move isolated groups to a new chain.
Emit a warning instead of segfaulting in some error cases.
Fix a bug where the link count between groups was not calculated
correctly. Fixes #144510.
2004-07-14 14:25:04 +00:00
|
|
|
/* at this point the group can be freed and gone, so don't touch */
|
2002-11-02 13:54:34 +00:00
|
|
|
}
|
2002-09-08 17:58:00 +00:00
|
|
|
}
|
|
|
|
|
2002-09-12 19:22:03 +00:00
|
|
|
/* a scheduler iteration is done by looping and scheduling the active chains */
|
2002-09-08 17:58:00 +00:00
|
|
|
static GstSchedulerState
|
2004-03-13 15:27:01 +00:00
|
|
|
gst_opt_scheduler_iterate (GstScheduler * sched)
|
2002-09-08 17:58:00 +00:00
|
|
|
{
|
2002-09-12 19:22:03 +00:00
|
|
|
GstSchedulerState state = GST_SCHEDULER_STATE_STOPPED;
|
2003-12-13 16:58:29 +00:00
|
|
|
GstOptScheduler *osched = GST_OPT_SCHEDULER (sched);
|
2002-09-12 19:22:03 +00:00
|
|
|
gint iterations = osched->iterations;
|
2002-09-08 17:58:00 +00:00
|
|
|
|
|
|
|
osched->state = GST_OPT_SCHEDULER_STATE_RUNNING;
|
|
|
|
|
2004-03-07 14:33:13 +00:00
|
|
|
GST_DEBUG_OBJECT (sched, "iterating");
|
2004-02-20 13:18:32 +00:00
|
|
|
|
2002-09-12 19:22:03 +00:00
|
|
|
while (iterations) {
|
|
|
|
gboolean scheduled = FALSE;
|
|
|
|
GSList *chains;
|
|
|
|
|
|
|
|
/* we have to schedule each of the scheduler chains now */
|
|
|
|
chains = osched->chains;
|
|
|
|
while (chains) {
|
|
|
|
GstOptSchedulerChain *chain = (GstOptSchedulerChain *) chains->data;
|
2002-09-08 17:58:00 +00:00
|
|
|
|
2003-02-27 23:07:30 +00:00
|
|
|
ref_chain (chain);
|
2002-09-12 19:22:03 +00:00
|
|
|
/* if the chain is not disabled, schedule it */
|
|
|
|
if (!GST_OPT_SCHEDULER_CHAIN_IS_DISABLED (chain)) {
|
2004-03-15 19:24:35 +00:00
|
|
|
GST_LOG ("scheduling chain %p", chain);
|
|
|
|
schedule_chain (chain);
|
|
|
|
scheduled = TRUE;
|
gst/autoplug/gstspideridentity.c: extra debugging
Original commit message from CVS:
* gst/autoplug/gstspideridentity.c: (gst_spider_identity_chain):
extra debugging
* gst/gstevent.h:
* gst/gstinfo.c: (gst_debug_log_default):
print time nicely. add thread pointer until someone figures out
a completely portable way of getting at thread id's.
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_try),
(_invent_event), (gst_pad_pull), (gst_pad_event_default_dispatch),
(gst_pad_call_chain_function):
extra debugging
* gst/schedulers/gstoptimalscheduler.c:
(get_group_schedule_function), (loop_group_schedule_function),
(gst_opt_scheduler_loop_wrapper), (gst_opt_scheduler_get_wrapper),
(pad_clear_queued), (gst_opt_scheduler_iterate):
rename BUFPEN and friends to DATAPEN since that's what they are.
2004-07-08 13:49:14 +00:00
|
|
|
GST_LOG ("scheduled chain %p", chain);
|
2004-05-27 09:33:29 +00:00
|
|
|
} else {
|
|
|
|
GST_LOG ("not scheduling disabled chain %p", chain);
|
2002-09-12 19:22:03 +00:00
|
|
|
}
|
2003-01-08 21:33:20 +00:00
|
|
|
|
2003-01-12 20:28:08 +00:00
|
|
|
/* don't schedule any more chains when in error */
|
2003-01-20 23:11:51 +00:00
|
|
|
if (osched->state == GST_OPT_SCHEDULER_STATE_ERROR) {
|
2004-03-15 19:24:35 +00:00
|
|
|
GST_ERROR_OBJECT (sched, "in error state");
|
|
|
|
break;
|
2004-03-13 15:27:01 +00:00
|
|
|
} else if (osched->state == GST_OPT_SCHEDULER_STATE_INTERRUPTED) {
|
2004-03-15 19:24:35 +00:00
|
|
|
GST_DEBUG_OBJECT (osched, "got interrupted, continue with next chain");
|
|
|
|
osched->state = GST_OPT_SCHEDULER_STATE_RUNNING;
|
2003-01-20 23:11:51 +00:00
|
|
|
}
|
2003-02-27 23:07:30 +00:00
|
|
|
|
|
|
|
chains = g_slist_next (chains);
|
|
|
|
unref_chain (chain);
|
2002-09-08 17:58:00 +00:00
|
|
|
}
|
|
|
|
|
2002-09-12 19:22:03 +00:00
|
|
|
/* at this point it's possible that the scheduler state is
|
|
|
|
* in error, we then return an error */
|
|
|
|
if (osched->state == GST_OPT_SCHEDULER_STATE_ERROR) {
|
|
|
|
state = GST_SCHEDULER_STATE_ERROR;
|
|
|
|
break;
|
2004-03-13 15:27:01 +00:00
|
|
|
} else {
|
2002-09-12 19:22:03 +00:00
|
|
|
/* if chains were scheduled, return our current state */
|
|
|
|
if (scheduled)
|
2004-03-15 19:24:35 +00:00
|
|
|
state = GST_SCHEDULER_STATE (sched);
|
2002-09-12 19:22:03 +00:00
|
|
|
/* if no chains were scheduled, we say we are stopped */
|
|
|
|
else {
|
2004-03-15 19:24:35 +00:00
|
|
|
state = GST_SCHEDULER_STATE_STOPPED;
|
|
|
|
break;
|
2002-09-12 19:22:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (iterations > 0)
|
|
|
|
iterations--;
|
2002-09-08 17:58:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
gst_opt_scheduler_show (GstScheduler * sched)
|
2002-09-08 17:58:00 +00:00
|
|
|
{
|
2003-12-13 16:58:29 +00:00
|
|
|
GstOptScheduler *osched = GST_OPT_SCHEDULER (sched);
|
2002-09-08 22:42:29 +00:00
|
|
|
GSList *chains;
|
|
|
|
|
2003-01-01 04:28:33 +00:00
|
|
|
g_print ("iterations: %d\n", osched->iterations);
|
|
|
|
g_print ("max recursion: %d\n", osched->max_recursion);
|
|
|
|
|
2002-09-08 22:42:29 +00:00
|
|
|
chains = osched->chains;
|
|
|
|
while (chains) {
|
|
|
|
GstOptSchedulerChain *chain = (GstOptSchedulerChain *) chains->data;
|
|
|
|
GSList *groups = chain->groups;
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2002-09-08 22:42:29 +00:00
|
|
|
chains = g_slist_next (chains);
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
g_print ("+- chain %p: refcount %d, %d groups, %d enabled, flags %d\n",
|
2004-03-15 19:24:35 +00:00
|
|
|
chain, chain->refcount, chain->num_groups, chain->num_enabled,
|
|
|
|
chain->flags);
|
2002-09-08 22:42:29 +00:00
|
|
|
|
|
|
|
while (groups) {
|
|
|
|
GstOptSchedulerGroup *group = (GstOptSchedulerGroup *) groups->data;
|
|
|
|
GSList *elements = group->elements;
|
2004-05-27 09:33:29 +00:00
|
|
|
GSList *group_links = group->group_links;
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2002-09-08 22:42:29 +00:00
|
|
|
groups = g_slist_next (groups);
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
g_print
|
2004-03-15 19:24:35 +00:00
|
|
|
(" +- group %p: refcount %d, %d elements, %d enabled, flags %d, entry %s, %s\n",
|
|
|
|
group, group->refcount, group->num_elements, group->num_enabled,
|
|
|
|
group->flags,
|
|
|
|
(group->entry ? GST_ELEMENT_NAME (group->entry) : "(none)"),
|
|
|
|
(group->type ==
|
|
|
|
GST_OPT_SCHEDULER_GROUP_GET ? "get-based" : "loop-based"));
|
2002-09-08 22:42:29 +00:00
|
|
|
|
|
|
|
while (elements) {
|
2004-03-15 19:24:35 +00:00
|
|
|
GstElement *element = (GstElement *) elements->data;
|
2002-09-08 22:42:29 +00:00
|
|
|
|
2004-03-15 19:24:35 +00:00
|
|
|
elements = g_slist_next (elements);
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2004-03-15 19:24:35 +00:00
|
|
|
g_print (" +- element %s\n", GST_ELEMENT_NAME (element));
|
2002-09-08 22:42:29 +00:00
|
|
|
}
|
2004-05-27 09:33:29 +00:00
|
|
|
while (group_links) {
|
|
|
|
GstOptSchedulerGroupLink *link =
|
|
|
|
(GstOptSchedulerGroupLink *) group_links->data;
|
|
|
|
|
|
|
|
group_links = g_slist_next (group_links);
|
|
|
|
|
|
|
|
g_print ("group link %p between %p and %p, count %d\n",
|
|
|
|
link, link->src, link->sink, link->count);
|
|
|
|
}
|
2002-09-08 22:42:29 +00:00
|
|
|
}
|
|
|
|
}
|
2002-09-08 17:58:00 +00:00
|
|
|
}
|
2002-09-12 19:22:03 +00:00
|
|
|
|
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
gst_opt_scheduler_get_property (GObject * object, guint prop_id,
|
|
|
|
GValue * value, GParamSpec * pspec)
|
2002-09-12 19:22:03 +00:00
|
|
|
{
|
|
|
|
GstOptScheduler *osched;
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2002-09-12 19:22:03 +00:00
|
|
|
g_return_if_fail (GST_IS_OPT_SCHEDULER (object));
|
|
|
|
|
2003-12-13 16:58:29 +00:00
|
|
|
osched = GST_OPT_SCHEDULER (object);
|
2002-09-12 19:22:03 +00:00
|
|
|
|
|
|
|
switch (prop_id) {
|
|
|
|
case ARG_ITERATIONS:
|
|
|
|
g_value_set_int (value, osched->iterations);
|
|
|
|
break;
|
2003-01-01 04:28:33 +00:00
|
|
|
case ARG_MAX_RECURSION:
|
|
|
|
g_value_set_int (value, osched->max_recursion);
|
|
|
|
break;
|
2002-09-12 19:22:03 +00:00
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-03-13 15:27:01 +00:00
|
|
|
gst_opt_scheduler_set_property (GObject * object, guint prop_id,
|
|
|
|
const GValue * value, GParamSpec * pspec)
|
2002-09-12 19:22:03 +00:00
|
|
|
{
|
|
|
|
GstOptScheduler *osched;
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2002-09-12 19:22:03 +00:00
|
|
|
g_return_if_fail (GST_IS_OPT_SCHEDULER (object));
|
|
|
|
|
2003-12-13 16:58:29 +00:00
|
|
|
osched = GST_OPT_SCHEDULER (object);
|
2002-09-12 19:22:03 +00:00
|
|
|
|
|
|
|
switch (prop_id) {
|
|
|
|
case ARG_ITERATIONS:
|
|
|
|
osched->iterations = g_value_get_int (value);
|
|
|
|
break;
|
2003-01-01 04:28:33 +00:00
|
|
|
case ARG_MAX_RECURSION:
|
|
|
|
osched->max_recursion = g_value_get_int (value);
|
|
|
|
break;
|
2002-09-12 19:22:03 +00:00
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|