summaryrefslogtreecommitdiffstats
path: root/src/plugins/avfoundation
diff options
context:
space:
mode:
authorYoann Lopes <yoann.lopes@theqtcompany.com>2015-04-09 15:14:36 +0200
committerTimur Pocheptsov <Timur.Pocheptsov@digia.com>2015-04-10 09:12:41 +0000
commitdef89d71716c7909351f6ccce512a0bff6492417 (patch)
tree6cae6c457b0ba6adaa73572116ac253b02c6ed9c /src/plugins/avfoundation
parentfa9e829a60bf843c45241b4b99f933ec0532b3c2 (diff)
AVFoundation: fix QCameraInfo::availableCameras() on OS X.
Cameras can be dynamically added or removed on OS X. Make sure the cache is updated often enough so QCameraInfo::availableCameras() return an up to date list. Task-number: QTBUG-39708 Change-Id: Id806d52278e1a29163fcc6707da7f86c0f3e7c0d Reviewed-by: Timur Pocheptsov <Timur.Pocheptsov@digia.com>
Diffstat (limited to 'src/plugins/avfoundation')
-rw-r--r--src/plugins/avfoundation/camera/avfcameraserviceplugin.mm18
-rw-r--r--src/plugins/avfoundation/camera/avfcamerasession.h10
-rw-r--r--src/plugins/avfoundation/camera/avfcamerasession.mm59
-rw-r--r--src/plugins/avfoundation/camera/avfvideodevicecontrol.mm10
4 files changed, 59 insertions, 38 deletions
diff --git a/src/plugins/avfoundation/camera/avfcameraserviceplugin.mm b/src/plugins/avfoundation/camera/avfcameraserviceplugin.mm
index 414a84751..99966f09b 100644
--- a/src/plugins/avfoundation/camera/avfcameraserviceplugin.mm
+++ b/src/plugins/avfoundation/camera/avfcameraserviceplugin.mm
@@ -71,18 +71,26 @@ void AVFServicePlugin::release(QMediaService *service)
QByteArray AVFServicePlugin::defaultDevice(const QByteArray &service) const
{
- if (service == Q_MEDIASERVICE_CAMERA)
- return AVFCameraSession::defaultCameraDevice();
+ if (service == Q_MEDIASERVICE_CAMERA) {
+ int i = AVFCameraSession::defaultCameraIndex();
+ if (i != -1)
+ return AVFCameraSession::availableCameraDevices().at(i).deviceId;
+ }
return QByteArray();
}
QList<QByteArray> AVFServicePlugin::devices(const QByteArray &service) const
{
- if (service == Q_MEDIASERVICE_CAMERA)
- return AVFCameraSession::availableCameraDevices();
+ QList<QByteArray> devs;
+
+ if (service == Q_MEDIASERVICE_CAMERA) {
+ const QList<AVFCameraInfo> &cameras = AVFCameraSession::availableCameraDevices();
+ Q_FOREACH (const AVFCameraInfo &info, cameras)
+ devs.append(info.deviceId);
+ }
- return QList<QByteArray>();
+ return devs;
}
QString AVFServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device)
diff --git a/src/plugins/avfoundation/camera/avfcamerasession.h b/src/plugins/avfoundation/camera/avfcamerasession.h
index 75ca3f4ce..8ce7461df 100644
--- a/src/plugins/avfoundation/camera/avfcamerasession.h
+++ b/src/plugins/avfoundation/camera/avfcamerasession.h
@@ -52,6 +52,7 @@ struct AVFCameraInfo
AVFCameraInfo() : position(QCamera::UnspecifiedPosition), orientation(0)
{ }
+ QByteArray deviceId;
QString description;
QCamera::Position position;
int orientation;
@@ -64,8 +65,8 @@ public:
AVFCameraSession(AVFCameraService *service, QObject *parent = 0);
~AVFCameraSession();
- static const QByteArray &defaultCameraDevice();
- static const QList<QByteArray> &availableCameraDevices();
+ static int defaultCameraIndex();
+ static const QList<AVFCameraInfo> &availableCameraDevices();
static AVFCameraInfo cameraDeviceInfo(const QByteArray &device);
void setVideoOutput(AVFVideoRendererControl *output);
@@ -93,9 +94,8 @@ private:
static void updateCameraDevices();
void attachInputDevices();
- static QByteArray m_defaultCameraDevice;
- static QList<QByteArray> m_cameraDevices;
- static QMap<QByteArray, AVFCameraInfo> m_cameraInfo;
+ static int m_defaultCameraIndex;
+ static QList<AVFCameraInfo> m_cameraDevices;
AVFCameraService *m_service;
AVFVideoRendererControl *m_videoOutput;
diff --git a/src/plugins/avfoundation/camera/avfcamerasession.mm b/src/plugins/avfoundation/camera/avfcamerasession.mm
index a72ef5041..4d4b2f657 100644
--- a/src/plugins/avfoundation/camera/avfcamerasession.mm
+++ b/src/plugins/avfoundation/camera/avfcamerasession.mm
@@ -52,14 +52,14 @@
#include <QtCore/qdatetime.h>
#include <QtCore/qurl.h>
+#include <QtCore/qelapsedtimer.h>
#include <QtCore/qdebug.h>
QT_USE_NAMESPACE
-QByteArray AVFCameraSession::m_defaultCameraDevice;
-QList<QByteArray> AVFCameraSession::m_cameraDevices;
-QMap<QByteArray, AVFCameraInfo> AVFCameraSession::m_cameraInfo;
+int AVFCameraSession::m_defaultCameraIndex;
+QList<AVFCameraInfo> AVFCameraSession::m_cameraDevices;
@interface AVFCameraSessionObserver : NSObject
{
@@ -172,45 +172,55 @@ AVFCameraSession::~AVFCameraSession()
[m_captureSession release];
}
-const QByteArray &AVFCameraSession::defaultCameraDevice()
+int AVFCameraSession::defaultCameraIndex()
{
- if (m_cameraDevices.isEmpty())
- updateCameraDevices();
-
- return m_defaultCameraDevice;
+ updateCameraDevices();
+ return m_defaultCameraIndex;
}
-const QList<QByteArray> &AVFCameraSession::availableCameraDevices()
+const QList<AVFCameraInfo> &AVFCameraSession::availableCameraDevices()
{
- if (m_cameraDevices.isEmpty())
- updateCameraDevices();
-
+ updateCameraDevices();
return m_cameraDevices;
}
AVFCameraInfo AVFCameraSession::cameraDeviceInfo(const QByteArray &device)
{
- if (m_cameraDevices.isEmpty())
- updateCameraDevices();
+ updateCameraDevices();
- return m_cameraInfo.value(device);
+ Q_FOREACH (const AVFCameraInfo &info, m_cameraDevices) {
+ if (info.deviceId == device)
+ return info;
+ }
+
+ return AVFCameraInfo();
}
void AVFCameraSession::updateCameraDevices()
{
- m_defaultCameraDevice.clear();
+#ifdef Q_OS_IOS
+ // Cameras can't change dynamically on iOS. Update only once.
+ if (!m_cameraDevices.isEmpty())
+ return;
+#else
+ // On OS X, cameras can be added or removed. Update the list every time, but not more than
+ // once every 500 ms
+ static QElapsedTimer timer;
+ if (timer.isValid() && timer.elapsed() < 500) // ms
+ return;
+#endif
+
+ m_defaultCameraIndex = -1;
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]);
+ if (defaultDevice && [defaultDevice.uniqueID isEqualToString:device.uniqueID])
+ m_defaultCameraIndex = m_cameraDevices.count();
AVFCameraInfo info;
+ info.deviceId = QByteArray([[device uniqueID] UTF8String]);
info.description = QString::fromNSString([device localizedName]);
// There is no API to get the camera sensor orientation, however, cameras are always
@@ -235,9 +245,12 @@ void AVFCameraSession::updateCameraDevices()
break;
}
- m_cameraDevices << deviceId;
- m_cameraInfo.insert(deviceId, info);
+ m_cameraDevices.append(info);
}
+
+#ifndef Q_OS_IOS
+ timer.restart();
+#endif
}
void AVFCameraSession::setVideoOutput(AVFVideoRendererControl *output)
diff --git a/src/plugins/avfoundation/camera/avfvideodevicecontrol.mm b/src/plugins/avfoundation/camera/avfvideodevicecontrol.mm
index 03736c395..1730437f8 100644
--- a/src/plugins/avfoundation/camera/avfvideodevicecontrol.mm
+++ b/src/plugins/avfoundation/camera/avfvideodevicecontrol.mm
@@ -65,25 +65,25 @@ int AVFVideoDeviceControl::deviceCount() const
QString AVFVideoDeviceControl::deviceName(int index) const
{
- const QList<QByteArray> &devices = AVFCameraSession::availableCameraDevices();
+ const QList<AVFCameraInfo> &devices = AVFCameraSession::availableCameraDevices();
if (index < 0 || index >= devices.count())
return QString();
- return QString::fromUtf8(devices.at(index));
+ return QString::fromUtf8(devices.at(index).deviceId);
}
QString AVFVideoDeviceControl::deviceDescription(int index) const
{
- const QList<QByteArray> &devices = AVFCameraSession::availableCameraDevices();
+ const QList<AVFCameraInfo> &devices = AVFCameraSession::availableCameraDevices();
if (index < 0 || index >= devices.count())
return QString();
- return AVFCameraSession::cameraDeviceInfo(devices.at(index)).description;
+ return devices.at(index).description;
}
int AVFVideoDeviceControl::defaultDevice() const
{
- return AVFCameraSession::availableCameraDevices().indexOf(AVFCameraSession::defaultCameraDevice());
+ return AVFCameraSession::defaultCameraIndex();
}
int AVFVideoDeviceControl::selectedDevice() const