basecamerabinsrc: Handle errors from preview pipeline
authorLauri Lehtinen <lauri.lehtinen@digia.com>
Mon, 11 Apr 2011 18:33:20 +0000 (15:33 -0300)
committerThiago Santos <thiago.sousa.santos@collabora.co.uk>
Mon, 16 May 2011 21:08:39 +0000 (18:08 -0300)
Implements a message handling function to preview pipeline bus.
If GST_MESSAGE_ERROR is seen, considers preview pipeline unable
to do its job and posts an error message to application.

Sets pipeline element to NULL so that subsequent calls to post_preview
and set_caps functions just returns without pushing anything to the
disposed preview pipeline. Leaves further actions to the application.

gst-libs/gst/basecamerabinsrc/gstcamerabinpreview.c

index 94c6388..2c3bee5 100644 (file)
 static void _gst_camerabin_preview_set_caps (GstCameraBinPreviewPipelineData *
     preview, GstCaps * caps);
 
+static gboolean
+bus_callback (GstBus * bus, GstMessage * message, gpointer user_data)
+{
+  switch (GST_MESSAGE_TYPE (message)) {
+    case GST_MESSAGE_ERROR:{
+      GError *err;
+      GstCameraBinPreviewPipelineData *data;
+
+      data = user_data;
+
+      gst_message_parse_error (message, &err, NULL);
+      GST_WARNING ("Error from preview pipeline: %s", err->message);
+      g_error_free (err);
+
+      /* TODO Not sure if we should post an Error or Warning here */
+      GST_ELEMENT_ERROR (data, CORE, FAILED,
+          ("fatal error in preview pipeline, disposing the pipeline"), (NULL));
+
+      /* Possible error situations:
+       * 1) cond_wait pending. prevent deadlock by signalling the cond
+       * 2) preview_pipeline_post called with new buffer to handle. returns
+       *    because data->pipeline is set to null
+       * 3) new preview caps incoming. returns because data->pipeline is null
+       */
+
+      if (data->pipeline) {
+        gst_element_set_state (data->pipeline, GST_STATE_NULL);
+        gst_object_unref (data->pipeline);
+        data->pipeline = NULL;
+      }
+
+      g_cond_signal (data->processing_cond);
+
+      break;
+    }
+    default:
+      break;
+  }
+  return TRUE;
+}
+
 static GstFlowReturn
 gst_camerabin_preview_pipeline_new_preroll (GstAppSink * appsink,
     gpointer user_data)
@@ -99,6 +140,7 @@ gst_camerabin_create_preview_pipeline (GstElement * element,
   GstElement *csp2;
   GstElement *vscale;
   gboolean added = FALSE;
+  GstBus *bus;
   GstAppSinkCallbacks callbacks = { 0, };
 
   data = g_new (GstCameraBinPreviewPipelineData, 1);
@@ -138,6 +180,10 @@ gst_camerabin_create_preview_pipeline (GstElement * element,
   gst_app_sink_set_callbacks ((GstAppSink *) data->appsink, &callbacks, data,
       NULL);
 
+  bus = gst_pipeline_get_bus (GST_PIPELINE (data->pipeline));
+  gst_bus_add_watch (bus, bus_callback, data);
+  gst_object_unref (bus);
+
   g_object_set (data->appsink, "sync", FALSE, NULL);
 
   data->element = element;
@@ -214,6 +260,7 @@ gst_camerabin_preview_pipeline_post (GstCameraBinPreviewPipelineData * preview,
   g_return_val_if_fail (buffer, FALSE);
 
   g_mutex_lock (preview->processing_lock);
+  g_return_val_if_fail (preview->pipeline != NULL, FALSE);
 
   if (preview->pending_preview_caps) {
     if (preview->processing > 0) {
@@ -241,6 +288,7 @@ _gst_camerabin_preview_set_caps (GstCameraBinPreviewPipelineData * preview,
   GstStateChangeReturn ret;
 
   g_return_if_fail (preview != NULL);
+  g_return_if_fail (preview->pipeline != NULL);
 
   ret = gst_element_get_state (preview->pipeline, &state, &pending, 0);
   if (ret == GST_STATE_CHANGE_FAILURE) {