diff options
Diffstat (limited to 'src/multimedia/platform/darwin/camera/avfcamera.mm')
-rw-r--r-- | src/multimedia/platform/darwin/camera/avfcamera.mm | 1004 |
1 files changed, 0 insertions, 1004 deletions
diff --git a/src/multimedia/platform/darwin/camera/avfcamera.mm b/src/multimedia/platform/darwin/camera/avfcamera.mm deleted file mode 100644 index ede3c49eb..000000000 --- a/src/multimedia/platform/darwin/camera/avfcamera.mm +++ /dev/null @@ -1,1004 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). -** 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 "avfcameradebug_p.h" -#include "avfcamera_p.h" -#include "avfcamerasession_p.h" -#include "avfcameraservice_p.h" -#include "avfcamerautility_p.h" -#include "avfcamerarenderer_p.h" -#include <qmediacapturesession.h> - -QT_USE_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, QCamera::ExposureMode mode, - AVCaptureExposureMode &avMode) -{ - // Test if mode supported and convert. - Q_ASSERT(captureDevice); - - if (mode == QCamera::ExposureAuto) { - if ([captureDevice isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure]) { - avMode = AVCaptureExposureModeContinuousAutoExposure; - return true; - } - } - - if (mode == QCamera::ExposureManual) { - if ([captureDevice isExposureModeSupported:AVCaptureExposureModeCustom]) { - avMode = AVCaptureExposureModeCustom; - return true; - } - } - - return false; -} - -#endif // defined(Q_OS_IOS) - -} // Unnamed namespace. - - -AVFCamera::AVFCamera(QCamera *camera) - : QPlatformCamera(camera) -{ - Q_ASSERT(camera); -} - -AVFCamera::~AVFCamera() -{ -} - -bool AVFCamera::isActive() const -{ - return m_active; -} - -void AVFCamera::setActive(bool active) -{ - if (m_active == active) - return; - if (m_cameraDevice.isNull() && active) - return; - - m_active = active; - if (m_session) - m_session->setActive(active); - - if (active) - updateCameraConfiguration(); - Q_EMIT activeChanged(m_active); -} - -void AVFCamera::setCamera(const QCameraDevice &camera) -{ - if (m_cameraDevice == camera) - return; - m_cameraDevice = camera; - if (m_session) - m_session->setActiveCamera(camera); - setCameraFormat({}); -} - -bool AVFCamera::setCameraFormat(const QCameraFormat &format) -{ - if (!format.isNull() && !m_cameraDevice.videoFormats().contains(format)) - return false; - - m_cameraFormat = format.isNull() ? findBestCameraFormat(m_cameraDevice) : format; - - if (m_session) - m_session->setCameraFormat(m_cameraFormat); - - return true; -} - -void AVFCamera::setCaptureSession(QPlatformMediaCaptureSession *session) -{ - AVFCameraService *captureSession = static_cast<AVFCameraService *>(session); - if (m_service == captureSession) - return; - - if (m_session) { - m_session->disconnect(this); - m_session->setActiveCamera({}); - m_session->setCameraFormat({}); - } - - m_service = captureSession; - if (!m_service) { - m_session = nullptr; - return; - } - - m_session = m_service->session(); - Q_ASSERT(m_session); - - m_session->setActiveCamera(m_cameraDevice); - m_session->setCameraFormat(m_cameraFormat); - m_session->setActive(m_active); -} - -AVCaptureConnection *AVFCamera::videoConnection() const -{ - if (!m_session || !m_session->videoOutput() || !m_session->videoOutput()->videoDataOutput()) - return nil; - - return [m_session->videoOutput()->videoDataOutput() connectionWithMediaType:AVMediaTypeVideo]; -} - -AVCaptureDevice *AVFCamera::device() const -{ - AVCaptureDevice *device = nullptr; - QByteArray deviceId = m_cameraDevice.id(); - if (!deviceId.isEmpty()) { - device = [AVCaptureDevice deviceWithUniqueID: - [NSString stringWithUTF8String: - deviceId.constData()]]; - } - return device; -} - -#ifdef Q_OS_IOS -namespace -{ - -bool qt_focus_mode_supported(QCamera::FocusMode mode) -{ - // Check if QCamera::FocusMode has counterpart in AVFoundation. - - // AVFoundation has 'Manual', 'Auto' and 'Continuous', - // where 'Manual' is actually 'Locked' + writable property 'lensPosition'. - return mode == QCamera::FocusModeAuto - || mode == QCamera::FocusModeManual; -} - -AVCaptureFocusMode avf_focus_mode(QCamera::FocusMode requestedMode) -{ - switch (requestedMode) { - case QCamera::FocusModeHyperfocal: - case QCamera::FocusModeInfinity: - case QCamera::FocusModeManual: - return AVCaptureFocusModeLocked; - default: - return AVCaptureFocusModeContinuousAutoFocus; - } - -} - -} -#endif - -void AVFCamera::setFocusMode(QCamera::FocusMode mode) -{ -#ifdef Q_OS_IOS - if (focusMode() == mode) - return; - - AVCaptureDevice *captureDevice = device(); - if (!captureDevice) { - if (qt_focus_mode_supported(mode)) { - focusModeChanged(mode); - } else { - qDebugCamera() << Q_FUNC_INFO - << "focus mode not supported"; - } - return; - } - - if (isFocusModeSupported(mode)) { - const AVFConfigurationLock lock(captureDevice); - if (!lock) { - qDebugCamera() << Q_FUNC_INFO - << "failed to lock for configuration"; - return; - } - - captureDevice.focusMode = avf_focus_mode(mode); - } else { - qDebugCamera() << Q_FUNC_INFO << "focus mode not supported"; - return; - } - - Q_EMIT focusModeChanged(mode); -#else - Q_UNUSED(mode); -#endif -} - -bool AVFCamera::isFocusModeSupported(QCamera::FocusMode mode) const -{ -#ifdef Q_OS_IOS - AVCaptureDevice *captureDevice = device(); - if (captureDevice) { - AVCaptureFocusMode avMode = avf_focus_mode(mode); - switch (mode) { - case QCamera::FocusModeAuto: - case QCamera::FocusModeHyperfocal: - case QCamera::FocusModeInfinity: - case QCamera::FocusModeManual: - return [captureDevice isFocusModeSupported:avMode]; - case QCamera::FocusModeAutoNear: - Q_FALLTHROUGH(); - case QCamera::FocusModeAutoFar: - return captureDevice.autoFocusRangeRestrictionSupported - && [captureDevice isFocusModeSupported:avMode]; - } - } -#endif - return mode == QCamera::FocusModeAuto; // stupid builtin webcam doesn't do any focus handling, but hey it's usually focused :) -} - -void AVFCamera::setCustomFocusPoint(const QPointF &point) -{ - if (customFocusPoint() == point) - return; - - if (!QRectF(0.f, 0.f, 1.f, 1.f).contains(point)) { - // ### release custom focus point, tell the camera to focus where it wants... - qDebugCamera() << Q_FUNC_INFO << "invalid focus point (out of range)"; - return; - } - - AVCaptureDevice *captureDevice = device(); - if (!captureDevice) - return; - - if ([captureDevice isFocusPointOfInterestSupported]) { - const AVFConfigurationLock lock(captureDevice); - if (!lock) { - qDebugCamera() << Q_FUNC_INFO << "failed to lock for configuration"; - return; - } - - const CGPoint focusPOI = CGPointMake(point.x(), point.y()); - [captureDevice setFocusPointOfInterest:focusPOI]; - if (focusMode() != QCamera::FocusModeAuto) - [captureDevice setFocusMode:AVCaptureFocusModeAutoFocus]; - - customFocusPointChanged(point); - } -} - -void AVFCamera::setFocusDistance(float d) -{ -#ifdef Q_OS_IOS - AVCaptureDevice *captureDevice = device(); - if (!captureDevice) - return; - - if (captureDevice.lockingFocusWithCustomLensPositionSupported) { - qDebugCamera() << Q_FUNC_INFO << "Setting custom focus distance not supported\n"; - return; - } - - { - AVFConfigurationLock lock(captureDevice); - if (!lock) { - qDebugCamera() << Q_FUNC_INFO << "failed to lock for configuration"; - return; - } - [captureDevice setFocusModeLockedWithLensPosition:d completionHandler:nil]; - } - focusDistanceChanged(d); -#else - Q_UNUSED(d); -#endif -} - -void AVFCamera::updateCameraConfiguration() -{ - AVCaptureDevice *captureDevice = device(); - if (!captureDevice) { - qDebugCamera() << Q_FUNC_INFO << "capture device is nil in 'active' state"; - return; - } - - const AVFConfigurationLock lock(captureDevice); - if (!lock) { - qDebugCamera() << Q_FUNC_INFO << "failed to lock for configuration"; - return; - } - - if ([captureDevice isFocusPointOfInterestSupported]) { - auto point = customFocusPoint(); - const CGPoint focusPOI = CGPointMake(point.x(), point.y()); - [captureDevice setFocusPointOfInterest:focusPOI]; - } - -#ifdef Q_OS_IOS - if (focusMode() != QCamera::FocusModeAuto) { - const AVCaptureFocusMode avMode = avf_focus_mode(focusMode()); - if (captureDevice.focusMode != avMode) { - if ([captureDevice isFocusModeSupported:avMode]) { - [captureDevice setFocusMode:avMode]; - } else { - qDebugCamera() << Q_FUNC_INFO << "focus mode not supported"; - } - } - } - - if (!captureDevice.activeFormat) { - qDebugCamera() << Q_FUNC_INFO << "camera state is active, but active format is nil"; - return; - } - - minimumZoomFactorChanged(captureDevice.minAvailableVideoZoomFactor); - maximumZoomFactorChanged(captureDevice.maxAvailableVideoZoomFactor); - - captureDevice.videoZoomFactor = zoomFactor(); - - CMTime newDuration = AVCaptureExposureDurationCurrent; - bool setCustomMode = false; - - float exposureTime = manualExposureTime(); - if (exposureTime > 0 - && !qt_exposure_duration_equal(captureDevice, exposureTime)) { - newDuration = CMTimeMakeWithSeconds(exposureTime, 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; - int iso = manualIsoSensitivity(); - if (iso > 0 && !qt_iso_equal(captureDevice, iso)) { - newISO = iso; - if (!qt_check_ISO_value(captureDevice, newISO)) { - qDebugCamera() << Q_FUNC_INFO << "requested ISO value is out of range"; - return; - } - setCustomMode = true; - } - - float bias = exposureCompensation(); - if (bias != 0 && !qt_exposure_bias_equal(captureDevice, bias)) { - // TODO: mixed fpns. - if (bias < captureDevice.minExposureTargetBias || bias > captureDevice.maxExposureTargetBias) { - qDebugCamera() << Q_FUNC_INFO << "exposure compensation value is" - << "out of range"; - return; - } - [captureDevice setExposureTargetBias:bias completionHandler:nil]; - } - - // 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) { - [captureDevice setExposureModeCustomWithDuration:newDuration - ISO:newISO - completionHandler:nil]; - return; - } - - QCamera::ExposureMode qtMode = exposureMode(); - AVCaptureExposureMode avMode = AVCaptureExposureModeContinuousAutoExposure; - if (!qt_convert_exposure_mode(captureDevice, qtMode, avMode)) { - qDebugCamera() << Q_FUNC_INFO << "requested exposure mode is not supported"; - return; - } - - captureDevice.exposureMode = avMode; -#endif - - isFlashSupported = isFlashAutoSupported = false; - isTorchSupported = isTorchAutoSupported = false; - - if (captureDevice.hasFlash) { - if ([captureDevice isFlashModeSupported:AVCaptureFlashModeOn]) - isFlashSupported = true; - if ([captureDevice isFlashModeSupported:AVCaptureFlashModeAuto]) - isFlashAutoSupported = true; - } - - if (captureDevice.hasTorch) { - if ([captureDevice isTorchModeSupported:AVCaptureTorchModeOn]) - isTorchSupported = true; - if ([captureDevice isTorchModeSupported:AVCaptureTorchModeAuto]) - isTorchAutoSupported = true; - } - - applyFlashSettings(); - flashReadyChanged(isFlashSupported); -} - -void AVFCamera::updateCameraProperties() -{ - QCamera::Features features; - AVCaptureDevice *captureDevice = device(); - -#ifdef Q_OS_IOS - features = QCamera::Feature::ColorTemperature | QCamera::Feature::ExposureCompensation | - QCamera::Feature::IsoSensitivity | QCamera::Feature::ManualExposureTime; - - if (captureDevice && [captureDevice isLockingFocusWithCustomLensPositionSupported]) - features |= QCamera::Feature::FocusDistance; -#endif - - if (captureDevice && [captureDevice isFocusPointOfInterestSupported]) - features |= QCamera::Feature::CustomFocusPoint; - - supportedFeaturesChanged(features); -} - -void AVFCamera::zoomTo(float factor, float rate) -{ - Q_UNUSED(factor); - Q_UNUSED(rate); - -#ifdef Q_OS_IOS - if (zoomFactor() == factor) - return; - - AVCaptureDevice *captureDevice = device(); - if (!captureDevice || !captureDevice.activeFormat) - return; - - factor = qBound(captureDevice.minAvailableVideoZoomFactor, factor, captureDevice.maxAvailableVideoZoomFactor); - - const AVFConfigurationLock lock(captureDevice); - if (!lock) { - qDebugCamera() << Q_FUNC_INFO << "failed to lock for configuration"; - return; - } - - if (rate < 0) - captureDevice.videoZoomFactor = factor; - else - [AVCaptureDevice rampToVideoZoomFactor:factor withRate:rate]; -#endif -} - -void AVFCamera::setFlashMode(QCamera::FlashMode mode) -{ - if (flashMode() == mode) - return; - - if (isActive() && !isFlashModeSupported(mode)) { - qDebugCamera() << Q_FUNC_INFO << "unsupported mode" << mode; - return; - } - - flashModeChanged(mode); - - if (!isActive()) - return; - - applyFlashSettings(); -} - -bool AVFCamera::isFlashModeSupported(QCamera::FlashMode mode) const -{ - if (mode == QCamera::FlashOff) - return true; - else if (mode == QCamera::FlashOn) - return isFlashSupported; - else //if (mode == QCamera::FlashAuto) - return isFlashAutoSupported; -} - -bool AVFCamera::isFlashReady() const -{ - if (!isActive()) - return false; - - AVCaptureDevice *captureDevice = device(); - if (!captureDevice) - return false; - - if (!captureDevice.hasFlash) - return false; - - if (!isFlashModeSupported(flashMode())) - return false; - -#ifdef Q_OS_IOS - // AVCaptureDevice's docs: - // "The flash may become unavailable if, for example, - // the device overheats and needs to cool off." - return [captureDevice isFlashAvailable]; -#endif - - return true; -} - -void AVFCamera::setTorchMode(QCamera::TorchMode mode) -{ - if (torchMode() == mode) - return; - - if (isActive() && !isTorchModeSupported(mode)) { - qDebugCamera() << Q_FUNC_INFO << "unsupported torch mode" << mode; - return; - } - - torchModeChanged(mode); - - if (!isActive()) - return; - - applyFlashSettings(); -} - -bool AVFCamera::isTorchModeSupported(QCamera::TorchMode mode) const -{ - if (mode == QCamera::TorchOff) - return true; - else if (mode == QCamera::TorchOn) - return isTorchSupported; - else //if (mode == QCamera::TorchAuto) - return isTorchAutoSupported; -} - -void AVFCamera::setExposureMode(QCamera::ExposureMode qtMode) -{ -#ifdef Q_OS_IOS - if (qtMode != QCamera::ExposureAuto && qtMode != QCamera::ExposureManual) { - qDebugCamera() << Q_FUNC_INFO << "exposure mode not supported"; - return; - } - - AVCaptureDevice *captureDevice = device(); - if (!captureDevice) { - exposureModeChanged(qtMode); - return; - } - - AVCaptureExposureMode avMode = AVCaptureExposureModeContinuousAutoExposure; - if (!qt_convert_exposure_mode(captureDevice, qtMode, avMode)) { - qDebugCamera() << Q_FUNC_INFO << "exposure mode not supported"; - return; - } - - const AVFConfigurationLock lock(captureDevice); - if (!lock) { - qDebugCamera() << Q_FUNC_INFO << "failed to lock a capture device" - << "for configuration"; - return; - } - - [captureDevice setExposureMode:avMode]; - exposureModeChanged(qtMode); -#else - Q_UNUSED(qtMode); -#endif -} - -bool AVFCamera::isExposureModeSupported(QCamera::ExposureMode mode) const -{ - if (mode == QCamera::ExposureAuto) - return true; - if (mode != QCamera::ExposureManual) - return false; - - if (@available(macOS 10.15, *)) { - AVCaptureDevice *captureDevice = device(); - return captureDevice && [captureDevice isExposureModeSupported:AVCaptureExposureModeCustom]; - } - - return false; -} - -void AVFCamera::applyFlashSettings() -{ - Q_ASSERT(isActive()); - - AVCaptureDevice *captureDevice = device(); - if (!captureDevice) { - qDebugCamera() << Q_FUNC_INFO << "no capture device found"; - return; - } - - - const AVFConfigurationLock lock(captureDevice); - - if (captureDevice.hasFlash) { - auto mode = flashMode(); - if (mode == QCamera::FlashOff) { - captureDevice.flashMode = AVCaptureFlashModeOff; - } else { -#ifdef Q_OS_IOS - if (![captureDevice isFlashAvailable]) { - qDebugCamera() << Q_FUNC_INFO << "flash is not available at the moment"; - return; - } -#endif - if (mode == QCamera::FlashOn) - captureDevice.flashMode = AVCaptureFlashModeOn; - else if (mode == QCamera::FlashAuto) - captureDevice.flashMode = AVCaptureFlashModeAuto; - } - } - - if (captureDevice.hasTorch) { - auto mode = torchMode(); - if (mode == QCamera::TorchOff) { - captureDevice.torchMode = AVCaptureTorchModeOff; - } else { -#ifdef Q_OS_IOS - if (![captureDevice isTorchAvailable]) { - qDebugCamera() << Q_FUNC_INFO << "torch is not available at the moment"; - return; - } -#endif - if (mode == QCamera::TorchOn) - captureDevice.torchMode = AVCaptureTorchModeOn; - else if (mode == QCamera::TorchAuto) - captureDevice.torchMode = AVCaptureTorchModeAuto; - } - } -} - - -void AVFCamera::setExposureCompensation(float bias) -{ -#ifdef Q_OS_IOS - AVCaptureDevice *captureDevice = device(); - if (!captureDevice) { - exposureCompensationChanged(bias); - return; - } - - bias = qBound(captureDevice.minExposureTargetBias, bias, captureDevice.maxExposureTargetBias); - - const AVFConfigurationLock lock(captureDevice); - if (!lock) { - qDebugCamera() << Q_FUNC_INFO << "failed to lock for configuration"; - return; - } - - [captureDevice setExposureTargetBias:bias completionHandler:nil]; - exposureCompensationChanged(bias); -#else - Q_UNUSED(bias); -#endif -} - -void AVFCamera::setManualExposureTime(float value) -{ -#ifdef Q_OS_IOS - if (value < 0) { - setExposureMode(QCamera::ExposureAuto); - return; - } - - AVCaptureDevice *captureDevice = device(); - if (!captureDevice) { - exposureTimeChanged(value); - return; - } - - const CMTime newDuration = CMTimeMakeWithSeconds(value, captureDevice.exposureDuration.timescale); - if (!qt_check_exposure_duration(captureDevice, newDuration)) { - qDebugCamera() << Q_FUNC_INFO << "shutter speed value is out of range"; - return; - } - - const AVFConfigurationLock lock(captureDevice); - if (!lock) { - qDebugCamera() << Q_FUNC_INFO << "failed to lock for configuration"; - return; - } - - // Setting the shutter speed (exposure duration in Apple's terms, - // since there is no shutter actually) will also reset - // exposure mode into custom mode. - [captureDevice setExposureModeCustomWithDuration:newDuration - ISO:AVCaptureISOCurrent - completionHandler:nil]; - - exposureTimeChanged(value); - -#else - Q_UNUSED(value); -#endif -} - -float AVFCamera::exposureTime() const -{ -#ifdef Q_OS_IOS - AVCaptureDevice *captureDevice = device(); - if (!captureDevice) - return -1.; - auto duration = captureDevice.exposureDuration; - return CMTimeGetSeconds(duration); -#else - return -1; -#endif -} - -#ifdef Q_OS_IOS -namespace { - -void avf_convert_white_balance_mode(QCamera::WhiteBalanceMode qtMode, - AVCaptureWhiteBalanceMode &avMode) -{ - if (qtMode == QCamera::WhiteBalanceAuto) - avMode = AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance; - else - avMode = AVCaptureWhiteBalanceModeLocked; -} - -bool avf_set_white_balance_mode(AVCaptureDevice *captureDevice, - AVCaptureWhiteBalanceMode avMode) -{ - Q_ASSERT(captureDevice); - - const bool lock = [captureDevice lockForConfiguration:nil]; - if (!lock) { - qDebug() << "Failed to lock a capture device for configuration\n"; - return false; - } - - captureDevice.whiteBalanceMode = avMode; - [captureDevice unlockForConfiguration]; - return true; -} - -bool avf_convert_temp_and_tint_to_wb_gains(AVCaptureDevice *captureDevice, - float temp, float tint, AVCaptureWhiteBalanceGains &wbGains) -{ - Q_ASSERT(captureDevice); - - AVCaptureWhiteBalanceTemperatureAndTintValues wbTTValues = { - .temperature = temp, - .tint = tint - }; - wbGains = [captureDevice deviceWhiteBalanceGainsForTemperatureAndTintValues:wbTTValues]; - - if (wbGains.redGain >= 1.0 && wbGains.redGain <= captureDevice.maxWhiteBalanceGain - && wbGains.greenGain >= 1.0 && wbGains.greenGain <= captureDevice.maxWhiteBalanceGain - && wbGains.blueGain >= 1.0 && wbGains.blueGain <= captureDevice.maxWhiteBalanceGain) - return true; - - return false; -} - -bool avf_set_white_balance_gains(AVCaptureDevice *captureDevice, - AVCaptureWhiteBalanceGains wbGains) -{ - const bool lock = [captureDevice lockForConfiguration:nil]; - if (!lock) { - qDebug() << "Failed to lock a capture device for configuration\n"; - return false; - } - - [captureDevice setWhiteBalanceModeLockedWithDeviceWhiteBalanceGains:wbGains - completionHandler:nil]; - [captureDevice unlockForConfiguration]; - return true; -} - -} - -bool AVFCamera::isWhiteBalanceModeSupported(QCamera::WhiteBalanceMode mode) const -{ - if (mode == QCamera::WhiteBalanceAuto) - return true; - AVCaptureDevice *captureDevice = device(); - if (!captureDevice) - return false; - return [captureDevice isWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeLocked]; -} - -void AVFCamera::setWhiteBalanceMode(QCamera::WhiteBalanceMode mode) -{ - if (!isWhiteBalanceModeSupported(mode)) - return; - - AVCaptureDevice *captureDevice = device(); - Q_ASSERT(captureDevice); - - const AVFConfigurationLock lock(captureDevice); - if (!lock) { - qDebugCamera() << Q_FUNC_INFO << "failed to lock a capture device" - << "for configuration"; - return; - } - - AVCaptureWhiteBalanceMode avMode; - avf_convert_white_balance_mode(mode, avMode); - avf_set_white_balance_mode(captureDevice, avMode); - - if (mode == QCamera::WhiteBalanceAuto || mode == QCamera::WhiteBalanceManual) { - whiteBalanceModeChanged(mode); - return; - } - - const int colorTemp = colorTemperatureForWhiteBalance(mode); - AVCaptureWhiteBalanceGains wbGains; - if (avf_convert_temp_and_tint_to_wb_gains(captureDevice, colorTemp, 0., wbGains) - && avf_set_white_balance_gains(captureDevice, wbGains)) - whiteBalanceModeChanged(mode); -} - -void AVFCamera::setColorTemperature(int colorTemp) -{ - if (colorTemp == 0) { - colorTemperatureChanged(colorTemp); - return; - } - - AVCaptureDevice *captureDevice = device(); - if (!captureDevice || ![captureDevice isWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeLocked]) - return; - - const AVFConfigurationLock lock(captureDevice); - if (!lock) { - qDebugCamera() << Q_FUNC_INFO << "failed to lock a capture device" - << "for configuration"; - return; - } - - AVCaptureWhiteBalanceGains wbGains; - if (avf_convert_temp_and_tint_to_wb_gains(captureDevice, colorTemp, 0., wbGains) - && avf_set_white_balance_gains(captureDevice, wbGains)) - colorTemperatureChanged(colorTemp); -} -#endif - -void AVFCamera::setManualIsoSensitivity(int value) -{ -#ifdef Q_OS_IOS - if (value < 0) { - setExposureMode(QCamera::ExposureAuto); - return; - } - - AVCaptureDevice *captureDevice = device(); - if (!captureDevice) { - isoSensitivityChanged(value); - return; - } - - if (!qt_check_ISO_value(captureDevice, value)) { - qDebugCamera() << Q_FUNC_INFO << "ISO value is out of range"; - return; - } - - const AVFConfigurationLock lock(captureDevice); - if (!lock) { - qDebugCamera() << Q_FUNC_INFO << "failed to lock a capture device" - << "for configuration"; - return; - } - - // Setting the ISO will also reset - // exposure mode to the custom mode. - [captureDevice setExposureModeCustomWithDuration:AVCaptureExposureDurationCurrent - ISO:value - completionHandler:nil]; - - isoSensitivityChanged(value); -#else - Q_UNUSED(value); -#endif -} - -int AVFCamera::isoSensitivity() const -{ - return manualIsoSensitivity(); -} - - -#include "moc_avfcamera_p.cpp" |