From 9932feec63994d87c586a07513e692545ba0db9e Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Tue, 25 Nov 2014 09:22:23 +1000 Subject: [PATCH] Implement exposure and whitebalance lock for gstreamer camera. Change-Id: I58277d69c18ad2e31cad719a2dd6361c0c2d7e98 Reviewed-by: Yoann Lopes --- .../camerabin/camerabinimageprocessing.cpp | 56 +++++-- .../gstreamer/camerabin/camerabinimageprocessing.h | 6 + src/plugins/gstreamer/camerabin/camerabinlocks.cpp | 164 ++++++++++++++++++++- src/plugins/gstreamer/camerabin/camerabinlocks.h | 19 +++ 4 files changed, 227 insertions(+), 18 deletions(-) diff --git a/src/plugins/gstreamer/camerabin/camerabinimageprocessing.cpp b/src/plugins/gstreamer/camerabin/camerabinimageprocessing.cpp index 811225f..5e4b67b 100644 --- a/src/plugins/gstreamer/camerabin/camerabinimageprocessing.cpp +++ b/src/plugins/gstreamer/camerabin/camerabinimageprocessing.cpp @@ -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(), ¤tMode) + && 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 diff --git a/src/plugins/gstreamer/camerabin/camerabinimageprocessing.h b/src/plugins/gstreamer/camerabin/camerabinimageprocessing.h index 2c6347f..9a3c951 100644 --- a/src/plugins/gstreamer/camerabin/camerabinimageprocessing.h +++ b/src/plugins/gstreamer/camerabin/camerabinimageprocessing.h @@ -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 m_mappedWbValues; #endif + QCameraImageProcessing::WhiteBalanceMode m_whiteBalanceMode; }; QT_END_NAMESPACE diff --git a/src/plugins/gstreamer/camerabin/camerabinlocks.cpp b/src/plugins/gstreamer/camerabin/camerabinlocks.cpp index 7e779b5..87d0273 100644 --- a/src/plugins/gstreamer/camerabin/camerabinlocks.cpp +++ b/src/plugins/gstreamer/camerabin/camerabinlocks.cpp @@ -34,6 +34,9 @@ #include "camerabinlocks.h" #include "camerabinsession.h" #include "camerabinfocus.h" +#include "camerabinimageprocessing.h" + +#include #include @@ -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 diff --git a/src/plugins/gstreamer/camerabin/camerabinlocks.h b/src/plugins/gstreamer/camerabin/camerabinlocks.h index 80044d1..752bc94 100644 --- a/src/plugins/gstreamer/camerabin/camerabinlocks.h +++ b/src/plugins/gstreamer/camerabin/camerabinlocks.h @@ -37,6 +37,8 @@ #include #include +#include + #include #include @@ -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 -- 2.7.4