summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBartlomiej Moskal <bartlomiej.moskal@qt.io>2024-02-26 13:41:48 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2024-02-29 20:02:48 +0000
commitb04f18195e8bd5428376b34d07dbe7f16847d1fe (patch)
treeb937581989b133e03c1f26aefee3ebc78e25f01b
parent2fe57dae028205b118670e4aa4293d4f8aa14744 (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.cpp38
-rw-r--r--src/plugins/multimedia/ffmpeg/qffmpeghwaccel_mediacodec_p.h1
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