diff options
author | Samuel Mira <samuel.mira@qt.io> | 2022-07-18 19:05:01 +0300 |
---|---|---|
committer | Samuel Mira <samuel.mira@qt.io> | 2022-07-19 13:54:36 +0300 |
commit | bd57cdf241f81a19efba3dc29621cb9e994eeabe (patch) | |
tree | f73c2202c262464a821b7499a1ca74faa10b6d4f | |
parent | eee36ac9d2c28d5bebad89dc0e432d6e90bbaa2b (diff) | |
download | qtmultimedia-bd57cdf241f81a19efba3dc29621cb9e994eeabe.tar.gz |
Android: Fix framerate drop when QML animation is over video/camera
The reason for framerate drop was the invoke method that forces to
readback a new frame from the surface. Removing that method may lead
for the video output to be become stuck when the render thread becomes
blocked, since because the object needs to be moved to OpenGL thread to
be able to create OpenGLContext. To solve this, it now verifies if the
thread needs to create OpenGLContext and moves to OpenGL thread but will
move back to the original thread after the OpenGLContext are created.
Fixes: QTBUG-104133
Change-Id: I38517e8c1e9db2f4098aaaaa5a0598a406f04281
Reviewed-by: Lars Knoll <lars.knoll@gmail.com>
(cherry picked from commit e8248b7a953ca2284f4fa489dfc31579bb92f66e)
-rw-r--r-- | src/multimedia/platform/android/common/qandroidvideooutput.cpp | 34 | ||||
-rw-r--r-- | src/multimedia/platform/android/common/qandroidvideooutput_p.h | 2 |
2 files changed, 23 insertions, 13 deletions
diff --git a/src/multimedia/platform/android/common/qandroidvideooutput.cpp b/src/multimedia/platform/android/common/qandroidvideooutput.cpp index d8e9ca79c..f3a8bff2e 100644 --- a/src/multimedia/platform/android/common/qandroidvideooutput.cpp +++ b/src/multimedia/platform/android/common/qandroidvideooutput.cpp @@ -123,10 +123,12 @@ static QMatrix4x4 extTransformMatrix(AndroidSurfaceTexture *surfaceTexture) quint64 AndroidTextureVideoBuffer::textureHandle(int plane) const { - if (plane != 0 || !rhi || !m_output->m_nativeSize.isValid()) + if (plane != 0 || !rhi || !m_output->m_nativeSize.isValid() || !m_output->m_readbackRhi + || !m_output->m_surfaceTexture) return 0; - m_output->ensureExternalTexture(rhi); + m_output->m_readbackRhi->makeThreadLocalNativeContextCurrent(); + m_output->ensureExternalTexture(m_output->m_readbackRhi); m_output->m_surfaceTexture->updateTexImage(); m_externalMatrix = extTransformMatrix(m_output->m_surfaceTexture); return m_output->m_externalTex->nativeTexture().object; @@ -233,15 +235,13 @@ void QAndroidTextureVideoOutput::setVideoSize(const QSize &size) if (m_nativeSize == size) return; - stop(); - m_nativeSize = size; } void QAndroidTextureVideoOutput::start() { m_started = true; - renderAndReadbackFrame(); + QMetaObject::invokeMethod(this, "onFrameAvailable", Qt::QueuedConnection); } void QAndroidTextureVideoOutput::stop() @@ -304,6 +304,22 @@ void QAndroidTextureVideoOutput::onFrameAvailable() if (!(m_nativeSize.isValid() && m_sink) || !(m_started || m_renderFrame)) return; + const bool needsToBeInOpenGLThread = + !m_readbackRhi || !m_readbackTex || !m_readbackSrb || !m_readbackPs; + + const bool movedToOpenGLThread = needsToBeInOpenGLThread && moveToOpenGLContextThread(); + + if (movedToOpenGLThread || QThread::currentThread() != m_thread) { + // the render thread may get blocked waiting for events, force refresh until get back to + // original thread. + QMetaObject::invokeMethod(this, "onFrameAvailable", Qt::QueuedConnection); + + if (!needsToBeInOpenGLThread) { + parent()->moveToThread(m_thread); + moveToThread(m_thread); + } + } + m_renderFrame = false; QRhi *rhi = m_sink ? m_sink->rhi() : nullptr; @@ -313,8 +329,6 @@ void QAndroidTextureVideoOutput::onFrameAvailable() : QVideoFrameFormat::Format_RGBA8888; QVideoFrame frame(buffer, QVideoFrameFormat(m_nativeSize, format)); m_sink->platformVideoSink()->setVideoFrame(frame); - - QMetaObject::invokeMethod(m_surfaceTexture, "frameAvailable", Qt::QueuedConnection); } static const float g_quad[] = { @@ -340,12 +354,6 @@ bool QAndroidTextureVideoOutput::renderAndReadbackFrame() if (!m_nativeSize.isValid() || !m_surfaceTexture) return false; - if (moveToOpenGLContextThread()) { - // just moved to another thread, must close the execution of this method - QMetaObject::invokeMethod(this, "onFrameAvailable", Qt::ConnectionType::DirectConnection); - return false; - } - if (!m_readbackRhi) { QRhi *sinkRhi = m_sink ? m_sink->rhi() : nullptr; if (sinkRhi && sinkRhi->backend() == QRhi::OpenGLES2) { diff --git a/src/multimedia/platform/android/common/qandroidvideooutput_p.h b/src/multimedia/platform/android/common/qandroidvideooutput_p.h index 473c58552..99ea44313 100644 --- a/src/multimedia/platform/android/common/qandroidvideooutput_p.h +++ b/src/multimedia/platform/android/common/qandroidvideooutput_p.h @@ -168,6 +168,8 @@ private: GraphicsResourceDeleter *m_graphicsDeleter = nullptr; + QThread *m_thread = QThread::currentThread(); + friend class AndroidTextureVideoBuffer; }; |