Allow the camerabin source selection to be overridden.
authorAndrew den Exter <andrew.den.exter@jollamobile.com>
Tue, 10 Dec 2013 03:11:07 +0000 (13:11 +1000)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Mon, 13 Jan 2014 05:05:05 +0000 (06:05 +0100)
Prefer the default camera-source element if there is one or an element
identified by an environment variable to a static list of possible
elements which may not be appropriate for the target environment.

Change-Id: I53816c949307953780f9046eb11e09effe059be0
Reviewed-by: John Brooks <john.brooks@dereferenced.net>
Reviewed-by: Andy Nichols <andy.nichols@digia.com>
Reviewed-by: Yoann Lopes <yoann.lopes@digia.com>
src/gsttools/qgstreamervideoinputdevicecontrol.cpp
src/multimedia/gsttools_headers/qgstreamervideoinputdevicecontrol_p.h
src/plugins/gstreamer/camerabin/camerabinservice.cpp
src/plugins/gstreamer/camerabin/camerabinsession.cpp
src/plugins/gstreamer/camerabin/camerabinsession.h

index 960853b..ad61aef 100644 (file)
 #include <linux/videodev2.h>
 
 QGstreamerVideoInputDeviceControl::QGstreamerVideoInputDeviceControl(QObject *parent)
-    :QVideoDeviceSelectorControl(parent), m_selectedDevice(0)
+    :QVideoDeviceSelectorControl(parent), m_source(0), m_selectedDevice(0)
 {
     update();
 }
 
+QGstreamerVideoInputDeviceControl::QGstreamerVideoInputDeviceControl(GstElement *source, QObject *parent)
+    :QVideoDeviceSelectorControl(parent), m_source(source), m_selectedDevice(0)
+{
+    if (m_source)
+        gst_object_ref(GST_OBJECT(m_source));
+
+    update();
+}
+
 QGstreamerVideoInputDeviceControl::~QGstreamerVideoInputDeviceControl()
 {
+    if (m_source)
+        gst_object_unref(GST_OBJECT(m_source));
 }
 
 int QGstreamerVideoInputDeviceControl::deviceCount() const
@@ -107,10 +118,15 @@ void QGstreamerVideoInputDeviceControl::update()
     m_names.clear();
     m_descriptions.clear();
 
-#ifdef Q_WS_MAEMO_6
-    m_names << QLatin1String("primary") << QLatin1String("secondary");
-    m_descriptions << tr("Main camera") << tr("Front camera");
-#else
+    // subdevsrc and the like have a camera-device property that takes an enumeration
+    // identifying a primary or secondary camera, so return identifiers that map to those
+    // instead of a list of actual devices.
+    if (m_source && g_object_class_find_property(G_OBJECT_GET_CLASS(m_source), "camera-device")) {
+        m_names << QLatin1String("primary") << QLatin1String("secondary");
+        m_descriptions << tr("Main camera") << tr("Front camera");
+        return;
+    }
+
     QDir devDir("/dev");
     devDir.setFilter(QDir::System);
 
@@ -151,5 +167,4 @@ void QGstreamerVideoInputDeviceControl::update()
         }
         ::close(fd);
     }
-#endif
 }
index 401f502..eeb576e 100644 (file)
@@ -45,6 +45,8 @@
 #include <qvideodeviceselectorcontrol.h>
 #include <QtCore/qstringlist.h>
 
+#include <gst/gst.h>
+
 QT_BEGIN_NAMESPACE
 
 class QGstreamerVideoInputDeviceControl : public QVideoDeviceSelectorControl
@@ -52,6 +54,7 @@ class QGstreamerVideoInputDeviceControl : public QVideoDeviceSelectorControl
 Q_OBJECT
 public:
     QGstreamerVideoInputDeviceControl(QObject *parent);
+    QGstreamerVideoInputDeviceControl(GstElement *source, QObject *parent);
     ~QGstreamerVideoInputDeviceControl();
 
     int deviceCount() const;
@@ -68,6 +71,8 @@ public Q_SLOTS:
 private:
     void update();
 
+    GstElement *m_source;
+
     int m_selectedDevice;
     QStringList m_names;
     QStringList m_descriptions;
