8#include <QtCore/qcoreapplication.h>
9#include <QtCore/qsize.h>
10#include <QtCore/qhash.h>
11#include <QtCore/qfile.h>
12#include <QtCore/qthreadstorage.h>
13#include <QtGui/qimage.h>
14#include <QtGui/qoffscreensurface.h>
15#include <qpa/qplatformintegration.h>
16#include <private/qvideotexturehelper_p.h>
17#include <private/qabstractvideobuffer_p.h>
18#include <private/qguiapplication_p.h>
22#include <QtCore/private/qcore_mac_p.h>
41 delete fallbackSurface;
108 bool mirrorX,
bool mirrorY)
114 t.rotate(
float(rotation));
130 return g_state.localData().rhi;
136#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
156 g_state.localData().fallbackSurface = QRhiGles2InitParams::newFallbackSurface();
158 params.fallbackSurface =
g_state.localData().fallbackSurface;
167 if (!
g_state.localData().rhi) {
168 g_state.localData().cpuOnly =
true;
172 return g_state.localData().rhi;
176 std::unique_ptr<QRhiBuffer> &uniformBuffer,
177 std::unique_ptr<QRhiSampler> &textureSampler,
178 std::unique_ptr<QRhiShaderResourceBindings> &shaderResourceBindings,
179 std::unique_ptr<QRhiGraphicsPipeline> &graphicsPipeline,
180 std::unique_ptr<QRhiRenderPassDescriptor> &renderPass,
182 const std::unique_ptr<QVideoFrameTextures> &videoFrameTextures)
185 auto pixelFormat =
format.pixelFormat();
192 uniformBuffer.get());
193 for (
int i = 0;
i < textureDesc->nplanes; ++
i)
195 videoFrameTextures->texture(
i), textureSampler.get());
196 shaderResourceBindings->setBindings(bindings,
b);
197 shaderResourceBindings->create();
210 graphicsPipeline->setShaderStages({
217 { 4 *
sizeof(float) }
224 graphicsPipeline->setVertexInputLayout(inputLayout);
225 graphicsPipeline->setShaderResourceBindings(shaderResourceBindings.get());
226 graphicsPipeline->setRenderPassDescriptor(renderPass.get());
227 graphicsPipeline->create();
276 std::unique_ptr<QRhiRenderPassDescriptor> renderPass;
277 std::unique_ptr<QRhiBuffer> vertexBuffer;
278 std::unique_ptr<QRhiBuffer> uniformBuffer;
279 std::unique_ptr<QRhiTexture> targetTexture;
280 std::unique_ptr<QRhiTextureRenderTarget> renderTarget;
281 std::unique_ptr<QRhiSampler> textureSampler;
282 std::unique_ptr<QRhiShaderResourceBindings> shaderResourceBindings;
283 std::unique_ptr<QRhiGraphicsPipeline> graphicsPipeline;
293 if (
frame.videoBuffer())
294 rhi =
frame.videoBuffer()->rhi();
304 const int rotationIndex = (rotation / 90) % 4;
307 if (rotationIndex % 2)
311 vertexBuffer->create();
314 uniformBuffer->create();
318 textureSampler->create();
323 if (!targetTexture->create()) {
324 qCDebug(qLcVideoFrameConverter) <<
"Failed to create target texture. Using CPU conversion.";
329 renderPass.reset(renderTarget->newCompatibleRenderPassDescriptor());
330 renderTarget->setRenderPassDescriptor(renderPass.get());
331 renderTarget->create();
336 qCDebug(qLcVideoFrameConverter) <<
"Failed to set up offscreen frame. Using CPU conversion.";
346 if (!videoFrameTextures) {
347 qCDebug(qLcVideoFrameConverter) <<
"Failed obtain textures. Using CPU conversion.";
351 if (!
updateTextures(rhi, uniformBuffer, textureSampler, shaderResourceBindings,
352 graphicsPipeline, renderPass, frameTmp, videoFrameTextures)) {
353 qCDebug(qLcVideoFrameConverter) <<
"Failed to update textures. Using CPU conversion.";
357 float xScale = mirrorX ? -1.0 : 1.0;
358 float yScale = mirrorY ? -1.0 : 1.0;
360 if (rhi->isYUpInFramebuffer())
368 rub->
updateDynamicBuffer(uniformBuffer.get(), 0, uniformData.size(), uniformData.constData());
370 cb->beginPass(renderTarget.get(),
Qt::black, { 1.0f, 0 }, rub);
371 cb->setGraphicsPipeline(graphicsPipeline.get());
374 cb->setShaderResources(shaderResourceBindings.get());
376 quint32 vertexOffset =
quint32(
sizeof(
float)) * 16 * rotationIndex;
378 cb->setVertexInput(0, 1, &vbufBinding);
383 bool readCompleted =
false;
385 readResult.
completed = [&readCompleted] { readCompleted =
true; };
387 rub = rhi->nextResourceUpdateBatch();
392 rhi->endOffscreenFrame();
394 if (!readCompleted) {
395 qCDebug(qLcVideoFrameConverter) <<
"Failed to read back texture. Using CPU conversion.";
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
static bool testAttribute(Qt::ApplicationAttribute attribute)
Returns true if attribute attribute is set; otherwise returns false.
static QPlatformIntegration * platformIntegration()
@ Format_RGBA8888_Premultiplied
@ Format_ARGB32_Premultiplied
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
QPair< QRhiBuffer *, quint32 > VertexInput
Synonym for QPair<QRhiBuffer *, quint32>.
\variable QRhiGles2InitParams::format
void updateDynamicBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
Enqueues updating a region of a QRhiBuffer buf created with the type QRhiBuffer::Dynamic.
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...
void readBackTexture(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
Enqueues a texture-to-host copy operation as described by rb.
static QRhiShaderResourceBinding sampledTexture(int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler)
static QRhiShaderResourceBinding uniformBuffer(int binding, StageFlags stage, QRhiBuffer *buf)
QRhiBuffer * newBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size)
QRhiShaderResourceBindings * newShaderResourceBindings()
Implementation backend() const
Implementation
Describes which graphics API-specific backend gets used by a QRhi instance.
QRhiSampler * newSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, QRhiSampler::Filter mipmapMode, QRhiSampler::AddressMode addressU, QRhiSampler::AddressMode addressV, QRhiSampler::AddressMode addressW=QRhiSampler::Repeat)
QRhiTextureRenderTarget * newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, QRhiTextureRenderTarget::Flags flags={})
bool isRecordingFrame() const
QRhiGraphicsPipeline * newGraphicsPipeline()
static QRhi * create(Implementation impl, QRhiInitParams *params, Flags flags={}, QRhiNativeHandles *importDevice=nullptr)
QRhiTexture * newTexture(QRhiTexture::Format format, const QSize &pixelSize, int sampleCount=1, QRhiTexture::Flags flags={})
const QRhiNativeHandles * nativeHandles()
FrameOpResult
Describes the result of operations that can have a soft failure.
static QShader fromSerialized(const QByteArray &data)
Creates a new QShader instance from the given data.
constexpr int height() const noexcept
Returns the height.
constexpr int width() const noexcept
Returns the width.
constexpr bool isEmpty() const noexcept
Returns true if either of the width and height is less than or equal to 0; otherwise returns false.
void transpose() noexcept
Swaps the width and height values.
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QThread * currentThread()
The QVideoFrame class represents a frame of video data.
RotationAngle
The angle of the clockwise rotation that should be applied to a video frame before displaying.
void unmap()
Releases the memory mapped by the map() function.
int height() const
Returns the height of a video frame.
uchar * bits(int plane)
Returns a pointer to the start of the frame data buffer for a plane.
bool map(QVideoFrame::MapMode mode)
Maps the contents of a video frame to system (CPU addressable) memory.
QVideoFrameFormat::PixelFormat pixelFormat() const
Returns the pixel format of this video frame.
int width() const
Returns the width of a video frame.
int mappedBytes(int plane) const
Returns the number of bytes occupied by plane plane of the mapped frame data.
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)
constexpr Initialization Uninitialized
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
GLboolean GLboolean GLboolean b
GLint GLsizei GLsizei GLenum format
GLuint GLenum GLenum transform
static constexpr QSize frameSize(const T &frame)
SSL_CTX int(* cb)(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
VideoFrameConvertFunc qConverterForFormat(QVideoFrameFormat::PixelFormat format)
QImage qImageFromVideoFrame(const QVideoFrame &frame, QVideoFrame::RotationAngle rotation, bool mirrorX, bool mirrorY)
static QImage convertCPU(const QVideoFrame &frame, QVideoFrame::RotationAngle rotation, bool mirrorX, bool mirrorY)
static QImage convertJPEG(const QVideoFrame &frame, QVideoFrame::RotationAngle 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 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 void rasterTransform(QImage &image, QVideoFrame::RotationAngle rotation, bool mirrorX, bool mirrorY)
static const float g_quad[]
static void imageCleanupHandler(void *info)
QFileInfo info(fileName)
[8]
std::function< void()> completed