Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qsgvideonode_p.cpp
Go to the documentation of this file.
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#include "qsgvideonode_p.h"
5#include "private/qmultimediautils_p.h"
6#include <QtQuick/qsgmaterial.h>
7#include "qsgvideotexture_p.h"
8#include <QtMultimedia/private/qvideotexturehelper_p.h>
9#include <private/qsginternaltextnode_p.h>
10#include <private/qquickitem_p.h>
11#include <private/qquickvideooutput_p.h>
12#include <private/qabstractvideobuffer_p.h>
13
15
16/* Helpers */
17static inline void qSetGeom(QSGGeometry::TexturedPoint2D *v, const QPointF &p)
18{
19 v->x = p.x();
20 v->y = p.y();
21}
22
23static inline void qSetTex(QSGGeometry::TexturedPoint2D *v, const QPointF &p)
24{
25 v->tx = p.x();
26 v->ty = p.y();
27}
28
30{
31 auto tvx = v0->tx;
32 auto tvy = v0->ty;
33 v0->tx = v1->tx;
34 v0->ty = v1->ty;
35 v1->tx = tvx;
36 v1->ty = tvy;
37}
38
40
42{
43public:
56
57 bool updateUniformData(RenderState &state, QSGMaterial *newMaterial,
58 QSGMaterial *oldMaterial) override;
59
60 void updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
61 QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
62
63protected:
67};
68
70{
71public:
72 QSGVideoMaterial(const QVideoFrameFormat &videoFormat);
73
74 [[nodiscard]] QSGMaterialType *type() const override {
75 static constexpr int NFormats = QRhiSwapChain::HDRExtendedDisplayP3Linear + 1;
78 }
79
83
84 int compare(const QSGMaterial *other) const override {
85 const QSGVideoMaterial *m = static_cast<const QSGVideoMaterial *>(other);
86
87 qint64 diff = m_textures[0].comparisonKey() - m->m_textures[0].comparisonKey();
88 if (!diff)
89 diff = m_textures[1].comparisonKey() - m->m_textures[1].comparisonKey();
90 if (!diff)
91 diff = m_textures[2].comparisonKey() - m->m_textures[2].comparisonKey();
92
93 return diff < 0 ? -1 : (diff > 0 ? 1 : 0);
94 }
95
97 // ### respect video formats with Alpha
99 }
100
103 m_texturesDirty = true;
104 }
105
106 void setSurfaceFormat(const QRhiSwapChain::Format surfaceFormat)
107 {
108 m_surfaceFormat = surfaceFormat;
109 }
110
111 void setHdrInfo(const QRhiSwapChainHdrInfo &hdrInfo)
112 {
113 m_hdrInfo = hdrInfo;
114 }
115
116 void updateTextures(QRhi *rhi, QRhiResourceUpdateBatch *resourceUpdates);
117
120 float m_opacity = 1.0f;
122
123 bool m_texturesDirty = false;
125
126 enum { NVideoFrameSlots = 4 };
128 std::array<QSGVideoTexture, 3> m_textures;
129 std::unique_ptr<QVideoFrameTextures> m_videoFrameTextures;
130};
131
133{
134 if (!m_texturesDirty)
135 return;
136
137 // keep the video frames alive until we know that they are not needed anymore
140
141 // update and upload all textures
144 return;
145
146 for (int plane = 0; plane < 3; ++plane)
147 m_textures[plane].setRhiTexture(m_videoFrameTextures->texture(plane));
148 m_texturesDirty = false;
149}
150
151
153 QSGMaterial *oldMaterial)
154{
155 Q_UNUSED(oldMaterial);
156
157 auto m = static_cast<QSGVideoMaterial *>(newMaterial);
158
159 if (!state.isMatrixDirty() && !state.isOpacityDirty())
160 return false;
161
162 if (state.isOpacityDirty()) {
163 m->m_opacity = state.opacity();
164 m->updateBlending();
165 }
166
167 // Do this here, not in updateSampledImage. First, with multiple textures we want to
168 // do this once. More importantly, on some platforms (Android) the externalMatrix is
169 // updated by this function and we need that already in updateUniformData.
170 m->updateTextures(state.rhi(), state.resourceUpdateBatch());
171
172 float maxNits = 100; // Default to de-facto SDR nits
175 maxNits = 100 * m_hdrInfo.limits.colorComponentValue.maxColorComponentValue;
176 else
177 maxNits = m_hdrInfo.limits.luminanceInNits.maxLuminance;
178 }
179
181 m->m_currentFrame, state.combinedMatrix(), state.opacity(), maxNits);
182
183 return true;
184}
185
187 QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
188{
190 Q_UNUSED(oldMaterial);
191 if (binding < 1 || binding > 3)
192 return;
193
194 auto m = static_cast<QSGVideoMaterial *>(newMaterial);
195 *texture = &m->m_textures[binding - 1];
196}
197
199 : m_videoFormat(videoFormat)
200{
201 setFlag(Blending, false);
202}
203
205 : m_parent(parent), m_videoFormat(videoFormat)
206{
209 m_material = new QSGVideoMaterial(videoFormat);
210 setMaterial(m_material);
211}
212
214{
215 delete m_subtitleTextNode;
216}
217
219{
220 m_material->setCurrentFrame(frame);
222 updateSubtitle(frame);
223}
224
226{
227 m_material->setSurfaceFormat(surfaceFormat);
229}
230
232{
233 m_material->setHdrInfo(hdrInfo);
235}
236
237void QSGVideoNode::updateSubtitle(const QVideoFrame &frame)
238{
239 QSize subtitleFrameSize = m_rect.size().toSize();
240 if (subtitleFrameSize.isEmpty())
241 return;
242
243 subtitleFrameSize = qRotatedFrameSize(subtitleFrameSize, m_orientation);
244
245 if (!m_subtitleLayout.update(subtitleFrameSize, frame.subtitleText()))
246 return;
247
248 delete m_subtitleTextNode;
249 m_subtitleTextNode = nullptr;
250 if (frame.subtitleText().isEmpty())
251 return;
252
253 QQuickItemPrivate *parent_d = QQuickItemPrivate::get(m_parent);
254
255 m_subtitleTextNode = parent_d->sceneGraphContext()->createInternalTextNode(parent_d->sceneGraphRenderContext());
256 m_subtitleTextNode->setColor(Qt::white);
257 QColor bgColor = Qt::black;
258 bgColor.setAlpha(128);
259 m_subtitleTextNode->addRectangleNode(m_subtitleLayout.bounds, bgColor);
260 m_subtitleTextNode->addTextLayout(m_subtitleLayout.layout.position(), &m_subtitleLayout.layout);
261 appendChildNode(m_subtitleTextNode);
262 setSubtitleGeometry();
263}
264
265void QSGVideoNode::setSubtitleGeometry()
266{
267 if (!m_subtitleTextNode)
268 return;
269
270 if (m_material)
271 updateSubtitle(m_material->m_currentFrame);
272
273 float rotate = -1.f * m_orientation;
274 float yTranslate = 0;
275 float xTranslate = 0;
276 if (m_orientation == 90) {
277 yTranslate = m_rect.height();
278 } else if (m_orientation == 180) {
279 yTranslate = m_rect.height();
280 xTranslate = m_rect.width();
281 } else if (m_orientation == 270) {
282 xTranslate = m_rect.width();
283 }
284
286 transform.translate(m_rect.x() + xTranslate, m_rect.y() + yTranslate);
287 transform.rotate(rotate, 0, 0, 1);
288
289 m_subtitleTextNode->setMatrix(transform);
290 m_subtitleTextNode->markDirty(DirtyGeometry);
291}
292
293/* Update the vertices and texture coordinates. Orientation must be in {0,90,180,270} */
294void QSGVideoNode::setTexturedRectGeometry(const QRectF &rect, const QRectF &textureRect, int orientation)
295{
296 const auto currentFrameOrientation = m_material ? static_cast<int>(m_material->m_currentFrame.rotation()) : 0;
297 bool frameChanged = false;
298 if (m_material) {
299 if (currentFrameOrientation != m_frameOrientation
300 || m_material->m_currentFrame.mirrored() != m_frameMirrored) {
301 frameChanged = true;
302 }
303 }
304 if (rect == m_rect && textureRect == m_textureRect && orientation == m_orientation
305 && !frameChanged)
306 return;
307
308 m_rect = rect;
309 m_textureRect = textureRect;
310 m_orientation = orientation;
311 if (m_material) {
312 m_frameOrientation = currentFrameOrientation;
313 m_frameMirrored = m_material->m_currentFrame.mirrored();
314 }
315 const int videoRotation = (orientation + currentFrameOrientation) % 360;
316
318
319 if (g == nullptr)
321
322 QSGGeometry::TexturedPoint2D *v = g->vertexDataAsTexturedPoint2D();
323
324 // Set geometry first
325 qSetGeom(v + 0, rect.topLeft());
326 qSetGeom(v + 1, rect.bottomLeft());
327 qSetGeom(v + 2, rect.topRight());
328 qSetGeom(v + 3, rect.bottomRight());
329
330 // and then texture coordinates
331 switch (videoRotation) {
332 default:
333 // tl, bl, tr, br
334 qSetTex(v + 0, textureRect.topLeft());
335 qSetTex(v + 1, textureRect.bottomLeft());
336 qSetTex(v + 2, textureRect.topRight());
337 qSetTex(v + 3, textureRect.bottomRight());
338 break;
339
340 case 90:
341 // bl, br, tl, tr
342 qSetTex(v + 0, textureRect.bottomLeft());
343 qSetTex(v + 1, textureRect.bottomRight());
344 qSetTex(v + 2, textureRect.topLeft());
345 qSetTex(v + 3, textureRect.topRight());
346 break;
347
348 case 180:
349 // br, tr, bl, tl
350 qSetTex(v + 0, textureRect.bottomRight());
351 qSetTex(v + 1, textureRect.topRight());
352 qSetTex(v + 2, textureRect.bottomLeft());
353 qSetTex(v + 3, textureRect.topLeft());
354 break;
355
356 case 270:
357 // tr, tl, br, bl
358 qSetTex(v + 0, textureRect.topRight());
359 qSetTex(v + 1, textureRect.topLeft());
360 qSetTex(v + 2, textureRect.bottomRight());
361 qSetTex(v + 3, textureRect.bottomLeft());
362 break;
363 }
364
365 if (m_material && m_material->m_currentFrame.mirrored()) {
366 qSwapTex(v + 0, v + 2);
367 qSwapTex(v + 1, v + 3);
368 }
369
370 if (!geometry())
371 setGeometry(g);
372
374
375 setSubtitleGeometry();
376}
377
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
void setAlpha(int alpha)
Sets the alpha of this color to alpha.
Definition qcolor.cpp:1481
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
Definition qmatrix4x4.h:25
void translate(const QVector3D &vector)
Multiplies this matrix by another that translates coordinates by the components of vector.
\inmodule QtCore\reentrant
Definition qpoint.h:217
static QQuickItemPrivate * get(QQuickItem *item)
Render video or camera viewfinder.
\inmodule QtCore\reentrant
Definition qrect.h:484
constexpr qreal y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:672
constexpr qreal height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:732
constexpr qreal width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:729
constexpr qreal x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:669
constexpr QSizeF size() const noexcept
Returns the size of the rectangle.
Definition qrect.h:735
\inmodule QtGui
Definition qrhi.h:1731
Format
Describes the swapchain format.
Definition qrhi.h:1561
@ HDRExtendedSrgbLinear
Definition qrhi.h:1563
@ HDRExtendedDisplayP3Linear
Definition qrhi.h:1565
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
Definition qrhi.h:1804
int resourceLimit(ResourceLimit limit) const
Definition qrhi.cpp:10121
int currentFrameSlot() const
Definition qrhi.cpp:10846
@ FramesInFlight
Definition qrhi.h:1890
const QSGGeometry * geometry() const
Returns this node's geometry.
Definition qsgnode.h:160
void setGeometry(QSGGeometry *geometry)
Sets the geometry of this node to geometry.
Definition qsgnode.cpp:764
void setMaterial(QSGMaterial *material)
Sets the material of this geometry node to material.
Definition qsgnode.cpp:927
The QSGGeometry class provides low-level storage for graphics primitives in the \l{Qt Quick Scene Gra...
Definition qsggeometry.h:15
static const AttributeSet & defaultAttributes_TexturedPoint2D()
Convenience function which returns attributes to be used for textured 2D drawing.
void setColor(QColor color) override
Sets the main color to use when rendering the text to color.
void addRectangleNode(const QRectF &rect, const QColor &color)
Encapsulates the current rendering state during a call to QSGMaterialShader::updateUniformData() and ...
The QSGMaterialShader class represents a graphics API independent shader program.
void setShaderFileName(Stage stage, const QString &filename)
Sets the filename for the shader for the specified stage.
The QSGMaterial class encapsulates rendering state for a shader program.
Definition qsgmaterial.h:15
void setFlag(Flags flags, bool on=true)
Sets the flags flags on this material if on is true; otherwise clears the attribute.
@ DirtyMaterial
Definition qsgnode.h:75
@ DirtyGeometry
Definition qsgnode.h:74
@ OwnsMaterial
Definition qsgnode.h:58
@ OwnsGeometry
Definition qsgnode.h:57
void appendChildNode(QSGNode *node)
Appends node to this node's list of children.
Definition qsgnode.cpp:398
void markDirty(DirtyState bits)
Notifies all connected renderers that the node has dirty bits.
Definition qsgnode.cpp:624
void setFlag(Flag, bool=true)
Sets the flag f on this node if enabled is true; otherwise clears the flag.
Definition qsgnode.cpp:586
RenderMode
\value RenderMode2D Normal 2D rendering \value RenderMode2DNoDepthBuffer Normal 2D rendering with dep...
void addTextLayout(QPointF position, QTextLayout *layout, int selectionStart=-1, int selectionCount=-1, int lineStart=0, int lineCount=-1)
Adds the contents of layout to the text node at position.
Definition qsgtextnode.h:67
\inmodule QtQuick
Definition qsgtexture.h:20
void setMatrix(const QMatrix4x4 &matrix)
Sets this transform node's matrix to matrix.
Definition qsgnode.cpp:1162
QVideoFrameFormat m_videoFormat
QRhiSwapChainHdrInfo m_hdrInfo
bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override
This function is called by the scene graph to get the contents of the shader program's uniform buffer...
QRhiSwapChain::Format m_surfaceFormat
void updateSampledImage(RenderState &state, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override
This function is called by the scene graph to prepare use of sampled images in the shader,...
QSGVideoMaterialRhiShader(const QVideoFrameFormat &videoFormat, const QRhiSwapChain::Format surfaceFormat, const QRhiSwapChainHdrInfo &hdrInfo)
QVideoFrame m_videoFrameSlots[NVideoFrameSlots]
QSGVideoMaterial(const QVideoFrameFormat &videoFormat)
QVideoFrame m_currentFrame
QSGMaterialShader * createShader(QSGRendererInterface::RenderMode) const override
This function returns a new instance of a the QSGMaterialShader implementation used to render geometr...
QSGMaterialType * type() const override
This function is called by the scene graph to query an identifier that is unique to the QSGMaterialSh...
void updateTextures(QRhi *rhi, QRhiResourceUpdateBatch *resourceUpdates)
void setHdrInfo(const QRhiSwapChainHdrInfo &hdrInfo)
void setCurrentFrame(const QVideoFrame &frame)
int compare(const QSGMaterial *other) const override
Compares this material to other and returns 0 if they are equal; -1 if this material should sort befo...
QRhiSwapChainHdrInfo m_hdrInfo
void setSurfaceFormat(const QRhiSwapChain::Format surfaceFormat)
std::unique_ptr< QVideoFrameTextures > m_videoFrameTextures
std::array< QSGVideoTexture, 3 > m_textures
QRhiSwapChain::Format m_surfaceFormat
QVideoFrameFormat m_videoFormat
void setHdrInfo(const QRhiSwapChainHdrInfo &hdrInfo)
void setTexturedRectGeometry(const QRectF &boundingRect, const QRectF &textureRect, int orientation)
void setSurfaceFormat(const QRhiSwapChain::Format surfaceFormat)
QSGVideoNode(QQuickVideoOutput *parent, const QVideoFrameFormat &videoFormat)
void setCurrentFrame(const QVideoFrame &frame)
\inmodule QtCore
Definition qsize.h:25
QPointF position() const
The QVideoFrameFormat class specifies the stream format of a video presentation surface.
QVideoFrameFormat::PixelFormat pixelFormat() const
Returns the pixel format of frames in a video stream.
static constexpr int NPixelFormats
The QVideoFrame class represents a frame of video data.
Definition qvideoframe.h:27
QtVideo::Rotation rotation() const
Returns the angle the frame should be rotated clockwise before displaying.
bool mirrored() const
Returns whether the frame should be mirrored before displaying.
rect
[4]
else opt state
[0]
QVector3D Q_QUICK3DUTILS_EXPORT rotate(const QMatrix4x4 &m, const QVector3D &v)
Definition qssgutils.cpp:75
Combined button and popup list for selecting options.
QString vertexShaderFileName(const QVideoFrameFormat &format)
QString fragmentShaderFileName(const QVideoFrameFormat &format, QRhiSwapChain::Format surfaceFormat)
std::unique_ptr< QVideoFrameTextures > createTextures(QVideoFrame &frame, QRhi *rhi, QRhiResourceUpdateBatch *rub, std::unique_ptr< QVideoFrameTextures > &&oldTextures)
void updateUniformData(QByteArray *dst, const QVideoFrameFormat &format, const QVideoFrame &frame, const QMatrix4x4 &transform, float opacity, float maxNits)
@ white
Definition qnamespace.h:31
@ black
Definition qnamespace.h:30
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
Definition qfloat16.h:333
QSize qRotatedFrameSize(QSize size, int rotation)
GLsizei const GLfloat * v
[13]
const GLfloat * m
GLenum type
GLint GLfloat v0
GLint GLfloat GLfloat v1
GLenum GLuint texture
GLboolean GLboolean g
GLuint GLenum GLenum transform
GLfloat GLfloat p
[1]
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
static void qSetTex(QSGGeometry::TexturedPoint2D *v, const QPointF &p)
static QT_BEGIN_NAMESPACE void qSetGeom(QSGGeometry::TexturedPoint2D *v, const QPointF &p)
static void qSwapTex(QSGGeometry::TexturedPoint2D *v0, QSGGeometry::TexturedPoint2D *v1)
#define Q_UNUSED(x)
long long qint64
Definition qtypes.h:60
QSharedPointer< T > other(t)
[5]
QFrame frame
[0]
\inmodule QtGui
Definition qrhi.h:1511
union QRhiSwapChainHdrInfo::@295 limits
LimitsType limitsType
Definition qrhi.h:1522
The QSGGeometry::TexturedPoint2D struct is a convenience struct for accessing 2D Points with texture ...
Definition qsggeometry.h:85
The QSGMaterialType class is used as a unique type token in combination with QSGMaterial.
bool update(const QSize &frameSize, QString text)