From 528588f9f106f25bbf95f632e79106774319079a Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Mon, 11 Jul 2016 16:07:21 +0200 Subject: DirectShow: fix possible deadlock when capturing camera image Don't emit signals while mutexes are locked. Task-number: QTBUG-41573 Change-Id: I287b031a579cbec1cd178501df4426ceff9e9142 Reviewed-by: Christian Stromme Reviewed-by: Ruslan Vorobei --- src/plugins/directshow/camera/dscamerasession.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'src/plugins/directshow/camera') diff --git a/src/plugins/directshow/camera/dscamerasession.cpp b/src/plugins/directshow/camera/dscamerasession.cpp index 3421f2cd1..1cb91cd4a 100644 --- a/src/plugins/directshow/camera/dscamerasession.cpp +++ b/src/plugins/directshow/camera/dscamerasession.cpp @@ -662,7 +662,7 @@ void DSCameraSession::onFrameAvailable(const char *frameData, long len) QMutexLocker locker(&m_captureMutex); if (m_currentImageId != -1 && !m_capturedFrame.isValid()) { m_capturedFrame = m_currentFrame; - emit imageExposed(m_currentImageId); + QMetaObject::invokeMethod(this, "imageExposed", Qt::QueuedConnection, Q_ARG(int, m_currentImageId)); } QMetaObject::invokeMethod(this, "presentFrame", Qt::QueuedConnection); @@ -679,6 +679,9 @@ void DSCameraSession::presentFrame() m_presentMutex.unlock(); + QImage captureImage; + int captureId; + m_captureMutex.lock(); if (m_capturedFrame.isValid()) { @@ -686,27 +689,31 @@ void DSCameraSession::presentFrame() m_capturedFrame.map(QAbstractVideoBuffer::ReadOnly); - QImage image = QImage(m_capturedFrame.bits(), - m_previewSize.width(), m_previewSize.height(), - QImage::Format_RGB32); + captureImage = QImage(m_capturedFrame.bits(), + m_previewSize.width(), m_previewSize.height(), + QImage::Format_RGB32); - image = image.mirrored(m_needsHorizontalMirroring); // also causes a deep copy of the data + captureImage = captureImage.mirrored(m_needsHorizontalMirroring); // also causes a deep copy of the data m_capturedFrame.unmap(); - emit imageCaptured(m_currentImageId, image); + captureId = m_currentImageId; QtConcurrent::run(this, &DSCameraSession::saveCapturedImage, - m_currentImageId, image, m_imageCaptureFileName); + m_currentImageId, captureImage, m_imageCaptureFileName); m_imageCaptureFileName.clear(); m_currentImageId = -1; - updateReadyForCapture(); m_capturedFrame = QVideoFrame(); } m_captureMutex.unlock(); + + if (!captureImage.isNull()) + emit imageCaptured(captureId, captureImage); + + updateReadyForCapture(); } void DSCameraSession::saveCapturedImage(int id, const QImage &image, const QString &path) -- cgit v1.2.3