From 1b58b96bdf32ab9a89cba0ae43170804c0571ede Mon Sep 17 00:00:00 2001 From: Val Doroshchuk Date: Wed, 9 May 2018 13:50:16 +0200 Subject: 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 Reviewed-by: Maurice Kalinowski --- src/plugins/directshow/camera/dscameracontrol.cpp | 8 +++++-- src/plugins/directshow/camera/dscamerasession.cpp | 28 +++++++++++++++++++++++ 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(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(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 #include #include - +#include #include #include #include @@ -229,6 +229,7 @@ private: // Internal state QCamera::Status m_status; + QTimer m_deviceLostEventTimer; QMap m_pendingImageProcessingParametrs; -- cgit v1.2.3