[FFmpeg-devel] [PATCH] avcodec/mmaldec: fix decoder freeze when flushing
Ho Ming Shun
cyph1984 at gmail.com
Thu Sep 16 16:46:52 EEST 2021
When mmal_flush is called before any packets are sent,
enabling/disabling the MMAL ports seems to cause the decoder to not
output any packets after flushing.
Bug is triggered when using 'mpv --hwdec=mmal --start=1 test.mp4'.
Proposed workaround in MPV: https://github.com/mpv-player/mpv/pull/9189
Signed-off-by: Ho Ming Shun <cyph1984 at gmail.com>
---
libavcodec/mmaldec.c | 38 +++++++++++++++++++++++---------------
1 file changed, 23 insertions(+), 15 deletions(-)
diff --git a/libavcodec/mmaldec.c b/libavcodec/mmaldec.c
index 8c7d749742..6c3e5d99b6 100644
--- a/libavcodec/mmaldec.c
+++ b/libavcodec/mmaldec.c
@@ -145,19 +145,21 @@ static int ffmmal_set_ref(AVFrame *frame, FFPoolRef *pool,
return 0;
}
-static void ffmmal_stop_decoder(AVCodecContext *avctx)
+static void ffmmal_stop_decoder(AVCodecContext *avctx, int flush_ports)
{
MMALDecodeContext *ctx = avctx->priv_data;
MMAL_COMPONENT_T *decoder = ctx->decoder;
MMAL_BUFFER_HEADER_T *buffer;
- mmal_port_disable(decoder->input[0]);
- mmal_port_disable(decoder->output[0]);
- mmal_port_disable(decoder->control);
+ if(flush_ports) {
+ mmal_port_disable(decoder->input[0]);
+ mmal_port_disable(decoder->output[0]);
+ mmal_port_disable(decoder->control);
- mmal_port_flush(decoder->input[0]);
- mmal_port_flush(decoder->output[0]);
- mmal_port_flush(decoder->control);
+ mmal_port_flush(decoder->input[0]);
+ mmal_port_flush(decoder->output[0]);
+ mmal_port_flush(decoder->control);
+ }
while ((buffer = mmal_queue_get(ctx->queue_decoded_frames)))
mmal_buffer_header_release(buffer);
@@ -185,7 +187,7 @@ static av_cold int ffmmal_close_decoder(AVCodecContext *avctx)
MMALDecodeContext *ctx = avctx->priv_data;
if (ctx->decoder)
- ffmmal_stop_decoder(avctx);
+ ffmmal_stop_decoder(avctx, 1);
mmal_component_destroy(ctx->decoder);
ctx->decoder = NULL;
@@ -456,14 +458,20 @@ static void ffmmal_flush(AVCodecContext *avctx)
MMAL_COMPONENT_T *decoder = ctx->decoder;
MMAL_STATUS_T status;
- ffmmal_stop_decoder(avctx);
+ // MMAL will freeze if ports are enabled/disabled/flushed before
+ // buffers are sent
+ int flush_ports = ctx->packets_sent || ctx->extradata_sent;
- if ((status = mmal_port_enable(decoder->control, control_port_cb)))
- goto fail;
- if ((status = mmal_port_enable(decoder->input[0], input_callback)))
- goto fail;
- if ((status = mmal_port_enable(decoder->output[0], output_callback)))
- goto fail;
+ ffmmal_stop_decoder(avctx, flush_ports);
+
+ if(flush_ports) {
+ if ((status = mmal_port_enable(decoder->control, control_port_cb)))
+ goto fail;
+ if ((status = mmal_port_enable(decoder->input[0], input_callback)))
+ goto fail;
+ if ((status = mmal_port_enable(decoder->output[0], output_callback)))
+ goto fail;
+ }
return;
--
2.33.0
More information about the ffmpeg-devel
mailing list