DirectShow: correctly update camera list.
8923c0ff fixed the list not being updated after plugging/unplugging a
camera from the system. However, it was only a partial fix affecting
only QCameraInfo::availableCameras(). DSVideoDeviceControl was still
internally keeping a list of cameras that was never updated, causing
the QCamera constructor to not take into account new or removed
cameras.
Change-Id: Ie5e79c46002017b1e85bfc53c6391a2a747361a0
Task-number: QTBUG-39708
Reviewed-by: Christian Stromme <christian.stromme@theqtcompany.com>
This commit is contained in:
@@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include <qelapsedtimer.h>
|
||||||
|
|
||||||
#include "dsvideodevicecontrol.h"
|
#include "dsvideodevicecontrol.h"
|
||||||
#include "dscamerasession.h"
|
#include "dscamerasession.h"
|
||||||
@@ -48,33 +49,37 @@ extern const CLSID CLSID_VideoInputDeviceCategory;
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
Q_GLOBAL_STATIC(QList<DSVideoDeviceInfo>, deviceList)
|
||||||
|
|
||||||
DSVideoDeviceControl::DSVideoDeviceControl(QObject *parent)
|
DSVideoDeviceControl::DSVideoDeviceControl(QObject *parent)
|
||||||
: QVideoDeviceSelectorControl(parent)
|
: QVideoDeviceSelectorControl(parent)
|
||||||
{
|
{
|
||||||
m_session = qobject_cast<DSCameraSession*>(parent);
|
m_session = qobject_cast<DSCameraSession*>(parent);
|
||||||
|
|
||||||
enumerateDevices(&m_devices, &m_descriptions);
|
|
||||||
|
|
||||||
selected = 0;
|
selected = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DSVideoDeviceControl::deviceCount() const
|
int DSVideoDeviceControl::deviceCount() const
|
||||||
{
|
{
|
||||||
return m_devices.count();
|
updateDevices();
|
||||||
|
return deviceList->count();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString DSVideoDeviceControl::deviceName(int index) const
|
QString DSVideoDeviceControl::deviceName(int index) const
|
||||||
{
|
{
|
||||||
if (index >= 0 && index <= m_devices.count())
|
updateDevices();
|
||||||
return QString::fromUtf8(m_devices.at(index).constData());
|
|
||||||
|
if (index >= 0 && index <= deviceList->count())
|
||||||
|
return QString::fromUtf8(deviceList->at(index).first.constData());
|
||||||
|
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString DSVideoDeviceControl::deviceDescription(int index) const
|
QString DSVideoDeviceControl::deviceDescription(int index) const
|
||||||
{
|
{
|
||||||
if (index >= 0 && index <= m_descriptions.count())
|
updateDevices();
|
||||||
return m_descriptions.at(index);
|
|
||||||
|
if (index >= 0 && index <= deviceList->count())
|
||||||
|
return deviceList->at(index).second;
|
||||||
|
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
@@ -89,10 +94,34 @@ int DSVideoDeviceControl::selectedDevice() const
|
|||||||
return selected;
|
return selected;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSVideoDeviceControl::enumerateDevices(QList<QByteArray> *devices, QStringList *descriptions)
|
void DSVideoDeviceControl::setSelectedDevice(int index)
|
||||||
{
|
{
|
||||||
devices->clear();
|
updateDevices();
|
||||||
descriptions->clear();
|
|
||||||
|
if (index >= 0 && index < deviceList->count()) {
|
||||||
|
if (m_session) {
|
||||||
|
QString device = deviceList->at(index).first;
|
||||||
|
if (device.startsWith("ds:"))
|
||||||
|
device.remove(0,3);
|
||||||
|
m_session->setDevice(device);
|
||||||
|
}
|
||||||
|
selected = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const QList<DSVideoDeviceInfo> &DSVideoDeviceControl::availableDevices()
|
||||||
|
{
|
||||||
|
updateDevices();
|
||||||
|
return *deviceList;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DSVideoDeviceControl::updateDevices()
|
||||||
|
{
|
||||||
|
static QElapsedTimer timer;
|
||||||
|
if (timer.isValid() && timer.elapsed() < 500) // ms
|
||||||
|
return;
|
||||||
|
|
||||||
|
deviceList->clear();
|
||||||
|
|
||||||
ICreateDevEnum* pDevEnum = NULL;
|
ICreateDevEnum* pDevEnum = NULL;
|
||||||
IEnumMoniker* pEnum = NULL;
|
IEnumMoniker* pEnum = NULL;
|
||||||
@@ -116,7 +145,9 @@ void DSVideoDeviceControl::enumerateDevices(QList<QByteArray> *devices, QStringL
|
|||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
QString output(QString::fromWCharArray(strName));
|
QString output(QString::fromWCharArray(strName));
|
||||||
mallocInterface->Free(strName);
|
mallocInterface->Free(strName);
|
||||||
devices->append(output.toUtf8().constData());
|
|
||||||
|
DSVideoDeviceInfo devInfo;
|
||||||
|
devInfo.first = output.toUtf8();
|
||||||
|
|
||||||
IPropertyBag *pPropBag;
|
IPropertyBag *pPropBag;
|
||||||
hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)(&pPropBag));
|
hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)(&pPropBag));
|
||||||
@@ -130,7 +161,9 @@ void DSVideoDeviceControl::enumerateDevices(QList<QByteArray> *devices, QStringL
|
|||||||
}
|
}
|
||||||
pPropBag->Release();
|
pPropBag->Release();
|
||||||
}
|
}
|
||||||
descriptions->append(output);
|
devInfo.second = output;
|
||||||
|
|
||||||
|
deviceList->append(devInfo);
|
||||||
}
|
}
|
||||||
pMoniker->Release();
|
pMoniker->Release();
|
||||||
}
|
}
|
||||||
@@ -139,19 +172,8 @@ void DSVideoDeviceControl::enumerateDevices(QList<QByteArray> *devices, QStringL
|
|||||||
}
|
}
|
||||||
pDevEnum->Release();
|
pDevEnum->Release();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void DSVideoDeviceControl::setSelectedDevice(int index)
|
timer.restart();
|
||||||
{
|
|
||||||
if (index >= 0 && index < m_devices.count()) {
|
|
||||||
if (m_session) {
|
|
||||||
QString device = m_devices.at(index);
|
|
||||||
if (device.startsWith("ds:"))
|
|
||||||
device.remove(0,3);
|
|
||||||
m_session->setDevice(device);
|
|
||||||
}
|
|
||||||
selected = index;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ class DSCameraSession;
|
|||||||
|
|
||||||
//QTM_USE_NAMESPACE
|
//QTM_USE_NAMESPACE
|
||||||
|
|
||||||
|
typedef QPair<QByteArray, QString> DSVideoDeviceInfo;
|
||||||
|
|
||||||
class DSVideoDeviceControl : public QVideoDeviceSelectorControl
|
class DSVideoDeviceControl : public QVideoDeviceSelectorControl
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -54,17 +56,15 @@ public:
|
|||||||
int defaultDevice() const;
|
int defaultDevice() const;
|
||||||
int selectedDevice() const;
|
int selectedDevice() const;
|
||||||
|
|
||||||
static void enumerateDevices(QList<QByteArray> *devices, QStringList *descriptions);
|
static const QList<DSVideoDeviceInfo> &availableDevices();
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void setSelectedDevice(int index);
|
void setSelectedDevice(int index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static void updateDevices();
|
||||||
|
|
||||||
DSCameraSession* m_session;
|
DSCameraSession* m_session;
|
||||||
|
|
||||||
QList<QByteArray> m_devices;
|
|
||||||
QStringList m_descriptions;
|
|
||||||
|
|
||||||
int selected;
|
int selected;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,6 @@
|
|||||||
#include "dsvideodevicecontrol.h"
|
#include "dsvideodevicecontrol.h"
|
||||||
|
|
||||||
#ifdef QMEDIA_DIRECTSHOW_CAMERA
|
#ifdef QMEDIA_DIRECTSHOW_CAMERA
|
||||||
#include <QtCore/QElapsedTimer>
|
|
||||||
#include <dshow.h>
|
#include <dshow.h>
|
||||||
#include "dscameraservice.h"
|
#include "dscameraservice.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -122,9 +121,9 @@ QByteArray DSServicePlugin::defaultDevice(const QByteArray &service) const
|
|||||||
{
|
{
|
||||||
#ifdef QMEDIA_DIRECTSHOW_CAMERA
|
#ifdef QMEDIA_DIRECTSHOW_CAMERA
|
||||||
if (service == Q_MEDIASERVICE_CAMERA) {
|
if (service == Q_MEDIASERVICE_CAMERA) {
|
||||||
updateDevices();
|
const QList<DSVideoDeviceInfo> &devs = DSVideoDeviceControl::availableDevices();
|
||||||
|
if (!devs.isEmpty())
|
||||||
return m_defaultCameraDevice;
|
return devs.first().first;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -133,52 +132,29 @@ QByteArray DSServicePlugin::defaultDevice(const QByteArray &service) const
|
|||||||
|
|
||||||
QList<QByteArray> DSServicePlugin::devices(const QByteArray &service) const
|
QList<QByteArray> DSServicePlugin::devices(const QByteArray &service) const
|
||||||
{
|
{
|
||||||
|
QList<QByteArray> result;
|
||||||
|
|
||||||
#ifdef QMEDIA_DIRECTSHOW_CAMERA
|
#ifdef QMEDIA_DIRECTSHOW_CAMERA
|
||||||
if (service == Q_MEDIASERVICE_CAMERA) {
|
if (service == Q_MEDIASERVICE_CAMERA) {
|
||||||
updateDevices();
|
const QList<DSVideoDeviceInfo> &devs = DSVideoDeviceControl::availableDevices();
|
||||||
|
Q_FOREACH (const DSVideoDeviceInfo &info, devs)
|
||||||
return m_cameraDevices;
|
result.append(info.first);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return QList<QByteArray>();
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString DSServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device)
|
QString DSServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device)
|
||||||
{
|
{
|
||||||
#ifdef QMEDIA_DIRECTSHOW_CAMERA
|
#ifdef QMEDIA_DIRECTSHOW_CAMERA
|
||||||
if (service == Q_MEDIASERVICE_CAMERA) {
|
if (service == Q_MEDIASERVICE_CAMERA) {
|
||||||
updateDevices();
|
const QList<DSVideoDeviceInfo> &devs = DSVideoDeviceControl::availableDevices();
|
||||||
|
Q_FOREACH (const DSVideoDeviceInfo &info, devs) {
|
||||||
for (int i=0; i<m_cameraDevices.count(); i++)
|
if (info.first == device)
|
||||||
if (m_cameraDevices[i] == device)
|
return info.second;
|
||||||
return m_cameraDescriptions[i];
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef QMEDIA_DIRECTSHOW_CAMERA
|
|
||||||
|
|
||||||
void DSServicePlugin::updateDevices() const
|
|
||||||
{
|
|
||||||
static QElapsedTimer timer;
|
|
||||||
if (timer.isValid() && timer.elapsed() < 500) // ms
|
|
||||||
return;
|
|
||||||
|
|
||||||
addRefCount();
|
|
||||||
|
|
||||||
m_defaultCameraDevice.clear();
|
|
||||||
DSVideoDeviceControl::enumerateDevices(&m_cameraDevices, &m_cameraDescriptions);
|
|
||||||
|
|
||||||
if (m_cameraDevices.isEmpty()) {
|
|
||||||
qWarning() << "No camera devices found";
|
|
||||||
} else {
|
|
||||||
m_defaultCameraDevice = m_cameraDevices.first();
|
|
||||||
}
|
|
||||||
|
|
||||||
releaseRefCount();
|
|
||||||
timer.restart();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|||||||
@@ -65,15 +65,6 @@ public:
|
|||||||
QByteArray defaultDevice(const QByteArray &service) const;
|
QByteArray defaultDevice(const QByteArray &service) const;
|
||||||
QList<QByteArray> devices(const QByteArray &service) const;
|
QList<QByteArray> devices(const QByteArray &service) const;
|
||||||
QString deviceDescription(const QByteArray &service, const QByteArray &device);
|
QString deviceDescription(const QByteArray &service, const QByteArray &device);
|
||||||
|
|
||||||
private:
|
|
||||||
#ifdef QMEDIA_DIRECTSHOW_CAMERA
|
|
||||||
void updateDevices() const;
|
|
||||||
|
|
||||||
mutable QByteArray m_defaultCameraDevice;
|
|
||||||
mutable QList<QByteArray> m_cameraDevices;
|
|
||||||
mutable QStringList m_cameraDescriptions;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DSSERVICEPLUGIN_H
|
#endif // DSSERVICEPLUGIN_H
|
||||||
|
|||||||
Reference in New Issue
Block a user