summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYoann Lopes <yoann.lopes@digia.com>2014-02-07 14:20:28 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-03-04 17:53:18 +0100
commit9a55f5ce5746fa1df6daa62a7111cb2d5ff5138d (patch)
treebeb13b03600a530a6820017dafa33cb0af364c6f
parent70415c3d9752e357e8d49633cdd8e82d3519e59b (diff)
downloadqtmultimedia-9a55f5ce5746fa1df6daa62a7111cb2d5ff5138d.tar.gz
qtmultimedia-9a55f5ce5746fa1df6daa62a7111cb2d5ff5138d.tar.bz2
qtmultimedia-9a55f5ce5746fa1df6daa62a7111cb2d5ff5138d.zip
AVFoundation: implement QCameraInfoControl.
Change-Id: I05f3daa5c4acb90e046e26d6d577ae40dfed0e30 Reviewed-by: Andy Nichols <andy.nichols@digia.com>
-rw-r--r--src/plugins/avfoundation/camera/avfcamerainfocontrol.h61
-rw-r--r--src/plugins/avfoundation/camera/avfcamerainfocontrol.mm62
-rw-r--r--src/plugins/avfoundation/camera/avfcameraservice.h2
-rw-r--r--src/plugins/avfoundation/camera/avfcameraservice.mm5
-rw-r--r--src/plugins/avfoundation/camera/avfcameraserviceplugin.h12
-rw-r--r--src/plugins/avfoundation/camera/avfcameraserviceplugin.mm51
-rw-r--r--src/plugins/avfoundation/camera/avfcamerasession.h19
-rw-r--r--src/plugins/avfoundation/camera/avfcamerasession.mm72
-rw-r--r--src/plugins/avfoundation/camera/avfvideodevicecontrol.h3
-rw-r--r--src/plugins/avfoundation/camera/avfvideodevicecontrol.mm35
-rw-r--r--src/plugins/avfoundation/camera/camera.pro2
11 files changed, 258 insertions, 66 deletions
diff --git a/src/plugins/avfoundation/camera/avfcamerainfocontrol.h b/src/plugins/avfoundation/camera/avfcamerainfocontrol.h
new file mode 100644
index 00000000..3cf86721
--- /dev/null
+++ b/src/plugins/avfoundation/camera/avfcamerainfocontrol.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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: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 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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef AVFCAMERAINFOCONTROL_H
+#define AVFCAMERAINFOCONTROL_H
+
+#include <qcamerainfocontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+class AVFCameraInfoControl : public QCameraInfoControl
+{
+ Q_OBJECT
+public:
+ explicit AVFCameraInfoControl(QObject *parent = 0);
+
+ QCamera::Position cameraPosition(const QString &deviceName) const;
+ int cameraOrientation(const QString &deviceName) const;
+};
+
+QT_END_NAMESPACE
+
+#endif // AVFCAMERAINFOCONTROL_H
diff --git a/src/plugins/avfoundation/camera/avfcamerainfocontrol.mm b/src/plugins/avfoundation/camera/avfcamerainfocontrol.mm
new file mode 100644
index 00000000..8ae908ad
--- /dev/null
+++ b/src/plugins/avfoundation/camera/avfcamerainfocontrol.mm
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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: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 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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "avfcamerainfocontrol.h"
+#include "avfcamerasession.h"
+
+QT_BEGIN_NAMESPACE
+
+AVFCameraInfoControl::AVFCameraInfoControl(QObject *parent)
+ : QCameraInfoControl(parent)
+{
+}
+
+QCamera::Position AVFCameraInfoControl::cameraPosition(const QString &deviceName) const
+{
+ return AVFCameraSession::cameraDeviceInfo(deviceName.toUtf8()).position;
+}
+
+int AVFCameraInfoControl::cameraOrientation(const QString &deviceName) const
+{
+ return AVFCameraSession::cameraDeviceInfo(deviceName.toUtf8()).orientation;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/avfoundation/camera/avfcameraservice.h b/src/plugins/avfoundation/camera/avfcameraservice.h
index e619c44b..b468a3b9 100644
--- a/src/plugins/avfoundation/camera/avfcameraservice.h
+++ b/src/plugins/avfoundation/camera/avfcameraservice.h
@@ -50,6 +50,7 @@
QT_BEGIN_NAMESPACE
class QCameraControl;
class AVFCameraControl;
+class AVFCameraInfoControl;
class AVFCameraMetaDataControl;
class AVFVideoWindowControl;
class AVFVideoWidgetControl;
@@ -82,6 +83,7 @@ public:
private:
AVFCameraSession *m_session;
AVFCameraControl *m_cameraControl;
+ AVFCameraInfoControl *m_cameraInfoControl;
AVFVideoDeviceControl *m_videoDeviceControl;
AVFAudioInputSelectorControl *m_audioInputSelectorControl;
AVFVideoRendererControl *m_videoOutput;
diff --git a/src/plugins/avfoundation/camera/avfcameraservice.mm b/src/plugins/avfoundation/camera/avfcameraservice.mm
index 094f1b40..25111c5c 100644
--- a/src/plugins/avfoundation/camera/avfcameraservice.mm
+++ b/src/plugins/avfoundation/camera/avfcameraservice.mm
@@ -44,6 +44,7 @@
#include "avfcameraservice.h"
#include "avfcameracontrol.h"
+#include "avfcamerainfocontrol.h"
#include "avfcamerasession.h"
#include "avfvideodevicecontrol.h"
#include "avfaudioinputselectorcontrol.h"
@@ -65,6 +66,7 @@ AVFCameraService::AVFCameraService(QObject *parent):
{
m_session = new AVFCameraSession(this);
m_cameraControl = new AVFCameraControl(this);
+ m_cameraInfoControl = new AVFCameraInfoControl(this);
m_videoDeviceControl = new AVFVideoDeviceControl(this);
m_audioInputSelectorControl = new AVFAudioInputSelectorControl(this);
@@ -98,6 +100,9 @@ QMediaControl *AVFCameraService::requestControl(const char *name)
if (qstrcmp(name, QCameraControl_iid) == 0)
return m_cameraControl;
+ if (qstrcmp(name, QCameraInfoControl_iid) == 0)
+ return m_cameraInfoControl;
+
if (qstrcmp(name, QVideoDeviceSelectorControl_iid) == 0)
return m_videoDeviceControl;
diff --git a/src/plugins/avfoundation/camera/avfcameraserviceplugin.h b/src/plugins/avfoundation/camera/avfcameraserviceplugin.h
index f974bcf0..3a00c0be 100644
--- a/src/plugins/avfoundation/camera/avfcameraserviceplugin.h
+++ b/src/plugins/avfoundation/camera/avfcameraserviceplugin.h
@@ -50,11 +50,13 @@ QT_BEGIN_NAMESPACE
class AVFServicePlugin : public QMediaServiceProviderPlugin,
public QMediaServiceSupportedDevicesInterface,
- public QMediaServiceDefaultDeviceInterface
+ public QMediaServiceDefaultDeviceInterface,
+ public QMediaServiceCameraInfoInterface
{
Q_OBJECT
Q_INTERFACES(QMediaServiceSupportedDevicesInterface)
Q_INTERFACES(QMediaServiceDefaultDeviceInterface)
+ Q_INTERFACES(QMediaServiceCameraInfoInterface)
Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0" FILE "avfcamera.json")
public:
@@ -67,12 +69,8 @@ public:
QList<QByteArray> devices(const QByteArray &service) const;
QString deviceDescription(const QByteArray &service, const QByteArray &device);
-private:
- void updateDevices() const;
-
- mutable QByteArray m_defaultCameraDevice;
- mutable QList<QByteArray> m_cameraDevices;
- mutable QMap<QByteArray, QString> m_cameraDescriptions;
+ QCamera::Position cameraPosition(const QByteArray &device) const;
+ int cameraOrientation(const QByteArray &device) const;
};
QT_END_NAMESPACE
diff --git a/src/plugins/avfoundation/camera/avfcameraserviceplugin.mm b/src/plugins/avfoundation/camera/avfcameraserviceplugin.mm
index 8ec3390e..414a8475 100644
--- a/src/plugins/avfoundation/camera/avfcameraserviceplugin.mm
+++ b/src/plugins/avfoundation/camera/avfcameraserviceplugin.mm
@@ -44,15 +44,12 @@
#include "avfcameraserviceplugin.h"
#include "avfcameraservice.h"
+#include "avfcamerasession.h"
#include <qmediaserviceproviderplugin.h>
-#import <AVFoundation/AVFoundation.h>
-
-
QT_BEGIN_NAMESPACE
-
AVFServicePlugin::AVFServicePlugin()
{
}
@@ -74,56 +71,36 @@ void AVFServicePlugin::release(QMediaService *service)
QByteArray AVFServicePlugin::defaultDevice(const QByteArray &service) const
{
- if (service == Q_MEDIASERVICE_CAMERA) {
- if (m_cameraDevices.isEmpty())
- updateDevices();
-
- return m_defaultCameraDevice;
- }
+ if (service == Q_MEDIASERVICE_CAMERA)
+ return AVFCameraSession::defaultCameraDevice();
return QByteArray();
}
QList<QByteArray> AVFServicePlugin::devices(const QByteArray &service) const
{
- if (service == Q_MEDIASERVICE_CAMERA) {
- if (m_cameraDevices.isEmpty())
- updateDevices();
-
- return m_cameraDevices;
- }
+ if (service == Q_MEDIASERVICE_CAMERA)
+ return AVFCameraSession::availableCameraDevices();
return QList<QByteArray>();
}
QString AVFServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device)
{
- if (service == Q_MEDIASERVICE_CAMERA) {
- if (m_cameraDevices.isEmpty())
- updateDevices();
-
- return m_cameraDescriptions.value(device);
- }
+ if (service == Q_MEDIASERVICE_CAMERA)
+ return AVFCameraSession::cameraDeviceInfo(device).description;
return QString();
}
-void AVFServicePlugin::updateDevices() const
+QCamera::Position AVFServicePlugin::cameraPosition(const QByteArray &device) const
+{
+ return AVFCameraSession::cameraDeviceInfo(device).position;
+}
+
+int AVFServicePlugin::cameraOrientation(const QByteArray &device) const
{
- m_defaultCameraDevice.clear();
- m_cameraDevices.clear();
- m_cameraDescriptions.clear();
-
- AVCaptureDevice *defaultDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
- if (defaultDevice)
- m_defaultCameraDevice = QByteArray([[defaultDevice uniqueID] UTF8String]);
-
- NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
- for (AVCaptureDevice *device in videoDevices) {
- QByteArray deviceId([[device uniqueID] UTF8String]);
- m_cameraDevices << deviceId;
- m_cameraDescriptions.insert(deviceId, QString::fromUtf8([[device localizedName] UTF8String]));
- }
+ return AVFCameraSession::cameraDeviceInfo(device).orientation;
}
QT_END_NAMESPACE
diff --git a/src/plugins/avfoundation/camera/avfcamerasession.h b/src/plugins/avfoundation/camera/avfcamerasession.h
index 2630a35f..5cc779f8 100644
--- a/src/plugins/avfoundation/camera/avfcamerasession.h
+++ b/src/plugins/avfoundation/camera/avfcamerasession.h
@@ -55,6 +55,16 @@ class AVFCameraControl;
class AVFCameraService;
class AVFVideoRendererControl;
+struct AVFCameraInfo
+{
+ AVFCameraInfo() : position(QCamera::UnspecifiedPosition), orientation(0)
+ { }
+
+ QString description;
+ QCamera::Position position;
+ int orientation;
+};
+
class AVFCameraSession : public QObject
{
Q_OBJECT
@@ -62,6 +72,10 @@ public:
AVFCameraSession(AVFCameraService *service, QObject *parent = 0);
~AVFCameraSession();
+ static const QByteArray &defaultCameraDevice();
+ static const QList<QByteArray> &availableCameraDevices();
+ static AVFCameraInfo cameraDeviceInfo(const QByteArray &device);
+
void setVideoOutput(AVFVideoRendererControl *output);
AVCaptureSession *captureSession() const { return m_captureSession; }
AVCaptureDevice *videoCaptureDevice() const;
@@ -84,8 +98,13 @@ Q_SIGNALS:
void error(int error, const QString &errorString);
private:
+ static void updateCameraDevices();
void attachInputDevices();
+ static QByteArray m_defaultCameraDevice;
+ static QList<QByteArray> m_cameraDevices;
+ static QMap<QByteArray, AVFCameraInfo> m_cameraInfo;
+
AVFCameraService *m_service;
AVFVideoRendererControl *m_videoOutput;
diff --git a/src/plugins/avfoundation/camera/avfcamerasession.mm b/src/plugins/avfoundation/camera/avfcamerasession.mm
index 93c2bacd..042855aa 100644
--- a/src/plugins/avfoundation/camera/avfcamerasession.mm
+++ b/src/plugins/avfoundation/camera/avfcamerasession.mm
@@ -57,6 +57,10 @@
QT_USE_NAMESPACE
+QByteArray AVFCameraSession::m_defaultCameraDevice;
+QList<QByteArray> AVFCameraSession::m_cameraDevices;
+QMap<QByteArray, AVFCameraInfo> AVFCameraSession::m_cameraInfo;
+
@interface AVFCameraSessionObserver : NSObject
{
@private
@@ -151,6 +155,74 @@ AVFCameraSession::~AVFCameraSession()
[m_captureSession release];
}
+const QByteArray &AVFCameraSession::defaultCameraDevice()
+{
+ if (m_cameraDevices.isEmpty())
+ updateCameraDevices();
+
+ return m_defaultCameraDevice;
+}
+
+const QList<QByteArray> &AVFCameraSession::availableCameraDevices()
+{
+ if (m_cameraDevices.isEmpty())
+ updateCameraDevices();
+
+ return m_cameraDevices;
+}
+
+AVFCameraInfo AVFCameraSession::cameraDeviceInfo(const QByteArray &device)
+{
+ if (m_cameraDevices.isEmpty())
+ updateCameraDevices();
+
+ return m_cameraInfo.value(device);
+}
+
+void AVFCameraSession::updateCameraDevices()
+{
+ m_defaultCameraDevice.clear();
+ m_cameraDevices.clear();
+ m_cameraInfo.clear();
+
+ AVCaptureDevice *defaultDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
+ if (defaultDevice)
+ m_defaultCameraDevice = QByteArray([[defaultDevice uniqueID] UTF8String]);
+
+ NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
+ for (AVCaptureDevice *device in videoDevices) {
+ QByteArray deviceId([[device uniqueID] UTF8String]);
+
+ AVFCameraInfo info;
+ info.description = QString::fromNSString([device localizedName]);
+
+ // There is no API to get the camera sensor orientation, however, cameras are always
+ // mounted in landscape on iDevices.
+ // - Back-facing cameras have the top side of the sensor aligned with the right side of
+ // the screen when held in portrait ==> 270 degrees clockwise angle
+ // - Front-facing cameras have the top side of the sensor aligned with the left side of
+ // the screen when held in portrait ==> 270 degrees clockwise angle
+ // On Mac OS, the position will always be unspecified and the sensor orientation unknown.
+ switch (device.position) {
+ case AVCaptureDevicePositionBack:
+ info.position = QCamera::BackFace;
+ info.orientation = 270;
+ break;
+ case AVCaptureDevicePositionFront:
+ info.position = QCamera::FrontFace;
+ info.orientation = 270;
+ break;
+ default:
+ info.position = QCamera::UnspecifiedPosition;
+ info.orientation = 0;
+ break;
+ }
+
+ m_cameraDevices << deviceId;
+ m_cameraInfo.insert(deviceId, info);
+ }
+}
+
void AVFCameraSession::setVideoOutput(AVFVideoRendererControl *output)
{
m_videoOutput = output;
diff --git a/src/plugins/avfoundation/camera/avfvideodevicecontrol.h b/src/plugins/avfoundation/camera/avfvideodevicecontrol.h
index fe27906c..4f738022 100644
--- a/src/plugins/avfoundation/camera/avfvideodevicecontrol.h
+++ b/src/plugins/avfoundation/camera/avfvideodevicecontrol.h
@@ -80,9 +80,6 @@ private:
int m_selectedDevice;
bool m_dirty;
- int m_defaultDevice;
- QStringList m_devices;
- QStringList m_deviceDescriptions;
};
QT_END_NAMESPACE
diff --git a/src/plugins/avfoundation/camera/avfvideodevicecontrol.mm b/src/plugins/avfoundation/camera/avfvideodevicecontrol.mm
index 77670754..d049859c 100644
--- a/src/plugins/avfoundation/camera/avfvideodevicecontrol.mm
+++ b/src/plugins/avfoundation/camera/avfvideodevicecontrol.mm
@@ -42,6 +42,7 @@
#include "avfcameradebug.h"
#include "avfvideodevicecontrol.h"
#include "avfcameraservice.h"
+#include "avfcamerasession.h"
QT_USE_NAMESPACE
@@ -50,18 +51,7 @@ AVFVideoDeviceControl::AVFVideoDeviceControl(AVFCameraService *service, QObject
, m_service(service)
, m_selectedDevice(0)
, m_dirty(true)
- , m_defaultDevice(0)
{
- AVCaptureDevice *defaultDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
- NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
- int i = 0;
- for (AVCaptureDevice *device in videoDevices) {
- m_devices << QString::fromUtf8([[device uniqueID] UTF8String]);
- m_deviceDescriptions << QString::fromUtf8([[device localizedName] UTF8String]);
- if (defaultDevice && [[device uniqueID] isEqualToString:[defaultDevice uniqueID]])
- m_defaultDevice = i;
- ++i;
- }
}
AVFVideoDeviceControl::~AVFVideoDeviceControl()
@@ -70,22 +60,30 @@ AVFVideoDeviceControl::~AVFVideoDeviceControl()
int AVFVideoDeviceControl::deviceCount() const
{
- return m_devices.size();
+ return AVFCameraSession::availableCameraDevices().count();
}
QString AVFVideoDeviceControl::deviceName(int index) const
{
- return m_devices[index];
+ const QList<QByteArray> &devices = AVFCameraSession::availableCameraDevices();
+ if (index >= devices.count())
+ return QString();
+
+ return QString::fromUtf8(devices.at(index));
}
QString AVFVideoDeviceControl::deviceDescription(int index) const
{
- return m_deviceDescriptions[index];
+ const QList<QByteArray> &devices = AVFCameraSession::availableCameraDevices();
+ if (index >= devices.count())
+ return QString();
+
+ return AVFCameraSession::cameraDeviceInfo(devices.at(index)).description;
}
int AVFVideoDeviceControl::defaultDevice() const
{
- return m_defaultDevice;
+ return AVFCameraSession::availableCameraDevices().indexOf(AVFCameraSession::defaultCameraDevice());
}
int AVFVideoDeviceControl::selectedDevice() const
@@ -99,7 +97,7 @@ void AVFVideoDeviceControl::setSelectedDevice(int index)
m_dirty = true;
m_selectedDevice = index;
Q_EMIT selectedDeviceChanged(index);
- Q_EMIT selectedDeviceChanged(m_devices[index]);
+ Q_EMIT selectedDeviceChanged(deviceName(index));
}
}
@@ -108,9 +106,8 @@ AVCaptureDevice *AVFVideoDeviceControl::createCaptureDevice()
m_dirty = false;
AVCaptureDevice *device = 0;
- if (!m_devices.isEmpty()) {
- QString deviceId = m_devices.at(m_selectedDevice);
-
+ QString deviceId = deviceName(m_selectedDevice);
+ if (!deviceId.isEmpty()) {
device = [AVCaptureDevice deviceWithUniqueID:
[NSString stringWithUTF8String:
deviceId.toUtf8().constData()]];
diff --git a/src/plugins/avfoundation/camera/camera.pro b/src/plugins/avfoundation/camera/camera.pro
index 791ab8c4..1dac45f8 100644
--- a/src/plugins/avfoundation/camera/camera.pro
+++ b/src/plugins/avfoundation/camera/camera.pro
@@ -34,6 +34,7 @@ HEADERS += \
avfstoragelocation.h \
avfvideodevicecontrol.h \
avfaudioinputselectorcontrol.h \
+ avfcamerainfocontrol.h
OBJECTIVE_SOURCES += \
avfcameraserviceplugin.mm \
@@ -47,4 +48,5 @@ OBJECTIVE_SOURCES += \
avfstoragelocation.mm \
avfvideodevicecontrol.mm \
avfaudioinputselectorcontrol.mm \
+ avfcamerainfocontrol.mm