summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVal Doroshchuk <valentyn.doroshchuk@qt.io>2018-05-09 13:50:16 +0200
committerVaL Doroshchuk <valentyn.doroshchuk@qt.io>2018-08-02 09:21:16 +0000
commit1b58b96bdf32ab9a89cba0ae43170804c0571ede (patch)
treea5e1ad28d95f9c1198c0fec17dbf31ee093fc189
parent89e6018f6f45350924e3c5f7007f779b9ed4cdeb (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.cpp8
-rw-r--r--src/plugins/directshow/camera/dscamerasession.cpp28
-rw-r--r--src/plugins/directshow/camera/dscamerasession.h3
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, &param1, &param2, 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;