[gst-cvs] gst-plugins-bad: camerabin-example: cleanups for mainloop and state-changes . Fixes #608042

Stefan Kost ensonic at kemper.freedesktop.org
Thu Jan 28 05:05:45 PST 2010


Module: gst-plugins-bad
Branch: master
Commit: 0713748e1b63dea9298b00b10b8acffb01170368
URL:    http://cgit.freedesktop.org/gstreamer/gst-plugins-bad/commit/?id=0713748e1b63dea9298b00b10b8acffb01170368

Author: Stefan Kost <ensonic at users.sf.net>
Date:   Thu Jan 28 15:00:32 2010 +0200

camerabin-example: cleanups for mainloop and state-changes. Fixes #608042

Start camerabin via idle handler to have the mainloop already running. Avoid
some unnecessary state changes. Cleanup the bus usage when restarting.

---

 tests/examples/camerabin/gst-camera.c |   78 ++++++++++++++++++++++----------
 1 files changed, 53 insertions(+), 25 deletions(-)

diff --git a/tests/examples/camerabin/gst-camera.c b/tests/examples/camerabin/gst-camera.c
index 15ea040..43934a8 100644
--- a/tests/examples/camerabin/gst-camera.c
+++ b/tests/examples/camerabin/gst-camera.c
@@ -130,6 +130,8 @@ static gchar *image_post;
 
 static GList *video_caps_list = NULL;
 
+static guint bus_handler_id = 0;
+
 #ifdef HAVE_GST_PHOTO_IFACE_H
 static gchar *iso_speed_labels[] = { "auto", "100", "200", "400" };
 
@@ -314,11 +316,17 @@ my_bus_callback (GstBus * bus, GstMessage * message, gpointer data)
 
       gst_message_parse_state_changed (message, &old, &new, &pending);
 
+      GST_DEBUG_OBJECT (GST_MESSAGE_SRC (message), "state-change %s -> %s",
+          gst_element_state_get_name (old), gst_element_state_get_name (new));
+
       /* Create/destroy color controls according videosrc state */
       if (GST_MESSAGE_SRC (message) == GST_OBJECT (gst_videosrc)) {
-        if (old == GST_STATE_PAUSED && new == GST_STATE_READY) {
+        GST_INFO_OBJECT (GST_MESSAGE_SRC (message), "state-change %s -> %s",
+            gst_element_state_get_name (old), gst_element_state_get_name (new));
+
+        if (old == GST_STATE_READY && new == GST_STATE_NULL) {
           destroy_color_controls ();
-        } else if (old == GST_STATE_READY && new == GST_STATE_PAUSED) {
+        } else if (old == GST_STATE_NULL && new == GST_STATE_READY) {
           create_color_controls ();
         }
       }
@@ -334,8 +342,8 @@ my_bus_callback (GstBus * bus, GstMessage * message, gpointer data)
             GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS, dump_name);
         g_free (dump_name);
       }
-    }
       break;
+    }
     case GST_MESSAGE_ELEMENT:
     {
       handle_element_message (message);
@@ -502,7 +510,6 @@ me_gst_setup_pipeline_create_vid_post_bin (const gchar * videopost)
 static gboolean
 me_gst_setup_pipeline (const gchar * imagepost, const gchar * videopost)
 {
-  GstMessage *msg;
   GstBus *bus;
   GstCaps *preview_caps;
 
@@ -521,7 +528,7 @@ me_gst_setup_pipeline (const gchar * imagepost, const gchar * videopost)
   preview_caps = gst_caps_from_string (PREVIEW_CAPS);
 
   bus = gst_pipeline_get_bus (GST_PIPELINE (gst_camera_bin));
-  gst_bus_add_watch (bus, my_bus_callback, NULL);
+  bus_handler_id = gst_bus_add_watch (bus, my_bus_callback, NULL);
   gst_bus_set_sync_handler (bus, my_bus_sync_callback, NULL);
   gst_object_unref (bus);
 
@@ -570,17 +577,6 @@ me_gst_setup_pipeline (const gchar * imagepost, const gchar * videopost)
 
   gst_element_set_state (gst_camera_bin, GST_STATE_PLAYING);
 
-  msg = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (gst_camera_bin),
-      3 * GST_SECOND, GST_MESSAGE_ERROR | GST_MESSAGE_ASYNC_DONE);
-
-  if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
-    print_error_message (msg);
-    gst_message_unref (msg);
-    goto done;
-  }
-
-  gst_message_unref (msg);
-
 #ifdef HAVE_GST_PHOTO_IFACE_H
   /* Initialize menus to default settings */
   GtkWidget *sub_menu =
