mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 02:01:12 +00:00
Some more work on cleanup.
Original commit message from CVS: Some more work on cleanup. - added two functions in the scheduler _setup and _reset to initialize the context. In the case of the cothread context we have to map the cothread stack space onto the threads stack. - setup/reset the scheduler context in the threads context. - fix the ghostpad cleanup. - slightly changed the scheduler code to cleanly remove connections.
This commit is contained in:
parent
23eb626391
commit
5ad018148c
9 changed files with 126 additions and 42 deletions
|
@ -116,12 +116,14 @@ cothread_free (cothread_context *ctx)
|
|||
if (ctx->threads[i]->lock) {
|
||||
g_mutex_unlock(ctx->threads[i]->lock);
|
||||
g_mutex_free (ctx->threads[i]->lock);
|
||||
ctx->threads[i]->lock = NULL;
|
||||
}
|
||||
#endif
|
||||
if (i == 0)
|
||||
if (i == 0) {
|
||||
g_free (ctx->threads[i]);
|
||||
ctx->threads[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
g_hash_table_destroy (ctx->data);
|
||||
g_free (ctx);
|
||||
}
|
||||
|
|
11
gst/gstbin.c
11
gst/gstbin.c
|
@ -215,6 +215,12 @@ gst_bin_unset_element_sched (GstElement * element)
|
|||
g_return_if_fail (element != NULL);
|
||||
g_return_if_fail (GST_IS_ELEMENT (element));
|
||||
|
||||
if (GST_ELEMENT_SCHED (element) == NULL) {
|
||||
GST_INFO (GST_CAT_SCHEDULING, "element \"%s\" has no scheduler",
|
||||
GST_ELEMENT_NAME (element));
|
||||
return;
|
||||
}
|
||||
|
||||
GST_INFO (GST_CAT_SCHEDULING, "removing element \"%s\" from it sched %p",
|
||||
GST_ELEMENT_NAME (element), GST_ELEMENT_SCHED (element));
|
||||
|
||||
|
@ -335,11 +341,6 @@ gst_bin_remove (GstBin * bin, GstElement * element)
|
|||
GST_ELEMENT_NAME (bin));
|
||||
return;
|
||||
}
|
||||
#ifdef USE_GLIB2
|
||||
g_signal_handlers_disconnect_matched (G_OBJECT (element),
|
||||
G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, 0, 0, NULL,
|
||||
gst_bin_child_state_change, bin);
|
||||
#endif
|
||||
|
||||
/* remove this element from the list of managed elements */
|
||||
gst_bin_unset_element_sched (element);
|
||||
|
|
25
gst/gstpad.c
25
gst/gstpad.c
|
@ -534,9 +534,11 @@ gst_pad_disconnect (GstPad *srcpad,
|
|||
GST_RPAD_PEER(realsrc) = NULL;
|
||||
GST_RPAD_PEER(realsink) = NULL;
|
||||
|
||||
// now tell the scheduler
|
||||
if (realsrc->sched)
|
||||
gst_scheduler_pad_disconnect (realsrc->sched, (GstPad *)realsrc, (GstPad *)realsink);
|
||||
/* now tell the scheduler */
|
||||
if (GST_PAD_PARENT (realsrc)->sched)
|
||||
gst_scheduler_pad_disconnect (GST_PAD_PARENT (realsrc)->sched, (GstPad *)realsrc, (GstPad *)realsink);
|
||||
else if (GST_PAD_PARENT (realsink)->sched)
|
||||
gst_scheduler_pad_disconnect (GST_PAD_PARENT (realsink)->sched, (GstPad *)realsrc, (GstPad *)realsink);
|
||||
|
||||
/* fire off a signal to each of the pads telling them that they've been disconnected */
|
||||
g_signal_emit(G_OBJECT(realsrc), gst_real_pad_signals[REAL_DISCONNECTED], 0, realsink);
|
||||
|
@ -714,7 +716,8 @@ gst_pad_get_padtemplate (GstPad *pad)
|
|||
return GST_PAD_PADTEMPLATE (pad);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
/*
|
||||
* gst_pad_set_sched:
|
||||
* @pad: the pad to set the scheduler for
|
||||
* @sched: The scheduler to set
|
||||
|
@ -1036,11 +1039,6 @@ gst_real_pad_dispose (GObject *object)
|
|||
gst_pad_disconnect (pad, GST_PAD (GST_PAD_PEER (pad)));
|
||||
}
|
||||
|
||||
if (GST_IS_ELEMENT (GST_OBJECT_PARENT (pad))){
|
||||
GST_DEBUG (GST_CAT_REFCOUNTING, "removing pad from element '%s'\n",GST_OBJECT_NAME(GST_OBJECT (GST_ELEMENT (GST_OBJECT_PARENT (pad)))));
|
||||
gst_element_remove_pad (GST_ELEMENT (GST_OBJECT_PARENT (pad)), pad);
|
||||
}
|
||||
|
||||
/* FIXME we should destroy the ghostpads, because they are nothing without the real pad */
|
||||
if (GST_REAL_PAD (pad)->ghostpads) {
|
||||
GList *orig, *ghostpads;
|
||||
|
@ -1052,7 +1050,7 @@ gst_real_pad_dispose (GObject *object)
|
|||
|
||||
if (GST_IS_ELEMENT (GST_OBJECT_PARENT (ghostpad))){
|
||||
GST_DEBUG (GST_CAT_REFCOUNTING, "removing ghost pad from element '%s'\n", GST_OBJECT_NAME(GST_OBJECT_PARENT (ghostpad)));
|
||||
gst_element_remove_pad (GST_ELEMENT (GST_OBJECT_PARENT (ghostpad)), ghostpad);
|
||||
gst_element_remove_ghost_pad (GST_ELEMENT (GST_OBJECT_PARENT (ghostpad)), GST_PAD (ghostpad));
|
||||
}
|
||||
ghostpads = g_list_next (ghostpads);
|
||||
}
|
||||
|
@ -1060,6 +1058,11 @@ gst_real_pad_dispose (GObject *object)
|
|||
g_list_free (GST_REAL_PAD(pad)->ghostpads);
|
||||
}
|
||||
|
||||
if (GST_IS_ELEMENT (GST_OBJECT_PARENT (pad))){
|
||||
GST_DEBUG (GST_CAT_REFCOUNTING, "removing pad from element '%s'\n",GST_OBJECT_NAME(GST_OBJECT (GST_ELEMENT (GST_OBJECT_PARENT (pad)))));
|
||||
gst_element_remove_pad (GST_ELEMENT (GST_OBJECT_PARENT (pad)), pad);
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (real_pad_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
|
@ -1579,7 +1582,7 @@ gst_pad_select (GList *padlist)
|
|||
{
|
||||
GstPad *pad;
|
||||
|
||||
pad = gst_scheduler_pad_select (gst_pad_get_sched (GST_PAD (padlist->data)), padlist);
|
||||
pad = gst_scheduler_pad_select (GST_PAD_PARENT (padlist->data)->sched, padlist);
|
||||
|
||||
return pad;
|
||||
}
|
||||
|
|
|
@ -97,15 +97,21 @@ gst_pipeline_class_init (GstPipelineClass *klass)
|
|||
static void
|
||||
gst_pipeline_init (GstPipeline *pipeline)
|
||||
{
|
||||
GstScheduler *scheduler;
|
||||
|
||||
/* we're a manager by default */
|
||||
GST_FLAG_SET (pipeline, GST_BIN_FLAG_MANAGER);
|
||||
|
||||
GST_ELEMENT_SCHED (pipeline) = gst_schedulerfactory_make ("basic", GST_ELEMENT (pipeline));
|
||||
scheduler = gst_schedulerfactory_make ("basic", GST_ELEMENT (pipeline));
|
||||
|
||||
gst_object_ref (GST_OBJECT (GST_ELEMENT_SCHED (pipeline)));
|
||||
gst_object_sink (GST_OBJECT (GST_ELEMENT_SCHED (pipeline)));
|
||||
GST_ELEMENT_SCHED (pipeline) = scheduler;
|
||||
|
||||
GST_DEBUG (GST_CAT_PIPELINE, "pipeline's scheduler is %p\n", GST_ELEMENT_SCHED (pipeline));
|
||||
gst_object_ref (GST_OBJECT (scheduler));
|
||||
gst_object_sink (GST_OBJECT (scheduler));
|
||||
|
||||
gst_scheduler_setup (scheduler);
|
||||
|
||||
GST_DEBUG (GST_CAT_PIPELINE, "pipeline's scheduler is %p\n", scheduler);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -115,6 +121,7 @@ gst_pipeline_dispose (GObject *object)
|
|||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
|
||||
gst_scheduler_reset (GST_ELEMENT_SCHED (pipeline));
|
||||
gst_object_unref (GST_OBJECT (GST_ELEMENT_SCHED (pipeline)));
|
||||
}
|
||||
|
||||
|
|
|
@ -67,6 +67,32 @@ gst_scheduler_init (GstScheduler *sched)
|
|||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_scheduler_setup:
|
||||
* @sched: the schedulerr
|
||||
*
|
||||
* Prepare the scheduler.
|
||||
*/
|
||||
void
|
||||
gst_scheduler_setup (GstScheduler *sched)
|
||||
{
|
||||
if (CLASS (sched)->setup)
|
||||
CLASS (sched)->setup (sched);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_scheduler_reset:
|
||||
* @sched: the schedulerr
|
||||
*
|
||||
* Reset the scheduler
|
||||
*/
|
||||
void
|
||||
gst_scheduler_reset (GstScheduler *sched)
|
||||
{
|
||||
if (CLASS (sched)->reset)
|
||||
CLASS (sched)->reset (sched);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_scheduler_pad_connect:
|
||||
* @sched: the schedulerr
|
||||
|
|
|
@ -65,6 +65,8 @@ struct _GstScheduler {
|
|||
struct _GstSchedulerClass {
|
||||
GstObjectClass parent_class;
|
||||
|
||||
void (*setup) (GstScheduler *sched);
|
||||
void (*reset) (GstScheduler *sched);
|
||||
void (*add_element) (GstScheduler *sched, GstElement *element);
|
||||
void (*remove_element) (GstScheduler *sched, GstElement *element);
|
||||
void (*enable_element) (GstScheduler *sched, GstElement *element);
|
||||
|
@ -84,6 +86,8 @@ GType gst_scheduler_get_type (void);
|
|||
|
||||
#define gst_scheduler_destroy(sched) gst_object_destroy(GST_OBJECT(sched))
|
||||
|
||||
void gst_scheduler_setup (GstScheduler *sched);
|
||||
void gst_scheduler_reset (GstScheduler *sched);
|
||||
void gst_scheduler_add_element (GstScheduler *sched, GstElement *element);
|
||||
void gst_scheduler_remove_element (GstScheduler *sched, GstElement *element);
|
||||
void gst_scheduler_enable_element (GstScheduler *sched, GstElement *element);
|
||||
|
|
|
@ -434,6 +434,7 @@ gst_thread_main_loop (void *arg)
|
|||
|
||||
g_mutex_lock (thread->lock);
|
||||
|
||||
gst_scheduler_setup (GST_ELEMENT_SCHED (thread));
|
||||
GST_FLAG_UNSET (thread, GST_THREAD_STATE_REAPING);
|
||||
|
||||
thread->pid = getpid();
|
||||
|
@ -549,6 +550,10 @@ gst_thread_main_loop (void *arg)
|
|||
break;
|
||||
}
|
||||
}
|
||||
/* we need to destroy the scheduler here bacause it has mapped it's
|
||||
* stack into the threads stack space */
|
||||
gst_scheduler_reset (GST_ELEMENT_SCHED (thread));
|
||||
|
||||
/* since we don't unlock at the end of the while loop, do it here */
|
||||
g_mutex_unlock (thread->lock);
|
||||
|
||||
|
|
|
@ -46,6 +46,8 @@ static void gst_basic_scheduler_init (GstScheduler * scheduler);
|
|||
|
||||
static void gst_basic_scheduler_dispose (GObject *object);
|
||||
|
||||
static void gst_basic_scheduler_setup (GstScheduler *sched);
|
||||
static void gst_basic_scheduler_reset (GstScheduler *sched);
|
||||
static void gst_basic_scheduler_add_element (GstScheduler *sched, GstElement *element);
|
||||
static void gst_basic_scheduler_remove_element (GstScheduler *sched, GstElement *element);
|
||||
static void gst_basic_scheduler_enable_element (GstScheduler *sched, GstElement *element);
|
||||
|
@ -96,6 +98,8 @@ gst_basic_scheduler_class_init (GstSchedulerClass * klass)
|
|||
|
||||
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_basic_scheduler_dispose);
|
||||
|
||||
klass->setup = GST_DEBUG_FUNCPTR (gst_basic_scheduler_setup);
|
||||
klass->reset = GST_DEBUG_FUNCPTR (gst_basic_scheduler_reset);
|
||||
klass->add_element = GST_DEBUG_FUNCPTR (gst_basic_scheduler_add_element);
|
||||
klass->remove_element = GST_DEBUG_FUNCPTR (gst_basic_scheduler_remove_element);
|
||||
klass->enable_element = GST_DEBUG_FUNCPTR (gst_basic_scheduler_enable_element);
|
||||
|
@ -116,12 +120,6 @@ gst_basic_scheduler_init (GstScheduler *scheduler)
|
|||
static void
|
||||
gst_basic_scheduler_dispose (GObject *object)
|
||||
{
|
||||
GstScheduler *sched = GST_SCHEDULER (object);
|
||||
cothread_context *ctx;
|
||||
|
||||
ctx = GST_BIN (GST_SCHED_PARENT (sched))->threadcontext;
|
||||
|
||||
cothread_free (ctx);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
@ -407,11 +405,8 @@ gst_basic_scheduler_cothreaded_chain (GstBin * bin, GstSchedulerChain * chain)
|
|||
|
||||
GST_DEBUG (GST_CAT_SCHEDULING, "chain is using COTHREADS\n");
|
||||
|
||||
/* first create thread context */
|
||||
if (bin->threadcontext == NULL) {
|
||||
GST_DEBUG (GST_CAT_SCHEDULING, "initializing cothread context\n");
|
||||
bin->threadcontext = cothread_init ();
|
||||
}
|
||||
g_assert (bin->threadcontext != NULL);
|
||||
|
||||
|
||||
/* walk through all the chain's elements */
|
||||
elements = chain->elements;
|
||||
|
@ -784,6 +779,37 @@ gst_basic_scheduler_chain_recursive_add (GstSchedulerChain * chain, GstElement *
|
|||
/*
|
||||
* Entry points for this scheduler.
|
||||
*/
|
||||
static void
|
||||
gst_basic_scheduler_setup (GstScheduler *sched)
|
||||
{
|
||||
GstBin *bin = GST_BIN (sched->parent);
|
||||
|
||||
/* first create thread context */
|
||||
if (bin->threadcontext == NULL) {
|
||||
GST_DEBUG (GST_CAT_SCHEDULING, "initializing cothread context\n");
|
||||
bin->threadcontext = cothread_init ();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_basic_scheduler_reset (GstScheduler *sched)
|
||||
{
|
||||
cothread_context *ctx;
|
||||
GstBin *bin = GST_BIN (GST_SCHED_PARENT (sched));
|
||||
GList *elements = sched->elements;
|
||||
|
||||
while (elements) {
|
||||
GST_ELEMENT (elements->data)->threadstate = NULL;
|
||||
elements = g_list_next (elements);
|
||||
}
|
||||
|
||||
ctx = GST_BIN (GST_SCHED_PARENT (sched))->threadcontext;
|
||||
|
||||
cothread_free (ctx);
|
||||
|
||||
GST_BIN (GST_SCHED_PARENT (sched))->threadcontext = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_basic_scheduler_add_element (GstScheduler * sched, GstElement * element)
|
||||
{
|
||||
|
@ -962,10 +988,17 @@ gst_basic_scheduler_pad_disconnect (GstScheduler * sched, GstPad * srcpad, GstPa
|
|||
* since they are guaranteed to be in the same chain
|
||||
* FIXME is it potentially better to make an attempt at splitting cleaner??
|
||||
*/
|
||||
chain = gst_basic_scheduler_find_chain (sched, element1);
|
||||
if (chain) {
|
||||
chain1 = gst_basic_scheduler_find_chain (sched, element1);
|
||||
chain2 = gst_basic_scheduler_find_chain (sched, element2);
|
||||
|
||||
if (chain1 != chain2) {
|
||||
GST_INFO (GST_CAT_SCHEDULING, "elements not in the same chain");
|
||||
return;
|
||||
}
|
||||
|
||||
if (chain1) {
|
||||
GST_INFO (GST_CAT_SCHEDULING, "destroying chain");
|
||||
gst_basic_scheduler_chain_destroy (chain);
|
||||
gst_basic_scheduler_chain_destroy (chain1);
|
||||
|
||||
/* now create a new chain to hold element1 and build it from scratch */
|
||||
chain1 = gst_basic_scheduler_chain_new (sched);
|
||||
|
@ -973,7 +1006,10 @@ gst_basic_scheduler_pad_disconnect (GstScheduler * sched, GstPad * srcpad, GstPa
|
|||
}
|
||||
|
||||
/* check the other element to see if it landed in the newly created chain */
|
||||
if (gst_basic_scheduler_find_chain (sched, element2) == NULL) {
|
||||
if (chain2) {
|
||||
GST_INFO (GST_CAT_SCHEDULING, "destroying chain");
|
||||
gst_basic_scheduler_chain_destroy (chain2);
|
||||
|
||||
/* if not in chain, create chain and build from scratch */
|
||||
chain2 = gst_basic_scheduler_chain_new (sched);
|
||||
gst_basic_scheduler_chain_recursive_add (chain2, element2);
|
||||
|
|
Loading…
Reference in a new issue