diff --git a/configure.base b/configure.base index 0433401abe..3cf10b3f9c 100644 --- a/configure.base +++ b/configure.base @@ -46,6 +46,7 @@ AM_MAINTAINER_MODE AC_PROG_CC AM_PROG_CC_STDC +dnl you need automake 1.5 for AM_PROG_AS to work ! AM_PROG_AS AC_PROG_CXX AC_PROG_CXXCPP @@ -1103,6 +1104,7 @@ dnl ######################### dnl until ffmpeg is handled by configure plugins/ffmpeg/Makefile dnl components/bonobo-gstmediaplay/Makefile dnl someone should fix this test/misc/Makefile +dnl wtay fix this: testsuite/threads/Makefile SUBSTFOR configure.ac:AC_OUTPUT( SUBSTFOR configure.ac:Makefile SUBSTFOR configure.in:AC_OUTPUT([Makefile @@ -1112,6 +1114,7 @@ gst/gstversion.h gst/types/Makefile gst/elements/Makefile gst/autoplug/Makefile +gst/schedulers/Makefile libs/Makefile libs/riff/Makefile libs/getbits/Makefile @@ -1184,6 +1187,7 @@ plugins/filters/cutter/Makefile plugins/filters/deinterlace/Makefile plugins/filters/volume/Makefile plugins/filters/speed/Makefile +plugins/filters/playondemand/Makefile plugins/gnomevfs/Makefile plugins/icecast/Makefile plugins/icecast/icecastsend/Makefile diff --git a/docs/gst/.gitignore b/docs/gst/.gitignore index 80491c9cb6..099652a986 100644 --- a/docs/gst/.gitignore +++ b/docs/gst/.gitignore @@ -6,6 +6,7 @@ gstreamer.signals gstreamer.types gstreamer.html gstreamer-unused.txt +gstreamer-undocumented.txt gstreamer-decl-list.txt gstreamer-decl.txt gstreamer-scan.c diff --git a/docs/random/wtay/threads_hilevel b/docs/random/wtay/threads_hilevel index 263ec6d5d8..f8eb9e35ad 100644 --- a/docs/random/wtay/threads_hilevel +++ b/docs/random/wtay/threads_hilevel @@ -100,6 +100,7 @@ flow: unlock (release lock) ! ! status = iterate() (*) lock mutex + signal TH if (!status) // EOS unset SPINNING flag } diff --git a/editor/Makefile.am b/editor/Makefile.am index 0b426547b1..9be4d57d51 100644 --- a/editor/Makefile.am +++ b/editor/Makefile.am @@ -1,5 +1,3 @@ -CFLAGS += -DDATADIR="\"$(gladedir)/\"" $(GNOME_CFLAGS) $(LIBGLADE_GNOME_CFLAGS) -LDFLAGS += $(GNOME_LIBS) $(LIBGLADE_GNOME_LIBS) lib_LTLIBRARIES = libgsteditor.la @@ -19,6 +17,9 @@ libgsteditor_la_SOURCES = \ gstelementselect.c \ gsteditorcreate.c +libgsteditor_la_CFLAGS = -DDATADIR="\"$(gladedir)/\"" $(GNOME_CFLAGS) $(LIBGLADE_GNOME_CFLAGS) +libgsteditor_la_LDFLAGS = $(GNOME_LIBS) $(LIBGLADE_GNOME_LIBS) + libgsteditorincludedir = $(includedir)/gst libgsteditorinclude_HEADERS = \ gsteditor.h diff --git a/examples/autoplug/Makefile.am b/examples/autoplug/Makefile.am index f263f27100..8f8cdd4153 100644 --- a/examples/autoplug/Makefile.am +++ b/examples/autoplug/Makefile.am @@ -1,5 +1,5 @@ noinst_PROGRAMS = autoplug # just an app here, we're safe -LIBS += $(GNOME_LIBS) $(GST_LIBS) -CFLAGS += $(GNOME_CFLAGS) $(GST_CFLAGS) +autoplug_LDADD = $(GNOME_LIBS) $(GST_LIBS) $(GLIB_LIBS) +autoplug_CFLAGS = $(GNOME_CFLAGS) $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/examples/cutter/Makefile.am b/examples/cutter/Makefile.am index c1fca3f985..29da841f05 100644 --- a/examples/cutter/Makefile.am +++ b/examples/cutter/Makefile.am @@ -1,5 +1,5 @@ noinst_PROGRAMS = cutter noinst_HEADERS = cutter.h -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +cutter_LDADD = $(GST_LIBS) +cutter_CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/examples/helloworld/Makefile.am b/examples/helloworld/Makefile.am index 77e8ef336a..5821f461f2 100644 --- a/examples/helloworld/Makefile.am +++ b/examples/helloworld/Makefile.am @@ -1,4 +1,4 @@ noinst_PROGRAMS = helloworld -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +helloworld_LDADD = $(GST_LIBS) +helloworld_CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/examples/helloworld2/Makefile.am b/examples/helloworld2/Makefile.am index 6d686a4092..1daf5c0da1 100644 --- a/examples/helloworld2/Makefile.am +++ b/examples/helloworld2/Makefile.am @@ -1,5 +1,5 @@ noinst_PROGRAMS = helloworld2 -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +helloworld2_LDADD = $(GST_LIBS) +helloworld2_CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/examples/launch/Makefile.am b/examples/launch/Makefile.am index 11c2e57cfc..c1d844569c 100644 --- a/examples/launch/Makefile.am +++ b/examples/launch/Makefile.am @@ -1,8 +1,8 @@ noinst_PROGRAMS = mp3parselaunch # just an app here, we're safe -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +mp3parselaunch_LDADD = $(GST_LIBS) +mp3parselaunch_CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) noinst_SCRIPTS = mp3play EXTRA_DIST = mp3play diff --git a/examples/mixer/Makefile.am b/examples/mixer/Makefile.am index d15b425208..8d993da8c7 100644 --- a/examples/mixer/Makefile.am +++ b/examples/mixer/Makefile.am @@ -1,5 +1,5 @@ noinst_PROGRAMS = mixer noinst_HEADERS = mixer.h -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +mixer_LDADD = $(GST_LIBS) +mixer_CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/examples/mixer/mixer.c b/examples/mixer/mixer.c index 7a02eddcb4..ec492cad34 100644 --- a/examples/mixer/mixer.c +++ b/examples/mixer/mixer.c @@ -190,7 +190,7 @@ int main(int argc,char *argv[]) gst_element_set_state(main_bin, GST_STATE_PLAYING); // write out the schedule - gst_schedule_show(GST_ELEMENT_SCHED(main_bin)); + gst_scheduler_show(GST_ELEMENT_SCHED(main_bin)); playing = TRUE; j = 0; diff --git a/examples/plugins/Makefile.am b/examples/plugins/Makefile.am index 5e0b9fca0f..11c631711d 100644 --- a/examples/plugins/Makefile.am +++ b/examples/plugins/Makefile.am @@ -1,4 +1,5 @@ noinst_LTLIBRARIES = libexample.la libexample_la_SOURCES = example.c +libexample_la_CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) noinst_HEADERS = example.h diff --git a/examples/queue/Makefile.am b/examples/queue/Makefile.am index e4ef4c7ce8..7b67eeabd6 100644 --- a/examples/queue/Makefile.am +++ b/examples/queue/Makefile.am @@ -1,5 +1,5 @@ noinst_PROGRAMS = queue -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +queue_LDADD = $(GST_LIBS) +queue_CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/examples/queue2/Makefile.am b/examples/queue2/Makefile.am index fd4f914bbd..5bd7542f1c 100644 --- a/examples/queue2/Makefile.am +++ b/examples/queue2/Makefile.am @@ -1,5 +1,5 @@ noinst_PROGRAMS = queue2 -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +queue2_LDADD = $(GST_LIBS) +queue2_CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/examples/queue3/Makefile.am b/examples/queue3/Makefile.am index be6313ce6d..de2d00faab 100644 --- a/examples/queue3/Makefile.am +++ b/examples/queue3/Makefile.am @@ -1,5 +1,5 @@ noinst_PROGRAMS = queue3 -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +queue3_LDADD = $(GST_LIBS) +queue3_CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/examples/queue4/Makefile.am b/examples/queue4/Makefile.am index 0b1a4857b8..8d6e2eec95 100644 --- a/examples/queue4/Makefile.am +++ b/examples/queue4/Makefile.am @@ -1,5 +1,5 @@ noinst_PROGRAMS = queue4 -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +queue4_LDADD = $(GST_LIBS) +queue4_CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/examples/thread/Makefile.am b/examples/thread/Makefile.am index 4e019cb731..ae9f9ac759 100644 --- a/examples/thread/Makefile.am +++ b/examples/thread/Makefile.am @@ -1,5 +1,5 @@ noinst_PROGRAMS = thread -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +thread_LDADD = $(GST_LIBS) +thread_CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/examples/typefind/Makefile.am b/examples/typefind/Makefile.am index 57669bdcc0..e8a9b4f1c8 100644 --- a/examples/typefind/Makefile.am +++ b/examples/typefind/Makefile.am @@ -1,5 +1,5 @@ noinst_PROGRAMS = typefind -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +typefind_LDADD = $(GST_LIBS) +typefind_CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/examples/xml/Makefile.am b/examples/xml/Makefile.am index 24b890fd84..7b8e2f4745 100644 --- a/examples/xml/Makefile.am +++ b/examples/xml/Makefile.am @@ -1,5 +1,7 @@ noinst_PROGRAMS = createxml runxml -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +createxml_LDADD = $(GST_LIBS) +createxml_CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) +runxml_LDADD = $(GST_LIBS) +runxml_CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/gst/Makefile.am b/gst/Makefile.am index 79e72f96a3..76c92667bb 100644 --- a/gst/Makefile.am +++ b/gst/Makefile.am @@ -52,8 +52,8 @@ endif EXTRA_libgst_la_SOURCES = gstcpuid_i386.s gstmarshal.list gobject2gtk.c gobject2gtk.h gstxml.c gsttypefind.c gstparse.c gstautoplug.c gsttrace.c -SUBDIRS = . types elements $(GST_AUTOPLUG_DIRS) -DIST_SUBDIRS = types elements autoplug +SUBDIRS = . types elements $(GST_AUTOPLUG_DIRS) schedulers +DIST_SUBDIRS = types elements autoplug schedulers libgst_la_SOURCES = \ cothreads.c \ @@ -214,7 +214,6 @@ libgst_la_CFLAGS = -D_GNU_SOURCE -DGST_CONFIG_DIR=\""$(GST_CONFIG_DIR)"\" \ -Winline -Wno-unused libgst_la_LIBADD = $(LIBGST_LIBS) - libgst_la_LDFLAGS = -version-info $(GST_LIBVERSION) EXTRA_DIST = ROADMAP diff --git a/gst/autoplug/autoplugtest.c b/gst/autoplug/autoplugtest.c index 6385286788..bb8895f5c5 100644 --- a/gst/autoplug/autoplugtest.c +++ b/gst/autoplug/autoplugtest.c @@ -9,16 +9,16 @@ void cache_empty(GstElement *element, gpointer private) { gst_element_set_state (pipeline, GST_STATE_PAUSED); gst_element_disconnect(src,"src",cache,"sink"); - gst_schedule_show (GST_ELEMENT_SCHED(pipeline)); + gst_scheduler_show (GST_ELEMENT_SCHED(pipeline)); gst_element_disconnect(cache,"src",decoder,"sink"); - gst_schedule_show (GST_ELEMENT_SCHED(pipeline)); + gst_scheduler_show (GST_ELEMENT_SCHED(pipeline)); gst_bin_remove (GST_BIN(autobin), cache); - gst_schedule_show (GST_ELEMENT_SCHED(pipeline)); + gst_scheduler_show (GST_ELEMENT_SCHED(pipeline)); gst_element_connect(src,"src",decoder,"sink"); - gst_schedule_show (GST_ELEMENT_SCHED(pipeline)); + gst_scheduler_show (GST_ELEMENT_SCHED(pipeline)); gst_element_set_state (pipeline, GST_STATE_PLAYING); - gst_schedule_show (GST_ELEMENT_SCHED(pipeline)); + gst_scheduler_show (GST_ELEMENT_SCHED(pipeline)); fprintf(stderr,"done with cache_empty\n"); } @@ -32,7 +32,7 @@ void have_type(GstElement *element, GstCaps *caps, GstCaps **private_caps) { gst_element_disconnect(cache,"src",typefind,"sink"); gst_bin_remove(GST_BIN(autobin),typefind); - gst_schedule_show (GST_ELEMENT_SCHED(pipeline)); + gst_scheduler_show (GST_ELEMENT_SCHED(pipeline)); if (strstr(gst_caps_get_mime(caps),"mp3")) { decoder = gst_elementfactory_make ("mad","decoder"); diff --git a/gst/autoplug/gststaticautoplug.c b/gst/autoplug/gststaticautoplug.c index 2306080b1c..2530ad2049 100644 --- a/gst/autoplug/gststaticautoplug.c +++ b/gst/autoplug/gststaticautoplug.c @@ -475,8 +475,6 @@ differ: GST_DEBUG (0,"delaying the creation of a ghostpad for %s\n", GST_ELEMENT_NAME (thesrcelement)); g_signal_connect (G_OBJECT (thesrcelement), "new_pad", G_CALLBACK (autoplug_dynamic_pad), data); - g_signal_connect (G_OBJECT (thesrcelement), "new_ghost_pad", - G_CALLBACK (autoplug_dynamic_pad), data); } } } diff --git a/gst/autoplug/gststaticautoplugrender.c b/gst/autoplug/gststaticautoplugrender.c index 0c71fffc08..d4c9ad1a54 100644 --- a/gst/autoplug/gststaticautoplugrender.c +++ b/gst/autoplug/gststaticautoplugrender.c @@ -95,6 +95,9 @@ plugin_init (GModule *module, GstPlugin *plugin) if (factory != NULL) { gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory)); } + else { + g_warning ("could not register autoplugger: staticrender"); + } return TRUE; } @@ -232,8 +235,6 @@ gst_autoplug_pads_autoplug (GstElement *src, GstElement *sink) GST_ELEMENT_NAME(src), GST_ELEMENT_NAME(sink)); g_signal_connect (G_OBJECT(src),"new_pad", G_CALLBACK (gst_autoplug_pads_autoplug_func), sink); - g_signal_connect (G_OBJECT(src),"new_ghost_pad", - G_CALLBACK (gst_autoplug_pads_autoplug_func), sink); } } @@ -398,7 +399,7 @@ next: GST_DEBUG (0,"common factory \"%s\"\n", GST_OBJECT_NAME (factory)); - element = gst_elementfactory_create (factory, GST_OBJECT_NAME (factory)); + element = gst_elementfactory_create (factory, g_strdup (GST_OBJECT_NAME (factory))); gst_bin_add (GST_BIN(result), element); if (srcelement != NULL) { @@ -457,7 +458,7 @@ differ: factory = (GstElementFactory *)(factories[i]->data); GST_DEBUG (0,"factory \"%s\"\n", GST_OBJECT_NAME (factory)); - element = gst_elementfactory_create(factory, GST_OBJECT_NAME (factory)); + element = gst_elementfactory_create(factory, g_strdup (GST_OBJECT_NAME (factory))); } else { element = sinkelement; @@ -468,6 +469,7 @@ differ: if (GST_ELEMENT_IS_THREAD_SUGGESTED(element) || use_thread) { GstElement *queue; GstPad *srcpad; + GstElement *current_bin = thebin; use_thread = FALSE; @@ -491,7 +493,7 @@ differ: gst_bin_add(GST_BIN(thebin), element); gst_autoplug_signal_new_object (GST_AUTOPLUG (autoplug), GST_OBJECT (element)); GST_DEBUG (0,"adding element %s\n", GST_ELEMENT_NAME (thebin)); - gst_bin_add(GST_BIN(result), thebin); + gst_bin_add(GST_BIN(current_bin), thebin); gst_autoplug_signal_new_object (GST_AUTOPLUG (autoplug), GST_OBJECT (thebin)); thesrcelement = queue; } diff --git a/gst/elements/gstfakesink.c b/gst/elements/gstfakesink.c index 02eb921fa3..69b8740525 100644 --- a/gst/elements/gstfakesink.c +++ b/gst/elements/gstfakesink.c @@ -213,14 +213,6 @@ gst_fakesink_get_property (GObject *object, guint prop_id, GValue *value, GParam } } -/** - * gst_fakesink_chain: - * @pad: the pad this faksink is connected to - * @buffer: the buffer or event that has to be absorbed - * - * Take the buffer or event from the pad and unref it without doing - * anything with it. - */ static void gst_fakesink_chain (GstPad *pad, GstBuffer *buf) { @@ -232,21 +224,12 @@ gst_fakesink_chain (GstPad *pad, GstBuffer *buf) fakesink = GST_FAKESINK (gst_pad_get_parent (pad)); - if (GST_IS_EVENT(buf)) { - GstEvent *event = GST_EVENT (buf); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_EOS: - g_print("fakesink: have EOS event!\n"); - gst_element_set_state (GST_ELEMENT (fakesink), GST_STATE_PAUSED); - break; - default: - g_print("fakesink: have unhandled event!\n"); - break; - } - gst_event_free (event); + /* + if (GST_IS_EVENT (buf)) { + gst_pad_event_default (pad, GST_EVENT (buf)); return; } + */ if (!fakesink->silent) g_print("fakesink: chain ******* (%s:%s)< (%d bytes, %lld) %p\n", diff --git a/gst/gobject2gtk.h b/gst/gobject2gtk.h index a14203a263..03bd676077 100644 --- a/gst/gobject2gtk.h +++ b/gst/gobject2gtk.h @@ -220,6 +220,14 @@ gtk_signal_emit((GtkObject *)object,signal, ## args ) g_signal_connect(object,name,func,func_data) \ gtk_signal_connect((GtkObject *)object,name,func,func_data) +#define \ +g_signal_handlers_disconnect_by_func(object,func,func_data) \ +gtk_signal_disconnect_by_func((GtkObject *)object,func,func_data) + +#define \ +g_signal_connect_object(object,name,func,func_data) \ +gtk_signal_connect_object((GtkObject *)object,name,func,(GtkObject*)func_data) + #define \ g_signal_emit_by_name(object,name,data,self) \ gtk_signal_emit_by_name ((GtkObject *)object,name,data,self) @@ -251,8 +259,8 @@ GSList* g_slist_delete_link (GSList *list, GSList *link) __attribute__ ((no_ins typedef struct _GParamSpec GParamSpec; struct _GParamSpec { gchar *name; - gint value_type; - gint flags; + GType value_type; + GParamFlags flags; }; #define g_value_init(value,t) ((value)->type = (t)) diff --git a/gst/gst.c b/gst/gst.c index c6afbb12d5..6b47f66aa8 100644 --- a/gst/gst.c +++ b/gst/gst.c @@ -24,17 +24,8 @@ #include "gst_private.h" -#include "gstversion.h" -#include "gstcpu.h" -#include "gsttype.h" -#include "gstplugin.h" -#include "gstbuffer.h" -#include "gstbin.h" -#include "gstpipeline.h" -#include "gstthread.h" +#include "gst.h" #include "gstqueue.h" -#include "gstautoplug.h" -#include "gstscheduler.h" #ifndef GST_DISABLE_TYPEFIND #include "gsttypefind.h" #endif @@ -118,7 +109,7 @@ gst_init (int *argc, char **argv[]) gst_elementfactory_get_type (); gst_element_get_type (); gst_typefactory_get_type (); - gst_schedule_get_type (); + gst_schedulerfactory_get_type (); gst_bin_get_type (); #ifndef GST_DISABLE_AUTOPLUG gst_autoplugfactory_get_type (); @@ -166,7 +157,6 @@ split_and_iterate (const gchar *stringlist, gchar *separator, GFunc iterator) while (lastlist) { strings = g_strsplit (lastlist, separator, MAX_PATH_SPLIT); - //strings = g_strsplit (lastlist, G_SEARCHPATH_SEPARATOR_S, MAX_PATH_SPLIT); g_free (lastlist); lastlist = NULL; diff --git a/gst/gst.h b/gst/gst.h index 032d5d2c57..5fed0630f8 100644 --- a/gst/gst.h +++ b/gst/gst.h @@ -60,7 +60,7 @@ extern "C" { #endif /* __cplusplus */ /* initialize GST */ -void gst_init(int *argc,char **argv[]); +void gst_init (int *argc, char **argv[]); void gst_main (void); void gst_main_quit (void); diff --git a/gst/gstautoplug.c b/gst/gstautoplug.c index c1c813e65e..10e6df1b54 100644 --- a/gst/gstautoplug.c +++ b/gst/gstautoplug.c @@ -365,7 +365,7 @@ gst_autoplugfactory_make (const gchar *name) if (factory == NULL) return NULL; - return gst_autoplugfactory_create (factory);; + return gst_autoplugfactory_create (factory); } #ifndef GST_DISABLE_REGISTRY diff --git a/gst/gstbin.c b/gst/gstbin.c index 9a149d2b5f..579fce9a9a 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -45,6 +45,8 @@ static GstElementStateReturn gst_bin_change_state_norecurse (GstBin *bin); static gboolean gst_bin_change_state_type (GstBin *bin, GstElementState state, GType type); +static void gst_bin_child_state_change (GstBin *bin, GstElementState old, + GstElementState new, GstElement *child); static gboolean gst_bin_iterate_func (GstBin *bin); @@ -135,7 +137,6 @@ gst_bin_init (GstBin *bin) bin->children = NULL; bin->eos_providers = NULL; bin->num_eos_providers = 0; - bin->chains = NULL; bin->eoscond = g_cond_new (); } @@ -154,23 +155,15 @@ gst_bin_new (const gchar *name) } static inline void -gst_bin_reset_element_sched (GstElement *element, GstSchedule *sched) +gst_bin_reset_element_sched (GstElement *element, GstScheduler *sched) { GST_INFO_ELEMENT (GST_CAT_PARENTAGE, element, "resetting element's scheduler"); - // 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_sched (element,sched); - - // and add it to the new scheduler -// if (sched) -// GST_SCHEDULE_ADD_ELEMENT (sched, element); } static void -gst_bin_set_element_sched (GstElement *element,GstSchedule *sched) +gst_bin_set_element_sched (GstElement *element,GstScheduler *sched) { GList *children; GstElement *child; @@ -178,21 +171,20 @@ gst_bin_set_element_sched (GstElement *element,GstSchedule *sched) 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)); + g_return_if_fail (GST_IS_SCHEDULER(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)) { - - if (GST_FLAG_IS_SET(element,GST_BIN_FLAG_MANAGER)) { + if (GST_FLAG_IS_SET (element, GST_BIN_FLAG_MANAGER)) { GST_INFO_ELEMENT (GST_CAT_PARENTAGE, element, "child is already a manager, not resetting"); return; } GST_INFO_ELEMENT (GST_CAT_PARENTAGE, element, "setting children's schedule to parent's"); - GST_SCHEDULE_ADD_ELEMENT (sched, element); + gst_scheduler_add_element (sched, element); // set the children's schedule children = GST_BIN(element)->children; @@ -205,7 +197,7 @@ gst_bin_set_element_sched (GstElement *element,GstSchedule *sched) // otherwise, if it's just a regular old element } else { - GST_SCHEDULE_ADD_ELEMENT (sched, element); + gst_scheduler_add_element (sched, element); } } @@ -232,7 +224,7 @@ gst_bin_unset_element_sched (GstElement *element) // FIXME this check should be irrelevant if (GST_ELEMENT_SCHED (element)) - GST_SCHEDULE_REMOVE_ELEMENT (GST_ELEMENT_SCHED(element), element); + gst_scheduler_remove_element (GST_ELEMENT_SCHED(element), element); // for each child, remove them from their schedule children = GST_BIN(element)->children; @@ -247,7 +239,7 @@ gst_bin_unset_element_sched (GstElement *element) } else { // FIXME this check should be irrelevant if (GST_ELEMENT_SCHED (element)) - GST_SCHEDULE_REMOVE_ELEMENT (GST_ELEMENT_SCHED(element), element); + gst_scheduler_remove_element (GST_ELEMENT_SCHED(element), element); } } @@ -270,27 +262,33 @@ gst_bin_add (GstBin *bin, g_return_if_fail (GST_IS_ELEMENT (element)); GST_DEBUG (GST_CAT_PARENTAGE, "adding element \"%s\" to bin \"%s\"\n", - GST_ELEMENT_NAME(element),GST_ELEMENT_NAME(bin)); + GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (bin)); // must be not be in PLAYING state in order to modify bin -// g_return_if_fail (GST_STATE (bin) != GST_STATE_PLAYING); + g_return_if_fail (GST_STATE (bin) != GST_STATE_PLAYING); // the element must not already have a parent - g_return_if_fail (GST_ELEMENT_PARENT(element) == NULL); + g_return_if_fail (GST_ELEMENT_PARENT (element) == NULL); // then check to see if the element's name is already taken in the bin - g_return_if_fail (gst_object_check_uniqueness (bin->children, GST_ELEMENT_NAME(element)) == TRUE); + g_return_if_fail (gst_object_check_uniqueness (bin->children, GST_ELEMENT_NAME (element)) == TRUE); // set the element's parent and add the element to the bin's list of children gst_object_set_parent (GST_OBJECT (element), GST_OBJECT (bin)); + g_signal_connect_object (G_OBJECT (element), "state_change", gst_bin_child_state_change, G_OBJECT (bin)); + bin->children = g_list_append (bin->children, element); bin->numchildren++; ///// now we have to deal with manager stuff // 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)); + if (GST_IS_BIN(element) && GST_FLAG_IS_SET (element, GST_BIN_FLAG_MANAGER)) { + GST_INFO_ELEMENT (GST_CAT_PARENTAGE, element, "child is a manager"); + } + else 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)); @@ -343,6 +341,41 @@ gst_bin_remove (GstBin *bin, gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL); } +static void +gst_bin_child_state_change (GstBin *bin, GstElementState old, GstElementState new, GstElement *child) +{ + gint old_idx = 0, new_idx = 0, i; + + GST_INFO (GST_CAT_STATES, "child %s changed state in bin %s from %s to %s", + GST_ELEMENT_NAME (child), GST_ELEMENT_NAME (bin), + gst_element_statename (old), gst_element_statename (new)); + + while (old>>=1) old_idx++; + while (new>>=1) new_idx++; + + GST_LOCK (bin); + bin->child_states[old_idx]--; + bin->child_states[new_idx]++; + + for (i = GST_NUM_STATES-1; i >= 0; i--) { + if (bin->child_states[i] != 0) { + if (GST_STATE (bin) != (1 << i)) { + GST_INFO (GST_CAT_STATES, "bin %s need state change to %s", + GST_ELEMENT_NAME (bin), gst_element_statename (1<numchildren != 0, GST_STATE_FAILURE); - - -// g_print("-->\n"); children = bin->children; while (children) { child = GST_ELEMENT (children->data); -// GST_DEBUG (GST_CAT_STATES,"setting state on '%s'\n",GST_ELEMENT_NAME (child)); - switch (gst_element_set_state (child, GST_STATE_PENDING (element))) { + children = g_list_next (children); + + switch (gst_element_set_state (child, pending)) { case GST_STATE_FAILURE: GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING; GST_DEBUG (GST_CAT_STATES,"child '%s' failed to go to state %d(%s)\n", GST_ELEMENT_NAME (child), - GST_STATE_PENDING (element), gst_element_statename (GST_STATE_PENDING (element))); - return GST_STATE_FAILURE; + pending, gst_element_statename (pending)); + + gst_element_set_state (child, old_state); + if (GST_ELEMENT_SCHED (child) == GST_ELEMENT_SCHED (element)) { + return GST_STATE_FAILURE; + } break; case GST_STATE_ASYNC: GST_DEBUG (GST_CAT_STATES,"child '%s' is changing state asynchronously\n", GST_ELEMENT_NAME (child)); + have_async = TRUE; break; } -// g_print("\n"); - children = g_list_next (children); } -// g_print("<-- \"%s\"\n",GST_OBJECT_NAME(bin)); GST_INFO_ELEMENT (GST_CAT_STATES, element, "done changing bin's state from %s to %s", - gst_element_statename (GST_STATE (element)), - gst_element_statename (GST_STATE_PENDING (element))); - ret = gst_bin_change_state_norecurse (bin); + gst_element_statename (old_state), + gst_element_statename (pending)); + + if (have_async) + ret = GST_STATE_ASYNC; + else + ret = GST_STATE_SUCCESS; return ret; } @@ -410,20 +445,16 @@ gst_bin_change_state_norecurse (GstBin *bin) } static gboolean -gst_bin_change_state_type(GstBin *bin, - GstElementState state, - GType type) +gst_bin_change_state_type (GstBin *bin, + GstElementState state, + GType type) { GList *children; GstElement *child; -// g_print("gst_bin_change_state_type(\"%s\",%d,%d);\n", -// GST_OBJECT_NAME(bin))),state,type); - g_return_val_if_fail (GST_IS_BIN (bin), FALSE); g_return_val_if_fail (bin->numchildren != 0, FALSE); -// g_print("-->\n"); children = bin->children; while (children) { child = GST_ELEMENT (children->data); @@ -434,11 +465,10 @@ gst_bin_change_state_type(GstBin *bin, if (!gst_element_set_state (child,state)) return FALSE; } -// g_print("\n"); children = g_list_next (children); } if (type == GST_TYPE_BIN) - gst_element_set_state (GST_ELEMENT (bin),state); + gst_element_set_state (GST_ELEMENT (bin), state); return TRUE; } @@ -646,6 +676,18 @@ gst_bin_restore_thyself (GstObject *object, } #endif /* GST_DISABLE_LOADSAVE */ +static gboolean +gst_bin_iterate_func (GstBin *bin) +{ + // only iterate if this is the manager bin + if (GST_ELEMENT_SCHED(bin)->parent == GST_ELEMENT (bin)) { + return gst_scheduler_iterate (GST_ELEMENT_SCHED(bin)); + } else { + g_warning ("bin \"%d\" can't be iterated on!\n", GST_ELEMENT_NAME (bin)); + } + + return FALSE; +} /** * gst_bin_iterate: @@ -671,8 +713,14 @@ gst_bin_iterate (GstBin *bin) GST_DEBUG_LEAVE("(\"%s\")",GST_ELEMENT_NAME (bin)); -// if (!running) - // gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED); + if (!running) { + if (GST_STATE (bin) == GST_STATE_PLAYING && GST_STATE_PENDING (bin) == GST_STATE_VOID_PENDING) { + GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, bin, "waiting for child shutdown after useless iteration\n"); + //gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED); + gst_element_wait_state_change (GST_ELEMENT (bin)); + GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, bin, "child shutdown\n"); + } + } return running; } @@ -692,22 +740,3 @@ gst_bin_received_eos (GstElement *element, GstBin *bin) GST_UNLOCK (bin); } -typedef struct { - gulong offset; - gulong size; -} region_struct; - - -static gboolean -gst_bin_iterate_func (GstBin *bin) -{ - // only iterate if this is the manager bin - if (GST_ELEMENT_SCHED(bin)->parent == GST_ELEMENT (bin)) { - return GST_SCHEDULE_ITERATE(GST_ELEMENT_SCHED(bin)); - } else { - GST_DEBUG (GST_CAT_SCHEDULING, "this bin can't be iterated on!\n"); - } - - return FALSE; -} - diff --git a/gst/gstbin.h b/gst/gstbin.h index f8e2c6d7ca..2a9c22cf9f 100644 --- a/gst/gstbin.h +++ b/gst/gstbin.h @@ -64,7 +64,6 @@ typedef enum { //typedef struct _GstBin GstBin; //typedef struct _GstBinClass GstBinClass; -typedef struct __GstBinChain _GstBinChain; struct _GstBin { GstElement element; @@ -76,16 +75,8 @@ struct _GstBin { GList *eos_providers; GCond *eoscond; - /* iteration state */ - gboolean need_cothreads; - GList *managed_elements; - gint num_managed_elements; - - GList *chains; - gint num_chains; - GList *entries; - gint num_entries; - + GstElementState child_states[GST_NUM_STATES]; + cothread_context *threadcontext; }; @@ -104,37 +95,20 @@ struct _GstBinClass { gboolean (*iterate) (GstBin *bin); }; -struct __GstBinChain { - GList *elements; - gint num_elements; - - GList *entries; - - gboolean need_cothreads; - gboolean need_scheduling; -}; - - GType gst_bin_get_type (void); GstElement* gst_bin_new (const gchar *name); #define gst_bin_destroy(bin) gst_object_destroy(GST_OBJECT(bin)) /* add and remove elements from the bin */ -void gst_bin_add (GstBin *bin, - GstElement *element); -void gst_bin_remove (GstBin *bin, - GstElement *element); +void gst_bin_add (GstBin *bin, GstElement *element); +void gst_bin_remove (GstBin *bin, GstElement *element); /* retrieve a single element or the list of children */ -GstElement* gst_bin_get_by_name (GstBin *bin, - const gchar *name); -GstElement* gst_bin_get_by_name_recurse_up (GstBin *bin, - const gchar *name); +GstElement* gst_bin_get_by_name (GstBin *bin, const gchar *name); +GstElement* gst_bin_get_by_name_recurse_up (GstBin *bin, const gchar *name); GList* gst_bin_get_list (GstBin *bin); -gboolean gst_bin_set_state_type (GstBin *bin, - GstElementState state, - GType type); +gboolean gst_bin_set_state_type (GstBin *bin, GstElementState state, GType type); gboolean gst_bin_iterate (GstBin *bin); diff --git a/gst/gstbuffer.c b/gst/gstbuffer.c index 1a45f4f83b..eedf8fd9f1 100644 --- a/gst/gstbuffer.c +++ b/gst/gstbuffer.c @@ -46,6 +46,7 @@ _gst_buffer_initialize (void) 0, // sizeof(object), 0, NULL, + NULL, }; // round up to the nearest 32 bytes for cache-line and other efficiencies @@ -173,10 +174,10 @@ gst_buffer_create_sub (GstBuffer *parent, buffer->maxsize = parent->size - offset; // deal with bogus/unknown offsets - if (parent->offset != -1) + if (parent->offset != (guint32)-1) buffer->offset = parent->offset + offset; else - buffer->offset = -1; + buffer->offset = (guint32)-1; // again, for lack of better, copy parent's timestamp buffer->timestamp = parent->timestamp; @@ -240,6 +241,7 @@ gst_buffer_append (GstBuffer *buffer, newbuf->data = g_malloc (newbuf->size); memcpy (newbuf->data, buffer->data, buffer->size); memcpy (newbuf->data+buffer->size, append->data, append->size); + GST_BUFFER_TIMESTAMP (newbuf) = GST_BUFFER_TIMESTAMP (buffer); GST_BUFFER_UNLOCK (buffer); gst_buffer_unref (buffer); buffer = newbuf; @@ -489,7 +491,7 @@ gst_buffer_span (GstBuffer *buf1, guint32 offset, GstBuffer *buf2, guint32 len) // copy the second buffer's data across memcpy(newbuf->data + (buf1->size - offset), buf2->data, len - (buf1->size - offset)); - if (newbuf->offset != -1) + if (newbuf->offset != (guint32)-1) newbuf->offset = buf1->offset + offset; newbuf->timestamp = buf1->timestamp; if (buf2->maxage > buf1->maxage) newbuf->maxage = buf2->maxage; @@ -518,6 +520,11 @@ gst_buffer_span (GstBuffer *buf1, guint32 offset, GstBuffer *buf2, guint32 len) GstBuffer * gst_buffer_merge (GstBuffer *buf1, GstBuffer *buf2) { + GstBuffer *result; // we're just a specific case of the more general gst_buffer_span() - return gst_buffer_span (buf1, 0, buf2, buf1->size + buf2->size); + result = gst_buffer_span (buf1, 0, buf2, buf1->size + buf2->size); + + GST_BUFFER_TIMESTAMP (result) = GST_BUFFER_TIMESTAMP (buf1); + + return result; } diff --git a/gst/gstelement.c b/gst/gstelement.c index e7597af6a6..bcf8d50f3c 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -21,6 +21,7 @@ */ //#define GST_DEBUG_ENABLED +#include #include "gst_private.h" #include "gstelement.h" @@ -34,8 +35,6 @@ enum { STATE_CHANGE, NEW_PAD, PAD_REMOVED, - NEW_GHOST_PAD, - GHOST_PAD_REMOVED, ERROR, EOS, LAST_SIGNAL @@ -103,54 +102,44 @@ gst_element_class_init (GstElementClass *klass) gst_element_signals[STATE_CHANGE] = g_signal_new ("state_change", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GstElementClass, state_change), NULL, NULL, - gst_marshal_VOID__INT, G_TYPE_NONE, 1, - G_TYPE_INT); + G_STRUCT_OFFSET (GstElementClass, state_change), NULL, NULL, + gst_marshal_VOID__INT_INT, G_TYPE_NONE, 2, + G_TYPE_INT, G_TYPE_INT); gst_element_signals[NEW_PAD] = g_signal_new ("new_pad", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GstElementClass, new_pad), NULL, NULL, - gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, - GST_TYPE_PAD); + G_STRUCT_OFFSET (GstElementClass, new_pad), NULL, NULL, + gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, + GST_TYPE_PAD); gst_element_signals[PAD_REMOVED] = g_signal_new ("pad_removed", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GstElementClass, pad_removed), NULL, NULL, - gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, - GST_TYPE_PAD); - gst_element_signals[NEW_GHOST_PAD] = - g_signal_new ("new_ghost_pad", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GstElementClass, new_ghost_pad), NULL, NULL, - gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, - GST_TYPE_PAD); - gst_element_signals[GHOST_PAD_REMOVED] = - g_signal_new ("ghost_pad_removed", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GstElementClass, ghost_pad_removed), NULL, NULL, - gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, - GST_TYPE_PAD); + G_STRUCT_OFFSET (GstElementClass, pad_removed), NULL, NULL, + gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, + GST_TYPE_PAD); gst_element_signals[ERROR] = g_signal_new ("error", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GstElementClass, error), NULL, NULL, - gst_marshal_VOID__STRING, G_TYPE_NONE,1, - G_TYPE_STRING); + G_STRUCT_OFFSET (GstElementClass, error), NULL, NULL, + gst_marshal_VOID__STRING, G_TYPE_NONE,1, + G_TYPE_STRING); gst_element_signals[EOS] = g_signal_new ("eos", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GstElementClass,eos), NULL, NULL, - gst_marshal_VOID__VOID, G_TYPE_NONE, 0); + G_STRUCT_OFFSET (GstElementClass,eos), NULL, NULL, + gst_marshal_VOID__VOID, G_TYPE_NONE, 0); - gobject_class->set_property = GST_DEBUG_FUNCPTR(gst_element_set_property); - gobject_class->get_property = GST_DEBUG_FUNCPTR(gst_element_get_property); - gobject_class->dispose = GST_DEBUG_FUNCPTR(gst_element_dispose); + gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_element_set_property); + gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_element_get_property); + gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_element_dispose); #ifndef GST_DISABLE_LOADSAVE - gstobject_class->save_thyself = GST_DEBUG_FUNCPTR(gst_element_save_thyself); - gstobject_class->restore_thyself = GST_DEBUG_FUNCPTR(gst_element_restore_thyself); + gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_element_save_thyself); + gstobject_class->restore_thyself = GST_DEBUG_FUNCPTR (gst_element_restore_thyself); #endif - klass->change_state = GST_DEBUG_FUNCPTR(gst_element_change_state); - klass->elementfactory = NULL; - klass->padtemplates = NULL; - klass->numpadtemplates = 0; + klass->change_state = GST_DEBUG_FUNCPTR (gst_element_change_state); + klass->elementfactory = NULL; + klass->padtemplates = NULL; + klass->numpadtemplates = 0; } static void @@ -184,12 +173,8 @@ gst_element_set_property (GObject *object, guint prop_id, const GValue *value, G { GstElementClass *oclass = (GstElementClass *)G_OBJECT_GET_CLASS(object); - GST_SCHEDULE_LOCK_ELEMENT ( GST_ELEMENT_SCHED(object), GST_ELEMENT(object) ); - if (oclass->set_property) (oclass->set_property)(object,prop_id,value,pspec); - - GST_SCHEDULE_UNLOCK_ELEMENT ( GST_ELEMENT_SCHED(object), GST_ELEMENT(object) ); } @@ -198,12 +183,8 @@ gst_element_get_property (GObject *object, guint prop_id, GValue *value, GParamS { GstElementClass *oclass = (GstElementClass *)G_OBJECT_GET_CLASS(object); - GST_SCHEDULE_LOCK_ELEMENT (GST_ELEMENT_SCHED(object), GST_ELEMENT(object) ); - if (oclass->get_property) (oclass->get_property)(object,prop_id,value,pspec); - - GST_SCHEDULE_UNLOCK_ELEMENT (GST_ELEMENT_SCHED(object), GST_ELEMENT(object) ); } @@ -385,7 +366,7 @@ gst_element_add_ghost_pad (GstElement *element, GstPad *pad, gchar *name) GST_DEBUG(GST_CAT_ELEMENT_PADS,"added ghostpad %s:%s\n",GST_DEBUG_PAD_NAME(ghostpad)); /* emit the NEW_GHOST_PAD signal */ - g_signal_emit (G_OBJECT (element), gst_element_signals[NEW_GHOST_PAD], 0, ghostpad); + g_signal_emit (G_OBJECT (element), gst_element_signals[NEW_PAD], 0, ghostpad); } /** @@ -810,6 +791,27 @@ gst_element_get_state (GstElement *element) return GST_STATE (element); } +static void +gst_element_wait_done (GstElement *element, GstElementState old, GstElementState new, GCond *cond) +{ + g_signal_handlers_disconnect_by_func (G_OBJECT (element), gst_element_wait_done, cond); + g_cond_signal (cond); +} + +void +gst_element_wait_state_change (GstElement *element) +{ + GCond *cond = g_cond_new (); + GMutex *mutex = g_mutex_new (); + + g_mutex_lock (mutex); + g_signal_connect (G_OBJECT (element), "state_change", gst_element_wait_done, cond); + g_cond_wait (cond, mutex); + g_mutex_unlock (mutex); + + g_mutex_free (mutex); + g_cond_free (cond); +} /** * gst_element_set_state: * @element: element to change state of @@ -842,7 +844,7 @@ gst_element_set_state (GstElement *element, GstElementState state) curpending = GST_STATE(element); /* loop until the final requested state is set */ - while (GST_STATE(element) != state) { + while (GST_STATE(element) != state && GST_STATE (element) != GST_STATE_VOID_PENDING) { /* move the curpending state in the correct direction */ if (curpending < state) curpending<<=1; else curpending>>=1; @@ -859,24 +861,80 @@ gst_element_set_state (GstElement *element, GstElementState state) if (oclass->change_state) return_val = (oclass->change_state)(element); - /* if that outright didn't work, we need to bail right away */ - /* NOTE: this will bail on ASYNC as well! */ - if (return_val == GST_STATE_FAILURE) { - GST_DEBUG_ELEMENT (GST_CAT_STATES,element,"have failed change_state return\n"); - return return_val; - } - - /* Last thing we do is verify that a successful state change really - * did change the state... */ - if (GST_STATE(element) != curpending) { - GST_DEBUG_ELEMENT (GST_CAT_STATES, element, "element claimed state-change success, but state didn't change\n"); - return GST_STATE_FAILURE; + switch (return_val) { + case GST_STATE_FAILURE: + GST_DEBUG_ELEMENT (GST_CAT_STATES,element,"have failed change_state return\n"); + return return_val; + case GST_STATE_ASYNC: + GST_DEBUG_ELEMENT (GST_CAT_STATES,element,"element will change state async\n"); + return return_val; + default: + /* Last thing we do is verify that a successful state change really + * did change the state... */ + if (GST_STATE(element) != curpending) { + GST_DEBUG_ELEMENT (GST_CAT_STATES, element, "element claimed state-change success, but state didn't change\n"); + return GST_STATE_FAILURE; + } + break; } } return return_val; } +static GstElementStateReturn +gst_element_change_state (GstElement *element) +{ + GstElementState old_state; + + g_return_val_if_fail (element != NULL, GST_STATE_FAILURE); + g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE); + + old_state = GST_STATE (element); + + if (GST_STATE_PENDING (element) == GST_STATE_VOID_PENDING || old_state == GST_STATE_PENDING (element)) { + g_warning ("no state change needed for element %s (VOID_PENDING)\n", GST_ELEMENT_NAME (element)); + return GST_STATE_SUCCESS; + } + + GST_INFO (GST_CAT_STATES, "%s default handler sets state from %s to %s %d", GST_ELEMENT_NAME (element), + gst_element_statename (old_state), + gst_element_statename (GST_STATE_PENDING (element)), + GST_STATE_TRANSITION (element)); + + if (GST_STATE_TRANSITION (element) == GST_STATE_PAUSED_TO_PLAYING) { + g_return_val_if_fail (GST_ELEMENT_SCHED (element), GST_STATE_FAILURE); + + if (GST_ELEMENT_PARENT (element)) { + GST_DEBUG (GST_CAT_STATES, "PAUSED->PLAYING: element \"%s\" has parent \"%s\" and sched %p\n", + GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (GST_ELEMENT_PARENT (element)), + GST_ELEMENT_SCHED (element)); + } + gst_scheduler_enable_element (element->sched, element); + } + else if (GST_STATE_TRANSITION (element) == GST_STATE_PLAYING_TO_PAUSED) { + if (GST_ELEMENT_PARENT (element)) { + GST_DEBUG (GST_CAT_STATES, "PLAYING->PAUSED: element \"%s\" has parent \"%s\" and sched %p\n", + GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (GST_ELEMENT_PARENT (element)), + GST_ELEMENT_SCHED (element)); + } + gst_scheduler_disable_element (element->sched, element); + } + + GST_STATE (element) = GST_STATE_PENDING (element); + GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING; + + // note: queues' state_change is a special case because it needs to lock + // for synchronization (from another thread). since this signal may block + // or (worse) make another state change, the queue needs to unlock before + // calling. thus, gstqueue.c::gst_queue_state_change() blocks, unblocks, + // unlocks, then emits this. + g_signal_emit (G_OBJECT (element), gst_element_signals[STATE_CHANGE], 0, + old_state, GST_STATE (element)); + + return GST_STATE_SUCCESS; +} + /** * gst_element_get_factory: * @element: element to request the factory @@ -898,53 +956,6 @@ gst_element_get_factory (GstElement *element) return oclass->elementfactory; } - -/** - * gst_element_change_state: - * @element: element to change state of - * - * Changes the state of the element, but more importantly fires off a signal - * indicating the new state. - * The element will have no pending states anymore. - * - * Returns: whether or not the state change was successfully set. - */ -GstElementStateReturn -gst_element_change_state (GstElement *element) -{ - g_return_val_if_fail (element != NULL, GST_STATE_FAILURE); - g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE); - -// GST_DEBUG_ELEMENT (GST_CAT_STATES, element, "default handler sets state to %s\n", -// gst_element_statename(GST_STATE_PENDING(element))); - - if (GST_STATE_TRANSITION(element) == GST_STATE_PAUSED_TO_PLAYING) { - g_return_val_if_fail(GST_ELEMENT_SCHED(element), GST_STATE_FAILURE); - if (GST_ELEMENT_PARENT(element)) - GST_DEBUG(GST_CAT_STATES,"PAUSED->PLAYING: element \"%s\" has parent \"%s\" and sched %p\n", -GST_ELEMENT_NAME(element),GST_ELEMENT_NAME(GST_ELEMENT_PARENT(element)),GST_ELEMENT_SCHED(element)); - GST_SCHEDULE_ENABLE_ELEMENT (element->sched,element); - } - else if (GST_STATE_TRANSITION(element) == GST_STATE_PLAYING_TO_PAUSED) { - if (GST_ELEMENT_PARENT(element)) - GST_DEBUG(GST_CAT_STATES,"PLAYING->PAUSED: element \"%s\" has parent \"%s\" and sched %p\n", -GST_ELEMENT_NAME(element),GST_ELEMENT_NAME(GST_ELEMENT_PARENT(element)),GST_ELEMENT_SCHED(element)); - GST_SCHEDULE_DISABLE_ELEMENT (element->sched,element); - } - - GST_STATE (element) = GST_STATE_PENDING (element); - GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING; - - // note: queues' state_change is a special case because it needs to lock - // for synchronization (from another thread). since this signal may block - // or (worse) make another state change, the queue needs to unlock before - // calling. thus, gstqueue.c::gst_queue_state_change() blocks, unblocks, - // unlocks, then emits this. - g_signal_emit (G_OBJECT (element), gst_element_signals[STATE_CHANGE], 0, - GST_STATE (element)); - return GST_STATE_SUCCESS; -} - static void gst_element_dispose (GObject *object) { @@ -1183,14 +1194,14 @@ gst_element_restore_thyself (xmlNodePtr self, GstObject *parent) /** * gst_element_set_sched: * @element: Element to set manager of. - * @sched: @GstSchedule to set. + * @sched: @GstScheduler to set. * * Sets the scheduler of the element. For internal use only, unless you're * writing a new bin subclass. */ void gst_element_set_sched (GstElement *element, - GstSchedule *sched) + GstScheduler *sched) { GST_INFO_ELEMENT (GST_CAT_PARENTAGE, element, "setting scheduler to %p",sched); element->sched = sched; @@ -1204,7 +1215,7 @@ gst_element_set_sched (GstElement *element, * * Returns: Element's scheduler */ -GstSchedule* +GstScheduler* gst_element_get_sched (GstElement *element) { return element->sched; @@ -1270,7 +1281,7 @@ gst_element_statename (GstElementState state) case GST_STATE_READY: return "\033[01;31mREADY\033[00m";break; case GST_STATE_PLAYING: return "\033[01;32mPLAYING\033[00m";break; case GST_STATE_PAUSED: return "\033[01;33mPAUSED\033[00m";break; - default: return "\033[01;37;41mUNKNOWN!\033[00m"; + default: return g_strdup_printf ("\033[01;37;41mUNKNOWN!\033[00m(%d)", state); #else case GST_STATE_VOID_PENDING: return "NONE_PENDING";break; case GST_STATE_NULL: return "NULL";break; diff --git a/gst/gstelement.h b/gst/gstelement.h index 9748e9b6d4..41197eb302 100644 --- a/gst/gstelement.h +++ b/gst/gstelement.h @@ -35,6 +35,7 @@ extern "C" { #endif /* __cplusplus */ +#define GST_NUM_STATES 4 typedef enum { GST_STATE_VOID_PENDING = 0, @@ -106,9 +107,6 @@ typedef enum { /* the element has to be scheduled as a cothread for any sanity */ GST_ELEMENT_USE_COTHREAD, - /* if this element is in EOS */ - GST_ELEMENT_EOS, - /* if this element can handle events */ GST_ELEMENT_EVENT_AWARE, @@ -141,7 +139,7 @@ struct _GstElement { guint8 current_state; guint8 pending_state; GstElement *manager; - GstSchedule *sched; + GstScheduler *sched; GstElementLoopFunction loopfunc; cothread_state *threadstate; @@ -163,12 +161,10 @@ struct _GstElementClass { gint numpadtemplates; /* signal callbacks */ - void (*state_change) (GstElement *element,GstElementState state); - void (*new_pad) (GstElement *element,GstPad *pad); - void (*pad_removed) (GstElement *element,GstPad *pad); - void (*new_ghost_pad) (GstElement *element,GstPad *pad); - void (*ghost_pad_removed) (GstElement *element,GstPad *pad); - void (*error) (GstElement *element,gchar *error); + void (*state_change) (GstElement *element, GstElementState old, GstElementState state); + void (*new_pad) (GstElement *element, GstPad *pad); + void (*pad_removed) (GstElement *element, GstPad *pad); + void (*error) (GstElement *element, gchar *error); void (*eos) (GstElement *element); /* local pointers for get/set */ @@ -195,8 +191,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_sched (GstElement *element, GstSchedule *sched); -GstSchedule* gst_element_get_sched (GstElement *element); +void gst_element_set_sched (GstElement *element, GstScheduler *sched); +GstScheduler* gst_element_get_sched (GstElement *element); void gst_element_add_pad (GstElement *element, GstPad *pad); void gst_element_remove_pad (GstElement *element, GstPad *pad); @@ -219,9 +215,11 @@ void gst_element_signal_eos (GstElement *element); GstElementState gst_element_get_state (GstElement *element); -/* called by the app to set the state of the element */ gint gst_element_set_state (GstElement *element, GstElementState state); -const gchar * gst_element_statename (GstElementState state); + +void gst_element_wait_state_change (GstElement *element); + +const gchar* gst_element_statename (GstElementState state); void gst_element_error (GstElement *element, const gchar *error); diff --git a/gst/gstelementfactory.c b/gst/gstelementfactory.c index b2079f9589..4fcb8864c0 100644 --- a/gst/gstelementfactory.c +++ b/gst/gstelementfactory.c @@ -25,15 +25,15 @@ #include "gstelement.h" -static void gst_elementfactory_class_init (GstElementFactoryClass *klass); -static void gst_elementfactory_init (GstElementFactory *factory); +static void gst_elementfactory_class_init (GstElementFactoryClass *klass); +static void gst_elementfactory_init (GstElementFactory *factory); #ifndef GST_DISABLE_REGISTRY -static void gst_elementfactory_restore_thyself (GstObject *object, xmlNodePtr parent); -static xmlNodePtr gst_elementfactory_save_thyself (GstObject *object, xmlNodePtr parent); +static void gst_elementfactory_restore_thyself (GstObject *object, xmlNodePtr parent); +static xmlNodePtr gst_elementfactory_save_thyself (GstObject *object, xmlNodePtr parent); #endif -static void gst_elementfactory_unload_thyself (GstPluginFeature *feature); +static void gst_elementfactory_unload_thyself (GstPluginFeature *feature); /* global list of registered elementfactories */ static GList* _gst_elementfactories; diff --git a/gst/gstevent.c b/gst/gstevent.c index e06ed50cca..f4f289cfc1 100644 --- a/gst/gstevent.c +++ b/gst/gstevent.c @@ -43,6 +43,7 @@ _gst_event_initialize (void) 0, 0, NULL, + NULL, }; // round up to the nearest 32 bytes for cache-line and other efficiencies diff --git a/gst/gstpad.c b/gst/gstpad.c index c753d01b83..a0d6558aca 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -539,9 +539,7 @@ gst_pad_disconnect (GstPad *srcpad, // now tell the scheduler if (realsrc->sched) - GST_SCHEDULE_PAD_DISCONNECT (realsrc->sched, (GstPad *)realsrc, (GstPad *)realsink); -// if (realsink->sched) -// GST_SCHEDULE_PAD_DISCONNECT (realsink->sched, (GstPad *)realsrc, (GstPad *)realsink); + gst_scheduler_pad_connect (realsrc->sched, (GstPad *)realsrc, (GstPad *)realsink); GST_INFO (GST_CAT_ELEMENT_PADS, "disconnected %s:%s and %s:%s", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad)); @@ -651,9 +649,9 @@ gst_pad_try_connect (GstPad *srcpad, // now tell the scheduler(s) if (realsrc->sched) - GST_SCHEDULE_PAD_CONNECT (realsrc->sched, (GstPad *)realsrc, (GstPad *)realsink); + gst_scheduler_pad_connect (realsrc->sched, (GstPad *)realsrc, (GstPad *)realsink); else if (realsink->sched) - GST_SCHEDULE_PAD_CONNECT (realsink->sched, (GstPad *)realsrc, (GstPad *)realsink); + gst_scheduler_pad_connect (realsink->sched, (GstPad *)realsrc, (GstPad *)realsink); GST_INFO (GST_CAT_PADS, "connected %s:%s and %s:%s", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad)); @@ -723,7 +721,7 @@ gst_pad_get_padtemplate (GstPad *pad) * Set the sceduler for the pad */ void -gst_pad_set_sched (GstPad *pad, GstSchedule *sched) +gst_pad_set_sched (GstPad *pad, GstScheduler *sched) { g_return_if_fail (pad != NULL); g_return_if_fail (GST_IS_PAD (pad)); @@ -739,7 +737,7 @@ gst_pad_set_sched (GstPad *pad, GstSchedule *sched) * * Returns: the scheduler of the pad. */ -GstSchedule* +GstScheduler* gst_pad_get_sched (GstPad *pad) { g_return_val_if_fail (pad != NULL, NULL); @@ -1580,7 +1578,7 @@ gst_pad_select (GList *padlist) { GstPad *pad; - pad = gst_schedule_pad_select (gst_pad_get_sched (GST_PAD (padlist->data)), padlist); + pad = gst_scheduler_pad_select (gst_pad_get_sched (GST_PAD (padlist->data)), padlist); return pad; } @@ -1971,7 +1969,7 @@ gst_pad_event_default (GstPad *pad, GstEvent *event) GList *pads = element->pads; while (pads) { - if (GST_PAD_DIRECTION (pads->data) == GST_PAD_SRC) { + if (GST_PAD_DIRECTION (pads->data) == GST_PAD_SRC && GST_PAD_CONNECTED (pads->data)) { gst_pad_push (GST_PAD (pads->data), GST_BUFFER (gst_event_new (GST_EVENT_TYPE (event)))); } pads = g_list_next (pads); diff --git a/gst/gstpad.h b/gst/gstpad.h index 7eb962afc4..c73ecf740b 100644 --- a/gst/gstpad.h +++ b/gst/gstpad.h @@ -178,7 +178,7 @@ struct _GstRealPad { guint64 offset; guint64 len; - GstSchedule *sched; + GstScheduler *sched; GstPadChainFunction chainfunc; GstPadChainFunction chainhandler; @@ -361,8 +361,8 @@ void gst_pad_set_parent (GstPad *pad, GstObject *parent); GstElement* gst_pad_get_parent (GstPad *pad); GstElement* gst_pad_get_real_parent (GstPad *pad); -void gst_pad_set_sched (GstPad *pad, GstSchedule *sched); -GstSchedule* gst_pad_get_sched (GstPad *pad); +void gst_pad_set_sched (GstPad *pad, GstScheduler *sched); +GstScheduler* 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); diff --git a/gst/gstparse.c b/gst/gstparse.c index 533d0cfc5a..bf8ffd7ea6 100644 --- a/gst/gstparse.c +++ b/gst/gstparse.c @@ -383,8 +383,6 @@ gst_parse_launch_cmdline(int argc,char *argv[],GstBin *parent,gst_parse_priv *pr g_signal_connect (G_OBJECT (previous), "new_pad", G_CALLBACK (dynamic_connect), connect); - g_signal_connect (G_OBJECT (previous), "new_ghost_pad", - G_CALLBACK (dynamic_connect), connect); } else { for (j=0; (jchange_state = gst_pipeline_change_state; } @@ -100,8 +100,8 @@ gst_pipeline_init (GstPipeline *pipeline) // we're a manager by default GST_FLAG_SET (pipeline, GST_BIN_FLAG_MANAGER); - GST_ELEMENT_SCHED(pipeline) = gst_schedule_new(GST_ELEMENT(pipeline)); - GST_DEBUG(GST_CAT_PIPELINE, "pipeline's scheduler is %p\n",GST_ELEMENT_SCHED(pipeline)); + GST_ELEMENT_SCHED (pipeline) = gst_schedulerfactory_make ("basic", GST_ELEMENT (pipeline)); + GST_DEBUG (GST_CAT_PIPELINE, "pipeline's scheduler is %p\n", GST_ELEMENT_SCHED (pipeline)); } diff --git a/gst/gstplugin.c b/gst/gstplugin.c index 753c6666da..38c3b5607f 100644 --- a/gst/gstplugin.c +++ b/gst/gstplugin.c @@ -86,6 +86,8 @@ _gst_plugin_initialize (void) PLUGINS_BUILDDIR "/gst/types"); _gst_plugin_paths = g_list_prepend (_gst_plugin_paths, PLUGINS_BUILDDIR "/gst/autoplug"); + _gst_plugin_paths = g_list_prepend (_gst_plugin_paths, + PLUGINS_BUILDDIR "/gst/schedulers"); #endif /* PLUGINS_USE_BUILDDIR */ #ifndef GST_DISABLE_REGISTRY diff --git a/gst/gstqueue.c b/gst/gstqueue.c index f78792d69a..cdad2e7aaf 100644 --- a/gst/gstqueue.c +++ b/gst/gstqueue.c @@ -265,6 +265,7 @@ gst_queue_chain (GstPad *pad, GstBuffer *buf) reader = FALSE; +restart: /* we have to lock the queue since we span threads */ GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "locking t:%ld\n", pthread_self ()); g_mutex_lock (queue->qlock); @@ -277,6 +278,8 @@ gst_queue_chain (GstPad *pad, GstBuffer *buf) gst_queue_locked_flush (queue); break; case GST_EVENT_EOS: + GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "eos in on %s %d\n", + GST_ELEMENT_NAME (queue), queue->level_buffers); break; default: gst_pad_event_default (pad, GST_EVENT (buf)); @@ -327,19 +330,13 @@ gst_queue_chain (GstPad *pad, GstBuffer *buf) while (queue->level_buffers == queue->size_buffers) { // if there's a pending state change for this queue or its manager, switch // back to iterator so bottom half of state change executes - if (GST_STATE_PENDING(queue) != GST_STATE_VOID_PENDING || -// GST_STATE_PENDING(GST_SCHEDULE(GST_ELEMENT(queue)->sched)->parent) != GST_STATE_VOID_PENDING) -GST_STATE_PENDING(GST_SCHED_PARENT(GST_ELEMENT_SCHED(GST_PAD_PARENT(GST_PAD_PEER(queue->sinkpad))))) != -GST_STATE_VOID_PENDING) - { + while (GST_STATE (queue) != GST_STATE_PLAYING) { GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "interrupted!!\n"); - if (GST_STATE_PENDING(queue) != GST_STATE_VOID_PENDING) - GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "GST_STATE_PENDING(queue) != GST_STATE_VOID_PENDING)\n"); - if (GST_STATE_PENDING(GST_SCHEDULE(GST_ELEMENT(queue)->sched)->parent) != GST_STATE_VOID_PENDING) - GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "GST_STATE_PENDING(GST_SCHEDULE(GST_ELEMENT(queue)->sched)->parent) != GST_STATE_VOID_PENDING\n"); g_mutex_unlock (queue->qlock); cothread_switch(cothread_current_main()); + goto restart; } + g_assert (GST_STATE (queue) == GST_STATE_PLAYING); GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "waiting for not_full, level:%d/%d\n", queue->level_buffers, queue->size_buffers); if (queue->writer) @@ -390,6 +387,7 @@ gst_queue_get (GstPad *pad) writer = FALSE; +restart: /* have to lock for thread-safety */ GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "locking t:%ld\n", pthread_self ()); g_mutex_lock (queue->qlock); @@ -399,19 +397,13 @@ gst_queue_get (GstPad *pad) while (queue->level_buffers == 0) { // if there's a pending state change for this queue or its manager, switch // back to iterator so bottom half of state change executes - if (GST_STATE_PENDING(queue) != GST_STATE_VOID_PENDING || -// GST_STATE_PENDING(GST_SCHEDULE(GST_ELEMENT(queue)->sched)->parent) != GST_STATE_VOID_PENDING) -GST_STATE_PENDING(GST_SCHED_PARENT(GST_ELEMENT_SCHED(GST_PAD_PARENT(GST_PAD_PEER(queue->srcpad))))) != -GST_STATE_VOID_PENDING) - { + while (GST_STATE (queue) != GST_STATE_PLAYING) { GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "interrupted!!\n"); - if (GST_STATE_PENDING(queue) != GST_STATE_VOID_PENDING) - GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "GST_STATE_PENDING(queue) != GST_STATE_VOID_PENDING)\n"); - if (GST_STATE_PENDING(GST_SCHEDULE(GST_ELEMENT(queue)->sched)->parent) != GST_STATE_VOID_PENDING) - GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "GST_STATE_PENDING(GST_SCHEDULE(GST_ELEMENT(queue)->sched)->parent) != GST_STATE_VOID_PENDING\n"); g_mutex_unlock (queue->qlock); cothread_switch(cothread_current_main()); + goto restart; } + g_assert (GST_STATE (queue) == GST_STATE_PLAYING); GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "waiting for not_empty, level:%d/%d\n", queue->level_buffers, queue->size_buffers); if (queue->reader) @@ -451,7 +443,7 @@ GST_STATE_VOID_PENDING) GstEvent *event = GST_EVENT(buf); switch (GST_EVENT_TYPE(event)) { case GST_EVENT_EOS: - GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "queue eos\n"); + GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "queue \"%s\" eos\n", GST_ELEMENT_NAME (queue)); gst_element_set_state (GST_ELEMENT (queue), GST_STATE_PAUSED); break; default: @@ -467,56 +459,41 @@ gst_queue_change_state (GstElement *element) { GstQueue *queue; GstElementStateReturn ret; + GstElementState new_state; g_return_val_if_fail (GST_IS_QUEUE (element), GST_STATE_FAILURE); queue = GST_QUEUE (element); + GST_DEBUG_ENTER("('%s')", GST_ELEMENT_NAME (element)); + // lock the queue so another thread (not in sync with this thread's state) // can't call this queue's _get (or whatever) - GST_LOCK (queue); + g_mutex_lock (queue->qlock); - /* if going down into NULL state, clear out buffers*/ - if (GST_STATE_PENDING (element) == GST_STATE_READY) { - /* otherwise (READY or higher) we need to open the file */ - gst_queue_flush (queue); + new_state = GST_STATE_PENDING (element); + + if (new_state == GST_STATE_PAUSED) { + g_cond_signal (queue->not_full); + g_cond_signal (queue->not_empty); + } + else if (new_state == GST_STATE_READY) { + gst_queue_locked_flush (queue); + } + else if (new_state == GST_STATE_PLAYING) { + if (!GST_PAD_CONNECTED (queue->sinkpad)) { + // FIXME can this be? + if (queue->reader) + g_cond_signal (queue->not_empty); + g_mutex_unlock (queue->qlock); + + return GST_STATE_FAILURE; + } } - // if we haven't failed already, give the parent class a chance to ;-) - if (GST_ELEMENT_CLASS (parent_class)->change_state) - { - gboolean valid_handler = FALSE; - guint state_change_id = g_signal_lookup("state_change", G_OBJECT_TYPE(element)); - - // determine whether we need to block the parent (element) class' - // STATE_CHANGE signal so we can UNLOCK before returning. we block - // it if we could find the state_change signal AND there's a signal - // handler attached to it. - // - // note: this assumes that change_state() *only* emits state_change signal. - // if element change_state() emits other signals, they need to be blocked - // as well. - if (state_change_id && - g_signal_has_handler_pending(G_OBJECT(element), state_change_id, 0, FALSE)) - valid_handler = TRUE; - if (valid_handler) - g_signal_handler_block(G_OBJECT(element), state_change_id); - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element); - - if (valid_handler) - g_signal_handler_unblock(G_OBJECT(element), state_change_id); - - // UNLOCK, *then* emit signal (if there's one there) - GST_UNLOCK(queue); - if (valid_handler) - g_signal_emit(G_OBJECT (element), state_change_id, 0, GST_STATE(element)); - } - else - { - ret = GST_STATE_SUCCESS; - GST_UNLOCK(queue); - } + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element); + g_mutex_unlock (queue->qlock); + GST_DEBUG_LEAVE("('%s')", GST_ELEMENT_NAME (element)); return ret; } diff --git a/gst/gstscheduler.c b/gst/gstscheduler.c index ccef994f6a..d11c93410c 100644 --- a/gst/gstscheduler.c +++ b/gst/gstscheduler.c @@ -1,6 +1,6 @@ /* GStreamer * Copyright (C) 1999,2000 Erik Walthinsen - * 2000 Wim Taymans + * 2000 Wim Taymans * * gstscheduler.c: Default scheduling code for most cases * @@ -20,1606 +20,451 @@ * Boston, MA 02111-1307, USA. */ -//#define GST_DEBUG_ENABLED +#define CLASS(obj) GST_SCHEDULER_CLASS (G_OBJECT_GET_CLASS (obj)) + #include "gst_private.h" #include "gstscheduler.h" -GType _gst_schedule_type = 0; - -static int -gst_schedule_loopfunc_wrapper (int argc,char *argv[]) -{ - GstElement *element = GST_ELEMENT (argv); - G_GNUC_UNUSED const gchar *name = GST_ELEMENT_NAME (element); - - GST_DEBUG_ENTER("(%d,'%s')",argc,name); - - do { - GST_DEBUG (GST_CAT_DATAFLOW,"calling loopfunc %s for element %s\n", - GST_DEBUG_FUNCPTR_NAME (element->loopfunc),name); - (element->loopfunc) (element); - GST_DEBUG (GST_CAT_DATAFLOW,"element %s ended loop function\n", name); - } while (!GST_ELEMENT_IS_COTHREAD_STOPPING(element)); - GST_FLAG_UNSET(element,GST_ELEMENT_COTHREAD_STOPPING); - - GST_DEBUG_LEAVE("(%d,'%s')",argc,name); - return 0; -} - -static int -gst_schedule_chain_wrapper (int argc,char *argv[]) -{ - GstElement *element = GST_ELEMENT (argv); - G_GNUC_UNUSED const gchar *name = GST_ELEMENT_NAME (element); - - GST_DEBUG_ENTER("(\"%s\")",name); - - GST_DEBUG (GST_CAT_DATAFLOW,"stepping through pads\n"); - - do { - GList *pads = element->pads; - - while (pads) { - GstPad *pad = GST_PAD (pads->data); - GstRealPad *realpad; - - pads = g_list_next (pads); - if (!GST_IS_REAL_PAD(pad)) - continue; - realpad = GST_REAL_PAD(pad); - if (GST_RPAD_DIRECTION (realpad) == GST_PAD_SINK) { - GstBuffer *buf; - - GST_DEBUG (GST_CAT_DATAFLOW,"pulling data from %s:%s\n", name, GST_PAD_NAME (pad)); - buf = gst_pad_pull (pad); - if (buf) { - if (GST_IS_EVENT (buf) && !GST_ELEMENT_IS_EVENT_AWARE (element)) { - //gst_pad_event_default (pad, GST_EVENT (buf)); - gst_pad_send_event (pad, GST_EVENT (buf)); - } - else { - GST_DEBUG (GST_CAT_DATAFLOW,"calling chain function of %s:%s\n", name, GST_PAD_NAME (pad)); - GST_RPAD_CHAINFUNC(realpad) (pad, buf); - } - } - GST_DEBUG (GST_CAT_DATAFLOW,"calling chain function of %s:%s done\n", name, GST_PAD_NAME (pad)); - } - } - } while (!GST_ELEMENT_IS_COTHREAD_STOPPING(element)); - GST_FLAG_UNSET(element,GST_ELEMENT_COTHREAD_STOPPING); - - GST_DEBUG_LEAVE("(%d,'%s')",argc,name); - return 0; -} - -static int -gst_schedule_src_wrapper (int argc,char *argv[]) -{ - GstElement *element = GST_ELEMENT (argv); - GList *pads; - GstRealPad *realpad; - GstBuffer *buf = NULL; - G_GNUC_UNUSED const gchar *name = GST_ELEMENT_NAME (element); - - GST_DEBUG_ENTER("(%d,\"%s\")",argc,name); - - do { - pads = element->pads; - while (pads) { - if (!GST_IS_REAL_PAD(pads->data)) continue; - realpad = (GstRealPad*)(pads->data); - pads = g_list_next(pads); - if (GST_RPAD_DIRECTION(realpad) == GST_PAD_SRC) { - GST_DEBUG (GST_CAT_DATAFLOW,"calling _getfunc for %s:%s\n",GST_DEBUG_PAD_NAME(realpad)); - if (realpad->regiontype != GST_REGION_VOID) { - g_return_val_if_fail (GST_RPAD_GETREGIONFUNC(realpad) != NULL, 0); -// if (GST_RPAD_GETREGIONFUNC(realpad) == NULL) -// fprintf(stderr,"error, no getregionfunc in \"%s\"\n", name); -// else - buf = (GST_RPAD_GETREGIONFUNC(realpad))((GstPad*)realpad,realpad->regiontype,realpad->offset,realpad->len); - realpad->regiontype = GST_REGION_VOID; - } else { - g_return_val_if_fail (GST_RPAD_GETFUNC(realpad) != NULL, 0); -// if (GST_RPAD_GETFUNC(realpad) == NULL) -// fprintf(stderr,"error, no getfunc in \"%s\"\n", name); -// else - buf = GST_RPAD_GETFUNC(realpad) ((GstPad*)realpad); - } - - GST_DEBUG (GST_CAT_DATAFLOW,"calling gst_pad_push on pad %s:%s\n",GST_DEBUG_PAD_NAME(realpad)); - gst_pad_push ((GstPad*)realpad, buf); - } - } - } while (!GST_ELEMENT_IS_COTHREAD_STOPPING(element)); - GST_FLAG_UNSET(element,GST_ELEMENT_COTHREAD_STOPPING); - - GST_DEBUG_LEAVE(""); - return 0; -} - -static void -gst_schedule_chainhandler_proxy (GstPad *pad, GstBuffer *buf) -{ - GstRealPad *peer = GST_RPAD_PEER(pad); - - GST_DEBUG_ENTER("(%s:%s)",GST_DEBUG_PAD_NAME(pad)); - GST_DEBUG (GST_CAT_DATAFLOW,"putting buffer %p in peer \"%s:%s\"'s pen\n",buf,GST_DEBUG_PAD_NAME(peer)); - - // FIXME this should be bounded - // loop until the bufferpen is empty so we can fill it up again - while (GST_RPAD_BUFPEN(pad) != NULL) { - GST_DEBUG (GST_CAT_DATAFLOW, "switching to %p to empty bufpen\n", - GST_ELEMENT (GST_PAD_PARENT (pad))->threadstate); - cothread_switch (GST_ELEMENT (GST_PAD_PARENT (pad))->threadstate); - - // we may no longer be the same pad, check. - if (GST_RPAD_PEER(peer) != (GstRealPad *)pad) { - GST_DEBUG (GST_CAT_DATAFLOW, "new pad in mid-switch!\n"); - pad = (GstPad *)GST_RPAD_PEER(peer); - } - } - - g_assert (GST_RPAD_BUFPEN(GST_RPAD_PEER(pad)) == NULL); - // now fill the bufferpen and switch so it can be consumed - GST_RPAD_BUFPEN(GST_RPAD_PEER(pad)) = buf; - GST_DEBUG (GST_CAT_DATAFLOW,"switching to %p\n",GST_ELEMENT (GST_PAD_PARENT (pad))->threadstate); - cothread_switch (GST_ELEMENT (GST_PAD_PARENT (pad))->threadstate); - - GST_DEBUG (GST_CAT_DATAFLOW,"done switching\n"); -} - -static void -gst_schedule_select_proxy (GstPad *pad, GstBuffer *buf) -{ - GstRealPad *peer = GST_RPAD_PEER(pad); - - g_print ("select proxy (%s:%s)\n",GST_DEBUG_PAD_NAME(pad)); - - GST_DEBUG_ENTER("(%s:%s)",GST_DEBUG_PAD_NAME(pad)); - - GST_DEBUG (GST_CAT_DATAFLOW,"putting buffer %p in peer's pen\n",buf); - - g_assert (GST_RPAD_BUFPEN(GST_RPAD_PEER(pad)) == NULL); - // now fill the bufferpen and switch so it can be consumed - GST_RPAD_BUFPEN(GST_RPAD_PEER(pad)) = buf; - GST_DEBUG (GST_CAT_DATAFLOW,"switching to %p\n",GST_ELEMENT (GST_PAD_PARENT (pad))->threadstate); - g_print ("%p %s\n", GST_ELEMENT (GST_PAD_PARENT (pad)), gst_element_get_name (GST_ELEMENT (GST_PAD_PARENT (pad)))); - GST_ELEMENT (GST_PAD_PARENT (pad))->select_pad = pad; - GST_FLAG_UNSET(GST_PAD_PARENT (pad), GST_ELEMENT_COTHREAD_STOPPING); - cothread_switch (GST_ELEMENT (GST_PAD_PARENT (pad))->threadstate); - - g_print ("done switching\n"); - GST_DEBUG (GST_CAT_DATAFLOW,"done switching\n"); -} - - -static GstBuffer* -gst_schedule_gethandler_proxy (GstPad *pad) -{ - GstBuffer *buf; - GstRealPad *peer = GST_RPAD_PEER(pad); - - GST_DEBUG_ENTER("(%s:%s)",GST_DEBUG_PAD_NAME(pad)); - - // FIXME this should be bounded - // we will loop switching to the peer until it's filled up the bufferpen - while (GST_RPAD_BUFPEN(pad) == NULL) { - GST_DEBUG (GST_CAT_DATAFLOW, "switching to \"%s\": %p to fill bufpen\n", - GST_ELEMENT_NAME(GST_ELEMENT(GST_PAD_PARENT(pad))), - GST_ELEMENT(GST_PAD_PARENT(pad))->threadstate); - cothread_switch (GST_ELEMENT(GST_PAD_PARENT(pad))->threadstate); - - // we may no longer be the same pad, check. - if (GST_RPAD_PEER(peer) != (GstRealPad *)pad) { - GST_DEBUG (GST_CAT_DATAFLOW, "new pad in mid-switch!\n"); - pad = (GstPad *)GST_RPAD_PEER(peer); - } - } - GST_DEBUG (GST_CAT_DATAFLOW,"done switching\n"); - - // now grab the buffer from the pen, clear the pen, and return the buffer - buf = GST_RPAD_BUFPEN(pad); - GST_RPAD_BUFPEN(pad) = NULL; - - return buf; -} - -static GstBuffer* -gst_schedule_pullregionfunc_proxy (GstPad *pad,GstRegionType type,guint64 offset,guint64 len) -{ - GstBuffer *buf; - GstRealPad *peer = GST_RPAD_PEER(pad); - - GST_DEBUG_ENTER("%s:%s,%d,%lld,%lld",GST_DEBUG_PAD_NAME(pad),type,offset,len); - - // put the region info into the pad - GST_RPAD_REGIONTYPE(pad) = type; - GST_RPAD_OFFSET(pad) = offset; - GST_RPAD_LEN(pad) = len; - - // FIXME this should be bounded - // we will loop switching to the peer until it's filled up the bufferpen - while (GST_RPAD_BUFPEN(pad) == NULL) { - GST_DEBUG (GST_CAT_DATAFLOW, "switching to %p to fill bufpen\n", - GST_ELEMENT(GST_PAD_PARENT(pad))->threadstate); - cothread_switch (GST_ELEMENT(GST_PAD_PARENT(pad))->threadstate); - - // we may no longer be the same pad, check. - if (GST_RPAD_PEER(peer) != (GstRealPad *)pad) { - GST_DEBUG (GST_CAT_DATAFLOW, "new pad in mid-switch!\n"); - pad = (GstPad *)GST_RPAD_PEER(peer); - } - } - GST_DEBUG (GST_CAT_DATAFLOW,"done switching\n"); - - // now grab the buffer from the pen, clear the pen, and return the buffer - buf = GST_RPAD_BUFPEN(pad); - GST_RPAD_BUFPEN(pad) = NULL; - return buf; -} - - -static void -gst_schedule_cothreaded_chain (GstBin *bin, GstScheduleChain *chain) { - GList *elements; - GstElement *element; - cothread_func wrapper_function; - GList *pads; - GstPad *pad; - - 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 (); - } - - // walk through all the chain's elements - elements = chain->elements; - while (elements) { - element = GST_ELEMENT (elements->data); - elements = g_list_next (elements); - - // start out without a wrapper function, we select it later - wrapper_function = NULL; - - // if the element has a loopfunc... - if (element->loopfunc != NULL) { - wrapper_function = GST_DEBUG_FUNCPTR(gst_schedule_loopfunc_wrapper); - GST_DEBUG (GST_CAT_SCHEDULING,"element '%s' is a loop-based\n",GST_ELEMENT_NAME(element)); - } else { - // otherwise we need to decide what kind of cothread - // if it's not DECOUPLED, we decide based on whether it's a source or not - if (!GST_FLAG_IS_SET (element, GST_ELEMENT_DECOUPLED)) { - // if it doesn't have any sinks, it must be a source (duh) - if (element->numsinkpads == 0) { - wrapper_function = GST_DEBUG_FUNCPTR(gst_schedule_src_wrapper); - GST_DEBUG (GST_CAT_SCHEDULING,"element '%s' is a source, using _src_wrapper\n",GST_ELEMENT_NAME(element)); - } else { - wrapper_function = GST_DEBUG_FUNCPTR(gst_schedule_chain_wrapper); - GST_DEBUG (GST_CAT_SCHEDULING,"element '%s' is a filter, using _chain_wrapper\n",GST_ELEMENT_NAME(element)); - } - } - } - - // now we have to walk through the pads to set up their state - pads = gst_element_get_pad_list (element); - while (pads) { - pad = GST_PAD (pads->data); - pads = g_list_next (pads); - if (!GST_IS_REAL_PAD(pad)) continue; - - // if the element is DECOUPLED or outside the manager, we have to chain - if ((wrapper_function == NULL) || - (GST_RPAD_PEER(pad) && - (GST_ELEMENT (GST_PAD_PARENT (GST_PAD (GST_RPAD_PEER (pad))))->sched != chain->sched)) - ) { - // set the chain proxies - if (GST_RPAD_DIRECTION(pad) == GST_PAD_SINK) { - GST_DEBUG (GST_CAT_SCHEDULING,"copying chain function into push proxy for %s:%s\n",GST_DEBUG_PAD_NAME(pad)); - GST_RPAD_CHAINHANDLER(pad) = GST_RPAD_CHAINFUNC(pad); - } else { - GST_DEBUG (GST_CAT_SCHEDULING,"copying get function into pull proxy for %s:%s\n",GST_DEBUG_PAD_NAME(pad)); - GST_RPAD_GETHANDLER(pad) = GST_RPAD_GETFUNC(pad); - GST_RPAD_PULLREGIONFUNC(pad) = GST_RPAD_GETREGIONFUNC(pad); - } - - // otherwise we really are a cothread - } else { - if (gst_pad_get_direction (pad) == GST_PAD_SINK) { - GST_DEBUG (GST_CAT_SCHEDULING,"setting cothreaded push proxy for sinkpad %s:%s\n",GST_DEBUG_PAD_NAME(pad)); - GST_RPAD_CHAINHANDLER(pad) = GST_DEBUG_FUNCPTR(gst_schedule_chainhandler_proxy); - } else { - GST_DEBUG (GST_CAT_SCHEDULING,"setting cothreaded pull proxy for srcpad %s:%s\n",GST_DEBUG_PAD_NAME(pad)); - GST_RPAD_GETHANDLER(pad) = GST_DEBUG_FUNCPTR(gst_schedule_gethandler_proxy); - GST_RPAD_PULLREGIONFUNC(pad) = GST_DEBUG_FUNCPTR(gst_schedule_pullregionfunc_proxy); - } - } - } - - // need to set up the cothread now - if (wrapper_function != NULL) { - if (element->threadstate == NULL) { - // FIXME handle cothread_create returning NULL - element->threadstate = cothread_create (bin->threadcontext); - GST_DEBUG (GST_CAT_SCHEDULING,"created cothread %p for '%s'\n",element->threadstate,GST_ELEMENT_NAME(element)); - } - cothread_setfunc (element->threadstate, wrapper_function, 0, (char **)element); - GST_DEBUG (GST_CAT_SCHEDULING,"set wrapper function for '%s' to &%s\n",GST_ELEMENT_NAME(element), - GST_DEBUG_FUNCPTR_NAME(wrapper_function)); - } - } -} - -G_GNUC_UNUSED static void -gst_schedule_chained_chain (GstBin *bin, _GstBinChain *chain) { - GList *elements; - GstElement *element; - GList *pads; - GstPad *pad; - - GST_DEBUG (GST_CAT_SCHEDULING,"chain entered\n"); - // walk through all the elements - elements = chain->elements; - while (elements) { - element = GST_ELEMENT (elements->data); - elements = g_list_next (elements); - - // walk through all the pads - pads = gst_element_get_pad_list (element); - while (pads) { - pad = GST_PAD (pads->data); - pads = g_list_next (pads); - if (!GST_IS_REAL_PAD(pad)) continue; - - if (GST_RPAD_DIRECTION(pad) == GST_PAD_SINK) { - GST_DEBUG (GST_CAT_SCHEDULING,"copying chain function into push proxy for %s:%s\n",GST_DEBUG_PAD_NAME(pad)); - GST_RPAD_CHAINHANDLER(pad) = GST_RPAD_CHAINFUNC(pad); - } else { - GST_DEBUG (GST_CAT_SCHEDULING,"copying get function into pull proxy for %s:%s\n",GST_DEBUG_PAD_NAME(pad)); - GST_RPAD_GETHANDLER(pad) = GST_RPAD_GETFUNC(pad); - GST_RPAD_PULLREGIONFUNC(pad) = GST_RPAD_GETREGIONFUNC(pad); - } - } - } -} - -/* depracated!! */ -static void -gst_bin_schedule_cleanup (GstBin *bin) -{ - GList *chains; - _GstBinChain *chain; - - chains = bin->chains; - while (chains) { - chain = (_GstBinChain *)(chains->data); - chains = g_list_next(chains); - -// g_list_free(chain->disabled); - g_list_free(chain->elements); - g_list_free(chain->entries); - - g_free(chain); - } - g_list_free(bin->chains); - - bin->chains = NULL; -} - -static void -gst_scheduler_handle_eos (GstElement *element, _GstBinChain *chain) -{ - GST_DEBUG (GST_CAT_SCHEDULING,"chain removed from scheduler, EOS from element \"%s\"\n", GST_ELEMENT_NAME (element)); - chain->need_scheduling = FALSE; -} - -/* -void gst_bin_schedule_func(GstBin *bin) { - GList *elements; - GstElement *element; - GSList *pending = NULL; - GList *pads; - GstPad *pad; - GstElement *peerparent; - GList *chains; - GstScheduleChain *chain; - - GST_DEBUG_ENTER("(\"%s\")",GST_ELEMENT_NAME (GST_ELEMENT (bin))); - - gst_bin_schedule_cleanup(bin); - - // next we have to find all the separate scheduling chains - GST_DEBUG (GST_CAT_SCHEDULING,"attempting to find scheduling chains...\n"); - // first make a copy of the managed_elements we can mess with - elements = g_list_copy (bin->managed_elements); - // we have to repeat until the list is empty to get all chains - while (elements) { - element = GST_ELEMENT (elements->data); - - // if this is a DECOUPLED element - if (GST_FLAG_IS_SET (element, GST_ELEMENT_DECOUPLED)) { - // skip this element entirely - GST_DEBUG (GST_CAT_SCHEDULING,"skipping '%s' because it's decoupled\n",GST_ELEMENT_NAME(element)); - elements = g_list_next (elements); - continue; - } - - GST_DEBUG (GST_CAT_SCHEDULING,"starting with element '%s'\n",GST_ELEMENT_NAME(element)); - - // prime the pending list with the first element off the top - pending = g_slist_prepend (NULL, element); - // and remove that one from the main list - elements = g_list_remove (elements, element); - - // create a chain structure - chain = g_new0 (_GstBinChain, 1); - chain->need_scheduling = TRUE; - - // for each pending element, walk the pipeline - do { - // retrieve the top of the stack and pop it - element = GST_ELEMENT (pending->data); - pending = g_slist_remove (pending, element); - - // add ourselves to the chain's list of elements - GST_DEBUG (GST_CAT_SCHEDULING,"adding '%s' to chain\n",GST_ELEMENT_NAME(element)); - chain->elements = g_list_prepend (chain->elements, element); - chain->num_elements++; - gtk_signal_connect (G_OBJECT (element), "eos", gst_scheduler_handle_eos, chain); - // set the cothreads flag as appropriate - if (GST_FLAG_IS_SET (element, GST_ELEMENT_USE_COTHREAD)) - chain->need_cothreads = TRUE; - if (bin->use_cothreads == TRUE) - chain->need_cothreads = TRUE; - - // if we're managed by the current bin, and we're not decoupled, - // go find all the peers and add them to the list of elements to check - if ((element->manager == GST_ELEMENT(bin)) && - !GST_FLAG_IS_SET (element, GST_ELEMENT_DECOUPLED)) { - // remove ourselves from the outer list of all managed elements -// GST_DEBUG (GST_CAT_SCHEDULING,"removing '%s' from list of possible elements\n",GST_ELEMENT_NAME(element)); - elements = g_list_remove (elements, element); - - // if this element is a source, add it as an entry - if (element->numsinkpads == 0) { - chain->entries = g_list_prepend (chain->entries, element); - GST_DEBUG (GST_CAT_SCHEDULING,"added '%s' as SRC entry into the chain\n",GST_ELEMENT_NAME(element)); - } - - // now we have to walk the pads to find peers - pads = gst_element_get_pad_list (element); - while (pads) { - pad = GST_PAD (pads->data); - pads = g_list_next (pads); - if (!GST_IS_REAL_PAD(pad)) continue; - GST_DEBUG (GST_CAT_SCHEDULING,"have pad %s:%s\n",GST_DEBUG_PAD_NAME(pad)); - - if (GST_RPAD_PEER(pad) == NULL) continue; - if (GST_RPAD_PEER(pad) == NULL) GST_ERROR(pad,"peer is null!"); - g_assert(GST_RPAD_PEER(pad) != NULL); - g_assert(GST_PAD_PARENT (GST_PAD(GST_RPAD_PEER(pad))) != NULL); - - peerparent = GST_ELEMENT(GST_PAD_PARENT (GST_PAD(GST_RPAD_PEER(pad)))); - - GST_DEBUG (GST_CAT_SCHEDULING,"peer pad %p\n", GST_RPAD_PEER(pad)); - // only bother with if the pad's peer's parent is this bin or it's DECOUPLED - // only add it if it's in the list of un-visited elements still - if ((g_list_find (elements, peerparent) != NULL) || - GST_FLAG_IS_SET (peerparent, GST_ELEMENT_DECOUPLED)) { - // add the peer element to the pending list - GST_DEBUG (GST_CAT_SCHEDULING,"adding '%s' to list of pending elements\n", - GST_ELEMENT_NAME(peerparent)); - pending = g_slist_prepend (pending, peerparent); - - // if this is a sink pad, then the element on the other side is an entry - if ((GST_RPAD_DIRECTION(pad) == GST_PAD_SINK) && - (GST_FLAG_IS_SET (peerparent, GST_ELEMENT_DECOUPLED))) { - chain->entries = g_list_prepend (chain->entries, peerparent); - gtk_signal_connect (G_OBJECT (peerparent), "eos", gst_scheduler_handle_eos, chain); - GST_DEBUG (GST_CAT_SCHEDULING,"added '%s' as DECOUPLED entry into the chain\n",GST_ELEMENT_NAME(peerparent)); - } - } else - GST_DEBUG (GST_CAT_SCHEDULING,"element '%s' has already been dealt with\n",GST_ELEMENT_NAME(peerparent)); - } - } - } while (pending); - - // add the chain to the bin - GST_DEBUG (GST_CAT_SCHEDULING,"have chain with %d elements: ",chain->num_elements); - { GList *elements = chain->elements; - while (elements) { - element = GST_ELEMENT (elements->data); - elements = g_list_next(elements); - GST_DEBUG_NOPREFIX(GST_CAT_SCHEDULING,"%s, ",GST_ELEMENT_NAME(element)); - } - } - GST_DEBUG_NOPREFIX(GST_CAT_DATAFLOW,"\n"); - bin->chains = g_list_prepend (bin->chains, chain); - bin->num_chains++; - } - // free up the list in case it's full of DECOUPLED elements - g_list_free (elements); - - GST_DEBUG (GST_CAT_SCHEDULING,"\nwe have %d chains to schedule\n",bin->num_chains); - - // now we have to go through all the chains and schedule them - chains = bin->chains; - while (chains) { - chain = (GstScheduleChain *)(chains->data); - chains = g_list_next (chains); - - // schedule as appropriate - if (chain->need_cothreads) { - gst_schedule_cothreaded_chain (bin,chain); - } else { - gst_schedule_chained_chain (bin,chain); - } - } - - GST_DEBUG_LEAVE("(\"%s\")",GST_ELEMENT_NAME(GST_ELEMENT(bin))); -} -*/ - - -/* - // ***** check for possible connections outside - // get the pad's peer - peer = gst_pad_get_peer (pad); - // FIXME this should be an error condition, if not disabled - if (!peer) break; - // get the parent of the peer of the pad - outside = GST_ELEMENT (gst_pad_get_parent (peer)); - // FIXME this should *really* be an error condition - if (!outside) break; - // if it's a source or connection and it's not ours... - if ((GST_IS_SRC (outside) || GST_IS_CONNECTION (outside)) && - (gst_object_get_parent (GST_OBJECT (outside)) != GST_OBJECT (bin))) { - if (gst_pad_get_direction (pad) == GST_PAD_SINK) { - GST_DEBUG (0,"dealing with outside source element %s\n",GST_ELEMENT_NAME(outside)); -// GST_DEBUG (0,"PUNT: copying gethandler ptr from %s:%s to %s:%s (@ %p)\n", -//GST_DEBUG_PAD_NAME(pad->peer),GST_DEBUG_PAD_NAME(pad),&pad->gethandler); -// pad->gethandler = pad->peer->gethandler; -// GST_DEBUG (0,"PUNT: setting chainhandler proxy to fake proxy on %s:%s\n",GST_DEBUG_PAD_NAME(pad->peer)); -// pad->peer->chainhandler = GST_DEBUG_FUNCPTR(gst_bin_chainhandler_fake_proxy); - GST_RPAD_GETHANDLER(pad) = GST_DEBUG_FUNCPTR(gst_bin_gethandler_proxy); - GST_RPAD_PULLREGIONFUNC(pad) = GST_DEBUG_FUNCPTR(gst_bin_pullregionfunc_proxy); - } - } else { -*/ - - - - - -/* - } else if (GST_IS_SRC (element)) { - GST_DEBUG (0,"adding '%s' as entry point, because it's a source\n",GST_ELEMENT_NAME (element)); - bin->entries = g_list_prepend (bin->entries,element); - bin->num_entries++; - cothread_setfunc(element->threadstate,gst_bin_src_wrapper,0,(char **)element); - } - - pads = gst_element_get_pad_list (element); - while (pads) { - pad = GST_PAD(pads->data); - - if (gst_pad_get_direction (pad) == GST_PAD_SINK) { - GST_DEBUG (0,"setting push proxy for sinkpad %s:%s\n",GST_DEBUG_PAD_NAME(pad)); - // set the proxy functions - pad->chainhandler = GST_DEBUG_FUNCPTR(gst_bin_chainhandler_proxy); - GST_DEBUG (0,"chainhandler %p = gst_bin_chainhandler_proxy %p\n",&pad->chainhandler,gst_bin_chainhandler_proxy); - } else if (gst_pad_get_direction (pad) == GST_PAD_SRC) { - GST_DEBUG (0,"setting pull proxies for srcpad %s:%s\n",GST_DEBUG_PAD_NAME(pad)); - // set the proxy functions - GST_RPAD_GETHANDLER(pad) = GST_DEBUG_FUNCPTR(gst_bin_gethandler_proxy); - GST_RPAD_PULLREGIONFUNC(pad) = GST_DEBUG_FUNCPTR(gst_bin_pullregionfunc_proxy); - GST_DEBUG (0,"pad->gethandler(@%p) = gst_bin_gethandler_proxy(@%p)\n", - &pad->gethandler,gst_bin_gethandler_proxy); - pad->pullregionfunc = GST_DEBUG_FUNCPTR(gst_bin_pullregionfunc_proxy); - } - pads = g_list_next (pads); - } - elements = g_list_next (elements); - - // if there are no entries, we have to pick one at random - if (bin->num_entries == 0) - bin->entries = g_list_prepend (bin->entries, GST_ELEMENT(bin->children->data)); - } - } else { - GST_DEBUG (0,"don't need cothreads, looking for entry points\n"); - // we have to find which elements will drive an iteration - elements = bin->children; - while (elements) { - element = GST_ELEMENT (elements->data); - GST_DEBUG (0,"found element \"%s\"\n", GST_ELEMENT_NAME (element)); - if (GST_IS_BIN (element)) { - gst_bin_create_plan (GST_BIN (element)); - } - if (GST_IS_SRC (element)) { - GST_DEBUG (0,"adding '%s' as entry point, because it's a source\n",GST_ELEMENT_NAME (element)); - bin->entries = g_list_prepend (bin->entries, element); - bin->num_entries++; - } - - // go through all the pads, set pointers, and check for connections - pads = gst_element_get_pad_list (element); - while (pads) { - pad = GST_PAD (pads->data); - - if (gst_pad_get_direction (pad) == GST_PAD_SINK) { - GST_DEBUG (0,"found SINK pad %s:%s\n", GST_DEBUG_PAD_NAME(pad)); - - // copy the peer's chain function, easy enough - GST_DEBUG (0,"copying peer's chainfunc to %s:%s's chainhandler\n",GST_DEBUG_PAD_NAME(pad)); - GST_RPAD_CHAINHANDLER(pad) = GST_DEBUG_FUNCPTR(GST_RPAD_CHAINFUNC(GST_RPAD_PEER(pad))); - - // need to walk through and check for outside connections -//FIXME need to do this for all pads - // get the pad's peer - peer = GST_RPAD_PEER(pad); - if (!peer) { - GST_DEBUG (0,"found SINK pad %s has no peer\n", GST_ELEMENT_NAME (pad)); - break; - } - // get the parent of the peer of the pad - outside = GST_ELEMENT (GST_PAD_PARENT(peer)); - if (!outside) break; - // if it's a connection and it's not ours... - if (GST_IS_CONNECTION (outside) && - (gst_object_get_parent (GST_OBJECT (outside)) != GST_OBJECT (bin))) { - gst_info("gstbin: element \"%s\" is the external source Connection " - "for internal element \"%s\"\n", - GST_ELEMENT_NAME (GST_ELEMENT (outside)), - GST_ELEMENT_NAME (GST_ELEMENT (element))); - bin->entries = g_list_prepend (bin->entries, outside); - bin->num_entries++; - } - } - else { - GST_DEBUG (0,"found pad %s\n", GST_ELEMENT_NAME (pad)); - } - pads = g_list_next (pads); - - } - elements = g_list_next (elements); - } -*/ - - - - -/* - // If cothreads are needed, we need to not only find elements but - // set up cothread states and various proxy functions. - if (bin->need_cothreads) { - GST_DEBUG (0,"bin is using cothreads\n"); - - // first create thread context - if (bin->threadcontext == NULL) { - GST_DEBUG (0,"initializing cothread context\n"); - bin->threadcontext = cothread_init (); - } - - // walk through all the children - elements = bin->managed_elements; - while (elements) { - element = GST_ELEMENT (elements->data); - elements = g_list_next (elements); - - // start out with a NULL warpper function, we'll set it if we want a cothread - wrapper_function = NULL; - - // have to decide if we need to or can use a cothreads, and if so which wrapper - // first of all, if there's a loopfunc, the decision's already made - if (element->loopfunc != NULL) { - wrapper_function = GST_DEBUG_FUNCPTR(gst_bin_loopfunc_wrapper); - GST_DEBUG (0,"element %s is a loopfunc, must use a cothread\n",GST_ELEMENT_NAME (element)); - } else { - // otherwise we need to decide if it needs a cothread - // if it's complex, or cothreads are preferred and it's *not* decoupled, cothread it - if (GST_FLAG_IS_SET (element,GST_ELEMENT_COMPLEX) || - (GST_FLAG_IS_SET (bin,GST_BIN_FLAG_PREFER_COTHREADS) && - !GST_FLAG_IS_SET (element,GST_ELEMENT_DECOUPLED))) { - // base it on whether we're going to loop through source or sink pads - if (element->numsinkpads == 0) - wrapper_function = GST_DEBUG_FUNCPTR(gst_bin_src_wrapper); - else - wrapper_function = GST_DEBUG_FUNCPTR(gst_bin_chain_wrapper); - } - } - - // walk through the all the pads for this element, setting proxy functions - // the selection of proxy functions depends on whether we're in a cothread or not - pads = gst_element_get_pad_list (element); - while (pads) { - pad = GST_PAD (pads->data); - pads = g_list_next (pads); - - // check to see if someone else gets to set up the element - peer_manager = GST_ELEMENT((pad)->peer->parent)->manager; - if (peer_manager != GST_ELEMENT(bin)) { - GST_DEBUG (0,"WARNING: pad %s:%s is connected outside of bin\n",GST_DEBUG_PAD_NAME(pad)); - } - - // if the wrapper_function is set, we need to use the proxy functions - if (wrapper_function != NULL) { - // set up proxy functions - if (gst_pad_get_direction (pad) == GST_PAD_SINK) { - GST_DEBUG (0,"setting push proxy for sinkpad %s:%s\n",GST_DEBUG_PAD_NAME(pad)); - pad->chainhandler = GST_DEBUG_FUNCPTR(gst_bin_chainhandler_proxy); - } else if (gst_pad_get_direction (pad) == GST_PAD_SRC) { - GST_DEBUG (0,"setting pull proxy for srcpad %s:%s\n",GST_DEBUG_PAD_NAME(pad)); - GST_RPAD_GETHANDLER(pad) = GST_DEBUG_FUNCPTR(gst_bin_gethandler_proxy); - GST_RPAD_PULLREGIONFUNC(pad) = GST_DEBUG_FUNCPTR(gst_bin_pullregionfunc_proxy); - } - } else { - // otherwise we need to set up for 'traditional' chaining - if (gst_pad_get_direction (pad) == GST_PAD_SINK) { - // we can just copy the chain function, since it shares the prototype - GST_DEBUG (0,"copying chain function into push proxy for %s:%s\n", - GST_DEBUG_PAD_NAME(pad)); - pad->chainhandler = pad->chainfunc; - } else if (gst_pad_get_direction (pad) == GST_PAD_SRC) { - // we can just copy the get function, since it shares the prototype - GST_DEBUG (0,"copying get function into pull proxy for %s:%s\n", - GST_DEBUG_PAD_NAME(pad)); - pad->gethandler = pad->getfunc; - } - } - } - - // if a loopfunc has been specified, create and set up a cothread - if (wrapper_function != NULL) { - if (element->threadstate == NULL) { - element->threadstate = cothread_create (bin->threadcontext); - GST_DEBUG (0,"created cothread %p (@%p) for \"%s\"\n",element->threadstate, - &element->threadstate,GST_ELEMENT_NAME (element)); - } - cothread_setfunc (element->threadstate, wrapper_function, 0, (char **)element); - GST_DEBUG (0,"set wrapper function for \"%s\" to &%s\n",GST_ELEMENT_NAME (element), - GST_DEBUG_FUNCPTR_NAME(wrapper_function)); - } - -// // HACK: if the element isn't decoupled, it's an entry -// if (!GST_FLAG_IS_SET(element,GST_ELEMENT_DECOUPLED)) -// bin->entries = g_list_append(bin->entries, element); - } - - // otherwise, cothreads are not needed - } else { - GST_DEBUG (0,"bin is chained, no cothreads needed\n"); - - elements = bin->managed_elements; - while (elements) { - element = GST_ELEMENT (elements->data); - elements = g_list_next (elements); - - pads = gst_element_get_pad_list (element); - while (pads) { - pad = GST_PAD (pads->data); - pads = g_list_next (pads); - - if (gst_pad_get_direction (pad) == GST_PAD_SINK) { - GST_DEBUG (0,"copying chain function into push proxy for %s:%s\n",GST_DEBUG_PAD_NAME(pad)); - pad->chainhandler = pad->chainfunc; - } else { - GST_DEBUG (0,"copying get function into pull proxy for %s:%s\n",GST_DEBUG_PAD_NAME(pad)); - pad->gethandler = pad->getfunc; - } - } - } - } -*/ - -static void -gst_schedule_lock_element (GstSchedule *sched,GstElement *element) -{ - if (element->threadstate) - cothread_lock(element->threadstate); -} - -static void -gst_schedule_unlock_element (GstSchedule *sched,GstElement *element) -{ - if (element->threadstate) - cothread_unlock(element->threadstate); -} - - -/*************** INCREMENTAL SCHEDULING CODE STARTS HERE ***************/ - - -static void gst_schedule_class_init (GstScheduleClass *klass); -static void gst_schedule_init (GstSchedule *schedule); +static void gst_scheduler_class_init (GstSchedulerClass *klass); +static void gst_scheduler_init (GstScheduler *sched); static GstObjectClass *parent_class = NULL; -GType -gst_schedule_get_type (void) +GType +gst_scheduler_get_type (void) { - if (!_gst_schedule_type) { - static const GTypeInfo schedule_info = { - sizeof(GstScheduleClass), + static GType _gst_scheduler_type = 0; + + if (!_gst_scheduler_type) { + static const GTypeInfo scheduler_info = { + sizeof (GstSchedulerClass), NULL, NULL, - (GClassInitFunc)gst_schedule_class_init, + (GClassInitFunc) gst_scheduler_class_init, NULL, NULL, - sizeof(GstSchedule), + sizeof (GstScheduler), 0, - (GInstanceInitFunc)gst_schedule_init, + (GInstanceInitFunc) gst_scheduler_init, NULL }; - _gst_schedule_type = g_type_register_static(GST_TYPE_OBJECT, "GstSchedule", &schedule_info, 0); + + _gst_scheduler_type = g_type_register_static (GST_TYPE_OBJECT, "GstScheduler", + &scheduler_info, G_TYPE_FLAG_ABSTRACT); } - return _gst_schedule_type; + return _gst_scheduler_type; } static void -gst_schedule_class_init (GstScheduleClass *klass) +gst_scheduler_class_init (GstSchedulerClass *klass) { - parent_class = g_type_class_ref(GST_TYPE_OBJECT); + parent_class = g_type_class_ref (GST_TYPE_OBJECT); } static void -gst_schedule_init (GstSchedule *schedule) +gst_scheduler_init (GstScheduler *sched) { - schedule->add_element = GST_DEBUG_FUNCPTR(gst_schedule_add_element); - schedule->remove_element = GST_DEBUG_FUNCPTR(gst_schedule_remove_element); - schedule->enable_element = GST_DEBUG_FUNCPTR(gst_schedule_enable_element); - schedule->disable_element = GST_DEBUG_FUNCPTR(gst_schedule_disable_element); - schedule->lock_element = GST_DEBUG_FUNCPTR(gst_schedule_lock_element); - schedule->unlock_element = GST_DEBUG_FUNCPTR(gst_schedule_unlock_element); - schedule->pad_connect = GST_DEBUG_FUNCPTR(gst_schedule_pad_connect); - schedule->pad_disconnect = GST_DEBUG_FUNCPTR(gst_schedule_pad_disconnect); - schedule->pad_select = GST_DEBUG_FUNCPTR(gst_schedule_pad_select); - schedule->iterate = GST_DEBUG_FUNCPTR(gst_schedule_iterate); } /** - * gst_schedule_new: - * @parent: the parent of the new scheduler - * - * Create a new scheduler for the given parent. - * - * Returns: the new scheduler. - */ -GstSchedule* -gst_schedule_new(GstElement *parent) -{ - GstSchedule *sched = GST_SCHEDULE (g_object_new(GST_TYPE_SCHEDULE,NULL)); - - 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. */ -/* DEPRACATED !!!! -GstElement *gst_schedule_check_pad (GstSchedule *sched, GstPad *pad) { - GstRealPad *peer; - GstElement *element, *peerelement; - - GST_INFO (GST_CAT_SCHEDULING, "checking pad %s:%s for peer in scheduler", - GST_DEBUG_PAD_NAME(pad)); - - element = GST_ELEMENT(GST_PAD_PARENT(peer)); - GST_DEBUG(GST_CAT_SCHEDULING, "element is \"%s\"\n",GST_ELEMENT_NAME(element)); - - peer = GST_PAD_PEER (pad); - if (peer == NULL) return NULL; - peerelement = GST_ELEMENT(GST_PAD_PARENT (peer)); - if (peerelement == NULL) return NULL; - GST_DEBUG(GST_CAT_SCHEDULING, "peer element is \"%s\"\n",GST_ELEMENT_NAME(peerelement)); - - // now check to see if it's in the same schedule - if (GST_ELEMENT_SCHED(element) == GST_ELEMENT_SCHED(peerelement)) { - GST_DEBUG(GST_CAT_SCHEDULING, "peer is in same schedule\n"); - return peerelement; - } - - // otherwise it's not a candidate - return NULL; -} -*/ - -static GstScheduleChain * -gst_schedule_chain_new (GstSchedule *sched) -{ - GstScheduleChain *chain = g_new (GstScheduleChain, 1); - - // initialize the chain with sane values - chain->sched = sched; - chain->disabled = NULL; - chain->elements = NULL; - chain->num_elements = 0; - chain->entry = NULL; - chain->cothreaded_elements = 0; - chain->schedule = FALSE; - - // add the chain to the schedules' list of chains - sched->chains = g_list_prepend (sched->chains, chain); - sched->num_chains++; - - GST_INFO (GST_CAT_SCHEDULING, "created new chain %p, now are %d chains in sched %p", - chain,sched->num_chains,sched); - - return chain; -} - -static void -gst_schedule_chain_destroy (GstScheduleChain *chain) -{ - GstSchedule *sched = chain->sched; - - // remove the chain from the schedules' list of chains - chain->sched->chains = g_list_remove (chain->sched->chains, chain); - chain->sched->num_chains--; - - // destroy the chain - g_list_free (chain->disabled); // should be empty... - g_list_free (chain->elements); // ditto - g_free (chain); - - GST_INFO (GST_CAT_SCHEDULING, "destroyed chain %p, now are %d chains in sched %p",chain,sched->num_chains,sched); -} - -static void -gst_schedule_chain_add_element (GstScheduleChain *chain, GstElement *element) -{ - GST_INFO (GST_CAT_SCHEDULING, "adding element \"%s\" to chain %p", GST_ELEMENT_NAME (element),chain); - - // set the sched pointer for the element - element->sched = chain->sched; - - // add the element to the list of 'disabled' elements - chain->disabled = g_list_prepend (chain->disabled, element); - chain->num_elements++; -} - -static void -gst_schedule_chain_enable_element (GstScheduleChain *chain, GstElement *element) -{ - GST_INFO (GST_CAT_SCHEDULING, "enabling element \"%s\" in chain %p", GST_ELEMENT_NAME (element),chain); - - // remove from disabled list - chain->disabled = g_list_remove (chain->disabled, element); - - // add to elements list - chain->elements = g_list_prepend (chain->elements, element); - - // reschedule the chain - gst_schedule_cothreaded_chain(GST_BIN(chain->sched->parent),chain); -} - -static void -gst_schedule_chain_disable_element (GstScheduleChain *chain, GstElement *element) -{ - GST_INFO (GST_CAT_SCHEDULING, "disabling element \"%s\" in chain %p", GST_ELEMENT_NAME (element),chain); - - // remove from elements list - chain->elements = g_list_remove (chain->elements, element); - - // add to disabled list - chain->disabled = g_list_prepend (chain->disabled, element); - - // reschedule the chain -// FIXME this should be done only if manager state != NULL -// gst_schedule_cothreaded_chain(GST_BIN(chain->sched->parent),chain); -} - -static void -gst_schedule_chain_remove_element (GstScheduleChain *chain, GstElement *element) -{ - GST_INFO (GST_CAT_SCHEDULING, "removing element \"%s\" from chain %p", GST_ELEMENT_NAME (element),chain); - - // if it's active, deactivate it - if (g_list_find (chain->elements, element)) { - gst_schedule_chain_disable_element (chain, element); - } - - // remove the element from the list of elements - chain->disabled = g_list_remove (chain->disabled, element); - chain->num_elements--; - - // if there are no more elements in the chain, destroy the chain - if (chain->num_elements == 0) - gst_schedule_chain_destroy(chain); - - // unset the sched pointer for the element - element->sched = NULL; -} - -static void -gst_schedule_chain_elements (GstSchedule *sched, GstElement *element1, GstElement *element2) -{ - GList *chains; - GstScheduleChain *chain; - GstScheduleChain *chain1 = NULL, *chain2 = NULL; - GstElement *element; - - // first find the chains that hold the two - chains = sched->chains; - while (chains) { - chain = (GstScheduleChain *)(chains->data); - chains = g_list_next(chains); - - if (g_list_find (chain->disabled,element1)) - chain1 = chain; - else if (g_list_find (chain->elements,element1)) - chain1 = chain; - - if (g_list_find (chain->disabled,element2)) - chain2 = chain; - else if (g_list_find (chain->elements,element2)) - chain2 = chain; - } - - // first check to see if they're in the same chain, we're done if that's the case - if ((chain1 != NULL) && (chain1 == chain2)) { - GST_INFO (GST_CAT_SCHEDULING, "elements are already in the same chain"); - return; - } - - // now, if neither element has a chain, create one - if ((chain1 == NULL) && (chain2 == NULL)) { - GST_INFO (GST_CAT_SCHEDULING, "creating new chain to hold two new elements"); - chain = gst_schedule_chain_new (sched); - gst_schedule_chain_add_element (chain, element1); - gst_schedule_chain_add_element (chain, element2); - // FIXME chain changed here -// gst_schedule_cothreaded_chain(chain->sched->parent,chain); - - // otherwise if both have chains already, join them - } else if ((chain1 != NULL) && (chain2 != NULL)) { - GST_INFO (GST_CAT_SCHEDULING, "merging chain %p into chain %p",chain2,chain1); - // take the contents of chain2 and merge them into chain1 - chain1->disabled = g_list_concat (chain1->disabled, g_list_copy(chain2->disabled)); - chain1->elements = g_list_concat (chain1->elements, g_list_copy(chain2->elements)); - chain1->num_elements += chain2->num_elements; - // FIXME chain changed here -// gst_schedule_cothreaded_chain(chain->sched->parent,chain); - - gst_schedule_chain_destroy(chain2); - - // otherwise one has a chain already, the other doesn't - } else { - // pick out which one has the chain, and which doesn't - if (chain1 != NULL) chain = chain1, element = element2; - else chain = chain2, element = element1; - - GST_INFO (GST_CAT_SCHEDULING, "adding element to existing chain"); - gst_schedule_chain_add_element (chain, element); - // FIXME chain changed here -// gst_schedule_cothreaded_chain(chain->sched->parent,chain); - } -} - -/** - * gst_schedule_pad_connect: - * @sched: the scheduler + * gst_scheduler_pad_connect: + * @sched: the schedulerr * @srcpad: the srcpad to connect * @sinkpad: the sinkpad to connect to * * Connect the srcpad to the given sinkpad. */ void -gst_schedule_pad_connect (GstSchedule *sched, GstPad *srcpad, GstPad *sinkpad) +gst_scheduler_pad_connect (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad) { - GstElement *srcelement,*sinkelement; - - srcelement = GST_PAD_PARENT(srcpad); - g_return_if_fail(srcelement != NULL); - sinkelement = GST_PAD_PARENT(sinkpad); - g_return_if_fail(sinkelement != NULL); - - GST_INFO (GST_CAT_SCHEDULING, "have pad connected callback on %s:%s to %s:%s",GST_DEBUG_PAD_NAME(srcpad),GST_DEBUG_PAD_NAME(sinkpad)); - GST_DEBUG(GST_CAT_SCHEDULING, "srcpad sched is %p, sinkpad sched is %p\n", -GST_ELEMENT_SCHED(srcelement),GST_ELEMENT_SCHED(sinkelement)); - - if (GST_ELEMENT_SCHED(srcelement) == GST_ELEMENT_SCHED(sinkelement)) { - GST_INFO (GST_CAT_SCHEDULING, "peer %s:%s is in same schedule, chaining together",GST_DEBUG_PAD_NAME(sinkpad)); - gst_schedule_chain_elements (sched, srcelement, sinkelement); - } -} - -// find the chain within the schedule that holds the element, if any -static GstScheduleChain * -gst_schedule_find_chain (GstSchedule *sched, GstElement *element) -{ - GList *chains; - GstScheduleChain *chain; - - GST_INFO (GST_CAT_SCHEDULING, "searching for element \"%s\" in chains",GST_ELEMENT_NAME(element)); - - chains = sched->chains; - while (chains) { - chain = (GstScheduleChain *)(chains->data); - chains = g_list_next (chains); - - if (g_list_find (chain->elements, element)) - return chain; - if (g_list_find (chain->disabled, element)) - return chain; - } - - return NULL; -} - -static void -gst_schedule_chain_recursive_add (GstScheduleChain *chain, GstElement *element) -{ - GList *pads; - GstPad *pad; - GstElement *peerelement; - - // add the element to the chain - gst_schedule_chain_add_element (chain, element); - - GST_DEBUG(GST_CAT_SCHEDULING, "recursing on element \"%s\"\n",GST_ELEMENT_NAME(element)); - // now go through all the pads and see which peers can be added - pads = element->pads; - while (pads) { - pad = GST_PAD(pads->data); - pads = g_list_next (pads); - - GST_DEBUG(GST_CAT_SCHEDULING, "have pad %s:%s, checking for valid peer\n",GST_DEBUG_PAD_NAME(pad)); - // if the peer exists and could be in the same chain - if (GST_PAD_PEER(pad)) { - GST_DEBUG(GST_CAT_SCHEDULING, "has peer %s:%s\n",GST_DEBUG_PAD_NAME(GST_PAD_PEER(pad))); - peerelement = GST_PAD_PARENT(GST_PAD_PEER(pad)); - if (GST_ELEMENT_SCHED(GST_PAD_PARENT(pad)) == GST_ELEMENT_SCHED(peerelement)) { - GST_DEBUG(GST_CAT_SCHEDULING, "peer \"%s\" is valid for same chain\n",GST_ELEMENT_NAME(peerelement)); - // if it's not already in a chain, add it to this one - if (gst_schedule_find_chain (chain->sched, peerelement) == NULL) { - gst_schedule_chain_recursive_add (chain, peerelement); - } - } - } - } + if (CLASS (sched)->pad_connect) + CLASS (sched)->pad_connect (sched, srcpad, sinkpad); } /** - * gst_schedule_pad_disconnect: - * @sched: the scheduler + * gst_scheduler_pad_disconnect: + * @sched: the schedulerr * @srcpad: the srcpad to disconnect * @sinkpad: the sinkpad to disconnect from * * Disconnect the srcpad to the given sinkpad. */ void -gst_schedule_pad_disconnect (GstSchedule *sched, GstPad *srcpad, GstPad *sinkpad) +gst_scheduler_pad_disconnect (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad) { - GstScheduleChain *chain; - GstElement *element1, *element2; - GstScheduleChain *chain1, *chain2; - - GST_INFO (GST_CAT_SCHEDULING, "disconnecting pads %s:%s and %s:%s", - GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad)); - - // we need to have the parent elements of each pad - element1 = GST_ELEMENT(GST_PAD_PARENT(srcpad)); - element2 = GST_ELEMENT(GST_PAD_PARENT(sinkpad)); - - // first task is to remove the old chain they belonged to. - // this can be accomplished by taking either of the elements, - // since they are guaranteed to be in the same chain - // FIXME is it potentially better to make an attempt at splitting cleaner?? - chain = gst_schedule_find_chain (sched, element1); - if (chain) { - GST_INFO (GST_CAT_SCHEDULING, "destroying chain"); - gst_schedule_chain_destroy (chain); - } - - // 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); - - // 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); - } + if (CLASS (sched)->pad_disconnect) + CLASS (sched)->pad_disconnect (sched, srcpad, sinkpad); } /** - * gst_schedule_pad_select: - * @sched: the scheduler + * gst_scheduler_pad_select: + * @sched: the schedulerr * @padlist: the padlist to select on * * register the given padlist for a select operation. * * Returns: the pad which received a buffer. */ -GstPad* -gst_schedule_pad_select (GstSchedule *sched, GList *padlist) +GstPad * +gst_scheduler_pad_select (GstScheduler *sched, GList *padlist) { - GstPad *pad = NULL; - GList *padlist2 = padlist; - GST_INFO (GST_CAT_SCHEDULING, "performing select"); - - while (padlist2) { - pad = GST_PAD (padlist2->data); - - if (gst_pad_peek (pad)) { - g_print ("found something in pad %s:%s\n", GST_DEBUG_PAD_NAME (pad)); - return pad; - } - - padlist2 = g_list_next (padlist2); - } - - /* else there is nothing ready to consume, set up the select functions */ - while (padlist) { - pad = GST_PAD (padlist->data); - - GST_RPAD_CHAINHANDLER(pad) = GST_DEBUG_FUNCPTR(gst_schedule_select_proxy); - - padlist = g_list_next (padlist); - } - if (pad != NULL) { - GstRealPad *peer = GST_RPAD_PEER(pad); - - cothread_switch (GST_ELEMENT (GST_PAD_PARENT (peer))->threadstate); - - g_print ("%p %s\n", GST_ELEMENT (GST_PAD_PARENT (pad)), gst_element_get_name (GST_ELEMENT (GST_PAD_PARENT (pad)))); - pad = GST_ELEMENT (GST_PAD_PARENT (pad))->select_pad; - - g_assert (pad != NULL); - g_print ("back from select (%s:%s)\n", GST_DEBUG_PAD_NAME (pad)); - } - return pad; + if (CLASS (sched)->pad_select) + CLASS (sched)->pad_select (sched, padlist); } /** - * gst_schedule_add_element: - * @sched: the scheduler - * @element: the element to add to the scheduler + * gst_scheduler_add_element: + * @sched: the schedulerr + * @element: the element to add to the schedulerr * - * Add an element to the scheduler. + * Add an element to the schedulerr. */ void -gst_schedule_add_element (GstSchedule *sched, GstElement *element) +gst_scheduler_add_element (GstScheduler *sched, GstElement *element) { - GList *pads; - GstPad *pad; - GstElement *peerelement; - GstScheduleChain *chain; - - g_return_if_fail (element != NULL); - g_return_if_fail (GST_IS_ELEMENT(element)); - - // if it's already in this schedule, don't bother doing anything - if (GST_ELEMENT_SCHED(element) == sched) return; - - GST_INFO (GST_CAT_SCHEDULING, "adding element \"%s\" to schedule", - GST_ELEMENT_NAME(element)); - - // if the element already has a different scheduler, remove the element from it - if (GST_ELEMENT_SCHED(element)) { - gst_schedule_remove_element(GST_ELEMENT_SCHED(element),element); - } - - // set the sched pointer in the element itself - GST_ELEMENT_SCHED(element) = sched; - - // only deal with elements after this point, not bins - // exception is made for Bin's that are schedulable, like the autoplugger - if (GST_IS_BIN (element) && !GST_FLAG_IS_SET(element, GST_BIN_SELF_SCHEDULABLE)) return; - - // first add it to the list of elements that are to be scheduled - sched->elements = g_list_prepend (sched->elements, element); - sched->num_elements++; - - // create a chain to hold it, and add - chain = gst_schedule_chain_new (sched); - gst_schedule_chain_add_element (chain, element); - - // set the sched pointer in all the pads - 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 exists and is a candidate - if (GST_PAD_PEER(pad)) { - peerelement = GST_PAD_PARENT( GST_PAD_PEER (pad) ); - if (GST_ELEMENT_SCHED(element) == GST_ELEMENT_SCHED(peerelement)) { - GST_INFO (GST_CAT_SCHEDULING, "peer is in same schedule, chaining together"); - // make sure that the two elements are in the same chain - gst_schedule_chain_elements (sched,element,peerelement); - } - } - } + if (CLASS (sched)->add_element) + CLASS (sched)->add_element (sched, element); } /** - * gst_schedule_enable_element: - * @sched: the scheduler + * gst_scheduler_enable_element: + * @sched: the schedulerr * @element: the element to enable * * Enable an element for scheduling. */ void -gst_schedule_enable_element (GstSchedule *sched, GstElement *element) +gst_scheduler_enable_element (GstScheduler *sched, GstElement *element) { - GstScheduleChain *chain; - - // find the chain the element's in - chain = gst_schedule_find_chain (sched, element); - - if (chain) - gst_schedule_chain_enable_element (chain, element); - else - GST_INFO (GST_CAT_SCHEDULING, "element not found in any chain, not enabling"); + if (CLASS (sched)->enable_element) + CLASS (sched)->enable_element (sched, element); } /** - * gst_schedule_disable_element: - * @sched: the scheduler + * gst_scheduler_disable_element: + * @sched: the schedulerr * @element: the element to disable * * Disable an element for scheduling. */ void -gst_schedule_disable_element (GstSchedule *sched, GstElement *element) +gst_scheduler_disable_element (GstScheduler *sched, GstElement *element) { - GstScheduleChain *chain; - - // find the chain the element is in - chain = gst_schedule_find_chain (sched, element); - - // remove it from the chain - if (chain) { - gst_schedule_chain_disable_element(chain,element); - } + if (CLASS (sched)->disable_element) + CLASS (sched)->disable_element (sched, element); } /** - * gst_schedule_remove_element: - * @sched: the scheduler + * gst_scheduler_remove_element: + * @sched: the schedulerr * @element: the element to remove * - * Remove an element from the scheduler. + * Remove an element from the schedulerr. */ void -gst_schedule_remove_element (GstSchedule *sched, GstElement *element) +gst_scheduler_remove_element (GstScheduler *sched, GstElement *element) { - GstScheduleChain *chain; + if (CLASS (sched)->remove_element) + CLASS (sched)->remove_element (sched, element); +} - g_return_if_fail (element != NULL); - g_return_if_fail (GST_IS_ELEMENT(element)); +void +gst_scheduler_lock_element (GstScheduler *sched, GstElement *element) +{ + if (CLASS (sched)->lock_element) + CLASS (sched)->lock_element (sched, element); +} - if (g_list_find (sched->elements, element)) { - GST_INFO (GST_CAT_SCHEDULING, "removing element \"%s\" from schedule", - GST_ELEMENT_NAME(element)); - - // find what chain the element is in - chain = gst_schedule_find_chain(sched, element); - - // remove it from its chain - gst_schedule_chain_remove_element (chain, element); - - // remove it from the list of elements - sched->elements = g_list_remove (sched->elements, element); - sched->num_elements--; - - // unset the scheduler pointer in the element - GST_ELEMENT_SCHED(element) = NULL; - } +void +gst_scheduler_unlock_element (GstScheduler *sched, GstElement *element) +{ + if (CLASS (sched)->unlock_element) + CLASS (sched)->unlock_element (sched, element); } /** - * gst_schedule_iterate: - * @sched: the scheduler + * gst_scheduler_iterate: + * @sched: the schedulerr * - * Perform one iteration on the scheduler. + * Perform one iteration on the schedulerr. * * Returns: a boolean indicating something usefull has happened. */ gboolean -gst_schedule_iterate (GstSchedule *sched) +gst_scheduler_iterate (GstScheduler *sched) { - GstBin *bin = GST_BIN(sched->parent); - GList *chains; - GstScheduleChain *chain; - GstElement *entry; - gint num_scheduled = 0; - gboolean eos = FALSE; - GList *elements; - - GST_DEBUG_ENTER("(\"%s\")", GST_ELEMENT_NAME (bin)); - - g_return_val_if_fail (bin != NULL, TRUE); - g_return_val_if_fail (GST_IS_BIN (bin), TRUE); -// g_return_val_if_fail (GST_STATE (bin) == GST_STATE_PLAYING, TRUE); - - // step through all the chains - chains = sched->chains; -// if (chains == NULL) return FALSE; -g_return_val_if_fail (chains != NULL, FALSE); - while (chains) { - chain = (GstScheduleChain *)(chains->data); - chains = g_list_next (chains); - -// if (!chain->need_scheduling) continue; - -// if (chain->need_cothreads) { - // all we really have to do is switch to the first child - // FIXME this should be lots more intelligent about where to start - GST_DEBUG (GST_CAT_DATAFLOW,"starting iteration via cothreads\n"); - - if (chain->elements) { - entry = NULL; //MattH ADDED? -GST_DEBUG(GST_CAT_SCHEDULING,"there are %d elements in this chain\n",chain->num_elements); - elements = chain->elements; - while (elements) { - entry = GST_ELEMENT(elements->data); - elements = g_list_next(elements); - if (GST_FLAG_IS_SET(entry,GST_ELEMENT_DECOUPLED)) { - GST_DEBUG(GST_CAT_SCHEDULING,"entry \"%s\" is DECOUPLED, skipping\n",GST_ELEMENT_NAME(entry)); - entry = NULL; - } else if (GST_FLAG_IS_SET(entry,GST_ELEMENT_NO_ENTRY)) { - GST_DEBUG(GST_CAT_SCHEDULING,"entry \"%s\" is not valid, skipping\n",GST_ELEMENT_NAME(entry)); - entry = NULL; - } else - break; - } - if (entry) { - GST_FLAG_SET (entry, GST_ELEMENT_COTHREAD_STOPPING); - GST_DEBUG (GST_CAT_DATAFLOW,"set COTHREAD_STOPPING flag on \"%s\"(@%p)\n", - GST_ELEMENT_NAME (entry),entry); - cothread_switch (entry->threadstate); - - // following is a check to see if the chain was interrupted due to a - // top-half state_change(). (i.e., if there's a pending state.) - // - // if it was, return to gstthread.c::gst_thread_main_loop() to - // execute the state change. - GST_DEBUG (GST_CAT_DATAFLOW,"cothread switch ended or interrupted\n"); - if (GST_STATE_PENDING(GST_SCHEDULE(sched)->parent) != GST_STATE_VOID_PENDING) - { - GST_DEBUG (GST_CAT_DATAFLOW,"handle pending state %d\n", - GST_STATE_PENDING(GST_SCHEDULE(sched)->parent)); - return 0; - } - - } else { - GST_INFO (GST_CAT_DATAFLOW,"NO ENTRY INTO CHAIN!"); -gst_schedule_show(sched); - //eos = TRUE; - //gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED); - } - } else { - GST_INFO (GST_CAT_DATAFLOW,"NO ENABLED ELEMENTS IN CHAIN!!"); - eos = TRUE; - } - -/* - } else { - GST_DEBUG (GST_CAT_DATAFLOW,"starting iteration via chain-functions\n"); - - entries = chain->entries; - - g_assert (entries != NULL); - - while (entries) { - entry = GST_ELEMENT (entries->data); - entries = g_list_next (entries); - - GST_DEBUG (GST_CAT_DATAFLOW,"have entry \"%s\"\n",GST_ELEMENT_NAME (entry)); - - if (GST_IS_BIN (entry)) { - gst_bin_iterate (GST_BIN (entry)); - } else { - pads = entry->pads; - while (pads) { - pad = GST_PAD (pads->data); - GST_DEBUG (GST_CAT_DATAFLOW,"calling getfunc of %s:%s\n",GST_DEBUG_PAD_NAME(pad)); - if (GST_REAL_PAD(pad)->getfunc == NULL) - fprintf(stderr, "error, no getfunc in \"%s\"\n", GST_ELEMENT_NAME (entry)); - else - buf = (GST_REAL_PAD(pad)->getfunc)(pad); - if (buf) gst_pad_push(pad,buf); - } - pads = g_list_next (pads); - } - } - } - }*/ - num_scheduled++; - } - -/* - // check if nothing was scheduled that was ours.. - if (!num_scheduled) { - // are there any other elements that are still busy? - if (bin->num_eos_providers) { - GST_LOCK (bin); - GST_DEBUG (GST_CATA_DATAFLOW,"waiting for eos providers\n"); - g_cond_wait (bin->eoscond, GST_OBJECT(bin)->lock); - GST_DEBUG (GST_CAT_DATAFLOW,"num eos providers %d\n", bin->num_eos_providers); - GST_UNLOCK (bin); - } - else { - gst_element_signal_eos (GST_ELEMENT (bin)); - eos = TRUE; - } - } -*/ - - GST_DEBUG (GST_CAT_DATAFLOW, "leaving (%s)\n", GST_ELEMENT_NAME (bin)); - return !eos; + if (CLASS (sched)->iterate) + CLASS (sched)->iterate (sched); } /** - * gst_schedule_show: - * @sched: the scheduler + * gst_scheduler_show: + * @sched: the schedulerr * - * Dump the state of the scheduler + * Dump the state of the schedulerr */ void -gst_schedule_show (GstSchedule *sched) +gst_scheduler_show (GstScheduler *sched) { - GList *chains, *elements; - GstElement *element; - GstScheduleChain *chain; + if (CLASS (sched)->show) + CLASS (sched)->show (sched); +} - if (sched == NULL) { - g_print("schedule doesn't exist for this element\n"); - return; +/* + * Factory stuff starts here + * + */ + +static GList* _gst_schedulerfactories; + +static void gst_schedulerfactory_class_init (GstSchedulerFactoryClass *klass); +static void gst_schedulerfactory_init (GstSchedulerFactory *factory); + +#ifndef GST_DISABLE_REGISTRY +static xmlNodePtr gst_schedulerfactory_save_thyself (GstObject *object, xmlNodePtr parent); +static void gst_schedulerfactory_restore_thyself (GstObject *object, xmlNodePtr parent); +#endif + +static GstPluginFeatureClass *factory_parent_class = NULL; +//static guint gst_schedulerfactory_signals[LAST_SIGNAL] = { 0 }; + +GType +gst_schedulerfactory_get_type (void) +{ + static GType schedulerfactory_type = 0; + + if (!schedulerfactory_type) { + static const GTypeInfo schedulerfactory_info = { + sizeof (GstSchedulerFactoryClass), + NULL, + NULL, + (GClassInitFunc) gst_schedulerfactory_class_init, + NULL, + NULL, + sizeof(GstSchedulerFactory), + 0, + (GInstanceInitFunc) gst_schedulerfactory_init, + NULL + }; + schedulerfactory_type = g_type_register_static (GST_TYPE_PLUGIN_FEATURE, + "GstSchedulerFactory", &schedulerfactory_info, 0); + } + return schedulerfactory_type; +} + +static void +gst_schedulerfactory_class_init (GstSchedulerFactoryClass *klass) +{ + GObjectClass *gobject_class; + GstObjectClass *gstobject_class; + GstPluginFeatureClass *gstpluginfeature_class; + + gobject_class = (GObjectClass*)klass; + gstobject_class = (GstObjectClass*)klass; + gstpluginfeature_class = (GstPluginFeatureClass*) klass; + + factory_parent_class = g_type_class_ref (GST_TYPE_PLUGIN_FEATURE); + +#ifndef GST_DISABLE_REGISTRY + gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_schedulerfactory_save_thyself); + gstobject_class->restore_thyself = GST_DEBUG_FUNCPTR (gst_schedulerfactory_restore_thyself); +#endif + + _gst_schedulerfactories = NULL; +} + +static void +gst_schedulerfactory_init (GstSchedulerFactory *factory) +{ + _gst_schedulerfactories = g_list_prepend (_gst_schedulerfactories, factory); +} + + +/** + * gst_schedulerfactory_new: + * @name: name of schedulerfactory to create + * @longdesc: long description of schedulerfactory to create + * @type: the gtk type of the GstScheduler element of this factory + * + * Create a new schedulerfactory with the given parameters + * + * Returns: a new #GstSchedulerFactory. + */ +GstSchedulerFactory* +gst_schedulerfactory_new (const gchar *name, const gchar *longdesc, GType type) +{ + GstSchedulerFactory *factory; + + g_return_val_if_fail(name != NULL, NULL); + factory = gst_schedulerfactory_find (name); + if (!factory) { + factory = GST_SCHEDULERFACTORY (g_object_new (GST_TYPE_SCHEDULERFACTORY, NULL)); } - g_return_if_fail(GST_IS_SCHEDULE(sched)); + gst_object_set_name (GST_OBJECT (factory), name); + if (factory->longdesc) + g_free (factory->longdesc); + factory->longdesc = g_strdup (longdesc); + factory->type = type; - g_print("SCHEDULE DUMP FOR MANAGING BIN \"%s\"\n",GST_ELEMENT_NAME(sched->parent)); + return factory; +} - 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); +/** + * gst_schedulerfactory_destroy: + * @factory: factory to destroy + * + * Removes the scheduler from the global list. + */ +void +gst_schedulerfactory_destroy (GstSchedulerFactory *factory) +{ + g_return_if_fail (factory != NULL); - g_print("%s, ",GST_ELEMENT_NAME(element)); + _gst_schedulerfactories = g_list_remove (_gst_schedulerfactories, factory); + + // we don't free the struct bacause someone might have a handle to it.. +} + +/** + * gst_schedulerfactory_find: + * @name: name of schedulerfactory to find + * + * Search for an schedulerfactory of the given name. + * + * Returns: #GstSchedulerFactory if found, NULL otherwise + */ +GstSchedulerFactory* +gst_schedulerfactory_find (const gchar *name) +{ + GList *walk; + GstSchedulerFactory *factory; + + g_return_val_if_fail(name != NULL, NULL); + + GST_DEBUG (0,"gstscheduler: find \"%s\"\n", name); + + walk = _gst_schedulerfactories; + while (walk) { + factory = (GstSchedulerFactory *)(walk->data); + if (!strcmp (name, GST_OBJECT_NAME (factory))) + return factory; + walk = g_list_next (walk); } - 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); + return NULL; +} - g_print("%p: ",chain); +/** + * gst_schedulerfactory_get_list: + * + * Get the global list of schedulerfactories. + * + * Returns: GList of type #GstSchedulerFactory + */ +GList* +gst_schedulerfactory_get_list (void) +{ + return _gst_schedulerfactories; +} - elements = chain->disabled; - while (elements) { - element = GST_ELEMENT(elements->data); - elements = g_list_next(elements); +/** + * gst_schedulerfactory_create: + * @factory: the factory used to create the instance + * + * Create a new #GstScheduler instance from the + * given schedulerfactory. + * + * Returns: A new #GstScheduler instance. + */ +GstScheduler* +gst_schedulerfactory_create (GstSchedulerFactory *factory, GstElement *parent) +{ + GstScheduler *new = NULL; - g_print("!%s, ",GST_ELEMENT_NAME(element)); + g_return_val_if_fail (factory != NULL, NULL); + + if (gst_plugin_feature_ensure_loaded (GST_PLUGIN_FEATURE (factory))) { + g_return_val_if_fail (factory->type != 0, NULL); + + new = GST_SCHEDULER (g_object_new (factory->type, NULL)); + new->parent = parent; + } + + return new; +} + +/** + * gst_schedulerfactory_make: + * @name: the name of the factory used to create the instance + * + * Create a new #GstScheduler instance from the + * schedulerfactory with the given name. + * + * Returns: A new #GstScheduler instance. + */ +GstScheduler* +gst_schedulerfactory_make (const gchar *name, GstElement *parent) +{ + GstSchedulerFactory *factory; + + g_return_val_if_fail (name != NULL, NULL); + + factory = gst_schedulerfactory_find (name); + + if (factory == NULL) + return NULL; + + return gst_schedulerfactory_create (factory, parent); +} + +#ifndef GST_DISABLE_REGISTRY +static xmlNodePtr +gst_schedulerfactory_save_thyself (GstObject *object, xmlNodePtr parent) +{ + GstSchedulerFactory *factory; + + g_return_val_if_fail (GST_IS_SCHEDULERFACTORY (object), parent); + + factory = GST_SCHEDULERFACTORY (object); + + if (GST_OBJECT_CLASS (factory_parent_class)->save_thyself) { + GST_OBJECT_CLASS (factory_parent_class)->save_thyself (object, parent); + } + + xmlNewChild (parent, NULL, "longdesc", factory->longdesc); + + return parent; +} + +/** + * gst_schedulerfactory_load_thyself: + * @parent: the parent XML node pointer + * + * Load an schedulerfactory from the given XML parent node. + * + * Returns: A new factory based on the XML node. + */ +static void +gst_schedulerfactory_restore_thyself (GstObject *object, xmlNodePtr parent) +{ + GstSchedulerFactory *factory = GST_SCHEDULERFACTORY (object); + xmlNodePtr children = parent->xmlChildrenNode; + + if (GST_OBJECT_CLASS (factory_parent_class)->restore_thyself) { + GST_OBJECT_CLASS (factory_parent_class)->restore_thyself (object, parent); + } + + while (children) { + if (!strcmp(children->name, "name")) { + gst_object_set_name (GST_OBJECT (factory), xmlNodeGetContent (children)); } - - elements = chain->elements; - while (elements) { - element = GST_ELEMENT(elements->data); - elements = g_list_next(elements); - - g_print("%s, ",GST_ELEMENT_NAME(element)); + if (!strcmp(children->name, "longdesc")) { + factory->longdesc = xmlNodeGetContent (children); } - g_print("\n"); + children = children->next; } } +#endif /* GST_DISABLE_REGISTRY */ diff --git a/gst/gstscheduler.h b/gst/gstscheduler.h index b65c5ed2d8..042664d7b9 100644 --- a/gst/gstscheduler.h +++ b/gst/gstscheduler.h @@ -2,7 +2,7 @@ * Copyright (C) 1999,2000 Erik Walthinsen * 2000 Wim Taymans * - * gstscheduler.h: Header for default scheduler code + * gstschedulerr.h: Header for default schedulerr code * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -24,40 +24,33 @@ #ifndef __GST_SCHEDULER_H__ #define __GST_SCHEDULER_H__ +#include #include #include - #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -extern GType _gst_schedule_type; - -#define GST_TYPE_SCHEDULE (_gst_schedule_type) -# define GST_IS_SCHEDULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_SCHEDULE)) -# define GST_IS_SCHEDULE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_SCHEDULE)) - -#define GST_SCHEDULE_FAST(obj) ((GstSchedule*)(obj)) -#define GST_SCHEDULE_CLASS_FAST(klass) ((GstScheduleClass*)(klass)) - -#ifdef GST_TYPE_PARANOID -# define GST_SCHEDULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_SCHEDULE, GstSchedule)) -# define GST_SCHEDULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_SCHEDULE, GstScheduleClass)) -#else -# define GST_SCHEDULE GST_SCHEDULE_FAST -# define GST_SCHEDULE_CLASS GST_SCHEDULE_CLASS_FAST -#endif +#define GST_TYPE_SCHEDULER \ + (gst_scheduler_get_type()) +#define GST_SCHEDULER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SCHEDULER,GstScheduler)) +#define GST_SCHEDULER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SCHEDULER,GstSchedulerClass)) +#define GST_IS_SCHEDULER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SCHEDULER)) +#define GST_IS_SCHEDULER_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SCHEDULER)) #define GST_SCHED_PARENT(sched) ((sched)->parent) -//typedef struct _GstSchedule GstSchedule; -//typedef struct _GstScheduleClass GstScheduleClass; -typedef struct _GstScheduleChain GstScheduleChain; +//typedef struct _GstScheduler GstScheduler; +//typedef struct _GstSchedulerClass GstSchedulerClass; -struct _GstSchedule { +struct _GstScheduler { GstObject object; GstElement *parent; @@ -67,85 +60,80 @@ struct _GstSchedule { GList *chains; gint num_chains; - - void (*add_element) (GstSchedule *sched, GstElement *element); - void (*remove_element) (GstSchedule *sched, GstElement *element); - void (*enable_element) (GstSchedule *sched, GstElement *element); - void (*disable_element) (GstSchedule *sched, GstElement *element); - void (*lock_element) (GstSchedule *sched, GstElement *element); - void (*unlock_element) (GstSchedule *sched, GstElement *element); - void (*pad_connect) (GstSchedule *sched, GstPad *srcpad, GstPad *sinkpad); - void (*pad_disconnect) (GstSchedule *sched, GstPad *srcpad, GstPad *sinkpad); - void (*pad_select) (GstSchedule *sched, GList *padlist); - gboolean (*iterate) (GstSchedule *sched); }; -struct _GstScheduleClass { +struct _GstSchedulerClass { GstObjectClass parent_class; + + void (*add_element) (GstScheduler *sched, GstElement *element); + void (*remove_element) (GstScheduler *sched, GstElement *element); + void (*enable_element) (GstScheduler *sched, GstElement *element); + void (*disable_element) (GstScheduler *sched, GstElement *element); + void (*lock_element) (GstScheduler *sched, GstElement *element); + void (*unlock_element) (GstScheduler *sched, GstElement *element); + void (*pad_connect) (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad); + void (*pad_disconnect) (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad); + void (*pad_select) (GstScheduler *sched, GList *padlist); + gboolean (*iterate) (GstScheduler *sched); + + /* for debugging */ + void (*show) (GstScheduler *sched); }; -#define GST_SCHEDULE_SAFETY(sched) if (sched) -//#define GST_SCHEDULE_SAFETY(sched) +GType gst_scheduler_get_type (void); -#define GST_SCHEDULE_ADD_ELEMENT(sched,element) G_STMT_START{ \ - GST_SCHEDULE_SAFETY(sched) { ((sched)->add_element((sched),(element))); } \ -}G_STMT_END -#define GST_SCHEDULE_REMOVE_ELEMENT(sched,element) G_STMT_START{ \ - GST_SCHEDULE_SAFETY(sched) { ((sched)->remove_element((sched),(element))); } \ -}G_STMT_END -#define GST_SCHEDULE_ENABLE_ELEMENT(sched,element) G_STMT_START{ \ - GST_SCHEDULE_SAFETY(sched) { ((sched)->enable_element((sched),(element))); } \ -}G_STMT_END -#define GST_SCHEDULE_DISABLE_ELEMENT(sched,element) G_STMT_START{ \ - GST_SCHEDULE_SAFETY(sched) { ((sched)->disable_element((sched),(element))); } \ -}G_STMT_END -#define GST_SCHEDULE_LOCK_ELEMENT(sched,element) G_STMT_START{ \ - GST_SCHEDULE_SAFETY(sched) { if ((sched)->lock_element != NULL) \ - ((sched)->lock_element((sched),(element))); } \ -}G_STMT_END -#define GST_SCHEDULE_UNLOCK_ELEMENT(sched,element) G_STMT_START{ \ - GST_SCHEDULE_SAFETY(sched) { if ((sched)->unlock_element != NULL) \ - ((sched)->unlock_element((sched),(element))); } \ -}G_STMT_END -#define GST_SCHEDULE_PAD_CONNECT(sched,srcpad,sinkpad) G_STMT_START{ \ - GST_SCHEDULE_SAFETY(sched) { ((sched)->pad_connect((sched),(srcpad),(sinkpad))); } \ -}G_STMT_END -#define GST_SCHEDULE_PAD_DISCONNECT(sched,srcpad,sinkpad) G_STMT_START{ \ - GST_SCHEDULE_SAFETY(sched) { ((sched)->pad_disconnect((sched),(srcpad),(sinkpad))); } \ -}G_STMT_END -#define GST_SCHEDULE_ITERATE(sched) \ - ((sched)->iterate((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); +void gst_scheduler_disable_element (GstScheduler *sched, GstElement *element); +void gst_scheduler_lock_element (GstScheduler *sched, GstElement *element); +void gst_scheduler_unlock_element (GstScheduler *sched, GstElement *element); +void gst_scheduler_pad_connect (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad); +void gst_scheduler_pad_disconnect (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad); +GstPad* gst_scheduler_pad_select (GstScheduler *sched, GList *padlist); +gboolean gst_scheduler_iterate (GstScheduler *sched); +void gst_scheduler_show (GstScheduler *sched); +/* + * creating schedulers + * + */ +#define GST_TYPE_SCHEDULERFACTORY \ + (gst_schedulerfactory_get_type ()) +#define GST_SCHEDULERFACTORY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_SCHEDULERFACTORY, GstSchedulerFactory)) +#define GST_SCHEDULERFACTORY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_SCHEDULERFACTORY, GstSchedulerFactoryClass)) +#define GST_IS_SCHEDULERFACTORY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_SCHEDULERFACTORY)) +#define GST_IS_SCHEDULERFACTORY_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_SCHEDULERFACTORY)) -struct _GstScheduleChain { - GstSchedule *sched; +typedef struct _GstSchedulerFactory GstSchedulerFactory; +typedef struct _GstSchedulerFactoryClass GstSchedulerFactoryClass; - GList *disabled; +struct _GstSchedulerFactory { + GstPluginFeature feature; - GList *elements; - gint num_elements; - - GstElement *entry; - - gint cothreaded_elements; - gboolean schedule; + gchar *longdesc; /* long description of the scheduler (well, don't overdo it..) */ + GType type; /* unique GType of the scheduler */ }; +struct _GstSchedulerFactoryClass { + GstPluginFeatureClass parent; +}; -GType gst_schedule_get_type (void); -GstSchedule* gst_schedule_new (GstElement *parent); +GType gst_schedulerfactory_get_type (void); -void gst_schedule_add_element (GstSchedule *sched, GstElement *element); -void gst_schedule_remove_element (GstSchedule *sched, GstElement *element); -void gst_schedule_enable_element (GstSchedule *sched, GstElement *element); -void gst_schedule_disable_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); -GstPad* gst_schedule_pad_select (GstSchedule *sched, GList *padlist); -gboolean gst_schedule_iterate (GstSchedule *sched); +GstSchedulerFactory* gst_schedulerfactory_new (const gchar *name, const gchar *longdesc, GType type); +void gst_schedulerfactory_destroy (GstSchedulerFactory *factory); -void gst_schedule_show (GstSchedule *sched); +GstSchedulerFactory* gst_schedulerfactory_find (const gchar *name); +GList* gst_schedulerfactory_get_list (void); + +GstScheduler* gst_schedulerfactory_create (GstSchedulerFactory *factory, GstElement *parent); +GstScheduler* gst_schedulerfactory_make (const gchar *name, GstElement *parent); #ifdef __cplusplus diff --git a/gst/gstthread.c b/gst/gstthread.c index 65a3793f2d..269203bed9 100644 --- a/gst/gstthread.c +++ b/gst/gstthread.c @@ -53,7 +53,6 @@ enum { enum { ARG_0, - ARG_CREATE_THREAD, }; @@ -73,8 +72,6 @@ static xmlNodePtr gst_thread_save_thyself (GstObject *object, xmlNodePtr paren static void gst_thread_restore_thyself (GstObject *object, xmlNodePtr self); #endif -static void gst_thread_signal_thread (GstThread *thread, gboolean spinning); - static void* gst_thread_main_loop (void *arg); static GstBinClass *parent_class = NULL; @@ -117,10 +114,6 @@ gst_thread_class_init (GstThreadClass *klass) parent_class = g_type_class_ref (GST_TYPE_BIN); - g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_CREATE_THREAD, - g_param_spec_boolean("create_thread", "Create Thread", "Whether to create a thread.", - TRUE,G_PARAM_READWRITE)); - gobject_class->dispose = gst_thread_dispose; #ifndef GST_DISABLE_LOADSAVE @@ -146,16 +139,14 @@ gst_thread_init (GstThread *thread) // we're a manager by default GST_FLAG_SET (thread, GST_BIN_FLAG_MANAGER); - // default is to create a thread - GST_FLAG_SET (thread, GST_THREAD_CREATE); - thread->lock = g_mutex_new(); thread->cond = g_cond_new(); - GST_ELEMENT_SCHED(thread) = gst_schedule_new(GST_ELEMENT(thread)); + GST_ELEMENT_SCHED(thread) = gst_schedulerfactory_make ("basic", GST_ELEMENT(thread)); GST_DEBUG(GST_CAT_THREAD, "thread's scheduler is %p\n",GST_ELEMENT_SCHED(thread)); thread->ppid = getpid(); + thread->thread_id = -1; // gst_element_set_manager(GST_ELEMENT(thread),GST_ELEMENT(thread)); } @@ -184,17 +175,6 @@ gst_thread_set_property (GObject *object, guint prop_id, const GValue *value, GP g_return_if_fail (GST_IS_THREAD (object)); switch (prop_id) { - case ARG_CREATE_THREAD: - if (g_value_get_boolean(value)) { - GST_INFO (GST_CAT_THREAD,"turning ON the creation of the thread"); - GST_FLAG_SET (object, GST_THREAD_CREATE); -// GST_DEBUG (GST_CAT_THREAD,"flags are 0x%08x\n", GST_FLAGS (object)); - } else { - GST_INFO (GST_CAT_THREAD,"gstthread: turning OFF the creation of the thread"); - GST_FLAG_UNSET (object, GST_THREAD_CREATE); -// GST_DEBUG (GST_CAT_THREAD,"gstthread: flags are 0x%08x\n", GST_FLAGS (object)); - } - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -208,9 +188,6 @@ gst_thread_get_property (GObject *object, guint prop_id, GValue *value, GParamSp g_return_if_fail (GST_IS_THREAD (object)); switch (prop_id) { - case ARG_CREATE_THREAD: - g_value_set_boolean(value, GST_FLAG_IS_SET (object, GST_THREAD_CREATE)); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -247,256 +224,198 @@ gst_thread_new (const gchar *name) GST_DEBUG_ELEMENT(GST_CAT_THREAD, thread, "sync-main(" GST_DEBUG_THREAD_FORMAT "): " format , \ GST_DEBUG_THREAD_ARGS(thread->ppid) , ## args ) - -static GstElementStateReturn -gst_thread_change_state (GstElement *element) -{ - GstThread *thread; - gboolean stateset = GST_STATE_SUCCESS; - gint transition; - pthread_t self = pthread_self(); - - g_return_val_if_fail (GST_IS_THREAD(element), FALSE); -// GST_DEBUG_ENTER("(\"%s\")",GST_ELEMENT_NAME(element)); - - thread = GST_THREAD (element); -// GST_DEBUG (GST_CAT_THREAD, "**** THREAD %ld changing THREAD %ld ****\n",self,thread->thread_id); -// GST_DEBUG (GST_CAT_THREAD, "**** current pid=%d\n",getpid()); - - transition = GST_STATE_TRANSITION (element); - - THR_INFO("changing state from %s to %s", - gst_element_statename(GST_STATE (element)), - gst_element_statename(GST_STATE_PENDING (element))); - - //GST_FLAG_UNSET (thread, GST_THREAD_STATE_SPINNING); - - switch (transition) { - case GST_STATE_NULL_TO_READY: - // set the state to idle - GST_FLAG_UNSET (thread, GST_THREAD_STATE_SPINNING); - GST_FLAG_UNSET (thread, GST_THREAD_STATE_REAPING); - - // create the thread if that's what we're supposed to do - if (GST_FLAG_IS_SET (thread, GST_THREAD_CREATE)) { - THR_DEBUG ("creating thread \"%s\"\n", - GST_ELEMENT_NAME (element)); - - g_mutex_lock (thread->lock); - - // create the thread - pthread_create (&thread->thread_id, NULL, - gst_thread_main_loop, thread); - - // wait for it to 'spin up' - THR_DEBUG("waiting for child thread spinup\n"); - g_cond_wait(thread->cond,thread->lock); - THR_DEBUG("thread claims to be up\n"); - g_mutex_unlock(thread->lock); - } else { - GST_INFO (GST_CAT_THREAD, "NOT creating thread \"%s\"", - GST_ELEMENT_NAME (GST_ELEMENT (element))); - - // punt and change state on all the children - if (GST_ELEMENT_CLASS (parent_class)->change_state) - stateset = GST_ELEMENT_CLASS (parent_class)->change_state (element); - } - break; - case GST_STATE_READY_TO_PAUSED: - THR_INFO("readying thread"); - - // check to see if the thread is somehow changing its own state. - // FIXME this is currently illegal, but must somehow be made legal at some point. - if (pthread_equal(self, thread->thread_id)) - { - //FIXME this should not happen - g_assert(!pthread_equal(self, thread->thread_id)); - GST_FLAG_SET(thread, GST_THREAD_STATE_SPINNING); - GST_DEBUG(GST_CAT_THREAD,"no sync(" GST_DEBUG_THREAD_FORMAT "): setting own thread's state to spinning\n", - GST_DEBUG_THREAD_ARGS(thread->pid)); - } - else - { - g_mutex_lock(thread->lock); - gst_thread_signal_thread(thread,FALSE); - } - break; - case GST_STATE_PAUSED_TO_PLAYING: - THR_INFO("starting thread"); - - // check to see if the thread is somehow changing its own state. - // FIXME this is currently illegal, but must somehow be made legal at some point. - if (pthread_equal(self, thread->thread_id)) - { - //FIXME this should not happen - g_assert(!pthread_equal(self, thread->thread_id)); - GST_FLAG_SET(thread, GST_THREAD_STATE_SPINNING); - GST_DEBUG(GST_CAT_THREAD,"no sync(" GST_DEBUG_THREAD_FORMAT "): setting own thread's state to spinning\n", - GST_DEBUG_THREAD_ARGS(thread->pid)); - } - else - { - THR_DEBUG("telling thread to start spinning\n"); - g_mutex_lock(thread->lock); - gst_thread_signal_thread(thread,TRUE); - } - break; - case GST_STATE_PLAYING_TO_PAUSED: - THR_INFO("pausing thread"); - - // check to see if the thread is somehow changing its own state. - // FIXME this is currently illegal, but must somehow be made legal at some point. - if (pthread_equal(self, thread->thread_id)) - { - //FIXME this should not happen - GST_DEBUG(GST_CAT_THREAD,"no sync(" GST_DEBUG_THREAD_FORMAT "): setting own thread's state to paused\n", - GST_DEBUG_THREAD_ARGS(thread->pid)); - GST_FLAG_UNSET (thread, GST_THREAD_STATE_SPINNING); - g_assert(!pthread_equal(self, thread->thread_id)); - } - else - { - GList *elements = (element->sched)->elements; - - // the following code ensures that the bottom half of thread will run - // to perform each elements' change_state() (by calling gstbin.c:: - // change_state()). - // + the pending state was already set by gstelement.c::set_state() - // + find every queue we manage, and signal its empty and full conditions - - g_mutex_lock(thread->lock); - - GST_FLAG_UNSET (thread, GST_THREAD_STATE_SPINNING); - - while (elements) - { - GstElement *e = GST_ELEMENT(elements->data); - g_assert(e); - THR_DEBUG(" element \"%s\"\n",GST_ELEMENT_NAME(e)); - elements = g_list_next(elements); - if (GST_IS_QUEUE(e)) - { - //FIXME make this more efficient by only waking queues that are asleep - //FIXME and only waking the appropriate condition (depending on if it's - //FIXME on up- or down-stream side) - // - //FIXME also make this more efficient by keeping list of managed queues - THR_DEBUG("waking queue \"%s\"\n",GST_ELEMENT_NAME(e)); - //GST_LOCK(e); - g_cond_signal((GST_QUEUE(e)->not_empty)); - g_cond_signal((GST_QUEUE(e)->not_full)); - //GST_UNLOCK(e); - } - else - { - GList *pads = GST_ELEMENT_PADS(e); - while (pads) - { - GstRealPad *peer; - GstElement *peerelement; - GstPad *p = GST_PAD(pads->data); - pads = g_list_next(pads); - - peer = GST_PAD_PEER(p); - if (!peer) continue; - - peerelement = GST_PAD_PARENT(peer); - if (!peerelement) continue; // deal with case where there's no peer - - if (!GST_FLAG_IS_SET(peerelement,GST_ELEMENT_DECOUPLED)) { - GST_DEBUG(GST_CAT_THREAD,"peer element isn't DECOUPLED\n"); - continue; - } - - // FIXME this needs to go away eventually - if (!GST_IS_QUEUE(peerelement)) { - GST_DEBUG(GST_CAT_THREAD,"peer element isn't a Queue\n"); - continue; - } - - if (GST_ELEMENT_SCHED(peerelement) != GST_ELEMENT_SCHED(thread)) - { - THR_DEBUG(" element \"%s\" has pad cross sched boundary\n",GST_ELEMENT_NAME(e)); - //GST_LOCK(peerelement); - g_cond_signal(GST_QUEUE(peerelement)->not_empty); - g_cond_signal(GST_QUEUE(peerelement)->not_full); - //GST_UNLOCK(peerelement); - } - } - } - } - THR_DEBUG("waiting for thread to stop spinning\n"); - g_cond_wait (thread->cond, thread->lock); - THR_DEBUG("telling thread to pause\n"); - gst_thread_signal_thread(thread,FALSE); - } - break; - case GST_STATE_READY_TO_NULL: - THR_INFO("stopping thread"); - - GST_FLAG_SET (thread, GST_THREAD_STATE_REAPING); - - // check to see if the thread is somehow changing its own state. - // FIXME this is currently illegal, but must somehow be made legal at some point. - if (pthread_equal(self, thread->thread_id)) - { - //FIXME this should not happen - g_assert(!pthread_equal(self, thread->thread_id)); - THR_DEBUG("setting own thread's state to NULL (paused)\n"); - GST_FLAG_UNSET (thread, GST_THREAD_STATE_SPINNING); - } - else - { - THR_DEBUG("telling thread to pause (null) - and joining\n"); - //MattH FIXME revisit - g_mutex_lock(thread->lock); - gst_thread_signal_thread(thread,FALSE); - pthread_join(thread->thread_id,NULL); - } - - GST_FLAG_UNSET(thread,GST_THREAD_STATE_REAPING); - GST_FLAG_UNSET(thread,GST_THREAD_STATE_STARTED); - GST_FLAG_UNSET(thread,GST_THREAD_STATE_SPINNING); - GST_FLAG_UNSET(thread,GST_THREAD_STATE_ELEMENT_CHANGED); - - break; - case GST_STATE_PAUSED_TO_READY: - THR_INFO("stopping thread"); - - // check to see if the thread is somehow changing its own state. - // FIXME this is currently illegal, but must somehow be made legal at some point. - if (pthread_equal(self, thread->thread_id)) - { - //FIXME this should not happen - g_assert(!pthread_equal(self, thread->thread_id)); - GST_FLAG_SET(thread, GST_THREAD_STATE_SPINNING); - GST_DEBUG(GST_CAT_THREAD,"no sync(" GST_DEBUG_THREAD_FORMAT "): setting own thread's state to spinning\n", - GST_DEBUG_THREAD_ARGS(thread->pid)); - } - else - { - THR_DEBUG("telling thread to stop spinning\n"); - g_mutex_lock(thread->lock); - gst_thread_signal_thread(thread,FALSE); - } - - break; - default: - GST_DEBUG_ELEMENT(GST_CAT_THREAD, element, "UNHANDLED STATE CHANGE! %x\n",transition); - break; - } - - return stateset; -} - -static void gst_thread_update_state (GstThread *thread) +static GstElementStateReturn +gst_thread_update_state (GstThread *thread) { // check for state change if (GST_STATE_PENDING(thread) != GST_STATE_VOID_PENDING) { // punt and change state on all the children if (GST_ELEMENT_CLASS (parent_class)->change_state) - GST_ELEMENT_CLASS (parent_class)->change_state (GST_ELEMENT(thread)); + return GST_ELEMENT_CLASS (parent_class)->change_state (GST_ELEMENT(thread)); } + + return GST_STATE_SUCCESS; +} + + +static GstElementStateReturn +gst_thread_change_state (GstElement * element) +{ + GstThread *thread; + gboolean stateset = GST_STATE_SUCCESS; + gint transition; + pthread_t self = pthread_self (); + + g_return_val_if_fail (GST_IS_THREAD (element), FALSE); + + thread = GST_THREAD (element); + + transition = GST_STATE_TRANSITION (element); + + THR_INFO ("changing state from %s to %s", + gst_element_statename (GST_STATE (element)), + gst_element_statename (GST_STATE_PENDING (element))); + + if (pthread_equal (self, thread->thread_id)) { + GST_DEBUG (GST_CAT_THREAD, + "no sync(" GST_DEBUG_THREAD_FORMAT "): setting own thread's state to spinning\n", + GST_DEBUG_THREAD_ARGS (thread->pid)); + return gst_thread_update_state (thread); + } + + switch (transition) { + case GST_STATE_NULL_TO_READY: + // set the state to idle + GST_FLAG_UNSET (thread, GST_THREAD_STATE_SPINNING); + + THR_DEBUG ("creating thread \"%s\"\n", GST_ELEMENT_NAME (element)); + + g_mutex_lock (thread->lock); + + // create the thread + pthread_create (&thread->thread_id, NULL, gst_thread_main_loop, thread); + + // wait for it to 'spin up' + THR_DEBUG ("waiting for child thread spinup\n"); + g_cond_wait (thread->cond, thread->lock); + THR_DEBUG ("thread claims to be up\n"); + g_mutex_unlock (thread->lock); + break; + case GST_STATE_READY_TO_PAUSED: + THR_INFO ("readying thread"); + g_mutex_lock (thread->lock); + THR_DEBUG ("signaling\n"); + g_cond_signal (thread->cond); + THR_DEBUG ("waiting for ack\n"); + g_cond_wait (thread->cond, thread->lock); + THR_DEBUG ("got ack\n"); + g_mutex_unlock (thread->lock); + break; + case GST_STATE_PAUSED_TO_PLAYING: + THR_DEBUG ("telling thread to start spinning\n"); + g_mutex_lock (thread->lock); + THR_DEBUG ("signaling\n"); + g_cond_signal (thread->cond); + THR_DEBUG ("waiting for ack\n"); + g_cond_wait (thread->cond, thread->lock); + THR_DEBUG ("got ack\n"); + g_mutex_unlock (thread->lock); + break; + case GST_STATE_PLAYING_TO_PAUSED: + { + GList *elements = (element->sched)->elements; + + THR_INFO ("pausing thread"); + + // the following code ensures that the bottom half of thread will run + // to perform each elements' change_state() (by calling gstbin.c:: + // change_state()). + // + the pending state was already set by gstelement.c::set_state() + // + find every queue we manage, and signal its empty and full conditions + g_mutex_lock (thread->lock); + + GST_FLAG_UNSET (thread, GST_THREAD_STATE_SPINNING); + + while (elements) { + GstElement *e = GST_ELEMENT (elements->data); + + g_assert (e); + THR_DEBUG (" element \"%s\"\n", GST_ELEMENT_NAME (e)); + elements = g_list_next (elements); + if (GST_IS_QUEUE (e)) { + //FIXME make this more efficient by only waking queues that are asleep + //FIXME and only waking the appropriate condition (depending on if it's + //FIXME on up- or down-stream side) + // + //FIXME also make this more efficient by keeping list of managed queues + THR_DEBUG ("waking queue \"%s\"\n", GST_ELEMENT_NAME (e)); + gst_element_set_state (e, GST_STATE_PAUSED); + } + else { + GList *pads = GST_ELEMENT_PADS (e); + + while (pads) { + GstRealPad *peer; + GstElement *peerelement; + GstPad *p = GST_PAD (pads->data); + + pads = g_list_next (pads); + + peer = GST_PAD_PEER (p); + if (!peer) + continue; + + peerelement = GST_PAD_PARENT (peer); + if (!peerelement) + continue; // deal with case where there's no peer + + if (!GST_FLAG_IS_SET (peerelement, GST_ELEMENT_DECOUPLED)) { + GST_DEBUG (GST_CAT_THREAD, "peer element isn't DECOUPLED\n"); + continue; + } + + // FIXME this needs to go away eventually + if (!GST_IS_QUEUE (peerelement)) { + GST_DEBUG (GST_CAT_THREAD, "peer element isn't a Queue\n"); + continue; + } + + if (GST_ELEMENT_SCHED (peerelement) != GST_ELEMENT_SCHED (thread)) { + GstQueue *queue = GST_QUEUE (peerelement); + + THR_DEBUG (" element \"%s\" has pad cross sched boundary\n", GST_ELEMENT_NAME (e)); + // FIXME!! + g_mutex_lock (queue->qlock); + g_cond_signal (queue->not_full); + g_cond_signal (queue->not_empty); + g_mutex_unlock (queue->qlock); + } + } + } + } + THR_DEBUG ("telling thread to pause, signaling\n"); + g_cond_signal (thread->cond); + THR_DEBUG ("waiting for ack\n"); + g_cond_wait (thread->cond, thread->lock); + THR_DEBUG ("got ack\n"); + g_mutex_unlock (thread->lock); + break; + } + case GST_STATE_READY_TO_NULL: + THR_DEBUG ("telling thread to pause (null) - and joining\n"); + //MattH FIXME revisit + g_mutex_lock (thread->lock); + THR_DEBUG ("signaling\n"); + g_cond_signal (thread->cond); + THR_DEBUG ("waiting for ack\n"); + g_cond_wait (thread->cond, thread->lock); + THR_DEBUG ("got ack\n"); + pthread_join (thread->thread_id, NULL); + thread->thread_id = -1; + g_mutex_unlock (thread->lock); + + GST_FLAG_UNSET (thread, GST_THREAD_STATE_REAPING); + GST_FLAG_UNSET (thread, GST_THREAD_STATE_STARTED); + GST_FLAG_UNSET (thread, GST_THREAD_STATE_SPINNING); + + break; + case GST_STATE_PAUSED_TO_READY: + THR_DEBUG ("telling thread to stop spinning\n"); + g_mutex_lock (thread->lock); + THR_DEBUG ("signaling\n"); + g_cond_signal (thread->cond); + THR_DEBUG ("waiting for ack\n"); + g_cond_wait (thread->cond, thread->lock); + THR_DEBUG ("got ack\n"); + g_mutex_unlock (thread->lock); + + break; + default: + GST_DEBUG_ELEMENT (GST_CAT_THREAD, element, "UNHANDLED STATE CHANGE! %x\n", transition); + break; + } + + return stateset; } /** @@ -512,151 +431,123 @@ gst_thread_main_loop (void *arg) GstThread *thread = GST_THREAD (arg); gint stateset; + g_mutex_lock (thread->lock); + + GST_FLAG_UNSET (thread, GST_THREAD_STATE_REAPING); + thread->pid = getpid(); THR_INFO_MAIN("thread is running"); // first we need to change the state of all the children - if (GST_ELEMENT_CLASS (parent_class)->change_state) + if (GST_ELEMENT_CLASS (parent_class)->change_state) { stateset = GST_ELEMENT_CLASS (parent_class)->change_state (GST_ELEMENT(thread)); - // construct the plan and signal back -/* DEPRACATED for INCSCHED1 - THR_DEBUG_MAIN("creating plan for thread\n"); - if (GST_BIN_CLASS (parent_class)->schedule) - GST_BIN_CLASS (parent_class)->schedule (GST_BIN (thread)); -*/ + if (stateset != GST_STATE_SUCCESS) { + THR_DEBUG_MAIN ("state change of children failed\n"); + } + } -// THR_DEBUG_MAIN("indicating spinup\n"); - g_mutex_lock (thread->lock); + + THR_DEBUG_MAIN ("indicating spinup\n"); g_cond_signal (thread->cond); // don't unlock the mutex because we hold it into the top of the while loop - THR_DEBUG_MAIN("thread has indicated spinup to parent process\n"); + THR_DEBUG_MAIN ("thread has indicated spinup to parent process\n"); /***** THREAD IS NOW IN READY STATE *****/ while (!GST_FLAG_IS_SET (thread, GST_THREAD_STATE_REAPING)) { // NOTE we hold the thread lock at this point // what we do depends on what state we're in - switch (GST_STATE(thread)) { + switch (GST_STATE (thread)) { // NOTE: cannot be in NULL, we're not running in that state at all case GST_STATE_READY: // wait to be set to either the NULL or PAUSED states - THR_DEBUG_MAIN("thread in %s state, waiting for either %s or %s\n", - gst_element_statename(GST_STATE_READY), - gst_element_statename(GST_STATE_NULL), - gst_element_statename(GST_STATE_PAUSED)); - g_cond_wait(thread->cond,thread->lock); + THR_DEBUG_MAIN ("thread in %s state, waiting for either %s or %s\n", + gst_element_statename (GST_STATE_READY), + gst_element_statename (GST_STATE_NULL), + gst_element_statename (GST_STATE_PAUSED)); + g_cond_wait (thread->cond,thread->lock); + + g_assert (GST_STATE_PENDING (thread) == GST_STATE_NULL || + GST_STATE_PENDING (thread) == GST_STATE_PAUSED); + // been signaled, we need to state transition now and signal back - gst_thread_update_state(thread); - THR_DEBUG_MAIN("done with state transition, signaling back to parent process\n"); - g_cond_signal(thread->cond); -// g_mutex_unlock(thread->lock); - // now we decide what to do next (FIXME can be collapsed to a continue) - if (GST_STATE(thread) == GST_STATE_NULL) { + gst_thread_update_state (thread); + THR_DEBUG_MAIN ("done with state transition, signaling back to parent process\n"); + g_cond_signal (thread->cond); + // now we decide what to do next + if (GST_STATE (thread) == GST_STATE_NULL) { // REAPING must be set, we can simply break this iteration - continue; - } else { - // PAUSED is the next state, we can wait for that next - continue; - } - break; + GST_FLAG_SET (thread, GST_THREAD_STATE_REAPING); + } + continue; case GST_STATE_PAUSED: // wait to be set to either the READY or PLAYING states THR_DEBUG_MAIN("thread in %s state, waiting for either %s or %s\n", - gst_element_statename(GST_STATE_PAUSED), - gst_element_statename(GST_STATE_READY), - gst_element_statename(GST_STATE_PLAYING)); - g_cond_wait(thread->cond,thread->lock); + gst_element_statename (GST_STATE_PAUSED), + gst_element_statename (GST_STATE_READY), + gst_element_statename (GST_STATE_PLAYING)); + g_cond_wait (thread->cond,thread->lock); + + g_assert (GST_STATE_PENDING (thread) == GST_STATE_READY || + GST_STATE_PENDING (thread) == GST_STATE_PLAYING); + // been signaled, we need to state transition now and signal back - gst_thread_update_state(thread); - g_cond_signal(thread->cond); -// g_mutex_unlock(thread->lock); + gst_thread_update_state (thread); // now we decide what to do next - if (GST_STATE(thread) == GST_STATE_READY) { - // READY is the next state, we can wait for that next + if (GST_STATE (thread) != GST_STATE_PLAYING) { + // either READY or the state change failed for some reason + g_cond_signal (thread->cond); continue; - } else { - g_mutex_unlock(thread->lock); + } + else { + GST_FLAG_SET (thread, GST_THREAD_STATE_SPINNING); // PLAYING is coming up, so we can now start spinning while (GST_FLAG_IS_SET (thread, GST_THREAD_STATE_SPINNING)) { - if (!gst_bin_iterate (GST_BIN (thread))) { -// GST_FLAG_UNSET (thread, GST_THREAD_STATE_SPINNING); -// THR_DEBUG_MAIN("removed spinning state due to failed iteration!\n"); - // FIXME FIXME FIXME this is ugly! - THR_DEBUG_MAIN("iteration failed, something very wrong, spinning to let parent sync\n"); - while (GST_FLAG_IS_SET(thread, GST_THREAD_STATE_SPINNING)) ; - } + gboolean status; + + g_cond_signal (thread->cond); + g_mutex_unlock (thread->lock); + status = gst_bin_iterate (GST_BIN (thread)); + g_mutex_lock (thread->lock); + //g_cond_signal(thread->cond); + + if (!status || GST_STATE_PENDING (thread) != GST_STATE_VOID_PENDING) + GST_FLAG_UNSET (thread, GST_THREAD_STATE_SPINNING); } - g_mutex_lock(thread->lock); + // looks like we were stopped because of a statechange + if (GST_STATE_PENDING (thread)) { + gst_thread_update_state (thread); + } // once we're here, SPINNING has stopped, we should signal that we're done - THR_DEBUG_MAIN("SPINNING stopped, signaling back to parent process\n"); + THR_DEBUG_MAIN ("SPINNING stopped, signaling back to parent process\n"); g_cond_signal (thread->cond); // now we can wait for PAUSED continue; } - break; case GST_STATE_PLAYING: // wait to be set to PAUSED - THR_DEBUG_MAIN("thread in %s state, waiting for %s\n", - gst_element_statename(GST_STATE_PLAYING), - gst_element_statename(GST_STATE_PAUSED)); - g_cond_wait(thread->cond,thread->lock); + THR_DEBUG_MAIN ("thread in %s state, waiting for %s\n", + gst_element_statename(GST_STATE_PLAYING), + gst_element_statename(GST_STATE_PAUSED)); + g_cond_wait (thread->cond,thread->lock); + // been signaled, we need to state transition now and signal back - gst_thread_update_state(thread); - g_cond_signal(thread->cond); -// g_mutex_unlock(thread->lock); + gst_thread_update_state (thread); + g_cond_signal (thread->cond); // now we decide what to do next // there's only PAUSED, we we just wait for it continue; + case GST_STATE_NULL: + THR_DEBUG_MAIN ("thread in %s state, preparing to die\n", + gst_element_statename(GST_STATE_NULL)); + GST_FLAG_SET (thread, GST_THREAD_STATE_REAPING); + break; + default: + g_assert_not_reached (); break; } - - // need to grab the lock so we're ready for the top of the loop -// g_mutex_lock(thread->lock); } - -/* - while (!GST_FLAG_IS_SET (thread, GST_THREAD_STATE_REAPING)) { - // start out by waiting for a state change into spinning - THR_DEBUG_MAIN("waiting for signal from parent process (at top of while())\n"); - g_cond_wait (thread->cond,thread->lock); - THR_DEBUG_MAIN("woken up with %s pending\n",gst_element_statename(GST_STATE(thread))); - // now is a good time to change the state of the children and the thread itself - gst_thread_update_state (thread); - THR_DEBUG_MAIN("done changing state, signaling back\n"); - g_cond_signal (thread->cond); - g_mutex_unlock (thread->lock); - THR_DEBUG_MAIN("finished sycnronizing with main process\n"); - - while (GST_FLAG_IS_SET (thread, GST_THREAD_STATE_SPINNING)) { - if (!gst_bin_iterate (GST_BIN (thread))) { - GST_FLAG_UNSET (thread, GST_THREAD_STATE_SPINNING); - THR_DEBUG_MAIN("removed spinning state due to failed iteration!\n"); - } - } - - g_mutex_lock (thread->lock); - - if (GST_STATE_PENDING(thread) == GST_STATE_PAUSED) { - // we've stopped spinning, because of PLAYING->PAUSED - THR_DEBUG_MAIN("SPINNING flag unset, signaling parent process we're stopped\n"); - // we need to signal back that we've stopped spinning - g_cond_signal (thread->cond); - } - -// THR_DEBUG_MAIN("signaling that the thread is out of the SPINNING loop\n"); -// g_cond_signal (thread->cond); -// g_cond_wait (thread->cond, thread->lock); -// THR_DEBUG_MAIN("parent process has signaled at bottom of while\n"); -// // now change the children's and thread's state -// gst_thread_update_state (thread); -// THR_DEBUG_MAIN("done changing state, signaling back to parent process\n"); -// g_cond_signal (thread->cond); -// // don't release the mutex, we hold that into the top of the loop -// THR_DEBUG_MAIN("done syncing with parent process at bottom of while\n"); - } -*/ - // since we don't unlock at the end of the while loop, do it here g_mutex_unlock (thread->lock); @@ -665,37 +556,6 @@ gst_thread_main_loop (void *arg) return NULL; } -// the set flag is to say whether it should set TRUE or FALSE -// -// WARNING: this has synchronization built in! if you remove or add any -// locks, waits, signals, or unlocks you need to be sure they match the -// code above (in gst_thread_main_loop()). basically, don't change anything. -static void -gst_thread_signal_thread (GstThread *thread, gboolean spinning) -{ - // set the spinning state - if (spinning) GST_FLAG_SET(thread,GST_THREAD_STATE_SPINNING); - else GST_FLAG_UNSET (thread, GST_THREAD_STATE_SPINNING); - - THR_DEBUG("thread locked\n"); -// g_mutex_lock(thread->lock); - -// if (!spinning) { -// THR_DEBUG("waiting for spindown\n"); -// g_cond_wait (thread->cond, thread->lock); -// } - THR_DEBUG("signaling\n"); - g_cond_signal (thread->cond); - THR_DEBUG("waiting for ack\n"); - g_cond_wait (thread->cond,thread->lock); - THR_DEBUG("got ack\n"); - - THR_DEBUG("unlocking\n"); - g_mutex_unlock(thread->lock); - THR_DEBUG("unlocked\n"); -} - - #ifndef GST_DISABLE_LOADSAVE static xmlNodePtr gst_thread_save_thyself (GstObject *object, diff --git a/gst/gstthread.h b/gst/gstthread.h index 961457679c..def68e3257 100644 --- a/gst/gstthread.h +++ b/gst/gstthread.h @@ -38,12 +38,9 @@ extern GstElementDetails gst_thread_details; typedef enum { - GST_THREAD_CREATE = GST_BIN_FLAG_LAST, - - GST_THREAD_STATE_STARTED, + GST_THREAD_STATE_STARTED = GST_BIN_FLAG_LAST, GST_THREAD_STATE_SPINNING, GST_THREAD_STATE_REAPING, - GST_THREAD_STATE_ELEMENT_CHANGED, /* padding */ GST_THREAD_FLAG_LAST = GST_BIN_FLAG_LAST + 4, diff --git a/gst/gsttrace.c b/gst/gsttrace.c index 6aad091253..b792169cc4 100644 --- a/gst/gsttrace.c +++ b/gst/gsttrace.c @@ -33,101 +33,119 @@ #include "gstlog.h" #include "gsttrace.h" - -__inline__ void read_tsc(guint64 *dst) { +static __inline__ void +read_tsc (guint64 * dst) +{ #ifdef HAVE_RDTSC guint64 tsc; - __asm__ __volatile__ ("rdtsc" : "=A" (tsc)); + __asm__ __volatile__ ("rdtsc":"=A" (tsc)); + *dst = tsc; #else *dst = 0; #endif } -void gst_trace_read_tsc(guint64 *dst) { - read_tsc(dst); +void +gst_trace_read_tsc (guint64 * dst) +{ + read_tsc (dst); } GstTrace *_gst_trace_default = NULL; gint _gst_trace_on = 1; -GstTrace *gst_trace_new(guchar *filename,gint size) { - GstTrace *trace = g_malloc(sizeof(GstTrace)); +GstTrace * +gst_trace_new (guchar * filename, gint size) +{ + GstTrace *trace = g_malloc (sizeof (GstTrace)); - g_return_val_if_fail(trace != NULL,NULL); - trace->filename = g_strdup(filename); - g_print("opening '%s'\n",trace->filename); - trace->fd = open(trace->filename,O_RDWR|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR); - perror("opening trace file"); - g_return_val_if_fail(trace->fd > 0,NULL); - trace->buf = g_malloc(size * sizeof(GstTraceEntry)); - g_return_val_if_fail(trace->buf != NULL,NULL); + g_return_val_if_fail (trace != NULL, NULL); + trace->filename = g_strdup (filename); + g_print ("opening '%s'\n", trace->filename); + trace->fd = open (trace->filename, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); + perror ("opening trace file"); + g_return_val_if_fail (trace->fd > 0, NULL); + trace->buf = g_malloc (size * sizeof (GstTraceEntry)); + g_return_val_if_fail (trace->buf != NULL, NULL); trace->bufsize = size; trace->bufoffset = 0; return trace; } -void gst_trace_destroy(GstTrace *trace) { - g_return_if_fail(trace != NULL); - g_return_if_fail(trace->buf != NULL); +void +gst_trace_destroy (GstTrace * trace) +{ + g_return_if_fail (trace != NULL); + g_return_if_fail (trace->buf != NULL); - if (gst_trace_get_remaining(trace) > 0) - gst_trace_flush(trace); - close(trace->fd); - g_free(trace->buf); - g_free(trace); + if (gst_trace_get_remaining (trace) > 0) + gst_trace_flush (trace); + close (trace->fd); + g_free (trace->buf); + g_free (trace); } -void gst_trace_flush(GstTrace *trace) { +void +gst_trace_flush (GstTrace * trace) +{ if (!trace) { trace = _gst_trace_default; - if (!trace ) return; + if (!trace) + return; } - write(trace->fd,trace->buf,trace->bufoffset * sizeof(GstTraceEntry)); + write (trace->fd, trace->buf, trace->bufoffset * sizeof (GstTraceEntry)); trace->bufoffset = 0; } -void gst_trace_text_flush(GstTrace *trace) { +void +gst_trace_text_flush (GstTrace * trace) +{ int i; - const int strsize = 20+1 + 10+1 + 10+1 + 112+1 + 1; + const int strsize = 20 + 1 + 10 + 1 + 10 + 1 + 112 + 1 + 1; char str[strsize]; if (!trace) { trace = _gst_trace_default; - if (!trace ) return; + if (!trace) + return; } - for (i=0; ibufoffset; i++) { - snprintf(str, strsize, "%20lld %10d %10d %s\n", - trace->buf[i].timestamp, - trace->buf[i].sequence, - trace->buf[i].data, - trace->buf[i].message); - write(trace->fd,str,strlen(str)); + for (i = 0; i < trace->bufoffset; i++) { + snprintf (str, strsize, "%20lld %10d %10d %s\n", + trace->buf[i].timestamp, + trace->buf[i].sequence, trace->buf[i].data, trace->buf[i].message); + write (trace->fd, str, strlen (str)); } trace->bufoffset = 0; } -void gst_trace_set_default(GstTrace *trace) { - g_return_if_fail(trace != NULL); +void +gst_trace_set_default (GstTrace * trace) +{ + g_return_if_fail (trace != NULL); _gst_trace_default = trace; } -void _gst_trace_add_entry(GstTrace *trace,guint32 seq,guint32 data,gchar *msg) { +void +_gst_trace_add_entry (GstTrace * trace, guint32 seq, guint32 data, gchar * msg) +{ GstTraceEntry *entry; + if (!trace) { trace = _gst_trace_default; - if (!trace ) return; + if (!trace) + return; } entry = trace->buf + trace->bufoffset; - read_tsc(&(entry->timestamp)); + read_tsc (&(entry->timestamp)); entry->sequence = seq; entry->data = data; - strncpy(entry->message,msg,112); + strncpy (entry->message, msg, 112); trace->bufoffset++; - gst_trace_flush(trace); + gst_trace_flush (trace); } diff --git a/gst/gsttypes.h b/gst/gsttypes.h index a7c07ed8fb..e6f0335b41 100644 --- a/gst/gsttypes.h +++ b/gst/gsttypes.h @@ -11,7 +11,7 @@ typedef struct _GstElement GstElement; typedef struct _GstElementClass GstElementClass; typedef struct _GstBin GstBin; typedef struct _GstBinClass GstBinClass; -typedef struct _GstSchedule GstSchedule; -typedef struct _GstScheduleClass GstScheduleClass; +typedef struct _GstScheduler GstScheduler; +typedef struct _GstSchedulerClass GstSchedulerClass; #endif diff --git a/gst/gstutils.c b/gst/gstutils.c index b119a868a4..5e9c55f295 100644 --- a/gst/gstutils.c +++ b/gst/gstutils.c @@ -562,8 +562,9 @@ gst_print_element_args (GString * buf, gint indent, GstElement * element) g_string_append_c (buf, '\n'); - if (G_VALUE_TYPE (&value)) + if (G_VALUE_TYPE (&value)) { g_value_unset (&value); + } } g_free (property_specs); } diff --git a/gst/types/Makefile.am b/gst/types/Makefile.am index df92364e5f..cf6ae60bd0 100644 --- a/gst/types/Makefile.am +++ b/gst/types/Makefile.am @@ -5,7 +5,5 @@ filter_LTLIBRARIES = libgsttypes.la libgsttypes_la_SOURCES = gsttypes.c libgsttypes_la_CFLAGS = $(XML_CFLAGS) $(GLIB_CFLAGS) - libgsttypes_la_LIBADD = $(XML_LIBS) $(GLIB_LIBS) - libgsttypes_la_LDFLAGS = -version-info $(GST_LIBVERSION) diff --git a/gstplay/ChangeLog b/gstplay/ChangeLog index c21f14061c..232e5227d5 100644 --- a/gstplay/ChangeLog +++ b/gstplay/ChangeLog @@ -1,3 +1,17 @@ +2001-12-04 Arik Devens + + This is a minor update on a few things while i work on getting the + new gstplay into cvs. Enjoy :-) + + * gstmediaplay.c (on_load_file_selected): As below, commented out + the addto_playlist line to get rid of GtkCList warnings. + (gst_media_play_set_fullscreen): Added setting and unsetting of + the GdkCursor on fullscreen to hide the cursor while playing + video. + + * main.c (main): Commented out adding to the playlist for now to + get rid of the GtkCList warning. + 2001-08-15 Arik Devens * gstmediaplay.c (gst_media_play_set_fullscreen): Added a hacky diff --git a/gstplay/gstmediaplay.c b/gstplay/gstmediaplay.c index c9f59679ee..b468caae92 100644 --- a/gstplay/gstmediaplay.c +++ b/gstplay/gstmediaplay.c @@ -316,7 +316,7 @@ on_load_file_selected (GtkWidget *button, gst_media_play_start_uri (play, file_name); gdk_threads_enter(); - gst_media_play_addto_playlist (play, file_name); + //gst_media_play_addto_playlist (play, file_name); g_free (data); } @@ -506,6 +506,19 @@ gst_media_play_set_fullscreen (GstMediaPlay *mplay) gint width, height, source_width, source_height; GstPlay *play; GtkWidget *video_widget; + GdkCursor* cursor; + GdkPixmap *source; + GdkPixmap *mask; + GdkColor fg = {0, 0, 0, 0}; + GdkColor bg = {0, 0, 0, 0}; + static unsigned char cursor_bits[] = { + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + static unsigned char cursormask_bits[] = { + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; gdk_window = mplay->window->window; play = mplay->play; @@ -530,6 +543,16 @@ gst_media_play_set_fullscreen (GstMediaPlay *mplay) gtk_widget_set_usize (video_widget, gdk_screen_width () + 1, gdk_screen_height () + 1); + source = gdk_bitmap_create_from_data (NULL, cursor_bits, + 16, 16); + mask = gdk_bitmap_create_from_data (NULL, cursormask_bits, + 16, 16); + cursor = gdk_cursor_new_from_pixmap (source, mask, &fg, &bg, 8, 8); + gdk_pixmap_unref (source); + gdk_pixmap_unref (mask); + + gdk_window_set_cursor (mplay->window->window, cursor); + mplay->x = root_x - client_x; mplay->y = root_y - client_y; mplay->width = width; @@ -550,6 +573,8 @@ gst_media_play_set_fullscreen (GstMediaPlay *mplay) gdk_window_move (gdk_window, mplay->x, mplay->y); gtk_widget_set_usize (video_widget, source_width, source_height); + + gdk_window_set_cursor (mplay->window->window, NULL); gtk_signal_disconnect (GTK_OBJECT (mplay->window), mplay->fullscreen_connection_id); diff --git a/gstplay/gstmediaplay.glade b/gstplay/gstmediaplay.glade index 3705547610..a4c90636e1 100644 --- a/gstplay/gstmediaplay.glade +++ b/gstplay/gstmediaplay.glade @@ -428,6 +428,14 @@ stop.xpm False + + + GtkButton + Toolbar:button + button1 + + play.xpm + @@ -513,6 +521,7 @@ Arik Devens <arik@gnome.org> Sun, 06 Aug 2000 15:55:52 GMT GNOME_STOCK_BUTTON_OK + GTK_RELIEF_NORMAL @@ -528,6 +537,7 @@ Arik Devens <arik@gnome.org> Sun, 06 Aug 2000 15:53:48 GMT GNOME_STOCK_BUTTON_CANCEL + GTK_RELIEF_NORMAL diff --git a/gstplay/gstplay.c b/gstplay/gstplay.c index 42071c33f6..22d84cd9cc 100644 --- a/gstplay/gstplay.c +++ b/gstplay/gstplay.c @@ -147,6 +147,7 @@ gst_play_init (GstPlay *play) "sink"); } else { + GST_FLAG_SET (priv->video_element, GST_ELEMENT_THREAD_SUGGESTED); gst_bin_add (GST_BIN (priv->video_element), colorspace); gst_element_connect (colorspace, "src", priv->video_show, "sink"); gst_element_add_ghost_pad (priv->video_element, @@ -178,7 +179,11 @@ gst_play_new () static gboolean gst_play_idle_func (gpointer data) { - return gst_bin_iterate (GST_BIN (data)); + gboolean busy; + + busy = gst_bin_iterate (GST_BIN (data)); + + return busy; } static void diff --git a/gstplay/main.c b/gstplay/main.c index f8a6859b0f..2ed5c7daf8 100644 --- a/gstplay/main.c +++ b/gstplay/main.c @@ -21,7 +21,7 @@ main (int argc, char *argv[]) gst_media_play_start_uri (play, argv[1]); for (i=1;i -#include - #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ @@ -34,6 +31,8 @@ extern "C" { #include +void gst_control_init (int *argc, char **argv[]); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/libs/control/gstdparam.c b/libs/control/gstdparam.c index 665b66d2a8..44cceff6dc 100644 --- a/libs/control/gstdparam.c +++ b/libs/control/gstdparam.c @@ -28,6 +28,7 @@ static void gst_dparam_class_init (GstDParamClass *klass); static void gst_dparam_init (GstDParam *dparam); +static void gst_dparam_dispose (GObject *object); static void gst_dparam_do_update_realtime (GstDParam *dparam, gint64 timestamp); static GValue** gst_dparam_get_point_realtime (GstDParam *dparam, gint64 timestamp); @@ -63,7 +64,8 @@ gst_dparam_class_init (GstDParamClass *klass) gobject_class = (GObjectClass*)klass; dparam_class = (GstDParamClass*)klass; gstobject_class = (GstObjectClass*) klass; - + + gobject_class->dispose = gst_dparam_dispose; //gstobject_class->save_thyself = gst_dparam_save_thyself; } @@ -101,23 +103,42 @@ gst_dparam_new (GType type) return dparam; } +static void +gst_dparam_dispose (GObject *object) +{ + GstDParam *dparam = GST_DPARAM(object); + GValue **point = dparam->point; + guint i = 0; + gchar *dparam_name = g_strdup(GST_DPARAM_NAME(dparam)); + + g_print("disposing of %s\n", dparam_name); + if (GST_DPARAM_MANAGER(dparam)){ + gst_dpman_detach_dparam(GST_DPARAM_MANAGER(dparam), dparam_name); + } + point = dparam->point; + while (point[i]){ + g_value_unset(point[i]); + g_free(point[i]); + i++; + } + g_free(dparam_name); + +} + /** * gst_dparam_attach * @dparam: GstDParam instance - * @parent: the GstDParamManager that this dparam belongs to + * @manager: the GstDParamManager that this dparam belongs to * */ void -gst_dparam_attach (GstDParam *dparam, GstObject *parent, GValue *value, GstDParamSpec *spec) +gst_dparam_attach (GstDParam *dparam, GstDParamManager *manager, GValue *value, GstDParamSpec *spec) { g_return_if_fail (dparam != NULL); g_return_if_fail (GST_IS_DPARAM (dparam)); - g_return_if_fail (GST_DPARAM_PARENT (dparam) == NULL); - g_return_if_fail (parent != NULL); - g_return_if_fail (G_IS_OBJECT (parent)); - g_return_if_fail (GST_IS_DPMAN (parent)); - g_return_if_fail ((gpointer)dparam != (gpointer)parent); + g_return_if_fail (manager != NULL); + g_return_if_fail (GST_IS_DPMAN (manager)); g_return_if_fail (value != NULL); g_return_if_fail (spec != NULL); g_return_if_fail (GST_DPARAM_TYPE(dparam) == G_VALUE_TYPE(value)); @@ -125,7 +146,26 @@ gst_dparam_attach (GstDParam *dparam, GstObject *parent, GValue *value, GstDPara GST_DPARAM_NAME(dparam) = spec->dparam_name; GST_DPARAM_VALUE(dparam) = value; GST_DPARAM_SPEC(dparam) = spec; - gst_object_set_parent (GST_OBJECT (dparam), parent); + GST_DPARAM_MANAGER(dparam) = manager; +} + +/** + * gst_dparam_detach + * @dparam: GstDParam instance + * @manager: the GstDParamManager that this dparam belongs to + * + */ +void +gst_dparam_detach (GstDParam *dparam) +{ + + g_return_if_fail (dparam != NULL); + g_return_if_fail (GST_IS_DPARAM (dparam)); + + GST_DPARAM_NAME(dparam) = NULL; + GST_DPARAM_VALUE(dparam) = NULL; + GST_DPARAM_SPEC(dparam) = NULL; + GST_DPARAM_MANAGER(dparam) = NULL; } /** diff --git a/libs/control/gstdparam.h b/libs/control/gstdparam.h index 72d5fad3a9..1b3131af66 100644 --- a/libs/control/gstdparam.h +++ b/libs/control/gstdparam.h @@ -24,12 +24,12 @@ #include #include +#include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ - #define GST_TYPE_DPARAM (gst_dparam_get_type ()) #define GST_DPARAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DPARAM,GstDParam)) #define GST_DPARAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DPARAM,GstDParam)) @@ -40,6 +40,7 @@ extern "C" { #define GST_DPARAM_PARENT(dparam) (GST_OBJECT_PARENT(dparam)) #define GST_DPARAM_VALUE(dparam) ((dparam)->value) #define GST_DPARAM_SPEC(dparam) ((dparam)->spec) +#define GST_DPARAM_MANAGER(dparam) ((dparam)->manager) #define GST_DPARAM_TYPE(dparam) ((dparam)->type) #define GST_DPARAM_LOCK(dparam) (g_mutex_lock((dparam)->lock)) @@ -78,9 +79,7 @@ typedef enum { GST_DPARAM_FOUND_CLOSEST, } GstDParamSearchResult; -typedef struct _GstDParam GstDParam; typedef struct _GstDParamClass GstDParamClass; -typedef struct _GstDParamSpec GstDParamSpec; typedef GValue** (*GstDParamInsertPointFunction) (GstDParam *dparam, guint64 timestamp); typedef void (*GstDParamRemovePointFunction) (GstDParam *dparam, GValue** point); @@ -102,6 +101,7 @@ struct _GstDParam { GMutex *lock; GValue *value; + GstDParamManager *manager; GstDParamSpec *spec; GValue **point; GType type; @@ -129,7 +129,8 @@ struct _GstDParamSpec { GType gst_dparam_get_type (void); GstDParam* gst_dparam_new (GType type); -void gst_dparam_attach (GstDParam *dparam, GstObject *parent, GValue *value, GstDParamSpec *spec); +void gst_dparam_attach (GstDParam *dparam, GstDParamManager *manager, GValue *value, GstDParamSpec *spec); +void gst_dparam_detach (GstDParam *dparam); GValue** gst_dparam_new_value_array(GType type, ...); void gst_dparam_set_value_from_string(GValue *value, const gchar *value_str); diff --git a/libs/control/gstdparammanager.c b/libs/control/gstdparammanager.c index efba3735a2..de03640a5a 100644 --- a/libs/control/gstdparammanager.c +++ b/libs/control/gstdparammanager.c @@ -27,6 +27,7 @@ static GHashTable *_element_registry; static void gst_dpman_class_init (GstDParamManagerClass *klass); static void gst_dpman_init (GstDParamManager *dpman); +static void gst_dpman_dispose (GObject *object); static GstDParamWrapper* gst_dpman_new_wrapper(GstDParamManager *dpman, gchar *dparam_name, GType type, GstDPMUpdateMethod update_method); static GstDParamWrapper* gst_dpman_get_wrapper(GstDParamManager *dpman, gchar *dparam_name); static void gst_dpman_state_change (GstElement *element, gint state, GstDParamManager *dpman); @@ -35,6 +36,12 @@ static guint gst_dpman_preprocess_synchronous(GstDParamManager *dpman, guint fra static guint gst_dpman_preprocess_noop(GstDParamManager *dpman, guint frames, gint64 timestamp); static guint gst_dpman_process_noop(GstDParamManager *dpman, guint frame_count); +void +_gst_dpman_initialize() +{ + _element_registry = g_hash_table_new(NULL,NULL); +} + GType gst_dpman_get_type (void) { @@ -65,9 +72,9 @@ gst_dpman_class_init (GstDParamManagerClass *klass) gstobject_class = (GstObjectClass*) klass; gobject_class = (GObjectClass*) klass; + gobject_class->dispose = gst_dpman_dispose; klass->modes = g_hash_table_new(g_str_hash,g_str_equal); - _element_registry = g_hash_table_new(NULL,NULL); gst_dpman_register_mode (klass, "synchronous", gst_dpman_preprocess_synchronous, gst_dpman_process_noop, NULL, NULL); @@ -114,6 +121,15 @@ gst_dpman_new (gchar *name, GstElement *parent) return dpman; } + +static void +gst_dpman_dispose (GObject *object) +{ + GstDParamManager *dpman = GST_DPMAN(object); + + +} + /** * gst_dpman_add_required_dparam_callback: * @dpman: GstDParamManager instance @@ -268,19 +284,19 @@ gst_dpman_attach_dparam (GstDParamManager *dpman, gchar *dparam_name, GstDParam g_return_val_if_fail(dpwrap->value != NULL, FALSE); dpwrap->dparam = dparam; - gst_dparam_attach(dparam, GST_OBJECT(dpman), dpwrap->value, dpwrap->spec); + gst_dparam_attach(dparam, dpman, dpwrap->value, dpwrap->spec); return TRUE; } /** - * gst_dpman_dettach_dparam: + * gst_dpman_detach_dparam: * @dpman: GstDParamManager instance * @dparam_name: the name of a parameter with a previously attached GstDParam * */ void -gst_dpman_dettach_dparam (GstDParamManager *dpman, gchar *dparam_name) +gst_dpman_detach_dparam (GstDParamManager *dpman, gchar *dparam_name) { GstDParamWrapper* dpwrap; @@ -292,10 +308,7 @@ gst_dpman_dettach_dparam (GstDParamManager *dpman, gchar *dparam_name) g_return_if_fail(dpwrap); - GST_DPARAM_VALUE(dpwrap->dparam) = NULL; - GST_DPARAM_NAME(dpwrap->dparam) = NULL; - gst_object_unparent (GST_OBJECT(dpwrap->dparam)); - + gst_dparam_detach(dpwrap->dparam); dpwrap->dparam = NULL; } @@ -442,6 +455,12 @@ gst_dpman_set_mode(GstDParamManager *dpman, gchar *modename) mode = g_hash_table_lookup(oclass->modes, modename); g_return_val_if_fail (mode != NULL, FALSE); + + if (GST_DPMAN_MODE(dpman) == mode) { + GST_DEBUG(GST_CAT_PARAMS, "mode %s already set\n", modename); + return TRUE; + } + GST_DEBUG(GST_CAT_PARAMS, "setting mode to %s\n", modename); if (GST_DPMAN_MODE(dpman) && GST_DPMAN_TEARDOWNFUNC(dpman)){ GST_DPMAN_TEARDOWNFUNC(dpman)(dpman); @@ -491,7 +510,6 @@ gst_dpman_get_manager (GstElement *parent) g_return_val_if_fail (GST_IS_ELEMENT (parent), NULL); dpman = (GstDParamManager*)g_hash_table_lookup(_element_registry, parent); - g_return_val_if_fail (dpman != NULL, NULL); return dpman; } diff --git a/libs/control/gstdparammanager.h b/libs/control/gstdparammanager.h index e8799e6313..59171ac906 100644 --- a/libs/control/gstdparammanager.h +++ b/libs/control/gstdparammanager.h @@ -24,6 +24,7 @@ #include #include +#include #include #ifdef __cplusplus @@ -52,7 +53,6 @@ typedef enum { GST_DPMAN_ARRAY, } GstDPMUpdateMethod; -typedef struct _GstDParamManager GstDParamManager; typedef struct _GstDParamManagerClass GstDParamManagerClass; typedef struct _GstDPMMode GstDPMMode; typedef struct _GstDParamWrapper GstDParamWrapper; @@ -118,6 +118,7 @@ struct _GstDParamWrapper { #define GST_DPMAN_DO_UPDATE(dpwrap) ((dpwrap->update_func)(dpwrap->value, dpwrap->update_data)) +void _gst_dpman_initialize(); GType gst_dpman_get_type (void); GstDParamManager* gst_dpman_new (gchar *name, GstElement *parent); void gst_dpman_set_parent (GstDParamManager *dpman, GstElement *parent); @@ -138,7 +139,7 @@ gboolean gst_dpman_add_required_dparam_array (GstDParamManager *dpman, gpointer update_data); void gst_dpman_remove_required_dparam (GstDParamManager *dpman, gchar *dparam_name); gboolean gst_dpman_attach_dparam (GstDParamManager *dpman, gchar *dparam_name, GstDParam *dparam); -void gst_dpman_dettach_dparam (GstDParamManager *dpman, gchar *dparam_name); +void gst_dpman_detach_dparam (GstDParamManager *dpman, gchar *dparam_name); GstDParam* gst_dpman_get_dparam(GstDParamManager *dpman, gchar *name); GType gst_dpman_get_dparam_type (GstDParamManager *dpman, gchar *name); diff --git a/libs/resample/Makefile.am b/libs/resample/Makefile.am index b4f88d1aa8..f4b33d909b 100644 --- a/libs/resample/Makefile.am +++ b/libs/resample/Makefile.am @@ -27,4 +27,3 @@ endif libresample_la_LIBADD = $(GST_LIBS) libresample_la_CFLAGS = $(GST_CFLAGS) -ffast-math $(ARCHCFLAGS) - diff --git a/plugins/elements/gstfakesink.c b/plugins/elements/gstfakesink.c index 02eb921fa3..69b8740525 100644 --- a/plugins/elements/gstfakesink.c +++ b/plugins/elements/gstfakesink.c @@ -213,14 +213,6 @@ gst_fakesink_get_property (GObject *object, guint prop_id, GValue *value, GParam } } -/** - * gst_fakesink_chain: - * @pad: the pad this faksink is connected to - * @buffer: the buffer or event that has to be absorbed - * - * Take the buffer or event from the pad and unref it without doing - * anything with it. - */ static void gst_fakesink_chain (GstPad *pad, GstBuffer *buf) { @@ -232,21 +224,12 @@ gst_fakesink_chain (GstPad *pad, GstBuffer *buf) fakesink = GST_FAKESINK (gst_pad_get_parent (pad)); - if (GST_IS_EVENT(buf)) { - GstEvent *event = GST_EVENT (buf); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_EOS: - g_print("fakesink: have EOS event!\n"); - gst_element_set_state (GST_ELEMENT (fakesink), GST_STATE_PAUSED); - break; - default: - g_print("fakesink: have unhandled event!\n"); - break; - } - gst_event_free (event); + /* + if (GST_IS_EVENT (buf)) { + gst_pad_event_default (pad, GST_EVENT (buf)); return; } + */ if (!fakesink->silent) g_print("fakesink: chain ******* (%s:%s)< (%d bytes, %lld) %p\n", diff --git a/plugins/elements/gstqueue.c b/plugins/elements/gstqueue.c index f78792d69a..cdad2e7aaf 100644 --- a/plugins/elements/gstqueue.c +++ b/plugins/elements/gstqueue.c @@ -265,6 +265,7 @@ gst_queue_chain (GstPad *pad, GstBuffer *buf) reader = FALSE; +restart: /* we have to lock the queue since we span threads */ GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "locking t:%ld\n", pthread_self ()); g_mutex_lock (queue->qlock); @@ -277,6 +278,8 @@ gst_queue_chain (GstPad *pad, GstBuffer *buf) gst_queue_locked_flush (queue); break; case GST_EVENT_EOS: + GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "eos in on %s %d\n", + GST_ELEMENT_NAME (queue), queue->level_buffers); break; default: gst_pad_event_default (pad, GST_EVENT (buf)); @@ -327,19 +330,13 @@ gst_queue_chain (GstPad *pad, GstBuffer *buf) while (queue->level_buffers == queue->size_buffers) { // if there's a pending state change for this queue or its manager, switch // back to iterator so bottom half of state change executes - if (GST_STATE_PENDING(queue) != GST_STATE_VOID_PENDING || -// GST_STATE_PENDING(GST_SCHEDULE(GST_ELEMENT(queue)->sched)->parent) != GST_STATE_VOID_PENDING) -GST_STATE_PENDING(GST_SCHED_PARENT(GST_ELEMENT_SCHED(GST_PAD_PARENT(GST_PAD_PEER(queue->sinkpad))))) != -GST_STATE_VOID_PENDING) - { + while (GST_STATE (queue) != GST_STATE_PLAYING) { GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "interrupted!!\n"); - if (GST_STATE_PENDING(queue) != GST_STATE_VOID_PENDING) - GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "GST_STATE_PENDING(queue) != GST_STATE_VOID_PENDING)\n"); - if (GST_STATE_PENDING(GST_SCHEDULE(GST_ELEMENT(queue)->sched)->parent) != GST_STATE_VOID_PENDING) - GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "GST_STATE_PENDING(GST_SCHEDULE(GST_ELEMENT(queue)->sched)->parent) != GST_STATE_VOID_PENDING\n"); g_mutex_unlock (queue->qlock); cothread_switch(cothread_current_main()); + goto restart; } + g_assert (GST_STATE (queue) == GST_STATE_PLAYING); GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "waiting for not_full, level:%d/%d\n", queue->level_buffers, queue->size_buffers); if (queue->writer) @@ -390,6 +387,7 @@ gst_queue_get (GstPad *pad) writer = FALSE; +restart: /* have to lock for thread-safety */ GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "locking t:%ld\n", pthread_self ()); g_mutex_lock (queue->qlock); @@ -399,19 +397,13 @@ gst_queue_get (GstPad *pad) while (queue->level_buffers == 0) { // if there's a pending state change for this queue or its manager, switch // back to iterator so bottom half of state change executes - if (GST_STATE_PENDING(queue) != GST_STATE_VOID_PENDING || -// GST_STATE_PENDING(GST_SCHEDULE(GST_ELEMENT(queue)->sched)->parent) != GST_STATE_VOID_PENDING) -GST_STATE_PENDING(GST_SCHED_PARENT(GST_ELEMENT_SCHED(GST_PAD_PARENT(GST_PAD_PEER(queue->srcpad))))) != -GST_STATE_VOID_PENDING) - { + while (GST_STATE (queue) != GST_STATE_PLAYING) { GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "interrupted!!\n"); - if (GST_STATE_PENDING(queue) != GST_STATE_VOID_PENDING) - GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "GST_STATE_PENDING(queue) != GST_STATE_VOID_PENDING)\n"); - if (GST_STATE_PENDING(GST_SCHEDULE(GST_ELEMENT(queue)->sched)->parent) != GST_STATE_VOID_PENDING) - GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "GST_STATE_PENDING(GST_SCHEDULE(GST_ELEMENT(queue)->sched)->parent) != GST_STATE_VOID_PENDING\n"); g_mutex_unlock (queue->qlock); cothread_switch(cothread_current_main()); + goto restart; } + g_assert (GST_STATE (queue) == GST_STATE_PLAYING); GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "waiting for not_empty, level:%d/%d\n", queue->level_buffers, queue->size_buffers); if (queue->reader) @@ -451,7 +443,7 @@ GST_STATE_VOID_PENDING) GstEvent *event = GST_EVENT(buf); switch (GST_EVENT_TYPE(event)) { case GST_EVENT_EOS: - GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "queue eos\n"); + GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "queue \"%s\" eos\n", GST_ELEMENT_NAME (queue)); gst_element_set_state (GST_ELEMENT (queue), GST_STATE_PAUSED); break; default: @@ -467,56 +459,41 @@ gst_queue_change_state (GstElement *element) { GstQueue *queue; GstElementStateReturn ret; + GstElementState new_state; g_return_val_if_fail (GST_IS_QUEUE (element), GST_STATE_FAILURE); queue = GST_QUEUE (element); + GST_DEBUG_ENTER("('%s')", GST_ELEMENT_NAME (element)); + // lock the queue so another thread (not in sync with this thread's state) // can't call this queue's _get (or whatever) - GST_LOCK (queue); + g_mutex_lock (queue->qlock); - /* if going down into NULL state, clear out buffers*/ - if (GST_STATE_PENDING (element) == GST_STATE_READY) { - /* otherwise (READY or higher) we need to open the file */ - gst_queue_flush (queue); + new_state = GST_STATE_PENDING (element); + + if (new_state == GST_STATE_PAUSED) { + g_cond_signal (queue->not_full); + g_cond_signal (queue->not_empty); + } + else if (new_state == GST_STATE_READY) { + gst_queue_locked_flush (queue); + } + else if (new_state == GST_STATE_PLAYING) { + if (!GST_PAD_CONNECTED (queue->sinkpad)) { + // FIXME can this be? + if (queue->reader) + g_cond_signal (queue->not_empty); + g_mutex_unlock (queue->qlock); + + return GST_STATE_FAILURE; + } } - // if we haven't failed already, give the parent class a chance to ;-) - if (GST_ELEMENT_CLASS (parent_class)->change_state) - { - gboolean valid_handler = FALSE; - guint state_change_id = g_signal_lookup("state_change", G_OBJECT_TYPE(element)); - - // determine whether we need to block the parent (element) class' - // STATE_CHANGE signal so we can UNLOCK before returning. we block - // it if we could find the state_change signal AND there's a signal - // handler attached to it. - // - // note: this assumes that change_state() *only* emits state_change signal. - // if element change_state() emits other signals, they need to be blocked - // as well. - if (state_change_id && - g_signal_has_handler_pending(G_OBJECT(element), state_change_id, 0, FALSE)) - valid_handler = TRUE; - if (valid_handler) - g_signal_handler_block(G_OBJECT(element), state_change_id); - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element); - - if (valid_handler) - g_signal_handler_unblock(G_OBJECT(element), state_change_id); - - // UNLOCK, *then* emit signal (if there's one there) - GST_UNLOCK(queue); - if (valid_handler) - g_signal_emit(G_OBJECT (element), state_change_id, 0, GST_STATE(element)); - } - else - { - ret = GST_STATE_SUCCESS; - GST_UNLOCK(queue); - } + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element); + g_mutex_unlock (queue->qlock); + GST_DEBUG_LEAVE("('%s')", GST_ELEMENT_NAME (element)); return ret; } diff --git a/test/Makefile.am b/test/Makefile.am index 88ca16a9e9..5f062b4e0a 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -4,7 +4,7 @@ if HAVE_GNOME GNOME_PROGS = spectrum wave mp1parse videotest aviparse \ videotest2 video2mp1 dvshow dv2mp1 \ mpeg2parse2 mpeg2parse3 \ - mp2tomp1v2 main sinesliders testspeed dvdplay + mp2tomp1v2 main sinesliders testspeed dvdplay testpod sinesliders_LDADD = ../libs/control/libgstcontrol.la else GNOME_PROGS = @@ -14,7 +14,7 @@ noinst_PROGRAMS = qtest $(GNOME_PROGS) record mp3 teardown buffer mp3parse \ mp3play ac3parse ac3play dvdcat fake cobin \ vidcapture avi2mpg mp2tomp1 mp1tomp1 pipetest \ vidcapture2 mp2toavi mp3tovorbis xmmstest \ - mp3mad lat + mp3mad lat SUBDIRS = xml bindings events memchunk @@ -24,7 +24,7 @@ ac3play_SOURCES = ac3play.c mem.c noinst_HEADERS = mem.h -LIBS += $(GNOME_LIBS) $(GST_LIBS) -CFLAGS += $(GNOME_CFLAGS) $(GST_CFLAGS) +LIBS = $(GNOME_LIBS) $(GST_LIBS) +CFLAGS = $(GNOME_CFLAGS) $(GST_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) EXTRA_DIST = README diff --git a/test/bindings/Makefile.am b/test/bindings/Makefile.am index 27542ace21..fdc7dc05f8 100644 --- a/test/bindings/Makefile.am +++ b/test/bindings/Makefile.am @@ -1,10 +1,10 @@ noinst_LTLIBRARIES = libcrashtest.la -libcrashtest_la_SOURCES = \ - dummy.c +libcrashtest_la_SOURCES = dummy.c +libcrashtest_la_CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) -noinst_HEADERS = \ - dummy.h +noinst_HEADERS = dummy.h noinst_PROGRAMS = test -test_LDADD = libcrashtest.la +test_LDADD = libcrashtest.la $(GLIB_LIBS) +test_CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/test/events/Makefile.am b/test/events/Makefile.am index f2300be1ac..82d65e2f46 100644 --- a/test/events/Makefile.am +++ b/test/events/Makefile.am @@ -1,4 +1,4 @@ noinst_PROGRAMS = seek -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +LIBS = $(GLIB_LIBS) $(GST_LIBS) +CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/test/memchunk/Makefile.am b/test/memchunk/Makefile.am index e3198c289e..fdc2c40925 100644 --- a/test/memchunk/Makefile.am +++ b/test/memchunk/Makefile.am @@ -3,5 +3,5 @@ noinst_PROGRAMS = gmemchunktest gstmemchunktest gmemchunktest_SOURCES = gmemchunktest.c gstmemchunktest_SOURCES = gstmemchunktest.c gstmemchunk.c gstmemchunk.h -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +LIBS = $(GST_LIBS) +CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/test/mpeg2parse2.c b/test/mpeg2parse2.c index 29f2d98d39..ae66fdf924 100644 --- a/test/mpeg2parse2.c +++ b/test/mpeg2parse2.c @@ -14,7 +14,7 @@ gboolean idle_func(gpointer data) { return TRUE; } -void mpeg2parse_newpad(GstElement *parser,GstPad *pad, GstElement *pipeline) { +void mpegdemux_newpad(GstElement *parser,GstPad *pad, GstElement *pipeline) { g_print("***** a new pad %s was created %p\n", gst_pad_get_name(pad), pipeline); gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PAUSED); @@ -57,7 +57,7 @@ int main(int argc,char *argv[]) { } g_print("should be using file '%s'\n",argv[1]); - parse = gst_elementfactory_make("mpeg2parse","parse"); + parse = gst_elementfactory_make("mpegdemux","parse"); //parse = gst_elementfactory_make("mpeg1parse","parse"); g_return_val_if_fail(parse != NULL, -1); @@ -106,7 +106,7 @@ int main(int argc,char *argv[]) { gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(thread)); - gtk_signal_connect(GTK_OBJECT(parse),"new_pad",mpeg2parse_newpad, pipeline); + gtk_signal_connect(GTK_OBJECT(parse),"new_pad",mpegdemux_newpad, pipeline); gtk_signal_connect(GTK_OBJECT(src),"eos",GTK_SIGNAL_FUNC(eof),NULL); diff --git a/test/mpeg2parse3.c b/test/mpeg2parse3.c index 75bf72736e..88d4f84d92 100644 --- a/test/mpeg2parse3.c +++ b/test/mpeg2parse3.c @@ -12,11 +12,10 @@ void eof(GstElement *src) { } gboolean idle_func(gpointer data) { - gst_bin_iterate(GST_BIN(data)); - return TRUE; + return gst_bin_iterate(GST_BIN(data)); } -void mpeg2parse_newpad(GstElement *parser,GstPad *pad, GstElement *pipeline) { +void mpegdemux_newpad(GstElement *parser,GstPad *pad, GstElement *pipeline) { g_print("***** a new pad %s was created\n", gst_pad_get_name(pad)); @@ -31,7 +30,7 @@ void mpeg2parse_newpad(GstElement *parser,GstPad *pad, GstElement *pipeline) { } } -void mpeg2parse_have_size(GstElement *videosink,gint width,gint height) { +void mpegdemux_have_size(GstElement *videosink,gint width,gint height) { gtk_widget_set_usize(gtk_socket,width,height); gtk_widget_show_all(appwindow); } @@ -54,7 +53,7 @@ int main(int argc,char *argv[]) { src = gst_elementfactory_make("dvdsrc","src"); g_print("using DVD source\n"); } else { - src = gst_elementfactory_make("disksrc","src"); + src = gst_elementfactory_make("filesrc","src"); } g_return_val_if_fail(src != NULL, -1); @@ -65,7 +64,7 @@ int main(int argc,char *argv[]) { } g_print("should be using file '%s'\n",argv[1]); - parse = gst_elementfactory_make("mpeg2parse","parse"); + parse = gst_elementfactory_make("mpegdemux","parse"); //parse = gst_elementfactory_make("mpeg1parse","parse"); g_return_val_if_fail(parse != NULL, -1); @@ -135,9 +134,9 @@ int main(int argc,char *argv[]) { gtk_socket_steal (GTK_SOCKET (gtk_socket), gst_util_get_int_arg (GTK_OBJECT(show), "xid")); - gtk_signal_connect(GTK_OBJECT(parse),"new_pad",mpeg2parse_newpad, pipeline); + gtk_signal_connect(GTK_OBJECT(parse),"new_pad",mpegdemux_newpad, pipeline); gtk_signal_connect(GTK_OBJECT(src),"eos",GTK_SIGNAL_FUNC(eof),NULL); - gtk_signal_connect(GTK_OBJECT(show),"have_size",mpeg2parse_have_size, pipeline); + gtk_signal_connect(GTK_OBJECT(show),"have_size",mpegdemux_have_size, pipeline); g_print("setting to PLAYING state\n"); gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PLAYING); diff --git a/test/sinesliders.c b/test/sinesliders.c index aaab8bbb60..edec550e58 100644 --- a/test/sinesliders.c +++ b/test/sinesliders.c @@ -9,11 +9,6 @@ static gint quit_live(GtkWidget *window, GdkEventAny *e, gpointer data) { return FALSE; } -//static void volume_changed(GtkAdjustment *adj,GstElement *element) { - //fprintf(stderr,"setting volume to %f\n",adj->value); -// gtk_object_set(GTK_OBJECT(element),"volume",adj->value,NULL); -//} - static void dynparm_log_value_changed(GtkAdjustment *adj,GstDParam *dparam) { GValue **point; g_return_if_fail(dparam != NULL); @@ -61,6 +56,7 @@ int main(int argc,char *argv[]) { gtk_init(&argc,&argv); gst_init(&argc,&argv); + gst_control_init(&argc,&argv); /***** construct the pipeline *****/ diff --git a/test/xml/Makefile.am b/test/xml/Makefile.am index 045355ec2e..2f9ac71747 100644 --- a/test/xml/Makefile.am +++ b/test/xml/Makefile.am @@ -1,5 +1,6 @@ noinst_PROGRAMS = readreg createreg LDADD = $(GST_LIBS) +CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) EXTRA_DIST = README diff --git a/tests/Makefile.am b/tests/Makefile.am index 43ac3402a0..9eeeb6f223 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -13,7 +13,7 @@ incsched reaping threadlock mp1vid reconnect \ faketest events timecache # we have nothing but apps here, we can do this safely -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +LIBS = $(GST_LIBS) +CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) EXTRA_DIST = README diff --git a/tests/eos/Makefile.am b/tests/eos/Makefile.am index 55839b9e5a..aa55a8fcd5 100644 --- a/tests/eos/Makefile.am +++ b/tests/eos/Makefile.am @@ -1,5 +1,5 @@ noinst_PROGRAMS = case1 case2 case3 case4 case5 case6 case7 # jsut apps here, this is safe -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +LIBS = $(GST_LIBS) +CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/tests/incsched.c b/tests/incsched.c index 1e63534ad3..edb73f88a4 100644 --- a/tests/incsched.c +++ b/tests/incsched.c @@ -19,108 +19,108 @@ int main(int argc,char *argv[]) { g_print("\nAdding src to thread:\n"); gst_bin_add(thread,src); - gst_schedule_show(GST_ELEMENT_SCHED(thread)); + gst_scheduler_show(GST_ELEMENT_SCHED(thread)); g_print("\nAdding identity to thread:\n"); gst_bin_add(thread,identity); - gst_schedule_show(GST_ELEMENT_SCHED(thread)); + gst_scheduler_show(GST_ELEMENT_SCHED(thread)); g_print("\nRemoving identity from thread:\n"); gst_bin_remove(thread, identity); - gst_schedule_show(GST_ELEMENT_SCHED(thread)); + gst_scheduler_show(GST_ELEMENT_SCHED(thread)); g_print("\nAdding identity to thread:\n"); gst_bin_add(thread,identity); - gst_schedule_show(GST_ELEMENT_SCHED(thread)); + gst_scheduler_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)); + gst_scheduler_show(GST_ELEMENT_SCHED(thread)); g_print("\nDisconnecting src from identity:\n"); gst_element_disconnect(src,"src",identity,"sink"); - gst_schedule_show(GST_ELEMENT_SCHED(thread)); + gst_scheduler_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)); + gst_scheduler_show(GST_ELEMENT_SCHED(thread)); g_print("\nAdding sink to bin:\n"); gst_bin_add(bin,sink); - gst_schedule_show(GST_ELEMENT_SCHED(thread)); + gst_scheduler_show(GST_ELEMENT_SCHED(thread)); g_print("\nAdding bin to thread:\n"); gst_bin_add(thread, GST_ELEMENT(bin)); - gst_schedule_show(GST_ELEMENT_SCHED(thread)); + gst_scheduler_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)); + gst_scheduler_show(GST_ELEMENT_SCHED(thread)); g_print("\nDisconnecting sink:\n"); gst_element_disconnect(identity,"src",sink,"sink"); - gst_schedule_show(GST_ELEMENT_SCHED(thread)); + gst_scheduler_show(GST_ELEMENT_SCHED(thread)); g_print("\nAdding identity2 to bin:\n"); gst_bin_add(bin, identity2); - gst_schedule_show(GST_ELEMENT_SCHED(thread)); + gst_scheduler_show(GST_ELEMENT_SCHED(thread)); g_print("\nConnecting identity2 to sink\n"); gst_element_connect(identity2,"src",sink,"sink"); - gst_schedule_show(GST_ELEMENT_SCHED(thread)); + gst_scheduler_show(GST_ELEMENT_SCHED(thread)); g_print("\nConnecting identity to identity2\n"); gst_element_connect(identity,"src",identity2,"sink"); - gst_schedule_show(GST_ELEMENT_SCHED(thread)); + gst_scheduler_show(GST_ELEMENT_SCHED(thread)); g_print("\n\nNow setting state from NULL to READY:\n"); gst_element_set_state(GST_ELEMENT(thread),GST_STATE_READY); - gst_schedule_show(GST_ELEMENT_SCHED(thread)); + gst_scheduler_show(GST_ELEMENT_SCHED(thread)); g_print("\n\nNow setting state from READY to PLAYING:\n"); gst_element_set_state(GST_ELEMENT(thread),GST_STATE_PLAYING); - gst_schedule_show(GST_ELEMENT_SCHED(thread)); + gst_scheduler_show(GST_ELEMENT_SCHED(thread)); g_print("\n\nIterating:\n"); gst_bin_iterate(thread); g_print("\n\nNow setting state from PLAYING to READY:\n"); gst_element_set_state(GST_ELEMENT(thread),GST_STATE_READY); - gst_schedule_show(GST_ELEMENT_SCHED(thread)); + gst_scheduler_show(GST_ELEMENT_SCHED(thread)); g_print("\n\nNow setting state from READY to PLAYING:\n"); gst_element_set_state(GST_ELEMENT(thread),GST_STATE_PLAYING); - gst_schedule_show(GST_ELEMENT_SCHED(thread)); + gst_scheduler_show(GST_ELEMENT_SCHED(thread)); g_print("\n\nIterating:\n"); gst_bin_iterate(thread); g_print("\n\nNow setting state from PLAYING to READY:\n"); gst_element_set_state(GST_ELEMENT(thread),GST_STATE_READY); - gst_schedule_show(GST_ELEMENT_SCHED(thread)); + gst_scheduler_show(GST_ELEMENT_SCHED(thread)); g_print("\nDisconnecting identity from identity2:\n"); gst_element_disconnect(identity,"src",identity2,"sink"); - gst_schedule_show(GST_ELEMENT_SCHED(thread)); + gst_scheduler_show(GST_ELEMENT_SCHED(thread)); g_print("\nDisconnecting identity2 from sink:\n"); gst_element_disconnect(identity2,"src",sink,"sink"); - gst_schedule_show(GST_ELEMENT_SCHED(thread)); + gst_scheduler_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)); + gst_scheduler_show(GST_ELEMENT_SCHED(thread)); g_print("\n\nNow setting identity2 to NULL:\n"); gst_element_set_state(identity2,GST_STATE_NULL); g_print("\nRemoving identity2 from bin:\n"); gst_bin_remove(bin, identity2); - gst_schedule_show(GST_ELEMENT_SCHED(thread)); + gst_scheduler_show(GST_ELEMENT_SCHED(thread)); g_print("\n\nNow setting state from READY to PLAYING:\n"); gst_element_set_state(GST_ELEMENT(thread),GST_STATE_PLAYING); - gst_schedule_show(GST_ELEMENT_SCHED(thread)); + gst_scheduler_show(GST_ELEMENT_SCHED(thread)); g_print("\n\nIterating:\n"); gst_bin_iterate(thread); diff --git a/tests/mp1vid.c b/tests/mp1vid.c index 678f2f31f9..c502b1bc29 100644 --- a/tests/mp1vid.c +++ b/tests/mp1vid.c @@ -59,7 +59,7 @@ int main(int argc,char *argv[]) { gst_bin_add(GST_BIN(pipeline),sourcethread); - gst_schedule_show(GST_ELEMENT_SCHED(pipeline)); + gst_scheduler_show(GST_ELEMENT_SCHED(pipeline)); gst_element_set_state(pipeline,GST_STATE_PLAYING); sleep(1); diff --git a/tests/muxing/Makefile.am b/tests/muxing/Makefile.am index 5b25390e24..447ed2f940 100644 --- a/tests/muxing/Makefile.am +++ b/tests/muxing/Makefile.am @@ -1,5 +1,5 @@ noinst_PROGRAMS = case1 # jsut apps here, this is safe -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +LIBS = $(GST_LIBS) +CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/tests/nego/Makefile.am b/tests/nego/Makefile.am index 4260472389..7e47fff9b6 100644 --- a/tests/nego/Makefile.am +++ b/tests/nego/Makefile.am @@ -1,5 +1,5 @@ noinst_PROGRAMS = nego1 # jsut apps here, this is safe -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +LIBS = $(GST_LIBS) +CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/tests/old/examples/autoplug/Makefile.am b/tests/old/examples/autoplug/Makefile.am index f263f27100..8f8cdd4153 100644 --- a/tests/old/examples/autoplug/Makefile.am +++ b/tests/old/examples/autoplug/Makefile.am @@ -1,5 +1,5 @@ noinst_PROGRAMS = autoplug # just an app here, we're safe -LIBS += $(GNOME_LIBS) $(GST_LIBS) -CFLAGS += $(GNOME_CFLAGS) $(GST_CFLAGS) +autoplug_LDADD = $(GNOME_LIBS) $(GST_LIBS) $(GLIB_LIBS) +autoplug_CFLAGS = $(GNOME_CFLAGS) $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/tests/old/examples/cutter/Makefile.am b/tests/old/examples/cutter/Makefile.am index c1fca3f985..29da841f05 100644 --- a/tests/old/examples/cutter/Makefile.am +++ b/tests/old/examples/cutter/Makefile.am @@ -1,5 +1,5 @@ noinst_PROGRAMS = cutter noinst_HEADERS = cutter.h -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +cutter_LDADD = $(GST_LIBS) +cutter_CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/tests/old/examples/helloworld/Makefile.am b/tests/old/examples/helloworld/Makefile.am index 77e8ef336a..5821f461f2 100644 --- a/tests/old/examples/helloworld/Makefile.am +++ b/tests/old/examples/helloworld/Makefile.am @@ -1,4 +1,4 @@ noinst_PROGRAMS = helloworld -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +helloworld_LDADD = $(GST_LIBS) +helloworld_CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/tests/old/examples/helloworld2/Makefile.am b/tests/old/examples/helloworld2/Makefile.am index 6d686a4092..1daf5c0da1 100644 --- a/tests/old/examples/helloworld2/Makefile.am +++ b/tests/old/examples/helloworld2/Makefile.am @@ -1,5 +1,5 @@ noinst_PROGRAMS = helloworld2 -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +helloworld2_LDADD = $(GST_LIBS) +helloworld2_CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/tests/old/examples/launch/Makefile.am b/tests/old/examples/launch/Makefile.am index 11c2e57cfc..c1d844569c 100644 --- a/tests/old/examples/launch/Makefile.am +++ b/tests/old/examples/launch/Makefile.am @@ -1,8 +1,8 @@ noinst_PROGRAMS = mp3parselaunch # just an app here, we're safe -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +mp3parselaunch_LDADD = $(GST_LIBS) +mp3parselaunch_CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) noinst_SCRIPTS = mp3play EXTRA_DIST = mp3play diff --git a/tests/old/examples/mixer/Makefile.am b/tests/old/examples/mixer/Makefile.am index d15b425208..8d993da8c7 100644 --- a/tests/old/examples/mixer/Makefile.am +++ b/tests/old/examples/mixer/Makefile.am @@ -1,5 +1,5 @@ noinst_PROGRAMS = mixer noinst_HEADERS = mixer.h -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +mixer_LDADD = $(GST_LIBS) +mixer_CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/tests/old/examples/mixer/mixer.c b/tests/old/examples/mixer/mixer.c index 7a02eddcb4..ec492cad34 100644 --- a/tests/old/examples/mixer/mixer.c +++ b/tests/old/examples/mixer/mixer.c @@ -190,7 +190,7 @@ int main(int argc,char *argv[]) gst_element_set_state(main_bin, GST_STATE_PLAYING); // write out the schedule - gst_schedule_show(GST_ELEMENT_SCHED(main_bin)); + gst_scheduler_show(GST_ELEMENT_SCHED(main_bin)); playing = TRUE; j = 0; diff --git a/tests/old/examples/plugins/Makefile.am b/tests/old/examples/plugins/Makefile.am index 5e0b9fca0f..11c631711d 100644 --- a/tests/old/examples/plugins/Makefile.am +++ b/tests/old/examples/plugins/Makefile.am @@ -1,4 +1,5 @@ noinst_LTLIBRARIES = libexample.la libexample_la_SOURCES = example.c +libexample_la_CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) noinst_HEADERS = example.h diff --git a/tests/old/examples/queue/Makefile.am b/tests/old/examples/queue/Makefile.am index e4ef4c7ce8..7b67eeabd6 100644 --- a/tests/old/examples/queue/Makefile.am +++ b/tests/old/examples/queue/Makefile.am @@ -1,5 +1,5 @@ noinst_PROGRAMS = queue -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +queue_LDADD = $(GST_LIBS) +queue_CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/tests/old/examples/queue2/Makefile.am b/tests/old/examples/queue2/Makefile.am index fd4f914bbd..5bd7542f1c 100644 --- a/tests/old/examples/queue2/Makefile.am +++ b/tests/old/examples/queue2/Makefile.am @@ -1,5 +1,5 @@ noinst_PROGRAMS = queue2 -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +queue2_LDADD = $(GST_LIBS) +queue2_CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/tests/old/examples/queue3/Makefile.am b/tests/old/examples/queue3/Makefile.am index be6313ce6d..de2d00faab 100644 --- a/tests/old/examples/queue3/Makefile.am +++ b/tests/old/examples/queue3/Makefile.am @@ -1,5 +1,5 @@ noinst_PROGRAMS = queue3 -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +queue3_LDADD = $(GST_LIBS) +queue3_CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/tests/old/examples/queue4/Makefile.am b/tests/old/examples/queue4/Makefile.am index 0b1a4857b8..8d6e2eec95 100644 --- a/tests/old/examples/queue4/Makefile.am +++ b/tests/old/examples/queue4/Makefile.am @@ -1,5 +1,5 @@ noinst_PROGRAMS = queue4 -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +queue4_LDADD = $(GST_LIBS) +queue4_CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/tests/old/examples/thread/Makefile.am b/tests/old/examples/thread/Makefile.am index 4e019cb731..ae9f9ac759 100644 --- a/tests/old/examples/thread/Makefile.am +++ b/tests/old/examples/thread/Makefile.am @@ -1,5 +1,5 @@ noinst_PROGRAMS = thread -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +thread_LDADD = $(GST_LIBS) +thread_CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/tests/old/examples/typefind/Makefile.am b/tests/old/examples/typefind/Makefile.am index 57669bdcc0..e8a9b4f1c8 100644 --- a/tests/old/examples/typefind/Makefile.am +++ b/tests/old/examples/typefind/Makefile.am @@ -1,5 +1,5 @@ noinst_PROGRAMS = typefind -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +typefind_LDADD = $(GST_LIBS) +typefind_CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/tests/old/examples/xml/Makefile.am b/tests/old/examples/xml/Makefile.am index 24b890fd84..7b8e2f4745 100644 --- a/tests/old/examples/xml/Makefile.am +++ b/tests/old/examples/xml/Makefile.am @@ -1,5 +1,7 @@ noinst_PROGRAMS = createxml runxml -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +createxml_LDADD = $(GST_LIBS) +createxml_CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) +runxml_LDADD = $(GST_LIBS) +runxml_CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/tests/old/testsuite/Makefile.am b/tests/old/testsuite/Makefile.am index 74d5101862..e5d82ee00a 100644 --- a/tests/old/testsuite/Makefile.am +++ b/tests/old/testsuite/Makefile.am @@ -8,8 +8,8 @@ TESTS = $(testprogs) check_PROGRAMS = $(testprogs) # we have nothing but apps here, we can do this safely -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +LIBS = $(GST_LIBS) +CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) DIST_SUBDIRS = refcounting capsnego plugin bytestream diff --git a/tests/old/testsuite/bytestream/Makefile.am b/tests/old/testsuite/bytestream/Makefile.am index 75aeed7915..1f617b231f 100644 --- a/tests/old/testsuite/bytestream/Makefile.am +++ b/tests/old/testsuite/bytestream/Makefile.am @@ -9,5 +9,5 @@ test1_LDFLAGS = -L$(top_builddir)/libs/bytestream/ -lgstbytestream # we have nothing but apps here, we can do this safely -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +LIBS = $(GST_LIBS) +CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/tests/old/testsuite/capsnego/Makefile.am b/tests/old/testsuite/capsnego/Makefile.am index 6b1c466c7c..8dc74bb8c0 100644 --- a/tests/old/testsuite/capsnego/Makefile.am +++ b/tests/old/testsuite/capsnego/Makefile.am @@ -5,5 +5,5 @@ TESTS = $(testprogs) check_PROGRAMS = $(testprogs) # we have nothing but apps here, we can do this safely -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +LIBS = $(GST_LIBS) +CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/tests/old/testsuite/plugin/Makefile.am b/tests/old/testsuite/plugin/Makefile.am index 9acef8767d..4cadb77724 100644 --- a/tests/old/testsuite/plugin/Makefile.am +++ b/tests/old/testsuite/plugin/Makefile.am @@ -16,5 +16,5 @@ TESTS = $(testprogs) check_PROGRAMS = $(testprogs) # we have nothing but apps here, we can do this safely -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +LIBS = $(GST_LIBS) +CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/tests/old/testsuite/refcounting/Makefile.am b/tests/old/testsuite/refcounting/Makefile.am index 06319a7597..3d98225aa8 100644 --- a/tests/old/testsuite/refcounting/Makefile.am +++ b/tests/old/testsuite/refcounting/Makefile.am @@ -16,6 +16,6 @@ EXTRA_DIST = thread.c object.c element.c element_pad.c bin.c noinst_HEADERS = mem.h # we have nothing but apps here, we can do this safely -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +LIBS = $(GST_LIBS) +CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/tests/sched/Makefile.am b/tests/sched/Makefile.am index 2bcb8cee39..8f1fa53d6a 100644 --- a/tests/sched/Makefile.am +++ b/tests/sched/Makefile.am @@ -7,5 +7,5 @@ endif dynamic_pipeline_SOURCES = dynamic-pipeline.c # nothing but apps here, this is safe -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +LIBS = $(GST_LIBS) +CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am index 74d5101862..e5d82ee00a 100644 --- a/testsuite/Makefile.am +++ b/testsuite/Makefile.am @@ -8,8 +8,8 @@ TESTS = $(testprogs) check_PROGRAMS = $(testprogs) # we have nothing but apps here, we can do this safely -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +LIBS = $(GST_LIBS) +CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) DIST_SUBDIRS = refcounting capsnego plugin bytestream diff --git a/testsuite/bytestream/Makefile.am b/testsuite/bytestream/Makefile.am index 75aeed7915..1f617b231f 100644 --- a/testsuite/bytestream/Makefile.am +++ b/testsuite/bytestream/Makefile.am @@ -9,5 +9,5 @@ test1_LDFLAGS = -L$(top_builddir)/libs/bytestream/ -lgstbytestream # we have nothing but apps here, we can do this safely -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +LIBS = $(GST_LIBS) +CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/testsuite/capsnego/Makefile.am b/testsuite/capsnego/Makefile.am index 6b1c466c7c..8dc74bb8c0 100644 --- a/testsuite/capsnego/Makefile.am +++ b/testsuite/capsnego/Makefile.am @@ -5,5 +5,5 @@ TESTS = $(testprogs) check_PROGRAMS = $(testprogs) # we have nothing but apps here, we can do this safely -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +LIBS = $(GST_LIBS) +CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/testsuite/plugin/Makefile.am b/testsuite/plugin/Makefile.am index 9acef8767d..4cadb77724 100644 --- a/testsuite/plugin/Makefile.am +++ b/testsuite/plugin/Makefile.am @@ -16,5 +16,5 @@ TESTS = $(testprogs) check_PROGRAMS = $(testprogs) # we have nothing but apps here, we can do this safely -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +LIBS = $(GST_LIBS) +CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/testsuite/refcounting/Makefile.am b/testsuite/refcounting/Makefile.am index 06319a7597..3d98225aa8 100644 --- a/testsuite/refcounting/Makefile.am +++ b/testsuite/refcounting/Makefile.am @@ -16,6 +16,6 @@ EXTRA_DIST = thread.c object.c element.c element_pad.c bin.c noinst_HEADERS = mem.h # we have nothing but apps here, we can do this safely -LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +LIBS = $(GST_LIBS) +CFLAGS = $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS) diff --git a/tools/Makefile.am b/tools/Makefile.am index c09859ef75..eb41c9c250 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -30,11 +30,15 @@ man_MANS = gstreamer-launch.1 gstreamer-register.1 gstreamer-inspect.1 \ gstreamer_launch_LDADD = $(GST_LIBS) gstreamer_launch_CFLAGS = $(GST_CFLAGS) -DGST_CONFIG_DIR=\"$(GST_CONFIG_DIR)\" +if !USE_GLIB2 gstreamer_guilaunch_LDADD = $(GST_LIBS) gstreamer_guilaunch_CFLAGS = $(GST_CFLAGS) -DGST_CONFIG_DIR=\"$(GST_CONFIG_DIR)\" +endif +if !GST_DISABLE_REGISTRY gstreamer_register_LDADD = $(GST_LIBS) gstreamer_register_CFLAGS = $(GST_CFLAGS) -DGST_CONFIG_DIR=\"$(GST_CONFIG_DIR)\" +endif gstreamer_inspect_LDADD = $(GST_LIBS) gstreamer_inspect_CFLAGS = $(GST_CFLAGS) -DGST_CONFIG_DIR=\"$(GST_CONFIG_DIR)\" @@ -42,7 +46,9 @@ gstreamer_inspect_CFLAGS = $(GST_CFLAGS) -DGST_CONFIG_DIR=\"$(GST_CONFIG_DIR)\" gstreamer_complete_LDADD = $(GST_LIBS) gstreamer_complete_CFLAGS = $(GST_CFLAGS) -DGST_CONFIG_DIR=\"$(GST_CONFIG_DIR)\" +if !GST_DISABLE_LOADSAVE gstreamer_compprep_LDADD = $(GST_LIBS) gstreamer_compprep_CFLAGS = $(GST_CFLAGS) -DGST_CONFIG_DIR=\"$(GST_CONFIG_DIR)\" +endif EXTRA_DIST = $(man_MANS) diff --git a/tools/gstreamer-inspect.c b/tools/gstreamer-inspect.c index 6ac84be18a..423516a698 100644 --- a/tools/gstreamer-inspect.c +++ b/tools/gstreamer-inspect.c @@ -440,6 +440,12 @@ print_element_list (void) if (factory->typefindfunc) printf(" Has typefind function: %s\n",GST_DEBUG_FUNCPTR_NAME(factory->typefindfunc)); } + else if (GST_IS_SCHEDULERFACTORY (feature)) { + GstSchedulerFactory *factory; + + factory = GST_SCHEDULERFACTORY (feature); + printf("%s: %s: %s\n", plugin->name, GST_OBJECT_NAME (factory), factory->longdesc); + } else { printf("%s: %s (%s)\n", plugin->name, gst_object_get_name (GST_OBJECT (feature)), g_type_name (G_OBJECT_TYPE (feature))); @@ -489,6 +495,12 @@ print_plugin_info (GstPlugin *plugin) if (factory->typefindfunc) printf(" Has typefind function: %s\n",GST_DEBUG_FUNCPTR_NAME(factory->typefindfunc)); } + else if (GST_IS_SCHEDULERFACTORY (feature)) { + GstSchedulerFactory *factory; + + factory = GST_SCHEDULERFACTORY (feature); + printf(" %s: %s\n", GST_OBJECT_NAME (factory), factory->longdesc); + } else { printf(" %s (%s)\n", gst_object_get_name (GST_OBJECT (feature)), g_type_name (G_OBJECT_TYPE (feature))); diff --git a/tools/gstreamer-launch.c b/tools/gstreamer-launch.c index 8e91fc05ce..e50db14cbd 100644 --- a/tools/gstreamer-launch.c +++ b/tools/gstreamer-launch.c @@ -65,6 +65,7 @@ idle_func (gpointer data) #ifndef USE_GLIB2 gtk_main_quit (); #endif + g_print ("iteration ended\n"); return FALSE; } return TRUE;