diff options
author | Tim Blechmann <tim@klingt.org> | 2024-03-08 12:48:45 +0800 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2024-03-14 03:43:38 +0000 |
commit | 1e23d963376c03feb40d474d766efee8bec7e727 (patch) | |
tree | 2c14a2dc6cd20e7fb2dc3faccee0b4a56939ac4d | |
parent | b1ca01a8b22755150fc7d3de19445ebb315826cf (diff) |
GStreamer: camera - prevent pipeline changes while pipeline is running
When switching cameras, `QGstreamerCamera::setCamera` would modify the
pipeline while it's running
Pick-to: 6.5
Change-Id: I96895b882270018f900126979f161ca614adfb16
Reviewed-by: Artem Dyomin <artem.dyomin@qt.io>
(cherry picked from commit d0e41971ea34dd802bb04159e1a7f49e50e4dac5)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
(cherry picked from commit 992812185cf2c207b75b2455c85327cac3475e51)
3 files changed, 37 insertions, 18 deletions
diff --git a/src/plugins/multimedia/gstreamer/mediacapture/qgstreamercamera.cpp b/src/plugins/multimedia/gstreamer/mediacapture/qgstreamercamera.cpp index c1aaab818..226a08bc9 100644 --- a/src/plugins/multimedia/gstreamer/mediacapture/qgstreamercamera.cpp +++ b/src/plugins/multimedia/gstreamer/mediacapture/qgstreamercamera.cpp @@ -103,20 +103,22 @@ void QGstreamerCamera::setCamera(const QCameraDevice &camera) auto gstNewDecode = QGstElement::createFromFactory( f.pixelFormat() == QVideoFrameFormat::Format_Jpeg ? "jpegdec" : "identity"); - qUnlinkGstElements(gstCamera, gstCapsFilter, gstDecode, gstVideoConvert); - gstCameraBin.stopAndRemoveElements(gstCamera, gstDecode); - - gstCapsFilter.set("caps", caps); + auto updateCameraBin = [&] { + qUnlinkGstElements(gstCamera, gstCapsFilter, gstDecode, gstVideoConvert); + gstCameraBin.stopAndRemoveElements(gstCamera, gstDecode); - gstCameraBin.add(gstNewCamera, gstNewDecode); - qLinkGstElements(gstNewCamera, gstCapsFilter, gstNewDecode, gstVideoConvert); + gstCapsFilter.set("caps", caps); - // Start sending frames once pipeline is linked - // FIXME: put camera to READY state before linking to decoder as in the NULL state it does not - // know its true caps + gstCameraBin.add(gstNewCamera, gstNewDecode); + qLinkGstElements(gstNewCamera, gstCapsFilter, gstNewDecode, gstVideoConvert); - gstCameraBin.syncChildrenState(); + gstCameraBin.syncChildrenState(); + }; + if (gstPipeline) + gstPipeline.modifyPipelineWhileNotRunning(updateCameraBin); + else + updateCameraBin(); gstCamera = gstNewCamera; gstDecode = gstNewDecode; @@ -137,23 +139,35 @@ bool QGstreamerCamera::setCameraFormat(const QCameraFormat &format) auto newGstDecode = QGstElement::createFromFactory( f.pixelFormat() == QVideoFrameFormat::Format_Jpeg ? "jpegdec" : "identity"); - gstCameraBin.add(newGstDecode); - newGstDecode.syncStateWithParent(); - gstCamera.staticPad("src").doInIdleProbe([&]() { + auto updateCameraBin = [&] { + newGstDecode.syncStateWithParent(); + qUnlinkGstElements(gstCamera, gstCapsFilter, gstDecode, gstVideoConvert); + gstCameraBin.stopAndRemoveElements(gstDecode); gstCapsFilter.set("caps", caps); + + gstCameraBin.add(newGstDecode); qLinkGstElements(gstCamera, gstCapsFilter, newGstDecode, gstVideoConvert); - }); + gstCameraBin.syncChildrenState(); + }; - gstCameraBin.stopAndRemoveElements(gstDecode); + if (gstPipeline) + gstPipeline.modifyPipelineWhileNotRunning(updateCameraBin); + else + updateCameraBin(); gstDecode = newGstDecode; return true; } +void QGstreamerCamera::setPipeline(QGstPipeline const &pipeline) +{ + gstPipeline = pipeline; +} + void QGstreamerCamera::updateCameraProperties() { #if QT_CONFIG(linux_v4l) diff --git a/src/plugins/multimedia/gstreamer/mediacapture/qgstreamercamera_p.h b/src/plugins/multimedia/gstreamer/mediacapture/qgstreamercamera_p.h index 7926f9004..59d69337f 100644 --- a/src/plugins/multimedia/gstreamer/mediacapture/qgstreamercamera_p.h +++ b/src/plugins/multimedia/gstreamer/mediacapture/qgstreamercamera_p.h @@ -15,11 +15,12 @@ // We mean it. // -#include <QHash> #include <private/qplatformcamera_p.h> #include <private/qmultimediautils_p.h> -#include "qgstreamermediacapture_p.h" -#include <qgst_p.h> + +#include <mediacapture/qgstreamermediacapture_p.h> +#include <common/qgst_p.h> +#include <common/qgstpipeline_p.h> QT_BEGIN_NAMESPACE @@ -37,6 +38,7 @@ public: void setCamera(const QCameraDevice &camera) override; bool setCameraFormat(const QCameraFormat &format) override; + void setPipeline(const QGstPipeline &); QGstElement gstElement() const { return QGstElement(gstCameraBin.element()); } #if QT_CONFIG(gstreamer_photography) GstPhotography *photography() const; @@ -117,6 +119,7 @@ private: QGstElement gstDecode; QGstElement gstVideoConvert; QGstElement gstVideoScale; + QGstPipeline gstPipeline; bool m_active = false; QString m_v4l2DevicePath; diff --git a/src/plugins/multimedia/gstreamer/mediacapture/qgstreamermediacapture.cpp b/src/plugins/multimedia/gstreamer/mediacapture/qgstreamermediacapture.cpp index 8eb37ac06..4a5fbe6e6 100644 --- a/src/plugins/multimedia/gstreamer/mediacapture/qgstreamermediacapture.cpp +++ b/src/plugins/multimedia/gstreamer/mediacapture/qgstreamermediacapture.cpp @@ -93,11 +93,13 @@ void QGstreamerMediaCapture::setCamera(QPlatformCamera *platformCamera) QObject::disconnect(gstCameraActiveConnection); if (gstVideoTee) setCameraActive(false); + gstCamera->setPipeline({}); } gstCamera = camera; if (gstCamera) { + gstCamera->setPipeline(gstPipeline); gstCameraActiveConnection = QObject::connect(camera, &QGstreamerCamera::activeChanged, this, &QGstreamerMediaCapture::setCameraActive); if (gstCamera->isActive()) |