From 048e978e8eb3dc645114102655cdcb065c3eb6c2 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 12 Jun 2024 12:42:27 +0200 Subject: [PATCH] lavc/decode: wrap AV_FRAME_FLAG_DISCARD handling in a loop Makes sure discarded frames do not cause EAGAIN to be returned during flushing, which is forbidden. --- libavcodec/decode.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index d8e60567bd..a5d4f696b2 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -613,17 +613,22 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame) av_assert0(!frame->buf[0]); if (codec->cb_type == FF_CODEC_CB_TYPE_RECEIVE_FRAME) { + while (1) { frame->pict_type = dc->initial_pict_type; frame->flags |= dc->intra_only_flag; ret = codec->cb.receive_frame(avctx, frame); emms_c(); if (!ret) { - if (avctx->codec->type == AVMEDIA_TYPE_VIDEO) - ret = (frame->flags & AV_FRAME_FLAG_DISCARD) ? AVERROR(EAGAIN) : 0; - else if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) { + if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) { int64_t discarded_samples = 0; ret = discard_samples(avctx, frame, &discarded_samples); } + if (ret == AVERROR(EAGAIN) || (frame->flags & AV_FRAME_FLAG_DISCARD)) { + av_frame_unref(frame); + continue; + } + } + break; } } else ret = decode_simple_receive_frame(avctx, frame);