diff options
author | Artem Dyomin <artem.dyomin@qt.io> | 2023-12-28 20:04:25 +0100 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2024-01-06 14:05:24 +0000 |
commit | 16fd75b0cd39451d7317eb231a50d88e81e3120a (patch) | |
tree | e710bb9f07b4d048135960a22cbf4d5b1d86f869 /src | |
parent | f61c751d4ed3a041fe4e43b1958d0402009abd78 (diff) |
Implement zero copy rendering of QMemoryVideoBuffer
We use QRhiTextureUploadEntry to create textures from memory.
QRhiTextureUploadEntry takes QByteArray, let's
pass there the array from QMemoryVideoBuffer to
get round extra copying.
Some of the added functionality is unit-tested in the next CR.
Pick-to: 6.6 6.5
Change-Id: Iaa16cbceb189b38713e427eb76f72396ad0d759d
Reviewed-by: Lars Knoll <lars@knoll.priv.no>
(cherry picked from commit 70c4bf4c565c3ace547f5cbd0398953fcd1ff4f3)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/multimedia/video/qabstractvideobuffer_p.h | 2 | ||||
-rw-r--r-- | src/multimedia/video/qmemoryvideobuffer.cpp | 15 | ||||
-rw-r--r-- | src/multimedia/video/qmemoryvideobuffer_p.h | 1 | ||||
-rw-r--r-- | src/multimedia/video/qvideotexturehelper.cpp | 13 |
4 files changed, 29 insertions, 2 deletions
diff --git a/src/multimedia/video/qabstractvideobuffer_p.h b/src/multimedia/video/qabstractvideobuffer_p.h index eeff5804e..19637147a 100644 --- a/src/multimedia/video/qabstractvideobuffer_p.h +++ b/src/multimedia/video/qabstractvideobuffer_p.h @@ -63,6 +63,8 @@ public: virtual quint64 textureHandle(int /*plane*/) const { return 0; } virtual QMatrix4x4 externalTextureMatrix() const { return {}; } + + virtual QByteArray underlyingByteArray(int /*plane*/) const { return {}; } protected: QVideoFrame::HandleType m_type; QRhi *m_rhi = nullptr; diff --git a/src/multimedia/video/qmemoryvideobuffer.cpp b/src/multimedia/video/qmemoryvideobuffer.cpp index f868737db..bcbbe7e59 100644 --- a/src/multimedia/video/qmemoryvideobuffer.cpp +++ b/src/multimedia/video/qmemoryvideobuffer.cpp @@ -48,7 +48,12 @@ QAbstractVideoBuffer::MapData QMemoryVideoBuffer::map(QVideoFrame::MapMode mode) mapData.nPlanes = 1; mapData.bytesPerLine[0] = m_bytesPerLine; - mapData.data[0] = reinterpret_cast<uchar *>(m_data.data()); + // avoid detaching and extra copying in case the underlyingByteArray is + // being held by textures or anything else. + if (mode == QVideoFrame::ReadOnly) + mapData.data[0] = reinterpret_cast<uchar *>(const_cast<char*>(m_data.constData())); + else + mapData.data[0] = reinterpret_cast<uchar *>(m_data.data()); mapData.size[0] = m_data.size(); } @@ -63,4 +68,12 @@ void QMemoryVideoBuffer::unmap() m_mapMode = QVideoFrame::NotMapped; } +/*! + \reimp +*/ +QByteArray QMemoryVideoBuffer::underlyingByteArray(int plane) const +{ + return plane == 0 ? m_data : QByteArray{}; +} + QT_END_NAMESPACE diff --git a/src/multimedia/video/qmemoryvideobuffer_p.h b/src/multimedia/video/qmemoryvideobuffer_p.h index d15e91ad9..ec97abd4f 100644 --- a/src/multimedia/video/qmemoryvideobuffer_p.h +++ b/src/multimedia/video/qmemoryvideobuffer_p.h @@ -30,6 +30,7 @@ public: MapData map(QVideoFrame::MapMode mode) override; void unmap() override; + QByteArray underlyingByteArray(int plane) const override; private: int m_bytesPerLine = 0; QVideoFrame::MapMode m_mapMode = QVideoFrame::NotMapped; diff --git a/src/multimedia/video/qvideotexturehelper.cpp b/src/multimedia/video/qvideotexturehelper.cpp index 385880bed..f91ed3daa 100644 --- a/src/multimedia/video/qvideotexturehelper.cpp +++ b/src/multimedia/video/qvideotexturehelper.cpp @@ -629,7 +629,18 @@ static bool updateTextureWithMap(QVideoFrame frame, QRhi *rhi, QRhiResourceUpdat subresDesc.setData(QByteArray((const char *)image.bits(), image.bytesPerLine()*image.height())); subresDesc.setDataStride(image.bytesPerLine()); } else { - subresDesc.setData(QByteArray::fromRawData((const char *)frame.bits(plane), frame.mappedBytes(plane))); + const auto frameBits = reinterpret_cast<const char *>(frame.bits(plane)); + const auto mappedBytes = frame.mappedBytes(plane); + auto underlyingByteArray = frame.videoBuffer()->underlyingByteArray(plane); + + if (underlyingByteArray.size() == mappedBytes) { + Q_ASSERT(underlyingByteArray.constData() == frameBits); + subresDesc.setData(std::move(underlyingByteArray)); + } + else { + subresDesc.setData(QByteArray::fromRawData(frameBits, mappedBytes)); + } + subresDesc.setDataStride(frame.bytesPerLine(plane)); } |