1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QVIDEOTEXTUREHELPER_H
5#define QVIDEOTEXTUREHELPER_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <qvideoframeformat.h>
19#include <rhi/qrhi.h>
20
21#include <QtGui/qtextlayout.h>
22
23QT_BEGIN_NAMESPACE
24
25class QVideoFrame;
26class QTextLayout;
27class QVideoFrameTextures;
28using QVideoFrameTexturesUPtr = std::unique_ptr<QVideoFrameTextures>;
29class QVideoFrameTexturesHandles;
30using QVideoFrameTexturesHandlesUPtr = std::unique_ptr<QVideoFrameTexturesHandles>;
31
32namespace QVideoTextureHelper
33{
34
35struct Q_MULTIMEDIA_EXPORT TextureDescription
36{
37 static constexpr int maxPlanes = 3;
38 struct SizeScale {
39 int x;
40 int y;
41 };
42 using BytesRequired = int(*)(int stride, int height);
43
44 enum TextureFormat {
45 UnknownFormat,
46 Red_8,
47 RG_8,
48 RGBA_8,
49 BGRA_8,
50 Red_16,
51 RG_16,
52 };
53
54 QRhiTexture::Format rhiTextureFormat(int plane, QRhi *rhi) const;
55
56 inline int strideForWidth(int width) const { return (width*strideFactor + 15) & ~15; }
57 inline int bytesForSize(QSize s) const { return bytesRequired(strideForWidth(width: s.width()), s.height()); }
58 int widthForPlane(int width, int plane) const
59 {
60 if (plane > nplanes) return 0;
61 return (width + sizeScale[plane].x - 1)/sizeScale[plane].x;
62 }
63 int heightForPlane(int height, int plane) const
64 {
65 if (plane > nplanes) return 0;
66 return (height + sizeScale[plane].y - 1)/sizeScale[plane].y;
67 }
68
69 /**
70 * \returns Plane scaling factors taking into account possible workarounds due to QRhi backend
71 * capabilities.
72 */
73 SizeScale rhiSizeScale(int plane, QRhi *rhi) const
74 {
75 if (!rhi)
76 return sizeScale[plane];
77
78 // NOTE: We need to handle sizing difference when packing two-component textures to RGBA8,
79 // where width gets cut in half.
80 // Another option would be to compare QRhiImplementation::TextureFormatInfo to expected
81 // based on TextureDescription::Format.
82 if ((textureFormat[plane] == TextureDescription::RG_8
83 || textureFormat[plane] == TextureDescription::Red_16)
84 && rhiTextureFormat(plane, rhi) == QRhiTexture::RGBA8)
85 return { .x: sizeScale[plane].x * 2, .y: sizeScale[plane].y };
86
87 return sizeScale[plane];
88 }
89
90 QSize rhiPlaneSize(QSize frameSize, int plane, QRhi *rhi) const
91 {
92 SizeScale scale = rhiSizeScale(plane, rhi);
93 return QSize(frameSize.width() / scale.x, frameSize.height() / scale.y);
94 }
95
96 bool hasTextureFormat(TextureFormat format) const
97 {
98 return std::any_of(first: textureFormat, last: textureFormat + nplanes, pred: [format](TextureFormat f) {
99 return f == format;
100 });
101 }
102
103 int nplanes;
104 int strideFactor;
105 BytesRequired bytesRequired;
106 TextureFormat textureFormat[maxPlanes];
107 SizeScale sizeScale[maxPlanes];
108};
109
110Q_MULTIMEDIA_EXPORT const TextureDescription *textureDescription(QVideoFrameFormat::PixelFormat format);
111
112Q_MULTIMEDIA_EXPORT QString vertexShaderFileName(const QVideoFrameFormat &format);
113Q_MULTIMEDIA_EXPORT QString
114fragmentShaderFileName(const QVideoFrameFormat &format, QRhi *rhi,
115 QRhiSwapChain::Format surfaceFormat = QRhiSwapChain::SDR);
116Q_MULTIMEDIA_EXPORT void updateUniformData(QByteArray *dst, QRhi *rhi,
117 const QVideoFrameFormat &format,
118 const QVideoFrame &frame, const QMatrix4x4 &transform,
119 float opacity, float maxNits = 100);
120
121/**
122 * @brief Creates plane textures from texture handles set by the specified rhi.
123 * The result owns the specified handles set; the QRhiTexture(s), exposed by the result
124 * refer to the owned handles set.
125 * If the specified size is empty or pixelFormat is invalid, null is returned.
126 */
127Q_MULTIMEDIA_EXPORT QVideoFrameTexturesUPtr
128createTexturesFromHandles(QVideoFrameTexturesHandlesUPtr handles, QRhi &rhi,
129 QVideoFrameFormat::PixelFormat pixelFormat, QSize size);
130
131
132/**
133 * @brief Creates plane textures from a video frame by the specified rhi.
134 If possible, the function modifies 'oldTextures', which is the texture from the pool,
135 and returns the specified one or a new one with any taken data.
136 */
137Q_MULTIMEDIA_EXPORT QVideoFrameTexturesUPtr createTextures(const QVideoFrame &frame, QRhi &rhi,
138 QRhiResourceUpdateBatch &rub,
139 QVideoFrameTexturesUPtr &oldTextures);
140
141/**
142 * @brief Returns a QRhiTexture::Format taking into account rhi capabilities and explicitly excluded
143 * formats using a chain of pre-defined fallback texture formats. If no valid fallback is
144 * determined, will return the format argument.
145 */
146Q_MULTIMEDIA_EXPORT QRhiTexture::Format
147resolvedRhiTextureFormat(QRhiTexture::Format format, QRhi *rhi);
148
149Q_MULTIMEDIA_EXPORT void
150setExcludedRhiTextureFormats(QList<QRhiTexture::Format> formats); // for tests only
151
152struct UniformData {
153 float transformMatrix[4][4];
154 float colorMatrix[4][4];
155 float opacity;
156 float width;
157 float masteringWhite;
158 float maxLum;
159 int redOrAlphaIndex;
160 int planeFormats[TextureDescription::maxPlanes];
161};
162
163struct Q_MULTIMEDIA_EXPORT SubtitleLayout
164{
165 QSize videoSize;
166 QRectF bounds;
167 QTextLayout layout;
168
169 bool update(const QSize &frameSize, QString text);
170 void draw(QPainter *painter, const QPointF &translate) const;
171 QImage toImage() const;
172};
173
174}
175
176QT_END_NAMESPACE
177
178#endif
179

source code of qtmultimedia/src/multimedia/video/qvideotexturehelper_p.h