From bd57cdf241f81a19efba3dc29621cb9e994eeabe Mon Sep 17 00:00:00 2001 From: Samuel Mira Date: Mon, 18 Jul 2022 19:05:01 +0300 Subject: 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 (cherry picked from commit e8248b7a953ca2284f4fa489dfc31579bb92f66e) --- .../android/common/qandroidvideooutput.cpp | 34 +++++++++++++--------- .../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; }; -- cgit v1.2.3