Camera zoom control - version for the AVFoundation plugin
authorTimur Pocheptsov <Timur.Pocheptsov@digia.com>
Fri, 19 Dec 2014 09:54:31 +0000 (10:54 +0100)
committerYoann Lopes <yoann.lopes@theqtcompany.com>
Thu, 5 Feb 2015 22:23:49 +0000 (22:23 +0000)
AVFCameraZoomControl for AVFoundation plugin (videoZoomFactor in
AVCaptureDeviceFormat). iOS only.

Change-Id: I585b8df4c2a477971ada7bd81fabbd44f2371d98
Reviewed-by: Yoann Lopes <yoann.lopes@theqtcompany.com>
src/plugins/avfoundation/camera/avfcameraservice.h
src/plugins/avfoundation/camera/avfcameraservice.mm
src/plugins/avfoundation/camera/avfcamerazoomcontrol.h [new file with mode: 0644]
src/plugins/avfoundation/camera/avfcamerazoomcontrol.mm [new file with mode: 0644]
src/plugins/avfoundation/camera/camera.pro

index e494704..10e3487 100644 (file)
@@ -54,6 +54,7 @@ class AVFCameraDeviceControl;
 class AVFAudioInputSelectorControl;
 class AVFCameraFocusControl;
 class AVFCameraExposureControl;
+class AVFCameraZoomControl;
 
 class AVFCameraService : public QMediaService
 {
@@ -74,6 +75,7 @@ public:
     AVFImageCaptureControl *imageCaptureControl() const { return m_imageCaptureControl; }
     AVFCameraFocusControl *cameraFocusControl() const { return m_cameraFocusControl; }
     AVFCameraExposureControl *cameraExposureControl() const {return m_cameraExposureControl; }
+    AVFCameraZoomControl *cameraZoomControl() const {return m_cameraZoomControl; }
 
 private:
     AVFCameraSession *m_session;
@@ -87,6 +89,7 @@ private:
     AVFImageCaptureControl *m_imageCaptureControl;
     AVFCameraFocusControl *m_cameraFocusControl;
     AVFCameraExposureControl *m_cameraExposureControl;
+    AVFCameraZoomControl *m_cameraZoomControl;
 };
 
 QT_END_NAMESPACE
index c1ac0b7..b40d1ff 100644 (file)
 #include "avfcamerafocuscontrol.h"
 #include "avfcameraexposurecontrol.h"
 
+#ifdef Q_OS_IOS
+#include "avfcamerazoomcontrol.h"
+#endif
+
 #include <private/qmediaplaylistnavigator_p.h>
 #include <qmediaplaylist.h>
 
@@ -83,6 +87,11 @@ AVFCameraService::AVFCameraService(QObject *parent):
     if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_8_0)
         m_cameraExposureControl = new AVFCameraExposureControl(this);
 #endif
+
+    m_cameraZoomControl = 0;
+#ifdef Q_OS_IOS
+    m_cameraZoomControl = new AVFCameraZoomControl(this);
+#endif
 }
 
 AVFCameraService::~AVFCameraService()
@@ -103,7 +112,9 @@ AVFCameraService::~AVFCameraService()
     delete m_cameraControl;
     delete m_cameraFocusControl;
     delete m_cameraExposureControl;
-
+#ifdef Q_OS_IOS
+    delete m_cameraZoomControl;
+#endif
     delete m_session;
 }
 
@@ -143,6 +154,12 @@ QMediaControl *AVFCameraService::requestControl(const char *name)
         m_session->addProbe(videoProbe);
         return videoProbe;
     }
