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>
24#include <QtCore/private/qcore_mac_p.h>
40#if defined(Q_OS_ANDROID)
51 delete fallbackSurface;
52 fallbackSurface =
nullptr;
120 bool mirrorX,
bool mirrorY)
142 return g_state.localData().rhi;
148#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
168 g_state.localData().fallbackSurface = QRhiGles2InitParams::newFallbackSurface();
170 params.fallbackSurface =
g_state.localData().fallbackSurface;
175#if defined(Q_OS_ANDROID)
177 if (!
g_state.localData().appStateChangedConnection) {
180 g_state.localData().resetRhi();
189 if (!
g_state.localData().rhi) {
190 g_state.localData().cpuOnly =
true;
194 return g_state.localData().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)
207 auto pixelFormat =
format.pixelFormat();
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();
232 graphicsPipeline->setShaderStages({
239 { 4 *
sizeof(float) }
246 graphicsPipeline->setVertexInputLayout(inputLayout);
247 graphicsPipeline->setShaderResourceBindings(shaderResourceBindings.get());
248 graphicsPipeline->setRenderPassDescriptor(renderPass.get());
249 graphicsPipeline->create();
262 image.loadFromData(varFrame.bits(0), varFrame.mappedBytes(0),
"JPG");
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;
315 if (
frame.videoBuffer())
316 rhi =
frame.videoBuffer()->rhi();
329 vertexBuffer->create();
332 uniformBuffer->create();
336 textureSampler->create();
341 if (!targetTexture->create()) {
342 qCDebug(qLcVideoFrameConverter) <<
"Failed to create target texture. Using CPU conversion.";
347 renderPass.reset(renderTarget->newCompatibleRenderPassDescriptor());
348 renderTarget->setRenderPassDescriptor(renderPass.get());
349 renderTarget->create();
354 qCDebug(qLcVideoFrameConverter) <<
"Failed to set up offscreen frame. Using CPU conversion.";
364 if (!videoFrameTextures) {
365 qCDebug(qLcVideoFrameConverter) <<
"Failed obtain textures. Using CPU conversion.";
369 if (!
updateTextures(rhi, uniformBuffer, textureSampler, shaderResourceBindings,
370 graphicsPipeline, renderPass, frameTmp, videoFrameTextures)) {
371 qCDebug(qLcVideoFrameConverter) <<
"Failed to update textures. Using CPU conversion.";
375 float xScale = mirrorX ? -1.0 : 1.0;
376 float yScale = mirrorY ? -1.0 : 1.0;
378 if (rhi->isYUpInFramebuffer())
386 rub->updateDynamicBuffer(uniformBuffer.get(), 0, uniformData.size(), uniformData.constData());
388 cb->beginPass(renderTarget.get(),
Qt::black, { 1.0f, 0 }, rub);
389 cb->setGraphicsPipeline(graphicsPipeline.get());
392 cb->setShaderResources(shaderResourceBindings.get());
394 const int rotationIndex = (
qToUnderlying(rotation) / 90) % 4;
395 const quint32 vertexOffset =
quint32(
sizeof(
float)) * 16 * rotationIndex;
397 cb->setVertexInput(0, 1, &vbufBinding);
402 bool readCompleted =
false;
404 readResult.
completed = [&readCompleted] { readCompleted =
true; };
406 rub = rhi->nextResourceUpdateBatch();
407 rub->readBackTexture(readDesc, &readResult);
411 rhi->endOffscreenFrame();
413 if (!readCompleted) {
414 qCDebug(qLcVideoFrameConverter) <<
"Failed to read back texture. Using CPU conversion.";
421 readResult.pixelSize.width(), readResult.pixelSize.height(),
428 if (plane >=
frame.planeCount())
432 qWarning() <<
"Cannot map a video frame in ReadOnly mode!";
441 frameHandle->ref.ref();
443 auto imageCleanupFunction = [](
void *
data) {
449 const auto bytesPerLine =
frame.bytesPerLine(plane);
451 bytesPerLine ?
qMin(targetSize.
height(),
frame.mappedBytes(plane) / bytesPerLine) : 0;
454 bytesPerLine, targetFormat, imageCleanupFunction, frameHandle);
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()
void applicationStateChanged(Qt::ApplicationState state)
Format
The following image formats are available in Qt.
@ Format_RGBA8888_Premultiplied
@ Format_ARGB32_Premultiplied
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
void scale(const QVector3D &vector)
Multiplies this matrix by another that scales coordinates by the components of vector.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
QPair< QRhiBuffer *, quint32 > VertexInput
Synonym for QPair<QRhiBuffer *, quint32>.
\variable QRhiGles2InitParams::format
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...
static QRhiShaderResourceBinding sampledTexture(int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler)
static QRhiShaderResourceBinding uniformBuffer(int binding, StageFlags stage, QRhiBuffer *buf)
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
QRhiBuffer * newBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size)
QRhiShaderResourceBindings * newShaderResourceBindings()
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={})
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.
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QThread * currentThread()
static QVideoFramePrivate * handle(QVideoFrame &frame)
The QVideoFrame class represents a frame of video 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
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
constexpr const T & qMin(const T &a, const T &b)
GLboolean GLboolean GLboolean b
GLint GLsizei GLsizei height
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
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)
QT_BEGIN_NAMESPACE constexpr std::underlying_type_t< Enum > qToUnderlying(Enum e) noexcept
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)
std::function< void()> completed