index 54c49f4..58d4433 100644 (file)
@@ -109,7 +109,8 @@ CameraBinService::CameraBinService(const QString &service, QObject *parent):
     if (service == Q_MEDIASERVICE_CAMERA) {
         m_captureSession = new CameraBinSession(this);
         m_cameraControl = new CameraBinControl(m_captureSession);
-        m_videoInputDevice = new QGstreamerVideoInputDeviceControl(m_captureSession);
+        m_videoInputDevice = new QGstreamerVideoInputDeviceControl(
+                    m_captureSession->buildCameraSource(), m_captureSession);
         m_imageCaptureControl = new CameraBinImageCapture(m_captureSession);
 
         connect(m_videoInputDevice, SIGNAL(selectedDeviceChanged(QString)),
index 2e5c53a..6e857d5 100644 (file)
@@ -169,6 +169,10 @@ CameraBinSession::CameraBinSession(QObject *parent)
     m_captureDestinationControl = new CameraBinCaptureDestination(this);
     m_captureBufferFormatControl = new CameraBinCaptureBufferFormat(this);
 
+    QByteArray envFlags = qgetenv("QT_GSTREAMER_CAMERABIN_FLAGS");
+    if (!envFlags.isEmpty())
+        g_object_set(G_OBJECT(m_camerabin), "flags", envFlags.toInt(), NULL);
+
     //post image preview in RGB format
     g_object_set(G_OBJECT(m_camerabin), POST_PREVIEWS_PROPERTY, TRUE, NULL);
 
@@ -197,19 +201,10 @@ GstPhotography *CameraBinSession::photography()
         return GST_PHOTOGRAPHY(m_camerabin);
     }
 
-    if (!m_videoSrc) {
-        m_videoSrc = buildCameraSource();
-
-        if (m_videoSrc)
-            g_object_set(m_camerabin, CAMERA_SOURCE_PROPERTY, m_videoSrc, NULL);
-        else
-            g_object_get(m_camerabin, CAMERA_SOURCE_PROPERTY, &m_videoSrc, NULL);
-
-        m_videoInputHasChanged = false;
-    }
+    GstElement * const source = buildCameraSource();
 
-    if (m_videoSrc && GST_IS_PHOTOGRAPHY(m_videoSrc))
-        return GST_PHOTOGRAPHY(m_videoSrc);
+    if (source && GST_IS_PHOTOGRAPHY(source))
+        return GST_PHOTOGRAPHY(source);
 
     return 0;
 }