+
+#ifdef Q_OS_IOS
+    if (qstrcmp(name, QCameraZoomControl_iid) == 0)
+        return m_cameraZoomControl;
+#endif
+
     if (!m_videoOutput) {
         if (qstrcmp(name, QVideoRendererControl_iid) == 0)
             m_videoOutput = new AVFCameraRendererControl(this);
diff --git a/src/plugins/avfoundation/camera/avfcamerazoomcontrol.h b/src/plugins/avfoundation/camera/avfcamerazoomcontrol.h
new file mode 100644 (file)
index 0000000..463f510
--- /dev/null
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef AVFCAMERAZOOMCONTROL_H
+#define AVFCAMERAZOOMCONTROL_H
+
+#include <QtMultimedia/qcamerazoomcontrol.h>
+#include <QtMultimedia/qcamera.h>
+
+#include <AVFoundation/AVFoundation.h>
+
+QT_BEGIN_NAMESPACE
+
+class AVFCameraService;
+class AVFCameraSession;
+class AVFCameraControl;
+
+class AVFCameraZoomControl : public QCameraZoomControl
+{
+    Q_OBJECT
+public:
+    AVFCameraZoomControl(AVFCameraService *service);
+
+    qreal maximumOpticalZoom() const Q_DECL_OVERRIDE;
+    qreal maximumDigitalZoom() const Q_DECL_OVERRIDE;
+
+    qreal requestedOpticalZoom() const Q_DECL_OVERRIDE;
+    qreal requestedDigitalZoom() const Q_DECL_OVERRIDE;
+    qreal currentOpticalZoom() const Q_DECL_OVERRIDE;
+    qreal currentDigitalZoom() const Q_DECL_OVERRIDE;
+
+    void zoomTo(qreal optical, qreal digital) Q_DECL_OVERRIDE;
+
+private Q_SLOTS:
+    void cameraStateChanged();
+
+private:
+    void zoomToRequestedDigital();
+
+    AVFCameraSession *m_session;
+
+    CGFloat m_maxZoomFactor;
+    CGFloat m_zoomFactor;
+    CGFloat m_requestedZoomFactor;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/avfoundation/camera/avfcamerazoomcontrol.mm b/src/plugins/avfoundation/camera/avfcamerazoomcontrol.mm
new file mode 100644 (file)
index 0000000..bbd20ac
--- /dev/null
@@ -0,0 +1,188 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "avfcamerazoomcontrol.h"
+#include "avfconfigurationlock.h"
+#include "avfcameraservice.h"
+#include "avfcamerasession.h"
+#include "avfcameracontrol.h"
+#include "avfcameradebug.h"
+
+#include <QtCore/qsysinfo.h>
+#include <QtCore/qglobal.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+AVFCameraZoomControl::AVFCameraZoomControl(AVFCameraService *service)
+    : m_session(service->session()),
+      m_maxZoomFactor(1.),
+      m_zoomFactor(1.),
+      m_requestedZoomFactor(1.)
+{
+    Q_ASSERT(m_session);
+    connect(m_session, SIGNAL(stateChanged(QCamera::State)),
+            SLOT(cameraStateChanged()));
+}
+
+qreal AVFCameraZoomControl::maximumOpticalZoom() const
+{
+    // Not supported.
+    return 1.;
+}
+
+qreal AVFCameraZoomControl::maximumDigitalZoom() const
+{
+    return m_maxZoomFactor;
+}
+
+qreal AVFCameraZoomControl::requestedOpticalZoom() const
+{
+    // Not supported.
+    return 1;
+}
+
+qreal AVFCameraZoomControl::requestedDigitalZoom() const
+{
+    return m_requestedZoomFactor;
+}
+
+qreal AVFCameraZoomControl::currentOpticalZoom() const
+{
+    // Not supported.
+    return 1.;
+}
+
+qreal AVFCameraZoomControl::currentDigitalZoom() const
+{
+    return m_zoomFactor;
+}
+
+void AVFCameraZoomControl::zoomTo(qreal optical, qreal digital)
+{
+    Q_UNUSED(optical)
+    Q_UNUSED(digital)
+#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_7_0)
+    if (QSysInfo::MacintoshVersion < QSysInfo::MV_IOS_7_0)
+        return;
+
+    if (qFuzzyCompare(CGFloat(digital), m_requestedZoomFactor))
+        return;
+
+    m_requestedZoomFactor = digital;
+    Q_EMIT requestedDigitalZoomChanged(digital);
+
+    zoomToRequestedDigital();
+#endif
+}
+
+void AVFCameraZoomControl::cameraStateChanged()
+{
+#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_7_0)
+    if (QSysInfo::MacintoshVersion < QSysInfo::MV_IOS_7_0)
+        return;
+
+    const QCamera::State state = m_session->state();
+    if (state != QCamera::ActiveState) {
+        if (state == QCamera::UnloadedState && m_maxZoomFactor > 1.) {
+            m_maxZoomFactor = 1.;
+            Q_EMIT maximumDigitalZoomChanged(1.);
+        }
+        return;
+    }
+
+    AVCaptureDevice *captureDevice = m_session->videoCaptureDevice();
+    if (!captureDevice || !captureDevice.activeFormat) {
+        qDebugCamera() << Q_FUNC_INFO << "camera state is active, but"
+                       << "video capture device and/or active format is nil";
+        return;
+    }
+
+    if (captureDevice.activeFormat.videoMaxZoomFactor > 1.
+        && !qFuzzyCompare(m_maxZoomFactor, captureDevice.activeFormat.videoMaxZoomFactor)) {
+        m_maxZoomFactor = captureDevice.activeFormat.videoMaxZoomFactor;
+
+        Q_EMIT maximumDigitalZoomChanged(m_maxZoomFactor);
+    } else if (!qFuzzyCompare(m_maxZoomFactor, CGFloat(1.))) {
+        m_maxZoomFactor = 1.;
+
+        Q_EMIT maximumDigitalZoomChanged(1.);
+    }
+
+    zoomToRequestedDigital();
+#endif
+}
+
+void AVFCameraZoomControl::zoomToRequestedDigital()
+{
+#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_7_0)
+    if (QSysInfo::MacintoshVersion < QSysInfo::MV_IOS_7_0)
+        return;
+
+    AVCaptureDevice *captureDevice = m_session->videoCaptureDevice();
+    if (!captureDevice || !captureDevice.activeFormat)
+        return;
+
+    if (qFuzzyCompare(captureDevice.activeFormat.videoMaxZoomFactor, CGFloat(1.)))
+        return;
+
+    const CGFloat clampedZoom = qBound(CGFloat(1.), m_requestedZoomFactor,
+                                       captureDevice.activeFormat.videoMaxZoomFactor);
+    const CGFloat deviceZoom = captureDevice.videoZoomFactor;
+    if (qFuzzyCompare(clampedZoom, deviceZoom)) {
+        // Nothing to set, but check if a signal must be emitted:
+        if (!qFuzzyCompare(m_zoomFactor, deviceZoom)) {
+            m_zoomFactor = deviceZoom;
+            Q_EMIT currentDigitalZoomChanged(deviceZoom);
+        }
+        return;
+    }
+
+    const AVFConfigurationLock lock(captureDevice);
+    if (!lock) {
+        qDebugCamera() << Q_FUNC_INFO << "failed to lock for configuration";
+        return;
+    }
+
+    captureDevice.videoZoomFactor = clampedZoom;
+
+    if (!qFuzzyCompare(clampedZoom, m_zoomFactor)) {
+        m_zoomFactor = clampedZoom;
+        Q_EMIT currentDigitalZoomChanged(clampedZoom);
+    }
+#endif
+}
+
+QT_END_NAMESPACE
+
+#include "moc_avfcamerazoomcontrol.cpp"
index fcf344f..88bb8c3 100644 (file)
@@ -59,3 +59,9 @@ OBJECTIVE_SOURCES += \
     avfcamerafocuscontrol.mm \
     avfcameraexposurecontrol.mm
 
+ios {
+
+HEADERS += avfcamerazoomcontrol.h
+OBJECTIVE_SOURCES += avfcamerazoomcontrol.mm
+
+}