8#include <QtGui/private/qopenglextensions_p.h>
9#include <private/qabstractvideobuffer_p.h>
10#include <private/qvideoframeconverter_p.h>
11#include <private/qplatformvideosink_p.h>
32 return plane == 0 ? m_tex.get() :
nullptr;
36 std::unique_ptr<QRhiTexture> m_tex;
49 std::shared_ptr<AndroidTextureThread> m_thread;
57 std::shared_ptr<QRhi>
rhi, std::shared_ptr<AndroidTextureThread>
thread,
58 std::unique_ptr<QRhiTexture> tex,
const QSize &
size)
62 , m_tex(
std::move(tex))
77 return std::make_unique<QAndroidVideoFrameTextures>(
rhi, m_size, m_tex->nativeTexture().object);
82 std::unique_ptr<QRhiTexture> m_tex;
124 -1.f, -1.f, 0.f, 0.f,
145 m_vertexBuffer->create();
148 m_uniformBuffer->create();
161 m_vertexShader = getShader(
QStringLiteral(
":/qt-project.org/multimedia/shaders/externalsampler.vert.qsb"));
163 m_fragmentShader = getShader(
QStringLiteral(
":/qt-project.org/multimedia/shaders/externalsampler.frag.qsb"));
170 QRhi *m_rhi =
nullptr;
171 std::unique_ptr<QRhiBuffer> m_vertexBuffer;
172 std::unique_ptr<QRhiBuffer> m_uniformBuffer;
173 std::unique_ptr<QRhiSampler> m_sampler;
174 std::unique_ptr<QRhiShaderResourceBindings> m_srb;
187 gp->setShaderStages({
193 { 4 *
sizeof(float) }
199 gp->setVertexInputLayout(inputLayout);
200 gp->setShaderResourceBindings(shaderResourceBindings);
201 gp->setRenderPassDescriptor(renderPassDescriptor);
210 if (!tex->create()) {
211 qWarning(
"Failed to create frame texture");
216 std::unique_ptr<QRhiRenderPassDescriptor> renderPassDescriptor(renderTarget->newCompatibleRenderPassDescriptor());
217 renderTarget->setRenderPassDescriptor(renderPassDescriptor.get());
218 renderTarget->create();
224 char *
p = m_uniformBuffer->beginFullDynamicBufferUpdateForCurrentFrame();
226 memcpy(
p + 64, externalTexMatrix.constData(), 64);
227 float opacity = 1.0f;
228 memcpy(
p + 64 + 64, &opacity, 4);
229 m_uniformBuffer->endFullDynamicBufferUpdateForCurrentFrame();
231 auto graphicsPipeline =
newGraphicsPipeline(m_rhi, m_srb.get(), renderPassDescriptor.get(),
232 m_vertexShader, m_fragmentShader);
241 cb->setGraphicsPipeline(graphicsPipeline.get());
242 cb->setViewport({0, 0, float(
size.width()), float(
size.height())});
243 cb->setShaderResources(m_srb.get());
244 cb->setVertexInput(0, 1, &vbufBinding);
247 m_rhi->endOffscreenFrame();
262 static const QMatrix4x4 flipV(1.0f, 0.0f, 0.0f, 0.0f,
263 0.0f, -1.0f, 0.0f, 1.0f,
264 0.0f, 0.0f, 1.0f, 0.0f,
265 0.0f, 0.0f, 0.0f, 1.0f);
297 params.fallbackSurface = QRhiGles2InitParams::newFallbackSurface();
306 if (m_surfaceTexture && m_surfaceTexture->index() ==
index) {
307 m_surfaceTexture->updateTexImage();
309 auto tex = m_textureCopy->copyExternalTexture(m_size,
matrix);
322 m_surfaceTexture.reset();
324 m_textureCopy.reset();
330 if (m_surfaceTexture)
331 return m_surfaceTexture.get();
340 m_surfaceTexture = std::make_unique<AndroidSurfaceTexture>(m_texture->nativeTexture().object);
341 if (m_surfaceTexture->surfaceTexture()) {
344 [
this,
index] () { this->onFrameAvailable(index); });
346 m_textureCopy = std::make_unique<TextureCopy>(m_rhi.get(), m_texture.get());
350 m_surfaceTexture.reset();
353 return m_surfaceTexture.get();
361 std::shared_ptr<QRhi> m_rhi;
362 std::unique_ptr<AndroidSurfaceTexture> m_surfaceTexture;
363 std::unique_ptr<QRhiTexture> m_texture;
364 std::unique_ptr<TextureCopy> m_textureCopy;
379 qDebug() <<
"Cannot create QAndroidTextureVideoOutput without a sink.";
380 m_surfaceThread =
nullptr;
384 startNewSurfaceThread();
387void QAndroidTextureVideoOutput::startNewSurfaceThread()
389 m_surfaceThread = std::make_shared<AndroidTextureThread>(
this);
391 this, &QAndroidTextureVideoOutput::newFrame);
392 m_surfaceThread->start();
413 return m_sink->
rhi() && m_surfaceCreatedWithoutRhi;
423 auto rhi = m_sink->rhi();
425 m_surfaceCreatedWithoutRhi = true;
427 else if (m_surfaceCreatedWithoutRhi) {
428 m_surfaceThread->clearSurfaceTexture();
429 m_surfaceCreatedWithoutRhi =
false;
431 surface = m_surfaceThread->createSurfaceTexture(rhi);
439 if (m_nativeSize ==
size)
444 [&](){ m_surfaceThread->setFrameSize(size); },
469#include "qandroidvideooutput.moc"
470#include "moc_qandroidvideooutput_p.cpp"
QMatrix4x4 getTransformMatrix()
AndroidTextureThread(QAndroidTextureVideoOutput *vo)
void onFrameAvailable(quint64 index)
void newFrame(const QVideoFrame &)
AndroidSurfaceTexture * createSurfaceTexture(QRhi *rhi)
void initRhi(QOpenGLContext *context)
void clearSurfaceTexture()
void setFrameSize(QSize size)
MapData map(QVideoFrame::MapMode mode) override
Independently maps the planes of a video buffer to memory.
QVideoFrame::MapMode mapMode() const override
void unmap() override
Releases the memory mapped by the map() function.
std::unique_ptr< QVideoFrameTextures > mapTextures(QRhi *rhi) override
AndroidTextureVideoBuffer(std::shared_ptr< QRhi > rhi, std::shared_ptr< AndroidTextureThread > thread, std::unique_ptr< QRhiTexture > tex, const QSize &size)
QVideoFrame::MapMode mapMode() const override
void unmap() override
Releases the memory mapped by the map() function.
ImageFromVideoFrameHelper(AndroidTextureVideoBuffer &atvb)
MapData map(QVideoFrame::MapMode) override
Independently maps the planes of a video buffer to memory.
std::unique_ptr< QVideoFrameTextures > mapTextures(QRhi *rhi) override
The QAbstractVideoBuffer class is an abstraction for video data. \inmodule QtMultimedia.
QRhi * rhi() const
Returns the QRhi instance.
void setSubtitle(const QString &subtitle)
QAndroidTextureVideoOutput(QVideoSink *sink, QObject *parent=0)
void setVideoSize(const QSize &) override
std::shared_ptr< AndroidTextureThread > getSurfaceThread()
AndroidSurfaceTexture * surfaceTexture() override
QVideoSink * surface() const
bool shouldTextureBeUpdated() const
~QAndroidTextureVideoOutput() override
QAndroidVideoFrameTextures(QRhi *rhi, QSize size, quint64 handle)
QRhiTexture * texture(uint plane) const override
qsizetype bytesPerLine() const
Returns the number of bytes per image scanline.
qsizetype sizeInBytes() const
uchar * bits()
Returns a pointer to the first pixel data.
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
const float * constData() const
Returns a constant pointer to the raw data of this matrix.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
QThread * thread() const
Returns the thread in which the object lives.
bool moveToThread(QThread *thread QT6_DECL_NEW_OVERLOAD_TAIL)
Changes the thread affinity for this object and its children and returns true on success.
static QOpenGLContext * currentContext()
Returns the last context which called makeCurrent in the current thread, or \nullptr,...
The QOpenGLFunctions class provides cross-platform access to the OpenGL ES 2.0 API.
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)
std::shared_ptr< QRhi > m_guardRhi
QRhiWithThreadGuard(std::shared_ptr< QRhi > r, std::shared_ptr< AndroidTextureThread > t)
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
QRhiBuffer * newBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size)
QRhiShaderResourceBindings * newShaderResourceBindings()
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={})
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()
static QShader fromSerialized(const QByteArray &data)
Creates a new QShader instance from the given data.
\macro QT_RESTRICTED_CAST_FROM_ASCII
void start(Priority=InheritPriority)
bool wait(QDeadlineTimer deadline=QDeadlineTimer(QDeadlineTimer::Forever))
The QVideoFrame class represents a frame of video data.
MapMode
Enumerates how a video buffer's data is mapped to system memory.
The QVideoSink class represents a generic sink for video data.
void setVideoFrame(const QVideoFrame &frame)
Sets the current video frame.
QPlatformVideoSink * platformVideoSink() const
QRhi * rhi() const
Returns the QRhi instance being used to create texture data in the video frames.
TextureCopy(QRhi *rhi, QRhiTexture *externalTex)
std::unique_ptr< QRhiTexture > copyExternalTexture(QSize size, const QMatrix4x4 &externalTexMatrix)
QMap< QString, QString > map
[6]
Combined button and popup list for selecting options.
@ BlockingQueuedConnection
static QMatrix4x4 extTransformMatrix(AndroidSurfaceTexture *surfaceTexture)
static std::unique_ptr< QRhiGraphicsPipeline > newGraphicsPipeline(QRhi *rhi, QRhiShaderResourceBindings *shaderResourceBindings, QRhiRenderPassDescriptor *renderPassDescriptor, QShader vertexShader, QShader fragmentShader)
static const float g_quad[]
static QDBusError::ErrorType get(const char *name)
GLuint64 GLenum void * handle
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLsizei GLenum GLboolean sink
static QAbstractVideoBuffer::MapData mapData(const camera_frame_nv12_t &frame, unsigned char *baseAddress)
SSL_CTX int(* cb)(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
#define QStringLiteral(str)
unsigned long long quint64
QImage qImageFromVideoFrame(const QVideoFrame &frame, QtVideo::Rotation rotation, bool mirrorX, bool mirrorY)
if(qFloatDistance(a, b)<(1<< 7))
[0]