@@ -600,11 +596,28 @@ done:
   return FALSE;
 }
 
+static gboolean
+me_gst_setup_default_pipeline (gpointer data)
+{
+  if (!me_gst_setup_pipeline (NULL, NULL)) {
+    gtk_main_quit ();
+  }
+  return FALSE;
+}
+
 static void
 me_gst_cleanup_element ()
 {
   if (gst_camera_bin) {
+    GstBus *bus;
+
     gst_element_set_state (gst_camera_bin, GST_STATE_NULL);
+    gst_element_get_state (gst_camera_bin, NULL, NULL, GST_CLOCK_TIME_NONE);
+
+    bus = gst_pipeline_get_bus (GST_PIPELINE (gst_camera_bin));
+    gst_bus_set_sync_handler (bus, NULL, NULL);
+    g_source_remove (bus_handler_id);
+
     gst_object_unref (gst_camera_bin);
     gst_camera_bin = NULL;
 
@@ -842,8 +855,21 @@ on_comboboxResolution_changed (GtkComboBox * widget, gpointer user_data)
       g_list_nth_data (video_caps_list, gtk_combo_box_get_active (widget));
 
   if (video_caps) {
-
-    gst_element_set_state (gst_camera_bin, GST_STATE_READY);
+    GstState old;
+
+    gst_element_get_state (gst_camera_bin, &old, NULL, GST_CLOCK_TIME_NONE);
+    GST_DEBUG ("change resolution in %s", gst_element_state_get_name (old));
+
+    if (old != GST_STATE_NULL) {
+      gst_element_set_state (gst_camera_bin, GST_STATE_READY);
+      /* source need to be NULL, otherwise changing the mode fails with device
+       * busy:
+       * - if src goes from NULL->PLAYING it sets new mode anyway
+       * - if src goes form READY->PLAYIN new mode is activated via reverse caps
+       *   negotiation, but then the device is already streaming
+       */
+      gst_element_set_state (gst_videosrc, GST_STATE_NULL);
+    }
 
     st = gst_caps_get_structure (video_caps, 0);
 
@@ -856,7 +882,9 @@ on_comboboxResolution_changed (GtkComboBox * widget, gpointer user_data)
 
     g_object_set (G_OBJECT (gst_camera_bin), "filter-caps", video_caps, NULL);
 
-    gst_element_set_state (gst_camera_bin, GST_STATE_PLAYING);
+    if (old != GST_STATE_NULL) {
+      gst_element_set_state (gst_camera_bin, old);
+    }
   }
 }
 
@@ -1198,15 +1226,16 @@ destroy_color_controls ()
 {
   GList *widgets, *item;
   GtkWidget *widget = NULL;
+  gpointer user_data = NULL;
 
   widgets = gtk_container_get_children (GTK_CONTAINER (ui_vbox_color_controls));
   for (item = widgets; item; item = g_list_next (item)) {
     widget = GTK_WIDGET (item->data);
+    user_data = g_object_get_data (G_OBJECT (widget), "channel");
     g_signal_handlers_disconnect_by_func (widget, (GFunc) format_value_callback,
-        g_object_get_data (G_OBJECT (widget), "channel"));
+        user_data);
     g_signal_handlers_disconnect_by_func (widget,
-        (GFunc) on_color_control_value_changed,
-        g_object_get_data (G_OBJECT (widget), "channel"));
+        (GFunc) on_color_control_value_changed, user_data);
     gtk_container_remove (GTK_CONTAINER (ui_vbox_color_controls), widget);
   }
   g_list_free (widgets);
@@ -1648,9 +1677,8 @@ main (int argc, char *argv[])
     goto done;
   }
   /* create pipeline and run */
-  if (me_gst_setup_pipeline (NULL, NULL)) {
-    gtk_main ();
-  }
+  g_idle_add (me_gst_setup_default_pipeline, NULL);
+  gtk_main ();
 
 done:
   me_gst_cleanup_element ();





More information about the Gstreamer-commits mailing list