@@ -225,17 +220,8 @@ CameraBinSession::CameraRole CameraBinSession::cameraRole() const
 */
 bool CameraBinSession::setupCameraBin()
 {
-    if (m_videoInputHasChanged) {
-        m_videoSrc = buildCameraSource();
-
-        if (m_videoSrc)
-            g_object_set(m_camerabin, CAMERA_SOURCE_PROPERTY, m_videoSrc, NULL);
-        else
-            g_object_get(m_camerabin, CAMERA_SOURCE_PROPERTY, &m_videoSrc, NULL);
-
-        m_videoInputHasChanged = false;
-    }
-
+    if (!buildCameraSource())
+        return false;
 
     if (m_viewfinderHasChanged) {
         if (m_viewfinderElement)
@@ -370,28 +356,43 @@ GstElement *CameraBinSession::buildCameraSource()
 #if CAMERABIN_DEBUG
     qDebug() << Q_FUNC_INFO;
 #endif
+    if (!m_videoInputHasChanged)
+        return m_videoSrc;
+    m_videoInputHasChanged = false;
+
     GstElement *videoSrc = 0;
+    g_object_get(G_OBJECT(m_camerabin), CAMERA_SOURCE_PROPERTY, &videoSrc, NULL);
 
-    QList<QByteArray> candidates;
-    candidates << "subdevsrc" << "wrappercamerabinsrc";
-    QByteArray sourceElementName;
+    // If the QT_GSTREAMER_CAMERABIN_SRC environment variable has been set use the source
+    // it recommends.
+    const QByteArray envCandidate = qgetenv("QT_GSTREAMER_CAMERABIN_SRC");
+    if (!m_videoSrc && !envCandidate.isEmpty()) {
+        m_videoSrc = gst_element_factory_make(envCandidate.constData(), "camera_source");
+    }
+
+    // If gstreamer has set a default source use it.
+    if (!m_videoSrc)
+        m_videoSrc = videoSrc;
 
-    foreach (sourceElementName, candidates) {
-        videoSrc = gst_element_factory_make(sourceElementName.constData(), "camera_source");
-        if (videoSrc)
-            break;
+    // If there's no better guidance try the names of some known camera source elements.
+    if (!m_videoSrc) {
+        const QList<QByteArray> candidates = QList<QByteArray>()
+                << "subdevsrc"
+                << "wrappercamerabinsrc";
+
+        foreach (const QByteArray &sourceElementName, candidates) {
+            m_videoSrc = gst_element_factory_make(sourceElementName.constData(), "camera_source");
+            if (m_videoSrc)
+                break;
+        }
     }
 
-    if (videoSrc && !m_inputDevice.isEmpty()) {
+    if (m_videoSrc && !m_inputDevice.isEmpty()) {
 #if CAMERABIN_DEBUG
         qDebug() << "set camera device" << m_inputDevice;
 #endif
-        if (sourceElementName == "subdevsrc") {
-            if (m_inputDevice == QLatin1String("secondary"))
-                g_object_set(G_OBJECT(videoSrc), "camera-device", 1, NULL);
-            else
-                g_object_set(G_OBJECT(videoSrc), "camera-device", 0, NULL);
-        } else if (sourceElementName == "wrappercamerabinsrc") {
+
+        if (g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSrc), "video-source")) {
             GstElement *src = 0;
 
             if (m_videoInputFactory)
@@ -401,12 +402,21 @@ GstElement *CameraBinSession::buildCameraSource()
 
             if (src) {
                 g_object_set(G_OBJECT(src), "device", m_inputDevice.toUtf8().constData(), NULL);
-                g_object_set(G_OBJECT(videoSrc), "video-source", src, NULL);
+                g_object_set(G_OBJECT(m_videoSrc), "video-source", src, NULL);
+            }
+        } else if (g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSrc), "camera-device")) {
+            if (m_inputDevice == QLatin1String("secondary")) {
+                g_object_set(G_OBJECT(m_videoSrc), "camera-device", 1, NULL);
+            } else {
+                g_object_set(G_OBJECT(m_videoSrc), "camera-device", 0, NULL);
             }
         }
     }
 
-    return videoSrc;
+    if (m_videoSrc != videoSrc)
+        g_object_set(G_OBJECT(m_camerabin), CAMERA_SOURCE_PROPERTY, m_videoSrc, NULL);
+
+    return m_videoSrc;
 }
 
 void CameraBinSession::captureImage(int requestId, const QString &fileName)
@@ -626,9 +636,7 @@ void CameraBinSession::setState(QCamera::State newState)
                 m_viewfinderInterface->stopRenderer();
 
             gst_element_set_state(m_camerabin, GST_STATE_NULL);
-            m_videoSrc = buildCameraSource();
-            g_object_set(m_camerabin, CAMERA_SOURCE_PROPERTY, m_videoSrc, NULL);
-            m_videoInputHasChanged = false;
+            buildCameraSource();
         }
 #ifdef USE_READY_STATE_ON_LOADED
         gst_element_set_state(m_camerabin, GST_STATE_READY);
index 305c116..bdc27f3 100644 (file)
@@ -117,6 +117,8 @@ public:
     QDir defaultDir(QCamera::CaptureModes mode) const;
     QString generateFileName(const QString &prefix, const QDir &dir, const QString &ext) const;
 
+    GstElement *buildCameraSource();
+
     CameraBinAudioEncoder *audioEncodeControl() const { return m_audioEncodeControl; }
     CameraBinVideoEncoder *videoEncodeControl() const { return m_videoEncodeControl; }
     CameraBinImageEncoder *imageEncodeControl() const { return m_imageEncodeControl; }
@@ -188,7 +190,6 @@ private slots:
 private:
     bool setupCameraBin();
     void setupCaptureResolution();
-    GstElement *buildCameraSource();
     static void updateBusyStatus(GObject *o, GParamSpec *p, gpointer d);
 
     QUrl m_sink;