-Wcast-align -Wsign-compare \
-Wmissing-prototypes -Wmissing-declarations \
-Wnested-externs \
- -Winline -Wno-unused
+ -Winline -Wno-unused
-libgst_la_LIBADD = $(XML_LIBS) $(GLIB_LIBS)
+libgst_la_LIBADD = $(XML_LIBS) $(GLIB_LIBS)
libgst_la_LDFLAGS = -version-info $(GST_LIBVERSION)
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);
}
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));
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);
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);
return GST_PAD_PADTEMPLATE (pad);
}
-/**
+
+/*
* gst_pad_set_sched:
* @pad: the pad to set the scheduler for
* @sched: The scheduler to set
{
g_return_if_fail (pad != NULL);
g_return_if_fail (GST_IS_PAD (pad));
-
+
GST_RPAD_SCHED(pad) = sched;
}
-
+
/**
* gst_pad_get_sched:
* @pad: the pad to get the scheduler from
{
g_return_val_if_fail (pad != NULL, NULL);
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
-
+
return GST_RPAD_SCHED(pad);
}
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;
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);
}
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);
}
{
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;
}
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_ELEMENT_SCHED (pipeline) = scheduler;
+
+ gst_object_ref (GST_OBJECT (scheduler));
+ gst_object_sink (GST_OBJECT (scheduler));
- gst_object_ref (GST_OBJECT (GST_ELEMENT_SCHED (pipeline)));
- gst_object_sink (GST_OBJECT (GST_ELEMENT_SCHED (pipeline)));
+ gst_scheduler_setup (scheduler);
- GST_DEBUG (GST_CAT_PIPELINE, "pipeline's scheduler is %p\n", GST_ELEMENT_SCHED (pipeline));
+ GST_DEBUG (GST_CAT_PIPELINE, "pipeline's scheduler is %p\n", scheduler);
}
static void
G_OBJECT_CLASS (parent_class)->dispose (object);
+ gst_scheduler_reset (GST_ELEMENT_SCHED (pipeline));
gst_object_unref (GST_OBJECT (GST_ELEMENT_SCHED (pipeline)));
}
}
/**
+ * 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
* @srcpad: the srcpad to connect
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);
#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);
g_mutex_lock (thread->lock);
+ gst_scheduler_setup (GST_ELEMENT_SCHED (thread));
GST_FLAG_UNSET (thread, GST_THREAD_STATE_REAPING);
thread->pid = getpid();
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);
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);
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);
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);
}
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;
* 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)
{
GList *pads;
* 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);
}
/* 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);