Qt 6.x
The Qt SDK
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 <QtQuick/qsgmaterial.h>
6#include "qsgvideotexture_p.h"
7#include <QtMultimedia/private/qvideotexturehelper_p.h>
8#include <private/qquicktextnode_p.h>
9#include <private/qquickvideooutput_p.h>
10#include <private/qabstractvideobuffer_p.h>
11#include <qmutex.h>
12
14
15/* Helpers */
16static inline void qSetGeom(QSGGeometry::TexturedPoint2D *v, const QPointF &p)
17{
18 v->x = p.x();
19 v->y = p.y();
20}
21
22static inline void qSetTex(QSGGeometry::TexturedPoint2D *v, const QPointF &p)
23{
24 v->tx = p.x();
25 v->ty = p.y();
26}
27
29{
30 auto tvx = v0->tx;
31 auto tvy = v0->ty;
32 v0->tx = v1->tx;
33 v0->ty = v1->ty;
34 v1->tx = tvx;
35 v1->ty = tvy;
36}
37
39
41{
42public:
45 {
48 }
49
50 bool updateUniformData(RenderState &state, QSGMaterial *newMaterial,
51 QSGMaterial *oldMaterial) override;
52
53 void updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
54 QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
55
56protected:
58 float m_planeWidth[3] = {0, 0, 0};
60};
61
63{
64public:
66
67 [[nodiscard]] QSGMaterialType *type() const override {
69 return &type[m_format.pixelFormat()];
70 }
71
74 }
75
76 int compare(const QSGMaterial *other) const override {
77 const QSGVideoMaterial *m = static_cast<const QSGVideoMaterial *>(other);
78
79 qint64 diff = m_textures[0]->comparisonKey() - m->m_textures[0]->comparisonKey();
80 if (!diff)
81 diff = m_textures[1]->comparisonKey() - m->m_textures[1]->comparisonKey();
82 if (!diff)
83 diff = m_textures[2]->comparisonKey() - m->m_textures[2]->comparisonKey();
84
85 return diff < 0 ? -1 : (diff > 0 ? 1 : 0);
86 }
87
89 // ### respect video formats with Alpha
91 }
92
96 m_texturesDirty = true;
97 }
98
99 void updateTextures(QRhi *rhi, QRhiResourceUpdateBatch *resourceUpdates);
100
102 float m_planeWidth[3];
104
106 bool m_texturesDirty = false;
108
109 enum { NVideoFrameSlots = 4 };
112 std::unique_ptr<QVideoFrameTextures> m_videoFrameTextures;
113};
114
116{
117 QMutexLocker locker(&m_frameMutex);
118 if (!m_texturesDirty)
119 return;
120
121 // keep the video frames alive until we know that they are not needed anymore
124
125 // update and upload all textures
127 for (int plane = 0; plane < 3; ++plane)
128 m_textures[plane]->setRhiTexture(m_videoFrameTextures->texture(plane));
129 m_texturesDirty = false;
130}
131
132
134 QSGMaterial *oldMaterial)
135{
136 Q_UNUSED(oldMaterial);
137
138 auto m = static_cast<QSGVideoMaterial *>(newMaterial);
139
140 if (!state.isMatrixDirty() && !state.isOpacityDirty())
141 return false;
142
143 if (state.isOpacityDirty()) {
144 m->m_opacity = state.opacity();
145 m->updateBlending();
146 }
147
148 // Do this here, not in updateSampledImage. First, with multiple textures we want to
149 // do this once. More importantly, on some platforms (Android) the externalMatrix is
150 // updated by this function and we need that already in updateUniformData.
151 m->updateTextures(state.rhi(), state.resourceUpdateBatch());
152
153 m_format.updateUniformData(state.uniformData(), m->m_currentFrame,
154 state.combinedMatrix(), state.opacity());
155
156 return true;
157}
158
160 QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
161{
163 Q_UNUSED(oldMaterial);
164 if (binding < 1 || binding > 3)
165 return;
166
167 auto m = static_cast<QSGVideoMaterial *>(newMaterial);
168 *texture = m->m_textures[binding - 1].data();
169}
170
172 m_format(format),
173 m_opacity(1.0)
174{
178
179 setFlag(Blending, false);
180}
181
183 : m_parent(parent),
184 m_orientation(-1),
185 m_frameOrientation(-1),
186 m_frameMirrored(false),
187 m_format(format)
188{
191 m_material = new QSGVideoMaterial(format);
192 setMaterial(m_material);
193}
194
196{
197 delete m_subtitleTextNode;
198}
199
201{
202 m_material->setCurrentFrame(frame);
204 updateSubtitle(frame);
205}
206
207void QSGVideoNode::updateSubtitle(const QVideoFrame &frame)
208{
209 QSize subtitleFrameSize = m_rect.size().toSize();
210 if (subtitleFrameSize.isEmpty())
211 return;
212 if (m_orientation % 180)
213 subtitleFrameSize.transpose();
214 if (!m_subtitleLayout.update(subtitleFrameSize, frame.subtitleText()))
215 return;
216
217 delete m_subtitleTextNode;
218 m_subtitleTextNode = nullptr;
219 if (frame.subtitleText().isEmpty())
220 return;
221
222 m_subtitleTextNode = new QQuickTextNode(m_parent);
223 QColor bgColor = Qt::black;
224 bgColor.setAlpha(128);
225 m_subtitleTextNode->addRectangleNode(m_subtitleLayout.bounds, bgColor);
226 m_subtitleTextNode->addTextLayout(m_subtitleLayout.layout.position(), &m_subtitleLayout.layout, Qt::white);
227 appendChildNode(m_subtitleTextNode);
228 setSubtitleGeometry();
229}
230
231void QSGVideoNode::setSubtitleGeometry()
232{
233 if (!m_subtitleTextNode)
234 return;
235
236 if (m_material)
237 updateSubtitle(m_material->m_currentFrame);
238
239 float rotate = -1.f * m_orientation;
240 float yTranslate = 0;
241 float xTranslate = 0;
242 if (m_orientation == 90) {
243 yTranslate = m_rect.height();
244 } else if (m_orientation == 180) {
245 yTranslate = m_rect.height();
246 xTranslate = m_rect.width();
247 } else if (m_orientation == 270) {
248 xTranslate = m_rect.width();
249 }
250
252 transform.translate(m_rect.x() + xTranslate, m_rect.y() + yTranslate);
253 transform.rotate(rotate, 0, 0, 1);
254
255 m_subtitleTextNode->setMatrix(transform);
256 m_subtitleTextNode->markDirty(DirtyGeometry);
257}
258
259/* Update the vertices and texture coordinates. Orientation must be in {0,90,180,270} */
260void QSGVideoNode::setTexturedRectGeometry(const QRectF &rect, const QRectF &textureRect, int orientation)
261{
262 bool frameChanged = false;
263 if (m_material) {
264 if (m_material->m_currentFrame.rotationAngle() != m_frameOrientation
265 || m_material->m_currentFrame.mirrored() != m_frameMirrored) {
266 frameChanged = true;
267 }
268 }
269 if (rect == m_rect && textureRect == m_textureRect && orientation == m_orientation
270 && !frameChanged)
271 return;
272
273 m_rect = rect;
274 m_textureRect = textureRect;
275 m_orientation = orientation;
276 if (m_material) {
277 m_frameOrientation = m_material->m_currentFrame.rotationAngle();
278 m_frameMirrored = m_material->m_currentFrame.mirrored();
279 }
280 int videoRotation = orientation;
281 videoRotation += m_material ? m_material->m_currentFrame.rotationAngle() : 0;
282 videoRotation %= 360;
283
285
286 if (g == nullptr)
288
289 QSGGeometry::TexturedPoint2D *v = g->vertexDataAsTexturedPoint2D();
290
291 // Set geometry first
292 qSetGeom(v + 0, rect.topLeft());
293 qSetGeom(v + 1, rect.bottomLeft());
294 qSetGeom(v + 2, rect.topRight());
295 qSetGeom(v + 3, rect.bottomRight());
296
297 // and then texture coordinates
298 switch (videoRotation) {
299 default:
300 // tl, bl, tr, br
301 qSetTex(v + 0, textureRect.topLeft());
302 qSetTex(v + 1, textureRect.bottomLeft());
303 qSetTex(v + 2, textureRect.topRight());
304 qSetTex(v + 3, textureRect.bottomRight());
305 break;
306
307 case 90:
308 // bl, br, tl, tr
309 qSetTex(v + 0, textureRect.bottomLeft());
310 qSetTex(v + 1, textureRect.bottomRight());
311 qSetTex(v + 2, textureRect.topLeft());
312 qSetTex(v + 3, textureRect.topRight());
313 break;
314
315 case 180:
316 // br, tr, bl, tl
317 qSetTex(v + 0, textureRect.bottomRight());
318 qSetTex(v + 1, textureRect.topRight());
319 qSetTex(v + 2, textureRect.bottomLeft());
320 qSetTex(v + 3, textureRect.topLeft());
321 break;
322
323 case 270:
324 // tr, tl, br, bl
325 qSetTex(v + 0, textureRect.topRight());
326 qSetTex(v + 1, textureRect.topLeft());
327 qSetTex(v + 2, textureRect.bottomRight());
328 qSetTex(v + 3, textureRect.bottomLeft());
329 break;
330 }
331
332 if (m_material && m_material->m_currentFrame.mirrored()) {
333 qSwapTex(v + 0, v + 2);
334 qSwapTex(v + 1, v + 3);
335 }
336
337 if (!geometry())
338 setGeometry(g);
339
341
342 setSubtitleGeometry();
343}
344
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
\inmodule QtCore
Definition qmutex.h:317
\inmodule QtCore
Definition qmutex.h:285
\inmodule QtCore\reentrant
Definition qpoint.h:214
void addRectangleNode(const QRectF &rect, const QColor &color)
void addTextLayout(const QPointF &position, QTextLayout *textLayout, const QColor &color=QColor(), QQuickText::TextStyle style=QQuickText::Normal, const QColor &styleColor=QColor(), const QColor &anchorColor=QColor(), const QColor &selectionColor=QColor(), const QColor &selectedTextColor=QColor(), int selectionStart=-1, int selectionEnd=-1, int lineStart=0, int lineCount=-1)
Render video or camera viewfinder.
\inmodule QtCore\reentrant
Definition qrect.h:483
constexpr qreal y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:658
constexpr qreal height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:718
constexpr qreal width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:715
constexpr qreal x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:655
constexpr QPointF bottomLeft() const noexcept
Returns the position of the rectangle's bottom-left corner.
Definition qrect.h:513
constexpr QPointF topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
Definition qrect.h:510
constexpr QPointF bottomRight() const noexcept
Returns the position of the rectangle's bottom-right corner.
Definition qrect.h:511
constexpr QSizeF size() const noexcept
Returns the size of the rectangle.
Definition qrect.h:721
constexpr QPointF topRight() const noexcept
Returns the position of the rectangle's top-right corner.
Definition qrect.h:512
\inmodule QtGui
Definition qrhi.h:1694
\inmodule QtGui
Definition qrhi.h:1767
int resourceLimit(ResourceLimit limit) const
Definition qrhi.cpp:9692
int currentFrameSlot() const
Definition qrhi.cpp:10409
@ FramesInFlight
Definition qrhi.h:1850
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:762
void setMaterial(QSGMaterial *material)
Sets the material of this geometry node to material.
Definition qsgnode.cpp:925
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.
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:396
void markDirty(DirtyState bits)
Notifies all connected renderers that the node has dirty bits.
Definition qsgnode.cpp:622
void setFlag(Flag, bool=true)
Sets the flag f on this node if enabled is true; otherwise clears the flag.
Definition qsgnode.cpp:584
RenderMode
\value RenderMode2D Normal 2D rendering \value RenderMode2DNoDepthBuffer Normal 2D rendering with dep...
\inmodule QtQuick
Definition qsgtexture.h:20
void setMatrix(const QMatrix4x4 &matrix)
Sets this transform node's matrix to matrix.
Definition qsgnode.cpp:1160
QSGVideoMaterialRhiShader(const QVideoFrameFormat &format)
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...
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,...
QVideoFrame m_videoFrameSlots[NVideoFrameSlots]
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)
QSGVideoMaterial(const QVideoFrameFormat &format)
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...
QVideoFrameFormat m_format
std::unique_ptr< QVideoFrameTextures > m_videoFrameTextures
QScopedPointer< QSGVideoTexture > m_textures[3]
void setTexturedRectGeometry(const QRectF &boundingRect, const QRectF &textureRect, int orientation)
QSGVideoNode(QQuickVideoOutput *parent, const QVideoFrameFormat &format)
void setCurrentFrame(const QVideoFrame &frame)
qint64 comparisonKey() const override
Returns a key suitable for comparing textures.
\inmodule QtCore
T * data() const noexcept
Returns the value of the pointer referenced by this object.
void reset(T *other=nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval< T * >())))
Deletes the existing object it is pointing to (if any), and sets its pointer to other.
constexpr QSize toSize() const noexcept
Returns an integer based copy of this size.
Definition qsize.h:390
\inmodule QtCore
Definition qsize.h:25
constexpr bool isEmpty() const noexcept
Returns true if either of the width and height is less than or equal to 0; otherwise returns false.
Definition qsize.h:123
void transpose() noexcept
Swaps the width and height values.
Definition qsize.cpp:130
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.
void updateUniformData(QByteArray *dst, const QVideoFrame &frame, const QMatrix4x4 &transform, float opacity) const
static constexpr int NPixelFormats
QString fragmentShaderFileName() const
QString vertexShaderFileName() const
The QVideoFrame class represents a frame of video data.
Definition qvideoframe.h:26
bool mirrored() const
Returns whether the frame should be mirrored before displaying.
RotationAngle rotationAngle() const
Returns the angle the frame should be rotated clockwise before displaying.
rect
[4]
else opt state
[0]
Combined button and popup list for selecting options.
std::unique_ptr< QVideoFrameTextures > createTextures(QVideoFrame &frame, QRhi *rhi, QRhiResourceUpdateBatch *rub, std::unique_ptr< QVideoFrameTextures > &&oldTextures)
@ white
Definition qnamespace.h:30
@ black
Definition qnamespace.h:29
QVector3D Q_QUICK3DUTILS_EXPORT rotate(const QMatrix4x4 &m, const QVector3D &v)
Definition qssgutils.cpp:75
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
Definition qfloat16.h:287
GLsizei const GLfloat * v
[13]
const GLfloat * m
GLenum type
GLint GLfloat v0
GLint GLfloat GLfloat v1
GLenum GLuint texture
GLboolean GLboolean g
GLint GLsizei GLsizei GLenum format
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:55
QReadWriteLock lock
[0]
QSharedPointer< T > other(t)
[5]
QFrame frame
[0]
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)
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent