More eos handling, bin in bin is handled correctly now.
authorWim Taymans <wim.taymans@gmail.com>
Sun, 21 Jan 2001 16:06:42 +0000 (16:06 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Sun, 21 Jan 2001 16:06:42 +0000 (16:06 +0000)
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
gst/gstbin.h
gst/gstelement.c
gst/gstthread.c
libs/videoscale/gstvideoscale.c
tests/eos/Makefile.am
tests/eos/case4.c
tests/eos/case5.c
tools/gstreamer-launch.c

index 44347d2..bcd9776 100644 (file)
@@ -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)));
index 4f238ec..6068088 100644 (file)
@@ -67,6 +67,7 @@ struct _GstBin {
   GList *children;
   gint num_eos_providers;
   GList *eos_providers;
+  GCond *eoscond;
 
   /* iteration state */
   gboolean need_cothreads;
index cd8bdfc..b864375 100644 (file)
@@ -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));
 
index 4f82a31..1e80a81 100644 (file)
@@ -34,7 +34,7 @@ GstElementDetails gst_thread_details = {
   "Container that creates/manages a thread",
   VERSION,
   "Erik Walthinsen <omega@cse.ogi.edu>",
-  "(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))
+    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)) 
+  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)));
index 8ec43fa..8184e45 100644 (file)
@@ -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);
index 6ae80af..55839b9 100644 (file)
@@ -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)
index 8043b57..9b2472f 100644 (file)
@@ -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");
index f9d45c3..f0bd8ca 100644 (file)
@@ -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");
index 1c5ae6d..82a8d23 100644 (file)
@@ -4,31 +4,33 @@
 #include <string.h>
 #include <stdlib.h>
 
-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 (gst_bin_iterate (GST_BIN (pipeline)));
 
-  while (1)
-    gst_bin_iterate (GST_BIN (pipeline));
+  gst_element_set_state (pipeline, GST_STATE_NULL);
 
   return 0;
 }