summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorArtem Dyomin <artem.dyomin@qt.io>2023-12-28 20:04:25 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2024-01-06 14:05:24 +0000
commit16fd75b0cd39451d7317eb231a50d88e81e3120a (patch)
treee710bb9f07b4d048135960a22cbf4d5b1d86f869 /src
parentf61c751d4ed3a041fe4e43b1958d0402009abd78 (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.h2
-rw-r--r--src/multimedia/video/qmemoryvideobuffer.cpp15
-rw-r--r--src/multimedia/video/qmemoryvideobuffer_p.h1
-rw-r--r--src/multimedia/video/qvideotexturehelper.cpp13
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));
}