diff options
author | Tim Blechmann <tim@klingt.org> | 2024-04-29 17:11:18 +0800 |
---|---|---|
committer | Tim Blechmann <tim@klingt.org> | 2024-05-17 14:32:50 +0800 |
commit | c3c0bb446ffff8f82dd18e724c4a54b89533a12c (patch) | |
tree | 52eea0c39c31293ea746eb496cb4eec5fed4582d /src | |
parent | c3655553e0c9e1a77fe54252a9b897fd9fa943db (diff) |
GStreamer: QGstreamerImageCapture - emit signals from app thread
When emitting signals on QPlatformImageCapture, we need to make sure
they are invoked on the thread. So we defer the invocations when
emitting from a worker thread to the thread owning
`QGstreamerImageCapture`.
This also makes sure that we don't emit signals while holding a mutex.
Pick-to: 6.5 6.7
Change-Id: If53ae5622d2a3d62a146afa3f9b6585909967069
Reviewed-by: Jøger Hansegård <joger.hansegard@qt.io>
Reviewed-by: Artem Dyomin <artem.dyomin@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/multimedia/gstreamer/mediacapture/qgstreamerimagecapture.cpp | 91 | ||||
-rw-r--r-- | src/plugins/multimedia/gstreamer/mediacapture/qgstreamerimagecapture_p.h | 6 |
2 files changed, 52 insertions, 45 deletions
diff --git a/src/plugins/multimedia/gstreamer/mediacapture/qgstreamerimagecapture.cpp b/src/plugins/multimedia/gstreamer/mediacapture/qgstreamerimagecapture.cpp index dca64e265..f1f336200 100644 --- a/src/plugins/multimedia/gstreamer/mediacapture/qgstreamerimagecapture.cpp +++ b/src/plugins/multimedia/gstreamer/mediacapture/qgstreamerimagecapture.cpp @@ -111,44 +111,40 @@ int QGstreamerImageCapture::doCapture(const QString &fileName) { qCDebug(qLcImageCaptureGst) << "do capture"; - // emit error in the next event loop, - // so application can associate it with returned request id. - auto invokeDeferred = [&](auto &&fn) { - QMetaObject::invokeMethod(this, std::forward<decltype(fn)>(fn), Qt::QueuedConnection); - }; - - QMutexLocker guard(&m_mutex); - if (!m_session) { - invokeDeferred([this] { - emit error(-1, QImageCapture::ResourceError, - QPlatformImageCapture::msgImageCaptureNotSet()); - }); + { + QMutexLocker guard(&m_mutex); + if (!m_session) { + invokeDeferred([this] { + emit error(-1, QImageCapture::ResourceError, + QPlatformImageCapture::msgImageCaptureNotSet()); + }); - qCDebug(qLcImageCaptureGst) << "error 1"; - return -1; - } - if (!m_session->camera()) { - invokeDeferred([this] { - emit error(-1, QImageCapture::ResourceError, tr("No camera available.")); - }); + qCDebug(qLcImageCaptureGst) << "error 1"; + return -1; + } + if (!m_session->camera()) { + invokeDeferred([this] { + emit error(-1, QImageCapture::ResourceError, tr("No camera available.")); + }); - qCDebug(qLcImageCaptureGst) << "error 2"; - return -1; - } - if (passImage) { - invokeDeferred([this] { - emit error(-1, QImageCapture::NotReadyError, - QPlatformImageCapture::msgCameraNotReady()); - }); + qCDebug(qLcImageCaptureGst) << "error 2"; + return -1; + } + if (passImage) { + invokeDeferred([this] { + emit error(-1, QImageCapture::NotReadyError, + QPlatformImageCapture::msgCameraNotReady()); + }); + + qCDebug(qLcImageCaptureGst) << "error 3"; + return -1; + } + m_lastId++; - qCDebug(qLcImageCaptureGst) << "error 3"; - return -1; + pendingImages.enqueue({ m_lastId, fileName, QMediaMetaData{} }); + // let one image pass the pipeline + passImage = true; } - m_lastId++; - - pendingImages.enqueue({m_lastId, fileName, QMediaMetaData{}}); - // let one image pass the pipeline - passImage = true; emit readyForCaptureChanged(false); return m_lastId; @@ -192,7 +188,10 @@ bool QGstreamerImageCapture::probeBuffer(GstBuffer *buffer) passImage = false; - emit readyForCaptureChanged(isReadyForCapture()); + bool ready = isReadyForCapture(); + invokeDeferred([this, ready] { + emit readyForCaptureChanged(ready); + }); QGstCaps caps = bin.staticPad("sink").currentCaps(); auto memoryFormat = caps.memoryFormat(); @@ -223,24 +222,26 @@ bool QGstreamerImageCapture::probeBuffer(GstBuffer *buffer) std::move(bufferHandle), previewInfo, sink, fmt, memoryFormat, }; QVideoFrame frame(gstBuffer, fmt); + QImage img = frame.toImage(); if (img.isNull()) { qDebug() << "received a null image"; return; } - auto &imageData = pendingImages.head(); - - emit imageExposed(imageData.id); - qCDebug(qLcImageCaptureGst) << "Image available!"; - emit imageAvailable(imageData.id, frame); - emit imageCaptured(imageData.id, img); - QMediaMetaData imageMetaData = metaData(); imageMetaData.insert(QMediaMetaData::Resolution, frame.size()); - imageData.metaData = imageMetaData; - - emit imageMetadataAvailable(imageData.id, imageMetaData); + pendingImages.head().metaData = std::move(imageMetaData); + PendingImage pendingImage = pendingImages.head(); + + invokeDeferred([this, pendingImage = std::move(pendingImage), frame = std::move(frame), + img = std::move(img)]() mutable { + emit imageExposed(pendingImage.id); + qCDebug(qLcImageCaptureGst) << "Image available!"; + emit imageAvailable(pendingImage.id, frame); + emit imageCaptured(pendingImage.id, img); + emit imageMetadataAvailable(pendingImage.id, pendingImage.metaData); + }); }); m_pendingFutures.insert(futureId, future); diff --git a/src/plugins/multimedia/gstreamer/mediacapture/qgstreamerimagecapture_p.h b/src/plugins/multimedia/gstreamer/mediacapture/qgstreamerimagecapture_p.h index 0ca3bd9b9..8dfceb969 100644 --- a/src/plugins/multimedia/gstreamer/mediacapture/qgstreamerimagecapture_p.h +++ b/src/plugins/multimedia/gstreamer/mediacapture/qgstreamerimagecapture_p.h @@ -97,6 +97,12 @@ private: QMap<int, QFuture<void>> m_pendingFutures; int futureIDAllocator = 0; + + template <typename Functor> + void invokeDeferred(Functor &&fn) + { + QMetaObject::invokeMethod(this, std::forward<decltype(fn)>(fn), Qt::QueuedConnection); + }; }; QT_END_NAMESPACE |