From df32997396392a94d74baac25f6e4cf2744ea513 Mon Sep 17 00:00:00 2001 From: Erik Walthinsen Date: Sat, 17 Feb 2001 07:11:12 +0000 Subject: [PATCH] Yes!, incsched is getting closer. Original commit message from CVS: Yes!, incsched is getting closer. --- gst/Makefile.am | 1 + gst/gst.h | 2 + gst/gstbin.c | 118 +++++++++++++++++++---------------- gst/gstbin.h | 4 +- gst/gstelement.c | 32 +++++----- gst/gstelement.h | 10 +-- gst/gstobject.h | 6 +- gst/gstpad.c | 25 ++++++++ gst/gstpad.h | 14 +++-- gst/gstpipeline.c | 4 +- gst/gstscheduler.c | 150 +++++++++++++++++++++++++++++++++++++++------ gst/gstscheduler.h | 48 ++++++++++++++- gst/gstthread.c | 2 +- tests/incsched.c | 72 ++++++++++++++-------- 14 files changed, 357 insertions(+), 131 deletions(-) diff --git a/gst/Makefile.am b/gst/Makefile.am index fb80219ba4..34e77090da 100644 --- a/gst/Makefile.am +++ b/gst/Makefile.am @@ -71,6 +71,7 @@ libgstincludedir = $(includedir)/gst libgstinclude_HEADERS = \ cothreads.h \ gst.h \ + gsttypes.h \ gstautoplug.h \ gstbin.h \ gstbuffer.h \ diff --git a/gst/gst.h b/gst/gst.h index a2d98c6a7c..e79eed1d40 100644 --- a/gst/gst.h +++ b/gst/gst.h @@ -26,6 +26,8 @@ #include +#include + #include #include #include diff --git a/gst/gstbin.c b/gst/gstbin.c index 29a4cba3f8..daa1ad5895 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -156,83 +156,94 @@ gst_bin_new (const gchar *name) } static inline void -gst_bin_reset_element_manager (GstElement *element, GstElement *manager) +gst_bin_reset_element_sched (GstElement *element, GstSchedule *sched) { - GST_INFO_ELEMENT (GST_CAT_PARENTAGE, element, "resetting element's manager"); + GST_INFO_ELEMENT (GST_CAT_PARENTAGE, element, "resetting element's scheduler"); - // first remove the element from its current manager, if any - if (element->manager) - gst_bin_remove_managed_element (GST_BIN(element->manager), element); + // first remove the element from its current schedule, if any +// if (GST_ELEMENT_SCHED(element)) +// GST_SCHEDULE_REMOVE_ELEMENT (GST_ELEMENT_SCHED(element), element); // then set the new manager - gst_element_set_manager (element,manager); - // and add it to the new manager's list - if (manager) - gst_bin_add_managed_element (GST_BIN(manager), element); + gst_element_set_sched (element,sched); + + // and add it to the new scheduler +// if (sched) +// GST_SCHEDULE_ADD_ELEMENT (sched, element); } void -gst_bin_set_element_manager (GstElement *element,GstElement *manager) +gst_bin_set_element_sched (GstElement *element,GstSchedule *sched) +{ + GstSchedule *realsched = NULL; + GList *children; + GstElement *child; + + g_return_if_fail (element != NULL); + g_return_if_fail (GST_IS_ELEMENT(element)); + g_return_if_fail (sched != NULL); + g_return_if_fail (GST_IS_SCHEDULE(sched)); + + GST_INFO (GST_CAT_SCHEDULING, "setting element \"%s\" sched to %p",GST_ELEMENT_NAME(element), + sched); + + // if it's actually a Bin + if (GST_IS_BIN(element)) { + + // figure out which element is the manager + if (GST_FLAG_IS_SET(element,GST_BIN_FLAG_MANAGER)) { + realsched = GST_ELEMENT_SCHED(element); + GST_INFO_ELEMENT (GST_CAT_PARENTAGE, element, "setting children's schedule to own sched"); + } else { + realsched = sched; + GST_INFO_ELEMENT (GST_CAT_PARENTAGE, element, "setting children's schedule to parent's"); + GST_SCHEDULE_ADD_ELEMENT (sched, element); + } + + // set the children's schedule + children = GST_BIN(element)->children; + while (children) { + child = GST_ELEMENT (children->data); + children = g_list_next(children); + + gst_bin_set_element_sched (child, realsched); + } + + // otherwise, if it's just a regular old element + } else { +g_print("calling schedule_add_element (%p, \"%s\")\n",sched, GST_ELEMENT_NAME(element)); + GST_SCHEDULE_ADD_ELEMENT (sched, element); + } +} + + +void +gst_bin_unset_element_sched (GstElement *element) { - GstElement *realmanager = NULL; GList *children; GstElement *child; g_return_if_fail (element != NULL); g_return_if_fail (GST_IS_ELEMENT(element)); - // figure out which element is the manager - if (manager) { - if (GST_FLAG_IS_SET(element,GST_BIN_FLAG_MANAGER)) { - realmanager = element; - GST_INFO_ELEMENT (GST_CAT_PARENTAGE, element, "setting children's manager to self"); - } else { - realmanager = manager; - GST_INFO_ELEMENT (GST_CAT_PARENTAGE, element, "setting children's manager to parent"); - } - } else { - GST_INFO_ELEMENT (GST_CAT_PARENTAGE, element, "unsetting children's manager"); - } - // if it's actually a Bin if (GST_IS_BIN(element)) { - // set the children's manager + + // for each child, remove them from their schedule children = GST_BIN(element)->children; while (children) { child = GST_ELEMENT (children->data); children = g_list_next(children); - gst_bin_set_element_manager (child, realmanager); + gst_bin_unset_element_sched (child); } // otherwise, if it's just a regular old element } else { - // simply reset the element's manager - gst_bin_reset_element_manager (element, realmanager); + if (GST_ELEMENT_SCHED (element)) + GST_SCHEDULE_REMOVE_ELEMENT (GST_ELEMENT_SCHED(element), element); } } -void -gst_bin_add_managed_element (GstBin *bin, GstElement *element) -{ - GST_INFO_ELEMENT (GST_CAT_PARENTAGE, bin, "adding managed element \"%s\"", GST_ELEMENT_NAME(element)); - bin->managed_elements = g_list_prepend (bin->managed_elements, element); - bin->num_managed_elements++; - - gst_schedule_add_element (NULL, element); -} - -void -gst_bin_remove_managed_element (GstBin *bin, GstElement *element) -{ - if (g_list_find (bin->managed_elements, element)) { - GST_INFO_ELEMENT (GST_CAT_PARENTAGE, bin, "removing managed element %s", GST_ELEMENT_NAME(element)); - bin->managed_elements = g_list_remove (bin->managed_elements, element); - bin->num_managed_elements--; - } - - gst_schedule_remove_element (NULL, element); -} - /** * gst_bin_add: @@ -269,7 +280,10 @@ gst_bin_add (GstBin *bin, bin->numchildren++; ///// now we have to deal with manager stuff - gst_bin_set_element_manager (element, GST_ELEMENT(bin)); + // we can only do this if there's a scheduler: + // if we're not a manager, and aren't attached to anything, we have no sched (yet) + if (GST_ELEMENT_SCHED(bin) != NULL) + gst_bin_set_element_sched (element, GST_ELEMENT_SCHED(bin)); GST_INFO_ELEMENT (GST_CAT_PARENTAGE, bin, "added child \"%s\"", GST_ELEMENT_NAME (element)); @@ -312,7 +326,7 @@ gst_bin_remove (GstBin *bin, } // remove this element from the list of managed elements - gst_bin_set_element_manager (element, NULL); + gst_bin_unset_element_sched (element); // now remove the element from the list of elements gst_object_unparent (GST_OBJECT (element)); diff --git a/gst/gstbin.h b/gst/gstbin.h index 03ae22c217..f947ae8b9d 100644 --- a/gst/gstbin.h +++ b/gst/gstbin.h @@ -55,8 +55,8 @@ typedef enum { GST_BIN_FLAG_LAST = GST_ELEMENT_FLAG_LAST + 4, } GstBinFlags; -typedef struct _GstBin GstBin; -typedef struct _GstBinClass GstBinClass; +//typedef struct _GstBin GstBin; +//typedef struct _GstBinClass GstBinClass; typedef struct __GstBinChain _GstBinChain; struct _GstBin { diff --git a/gst/gstelement.c b/gst/gstelement.c index 0f20248718..49193e7a7c 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -133,6 +133,7 @@ gst_element_init (GstElement *element) element->pads = NULL; element->loopfunc = NULL; element->threadstate = NULL; + element->sched = NULL; } /** @@ -847,8 +848,8 @@ gst_element_save_thyself (GstObject *object, xmlNewChild (parent, NULL, "version", factory->details->version); } - if (element->manager) - xmlNewChild(parent, NULL, "manager", GST_ELEMENT_NAME(element->manager)); +// if (element->manager) +// xmlNewChild(parent, NULL, "manager", GST_ELEMENT_NAME(element->manager)); // output all args to the element type = GTK_OBJECT_TYPE (element); @@ -1082,34 +1083,33 @@ gst_element_load_thyself (xmlNodePtr self, GstObject *parent) } /** - * gst_element_set_manager: + * gst_element_set_sched: * @element: Element to set manager of. - * @manager: Element to be the manager. + * @sched: @GstSchedule to set. * - * Sets the manager of the element. For internal use only, unless you're + * Sets the scheduler of the element. For internal use only, unless you're * writing a new bin subclass. */ void -gst_element_set_manager (GstElement *element, - GstElement *manager) +gst_element_set_sched (GstElement *element, + GstSchedule *sched) { - if (manager) - GST_INFO_ELEMENT (GST_CAT_PARENTAGE, element, "setting manager to \"%s\"",GST_ELEMENT_NAME(manager)); - element->manager = manager; + GST_INFO_ELEMENT (GST_CAT_PARENTAGE, element, "setting scheduler to %p",sched); + element->sched = sched; } /** - * gst_element_get_manager: + * gst_element_get_sched: * @element: Element to get manager of. * - * Returns the manager of the element. + * Returns the scheduler of the element. * - * Returns: Element's manager + * Returns: Element's scheduler */ -GstElement* -gst_element_get_manager (GstElement *element) +GstSchedule* +gst_element_get_sched (GstElement *element) { - return element->manager; + return element->sched; } /** diff --git a/gst/gstelement.h b/gst/gstelement.h index 622e7a4402..69583866be 100644 --- a/gst/gstelement.h +++ b/gst/gstelement.h @@ -123,9 +123,10 @@ typedef enum { #define GST_ELEMENT_NAME(obj) (GST_OBJECT_NAME(obj)) #define GST_ELEMENT_PARENT(obj) (GST_OBJECT_PARENT(obj)) #define GST_ELEMENT_MANAGER(obj) (((GstElement*)(obj))->manager) +#define GST_ELEMENT_SCHED(obj) (((GstElement*)(obj))->sched) -typedef struct _GstElement GstElement; -typedef struct _GstElementClass GstElementClass; +//typedef struct _GstElement GstElement; +//typedef struct _GstElementClass GstElementClass; typedef struct _GstElementDetails GstElementDetails; typedef struct _GstElementFactory GstElementFactory; @@ -146,6 +147,7 @@ struct _GstElement { GList *pads; GstElement *manager; + GstSchedule *sched; }; struct _GstElementClass { @@ -199,8 +201,8 @@ const gchar* gst_element_get_name (GstElement *element); void gst_element_set_parent (GstElement *element, GstObject *parent); GstObject* gst_element_get_parent (GstElement *element); -void gst_element_set_manager (GstElement *element, GstElement *manager); -GstElement* gst_element_get_manager (GstElement *element); +void gst_element_set_sched (GstElement *element, GstSchedule *sched); +GstSchedule* gst_element_get_sched (GstElement *element); void gst_element_add_pad (GstElement *element, GstPad *pad); GstPad* gst_element_get_pad (GstElement *element, const gchar *name); diff --git a/gst/gstobject.h b/gst/gstobject.h index bc34624acd..a32c26a95c 100644 --- a/gst/gstobject.h +++ b/gst/gstobject.h @@ -28,6 +28,8 @@ #include #include +#include + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -55,8 +57,8 @@ extern "C" { #define GST_IS_OBJECT_CLASS(obj) \ (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_OBJECT)) -typedef struct _GstObject GstObject; -typedef struct _GstObjectClass GstObjectClass; +//typedef struct _GstObject GstObject; +//typedef struct _GstObjectClass GstObjectClass; #define GST_OBJECT_FLAG_LAST 4 diff --git a/gst/gstpad.c b/gst/gstpad.c index cebf58bb2a..a9ddd66718 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -27,6 +27,7 @@ #include "gstelement.h" #include "gsttype.h" #include "gstbin.h" +#include "gstscheduler.h" /***** Start with the base GstPad class *****/ @@ -509,6 +510,9 @@ gst_pad_disconnect (GstPad *srcpad, gtk_signal_emit(GTK_OBJECT(realsrc), gst_real_pad_signals[REAL_DISCONNECTED], realsink); gtk_signal_emit(GTK_OBJECT(realsink), gst_real_pad_signals[REAL_DISCONNECTED], realsrc); + // now tell the scheduler + GST_SCHEDULE_PAD_DISCONNECT (realsrc->sched, realsrc, realsink); + GST_INFO (GST_CAT_ELEMENT_PADS, "disconnected %s:%s and %s:%s", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad)); } @@ -570,6 +574,9 @@ gst_pad_connect (GstPad *srcpad, gtk_signal_emit(GTK_OBJECT(realsrc), gst_real_pad_signals[REAL_CONNECTED], realsink); gtk_signal_emit(GTK_OBJECT(realsink), gst_real_pad_signals[REAL_CONNECTED], realsrc); + // now tell the scheduler + GST_SCHEDULE_PAD_CONNECT (realsrc->sched, realsrc, realsink); + GST_INFO (GST_CAT_ELEMENT_PADS, "connected %s:%s and %s:%s", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad)); } @@ -612,6 +619,24 @@ gst_pad_get_parent (GstPad *pad) return GST_OBJECT_PARENT (pad); } +void +gst_pad_set_sched (GstPad *pad, GstSchedule *sched) +{ + g_return_if_fail (pad != NULL); + g_return_if_fail (GST_IS_PAD (pad)); + + GST_RPAD_SCHED(pad) = sched; +} + +GstSchedule* +gst_pad_get_sched (GstPad *pad) +{ + 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_add_ghost_pad: * @pad: the pad to set the ghost parent diff --git a/gst/gstpad.h b/gst/gstpad.h index 42527dd781..ca09ff879b 100644 --- a/gst/gstpad.h +++ b/gst/gstpad.h @@ -56,14 +56,14 @@ extern "C" { #define GST_IS_GHOST_PAD_CLASS(obj) (GTK_CHECK_CLASS_TYPE ((klass), GST_TYPE_GHOST_PAD)) -typedef struct _GstPad GstPad; -typedef struct _GstPadClass GstPadClass; +//typedef struct _GstPad GstPad; +//typedef struct _GstPadClass GstPadClass; typedef struct _GstRealPad GstRealPad; typedef struct _GstRealPadClass GstRealPadClass; typedef struct _GstGhostPad GstGhostPad; typedef struct _GstGhostPadClass GstGhostPadClass; -typedef struct _GstPadTemplate GstPadTemplate; -typedef struct _GstPadTemplateClass GstPadTemplateClass; +//typedef struct _GstPadTemplate GstPadTemplate; +//typedef struct _GstPadTemplateClass GstPadTemplateClass; typedef enum { @@ -137,6 +137,8 @@ struct _GstRealPad { GstPadPullRegionFunction pullregionfunc; GList *ghostpads; + + GstSchedule *sched; }; struct _GstRealPadClass { @@ -174,6 +176,7 @@ struct _GstGhostPadClass { #define GST_RPAD_CAPS(pad) (((GstRealPad *)(pad))->caps) #define GST_RPAD_PEER(pad) (((GstRealPad *)(pad))->peer) #define GST_RPAD_BUFPEN(pad) (((GstRealPad *)(pad))->bufpen) +#define GST_RPAD_SCHED(pad) (((GstRealPad *)(pad))->sched) #define GST_RPAD_CHAINFUNC(pad) (((GstRealPad *)(pad))->chainfunc) #define GST_RPAD_GETFUNC(pad) (((GstRealPad *)(pad))->getfunc) #define GST_RPAD_GETREGIONFUNC(pad) (((GstRealPad *)(pad))->getregionfunc) @@ -275,6 +278,9 @@ const gchar* gst_pad_get_name (GstPad *pad); void gst_pad_set_parent (GstPad *pad, GstObject *parent); GstObject* gst_pad_get_parent (GstPad *pad); +void gst_pad_set_sched (GstPad *pad, GstSchedule *sched); +GstSchedule* gst_pad_get_sched (GstPad *pad); + void gst_pad_add_ghost_pad (GstPad *pad, GstPad *ghostpad); void gst_pad_remove_ghost_pad (GstPad *pad, GstPad *ghostpad); GList* gst_pad_get_ghost_pad_list (GstPad *pad); diff --git a/gst/gstpipeline.c b/gst/gstpipeline.c index baa2808de1..7714b4e663 100644 --- a/gst/gstpipeline.c +++ b/gst/gstpipeline.c @@ -105,7 +105,9 @@ gst_pipeline_init (GstPipeline *pipeline) pipeline->src = NULL; pipeline->sinks = NULL; - gst_element_set_manager(GST_ELEMENT(pipeline),GST_ELEMENT(pipeline)); + GST_ELEMENT_SCHED(pipeline) = gst_schedule_new(GST_ELEMENT(pipeline)); + g_print("pipeline's scheduler is %p\n",GST_ELEMENT_SCHED(pipeline)); +// gst_element_set_manager(GST_ELEMENT(pipeline),GST_ELEMENT(pipeline)); } diff --git a/gst/gstscheduler.c b/gst/gstscheduler.c index 04d8f2e0f5..2e66f2e765 100644 --- a/gst/gstscheduler.c +++ b/gst/gstscheduler.c @@ -747,13 +747,63 @@ void gst_bin_schedule_func(GstBin *bin) { /*************** INCREMENTAL SCHEDULING CODE STARTS HERE ***************/ -static GstSchedule realsched; -static GstSchedule *sched = &realsched; +//static GstSchedule realsched; +//static GstSchedule *sched = &realsched; + + +static void gst_schedule_class_init (GstScheduleClass *klass); +static void gst_schedule_init (GstSchedule *schedule); + +static GstObjectClass *parent_class = NULL; + +GtkType gst_schedule_get_type(void) { + static GtkType schedule_type = 0; + + if (!schedule_type) { + static const GtkTypeInfo schedule_info = { + "GstSchedule", + sizeof(GstSchedule), + sizeof(GstScheduleClass), + (GtkClassInitFunc)gst_schedule_class_init, + (GtkObjectInitFunc)gst_schedule_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL, + (GtkClassInitFunc)NULL, + }; + schedule_type = gtk_type_unique(GST_TYPE_OBJECT,&schedule_info); + } + return schedule_type; +} + +static void +gst_schedule_class_init (GstScheduleClass *klass) +{ + parent_class = gtk_type_class(GST_TYPE_OBJECT); +} + +static void +gst_schedule_init (GstSchedule *schedule) +{ + schedule->add_element = GST_DEBUG_FUNCPTR(gst_schedule_add_element); + schedule->remove_element = GST_DEBUG_FUNCPTR(gst_schedule_remove_element); + schedule->pad_connect = GST_DEBUG_FUNCPTR(gst_schedule_pad_connect); + schedule->pad_disconnect = GST_DEBUG_FUNCPTR(gst_schedule_pad_disconnect); +} + +GstSchedule* +gst_schedule_new(GstElement *parent) +{ + GstSchedule *sched = GST_SCHEDULE (gtk_type_new (GST_TYPE_SCHEDULE)); + + sched->parent = parent; + + return sched; +} /* this function will look at a pad and determine if the peer parent is * a possible candidate for connecting up in the same chain. */ -GstElement *gst_schedule_check_pad (GstSchedule *schedule, GstPad *pad) { +GstElement *gst_schedule_check_pad (GstSchedule *sched, GstPad *pad) { GstRealPad *peer; GstElement *peerelement; @@ -800,7 +850,7 @@ void gst_schedule_chain_destroy (GstScheduleChain *chain) { chain->sched->chains = g_list_remove (chain->sched->chains, chain); - sched->num_chains--; + chain->sched->num_chains--; g_list_free (chain->elements); g_free (chain); @@ -816,7 +866,7 @@ gst_schedule_chain_add_element (GstScheduleChain *chain, GstElement *element) } void -gst_schedule_chain_elements (GstSchedule *schedule, GstElement *element1, GstElement *element2) +gst_schedule_chain_elements (GstSchedule *sched, GstElement *element1, GstElement *element2) { GList *chains; GstScheduleChain *chain; @@ -853,11 +903,11 @@ gst_schedule_chain_elements (GstSchedule *schedule, GstElement *element1, GstEle } else if ((chain1 != NULL) && (chain2 != NULL)) { GST_INFO (GST_CAT_SCHEDULING, "joining two existing chains together"); // take the contents of chain2 and merge them into chain1 - chain1->elements = g_list_concat (chain1->elements, chain2->elements); + chain1->elements = g_list_concat (chain1->elements, g_list_copy(chain2->elements)); chain1->num_elements += chain2->num_elements; // FIXME chain changed here - g_free(chain2); + gst_schedule_chain_destroy(chain2); // otherwise one has a chain already, the other doesn't } else { @@ -872,18 +922,22 @@ gst_schedule_chain_elements (GstSchedule *schedule, GstElement *element1, GstEle } void -gst_schedule_pad_connect_callback (GstPad *pad, GstPad *peer, GstSchedule *sched) +gst_schedule_pad_connect_callback (GstPad *srcpad, GstPad *sinkpad, GstSchedule *sched) { GstElement *peerelement; - GST_INFO (GST_CAT_SCHEDULING, "have pad connected callback on %s:%s",GST_DEBUG_PAD_NAME(pad)); + GST_INFO (GST_CAT_SCHEDULING, "have pad connected callback on %s:%s",GST_DEBUG_PAD_NAME(srcpad)); - if ((peerelement = gst_schedule_check_pad(sched,pad))) { + if ((peerelement = gst_schedule_check_pad(sched,srcpad))) { GST_INFO (GST_CAT_SCHEDULING, "peer is in same schedule, chaining together"); - gst_schedule_chain_elements (sched, GST_ELEMENT(GST_PAD_PARENT(pad)), peerelement); + gst_schedule_chain_elements (sched, GST_ELEMENT(GST_PAD_PARENT(srcpad)), peerelement); } } +void gst_schedule_pad_connect (GstSchedule *sched, GstPad *srcpad, GstPad *sinkpad) { + gst_schedule_pad_connect_callback(srcpad,sinkpad,sched); +} + // find the chain within the schedule that holds the element, if any GstScheduleChain * gst_schedule_find_chain (GstSchedule *sched, GstElement *element) @@ -922,9 +976,9 @@ gst_schedule_chain_recursive_add (GstScheduleChain *chain, GstElement *element) pads = g_list_next (pads); // if it's a potential peer - if ((peerelement = gst_schedule_check_pad (sched, pad))) { + if ((peerelement = gst_schedule_check_pad (chain->sched, pad))) { // if it's not already in a chain, add it to this one - if (gst_schedule_find_chain (sched, peerelement) == NULL) { + if (gst_schedule_find_chain (chain->sched, peerelement) == NULL) { gst_schedule_chain_recursive_add (chain, peerelement); } } @@ -959,19 +1013,27 @@ gst_schedule_pad_disconnect_callback (GstPad *pad, GstPad *peer, GstSchedule *sc // now create a new chain to hold element1 and build it from scratch chain1 = gst_schedule_chain_new (sched); gst_schedule_chain_recursive_add (chain1, element1); - -return; + // this is an ugly hack to handle elements left over + if (chain1->num_elements == 1) + gst_schedule_chain_destroy(chain1); // check the other element to see if it landed in the newly created chain if (gst_schedule_find_chain (sched, element2) == NULL) { // if not in chain, create chain and build from scratch chain2 = gst_schedule_chain_new (sched); gst_schedule_chain_recursive_add (chain2, element2); + // this is an ugly hack to handle elements left over + if (chain2->num_elements == 1) + gst_schedule_chain_destroy(chain2); } } +void gst_schedule_pad_disconnect (GstSchedule *sched, GstPad *srcpad, GstPad *sinkpad) { + gst_schedule_pad_disconnect_callback(srcpad,sinkpad,sched); +} + void -gst_schedule_add_element (GstSchedule *schedule, GstElement *element) +gst_schedule_add_element (GstSchedule *sched, GstElement *element) { GList *pads; GstPad *pad; @@ -987,12 +1049,21 @@ gst_schedule_add_element (GstSchedule *schedule, GstElement *element) sched->elements = g_list_prepend (sched->elements, element); sched->num_elements++; + // set the sched pointer in the element itself + gst_element_set_sched (element, sched); + // now look through the pads and see what we need to do pads = element->pads; while (pads) { pad = GST_PAD(pads->data); pads = g_list_next(pads); + // we only operate on real pads + if (!GST_IS_REAL_PAD(pad)) continue; + + // set the pad's sched pointer + gst_pad_set_sched (pad, sched); + // if the peer element is a candidate if ((peerelement = gst_schedule_check_pad(sched,pad))) { GST_INFO (GST_CAT_SCHEDULING, "peer is in same schedule, chaining together"); @@ -1002,13 +1073,13 @@ gst_schedule_add_element (GstSchedule *schedule, GstElement *element) // now we have to attach a signal to each pad // FIXME this is stupid - gtk_signal_connect(pad,"connected",GTK_SIGNAL_FUNC(gst_schedule_pad_connect_callback),sched); - gtk_signal_connect(pad,"disconnected",GTK_SIGNAL_FUNC(gst_schedule_pad_disconnect_callback),sched); +// gtk_signal_connect(pad,"connected",GTK_SIGNAL_FUNC(gst_schedule_pad_connect_callback),sched); +// gtk_signal_connect(pad,"disconnected",GTK_SIGNAL_FUNC(gst_schedule_pad_disconnect_callback),sched); } } void -gst_schedule_remove_element (GstSchedule *schedule, GstElement *element) +gst_schedule_remove_element (GstSchedule *sched, GstElement *element) { GList *chains; GstScheduleChain *chain; @@ -1034,7 +1105,48 @@ gst_schedule_remove_element (GstSchedule *schedule, GstElement *element) } } + // unset the scheduler + gst_element_set_sched (element, NULL); + sched->elements = g_list_remove (sched->elements, element); sched->num_elements--; } } + + +void +gst_schedule_show (GstSchedule *sched) +{ + GList *chains, *elements; + GstElement *element; + GstScheduleChain *chain; + + g_return_if_fail(sched != NULL); + g_return_if_fail(GST_IS_SCHEDULE(sched)); + + g_print("schedule has %d elements in it: ",sched->num_elements); + elements = sched->elements; + while (elements) { + element = GST_ELEMENT(elements->data); + elements = g_list_next(elements); + + g_print("%s, ",GST_ELEMENT_NAME(element)); + } + g_print("\n"); + + g_print("schedule has %d chains in it\n",sched->num_chains); + chains = sched->chains; + while (chains) { + chain = (GstScheduleChain *)(chains->data); + chains = g_list_next(chains); + + elements = chain->elements; + while (elements) { + element = GST_ELEMENT(elements->data); + elements = g_list_next(elements); + + g_print("%s, ",GST_ELEMENT_NAME(element)); + } + g_print("\n"); + } +} diff --git a/gst/gstscheduler.h b/gst/gstscheduler.h index 4fd5ac93f3..13051f5a17 100644 --- a/gst/gstscheduler.h +++ b/gst/gstscheduler.h @@ -33,10 +33,25 @@ extern "C" { #endif /* __cplusplus */ +#define GST_TYPE_SCHEDULE \ + (gst_schedule_get_type()) +#define GST_SCHEDULE(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_SCHEDULE,GstSchedule)) +#define GST_SCHEDULE_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_SCHEDULE,GstScheduleClass)) +#define GST_IS_SCHEDULE(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_SCHEDULE)) +#define GST_IS_SCHEDULE_CLASS(klass) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_SCHEDULE)) + + +//typedef struct _GstSchedule GstSchedule; +//typedef struct _GstScheduleClass GstScheduleClass; typedef struct _GstScheduleChain GstScheduleChain; -typedef struct _GstSchedule GstSchedule; struct _GstSchedule { + GstObject object; + GstElement *parent; GList *elements; @@ -44,8 +59,28 @@ struct _GstSchedule { GList *chains; gint num_chains; + + void (*add_element) (GstSchedule *sched, GstElement *element); + void (*remove_element) (GstSchedule *sched, GstElement *element); + void (*pad_connect) (GstSchedule *sched, GstPad *srcpad, GstPad *sinkpad); + void (*pad_disconnect) (GstSchedule *sched, GstPad *srcpad, GstPad *sinkpad); }; +struct _GstScheduleClass { + GstObjectClass parent_class; +}; + +#define GST_SCHEDULE_ADD_ELEMENT(sched,element) \ + ((sched)->add_element((sched),(element))) +#define GST_SCHEDULE_REMOVE_ELEMENT(sched,element) \ + ((sched)->remove_element((sched),(element))) +#define GST_SCHEDULE_PAD_CONNECT(sched,srcpad,sinkpad) \ + ((sched)->pad_connect((sched),(srcpad),(sinkpad))) +#define GST_SCHEDULE_PAD_DISCONNECT(sched,srcpad,sinkpad) \ + ((sched)->pad_disconnect((sched),(srcpad),(sinkpad))) + + + struct _GstScheduleChain { GstSchedule *sched; @@ -61,8 +96,15 @@ struct _GstScheduleChain { void gst_bin_schedule_func(GstBin *bin); -void gst_schedule_add_element(GstSchedule *schedule,GstElement *element); -void gst_schedule_remove_element(GstSchedule *schedule,GstElement *element); +GtkType gst_schedule_get_type (void); +GstSchedule * gst_schedule_new (GstElement *parent); + +void gst_schedule_add_element (GstSchedule *sched, GstElement *element); +void gst_schedule_remove_element (GstSchedule *sched, GstElement *element); +void gst_schedule_pad_connect (GstSchedule *sched, GstPad *srcpad, GstPad *sinkpad); +void gst_schedule_pad_disconnect (GstSchedule *sched, GstPad *srcpad, GstPad *sinkpad); + +void gst_schedule_show (GstSchedule *sched); #ifdef __cplusplus diff --git a/gst/gstthread.c b/gst/gstthread.c index 91190ebee6..199cace249 100644 --- a/gst/gstthread.c +++ b/gst/gstthread.c @@ -135,7 +135,7 @@ gst_thread_init (GstThread *thread) thread->lock = g_mutex_new(); thread->cond = g_cond_new(); - gst_element_set_manager(GST_ELEMENT(thread),GST_ELEMENT(thread)); +// gst_element_set_manager(GST_ELEMENT(thread),GST_ELEMENT(thread)); } static void diff --git a/tests/incsched.c b/tests/incsched.c index 466bc435fc..32651c46ce 100644 --- a/tests/incsched.c +++ b/tests/incsched.c @@ -3,7 +3,7 @@ int main(int argc,char *argv[]) { GstBin *thread, *bin; - GstElement *src, *identity, *sink; + GstElement *src, *identity, *sink, *identity2; gst_init(&argc,&argv); gst_info_set_categories(-1); @@ -15,47 +15,65 @@ int main(int argc,char *argv[]) { src = gst_elementfactory_make("fakesrc","src"); identity = gst_elementfactory_make("identity","identity"); sink = gst_elementfactory_make("fakesink","sink"); + identity2 = gst_elementfactory_make("identity","identity2"); - g_print("\n\nConnecting:\n"); + g_print("\nAdding src to thread:\n"); + gst_bin_add(thread,src); + gst_schedule_show(GST_ELEMENT_SCHED(thread)); + + g_print("\nAdding identity to thread:\n"); + gst_bin_add(thread,identity); + gst_schedule_show(GST_ELEMENT_SCHED(thread)); + + g_print("\nRemoving identity from thread:\n"); + gst_bin_remove(thread, identity); + gst_schedule_show(GST_ELEMENT_SCHED(thread)); + + g_print("\nAdding identity to thread:\n"); + gst_bin_add(thread,identity); + gst_schedule_show(GST_ELEMENT_SCHED(thread)); + + g_print("\nConnecting src to identity:\n"); gst_element_connect(src,"src",identity,"sink"); + gst_schedule_show(GST_ELEMENT_SCHED(thread)); - g_print("\n\nAssembling things:\n"); - g_print("\nAdding src to bin:\n"); - gst_bin_add(bin,src); - g_print("there are %d managed elements in bin\n",bin->num_managed_elements); + g_print("\nDisconnecting src from identity:\n"); + gst_element_disconnect(src,"src",identity,"sink"); + gst_schedule_show(GST_ELEMENT_SCHED(thread)); - g_print("\nAdding identity to bin:\n"); - gst_bin_add(bin,identity); - g_print("there are %d managed elements in bin\n",bin->num_managed_elements); + g_print("\nConnecting src to identity:\n"); + gst_element_connect(src,"src",identity,"sink"); + gst_schedule_show(GST_ELEMENT_SCHED(thread)); g_print("\nAdding sink to bin:\n"); gst_bin_add(bin,sink); - g_print("there are %d managed elements in bin\n",bin->num_managed_elements); + gst_schedule_show(GST_ELEMENT_SCHED(bin)); + + g_print("\nAdding bin to thread:\n"); + gst_bin_add(thread, GST_ELEMENT(bin)); + gst_schedule_show(GST_ELEMENT_SCHED(thread)); g_print("\nConnecting identity to sink:\n"); gst_element_connect(identity,"src",sink,"sink"); + gst_schedule_show(GST_ELEMENT_SCHED(thread)); g_print("\nDisconnecting sink:\n"); gst_element_disconnect(identity,"src",sink,"sink"); + gst_schedule_show(GST_ELEMENT_SCHED(thread)); -// g_print("schedule has %d chains now\n",bin->sched->num_chains); + g_print("\nAdding identity2 to bin:\n"); + gst_bin_add(bin, identity2); + gst_schedule_show(GST_ELEMENT_SCHED(thread)); -// g_print("\nRemoving sink from bin:\n"); -// gst_bin_remove(bin,sink); -// g_print("there are %d managed elements in bin\n",bin->num_managed_elements); + g_print("\nConnecting identity2 to sink\n"); + gst_element_connect(identity2,"src",sink,"sink"); + gst_schedule_show(GST_ELEMENT_SCHED(thread)); -// g_print("\nAdding bin to thread:\n"); -// gst_bin_add(thread,bin); -// g_print("there are %d managed elements in thread now\n",thread->num_managed_elements); -// g_print("there are %d managed elements in bin now\n",bin->num_managed_elements); + g_print("\nConnecting identity to identity2\n"); + gst_element_connect(identity,"src",identity2,"sink"); + gst_schedule_show(GST_ELEMENT_SCHED(thread)); -/* - g_print("\n\nSaving xml:\n"); - xmlSaveFile("threadsync.gst", gst_xml_write(GST_ELEMENT(thread))); -*/ - -// g_print("\n\nSetting state to READY:\n"); -// gst_element_set_state(thread,GST_STATE_READY); - - sleep(1); + g_print("\nDisconnecting identity to identity2\n"); + gst_element_disconnect(identity,"src",identity2,"sink"); + gst_schedule_show(GST_ELEMENT_SCHED(thread)); }