camerabin2: Add camera-src property
authorThiago Santos <thiago.sousa.santos@collabora.co.uk>
Mon, 13 Dec 2010 19:36:19 +0000 (16:36 -0300)
committerThiago Santos <thiago.sousa.santos@collabora.co.uk>
Thu, 23 Dec 2010 16:18:57 +0000 (13:18 -0300)
Adds a property to select the camera source element to be used.
Changing only happens on the next NULL->READY transition

gst/camerabin2/gstcamerabin2.c
gst/camerabin2/gstcamerabin2.h

index 4168501..f15dddf 100644 (file)
@@ -63,6 +63,7 @@ enum
   PROP_0,
   PROP_MODE,
   PROP_LOCATION,
+  PROP_CAMERA_SRC,
   PROP_IMAGE_CAPTURE_SUPPORTED_CAPS,
   PROP_VIDEO_CAPTURE_SUPPORTED_CAPS
 };
@@ -196,7 +197,6 @@ gst_camera_bin_dispose (GObject * object)
 {
   GstCameraBin *camerabin = GST_CAMERA_BIN_CAST (object);
 
-
   g_free (camerabin->image_location);
   g_free (camerabin->video_location);
 
@@ -205,6 +205,8 @@ gst_camera_bin_dispose (GObject * object)
         camerabin->src_capture_notify_id);
   if (camerabin->src)
     gst_object_unref (camerabin->src);
+  if (camerabin->user_src)
+    gst_object_unref (camerabin->user_src);
 
   if (camerabin->viewfinderbin)
     gst_object_unref (camerabin->viewfinderbin);
