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>
This commit is contained in:
committed by
Timur Pocheptsov
parent
fa9e829a60
commit
def89d7171
@@ -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;
|
||||
|
||||
return QList<QByteArray>();
|
||||
if (service == Q_MEDIASERVICE_CAMERA) {
|
||||
const QList<AVFCameraInfo> &cameras = AVFCameraSession::availableCameraDevices();
|
||||
Q_FOREACH (const AVFCameraInfo &info, cameras)
|
||||
devs.append(info.deviceId);
|
||||
}
|
||||
|
||||
return devs;
|
||||
}
|
||||
|
||||
QString AVFServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user