From 044c4611af813c7049053bf355db79ef8be2f96c Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Sun, 21 Jan 2001 16:06:42 +0000 Subject: [PATCH] More eos handling, bin in bin is handled correctly now. Original commit message from CVS: More eos handling, bin in bin is handled correctly now. Updated gstreamer-launch to loop while !EOS. --- gst/gstbin.c | 78 +++++++++++++++++---------- gst/gstbin.h | 1 + gst/gstelement.c | 2 +- gst/gstthread.c | 96 ++++++++++++++++++--------------- libs/videoscale/gstvideoscale.c | 5 ++ tests/eos/Makefile.am | 2 +- tests/eos/case4.c | 14 ++--- tests/eos/case5.c | 5 +- tools/gstreamer-launch.c | 28 +++++----- 9 files changed, 136 insertions(+), 95 deletions(-) diff --git a/gst/gstbin.c b/gst/gstbin.c index 44347d2ae9..bcd97762c8 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -136,6 +136,7 @@ gst_bin_init (GstBin *bin) bin->eos_providers = NULL; bin->num_eos_providers = 0; bin->chains = NULL; + bin->eoscond = g_cond_new (); // FIXME temporary testing measure // bin->use_cothreads = TRUE; } @@ -250,6 +251,22 @@ gst_bin_change_state (GstElement *element) // g_return_val_if_fail(bin->numchildren != 0, GST_STATE_FAILURE); + switch (GST_STATE_TRANSITION (element)) { + case GST_STATE_NULL_TO_READY: + { + GstObject *parent; + + parent = gst_object_get_parent (GST_OBJECT (element)); + + if (!parent || !GST_IS_BIN (parent)) + gst_bin_create_plan (bin); + + break; + } + default: + break; + } + // g_print("-->\n"); children = bin->children; while (children) { @@ -271,21 +288,6 @@ gst_bin_change_state (GstElement *element) } // g_print("<-- \"%s\"\n",gst_object_get_name(GST_OBJECT(bin))); - switch (GST_STATE_TRANSITION (element)) { - case GST_STATE_NULL_TO_READY: - { - GstObject *parent; - - parent = gst_object_get_parent (GST_OBJECT (element)); - - if (!parent || !GST_IS_BIN (parent)) - gst_bin_create_plan (bin); - - break; - } - default: - break; - } return gst_bin_change_state_norecurse (bin); } @@ -551,9 +553,12 @@ gst_bin_received_eos (GstElement *element, GstBin *bin) GST_INFO_ELEMENT (GST_CAT_PLANNING, bin, "child %s fired eos, pending %d\n", gst_element_get_name (element), bin->num_eos_providers); + GST_LOCK (bin); if (bin->num_eos_providers) { bin->num_eos_providers--; + g_cond_signal (bin->eoscond); } + GST_UNLOCK (bin); } /** @@ -610,6 +615,7 @@ gst_bin_create_plan_func (GstBin *bin) } GST_DEBUG (0,"setting manager to \"%s\"\n", gst_element_get_name (manager)); } + gst_element_set_manager (GST_ELEMENT (bin), manager); // perform the first recursive pass of plan generation // we set the manager of every element but those who manage themselves @@ -635,8 +641,11 @@ gst_bin_create_plan_func (GstBin *bin) // we do recursion and such for Bins if (GST_IS_BIN (element)) { // recurse into the child Bin - GST_DEBUG (0,"recursing into child Bin \"%s\"\n",elementname); + GST_DEBUG (0,"recursing into child Bin \"%s\" with manager \"%s\"\n",elementname, + gst_element_get_name(element->manager)); gst_bin_create_plan (GST_BIN (element)); + GST_DEBUG (0,"after recurse got manager \"%s\"\n", + gst_element_get_name(element->manager)); // check to see if it needs cothreads and isn't self-managing if (((GST_BIN (element))->need_cothreads) && !GST_FLAG_IS_SET(element,GST_BIN_FLAG_MANAGER)) { GST_DEBUG (0,"requiring cothreads because child bin \"%s\" does\n",elementname); @@ -701,10 +710,6 @@ gst_bin_create_plan_func (GstBin *bin) GST_DEBUG (0,"flattened recurse into \"%s\"\n",elementname); pending = g_slist_prepend (pending, element); - gtk_signal_connect (GTK_OBJECT (element), "eos", gst_bin_received_eos, bin); - bin->eos_providers = g_list_prepend (bin->eos_providers, element); - bin->num_eos_providers++; - // otherwise add it to the list of elements } else { GST_DEBUG (0,"found element \"%s\" that I manage\n",elementname); @@ -712,6 +717,12 @@ gst_bin_create_plan_func (GstBin *bin) bin->num_managed_elements++; } } + // else it's not ours and we need to wait for EOS notifications + else { + gtk_signal_connect (GTK_OBJECT (element), "eos", gst_bin_received_eos, bin); + bin->eos_providers = g_list_prepend (bin->eos_providers, element); + bin->num_eos_providers++; + } } } while (pending); @@ -719,6 +730,10 @@ gst_bin_create_plan_func (GstBin *bin) gst_bin_schedule(bin); + g_print ("gstbin \"%s\", eos providers:%d\n", + gst_element_get_name (GST_ELEMENT (bin)), + bin->num_eos_providers); + GST_DEBUG_LEAVE("(\"%s\")",gst_element_get_name(GST_ELEMENT(bin))); } @@ -795,15 +810,20 @@ gst_bin_iterate_func (GstBin *bin) num_scheduled++; } - /* - g_print ("bin \"%s\", eos providers:%d, scheduled: %d\n", - gst_element_get_name (GST_ELEMENT (bin)), - bin->num_eos_providers, num_scheduled); - */ - - if (!num_scheduled && !bin->num_eos_providers) { - gst_element_signal_eos (GST_ELEMENT (bin)); - eos = TRUE; + // 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 (0,"waiting for eos providers\n"); + g_cond_wait (bin->eoscond, GST_OBJECT(bin)->lock); + GST_DEBUG (0,"num eos providers %d\n", bin->num_eos_providers); + GST_UNLOCK (bin); + } + else { + gst_element_signal_eos (GST_ELEMENT (bin)); + eos = TRUE; + } } GST_DEBUG_LEAVE("(%s)", gst_element_get_name (GST_ELEMENT (bin))); diff --git a/gst/gstbin.h b/gst/gstbin.h index 4f238ec8b2..60680881da 100644 --- a/gst/gstbin.h +++ b/gst/gstbin.h @@ -67,6 +67,7 @@ struct _GstBin { GList *children; gint num_eos_providers; GList *eos_providers; + GCond *eoscond; /* iteration state */ gboolean need_cothreads; diff --git a/gst/gstelement.c b/gst/gstelement.c index cd8bdfc985..b864375fa4 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -202,7 +202,7 @@ gst_element_add_ghost_pad (GstElement *element, GstPad *pad, gchar *name) element->pads = g_list_append (element->pads, ghostpad); element->numpads++; // set the parent of the ghostpad - gst_pad_set_parent(ghostpad,element); + gst_pad_set_parent(ghostpad, GST_OBJECT (element)); GST_DEBUG(0,"added ghostpad %s:%s\n",GST_DEBUG_PAD_NAME(ghostpad)); diff --git a/gst/gstthread.c b/gst/gstthread.c index 4f82a3147a..1e80a81563 100644 --- a/gst/gstthread.c +++ b/gst/gstthread.c @@ -34,7 +34,7 @@ GstElementDetails gst_thread_details = { "Container that creates/manages a thread", VERSION, "Erik Walthinsen ", - "(C) 1999", + "(C) 1999, 2000", }; @@ -50,21 +50,22 @@ enum { }; -static void gst_thread_class_init (GstThreadClass *klass); -static void gst_thread_init (GstThread *thread); +static void gst_thread_class_init (GstThreadClass *klass); +static void gst_thread_init (GstThread *thread); -static void gst_thread_set_arg (GtkObject *object,GtkArg *arg,guint id); -static void gst_thread_get_arg (GtkObject *object,GtkArg *arg,guint id); +static void gst_thread_set_arg (GtkObject *object,GtkArg *arg,guint id); +static void gst_thread_get_arg (GtkObject *object,GtkArg *arg,guint id); -static GstElementStateReturn gst_thread_change_state (GstElement *element); +static GstElementStateReturn gst_thread_change_state (GstElement *element); -static xmlNodePtr gst_thread_save_thyself (GstElement *element,xmlNodePtr parent); -static void gst_thread_restore_thyself (GstElement *element,xmlNodePtr parent, +static xmlNodePtr gst_thread_save_thyself (GstElement *element,xmlNodePtr parent); +static void gst_thread_restore_thyself (GstElement *element,xmlNodePtr parent, GHashTable *elements); -static void gst_thread_signal_thread (GstThread *thread); -static void gst_thread_wait_thread (GstThread *thread); -static void gst_thread_create_plan_dummy (GstBin *bin); +static void gst_thread_signal_thread (GstThread *thread); +static void gst_thread_wait_thread (GstThread *thread); +static void gst_thread_create_plan_dummy (GstBin *bin); +static void gst_thread_schedule_dummy (GstBin *bin); static void* gst_thread_main_loop (void *arg); @@ -92,36 +93,37 @@ gst_thread_get_type(void) { } static void -gst_thread_class_init (GstThreadClass *klass) +gst_thread_class_init (GstThreadClass *klass) { GtkObjectClass *gtkobject_class; GstObjectClass *gstobject_class; GstElementClass *gstelement_class; GstBinClass *gstbin_class; - gtkobject_class = (GtkObjectClass*)klass; - gstobject_class = (GstObjectClass*)klass; - gstelement_class = (GstElementClass*)klass; - gstbin_class = (GstBinClass*)klass; + gtkobject_class = (GtkObjectClass*)klass; + gstobject_class = (GstObjectClass*)klass; + gstelement_class = (GstElementClass*)klass; + gstbin_class = (GstBinClass*)klass; parent_class = gtk_type_class (GST_TYPE_BIN); gtk_object_add_arg_type ("GstThread::create_thread", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_CREATE_THREAD); - gstelement_class->change_state = gst_thread_change_state; - gstelement_class->save_thyself = gst_thread_save_thyself; - gstelement_class->restore_thyself = gst_thread_restore_thyself; + gstelement_class->change_state = gst_thread_change_state; + gstelement_class->save_thyself = gst_thread_save_thyself; + gstelement_class->restore_thyself = gst_thread_restore_thyself; - gstbin_class->create_plan = gst_thread_create_plan_dummy; + //gstbin_class->create_plan = gst_thread_create_plan_dummy; + gstbin_class->schedule = gst_thread_schedule_dummy; gtkobject_class->set_arg = gst_thread_set_arg; gtkobject_class->get_arg = gst_thread_get_arg; } -static void -gst_thread_init (GstThread *thread) +static void +gst_thread_init (GstThread *thread) { GST_DEBUG (0,"initializing thread '%s'\n",gst_element_get_name(GST_ELEMENT(thread))); @@ -136,19 +138,28 @@ gst_thread_init (GstThread *thread) thread->cond = g_cond_new(); } -static void -gst_thread_create_plan_dummy (GstBin *bin) +static void +gst_thread_schedule_dummy (GstBin *bin) { g_return_if_fail (GST_IS_THREAD (bin)); - if (!GST_FLAG_IS_SET (GST_THREAD (bin), GST_THREAD_STATE_SPINNING)) + if (!GST_FLAG_IS_SET (GST_THREAD (bin), GST_THREAD_STATE_SPINNING)) + GST_INFO (GST_CAT_THREAD,"gstthread: scheduling delayed until thread starts"); +} + +static void +gst_thread_create_plan_dummy (GstBin *bin) +{ + g_return_if_fail (GST_IS_THREAD (bin)); + + if (!GST_FLAG_IS_SET (GST_THREAD (bin), GST_THREAD_STATE_SPINNING)) GST_INFO (GST_CAT_THREAD,"gstthread: create plan delayed until thread starts"); } -static void +static void gst_thread_set_arg (GtkObject *object, GtkArg *arg, - guint id) + guint id) { /* it's not null if we got it, but it might not be ours */ g_return_if_fail (GST_IS_THREAD (object)); @@ -170,10 +181,10 @@ gst_thread_set_arg (GtkObject *object, } } -static void +static void gst_thread_get_arg (GtkObject *object, GtkArg *arg, - guint id) + guint id) { /* it's not null if we got it, but it might not be ours */ g_return_if_fail (GST_IS_THREAD (object)); @@ -197,15 +208,15 @@ gst_thread_get_arg (GtkObject *object, * Returns: The new thread */ GstElement* -gst_thread_new (guchar *name) +gst_thread_new (guchar *name) { return gst_elementfactory_make ("thread", name); } -static GstElementStateReturn -gst_thread_change_state (GstElement *element) +static GstElementStateReturn +gst_thread_change_state (GstElement *element) { GstThread *thread; gboolean stateset = GST_STATE_SUCCESS; @@ -217,7 +228,7 @@ gst_thread_change_state (GstElement *element) thread = GST_THREAD (element); GST_INFO (GST_CAT_THREAD,"gstthread: thread \"%s\" change state %d", - gst_element_get_name (GST_ELEMENT (element)), + gst_element_get_name (GST_ELEMENT (element)), GST_STATE_PENDING (element)); pending = GST_STATE_PENDING (element); @@ -229,8 +240,8 @@ gst_thread_change_state (GstElement *element) if (GST_ELEMENT_CLASS (parent_class)->change_state) stateset = GST_ELEMENT_CLASS (parent_class)->change_state (element); - - GST_INFO (GST_CAT_THREAD, "gstthread: stateset %d %d %d %02x", GST_STATE (element), stateset, + + GST_INFO (GST_CAT_THREAD, "gstthread: stateset %d %d %d %02x", GST_STATE (element), stateset, GST_STATE_PENDING (element), GST_STATE_TRANSITION (element)); switch (transition) { @@ -268,18 +279,18 @@ gst_thread_change_state (GstElement *element) GST_FLAG_SET (thread, GST_THREAD_STATE_SPINNING); gst_thread_signal_thread (thread); - break; + break; case GST_STATE_PLAYING_TO_PAUSED: GST_INFO (GST_CAT_THREAD,"gstthread: pausing thread \"%s\"", gst_element_get_name (GST_ELEMENT (element))); - + //GST_FLAG_UNSET(thread,GST_THREAD_STATE_SPINNING); gst_thread_signal_thread (thread); break; case GST_STATE_READY_TO_NULL: GST_INFO (GST_CAT_THREAD,"gstthread: stopping thread \"%s\"", gst_element_get_name (GST_ELEMENT (element))); - + GST_FLAG_SET (thread, GST_THREAD_STATE_REAPING); gst_thread_signal_thread (thread); break; @@ -298,7 +309,7 @@ gst_thread_change_state (GstElement *element) * while the state is GST_THREAD_STATE_SPINNING */ static void * -gst_thread_main_loop (void *arg) +gst_thread_main_loop (void *arg) { GstThread *thread = GST_THREAD (arg); @@ -306,8 +317,9 @@ gst_thread_main_loop (void *arg) gst_element_get_name (GST_ELEMENT (thread)), getpid ()); // construct the plan and signal back - if (GST_BIN_CLASS (parent_class)->create_plan) - GST_BIN_CLASS (parent_class)->create_plan (GST_BIN (thread)); + if (GST_BIN_CLASS (parent_class)->schedule) + GST_BIN_CLASS (parent_class)->schedule (GST_BIN (thread)); + gst_thread_signal_thread (thread); while (!GST_FLAG_IS_SET (thread, GST_THREAD_STATE_REAPING)) { @@ -323,7 +335,7 @@ gst_thread_main_loop (void *arg) } GST_FLAG_UNSET (thread, GST_THREAD_STATE_REAPING); -// pthread_join (thread->thread_id, 0); + //pthread_join (thread->thread_id, 0); GST_INFO (GST_CAT_THREAD, "gstthread: thread \"%s\" is stopped", gst_element_get_name (GST_ELEMENT (thread))); diff --git a/libs/videoscale/gstvideoscale.c b/libs/videoscale/gstvideoscale.c index 8ec43fa4ee..8184e45900 100644 --- a/libs/videoscale/gstvideoscale.c +++ b/libs/videoscale/gstvideoscale.c @@ -63,6 +63,11 @@ GstVideoScale *gst_videoscale_new(gint sw, gint sh, gint dw, gint dh, GstColorSp new->scale = gst_videoscale_scale_rgb; scale_bytes = 2; break; + case GST_COLORSPACE_RGB32: + case GST_COLORSPACE_BGR32: + new->scale = gst_videoscale_scale_rgb; + scale_bytes = 4; + break; default: g_print("videoscale: unsupported video format %d\n", format); g_free(new); diff --git a/tests/eos/Makefile.am b/tests/eos/Makefile.am index 6ae80af2cc..55839b9e5a 100644 --- a/tests/eos/Makefile.am +++ b/tests/eos/Makefile.am @@ -1,4 +1,4 @@ -noinst_PROGRAMS = case1 case2 case3 case4 case5 case6 +noinst_PROGRAMS = case1 case2 case3 case4 case5 case6 case7 # jsut apps here, this is safe LIBS += $(GST_LIBS) diff --git a/tests/eos/case4.c b/tests/eos/case4.c index 8043b57f52..9b2472f031 100644 --- a/tests/eos/case4.c +++ b/tests/eos/case4.c @@ -19,7 +19,7 @@ eos_signal (GstElement *element) int main(int argc,char *argv[]) { - GstBin *pipeline, *pipeline2; + GstBin *pipeline, *bin; GstElement *src,*identity,*sink; GstElement *src2,*identity2,*sink2; @@ -38,14 +38,14 @@ main(int argc,char *argv[]) sink = gst_elementfactory_make("fakesink","sink"); g_return_val_if_fail(sink != NULL, 4); - pipeline2 = GST_BIN(gst_pipeline_new("pipeline2")); - g_return_val_if_fail(pipeline2 != NULL, 1); + bin = GST_BIN(gst_bin_new("bin")); + g_return_val_if_fail(bin != NULL, 1); - gst_bin_add(pipeline2,GST_ELEMENT(src)); - gst_bin_add(pipeline2,GST_ELEMENT(identity)); - gst_bin_add(pipeline2,GST_ELEMENT(sink)); + gst_bin_add(bin,GST_ELEMENT(src)); + gst_bin_add(bin,GST_ELEMENT(identity)); + gst_bin_add(bin,GST_ELEMENT(sink)); - gst_bin_add(pipeline,GST_ELEMENT(pipeline2)); + gst_bin_add(pipeline,GST_ELEMENT(bin)); gst_element_connect(src,"src",identity,"sink"); gst_element_connect(identity,"src",sink,"sink"); diff --git a/tests/eos/case5.c b/tests/eos/case5.c index f9d45c3420..f0bd8ca38f 100644 --- a/tests/eos/case5.c +++ b/tests/eos/case5.c @@ -29,10 +29,11 @@ main(int argc,char *argv[]) g_return_val_if_fail(pipeline != NULL, 1); src = gst_elementfactory_make("fakesrc","src"); - gtk_object_set (GTK_OBJECT (src), "num_buffers", 1, NULL); + gtk_object_set (GTK_OBJECT (src), "num_buffers", 4, NULL); g_return_val_if_fail(src != NULL, 2); identity = gst_elementfactory_make("identity","identity"); + gtk_object_set (GTK_OBJECT (identity), "sleep_time", 1000000, NULL); g_return_val_if_fail(identity != NULL, 3); sink = gst_elementfactory_make("fakesink","sink"); @@ -51,7 +52,7 @@ main(int argc,char *argv[]) gst_element_connect(identity,"src",sink,"sink"); src2 = gst_elementfactory_make("fakesrc","src2"); - gtk_object_set (GTK_OBJECT (src2), "num_buffers", 4, NULL); + gtk_object_set (GTK_OBJECT (src2), "num_buffers", 1, NULL); g_return_val_if_fail(src2 != NULL, 2); identity2 = gst_elementfactory_make("identity","identity2"); diff --git a/tools/gstreamer-launch.c b/tools/gstreamer-launch.c index 1c5ae6ddda..82a8d234a5 100644 --- a/tools/gstreamer-launch.c +++ b/tools/gstreamer-launch.c @@ -4,31 +4,33 @@ #include #include -int main(int argc,char *argv[]) { +int +main(int argc, char *argv[]) +{ GstElement *pipeline; char **argvn; gchar *cmdline; - int i; - - gst_init(&argc,&argv); - pipeline = gst_pipeline_new("launch"); + gst_init (&argc, &argv); + + pipeline = gst_pipeline_new ("launch"); // make a null-terminated version of argv - argvn = g_new0(char *,argc); - memcpy(argvn,argv+1,sizeof(char*)*(argc-1)); + argvn = g_new0 (char *,argc); + memcpy (argvn, argv+1, sizeof (char*) * (argc-1)); // join the argvs together - cmdline = g_strjoinv(" ",argvn); + cmdline = g_strjoinv (" ", argvn); // free the null-terminated argv - g_free(argvn); + g_free (argvn); - gst_parse_launch(cmdline,pipeline); + gst_parse_launch (cmdline, GST_BIN (pipeline)); fprintf(stderr,"RUNNING pipeline\n"); - gst_element_set_state(pipeline,GST_STATE_PLAYING); + gst_element_set_state (pipeline, GST_STATE_PLAYING); - while (1) - gst_bin_iterate (GST_BIN (pipeline)); + while (gst_bin_iterate (GST_BIN (pipeline))); + + gst_element_set_state (pipeline, GST_STATE_NULL); return 0; }