diff options
author | Artem Dyomin <artem.dyomin@qt.io> | 2023-07-27 12:40:24 +0200 |
---|---|---|
committer | Artem Dyomin <artem.dyomin@qt.io> | 2023-07-27 14:00:50 +0000 |
commit | 60bf900d56cec69057677fa6069c5a96220c6d97 (patch) | |
tree | e65ebcdbdc7f49923c1134e2d5a59f6af4b45414 /src/multimedia/video/qvideoframe.cpp | |
parent | a2880974497bfe1ee3c17803fca4643a6ef3855e (diff) |
Fix QVideoFrame::toImage thread-safety
* toImage is const and it's expected to be thread-safe
* since video frames are often emitted from separate threads,
there might be collisions with 2 images created in parallel.
* Even though QImage assignment is thread safe, let's avoid
possible parallel rendering to different images.
Pick-to: 6.6 6.5 6.2
Task-number: QTBUG-111975
Change-Id: Ib26982e3a1df888dbf70c3c0ff73392d4dc81c80
Reviewed-by: Pavel Dubsky <pavel.dubsky@qt.io>
Reviewed-by: Artem Dyomin <artem.dyomin@qt.io>
Diffstat (limited to 'src/multimedia/video/qvideoframe.cpp')
-rw-r--r-- | src/multimedia/video/qvideoframe.cpp | 13 |
1 files changed, 9 insertions, 4 deletions
diff --git a/src/multimedia/video/qvideoframe.cpp b/src/multimedia/video/qvideoframe.cpp index 503a29f70..b626ad573 100644 --- a/src/multimedia/video/qvideoframe.cpp +++ b/src/multimedia/video/qvideoframe.cpp @@ -17,6 +17,8 @@ #include <qvariant.h> #include <rhi/qrhi.h> +#include <mutex> + #include <QDebug> QT_BEGIN_NAMESPACE @@ -46,6 +48,8 @@ public: QVideoFrame::RotationAngle rotationAngle = QVideoFrame::Rotation0; bool mirrored = false; QImage image; + std::once_flag imageOnceFlag; + private: Q_DISABLE_COPY(QVideoFramePrivate) }; @@ -676,11 +680,12 @@ QImage QVideoFrame::toImage() const { if (!isValid()) return {}; - if (!d->image.isNull()) - return d->image; - d->image = qImageFromVideoFrame(*this, rotationAngle(), mirrored(), - surfaceFormat().scanLineDirection() != QVideoFrameFormat::TopToBottom); + std::call_once(d->imageOnceFlag, [this]() { + const bool mirrorY = surfaceFormat().scanLineDirection() != QVideoFrameFormat::TopToBottom; + d->image = qImageFromVideoFrame(*this, rotationAngle(), mirrored(), mirrorY); + }); + return d->image; } |