@@ -285,6 +287,11 @@ gst_camera_bin_class_init (GstCameraBinClass * klass)
           "Default for images is img_%d and vid_%d for videos",
           DEFAULT_IMG_LOCATION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  g_object_class_install_property (object_class, PROP_CAMERA_SRC,
+      g_param_spec_object ("camera-src", "Camera source",
+          "The camera source element to be used",
+          GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
   g_object_class_install_property (object_class,
       PROP_IMAGE_CAPTURE_SUPPORTED_CAPS,
       g_param_spec_boxed ("image-capture-supported-caps",
@@ -352,63 +359,98 @@ gst_camera_bin_init (GstCameraBin * camerabin)
 static gboolean
 gst_camera_bin_create_elements (GstCameraBin * camera)
 {
-  if (camera->elements_created)
-    return TRUE;
-
-  camera->src = gst_element_factory_make ("v4l2camerasrc", "camerasrc");
-  camera->videobin = gst_element_factory_make ("videorecordingbin", "videobin");
-  camera->imagebin = gst_element_factory_make ("imagecapturebin", "imagebin");
-
-  camera->videobin_queue = gst_element_factory_make ("queue", "videobin-queue");
-  camera->imagebin_queue = gst_element_factory_make ("queue", "imagebin-queue");
-  camera->viewfinderbin_queue = gst_element_factory_make ("queue",
-      "viewfinderbin-queue");
-
-  camera->videobin_capsfilter = gst_element_factory_make ("capsfilter",
-      "videobin-capsfilter");
-  camera->imagebin_capsfilter = gst_element_factory_make ("capsfilter",
-      "imagebin-capsfilter");
-  camera->viewfinderbin_capsfilter = gst_element_factory_make ("capsfilter",
-      "viewfinderbin-capsfilter");
-
-  gst_bin_add_many (GST_BIN_CAST (camera), gst_object_ref (camera->src),
-      gst_object_ref (camera->videobin), gst_object_ref (camera->imagebin),
-      gst_object_ref (camera->videobin_queue),
-      gst_object_ref (camera->imagebin_queue),
-      gst_object_ref (camera->viewfinderbin_queue),
-      gst_object_ref (camera->videobin_capsfilter),
-      gst_object_ref (camera->imagebin_capsfilter),
-      gst_object_ref (camera->viewfinderbin_capsfilter), NULL);
-
-  /* Linking can be optimized TODO */
-  gst_element_link_many (camera->videobin_queue, camera->videobin_capsfilter,
-      camera->videobin, NULL);
-  gst_element_link_many (camera->imagebin_queue, camera->imagebin_capsfilter,
-      camera->imagebin, NULL);
-  gst_element_link_many (camera->viewfinderbin_queue,
-      camera->viewfinderbin_capsfilter, camera->viewfinderbin, NULL);
-  gst_element_link_pads (camera->src, "vfsrc", camera->viewfinderbin_queue,
-      "sink");
-  gst_element_link_pads (camera->src, "imgsrc", camera->imagebin_queue, "sink");
-  gst_element_link_pads (camera->src, "vidsrc", camera->videobin_queue, "sink");
-
-  /*
-   * Video can't get into playing as its internal filesink will open
-   * a file for writing and leave it empty if unused.
-   *
-   * Its state is managed using the current mode and the source's
-   * ready-for-capture notify callback. When we are at video mode and
-   * the source's ready-for-capture goes to FALSE it means it is
-   * starting recording, so we should prepare the video bin.
-   */
-  gst_element_set_locked_state (camera->videobin, TRUE);
-  camera->src_capture_notify_id = g_signal_connect (G_OBJECT (camera->src),
-      "notify::ready-for-capture",
-      G_CALLBACK (gst_camera_bin_src_notify_readyforcapture), camera);
+  gboolean new_src = FALSE;
+
+  if (!camera->elements_created) {
+
+    camera->videobin =
+        gst_element_factory_make ("videorecordingbin", "videobin");
+    camera->imagebin = gst_element_factory_make ("imagecapturebin", "imagebin");
+
+    camera->videobin_queue =
+        gst_element_factory_make ("queue", "videobin-queue");
+    camera->imagebin_queue =
+        gst_element_factory_make ("queue", "imagebin-queue");
+    camera->viewfinderbin_queue =
+        gst_element_factory_make ("queue", "viewfinderbin-queue");
+
+    camera->videobin_capsfilter = gst_element_factory_make ("capsfilter",
+        "videobin-capsfilter");
+    camera->imagebin_capsfilter = gst_element_factory_make ("capsfilter",
+        "imagebin-capsfilter");
+    camera->viewfinderbin_capsfilter = gst_element_factory_make ("capsfilter",
+        "viewfinderbin-capsfilter");
+
+    gst_bin_add_many (GST_BIN_CAST (camera),
+        gst_object_ref (camera->videobin), gst_object_ref (camera->imagebin),
+        gst_object_ref (camera->videobin_queue),
+        gst_object_ref (camera->imagebin_queue),
+        gst_object_ref (camera->viewfinderbin_queue),
+        gst_object_ref (camera->videobin_capsfilter),
+        gst_object_ref (camera->imagebin_capsfilter),
+        gst_object_ref (camera->viewfinderbin_capsfilter), NULL);
+
+    /* Linking can be optimized TODO */
+    gst_element_link_many (camera->videobin_queue, camera->videobin_capsfilter,
+        camera->videobin, NULL);
+    gst_element_link_many (camera->imagebin_queue, camera->imagebin_capsfilter,
+        camera->imagebin, NULL);
+    gst_element_link_many (camera->viewfinderbin_queue,
+        camera->viewfinderbin_capsfilter, camera->viewfinderbin, NULL);
+    /*
+     * Video can't get into playing as its internal filesink will open
+     * a file for writing and leave it empty if unused.
+     *
+     * Its state is managed using the current mode and the source's
+     * ready-for-capture notify callback. When we are at video mode and
+     * the source's ready-for-capture goes to FALSE it means it is
+     * starting recording, so we should prepare the video bin.
+     */
+    gst_element_set_locked_state (camera->videobin, TRUE);
+
+    g_object_set (camera->videobin, "location", camera->video_location, NULL);
+    g_object_set (camera->imagebin, "location", camera->image_location, NULL);
+  }
+
+  /* check if we need to replace the camera src */
+
+  if (camera->src) {
+    if (camera->user_src && camera->user_src != camera->src) {
+
+      if (camera->src_capture_notify_id)
+        g_signal_handler_disconnect (camera->src,
+            camera->src_capture_notify_id);
+
+      gst_bin_remove (GST_BIN_CAST (camera), camera->src);
+      gst_object_unref (camera->src);
+      camera->src = NULL;
+    }
+  }
+
+  if (!camera->src) {
+    if (camera->user_src) {
+      camera->src = gst_object_ref (camera->user_src);
+    } else {
+      camera->src = gst_element_factory_make ("v4l2camerasrc", "camerasrc");
+    }
+
+    new_src = TRUE;
+  }
 
+  g_assert (camera->src != NULL);
   g_object_set (camera->src, "mode", camera->mode, NULL);
-  g_object_set (camera->videobin, "location", camera->video_location, NULL);
-  g_object_set (camera->imagebin, "location", camera->image_location, NULL);
+  if (new_src) {
+    gst_bin_add (GST_BIN_CAST (camera), gst_object_ref (camera->src));
+    camera->src_capture_notify_id = g_signal_connect (G_OBJECT (camera->src),
+        "notify::ready-for-capture",
+        G_CALLBACK (gst_camera_bin_src_notify_readyforcapture), camera);
+    gst_element_link_pads (camera->src, "vfsrc", camera->viewfinderbin_queue,
+        "sink");
+    gst_element_link_pads (camera->src, "imgsrc", camera->imagebin_queue,
+        "sink");
+    gst_element_link_pads (camera->src, "vidsrc", camera->videobin_queue,
+        "sink");
+  }
 
   camera->elements_created = TRUE;
   return TRUE;
@@ -460,6 +502,20 @@ gst_camera_bin_set_location (GstCameraBin * camera, const gchar * location)
 }
 
 static void
+gst_camera_bin_set_camera_src (GstCameraBin * camera, GstElement * src)
+{
+  GST_DEBUG_OBJECT (GST_OBJECT (camera),
+      "Setting camera source %" GST_PTR_FORMAT, src);
+
+  if (camera->user_src)
+    g_object_unref (camera->user_src);
+
+  if (src)
+    g_object_ref (src);
+  camera->user_src = src;
+}
+
+static void
 gst_camera_bin_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec)
 {
@@ -472,6 +528,9 @@ gst_camera_bin_set_property (GObject * object, guint prop_id,
     case PROP_LOCATION:
       gst_camera_bin_set_location (camera, g_value_get_string (value));
       break;
+    case PROP_CAMERA_SRC:
+      gst_camera_bin_set_camera_src (camera, g_value_get_object (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -495,6 +554,9 @@ gst_camera_bin_get_property (GObject * object, guint prop_id,
         g_value_set_string (value, camera->image_location);
       }
       break;
+    case PROP_CAMERA_SRC:
+      g_value_set_object (value, camera->src);
+      break;
     case PROP_VIDEO_CAPTURE_SUPPORTED_CAPS:
     case PROP_IMAGE_CAPTURE_SUPPORTED_CAPS:{
       GstPad *pad;
index f887a1b..5664363 100644 (file)
@@ -38,6 +38,7 @@ struct _GstCameraBin
   GstPipeline pipeline;
 
   GstElement *src;
+  GstElement *user_src;
   gulong src_capture_notify_id;
 
   GstElement *videobin;