| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU Lesser General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU Lesser |
| ** General Public License version 3 as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
| ** packaging of this file. Please review the following information to |
| ** ensure the GNU Lesser General Public License version 3 requirements |
| ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 2.0 or (at your option) the GNU General |
| ** Public license version 3 or any later version approved by the KDE Free |
| ** Qt Foundation. The licenses are as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
| ** https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include "avfcameraexposurecontrol.h" |
| #include "avfcamerautility.h" |
| #include "avfcamerasession.h" |
| #include "avfcameraservice.h" |
| #include "avfcameradebug.h" |
| |
| #include <QtCore/qvariant.h> |
| #include <QtCore/qpointer.h> |
| #include <QtCore/qdebug.h> |
| #include <QtCore/qpair.h> |
| |
| #include <AVFoundation/AVFoundation.h> |
| |
| #include <limits> |
| |
| QT_BEGIN_NAMESPACE |
| |
| namespace { |
| |
| // All these methods to work with exposure/ISO/SS in custom mode do not support macOS. |
| |
| #ifdef Q_OS_IOS |
| |
| // Misc. helpers to check values/ranges: |
| |
| bool qt_check_ISO_conversion(float isoValue) |
| { |
| if (isoValue >= std::numeric_limits<int>::max()) |
| return false; |
| if (isoValue <= std::numeric_limits<int>::min()) |
| return false; |
| return true; |
| } |
| |
| bool qt_check_ISO_range(AVCaptureDeviceFormat *format) |
| { |
| // Qt is using int for ISO, AVFoundation - float. It looks like the ISO range |
| // at the moment can be represented by int (it's max - min > 100, etc.). |
| Q_ASSERT(format); |
| if (format.maxISO - format.minISO < 1.) { |
| // ISO is in some strange units? |
| return false; |
| } |
| |
| return qt_check_ISO_conversion(format.minISO) |
| && qt_check_ISO_conversion(format.maxISO); |
| } |
| |
| bool qt_check_exposure_duration(AVCaptureDevice *captureDevice, CMTime duration) |
| { |
| Q_ASSERT(captureDevice); |
| |
| AVCaptureDeviceFormat *activeFormat = captureDevice.activeFormat; |
| if (!activeFormat) { |
| qDebugCamera() << Q_FUNC_INFO << "failed to obtain capture device format"; |
| return false; |
| } |
| |
| return CMTimeCompare(duration, activeFormat.minExposureDuration) != -1 |
| && CMTimeCompare(activeFormat.maxExposureDuration, duration) != -1; |
| } |
| |
| bool qt_check_ISO_value(AVCaptureDevice *captureDevice, int newISO) |
| { |
| Q_ASSERT(captureDevice); |
| |
| AVCaptureDeviceFormat *activeFormat = captureDevice.activeFormat; |
| if (!activeFormat) { |
| qDebugCamera() << Q_FUNC_INFO << "failed to obtain capture device format"; |
| return false; |
| } |
| |
| return !(newISO < activeFormat.minISO || newISO > activeFormat.maxISO); |
| } |
| |
| bool qt_exposure_duration_equal(AVCaptureDevice *captureDevice, qreal qDuration) |
| { |
| Q_ASSERT(captureDevice); |
| const CMTime avDuration = CMTimeMakeWithSeconds(qDuration, captureDevice.exposureDuration.timescale); |
| return !CMTimeCompare(avDuration, captureDevice.exposureDuration); |
| } |
| |
| bool qt_iso_equal(AVCaptureDevice *captureDevice, int iso) |
| { |
| Q_ASSERT(captureDevice); |
| return qFuzzyCompare(float(iso), captureDevice.ISO); |
| } |
| |
| bool qt_exposure_bias_equal(AVCaptureDevice *captureDevice, qreal bias) |
| { |
| Q_ASSERT(captureDevice); |
| return qFuzzyCompare(bias, qreal(captureDevice.exposureTargetBias)); |
| } |
| |
| // Converters: |
| |
| bool qt_convert_exposure_mode(AVCaptureDevice *captureDevice, QCameraExposure::ExposureMode mode, |
| AVCaptureExposureMode &avMode) |
| { |
| // Test if mode supported and convert. |
| Q_ASSERT(captureDevice); |
| |
| if (mode == QCameraExposure::ExposureAuto) { |
| if ([captureDevice isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure]) { |
| avMode = AVCaptureExposureModeContinuousAutoExposure; |
| return true; |
| } |
| } |
| |
| if (mode == QCameraExposure::ExposureManual) { |
| if ([captureDevice isExposureModeSupported:AVCaptureExposureModeCustom]) { |
| avMode = AVCaptureExposureModeCustom; |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| // We set ISO/exposure duration with completion handlers, completion handlers try |
| // to avoid dangling pointers (thus QPointer for QObjects) and not to create |
| // a reference loop (in case we have ARC). |
| |
| void qt_set_exposure_bias(QPointer<AVFCameraService> service, QPointer<AVFCameraExposureControl> control, |
| AVCaptureDevice *captureDevice, float bias) |
| { |
| Q_ASSERT(captureDevice); |
| |
| __block AVCaptureDevice *device = captureDevice; //For ARC. |
| |
| void (^completionHandler)(CMTime syncTime) = ^(CMTime) { |
| // Test that service control is still alive and that |
| // capture device is our device, if yes - emit actual value changed. |
| if (service) { |
| if (control) { |
| if (service->session() && service->session()->videoCaptureDevice() == device) |
| Q_EMIT control->actualValueChanged(int(QCameraExposureControl::ExposureCompensation)); |
| } |
| } |
| device = nil; |
| }; |
| |
| [captureDevice setExposureTargetBias:bias completionHandler:completionHandler]; |
| } |
| |
| void qt_set_duration_iso(QPointer<AVFCameraService> service, QPointer<AVFCameraExposureControl> control, |
| AVCaptureDevice *captureDevice, CMTime duration, float iso) |
| { |
| Q_ASSERT(captureDevice); |
| |
| __block AVCaptureDevice *device = captureDevice; //For ARC. |
| const bool setDuration = CMTimeCompare(duration, AVCaptureExposureDurationCurrent); |
| const bool setISO = !qFuzzyCompare(iso, AVCaptureISOCurrent); |
| |
| void (^completionHandler)(CMTime syncTime) = ^(CMTime) { |
| // Test that service control is still alive and that |
| // capture device is our device, if yes - emit actual value changed. |
| if (service) { |
| if (control) { |
| if (service->session() && service->session()->videoCaptureDevice() == device) { |
| if (setDuration) |
| Q_EMIT control->actualValueChanged(int(QCameraExposureControl::ShutterSpeed)); |
| if (setISO) |
| Q_EMIT control->actualValueChanged(int(QCameraExposureControl::ISO)); |
| } |
| } |
| } |
| device = nil; |
| }; |
| |
| [captureDevice setExposureModeCustomWithDuration:duration |
| ISO:iso |
| completionHandler:completionHandler]; |
| } |
| |
| #endif // defined(Q_OS_IOS) |
| |
| } // Unnamed namespace. |
| |
| AVFCameraExposureControl::AVFCameraExposureControl(AVFCameraService *service) |
| : m_service(service), |
| m_session(nullptr) |
| { |
| Q_ASSERT(service); |
| m_session = m_service->session(); |
| Q_ASSERT(m_session); |
| |
| connect(m_session, SIGNAL(stateChanged(QCamera::State)), SLOT(cameraStateChanged())); |
| } |
| |
| bool AVFCameraExposureControl::isParameterSupported(ExposureParameter parameter) const |
| { |
| #ifdef Q_OS_IOS |
| AVCaptureDevice *captureDevice = m_session->videoCaptureDevice(); |
| if (!captureDevice) |
| return false; |
| |
| // These are the parameters we have an API to support: |
| return parameter == QCameraExposureControl::ISO |
| || parameter == QCameraExposureControl::ShutterSpeed |
| || parameter == QCameraExposureControl::ExposureCompensation |
| || parameter == QCameraExposureControl::ExposureMode; |
| #else |
| Q_UNUSED(parameter) |
| return false; |
| #endif |
| } |
| |
| QVariantList AVFCameraExposureControl::supportedParameterRange(ExposureParameter parameter, |
| bool *continuous) const |
| { |
| QVariantList parameterRange; |
| #ifdef Q_OS_IOS |
| |
| AVCaptureDevice *captureDevice = m_session->videoCaptureDevice(); |
| if (!captureDevice || !isParameterSupported(parameter)) { |
| qDebugCamera() << Q_FUNC_INFO << "parameter not supported"; |
| return parameterRange; |
| } |
| |
| if (continuous) |
| *continuous = false; |
| |
| AVCaptureDeviceFormat *activeFormat = captureDevice.activeFormat; |
| |
| if (parameter == QCameraExposureControl::ISO) { |
| if (!activeFormat) { |
| qDebugCamera() << Q_FUNC_INFO << "failed to obtain capture device format"; |
| return parameterRange; |
| } |
| |
| if (!qt_check_ISO_range(activeFormat)) { |
| qDebugCamera() << Q_FUNC_INFO << "ISO range can not be represented as int"; |
| return parameterRange; |
| } |
| |
| parameterRange << QVariant(int(activeFormat.minISO)); |
| parameterRange << QVariant(int(activeFormat.maxISO)); |
| if (continuous) |
| *continuous = true; |
| } else if (parameter == QCameraExposureControl::ExposureCompensation) { |
| parameterRange << captureDevice.minExposureTargetBias; |
| parameterRange << captureDevice.maxExposureTargetBias; |
| if (continuous) |
| *continuous = true; |
| } else if (parameter == QCameraExposureControl::ShutterSpeed) { |
| if (!activeFormat) { |
| qDebugCamera() << Q_FUNC_INFO << "failed to obtain capture device format"; |
| return parameterRange; |
| } |
| |
| // CMTimeGetSeconds returns Float64, test the conversion below, if it's valid? |
| parameterRange << qreal(CMTimeGetSeconds(activeFormat.minExposureDuration)); |
| parameterRange << qreal(CMTimeGetSeconds(activeFormat.maxExposureDuration)); |
| |
| if (continuous) |
| *continuous = true; |
| } else if (parameter == QCameraExposureControl::ExposureMode) { |
| if ([captureDevice isExposureModeSupported:AVCaptureExposureModeCustom]) |
| parameterRange << QVariant::fromValue(QCameraExposure::ExposureManual); |
| |
| if ([captureDevice isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure]) |
| parameterRange << QVariant::fromValue(QCameraExposure::ExposureAuto); |
| } |
| #else |
| Q_UNUSED(parameter) |
| Q_UNUSED(continuous) |
| #endif |
| return parameterRange; |
| } |
| |
| QVariant AVFCameraExposureControl::requestedValue(ExposureParameter parameter) const |
| { |
| if (!isParameterSupported(parameter)) { |
| qDebugCamera() << Q_FUNC_INFO << "parameter not supported"; |
| return QVariant(); |
| } |
| |
| if (parameter == QCameraExposureControl::ExposureMode) |
| return m_requestedMode; |
| |
| if (parameter == QCameraExposureControl::ExposureCompensation) |
| return m_requestedCompensation; |
| |
| if (parameter == QCameraExposureControl::ShutterSpeed) |
| return m_requestedShutterSpeed; |
| |
| if (parameter == QCameraExposureControl::ISO) |
| return m_requestedISO; |
| |
| return QVariant(); |
| } |
| |
| QVariant AVFCameraExposureControl::actualValue(ExposureParameter parameter) const |
| { |
| #ifdef Q_OS_IOS |
| AVCaptureDevice *captureDevice = m_session->videoCaptureDevice(); |
| if (!captureDevice || !isParameterSupported(parameter)) { |
| // Actually, at the moment !captiredevice => !isParameterSupported. |
| qDebugCamera() << Q_FUNC_INFO << "parameter not supported"; |
| return QVariant(); |
| } |
| |
| if (parameter == QCameraExposureControl::ExposureMode) { |
| // This code expects exposureMode to be continuous by default ... |
| if (captureDevice.exposureMode == AVCaptureExposureModeContinuousAutoExposure) |
| return QVariant::fromValue(QCameraExposure::ExposureAuto); |
| return QVariant::fromValue(QCameraExposure::ExposureManual); |
| } |
| |
| if (parameter == QCameraExposureControl::ExposureCompensation) |
| return captureDevice.exposureTargetBias; |
| |
| if (parameter == QCameraExposureControl::ShutterSpeed) |
| return qreal(CMTimeGetSeconds(captureDevice.exposureDuration)); |
| |
| if (parameter == QCameraExposureControl::ISO) { |
| if (captureDevice.activeFormat && qt_check_ISO_range(captureDevice.activeFormat) |
| && qt_check_ISO_conversion(captureDevice.ISO)) { |
| // Can be represented as int ... |
| return int(captureDevice.ISO); |
| } else { |
| qDebugCamera() << Q_FUNC_INFO << "ISO can not be represented as int"; |
| return QVariant(); |
| } |
| } |
| #else |
| Q_UNUSED(parameter) |
| #endif |
| return QVariant(); |
| } |
| |
| bool AVFCameraExposureControl::setValue(ExposureParameter parameter, const QVariant &value) |
| { |
| if (parameter == QCameraExposureControl::ExposureMode) |
| return setExposureMode(value); |
| else if (parameter == QCameraExposureControl::ExposureCompensation) |
| return setExposureCompensation(value); |
| else if (parameter == QCameraExposureControl::ShutterSpeed) |
| return setShutterSpeed(value); |
| else if (parameter == QCameraExposureControl::ISO) |
| return setISO(value); |
| |
| return false; |
| } |
| |
| bool AVFCameraExposureControl::setExposureMode(const QVariant &value) |
| { |
| #ifdef Q_OS_IOS |
| if (!value.canConvert<QCameraExposure::ExposureMode>()) { |
| qDebugCamera() << Q_FUNC_INFO << "invalid exposure mode value," |
| << "QCameraExposure::ExposureMode expected"; |
| return false; |
| } |
| |
| const QCameraExposure::ExposureMode qtMode = value.value<QCameraExposure::ExposureMode>(); |
| if (qtMode != QCameraExposure::ExposureAuto && qtMode != QCameraExposure::ExposureManual) { |
| qDebugCamera() << Q_FUNC_INFO << "exposure mode not supported"; |
| return false; |
| } |
| |
| AVCaptureDevice *captureDevice = m_session->videoCaptureDevice(); |
| if (!captureDevice) { |
| m_requestedMode = value; |
| Q_EMIT requestedValueChanged(int(QCameraExposureControl::ExposureMode)); |
| return true; |
| } |
| |
| AVCaptureExposureMode avMode = AVCaptureExposureModeAutoExpose; |
| if (!qt_convert_exposure_mode(captureDevice, qtMode, avMode)) { |
| qDebugCamera() << Q_FUNC_INFO << "exposure mode not supported"; |
| return false; |
| } |
| |
| const AVFConfigurationLock lock(captureDevice); |
| if (!lock) { |
| qDebugCamera() << Q_FUNC_INFO << "failed to lock a capture device" |
| << "for configuration"; |
| return false; |
| } |
| |
| m_requestedMode = value; |
| [captureDevice setExposureMode:avMode]; |
| Q_EMIT requestedValueChanged(int(QCameraExposureControl::ExposureMode)); |
| Q_EMIT actualValueChanged(int(QCameraExposureControl::ExposureMode)); |
| |
| return true; |
| #else |
| Q_UNUSED(value) |
| return false; |
| #endif |
| } |
| |
| bool AVFCameraExposureControl::setExposureCompensation(const QVariant &value) |
| { |
| #ifdef Q_OS_IOS |
| if (!value.canConvert<qreal>()) { |
| qDebugCamera() << Q_FUNC_INFO << "invalid exposure compensation" |
| <<"value, floating point number expected"; |
| return false; |
| } |
| |
| const qreal bias = value.toReal(); |
| AVCaptureDevice *captureDevice = m_session->videoCaptureDevice(); |
| if (!captureDevice) { |
| m_requestedCompensation = value; |
| Q_EMIT requestedValueChanged(int(QCameraExposureControl::ExposureCompensation)); |
| return true; |
| } |
| |
| if (bias < captureDevice.minExposureTargetBias || bias > captureDevice.maxExposureTargetBias) { |
| // TODO: mixed fp types! |
| qDebugCamera() << Q_FUNC_INFO << "exposure compenstation value is" |
| << "out of range"; |
| return false; |
| } |
| |
| const AVFConfigurationLock lock(captureDevice); |
| if (!lock) { |
| qDebugCamera() << Q_FUNC_INFO << "failed to lock for configuration"; |
| return false; |
| } |
| |
| qt_set_exposure_bias(m_service, this, captureDevice, bias); |
| m_requestedCompensation = value; |
| Q_EMIT requestedValueChanged(int(QCameraExposureControl::ExposureCompensation)); |
| |
| return true; |
| #else |
| Q_UNUSED(value) |
| return false; |
| #endif |
| } |
| |
| bool AVFCameraExposureControl::setShutterSpeed(const QVariant &value) |
| { |
| #ifdef Q_OS_IOS |
| if (value.isNull()) |
| return setExposureMode(QVariant::fromValue(QCameraExposure::ExposureAuto)); |
| |
| if (!value.canConvert<qreal>()) { |
| qDebugCamera() << Q_FUNC_INFO << "invalid shutter speed" |
| << "value, floating point number expected"; |
| return false; |
| } |
| |
| AVCaptureDevice *captureDevice = m_session->videoCaptureDevice(); |
| if (!captureDevice) { |
| m_requestedShutterSpeed = value; |
| Q_EMIT requestedValueChanged(int(QCameraExposureControl::ShutterSpeed)); |
| return true; |
| } |
| |
| const CMTime newDuration = CMTimeMakeWithSeconds(value.toReal(), |
| captureDevice.exposureDuration.timescale); |
| if (!qt_check_exposure_duration(captureDevice, newDuration)) { |
| qDebugCamera() << Q_FUNC_INFO << "shutter speed value is out of range"; |
| return false; |
| } |
| |
| const AVFConfigurationLock lock(captureDevice); |
| if (!lock) { |
| qDebugCamera() << Q_FUNC_INFO << "failed to lock for configuration"; |
| return false; |
| } |
| |
| // Setting the shutter speed (exposure duration in Apple's terms, |
| // since there is no shutter actually) will also reset |
| // exposure mode into custom mode. |
| qt_set_duration_iso(m_service, this, captureDevice, newDuration, AVCaptureISOCurrent); |
| |
| m_requestedShutterSpeed = value; |
| Q_EMIT requestedValueChanged(int(QCameraExposureControl::ShutterSpeed)); |
| |
| return true; |
| #else |
| Q_UNUSED(value) |
| return false; |
| #endif |
| } |
| |
| bool AVFCameraExposureControl::setISO(const QVariant &value) |
| { |
| #ifdef Q_OS_IOS |
| if (value.isNull()) |
| return setExposureMode(QVariant::fromValue(QCameraExposure::ExposureAuto)); |
| |
| if (!value.canConvert<int>()) { |
| qDebugCamera() << Q_FUNC_INFO << "invalid ISO value, int expected"; |
| return false; |
| } |
| |
| AVCaptureDevice *captureDevice = m_session->videoCaptureDevice(); |
| if (!captureDevice) { |
| m_requestedISO = value; |
| Q_EMIT requestedValueChanged(int(QCameraExposureControl::ISO)); |
| return true; |
| } |
| |
| if (!qt_check_ISO_value(captureDevice, value.toInt())) { |
| qDebugCamera() << Q_FUNC_INFO << "ISO value is out of range"; |
| return false; |
| } |
| |
| const AVFConfigurationLock lock(captureDevice); |
| if (!lock) { |
| qDebugCamera() << Q_FUNC_INFO << "failed to lock a capture device" |
| << "for configuration"; |
| return false; |
| } |
| |
| // Setting the ISO will also reset |
| // exposure mode to the custom mode. |
| qt_set_duration_iso(m_service, this, captureDevice, AVCaptureExposureDurationCurrent, value.toInt()); |
| |
| m_requestedISO = value; |
| Q_EMIT requestedValueChanged(int(QCameraExposureControl::ISO)); |
| |
| return true; |
| #else |
| Q_UNUSED(value) |
| return false; |
| #endif |
| } |
| |
| void AVFCameraExposureControl::cameraStateChanged() |
| { |
| #ifdef Q_OS_IOS |
| if (m_session->state() != QCamera::ActiveState) |
| return; |
| |
| AVCaptureDevice *captureDevice = m_session->videoCaptureDevice(); |
| if (!captureDevice) { |
| qDebugCamera() << Q_FUNC_INFO << "capture device is nil, but the session" |
| << "state is 'active'"; |
| return; |
| } |
| |
| Q_EMIT parameterRangeChanged(int(QCameraExposureControl::ExposureCompensation)); |
| Q_EMIT parameterRangeChanged(int(QCameraExposureControl::ExposureMode)); |
| Q_EMIT parameterRangeChanged(int(QCameraExposureControl::ShutterSpeed)); |
| Q_EMIT parameterRangeChanged(int(QCameraExposureControl::ISO)); |
| |
| const AVFConfigurationLock lock(captureDevice); |
| |
| CMTime newDuration = AVCaptureExposureDurationCurrent; |
| bool setCustomMode = false; |
| |
| if (!m_requestedShutterSpeed.isNull() |
| && !qt_exposure_duration_equal(captureDevice, m_requestedShutterSpeed.toReal())) { |
| newDuration = CMTimeMakeWithSeconds(m_requestedShutterSpeed.toReal(), |
| captureDevice.exposureDuration.timescale); |
| if (!qt_check_exposure_duration(captureDevice, newDuration)) { |
| qDebugCamera() << Q_FUNC_INFO << "requested exposure duration is out of range"; |
| return; |
| } |
| setCustomMode = true; |
| } |
| |
| float newISO = AVCaptureISOCurrent; |
| if (!m_requestedISO.isNull() && !qt_iso_equal(captureDevice, m_requestedISO.toInt())) { |
| newISO = m_requestedISO.toInt(); |
| if (!qt_check_ISO_value(captureDevice, newISO)) { |
| qDebugCamera() << Q_FUNC_INFO << "requested ISO value is out of range"; |
| return; |
| } |
| setCustomMode = true; |
| } |
| |
| if (!m_requestedCompensation.isNull() |
| && !qt_exposure_bias_equal(captureDevice, m_requestedCompensation.toReal())) { |
| // TODO: mixed fpns. |
| const qreal bias = m_requestedCompensation.toReal(); |
| if (bias < captureDevice.minExposureTargetBias || bias > captureDevice.maxExposureTargetBias) { |
| qDebugCamera() << Q_FUNC_INFO << "exposure compenstation value is" |
| << "out of range"; |
| return; |
| } |
| if (!lock) { |
| qDebugCamera() << Q_FUNC_INFO << "failed to lock for configuration"; |
| return; |
| } |
| qt_set_exposure_bias(m_service, this, captureDevice, bias); |
| } |
| |
| // Setting shutter speed (exposure duration) or ISO values |
| // also reset exposure mode into Custom. With this settings |
| // we ignore any attempts to set exposure mode. |
| |
| if (setCustomMode) { |
| if (!lock) |
| qDebugCamera() << Q_FUNC_INFO << "failed to lock for configuration"; |
| else |
| qt_set_duration_iso(m_service, this, captureDevice, newDuration, newISO); |
| return; |
| } |
| |
| if (!m_requestedMode.isNull()) { |
| QCameraExposure::ExposureMode qtMode = m_requestedMode.value<QCameraExposure::ExposureMode>(); |
| AVCaptureExposureMode avMode = AVCaptureExposureModeContinuousAutoExposure; |
| if (!qt_convert_exposure_mode(captureDevice, qtMode, avMode)) { |
| qDebugCamera() << Q_FUNC_INFO << "requested exposure mode is not supported"; |
| return; |
| } |
| |
| if (avMode == captureDevice.exposureMode) |
| return; |
| |
| if (!lock) { |
| qDebugCamera() << Q_FUNC_INFO << "failed to lock for configuration"; |
| return; |
| } |
| |
| [captureDevice setExposureMode:avMode]; |
| Q_EMIT actualValueChanged(int(QCameraExposureControl::ExposureMode)); |
| } |
| #endif |
| } |
| |
| QT_END_NAMESPACE |
| |
| #include "moc_avfcameraexposurecontrol.cpp" |