Implement exposure and whitebalance lock for gstreamer camera.
authorAndrew den Exter <andrew.den.exter@qinetic.com.au>
Mon, 24 Nov 2014 23:22:23 +0000 (09:22 +1000)
committerAndrew den Exter <andrew.den.exter@qinetic.com.au>
Fri, 28 Nov 2014 05:07:44 +0000 (06:07 +0100)
Change-Id: I58277d69c18ad2e31cad719a2dd6361c0c2d7e98
Reviewed-by: Yoann Lopes <yoann.lopes@theqtcompany.com>
src/plugins/gstreamer/camerabin/camerabinimageprocessing.cpp
src/plugins/gstreamer/camerabin/camerabinimageprocessing.h
src/plugins/gstreamer/camerabin/camerabinlocks.cpp
src/plugins/gstreamer/camerabin/camerabinlocks.h

index 811225f..5e4b67b 100644 (file)
@@ -44,15 +44,17 @@ QT_BEGIN_NAMESPACE
 
 CameraBinImageProcessing::CameraBinImageProcessing(CameraBinSession *session)
     :QCameraImageProcessingControl(session),
-     m_session(session)
+     m_session(session),
+     m_whiteBalanceMode(QCameraImageProcessing::WhiteBalanceAuto)
 {
 #ifdef HAVE_GST_PHOTOGRAPHY
-    m_mappedWbValues[GST_PHOTOGRAPHY_WB_MODE_AUTO] = QCameraImageProcessing::WhiteBalanceAuto;
-    m_mappedWbValues[GST_PHOTOGRAPHY_WB_MODE_DAYLIGHT] = QCameraImageProcessing::WhiteBalanceSunlight;
-    m_mappedWbValues[GST_PHOTOGRAPHY_WB_MODE_CLOUDY] = QCameraImageProcessing::WhiteBalanceCloudy;
-    m_mappedWbValues[GST_PHOTOGRAPHY_WB_MODE_SUNSET] = QCameraImageProcessing::WhiteBalanceSunset;
-    m_mappedWbValues[GST_PHOTOGRAPHY_WB_MODE_TUNGSTEN] = QCameraImageProcessing::WhiteBalanceTungsten;
-    m_mappedWbValues[GST_PHOTOGRAPHY_WB_MODE_FLUORESCENT] = QCameraImageProcessing::WhiteBalanceFluorescent;
+      m_mappedWbValues[GST_PHOTOGRAPHY_WB_MODE_AUTO] = QCameraImageProcessing::WhiteBalanceAuto;
+      m_mappedWbValues[GST_PHOTOGRAPHY_WB_MODE_DAYLIGHT] = QCameraImageProcessing::WhiteBalanceSunlight;
+      m_mappedWbValues[GST_PHOTOGRAPHY_WB_MODE_CLOUDY] = QCameraImageProcessing::WhiteBalanceCloudy;
+      m_mappedWbValues[GST_PHOTOGRAPHY_WB_MODE_SUNSET] = QCameraImageProcessing::WhiteBalanceSunset;
+      m_mappedWbValues[GST_PHOTOGRAPHY_WB_MODE_TUNGSTEN] = QCameraImageProcessing::WhiteBalanceTungsten;
+      m_mappedWbValues[GST_PHOTOGRAPHY_WB_MODE_FLUORESCENT] = QCameraImageProcessing::WhiteBalanceFluorescent;
+      unlockWhiteBalance();
 #endif
 
     updateColorBalanceValues();
@@ -129,20 +131,23 @@ bool CameraBinImageProcessing::setColorBalanceValue(const QString& channel, qrea
 
 QCameraImageProcessing::WhiteBalanceMode CameraBinImageProcessing::whiteBalanceMode() const
 {
-#ifdef HAVE_GST_PHOTOGRAPHY
-    GstPhotographyWhiteBalanceMode wbMode;
-    gst_photography_get_white_balance_mode(m_session->photography(), &wbMode);
-    return m_mappedWbValues[wbMode];
-#else
-    return QCameraImageProcessing::WhiteBalanceAuto;
-#endif
+    return m_whiteBalanceMode;
 }
 
 void CameraBinImageProcessing::setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceMode mode)
 {
 #ifdef HAVE_GST_PHOTOGRAPHY
-    if (isWhiteBalanceModeSupported(mode))
-        gst_photography_set_white_balance_mode(m_session->photography(), m_mappedWbValues.key(mode));
+    if (isWhiteBalanceModeSupported(mode)) {
+        m_whiteBalanceMode = mode;
+#if GST_CHECK_VERSION(1, 2, 0)
+        GstPhotographyWhiteBalanceMode currentMode;
+        if (gst_photography_get_white_balance_mode(m_session->photography(), &currentMode)
+                && currentMode != GST_PHOTOGRAPHY_WB_MODE_MANUAL)
+#endif
+        {
+            unlockWhiteBalance();
+        }
+    }
 #else
     Q_UNUSED(mode);
 #endif
@@ -215,4 +220,23 @@ void CameraBinImageProcessing::setParameter(QCameraImageProcessingControl::Proce
     updateColorBalanceValues();
 }
 
+#ifdef HAVE_GST_PHOTOGRAPHY
+void CameraBinImageProcessing::lockWhiteBalance()
+{
+#if GST_CHECK_VERSION(1, 2, 0)
+    if (GstPhotography *photography = m_session->photography()) {
+        gst_photography_set_white_balance_mode(photography, GST_PHOTOGRAPHY_WB_MODE_MANUAL);
+    }
+#endif
+}
+
+void CameraBinImageProcessing::unlockWhiteBalance()
+{
+    if (GstPhotography *photography = m_session->photography()) {
+        gst_photography_set_white_balance_mode(
+                photography, m_mappedWbValues.key(m_whiteBalanceMode));
+    }
+}
+#endif
+
 QT_END_NAMESPACE
index 2c6347f..9a3c951 100644 (file)
@@ -68,6 +68,11 @@ public:
     QVariant parameter(ProcessingParameter parameter) const;
     void setParameter(ProcessingParameter parameter, const QVariant &value);
 
+#ifdef HAVE_GST_PHOTOGRAPHY
+    void lockWhiteBalance();
+    void unlockWhiteBalance();
+#endif
+
 private:
     bool setColorBalanceValue(const QString& channel, qreal value);
     void updateColorBalanceValues();
@@ -78,6 +83,7 @@ private:
 #ifdef HAVE_GST_PHOTOGRAPHY
     QMap<GstPhotographyWhiteBalanceMode, QCameraImageProcessing::WhiteBalanceMode> m_mappedWbValues;
 #endif
+    QCameraImageProcessing::WhiteBalanceMode m_whiteBalanceMode;
 };
 
 QT_END_NAMESPACE
index 7e779b5..87d0273 100644 (file)
@@ -34,6 +34,9 @@
 #include "camerabinlocks.h"
 #include "camerabinsession.h"
 #include "camerabinfocus.h"
+#include "camerabinimageprocessing.h"
+
+#include <QtCore/qcoreevent.h>
 
 #include <gst/interfaces/photography.h>
 
@@ -56,29 +59,186 @@ CameraBinLocks::~CameraBinLocks()
 
 QCamera::LockTypes CameraBinLocks::supportedLocks() const
 {
-    return QCamera::LockFocus;
+    QCamera::LockTypes locks = QCamera::LockFocus;
+
+#if GST_CHECK_VERSION(1, 2, 0)
+    if (GstPhotography *photography = m_session->photography()) {
+        if (gst_photography_get_capabilities(photography) & GST_PHOTOGRAPHY_CAPS_WB_MODE)
+            locks |= QCamera::LockWhiteBalance;
+        if (g_object_class_find_property(
+                    G_OBJECT_GET_CLASS(m_session->cameraSource()), "exposure-mode")) {
+            locks |= QCamera::LockExposure;
+        }
+    }
+#endif
+
+    return locks;
 }
 
 QCamera::LockStatus CameraBinLocks::lockStatus(QCamera::LockType lock) const
 {
+    switch (lock) {
+    case QCamera::LockFocus:
+        return m_focus->focusStatus();
+#if GST_CHECK_VERSION(1, 2, 0)
+    case QCamera::LockExposure:
+        if (m_pendingLocks & QCamera::LockExposure)
+            return QCamera::Searching;
+        return isExposureLocked() ? QCamera::Locked : QCamera::Unlocked;
+    case QCamera::LockWhiteBalance:
+        if (m_pendingLocks & QCamera::LockWhiteBalance)
+            return QCamera::Searching;
+        return isWhiteBalanceLocked() ? QCamera::Locked : QCamera::Unlocked;
+#endif
+    default:
+        return QCamera::Unlocked;
+    }
+
     return lock == QCamera::LockFocus ? m_focus->focusStatus() : QCamera::Unlocked;
 }
 
 void CameraBinLocks::searchAndLock(QCamera::LockTypes locks)
 {
-    if (locks & QCamera::LockFocus)
+    m_pendingLocks &= ~locks;
+
+    if (locks & QCamera::LockFocus) {
+        m_pendingLocks |= QCamera::LockFocus;
         m_focus->_q_startFocusing();
+    }
+#if GST_CHECK_VERSION(1, 2, 0)
+    if (!m_pendingLocks)
+        m_lockTimer.stop();
+
+    if (locks & QCamera::LockExposure) {
+        if (isExposureLocked()) {
+            unlockExposure(QCamera::Searching, QCamera::UserRequest);
+            m_pendingLocks |= QCamera::LockExposure;
+            m_lockTimer.start(1000, this);
+        } else {
+            lockExposure(QCamera::UserRequest);
+        }
+    }
+    if (locks & QCamera::LockWhiteBalance) {
+        if (isWhiteBalanceLocked()) {
+            unlockWhiteBalance(QCamera::Searching, QCamera::UserRequest);
+            m_pendingLocks |= QCamera::LockWhiteBalance;
+            m_lockTimer.start(1000, this);
+        } else {
+            lockWhiteBalance(QCamera::UserRequest);
+        }
+    }
+#endif
+
 }
 
 void CameraBinLocks::unlock(QCamera::LockTypes locks)
 {
+    m_pendingLocks &= ~locks;
+
     if (locks & QCamera::LockFocus)
         m_focus->_q_stopFocusing();
+
+#if GST_CHECK_VERSION(1, 2, 0)
+    if (!m_pendingLocks)
+        m_lockTimer.stop();
+
+    if (locks & QCamera::LockExposure)
+        unlockExposure(QCamera::Unlocked, QCamera::UserRequest);
+    if (locks & QCamera::LockWhiteBalance)
+        unlockWhiteBalance(QCamera::Unlocked, QCamera::UserRequest);
+#endif
 }
 
 void CameraBinLocks::updateFocusStatus(QCamera::LockStatus status, QCamera::LockChangeReason reason)
 {
+    if (status != QCamera::Searching)
+        m_pendingLocks &= ~QCamera::LockFocus;
+
+#if GST_CHECK_VERSION(1, 2, 0)
+    if (status == QCamera::Locked && !m_lockTimer.isActive()) {
+        if (m_pendingLocks & QCamera::LockExposure)
+            lockExposure(QCamera::LockAcquired);
+        if (m_pendingLocks & QCamera::LockWhiteBalance)
+            lockWhiteBalance(QCamera::LockAcquired);
+    }
+#endif
     emit lockStatusChanged(QCamera::LockFocus, status, reason);
 }
 
+#if GST_CHECK_VERSION(1, 2, 0)
+
+void CameraBinLocks::timerEvent(QTimerEvent *event)
+{
+    if (event->timerId() != m_lockTimer.timerId())
+        return QCameraLocksControl::timerEvent(event);
+
+    m_lockTimer.stop();
+
+    if (!(m_pendingLocks & QCamera::LockFocus)) {
+        if (m_pendingLocks & QCamera::LockExposure)
+            lockExposure(QCamera::LockAcquired);
+        if (m_pendingLocks & QCamera::LockWhiteBalance)
+            lockWhiteBalance(QCamera::LockAcquired);
+    }
+}
+
+bool CameraBinLocks::isExposureLocked() const
+{
+    if (GstElement *source = m_session->cameraSource()) {
+        GstPhotographyExposureMode exposureMode = GST_PHOTOGRAPHY_EXPOSURE_MODE_AUTO;
+        g_object_get (G_OBJECT(source), "exposure-mode", &exposureMode, NULL);
+        return exposureMode == GST_PHOTOGRAPHY_EXPOSURE_MODE_MANUAL;
+    } else {
+        return false;
+    }
+}
+
+void CameraBinLocks::lockExposure(QCamera::LockChangeReason reason)
+{
+    m_pendingLocks &= ~QCamera::LockExposure;
+    g_object_set(
+                G_OBJECT(m_session->cameraSource()),
+                "exposure-mode",
+                GST_PHOTOGRAPHY_EXPOSURE_MODE_MANUAL,
+                NULL);
+    emit lockStatusChanged(QCamera::LockExposure, QCamera::Locked, reason);
+}
+
+void CameraBinLocks::unlockExposure(QCamera::LockStatus status, QCamera::LockChangeReason reason)
+{
+    g_object_set(
+                G_OBJECT(m_session->cameraSource()),
+                "exposure-mode",
+                GST_PHOTOGRAPHY_EXPOSURE_MODE_AUTO,
+                NULL);
+    emit lockStatusChanged(QCamera::LockExposure, status, reason);
+}
+
+bool CameraBinLocks::isWhiteBalanceLocked() const
+{
+    if (GstPhotography *photography = m_session->photography()) {
+        GstPhotographyWhiteBalanceMode whiteBalanceMode;
+        return gst_photography_get_white_balance_mode(photography, &whiteBalanceMode)
+                && whiteBalanceMode == GST_PHOTOGRAPHY_WB_MODE_MANUAL;
+    } else {
+        return false;
+    }
+}
+
+void CameraBinLocks::lockWhiteBalance(QCamera::LockChangeReason reason)
+{
+    m_pendingLocks &= ~QCamera::LockWhiteBalance;
+    m_session->imageProcessingControl()->lockWhiteBalance();
+    emit lockStatusChanged(QCamera::LockWhiteBalance, QCamera::Locked, reason);
+}
+
+void CameraBinLocks::unlockWhiteBalance(
+        QCamera::LockStatus status, QCamera::LockChangeReason reason)
+{
+    m_session->imageProcessingControl()->lockWhiteBalance();
+    emit lockStatusChanged(QCamera::LockWhiteBalance, status, reason);
+}
+
+#endif
+
 QT_END_NAMESPACE
index 80044d1..752bc94 100644 (file)
@@ -37,6 +37,8 @@
 #include <qcamera.h>
 #include <qcameralockscontrol.h>
 
+#include <QtCore/qbasictimer.h>
+
 #include <gst/gst.h>
 #include <glib.h>
 
@@ -60,12 +62,29 @@ public:
     void searchAndLock(QCamera::LockTypes locks);
     void unlock(QCamera::LockTypes locks);
 
+protected:
+#if GST_CHECK_VERSION(1, 2, 0)
+    void timerEvent(QTimerEvent *event);
+#endif
+
 private slots:
     void updateFocusStatus(QCamera::LockStatus status, QCamera::LockChangeReason reason);
 
 private:
+#if GST_CHECK_VERSION(1, 2, 0)
+    bool isExposureLocked() const;
+    void lockExposure(QCamera::LockChangeReason reason);
+    void unlockExposure(QCamera::LockStatus status, QCamera::LockChangeReason reason);
+
+    bool isWhiteBalanceLocked() const;
+    void lockWhiteBalance(QCamera::LockChangeReason reason);
+    void unlockWhiteBalance(QCamera::LockStatus status, QCamera::LockChangeReason reason);
+#endif
+
     CameraBinSession *m_session;
     CameraBinFocus *m_focus;
+    QBasicTimer m_lockTimer;
+    QCamera::LockTypes m_pendingLocks;
 };
 
 QT_END_NAMESPACE