summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTim Blechmann <tim@klingt.org>2024-04-29 17:11:18 +0800
committerTim Blechmann <tim@klingt.org>2024-05-17 14:32:50 +0800
commitc3c0bb446ffff8f82dd18e724c4a54b89533a12c (patch)
tree52eea0c39c31293ea746eb496cb4eec5fed4582d /src
parentc3655553e0c9e1a77fe54252a9b897fd9fa943db (diff)
GStreamer: QGstreamerImageCapture - emit signals from app threadHEADdev
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.cpp91
-rw-r--r--src/plugins/multimedia/gstreamer/mediacapture/qgstreamerimagecapture_p.h6
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