diff options
author | Bartlomiej Moskal <bartlomiej.moskal@qt.io> | 2024-02-26 13:41:48 +0100 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2024-02-29 20:02:48 +0000 |
commit | b04f18195e8bd5428376b34d07dbe7f16847d1fe (patch) | |
tree | b937581989b133e03c1f26aefee3ebc78e25f01b | |
parent | 2fe57dae028205b118670e4aa4293d4f8aa14744 (diff) |
Android-FFMpeg: Dynamically create/remove AndroidSurfaceTexture
Before this change, MediaCodecTextureConverter used a single static
AndroidSurfaceTexture. When trying to play another video, currently used
Surface was trying to be reused. Because of that, more than one
simultaneous video playback caused the app to crash on Android.
Android surface textures need to be created dynamically, depending as
needed.
MediaCodecTextureConverter is created as a backend in TextureConverter
when the first frame from videoSink appears. At this point the Surface
is already created, set in the codecContext and used by FFmpeg.
Pick-to: 6.6 6.5
Fixes: QTBUG-121182
Fixes: QTBUG-122649
Change-Id: Ie9845ac78d770e4c06b6046fc59c0afbd39fb14a
Reviewed-by: Artem Dyomin <artem.dyomin@qt.io>
(cherry picked from commit dd1d51a5c8cdc2bdd37493570e0481a618049280)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r-- | src/plugins/multimedia/ffmpeg/qffmpeghwaccel_mediacodec.cpp | 38 | ||||
-rw-r--r-- | src/plugins/multimedia/ffmpeg/qffmpeghwaccel_mediacodec_p.h | 1 |
2 files changed, 35 insertions, 4 deletions
diff --git a/src/plugins/multimedia/ffmpeg/qffmpeghwaccel_mediacodec.cpp b/src/plugins/multimedia/ffmpeg/qffmpeghwaccel_mediacodec.cpp index b1f9e8078..c28099c99 100644 --- a/src/plugins/multimedia/ffmpeg/qffmpeghwaccel_mediacodec.cpp +++ b/src/plugins/multimedia/ffmpeg/qffmpeghwaccel_mediacodec.cpp @@ -17,8 +17,6 @@ extern "C" { namespace QFFmpeg { -Q_GLOBAL_STATIC(AndroidSurfaceTexture, androidSurfaceTexture, 0); - class MediaCodecTextureSet : public TextureSet { public: @@ -30,8 +28,33 @@ private: qint64 handle; }; +namespace { + +void deleteSurface(AVHWDeviceContext *ctx) +{ + AndroidSurfaceTexture* s = reinterpret_cast<AndroidSurfaceTexture *>(ctx->user_opaque); + delete s; +} + +AndroidSurfaceTexture* getTextureSurface(AVFrame *frame) +{ + if (!frame || !frame->hw_frames_ctx) + return nullptr; + + auto *frameContext = reinterpret_cast<AVHWFramesContext *>(frame->hw_frames_ctx->data); + + if (!frameContext || !frameContext->device_ctx) + return nullptr; + + AVHWDeviceContext *deviceContext = frameContext->device_ctx; + + return reinterpret_cast<AndroidSurfaceTexture *>(deviceContext->user_opaque); +} +} // namespace + void MediaCodecTextureConverter::setupDecoderSurface(AVCodecContext *avCodecContext) { + std::unique_ptr<AndroidSurfaceTexture> androidSurfaceTexture(new AndroidSurfaceTexture(0)); AVMediaCodecContext *mediacodecContext = av_mediacodec_alloc_context(); av_mediacodec_default_init(avCodecContext, mediacodecContext, androidSurfaceTexture->surface()); @@ -51,14 +74,21 @@ void MediaCodecTextureConverter::setupDecoderSurface(AVCodecContext *avCodecCont return; mediaDeviceContext->surface = androidSurfaceTexture->surface(); + + Q_ASSERT(deviceContext->user_opaque == nullptr); + deviceContext->user_opaque = androidSurfaceTexture.release(); + deviceContext->free = deleteSurface; } TextureSet *MediaCodecTextureConverter::getTextures(AVFrame *frame) { - if (!androidSurfaceTexture->isValid()) + AndroidSurfaceTexture * androidSurfaceTexture = getTextureSurface(frame); + + if (!androidSurfaceTexture || !androidSurfaceTexture->isValid()) return {}; - if (!externalTexture) { + if (!externalTexture || m_currentSurfaceIndex != androidSurfaceTexture->index()) { + m_currentSurfaceIndex = androidSurfaceTexture->index(); androidSurfaceTexture->detachFromGLContext(); externalTexture = std::unique_ptr<QRhiTexture>( rhi->newTexture(QRhiTexture::Format::RGBA8, { frame->width, frame->height }, 1, diff --git a/src/plugins/multimedia/ffmpeg/qffmpeghwaccel_mediacodec_p.h b/src/plugins/multimedia/ffmpeg/qffmpeghwaccel_mediacodec_p.h index 95982ba4d..79d33d03e 100644 --- a/src/plugins/multimedia/ffmpeg/qffmpeghwaccel_mediacodec_p.h +++ b/src/plugins/multimedia/ffmpeg/qffmpeghwaccel_mediacodec_p.h @@ -30,6 +30,7 @@ public: static void setupDecoderSurface(AVCodecContext *s); private: std::unique_ptr<QRhiTexture> externalTexture; + quint64 m_currentSurfaceIndex = 0; }; } #endif // QFFMPEGHWACCEL_MEDIACODEC_P_H |