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
qvideoframeconverter.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 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
6#include "qvideoframeformat.h"
7#include "qvideoframe_p.h"
9
10#include <QtCore/qcoreapplication.h>
11#include <QtCore/qsize.h>
12#include <QtCore/qhash.h>
13#include <QtCore/qfile.h>
14#include <QtCore/qthreadstorage.h>
15#include <QtGui/qimage.h>
16#include <QtGui/qoffscreensurface.h>
17#include <qpa/qplatformintegration.h>
18#include <private/qvideotexturehelper_p.h>
19#include <private/qabstractvideobuffer_p.h>
20#include <private/qguiapplication_p.h>
21#include <rhi/qrhi.h>
22
23#ifdef Q_OS_DARWIN
24#include <QtCore/private/qcore_mac_p.h>
25#endif
26
28
29static Q_LOGGING_CATEGORY(qLcVideoFrameConverter, "qt.multimedia.video.frameconverter")
30
31namespace {
32
33struct State
34{
35 QRhi *rhi = nullptr;
36#if QT_CONFIG(opengl)
37 QOffscreenSurface *fallbackSurface = nullptr;
38#endif
39 bool cpuOnly = false;
40#if defined(Q_OS_ANDROID)
41 QMetaObject::Connection appStateChangedConnection;
42#endif
43 ~State() {
44 resetRhi();
45 }
46
47 void resetRhi() {
48 delete rhi;
49 rhi = nullptr;
50#if QT_CONFIG(opengl)
51 delete fallbackSurface;
52 fallbackSurface = nullptr;
53#endif
54 cpuOnly = false;
55 }
56};
57
58}
59
60static QThreadStorage<State> g_state;
61static QHash<QString, QShader> g_shaderCache;
62
63static const float g_quad[] = {
64 // Rotation 0 CW
65 1.f, -1.f, 1.f, 1.f,
66 1.f, 1.f, 1.f, 0.f,
67 -1.f, -1.f, 0.f, 1.f,
68 -1.f, 1.f, 0.f, 0.f,
69 // Rotation 90 CW
70 1.f, -1.f, 1.f, 0.f,
71 1.f, 1.f, 0.f, 0.f,
72 -1.f, -1.f, 1.f, 1.f,
73 -1.f, 1.f, 0.f, 1.f,
74 // Rotation 180 CW
75 1.f, -1.f, 0.f, 0.f,
76 1.f, 1.f, 0.f, 1.f,
77 -1.f, -1.f, 1.f, 0.f,
78 -1.f, 1.f, 1.f, 1.f,
79 // Rotation 270 CW
80 1.f, -1.f, 0.f, 1.f,
81 1.f, 1.f, 1.f, 1.f,
82 -1.f, -1.f, 0.f, 0.f,
83 -1.f, 1.f, 1.f, 0.f,
84};
85
102
104{
106 if (shader.isValid())
107 return shader;
108
109 QFile f(name);
110 if (f.open(QIODevice::ReadOnly))
111 shader = QShader::fromSerialized(f.readAll());
112
113 if (shader.isValid())
115
116 return shader;
117}
118
120 bool mirrorX, bool mirrorY)
121{
123 if (mirrorX)
124 t.scale(-1.f, 1.f);
125 if (rotation != QtVideo::Rotation::None)
126 t.rotate(float(rotation));
127 if (mirrorY)
128 t.scale(1.f, -1.f);
129 if (!t.isIdentity())
130 image = image.transformed(t);
131}
132
133static void imageCleanupHandler(void *info)
134{
135 QByteArray *imageData = reinterpret_cast<QByteArray *>(info);
136 delete imageData;
137}
138
139static QRhi *initializeRHI(QRhi *videoFrameRhi)
140{
141 if (g_state.localData().rhi || g_state.localData().cpuOnly)
142 return g_state.localData().rhi;
143
144 QRhi::Implementation backend = videoFrameRhi ? videoFrameRhi->backend() : QRhi::Null;
145
147
148#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
149 if (backend == QRhi::Metal || backend == QRhi::Null) {
151 g_state.localData().rhi = QRhi::create(QRhi::Metal, &params);
152 }
153#endif
154
155#if defined(Q_OS_WIN)
156 if (backend == QRhi::D3D11 || backend == QRhi::Null) {
158 g_state.localData().rhi = QRhi::create(QRhi::D3D11, &params);
159 }
160#endif
161
162#if QT_CONFIG(opengl)
163 if (!g_state.localData().rhi && (backend == QRhi::OpenGLES2 || backend == QRhi::Null)) {
167
168 g_state.localData().fallbackSurface = QRhiGles2InitParams::newFallbackSurface();
170 params.fallbackSurface = g_state.localData().fallbackSurface;
171 if (backend == QRhi::OpenGLES2)
172 params.shareContext = static_cast<const QRhiGles2NativeHandles*>(videoFrameRhi->nativeHandles())->context;
173 g_state.localData().rhi = QRhi::create(QRhi::OpenGLES2, &params);
174
175#if defined(Q_OS_ANDROID)
176 // reset RHI state on application suspension, as this will be invalid after resuming
177 if (!g_state.localData().appStateChangedConnection) {
178 g_state.localData().appStateChangedConnection = QObject::connect(qApp, &QGuiApplication::applicationStateChanged, qApp, [](auto state) {
180 g_state.localData().resetRhi();
181 });
182 }
183#endif
184 }
185 }
186#endif
187 }
188
189 if (!g_state.localData().rhi) {
190 g_state.localData().cpuOnly = true;
191 qWarning() << Q_FUNC_INFO << ": No RHI backend. Using CPU conversion.";
192 }
193
194 return g_state.localData().rhi;
195}
196
197static bool updateTextures(QRhi *rhi,
198 std::unique_ptr<QRhiBuffer> &uniformBuffer,
199 std::unique_ptr<QRhiSampler> &textureSampler,
200 std::unique_ptr<QRhiShaderResourceBindings> &shaderResourceBindings,
201 std::unique_ptr<QRhiGraphicsPipeline> &graphicsPipeline,
202 std::unique_ptr<QRhiRenderPassDescriptor> &renderPass,
204 const std::unique_ptr<QVideoFrameTextures> &videoFrameTextures)
205{
206 auto format = frame.surfaceFormat();
207 auto pixelFormat = format.pixelFormat();
208
209 auto textureDesc = QVideoTextureHelper::textureDescription(pixelFormat);
210
211 QRhiShaderResourceBinding bindings[4];
212 auto *b = bindings;
214 uniformBuffer.get());
215 for (int i = 0; i < textureDesc->nplanes; ++i)
217 videoFrameTextures->texture(i), textureSampler.get());
218 shaderResourceBindings->setBindings(bindings, b);
219 shaderResourceBindings->create();
220
221 graphicsPipeline.reset(rhi->newGraphicsPipeline());
222 graphicsPipeline->setTopology(QRhiGraphicsPipeline::TriangleStrip);
223
225 if (!vs.isValid())
226 return false;
227
229 if (!fs.isValid())
230 return false;
231
232 graphicsPipeline->setShaderStages({
235 });
236
237 QRhiVertexInputLayout inputLayout;
238 inputLayout.setBindings({
239 { 4 * sizeof(float) }
240 });
241 inputLayout.setAttributes({
243 { 0, 1, QRhiVertexInputAttribute::Float2, 2 * sizeof(float) }
244 });
245
246 graphicsPipeline->setVertexInputLayout(inputLayout);
247 graphicsPipeline->setShaderResourceBindings(shaderResourceBindings.get());
248 graphicsPipeline->setRenderPassDescriptor(renderPass.get());
249 graphicsPipeline->create();
250
251 return true;
252}
253
254static QImage convertJPEG(const QVideoFrame &frame, QtVideo::Rotation rotation, bool mirrorX, bool mirrorY)
255{
256 QVideoFrame varFrame = frame;
257 if (!varFrame.map(QVideoFrame::ReadOnly)) {
258 qCDebug(qLcVideoFrameConverter) << Q_FUNC_INFO << ": frame mapping failed";
259 return {};
260 }
262 image.loadFromData(varFrame.bits(0), varFrame.mappedBytes(0), "JPG");
263 varFrame.unmap();
264 rasterTransform(image, rotation, mirrorX, mirrorY);
265 return image;
266}
267
268static QImage convertCPU(const QVideoFrame &frame, QtVideo::Rotation rotation, bool mirrorX, bool mirrorY)
269{
270 VideoFrameConvertFunc convert = qConverterForFormat(frame.pixelFormat());
271 if (!convert) {
272 qCDebug(qLcVideoFrameConverter) << Q_FUNC_INFO << ": unsupported pixel format" << frame.pixelFormat();
273 return {};
274 } else {
275 QVideoFrame varFrame = frame;
276 if (!varFrame.map(QVideoFrame::ReadOnly)) {
277 qCDebug(qLcVideoFrameConverter) << Q_FUNC_INFO << ": frame mapping failed";
278 return {};
279 }
281 QImage image = QImage(varFrame.width(), varFrame.height(), format);
282 convert(varFrame, image.bits());
283 varFrame.unmap();
284 rasterTransform(image, rotation, mirrorX, mirrorY);
285 return image;
286 }
287}
288
289QImage qImageFromVideoFrame(const QVideoFrame &frame, QtVideo::Rotation rotation, bool mirrorX, bool mirrorY)
290{
291#ifdef Q_OS_DARWIN
292 QMacAutoReleasePool releasePool;
293#endif
294
295 if (!g_state.hasLocalData())
296 g_state.setLocalData({});
297
298 std::unique_ptr<QRhiRenderPassDescriptor> renderPass;
299 std::unique_ptr<QRhiBuffer> vertexBuffer;
300 std::unique_ptr<QRhiBuffer> uniformBuffer;
301 std::unique_ptr<QRhiTexture> targetTexture;
302 std::unique_ptr<QRhiTextureRenderTarget> renderTarget;
303 std::unique_ptr<QRhiSampler> textureSampler;
304 std::unique_ptr<QRhiShaderResourceBindings> shaderResourceBindings;
305 std::unique_ptr<QRhiGraphicsPipeline> graphicsPipeline;
306
307 if (frame.size().isEmpty() || frame.pixelFormat() == QVideoFrameFormat::Format_Invalid)
308 return {};
309
310 if (frame.pixelFormat() == QVideoFrameFormat::Format_Jpeg)
311 return convertJPEG(frame, rotation, mirrorX, mirrorY);
312
313 QRhi *rhi = nullptr;
314
315 if (frame.videoBuffer())
316 rhi = frame.videoBuffer()->rhi();
317
318 if (!rhi || rhi->thread() != QThread::currentThread())
319 rhi = initializeRHI(rhi);
320
321 if (!rhi || rhi->isRecordingFrame())
322 return convertCPU(frame, rotation, mirrorX, mirrorY);
323
324 // Do conversion using shaders
325
326 const QSize frameSize = qRotatedFrameSize(frame.size(), rotation);
327
328 vertexBuffer.reset(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(g_quad)));
329 vertexBuffer->create();
330
331 uniformBuffer.reset(rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64 + 64 + 4 + 4 + 4 + 4));
332 uniformBuffer->create();
333
336 textureSampler->create();
337
338 shaderResourceBindings.reset(rhi->newShaderResourceBindings());
339
341 if (!targetTexture->create()) {
342 qCDebug(qLcVideoFrameConverter) << "Failed to create target texture. Using CPU conversion.";
343 return convertCPU(frame, rotation, mirrorX, mirrorY);
344 }
345
346 renderTarget.reset(rhi->newTextureRenderTarget({ { targetTexture.get() } }));
347 renderPass.reset(renderTarget->newCompatibleRenderPassDescriptor());
348 renderTarget->setRenderPassDescriptor(renderPass.get());
349 renderTarget->create();
350
351 QRhiCommandBuffer *cb = nullptr;
352 QRhi::FrameOpResult r = rhi->beginOffscreenFrame(&cb);
353 if (r != QRhi::FrameOpSuccess) {
354 qCDebug(qLcVideoFrameConverter) << "Failed to set up offscreen frame. Using CPU conversion.";
355 return convertCPU(frame, rotation, mirrorX, mirrorY);
356 }
357
358 QRhiResourceUpdateBatch *rub = rhi->nextResourceUpdateBatch();
359
360 rub->uploadStaticBuffer(vertexBuffer.get(), g_quad);
361
362 QVideoFrame frameTmp = frame;
363 auto videoFrameTextures = QVideoTextureHelper::createTextures(frameTmp, rhi, rub, {});
364 if (!videoFrameTextures) {
365 qCDebug(qLcVideoFrameConverter) << "Failed obtain textures. Using CPU conversion.";
366 return convertCPU(frame, rotation, mirrorX, mirrorY);
367 }
368
369 if (!updateTextures(rhi, uniformBuffer, textureSampler, shaderResourceBindings,
370 graphicsPipeline, renderPass, frameTmp, videoFrameTextures)) {
371 qCDebug(qLcVideoFrameConverter) << "Failed to update textures. Using CPU conversion.";
372 return convertCPU(frame, rotation, mirrorX, mirrorY);
373 }
374
375 float xScale = mirrorX ? -1.0 : 1.0;
376 float yScale = mirrorY ? -1.0 : 1.0;
377
378 if (rhi->isYUpInFramebuffer())
379 yScale = -yScale;
380
382 transform.scale(xScale, yScale);
383
384 QByteArray uniformData(64 + 64 + 4 + 4, Qt::Uninitialized);
385 QVideoTextureHelper::updateUniformData(&uniformData, frame.surfaceFormat(), frame, transform, 1.f);
386 rub->updateDynamicBuffer(uniformBuffer.get(), 0, uniformData.size(), uniformData.constData());
387
388 cb->beginPass(renderTarget.get(), Qt::black, { 1.0f, 0 }, rub);
389 cb->setGraphicsPipeline(graphicsPipeline.get());
390
391 cb->setViewport({ 0, 0, float(frameSize.width()), float(frameSize.height()) });
392 cb->setShaderResources(shaderResourceBindings.get());
393
394 const int rotationIndex = (qToUnderlying(rotation) / 90) % 4;
395 const quint32 vertexOffset = quint32(sizeof(float)) * 16 * rotationIndex;
396 const QRhiCommandBuffer::VertexInput vbufBinding(vertexBuffer.get(), vertexOffset);
397 cb->setVertexInput(0, 1, &vbufBinding);
398 cb->draw(4);
399
400 QRhiReadbackDescription readDesc(targetTexture.get());
401 QRhiReadbackResult readResult;
402 bool readCompleted = false;
403
404 readResult.completed = [&readCompleted] { readCompleted = true; };
405
406 rub = rhi->nextResourceUpdateBatch();
407 rub->readBackTexture(readDesc, &readResult);
408
409 cb->endPass(rub);
410
411 rhi->endOffscreenFrame();
412
413 if (!readCompleted) {
414 qCDebug(qLcVideoFrameConverter) << "Failed to read back texture. Using CPU conversion.";
415 return convertCPU(frame, rotation, mirrorX, mirrorY);
416 }
417
418 QByteArray *imageData = new QByteArray(readResult.data);
419
420 return QImage(reinterpret_cast<const uchar *>(imageData->constData()),
421 readResult.pixelSize.width(), readResult.pixelSize.height(),
423}
424
426 QSize targetSize)
427{
428 if (plane >= frame.planeCount())
429 return {};
430
431 if (!frame.map(QVideoFrame::ReadOnly)) {
432 qWarning() << "Cannot map a video frame in ReadOnly mode!";
433 return {};
434 }
435
436 auto frameHandle = QVideoFramePrivate::handle(frame);
437
438 // With incrementing the reference counter, we share the mapped QVideoFrame
439 // with the target QImage. The function imageCleanupFunction is going to adopt
440 // the frameHandle by QVideoFrame and dereference it upon the destruction.
441 frameHandle->ref.ref();
442
443 auto imageCleanupFunction = [](void *data) {
444 QVideoFrame frame = reinterpret_cast<QVideoFramePrivate *>(data)->adoptThisByVideoFrame();
445 Q_ASSERT(frame.isMapped());
446 frame.unmap();
447 };
448
449 const auto bytesPerLine = frame.bytesPerLine(plane);
450 const auto height =
451 bytesPerLine ? qMin(targetSize.height(), frame.mappedBytes(plane) / bytesPerLine) : 0;
452
453 return QImage(reinterpret_cast<const uchar *>(frame.bits(plane)), targetSize.width(), height,
454 bytesPerLine, targetFormat, imageCleanupFunction, frameHandle);
455}
456
458
\inmodule QtCore
Definition qbytearray.h:57
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:124
static bool testAttribute(Qt::ApplicationAttribute attribute)
Returns true if attribute attribute is set; otherwise returns false.
\inmodule QtCore
Definition qfile.h:93
static QPlatformIntegration * platformIntegration()
void applicationStateChanged(Qt::ApplicationState state)
\inmodule QtGui
Definition qimage.h:37
Format
The following image formats are available in Qt.
Definition qimage.h:41
@ Format_RGB32
Definition qimage.h:46
@ Format_RGBA8888_Premultiplied
Definition qimage.h:60
@ Format_ARGB32_Premultiplied
Definition qimage.h:48
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
Definition qmatrix4x4.h:25
void scale(const QVector3D &vector)
Multiplies this matrix by another that scales coordinates by the components of vector.
\inmodule QtCore Represents a handle to a signal-slot (or signal-functor) connection.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
\inmodule QtGui
@ Immutable
Definition qrhi.h:849
@ Dynamic
Definition qrhi.h:851
@ VertexBuffer
Definition qrhi.h:855
@ UniformBuffer
Definition qrhi.h:857
\inmodule QtGui
Definition qrhi.h:1651
QPair< QRhiBuffer *, quint32 > VertexInput
Synonym for QPair<QRhiBuffer *, quint32>.
Definition qrhi.h:1680
\inmodule QtGui
\inmodule QtGui
\variable QRhiGles2InitParams::format
\inmodule QtRhi
\inmodule QtGui
Definition qrhi.h:777
\inmodule QtGui
Definition qrhi.h:1731
void uploadStaticBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
Enqueues updating a region of a QRhiBuffer buf created with the type QRhiBuffer::Immutable or QRhiBuf...
Definition qrhi.cpp:9011
@ ClampToEdge
Definition qrhi.h:1040
\inmodule QtGui
Definition qrhi.h:439
static QRhiShaderResourceBinding sampledTexture(int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler)
Definition qrhi.cpp:5640
static QRhiShaderResourceBinding uniformBuffer(int binding, StageFlags stage, QRhiBuffer *buf)
Definition qrhi.cpp:5526
@ RenderTarget
Definition qrhi.h:898
\inmodule QtGui
Definition qrhi.h:321
void setBindings(std::initializer_list< QRhiVertexInputBinding > list)
Sets the bindings from the specified list.
Definition qrhi.h:325
void setAttributes(std::initializer_list< QRhiVertexInputAttribute > list)
Sets the attributes from the specified list.
Definition qrhi.h:337
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
Definition qrhi.h:1804
QRhiBuffer * newBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size)
Definition qrhi.cpp:10508
QThread * thread() const
Definition qrhi.cpp:8792
QRhiShaderResourceBindings * newShaderResourceBindings()
Definition qrhi.cpp:10489
Implementation
Describes which graphics API-specific backend gets used by a QRhi instance.
Definition qrhi.h:1806
@ Metal
Definition qrhi.h:1811
@ Null
Definition qrhi.h:1807
@ D3D11
Definition qrhi.h:1810
@ OpenGLES2
Definition qrhi.h:1809
QRhiSampler * newSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, QRhiSampler::Filter mipmapMode, QRhiSampler::AddressMode addressU, QRhiSampler::AddressMode addressV, QRhiSampler::AddressMode addressW=QRhiSampler::Repeat)
Definition qrhi.cpp:10665
QRhiTextureRenderTarget * newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, QRhiTextureRenderTarget::Flags flags={})
Definition qrhi.cpp:10682
bool isRecordingFrame() const
Definition qrhi.cpp:10802
QRhiGraphicsPipeline * newGraphicsPipeline()
Definition qrhi.cpp:10466
static QRhi * create(Implementation impl, QRhiInitParams *params, Flags flags={}, QRhiNativeHandles *importDevice=nullptr)
Definition qrhi.cpp:8491
QRhiTexture * newTexture(QRhiTexture::Format format, const QSize &pixelSize, int sampleCount=1, QRhiTexture::Flags flags={})
Definition qrhi.cpp:10562
FrameOpResult
Describes the result of operations that can have a soft failure.
Definition qrhi.h:1824
@ FrameOpSuccess
Definition qrhi.h:1825
\inmodule QtGui
Definition qshader.h:81
static QShader fromSerialized(const QByteArray &data)
Creates a new QShader instance from the given data.
Definition qshader.cpp:540
bool isValid() const
Definition qshader.cpp:343
\inmodule QtCore
Definition qsize.h:25
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:133
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:130
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:124
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QThread * currentThread()
Definition qthread.cpp:1039
The QTransform class specifies 2D transformations of a coordinate system.
Definition qtransform.h:20
QTransform & rotate(qreal a, Qt::Axis axis=Qt::ZAxis, qreal distanceToPlane=1024.0f)
QTransform & scale(qreal sx, qreal sy)
Scales the coordinate system by sx horizontally and sy vertically, and returns a reference to the mat...
PixelFormat
Enumerates video data types.
static QVideoFramePrivate * handle(QVideoFrame &frame)
The QVideoFrame class represents a frame of video data.
Definition qvideoframe.h:27
QSize size
the size of the widget excluding any window frame
Definition qwidget.h:113
else opt state
[0]
Combined button and popup list for selecting options.
QString vertexShaderFileName(const QVideoFrameFormat &format)
QString fragmentShaderFileName(const QVideoFrameFormat &format, QRhiSwapChain::Format surfaceFormat)
const TextureDescription * textureDescription(QVideoFrameFormat::PixelFormat format)
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)
@ black
Definition qnamespace.h:30
@ AA_ForceRasterWidgets
Definition qnamespace.h:443
@ ApplicationSuspended
Definition qnamespace.h:263
constexpr Initialization Uninitialized
Definition image.cpp:4
static void * context
#define Q_FUNC_INFO
#define qApp
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
#define qWarning
Definition qlogging.h:166
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
QSize qRotatedFrameSize(QSize size, int rotation)
GLboolean GLboolean GLboolean b
GLint GLsizei GLsizei height
GLboolean r
[2]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLfloat GLfloat f
GLuint name
GLint GLsizei GLsizei GLenum format
void ** params
GLuint GLenum GLenum transform
GLuint shader
Definition qopenglext.h:665
GLdouble GLdouble t
Definition qopenglext.h:243
static constexpr QSize frameSize(const T &frame)
static constexpr To convert(const std::array< Mapping, N > &mapping, From Mapping::*from, To Mapping::*to, From value, To defaultValue)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
SSL_CTX int(* cb)(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
QT_BEGIN_NAMESPACE constexpr std::underlying_type_t< Enum > qToUnderlying(Enum e) noexcept
unsigned int quint32
Definition qtypes.h:50
unsigned char uchar
Definition qtypes.h:32
VideoFrameConvertFunc qConverterForFormat(QVideoFrameFormat::PixelFormat format)
static void rasterTransform(QImage &image, QtVideo::Rotation rotation, bool mirrorX, bool mirrorY)
static QShader vfcGetShader(const QString &name)
static QThreadStorage< State > g_state
static QHash< QString, QShader > g_shaderCache
static QRhi * initializeRHI(QRhi *videoFrameRhi)
static QImage convertJPEG(const QVideoFrame &frame, QtVideo::Rotation rotation, bool mirrorX, bool mirrorY)
QImage qImageFromVideoFrame(const QVideoFrame &frame, QtVideo::Rotation rotation, bool mirrorX, bool mirrorY)
static bool pixelFormatHasAlpha(QVideoFrameFormat::PixelFormat format)
static bool updateTextures(QRhi *rhi, std::unique_ptr< QRhiBuffer > &uniformBuffer, std::unique_ptr< QRhiSampler > &textureSampler, std::unique_ptr< QRhiShaderResourceBindings > &shaderResourceBindings, std::unique_ptr< QRhiGraphicsPipeline > &graphicsPipeline, std::unique_ptr< QRhiRenderPassDescriptor > &renderPass, QVideoFrame &frame, const std::unique_ptr< QVideoFrameTextures > &videoFrameTextures)
static QImage convertCPU(const QVideoFrame &frame, QtVideo::Rotation rotation, bool mirrorX, bool mirrorY)
static const float g_quad[]
QImage videoFramePlaneAsImage(QVideoFrame &frame, int plane, QImage::Format targetFormat, QSize targetSize)
Maps the video frame and returns an image having a shared ownership for the video frame and referenci...
static void imageCleanupHandler(void *info)
QByteArray imageData
[15]
QFrame frame
[0]
QHostInfo info
[0]
\inmodule QtGui
Definition qrhi.h:1723
std::function< void()> completed
Definition qrhi.h:1724