From 89e6018f6f45350924e3c5f7007f779b9ed4cdeb Mon Sep 17 00:00:00 2001 From: Val Doroshchuk Date: Fri, 27 Jul 2018 12:42:46 +0200 Subject: DirectShow: Postpone setting camera image processing param if not ready Setting camera image processing parameters fails if the graph builder is not ready. We avoid this race condition by having a list of pending parameter changes which is applied when graph builder has been created. Task-number: QTBUG-69143 Change-Id: I5702ea5a2dceacff333fcf8dce05372a0208b8d9 Reviewed-by: Oliver Wolff Reviewed-by: Maurice Kalinowski --- src/plugins/directshow/camera/dscamerasession.cpp | 13 ++++++++++--- src/plugins/directshow/camera/dscamerasession.h | 2 ++ 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'src/plugins/directshow') diff --git a/src/plugins/directshow/camera/dscamerasession.cpp b/src/plugins/directshow/camera/dscamerasession.cpp index ca3c47cb8..324ab44e2 100644 --- a/src/plugins/directshow/camera/dscamerasession.cpp +++ b/src/plugins/directshow/camera/dscamerasession.cpp @@ -208,8 +208,8 @@ QVariant DSCameraSession::imageProcessingParameter( QCameraImageProcessingControl::ProcessingParameter parameter) const { if (!m_graphBuilder) { - qWarning() << "failed to access to the graph builder"; - return QVariant(); + auto it = m_pendingImageProcessingParametrs.find(parameter); + return it != m_pendingImageProcessingParametrs.end() ? it.value() : QVariant(); } const QCameraImageProcessingControl::ProcessingParameter resultingParameter = @@ -249,7 +249,7 @@ void DSCameraSession::setImageProcessingParameter( const QVariant &value) { if (!m_graphBuilder) { - qWarning() << "failed to access to the graph builder"; + m_pendingImageProcessingParametrs.insert(parameter, value); return; } @@ -960,6 +960,13 @@ void DSCameraSession::updateImageProcessingParametersInfos() } pVideoProcAmp->Release(); + + for (auto it = m_pendingImageProcessingParametrs.cbegin(); + it != m_pendingImageProcessingParametrs.cend(); + ++it) { + setImageProcessingParameter(it.key(), it.value()); + } + m_pendingImageProcessingParametrs.clear(); } bool DSCameraSession::connectGraph() diff --git a/src/plugins/directshow/camera/dscamerasession.h b/src/plugins/directshow/camera/dscamerasession.h index 07c3d9ef9..c3be6144e 100644 --- a/src/plugins/directshow/camera/dscamerasession.h +++ b/src/plugins/directshow/camera/dscamerasession.h @@ -230,6 +230,8 @@ private: // Internal state QCamera::Status m_status; + QMap m_pendingImageProcessingParametrs; + friend class SampleGrabberCallbackPrivate; }; -- cgit v1.2.3 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(-) (limited to 'src/plugins/directshow') 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