camerabin: Add one property to set sink element for video recording pipeline

Add one property to set sink element for video recording. Default is
filesink.

https://bugzilla.gnome.org/show_bug.cgi?id=744508

Upstream Status: Inappropriate [i.MX specific]
diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c
index 0e4a3c7..6549bcb 100644
--- a/gst/camerabin2/gstcamerabin2.c
+++ b/gst/camerabin2/gstcamerabin2.c
@@ -203,6 +203,7 @@
   PROP_MUTE_AUDIO,
   PROP_AUDIO_CAPTURE_SUPPORTED_CAPS,
   PROP_AUDIO_CAPTURE_CAPS,
+  PROP_VIDEO_SINK,
   PROP_ZOOM,
   PROP_MAX_ZOOM,
   PROP_IMAGE_ENCODING_PROFILE,
@@ -342,7 +343,7 @@
 
   /* check that we have a valid location */
   if (camerabin->mode == MODE_VIDEO) {
-    if (camerabin->location == NULL) {
+    if (camerabin->location == NULL && !camerabin->user_video_sink) {
       GST_ELEMENT_ERROR (camerabin, RESOURCE, OPEN_WRITE,
           (_("File location is set to NULL, please set it to a valid filename")), (NULL));
       return;
@@ -477,10 +478,13 @@
     if (camera->mode == MODE_VIDEO) {
       /* a video recording is about to start, change the filesink location */
       gst_element_set_state (camera->videosink, GST_STATE_NULL);
-      location = g_strdup_printf (camera->location, camera->capture_index);
-      GST_DEBUG_OBJECT (camera, "Switching videobin location to %s", location);
-      g_object_set (camera->videosink, "location", location, NULL);
-      g_free (location);
+      /* shouldn't set location for user_video_sink */
+      if (!camera->user_video_sink) {
+        location = g_strdup_printf (camera->location, camera->capture_index);
+        GST_DEBUG_OBJECT (camera, "Switching videobin location to %s", location);
+        g_object_set (camera->videosink, "location", location, NULL);
+        g_free (location);
+      }
       if (gst_element_set_state (camera->videosink, GST_STATE_PLAYING) ==
           GST_STATE_CHANGE_FAILURE) {
         /* Resets the latest state change return, that would be a failure
@@ -535,6 +539,8 @@
 
   if (camerabin->videosink)
     gst_object_unref (camerabin->videosink);
+  if (camerabin->user_video_sink)
+    gst_object_unref (camerabin->user_video_sink);
   if (camerabin->video_encodebin)
     gst_object_unref (camerabin->video_encodebin);
   if (camerabin->videobin_capsfilter)
@@ -655,6 +661,12 @@
           " taken into use on the next null to ready transition",
           GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  g_object_class_install_property (object_class, PROP_VIDEO_SINK,
+      g_param_spec_object ("video-sink", "Video sink",
+          "The video sink element to be used on video recordings. It is only"
+          " taken into use on the next null to ready transition",
+          GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
   g_object_class_install_property (object_class, PROP_MUTE_AUDIO,
       g_param_spec_boolean ("mute", "Mute",
           "If the audio recording should be muted. Note that this still "
@@ -1519,13 +1531,30 @@
         g_signal_connect (camera->video_encodebin, "element-added",
         (GCallback) encodebin_element_added, camera);
 
-    camera->videosink =
-        gst_element_factory_make ("filesink", "videobin-filesink");
-    if (!camera->videosink) {
-      missing_element_name = "filesink";
-      goto missing_element;
+    /* check if we need to replace the videosink */
+    if (camera->videosink) {
+      if (camera->user_video_sink && camera->user_video_sink != camera->videosink) {
+        gst_bin_remove (GST_BIN_CAST (camera), camera->videosink);
+        gst_object_unref (camera->videosink);
+        camera->videosink = NULL;
+      }
     }
-    g_object_set (camera->videosink, "async", FALSE, NULL);
+
+    if (!camera->videosink) {
+      if (camera->user_video_sink) {
+        camera->videosink = gst_object_ref (camera->user_video_sink);
+      } else {
+        camera->videosink =
+          gst_element_factory_make ("filesink", "videobin-filesink");
+        if (!camera->videosink) {
+          missing_element_name = "filesink";
+          goto missing_element;
+        }
+        g_object_set (camera->videosink, "async", FALSE, NULL);
+      }
+    }
+
+    g_assert (camera->videosink != NULL);
 
     /* audio elements */
     if (!camera->audio_volume) {
@@ -1648,7 +1677,9 @@
     gst_element_set_locked_state (camera->videosink, TRUE);
     gst_element_set_locked_state (camera->imagesink, TRUE);
 
-    g_object_set (camera->videosink, "location", camera->location, NULL);
+    if (!camera->user_video_sink) {
+      g_object_set (camera->videosink, "location", camera->location, NULL);
+    }
     g_object_set (camera->imagesink, "location", camera->location, NULL);
   }
 
@@ -2014,6 +2045,20 @@
 }
 
 static void
+gst_camera_bin_set_video_sink (GstCameraBin2 * camera, GstElement * sink)
+{
+  GST_DEBUG_OBJECT (GST_OBJECT (camera),
+      "Setting video sink %" GST_PTR_FORMAT, sink);
+
+  if (camera->user_video_sink)
+    g_object_unref (camera->user_video_sink);
+
+  if (sink)
+    g_object_ref (sink);
+  camera->user_video_sink = sink;
+}
+
+static void
 gst_camera_bin_set_camera_src (GstCameraBin2 * camera, GstElement * src)
 {
   GST_DEBUG_OBJECT (GST_OBJECT (camera),
@@ -2046,6 +2091,9 @@
     case PROP_AUDIO_SRC:
       gst_camera_bin_set_audio_src (camera, g_value_get_object (value));
       break;
+    case PROP_VIDEO_SINK:
+      gst_camera_bin_set_video_sink (camera, g_value_get_object (value));
+      break;
     case PROP_MUTE_AUDIO:
       g_object_set (camera->audio_volume, "mute", g_value_get_boolean (value),
           NULL);
@@ -2229,6 +2277,9 @@
     case PROP_AUDIO_SRC:
       g_value_set_object (value, camera->user_audio_src);
       break;
+    case PROP_VIDEO_SINK:
+      g_value_set_object (value, camera->user_video_sink);
+      break;
     case PROP_MUTE_AUDIO:{
       gboolean mute;
 
diff --git a/gst/camerabin2/gstcamerabin2.h b/gst/camerabin2/gstcamerabin2.h
index ba55a7e..9e090b6 100644
--- a/gst/camerabin2/gstcamerabin2.h
+++ b/gst/camerabin2/gstcamerabin2.h
@@ -71,6 +71,7 @@
   GstElement *video_encodebin;
   gulong video_encodebin_signal_id;
   GstElement *videosink;
+  GstElement *user_video_sink;
   GstElement *videobin_capsfilter;
 
   GstElement *viewfinderbin;