diff options
author | Yoann Lopes <yoann.lopes@theqtcompany.com> | 2015-04-09 15:14:36 +0200 |
---|---|---|
committer | Timur Pocheptsov <Timur.Pocheptsov@digia.com> | 2015-04-10 09:12:41 +0000 |
commit | def89d71716c7909351f6ccce512a0bff6492417 (patch) | |
tree | 6cae6c457b0ba6adaa73572116ac253b02c6ed9c /src/plugins/avfoundation/camera | |
parent | fa9e829a60bf843c45241b4b99f933ec0532b3c2 (diff) | |
download | qtmultimedia-def89d71716c7909351f6ccce512a0bff6492417.tar.gz |
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/camera')
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 |