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
|
QByteArray AVFServicePlugin::defaultDevice(const QByteArray &service) const
|
||||||
{
|
{
|
||||||
if (service == Q_MEDIASERVICE_CAMERA)
|
if (service == Q_MEDIASERVICE_CAMERA) {
|
||||||
return AVFCameraSession::defaultCameraDevice();
|
int i = AVFCameraSession::defaultCameraIndex();
|
||||||
|
if (i != -1)
|
||||||
|
return AVFCameraSession::availableCameraDevices().at(i).deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
return QByteArray();
|
return QByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QByteArray> AVFServicePlugin::devices(const QByteArray &service) const
|
QList<QByteArray> AVFServicePlugin::devices(const QByteArray &service) const
|
||||||
{
|
{
|
||||||
if (service == Q_MEDIASERVICE_CAMERA)
|
QList<QByteArray> devs;
|
||||||
return AVFCameraSession::availableCameraDevices();
|
|
||||||
|
|
||||||
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)
|
QString AVFServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device)
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ struct AVFCameraInfo
|
|||||||
AVFCameraInfo() : position(QCamera::UnspecifiedPosition), orientation(0)
|
AVFCameraInfo() : position(QCamera::UnspecifiedPosition), orientation(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
QByteArray deviceId;
|
||||||
QString description;
|
QString description;
|
||||||
QCamera::Position position;
|
QCamera::Position position;
|
||||||
int orientation;
|
int orientation;
|
||||||
@@ -64,8 +65,8 @@ public:
|
|||||||
AVFCameraSession(AVFCameraService *service, QObject *parent = 0);
|
AVFCameraSession(AVFCameraService *service, QObject *parent = 0);
|
||||||
~AVFCameraSession();
|
~AVFCameraSession();
|
||||||
|
|
||||||
static const QByteArray &defaultCameraDevice();
|
static int defaultCameraIndex();
|
||||||
static const QList<QByteArray> &availableCameraDevices();
|
static const QList<AVFCameraInfo> &availableCameraDevices();
|
||||||
static AVFCameraInfo cameraDeviceInfo(const QByteArray &device);
|
static AVFCameraInfo cameraDeviceInfo(const QByteArray &device);
|
||||||
|
|
||||||
void setVideoOutput(AVFVideoRendererControl *output);
|
void setVideoOutput(AVFVideoRendererControl *output);
|
||||||
@@ -93,9 +94,8 @@ private:
|
|||||||
static void updateCameraDevices();
|
static void updateCameraDevices();
|
||||||
void attachInputDevices();
|
void attachInputDevices();
|
||||||
|
|
||||||
static QByteArray m_defaultCameraDevice;
|
static int m_defaultCameraIndex;
|
||||||
static QList<QByteArray> m_cameraDevices;
|
static QList<AVFCameraInfo> m_cameraDevices;
|
||||||
static QMap<QByteArray, AVFCameraInfo> m_cameraInfo;
|
|
||||||
|
|
||||||
AVFCameraService *m_service;
|
AVFCameraService *m_service;
|
||||||
AVFVideoRendererControl *m_videoOutput;
|
AVFVideoRendererControl *m_videoOutput;
|
||||||
|
|||||||
@@ -52,14 +52,14 @@
|
|||||||
|
|
||||||
#include <QtCore/qdatetime.h>
|
#include <QtCore/qdatetime.h>
|
||||||
#include <QtCore/qurl.h>
|
#include <QtCore/qurl.h>
|
||||||
|
#include <QtCore/qelapsedtimer.h>
|
||||||
|
|
||||||
#include <QtCore/qdebug.h>
|
#include <QtCore/qdebug.h>
|
||||||
|
|
||||||
QT_USE_NAMESPACE
|
QT_USE_NAMESPACE
|
||||||
|
|
||||||
QByteArray AVFCameraSession::m_defaultCameraDevice;
|
int AVFCameraSession::m_defaultCameraIndex;
|
||||||
QList<QByteArray> AVFCameraSession::m_cameraDevices;
|
QList<AVFCameraInfo> AVFCameraSession::m_cameraDevices;
|
||||||
QMap<QByteArray, AVFCameraInfo> AVFCameraSession::m_cameraInfo;
|
|
||||||
|
|
||||||
@interface AVFCameraSessionObserver : NSObject
|
@interface AVFCameraSessionObserver : NSObject
|
||||||
{
|
{
|
||||||
@@ -172,45 +172,55 @@ AVFCameraSession::~AVFCameraSession()
|
|||||||
[m_captureSession release];
|
[m_captureSession release];
|
||||||
}
|
}
|
||||||
|
|
||||||
const QByteArray &AVFCameraSession::defaultCameraDevice()
|
int AVFCameraSession::defaultCameraIndex()
|
||||||
{
|
{
|
||||||
if (m_cameraDevices.isEmpty())
|
updateCameraDevices();
|
||||||
updateCameraDevices();
|
return m_defaultCameraIndex;
|
||||||
|
|
||||||
return m_defaultCameraDevice;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const QList<QByteArray> &AVFCameraSession::availableCameraDevices()
|
const QList<AVFCameraInfo> &AVFCameraSession::availableCameraDevices()
|
||||||
{
|
{
|
||||||
if (m_cameraDevices.isEmpty())
|
updateCameraDevices();
|
||||||
updateCameraDevices();
|
|
||||||
|
|
||||||
return m_cameraDevices;
|
return m_cameraDevices;
|
||||||
}
|
}
|
||||||
|
|
||||||
AVFCameraInfo AVFCameraSession::cameraDeviceInfo(const QByteArray &device)
|
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()
|
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_cameraDevices.clear();
|
||||||
m_cameraInfo.clear();
|
|
||||||
|
|
||||||
AVCaptureDevice *defaultDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
|
AVCaptureDevice *defaultDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
|
||||||
if (defaultDevice)
|
|
||||||
m_defaultCameraDevice = QByteArray([[defaultDevice uniqueID] UTF8String]);
|
|
||||||
|
|
||||||
NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
|
NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
|
||||||
for (AVCaptureDevice *device in videoDevices) {
|
for (AVCaptureDevice *device in videoDevices) {
|
||||||
QByteArray deviceId([[device uniqueID] UTF8String]);
|
if (defaultDevice && [defaultDevice.uniqueID isEqualToString:device.uniqueID])
|
||||||
|
m_defaultCameraIndex = m_cameraDevices.count();
|
||||||
|
|
||||||
AVFCameraInfo info;
|
AVFCameraInfo info;
|
||||||
|
info.deviceId = QByteArray([[device uniqueID] UTF8String]);
|
||||||
info.description = QString::fromNSString([device localizedName]);
|
info.description = QString::fromNSString([device localizedName]);
|
||||||
|
|
||||||
// There is no API to get the camera sensor orientation, however, cameras are always
|
// There is no API to get the camera sensor orientation, however, cameras are always
|
||||||
@@ -235,9 +245,12 @@ void AVFCameraSession::updateCameraDevices()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_cameraDevices << deviceId;
|
m_cameraDevices.append(info);
|
||||||
m_cameraInfo.insert(deviceId, info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef Q_OS_IOS
|
||||||
|
timer.restart();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void AVFCameraSession::setVideoOutput(AVFVideoRendererControl *output)
|
void AVFCameraSession::setVideoOutput(AVFVideoRendererControl *output)
|
||||||
|
|||||||
@@ -65,25 +65,25 @@ int AVFVideoDeviceControl::deviceCount() const
|
|||||||
|
|
||||||
QString AVFVideoDeviceControl::deviceName(int index) 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())
|
if (index < 0 || index >= devices.count())
|
||||||
return QString();
|
return QString();
|
||||||
|
|
||||||
return QString::fromUtf8(devices.at(index));
|
return QString::fromUtf8(devices.at(index).deviceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString AVFVideoDeviceControl::deviceDescription(int index) const
|
QString AVFVideoDeviceControl::deviceDescription(int index) const
|
||||||
{
|
{
|
||||||
const QList<QByteArray> &devices = AVFCameraSession::availableCameraDevices();
|
const QList<AVFCameraInfo> &devices = AVFCameraSession::availableCameraDevices();
|
||||||
if (index < 0 || index >= devices.count())
|
if (index < 0 || index >= devices.count())
|
||||||
return QString();
|
return QString();
|
||||||
|
|
||||||
return AVFCameraSession::cameraDeviceInfo(devices.at(index)).description;
|
return devices.at(index).description;
|
||||||
}
|
}
|
||||||
|
|
||||||
int AVFVideoDeviceControl::defaultDevice() const
|
int AVFVideoDeviceControl::defaultDevice() const
|
||||||
{
|
{
|
||||||
return AVFCameraSession::availableCameraDevices().indexOf(AVFCameraSession::defaultCameraDevice());
|
return AVFCameraSession::defaultCameraIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
int AVFVideoDeviceControl::selectedDevice() const
|
int AVFVideoDeviceControl::selectedDevice() const
|
||||||
|
|||||||
Reference in New Issue
Block a user