summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Mira <samuel.mira@qt.io>2022-07-18 19:05:01 +0300
committerSamuel Mira <samuel.mira@qt.io>2022-07-19 13:54:36 +0300
commitbd57cdf241f81a19efba3dc29621cb9e994eeabe (patch)
treef73c2202c262464a821b7499a1ca74faa10b6d4f
parenteee36ac9d2c28d5bebad89dc0e432d6e90bbaa2b (diff)
downloadqtmultimedia-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.cpp34
-rw-r--r--src/multimedia/platform/android/common/qandroidvideooutput_p.h2
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;
};