diff options
author | Val Doroshchuk <valentyn.doroshchuk@qt.io> | 2018-05-09 13:50:16 +0200 |
---|---|---|
committer | VaL Doroshchuk <valentyn.doroshchuk@qt.io> | 2018-08-02 09:21:16 +0000 |
commit | 1b58b96bdf32ab9a89cba0ae43170804c0571ede (patch) | |
tree | a5e1ad28d95f9c1198c0fec17dbf31ee093fc189 | |
parent | 89e6018f6f45350924e3c5f7007f779b9ed4cdeb (diff) |
DirectShow: Notify if camera has been unplugged
If being used camera has been disconnected, state and status will
remain like it is still active. Also no events are sent.
Previously to fix this the camera needed to be unloaded and loaded again manually.
IMediaEvent provides an ability to catch device removal notification
with EC_DEVICE_LOST event.
Since ISampleGrabber is used to get buffers.
Added a fix to check if no buffers received for some time
afterwards check for EC_DEVICE_LOST event.
In case if the device is lost, the camera should be unloaded.
Change-Id: I3a5edf00ce8ee25d8b06800fdad833a722bdba0d
Task-number: QTBUG-68035
Reviewed-by: VaL Doroshchuk <valentyn.doroshchuk@qt.io>
Reviewed-by: Maurice Kalinowski <maurice.kalinowski@qt.io>
-rw-r--r-- | src/plugins/directshow/camera/dscameracontrol.cpp | 8 | ||||
-rw-r--r-- | src/plugins/directshow/camera/dscamerasession.cpp | 28 | ||||
-rw-r--r-- | src/plugins/directshow/camera/dscamerasession.h | 3 |
3 files changed, 36 insertions, 3 deletions
diff --git a/src/plugins/directshow/camera/dscameracontrol.cpp b/src/plugins/directshow/camera/dscameracontrol.cpp index 8d923da9f..7a2b46a2c 100644 --- a/src/plugins/directshow/camera/dscameracontrol.cpp +++ b/src/plugins/directshow/camera/dscameracontrol.cpp @@ -51,8 +51,12 @@ DSCameraControl::DSCameraControl(QObject *parent) , m_captureMode(QCamera::CaptureStillImage) { m_session = qobject_cast<DSCameraSession*>(parent); - connect(m_session, SIGNAL(statusChanged(QCamera::Status)), - this, SIGNAL(statusChanged(QCamera::Status))); + connect(m_session, &DSCameraSession::statusChanged, + [&](QCamera::Status status) { + if (status == QCamera::UnloadedStatus) + m_state = QCamera::UnloadedState; + emit statusChanged(status); + }); connect(m_session, &DSCameraSession::cameraError, this, &DSCameraControl::error); } diff --git a/src/plugins/directshow/camera/dscamerasession.cpp b/src/plugins/directshow/camera/dscamerasession.cpp index 324ab44e2..c309359ed 100644 --- a/src/plugins/directshow/camera/dscamerasession.cpp +++ b/src/plugins/directshow/camera/dscamerasession.cpp @@ -76,6 +76,30 @@ DSCameraSession::DSCameraSession(QObject *parent) { connect(this, SIGNAL(statusChanged(QCamera::Status)), this, SLOT(updateReadyForCapture())); + + m_deviceLostEventTimer.setSingleShot(true); + connect(&m_deviceLostEventTimer, &QTimer::timeout, [&]() { + IMediaEvent *pEvent = com_cast<IMediaEvent>(m_filterGraph, IID_IMediaEvent); + if (!pEvent) + return; + + long eventCode; + LONG_PTR param1; + LONG_PTR param2; + while (pEvent->GetEvent(&eventCode, ¶m1, ¶m2, 0) == S_OK) { + switch (eventCode) { + case EC_DEVICE_LOST: + unload(); + break; + default: + break; + } + + pEvent->FreeEventParams(eventCode, param1, param2); + } + + pEvent->Release(); + }); } DSCameraSession::~DSCameraSession() @@ -582,6 +606,10 @@ void DSCameraSession::onFrameAvailable(double time, const QByteArray &data) m_presentMutex.lock(); + // If no frames provided from ISampleGrabber for some time + // the device might be potentially unplugged. + m_deviceLostEventTimer.start(100); + // (We should be getting only RGB32 data) int stride = m_previewSize.width() * 4; diff --git a/src/plugins/directshow/camera/dscamerasession.h b/src/plugins/directshow/camera/dscamerasession.h index c3be6144e..433db8994 100644 --- a/src/plugins/directshow/camera/dscamerasession.h +++ b/src/plugins/directshow/camera/dscamerasession.h @@ -44,7 +44,7 @@ #include <QTime> #include <QUrl> #include <QMutex> - +#include <QTimer> #include <qcamera.h> #include <QtMultimedia/qvideoframe.h> #include <QtMultimedia/qabstractvideosurface.h> @@ -229,6 +229,7 @@ private: // Internal state QCamera::Status m_status; + QTimer m_deviceLostEventTimer; QMap<QCameraImageProcessingControl::ProcessingParameter, QVariant> m_pendingImageProcessingParametrs; |