summaryrefslogtreecommitdiffstats
path: root/src/multimedia
diff options
context:
space:
mode:
Diffstat (limited to 'src/multimedia')
-rw-r--r--src/multimedia/CMakeLists.txt1
-rw-r--r--src/multimedia/video/qvideoframe.cpp3
-rw-r--r--src/multimedia/video/qvideoframe.h5
-rw-r--r--src/multimedia/video/qvideosurfaceformat.cpp245
-rw-r--r--src/multimedia/video/qvideotexturehelper.cpp514
-rw-r--r--src/multimedia/video/qvideotexturehelper_p.h78
6 files changed, 604 insertions, 242 deletions
diff --git a/src/multimedia/CMakeLists.txt b/src/multimedia/CMakeLists.txt
index ce8f44f61..8a1010188 100644
--- a/src/multimedia/CMakeLists.txt
+++ b/src/multimedia/CMakeLists.txt
@@ -65,6 +65,7 @@ qt_internal_add_module(Multimedia
video/qmemoryvideobuffer.cpp video/qmemoryvideobuffer_p.h
video/qvideoframe.cpp video/qvideoframe.h
video/qvideosink.cpp video/qvideosink.h
+ video/qvideotexturehelper.cpp video/qvideotexturehelper_p.h
video/qvideoframeconversionhelper.cpp video/qvideoframeconversionhelper_p.h
video/qvideooutputorientationhandler.cpp video/qvideooutputorientationhandler_p.h
video/qvideosurfaceformat.cpp video/qvideosurfaceformat.h
diff --git a/src/multimedia/video/qvideoframe.cpp b/src/multimedia/video/qvideoframe.cpp
index 2fa5f9f88..a4a985a5f 100644
--- a/src/multimedia/video/qvideoframe.cpp
+++ b/src/multimedia/video/qvideoframe.cpp
@@ -49,6 +49,7 @@
#include <qpair.h>
#include <qsize.h>
#include <qvariant.h>
+#include <private/qrhi_p.h>
#include <QDebug>
@@ -812,7 +813,7 @@ int QVideoFrame::planeCount() const
\internal
Returns a texture id to the video frame's buffers.
*/
-quint64 QVideoFrame::textureHandle(int plane)
+quint64 QVideoFrame::textureHandle(int plane) const
{
return d->buffer->textureHandle(plane);
}
diff --git a/src/multimedia/video/qvideoframe.h b/src/multimedia/video/qvideoframe.h
index ea01ccb92..d2c371c3f 100644
--- a/src/multimedia/video/qvideoframe.h
+++ b/src/multimedia/video/qvideoframe.h
@@ -53,6 +53,9 @@ QT_BEGIN_NAMESPACE
class QSize;
class QVideoFramePrivate;
class QAbstractVideoBuffer;
+class QRhi;
+class QRhiResourceUpdateBatch;
+class QRhiTexture;
class Q_MULTIMEDIA_EXPORT QVideoFrame
{
@@ -113,7 +116,7 @@ public:
int mappedBytes() const;
int planeCount() const;
- quint64 textureHandle(int plane);
+ quint64 textureHandle(int plane) const;
qint64 startTime() const;
void setStartTime(qint64 time);
diff --git a/src/multimedia/video/qvideosurfaceformat.cpp b/src/multimedia/video/qvideosurfaceformat.cpp
index 5271a12db..745fe8b32 100644
--- a/src/multimedia/video/qvideosurfaceformat.cpp
+++ b/src/multimedia/video/qvideosurfaceformat.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qvideosurfaceformat.h"
+#include "qvideotexturehelper_p.h"
#include <qdebug.h>
#include <qlist.h>
@@ -259,49 +260,7 @@ int QVideoSurfaceFormat::frameHeight() const
int QVideoSurfaceFormat::nPlanes() const
{
- switch (d->pixelFormat) {
- case Format_Invalid:
- case Format_ARGB32:
- case Format_ARGB32_Premultiplied:
- case Format_RGB32:
- case Format_RGB24:
- case Format_RGB565:
- case Format_RGB555:
- case Format_ARGB8565_Premultiplied:
- case Format_BGRA32:
- case Format_BGRA32_Premultiplied:
- case Format_ABGR32:
- case Format_BGR32:
- case Format_BGR24:
- case Format_BGR565:
- case Format_BGR555:
- case Format_BGRA5658_Premultiplied:
- case Format_AYUV444:
- case Format_AYUV444_Premultiplied:
- case Format_YUV444:
- case Format_UYVY:
- case Format_YUYV:
- case Format_Y8:
- case Format_Y16:
- case Format_Jpeg:
- return 1;
- case Format_NV12:
- case Format_NV21:
- case Format_IMC2:
- case Format_IMC4:
- case Format_P010LE:
- case Format_P010BE:
- case Format_P016LE:
- case Format_P016BE:
- return 2;
- case Format_YUV420P:
- case Format_YUV422P:
- case Format_YV12:
- case Format_IMC1:
- case Format_IMC3:
- return 3;
- }
- return 0;
+ return QVideoTextureHelper::textureDescription(d->pixelFormat)->nplanes;
}
/*!
@@ -438,211 +397,17 @@ QSize QVideoSurfaceFormat::sizeHint() const
QString QVideoSurfaceFormat::vertexShaderFileName() const
{
- switch (d->pixelFormat) {
- case Format_Invalid:
- case Format_Jpeg:
-
- case Format_RGB24:
- case Format_RGB565:
- case Format_RGB555:
- case Format_ARGB8565_Premultiplied:
- case Format_BGR24:
- case Format_BGR565:
- case Format_BGR555:
- case Format_BGRA5658_Premultiplied:
-
- case Format_Y8:
- case Format_Y16:
-
- case Format_AYUV444:
- case Format_AYUV444_Premultiplied:
- case Format_YUV444:
-
- case Format_IMC1:
- case Format_IMC2:
- case Format_IMC3:
- case Format_IMC4:
- return QString();
- case Format_ARGB32:
- case Format_ARGB32_Premultiplied:
- case Format_RGB32:
- case Format_BGRA32:
- case Format_BGRA32_Premultiplied:
- case Format_ABGR32:
- case Format_BGR32:
- return QStringLiteral(":/qtmultimedia/shaders/rgba.vert.qsb");
- case Format_YUV420P:
- case Format_YUV422P:
- case Format_YV12:
- case Format_UYVY:
- case Format_YUYV:
- case Format_NV12:
- case Format_NV21:
- case Format_P010LE:
- case Format_P010BE:
- case Format_P016LE:
- case Format_P016BE:
- return QStringLiteral(":/qtmultimedia/shaders/yuv.vert.qsb");
- }
+ return QVideoTextureHelper::vertexShaderFileName(d->pixelFormat);
}
QString QVideoSurfaceFormat::fragmentShaderFileName() const
{
- switch (d->pixelFormat) {
- case Format_Invalid:
- case Format_Jpeg:
-
- case Format_RGB24:
- case Format_RGB565:
- case Format_RGB555:
- case Format_ARGB8565_Premultiplied:
- case Format_BGR24:
- case Format_BGR565:
- case Format_BGR555:
- case Format_BGRA5658_Premultiplied:
-
- case Format_Y8:
- case Format_Y16:
-
- case Format_AYUV444:
- case Format_AYUV444_Premultiplied:
- case Format_YUV444:
-
- case Format_IMC1:
- case Format_IMC2:
- case Format_IMC3:
- case Format_IMC4:
- return QString();
- case Format_ARGB32:
- case Format_ARGB32_Premultiplied:
- case Format_RGB32:
- case Format_BGRA32:
- case Format_BGRA32_Premultiplied:
- case Format_ABGR32:
- case Format_BGR32:
- return QStringLiteral(":/qtmultimedia/shaders/rgba.frag.qsb");
- case Format_YUV420P:
- case Format_YUV422P:
- case Format_YV12:
- return QStringLiteral(":/qtmultimedia/shaders/yuv_yv.frag.qsb");
- case Format_UYVY:
- return QStringLiteral(":/qtmultimedia/shaders/uyvy.frag.qsb");
- case Format_YUYV:
- return QStringLiteral(":/qtmultimedia/shaders/yuyv.frag.qsb");
- case Format_NV12:
- return QStringLiteral(":/qtmultimedia/shaders/nv12.frag.qsb");
- case Format_NV21:
- return QStringLiteral(":/qtmultimedia/shaders/nv21.frag.qsb");
- case Format_P010LE:
- case Format_P016LE:
- return QStringLiteral(":/qtmultimedia/shaders/p010le.frag.qsb");
- case Format_P010BE:
- case Format_P016BE:
- return QStringLiteral(":/qtmultimedia/shaders/p010be.frag.qsb");
- }
-}
-
-static QMatrix4x4 colorMatrix(QVideoSurfaceFormat::YCbCrColorSpace colorSpace)
-{
- switch (colorSpace) {
- case QVideoSurfaceFormat::YCbCr_JPEG:
- return QMatrix4x4(
- 1.0f, 0.000f, 1.402f, -0.701f,
- 1.0f, -0.344f, -0.714f, 0.529f,
- 1.0f, 1.772f, 0.000f, -0.886f,
- 0.0f, 0.000f, 0.000f, 1.0000f);
- case QVideoSurfaceFormat::YCbCr_BT709:
- case QVideoSurfaceFormat::YCbCr_xvYCC709:
- return QMatrix4x4(
- 1.164f, 0.000f, 1.793f, -0.5727f,
- 1.164f, -0.534f, -0.213f, 0.3007f,
- 1.164f, 2.115f, 0.000f, -1.1302f,
- 0.0f, 0.000f, 0.000f, 1.0000f);
- default: //BT 601:
- return QMatrix4x4(
- 1.164f, 0.000f, 1.596f, -0.8708f,
- 1.164f, -0.392f, -0.813f, 0.5296f,
- 1.164f, 2.017f, 0.000f, -1.081f,
- 0.0f, 0.000f, 0.000f, 1.0000f);
- }
+ return QVideoTextureHelper::fragmentShaderFileName(d->pixelFormat);
}
QByteArray QVideoSurfaceFormat::uniformData(const QMatrix4x4 &transform, float opacity) const
{
- static constexpr float pw[3] = {};
- const float *planeWidth = pw;
-
- switch (d->pixelFormat) {
- case Format_Invalid:
- case Format_Jpeg:
-
- case Format_RGB24:
- case Format_RGB565:
- case Format_RGB555:
- case Format_ARGB8565_Premultiplied:
- case Format_BGR24:
- case Format_BGR565:
- case Format_BGR555:
- case Format_BGRA5658_Premultiplied:
-
- case Format_Y8:
- case Format_Y16:
-
- case Format_AYUV444:
- case Format_AYUV444_Premultiplied:
- case Format_YUV444:
-
- case Format_IMC1:
- case Format_IMC2:
- case Format_IMC3:
- case Format_IMC4:
- return QByteArray();
- case Format_ARGB32:
- case Format_ARGB32_Premultiplied:
- case Format_RGB32:
- case Format_BGRA32:
- case Format_BGRA32_Premultiplied:
- case Format_ABGR32:
- case Format_BGR32: {
- // { matrix4x4, opacity }
- QByteArray buf(16*4 + 4, Qt::Uninitialized);
- char *data = buf.data();
- memcpy(data, transform.constData(), 64);
- memcpy(data + 64, &opacity, 4);
- return buf;
- }
- case Format_YUV420P:
- case Format_YUV422P:
- case Format_YV12: {
- static constexpr float pw[] = { 1, 1, 1 };
- planeWidth = pw;
- break;
- }
- case Format_UYVY:
- case Format_YUYV: {
- static constexpr float pw[] = { 1, 1, 0 };
- planeWidth = pw;
- break;
- }
- case Format_NV12:
- case Format_NV21:
- case Format_P010LE:
- case Format_P010BE:
- case Format_P016LE:
- case Format_P016BE: {
- static constexpr float pw[] = { 1, 1, 0 };
- planeWidth = pw;
- break;
- }
- }
- // { matrix4x4, colorMatrix, opacity, planeWidth[3] }
- QByteArray buf(64*2 + 4 + 3*4, Qt::Uninitialized);
- char *data = buf.data();
- memcpy(data, transform.constData(), 64);
- memcpy(data + 64, colorMatrix(d->ycbcrColorSpace).constData(), 64);
- memcpy(data + 64 + 64, &opacity, 4);
- memcpy(data + 64 + 64 + 4, planeWidth, 3*4);
- return buf;
+ return QVideoTextureHelper::uniformData(*this, transform, opacity);
}
diff --git a/src/multimedia/video/qvideotexturehelper.cpp b/src/multimedia/video/qvideotexturehelper.cpp
new file mode 100644
index 000000000..930456d7d
--- /dev/null
+++ b/src/multimedia/video/qvideotexturehelper.cpp
@@ -0,0 +1,514 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvideotexturehelper_p.h"
+#include "qvideoframe.h"
+
+namespace QVideoTextureHelper
+{
+
+static const TextureDescription descriptions[QVideoSurfaceFormat::NPixelFormats] = {
+ // Format_Invalid
+ { 0,
+ { QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat},
+ { { 1, 1 }, { 1, 1 }, { 1, 1 } }
+ },
+ // Format_ARGB32
+ { 1,
+ { QRhiTexture::BGRA8, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 1, 1 }, { 1, 1 } }
+ },
+ // Format_ARGB32_Premultiplied
+ { 1,
+ { QRhiTexture::BGRA8, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 1, 1 }, { 1, 1 } }
+ },
+ // Format_RGB32
+ { 1,
+ { QRhiTexture::BGRA8, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 1, 1 }, { 1, 1 } }
+ },
+ // Format_RGB24
+ { 1,
+ { QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 1, 1 }, { 1, 1 } }
+ },
+ // Format_RGB565
+ { 1,
+ { QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 1, 1 }, { 1, 1 } }
+ },
+ // Format_RGB555
+ { 1,
+ { QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 1, 1 }, { 1, 1 } }
+ },
+ // Format_ARGB8565_Premultiplied
+ { 1,
+ { QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 1, 1 }, { 1, 1 } }
+ },
+ // Format_BGRA32
+ { 1,
+ { QRhiTexture::BGRA8, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 1, 1 }, { 1, 1 } }
+ },
+ // Format_BGRA32_Premultiplied
+ { 1,
+ { QRhiTexture::BGRA8, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 1, 1 }, { 1, 1 } }
+ },
+ // Format_ABGR32
+ { 1,
+ { QRhiTexture::BGRA8, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 1, 1 }, { 1, 1 } }
+ },
+ // Format_BGR32
+ { 1,
+ { QRhiTexture::BGRA8, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 1, 1 }, { 1, 1 } }
+ },
+ // Format_BGR24
+ { 1,
+ { QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 1, 1 }, { 1, 1 } }
+ },
+ // Format_BGR565
+ { 1,
+ { QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 1, 1 }, { 1, 1 } }
+ },
+ // Format_BGR555
+ { 1,
+ { QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 1, 1 }, { 1, 1 } }
+ },
+ // Format_BGRA5658_Premultiplied
+ { 1,
+ { QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 1, 1 }, { 1, 1 } }
+ },
+
+ // Format_AYUV444
+ { 1,
+ { QRhiTexture::BGRA8, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 1, 1 }, { 1, 1 } }
+ },
+ // Format_AYUV444_Premultiplied
+ { 1,
+ { QRhiTexture::BGRA8, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 1, 1 }, { 1, 1 } }
+ },
+ // Format_YUV444
+ { 1,
+ { QRhiTexture::BGRA8, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 1, 1 }, { 1, 1 } }
+ },
+ // Format_YUV420P
+ { 3,
+ { QRhiTexture::R8, QRhiTexture::R8, QRhiTexture::R8 },
+ { { 1, 1 }, { 2, 2 }, { 2, 2 } }
+ },
+ // Format_YUV422P
+ { 3,
+ { QRhiTexture::R8, QRhiTexture::R8, QRhiTexture::R8 },
+ { { 1, 1 }, { 2, 1 }, { 2, 1 } }
+ },
+ // Format_YV12
+ { 3,
+ { QRhiTexture::R8, QRhiTexture::R8, QRhiTexture::R8 },
+ { { 1, 1 }, { 2, 2 }, { 2, 2 } }
+ },
+ // Format_UYVY
+ { 1,
+ { QRhiTexture::BGRA8, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 1, 1 }, { 1, 1 } }
+ },
+ // Format_YUYV
+ { 1,
+ { QRhiTexture::BGRA8, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 1, 1 }, { 1, 1 } }
+ },
+ // Format_NV12
+ { 2,
+ { QRhiTexture::RG8, QRhiTexture::R8, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 2, 2 }, { 1, 1 } }
+ },
+ // Format_NV21
+ { 2,
+ { QRhiTexture::RG8, QRhiTexture::R8, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 2, 2 }, { 1, 1 } }
+ },
+ // Format_IMC1
+ { 3,
+ { QRhiTexture::R8, QRhiTexture::R8, QRhiTexture::R8 },
+ { { 1, 1 }, { 1, 1 }, { 1, 1 } }
+ },
+ // Format_IMC2
+ { 2,
+ { QRhiTexture::R8, QRhiTexture::R8, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 1, 1 }, { 1, 1 } }
+ },
+ // Format_IMC3
+ { 3,
+ { QRhiTexture::R8, QRhiTexture::R8, QRhiTexture::R8 },
+ { { 1, 1 }, { 1, 1 }, { 1, 1 } }
+ },
+ // Format_IMC4
+ { 2,
+ { QRhiTexture::R8, QRhiTexture::R8, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 1, 1 }, { 1, 1 } }
+ },
+ // Format_Y8
+ { 1,
+ { QRhiTexture::R8, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 1, 1 }, { 1, 1 } }
+ },
+ // Format_Y16
+ { 1,
+ { QRhiTexture::R16, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 1, 1 }, { 1, 1 } }
+ },
+
+ // Format_P010LE
+ { 2,
+ { QRhiTexture::RG8, QRhiTexture::BGRA8, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 2, 2 }, { 1, 1 } }
+ },
+ // Format_P010BE
+ { 2,
+ { QRhiTexture::RG8, QRhiTexture::BGRA8, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 2, 2 }, { 1, 1 } }
+ },
+ // Format_P016LE
+ { 2,
+ { QRhiTexture::RG8, QRhiTexture::BGRA8, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 2, 2 }, { 1, 1 } }
+ },
+ // Format_P016BE
+ { 2,
+ { QRhiTexture::RG8, QRhiTexture::BGRA8, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 2, 2 }, { 1, 1 } }
+ },
+
+ // Format_Jpeg
+ { 1,
+ { QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
+ { { 1, 1 }, { 1, 1 }, { 1, 1 } }
+ }
+};
+
+
+const TextureDescription *textureDescription(QVideoSurfaceFormat::PixelFormat format)
+{
+ return descriptions + format;
+}
+
+QString vertexShaderFileName(QVideoSurfaceFormat::PixelFormat format)
+{
+ switch (format) {
+ case QVideoSurfaceFormat::Format_Invalid:
+ case QVideoSurfaceFormat::Format_Jpeg:
+
+ case QVideoSurfaceFormat::Format_RGB24:
+ case QVideoSurfaceFormat::Format_RGB565:
+ case QVideoSurfaceFormat::Format_RGB555:
+ case QVideoSurfaceFormat::Format_ARGB8565_Premultiplied:
+ case QVideoSurfaceFormat::Format_BGR24:
+ case QVideoSurfaceFormat::Format_BGR565:
+ case QVideoSurfaceFormat::Format_BGR555:
+ case QVideoSurfaceFormat::Format_BGRA5658_Premultiplied:
+
+ case QVideoSurfaceFormat::Format_Y8:
+ case QVideoSurfaceFormat::Format_Y16:
+
+ case QVideoSurfaceFormat::Format_YUV444:
+
+ case QVideoSurfaceFormat::Format_IMC1:
+ case QVideoSurfaceFormat::Format_IMC2:
+ case QVideoSurfaceFormat::Format_IMC3:
+ case QVideoSurfaceFormat::Format_IMC4:
+ return QString();
+ case QVideoSurfaceFormat::Format_AYUV444:
+ case QVideoSurfaceFormat::Format_AYUV444_Premultiplied:
+ return QStringLiteral(":/qtmultimedia/shaders/yuv.vert.qsb");
+ case QVideoSurfaceFormat::Format_ARGB32:
+ case QVideoSurfaceFormat::Format_ARGB32_Premultiplied:
+ case QVideoSurfaceFormat::Format_RGB32:
+ case QVideoSurfaceFormat::Format_BGRA32:
+ case QVideoSurfaceFormat::Format_BGRA32_Premultiplied:
+ case QVideoSurfaceFormat::Format_ABGR32:
+ case QVideoSurfaceFormat::Format_BGR32:
+ return QStringLiteral(":/qtmultimedia/shaders/rgba.vert.qsb");
+ case QVideoSurfaceFormat::Format_YUV420P:
+ case QVideoSurfaceFormat::Format_YUV422P:
+ case QVideoSurfaceFormat::Format_YV12:
+ case QVideoSurfaceFormat::Format_UYVY:
+ case QVideoSurfaceFormat::Format_YUYV:
+ case QVideoSurfaceFormat::Format_NV12:
+ case QVideoSurfaceFormat::Format_NV21:
+ case QVideoSurfaceFormat::Format_P010LE:
+ case QVideoSurfaceFormat::Format_P010BE:
+ case QVideoSurfaceFormat::Format_P016LE:
+ case QVideoSurfaceFormat::Format_P016BE:
+ return QStringLiteral(":/qtmultimedia/shaders/yuv.vert.qsb");
+ }
+}
+
+QString fragmentShaderFileName(QVideoSurfaceFormat::PixelFormat format)
+{
+ switch (format) {
+ case QVideoSurfaceFormat::Format_Invalid:
+ case QVideoSurfaceFormat::Format_Jpeg:
+
+ case QVideoSurfaceFormat::Format_RGB24:
+ case QVideoSurfaceFormat::Format_RGB565:
+ case QVideoSurfaceFormat::Format_RGB555:
+ case QVideoSurfaceFormat::Format_ARGB8565_Premultiplied:
+ case QVideoSurfaceFormat::Format_BGR24:
+ case QVideoSurfaceFormat::Format_BGR565:
+ case QVideoSurfaceFormat::Format_BGR555:
+ case QVideoSurfaceFormat::Format_BGRA5658_Premultiplied:
+
+ case QVideoSurfaceFormat::Format_Y8:
+ case QVideoSurfaceFormat::Format_Y16:
+
+ case QVideoSurfaceFormat::Format_YUV444:
+
+ case QVideoSurfaceFormat::Format_IMC1:
+ case QVideoSurfaceFormat::Format_IMC2:
+ case QVideoSurfaceFormat::Format_IMC3:
+ case QVideoSurfaceFormat::Format_IMC4:
+ return QString();
+ case QVideoSurfaceFormat::Format_AYUV444:
+ case QVideoSurfaceFormat::Format_AYUV444_Premultiplied:
+ return QStringLiteral(":/qtmultimedia/shaders/ayuv.frag.qsb");
+ case QVideoSurfaceFormat::Format_ARGB32:
+ case QVideoSurfaceFormat::Format_ARGB32_Premultiplied:
+ case QVideoSurfaceFormat::Format_RGB32:
+ case QVideoSurfaceFormat::Format_BGRA32:
+ case QVideoSurfaceFormat::Format_BGRA32_Premultiplied:
+ case QVideoSurfaceFormat::Format_ABGR32:
+ case QVideoSurfaceFormat::Format_BGR32:
+ return QStringLiteral(":/qtmultimedia/shaders/rgba.frag.qsb");
+ case QVideoSurfaceFormat::Format_YUV420P:
+ case QVideoSurfaceFormat::Format_YUV422P:
+ case QVideoSurfaceFormat::Format_YV12:
+ return QStringLiteral(":/qtmultimedia/shaders/yuv_yv.frag.qsb");
+ case QVideoSurfaceFormat::Format_UYVY:
+ return QStringLiteral(":/qtmultimedia/shaders/uyvy.frag.qsb");
+ case QVideoSurfaceFormat::Format_YUYV:
+ return QStringLiteral(":/qtmultimedia/shaders/yuyv.frag.qsb");
+ case QVideoSurfaceFormat::Format_NV12:
+ return QStringLiteral(":/qtmultimedia/shaders/nv12.frag.qsb");
+ case QVideoSurfaceFormat::Format_NV21:
+ return QStringLiteral(":/qtmultimedia/shaders/nv21.frag.qsb");
+ case QVideoSurfaceFormat::Format_P010LE:
+ case QVideoSurfaceFormat::Format_P016LE:
+ return QStringLiteral(":/qtmultimedia/shaders/p010le.frag.qsb");
+ case QVideoSurfaceFormat::Format_P010BE:
+ case QVideoSurfaceFormat::Format_P016BE:
+ return QStringLiteral(":/qtmultimedia/shaders/p010be.frag.qsb");
+ }
+}
+
+
+static QMatrix4x4 colorMatrix(QVideoSurfaceFormat::YCbCrColorSpace colorSpace)
+{
+ switch (colorSpace) {
+ case QVideoSurfaceFormat::YCbCr_JPEG:
+ return QMatrix4x4(
+ 1.0f, 0.000f, 1.402f, -0.701f,
+ 1.0f, -0.344f, -0.714f, 0.529f,
+ 1.0f, 1.772f, 0.000f, -0.886f,
+ 0.0f, 0.000f, 0.000f, 1.0000f);
+ case QVideoSurfaceFormat::YCbCr_BT709:
+ case QVideoSurfaceFormat::YCbCr_xvYCC709:
+ return QMatrix4x4(
+ 1.164f, 0.000f, 1.793f, -0.5727f,
+ 1.164f, -0.534f, -0.213f, 0.3007f,
+ 1.164f, 2.115f, 0.000f, -1.1302f,
+ 0.0f, 0.000f, 0.000f, 1.0000f);
+ default: //BT 601:
+ return QMatrix4x4(
+ 1.164f, 0.000f, 1.596f, -0.8708f,
+ 1.164f, -0.392f, -0.813f, 0.5296f,
+ 1.164f, 2.017f, 0.000f, -1.081f,
+ 0.0f, 0.000f, 0.000f, 1.0000f);
+ }
+}
+
+QByteArray uniformData(const QVideoSurfaceFormat &format, const QMatrix4x4 &transform, float opacity)
+{
+ static constexpr float pw[3] = {};
+ const float *planeWidth = pw;
+
+ switch (format.pixelFormat()) {
+ case QVideoSurfaceFormat::Format_Invalid:
+ case QVideoSurfaceFormat::Format_Jpeg:
+
+ case QVideoSurfaceFormat::Format_RGB24:
+ case QVideoSurfaceFormat::Format_RGB565:
+ case QVideoSurfaceFormat::Format_RGB555:
+ case QVideoSurfaceFormat::Format_ARGB8565_Premultiplied:
+ case QVideoSurfaceFormat::Format_BGR24:
+ case QVideoSurfaceFormat::Format_BGR565:
+ case QVideoSurfaceFormat::Format_BGR555:
+ case QVideoSurfaceFormat::Format_BGRA5658_Premultiplied:
+
+ case QVideoSurfaceFormat::Format_Y8:
+ case QVideoSurfaceFormat::Format_Y16:
+
+ case QVideoSurfaceFormat::Format_YUV444:
+
+ case QVideoSurfaceFormat::Format_IMC1:
+ case QVideoSurfaceFormat::Format_IMC2:
+ case QVideoSurfaceFormat::Format_IMC3:
+ case QVideoSurfaceFormat::Format_IMC4:
+ return QByteArray();
+ case QVideoSurfaceFormat::Format_ARGB32:
+ case QVideoSurfaceFormat::Format_ARGB32_Premultiplied:
+ case QVideoSurfaceFormat::Format_RGB32:
+ case QVideoSurfaceFormat::Format_BGRA32:
+ case QVideoSurfaceFormat::Format_BGRA32_Premultiplied:
+ case QVideoSurfaceFormat::Format_ABGR32:
+ case QVideoSurfaceFormat::Format_BGR32: {
+ // { matrix4x4, opacity }
+ QByteArray buf(16*4 + 4, Qt::Uninitialized);
+ char *data = buf.data();
+ memcpy(data, transform.constData(), 64);
+ memcpy(data + 64, &opacity, 4);
+ return buf;
+ }
+ case QVideoSurfaceFormat::Format_AYUV444:
+ case QVideoSurfaceFormat::Format_AYUV444_Premultiplied: {
+ static constexpr float pw[] = { 1, 0, 0 };
+ planeWidth = pw;
+ break;
+ }
+ case QVideoSurfaceFormat::Format_YUV420P:
+ case QVideoSurfaceFormat::Format_YUV422P:
+ case QVideoSurfaceFormat::Format_YV12: {
+ static constexpr float pw[] = { 1, 1, 1 };
+ planeWidth = pw;
+ break;
+ }
+ case QVideoSurfaceFormat::Format_UYVY:
+ case QVideoSurfaceFormat::Format_YUYV: {
+ static constexpr float pw[] = { 1, 1, 0 };
+ planeWidth = pw;
+ break;
+ }
+ case QVideoSurfaceFormat::Format_NV12:
+ case QVideoSurfaceFormat::Format_NV21:
+ case QVideoSurfaceFormat::Format_P010LE:
+ case QVideoSurfaceFormat::Format_P010BE:
+ case QVideoSurfaceFormat::Format_P016LE:
+ case QVideoSurfaceFormat::Format_P016BE: {
+ static constexpr float pw[] = { 1, 1, 0 };
+ planeWidth = pw;
+ break;
+ }
+ }
+ // { matrix4x4, colorMatrix, opacity, planeWidth[3] }
+ QByteArray buf(64*2 + 4 + 3*4, Qt::Uninitialized);
+ char *data = buf.data();
+ memcpy(data, transform.constData(), 64);
+ memcpy(data + 64, colorMatrix(format.yCbCrColorSpace()).constData(), 64);
+ memcpy(data + 64 + 64, &opacity, 4);
+ memcpy(data + 64 + 64 + 4, planeWidth, 3*4);
+ return buf;
+}
+
+int updateRhiTextures(QVideoFrame frame, QRhi *rhi, QRhiResourceUpdateBatch *resourceUpdates, QRhiTexture **textures)
+{
+ QVideoSurfaceFormat fmt = frame.surfaceFormat();
+ QVideoSurfaceFormat::PixelFormat pixelFormat = fmt.pixelFormat();
+ QSize size = fmt.frameSize();
+
+ const TextureDescription *description = descriptions + pixelFormat;
+
+ QSize planeSizes[TextureDescription::maxPlanes];
+ for (int plane = 0; plane < description->nplanes; ++plane)
+ planeSizes[plane] = QSize(size.width()/description->sizeScale[plane].x, size.height()/description->sizeScale[plane].y);
+
+ if (frame.handleType() == QVideoFrame::RhiTextureHandle) {
+ for (int plane = 0; plane < description->nplanes; ++plane) {
+ quint64 nativeTexture = frame.textureHandle(plane);
+ Q_ASSERT(nativeTexture);
+ textures[plane] = rhi->newTexture(description->textureFormat[plane], planeSizes[plane], 1, {});
+ textures[plane]->createFrom({nativeTexture, 0});
+ }
+ return description->nplanes;
+ }
+
+ // need to upload textures
+ bool mapped = frame.map(QVideoFrame::ReadOnly);
+ if (!mapped) {
+ qWarning() << "could not map data of QVideoFrame for upload";
+ return 0;
+ }
+
+ Q_ASSERT(frame.planeCount() == description->nplanes);
+ for (int plane = 0; plane < description->nplanes; ++plane) {
+
+ bool needsRebuild = !textures[plane] || textures[plane]->pixelSize() != planeSizes[plane];
+ if (!textures[plane])
+ textures[plane] = rhi->newTexture(description->textureFormat[plane], planeSizes[plane], 1, {});
+
+ if (needsRebuild) {
+ textures[plane]->setPixelSize(planeSizes[plane]);
+ bool created = textures[plane]->create();
+ if (!created) {
+ qWarning("Failed to create texture (size %dx%d)", planeSizes[plane].width(), planeSizes[plane].height());
+ return 0;
+ }
+ }
+
+ QRhiTextureSubresourceUploadDescription subresDesc(frame.bits(plane), frame.bytesPerLine(plane)*planeSizes[plane].height());
+ subresDesc.setSourceSize(planeSizes[plane]);
+ subresDesc.setDestinationTopLeft(QPoint(0, 0));
+ QRhiTextureUploadEntry entry(0, 0, subresDesc);
+ QRhiTextureUploadDescription desc({ entry });
+ resourceUpdates->uploadTexture(textures[plane], desc);
+ }
+ return description->nplanes;
+}
+
+}
diff --git a/src/multimedia/video/qvideotexturehelper_p.h b/src/multimedia/video/qvideotexturehelper_p.h
new file mode 100644
index 000000000..4b369594a
--- /dev/null
+++ b/src/multimedia/video/qvideotexturehelper_p.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVIDEOTEXTUREHELPER_H
+#define QVIDEOTEXTUREHELPER_H
+
+#include <qvideosurfaceformat.h>
+#include <private/qrhi_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QVideoFrame;
+
+namespace QVideoTextureHelper
+{
+
+struct TextureDescription
+{
+ static constexpr int maxPlanes = 3;
+ struct SizeScale {
+ int x;
+ int y;
+ };
+
+ int nplanes;
+ QRhiTexture::Format textureFormat[maxPlanes];
+ SizeScale sizeScale[maxPlanes];
+};
+
+Q_MULTIMEDIA_EXPORT const TextureDescription *textureDescription(QVideoSurfaceFormat::PixelFormat format);
+
+Q_MULTIMEDIA_EXPORT QString vertexShaderFileName(QVideoSurfaceFormat::PixelFormat format);
+Q_MULTIMEDIA_EXPORT QString fragmentShaderFileName(QVideoSurfaceFormat::PixelFormat format);
+Q_MULTIMEDIA_EXPORT QByteArray uniformData(const QVideoSurfaceFormat &format, const QMatrix4x4 &transform, float opacity);
+Q_MULTIMEDIA_EXPORT int updateRhiTextures(QVideoFrame frame, QRhi *rhi,
+ QRhiResourceUpdateBatch *resourceUpdates, QRhiTexture **textures);
+
+}
+
+QT_END_NAMESPACE
+
+#endif