PR #20511 opened by Zhao Zhili (quink) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20511 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20511.patch
>From aa109c9581468287eab30a987992f9bfbcf5f7ef Mon Sep 17 00:00:00 2001 From: Zhao Zhili <zhiliz...@tencent.com> Date: Sat, 13 Sep 2025 12:26:08 +0800 Subject: [PATCH 1/2] avcodec/rkmppdec: fix input queue overflow The strategy to count free slots isn't reliable. The value of INPUT_MAX_PACKETS is a hardcoded value, and MPP_DEC_GET_STREAM_COUNT doesn't always work as expected. When freeslots is nonzero, the mpp decoder still returns MPP_ERR_BUFFER_FULL. Before this patch, all packets are dropped once went into MPP_ERR_BUFFER_FULL state. Don't drop packet and return error in MPP_ERR_BUFFER_FULL state. Receive frame to allow the decoder's state machine to resume. --- libavcodec/rkmppdec.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c index dad0e4c25f..c4bceb4dc4 100644 --- a/libavcodec/rkmppdec.c +++ b/libavcodec/rkmppdec.c @@ -55,6 +55,7 @@ typedef struct { AVBufferRef *frames_ref; AVBufferRef *device_ref; + AVPacket pkt; } RKMPPDecoder; typedef struct { @@ -148,6 +149,7 @@ static void rkmpp_release_decoder(AVRefStructOpaque unused, void *obj) av_buffer_unref(&decoder->frames_ref); av_buffer_unref(&decoder->device_ref); + av_packet_unref(&decoder->pkt); } static av_cold int rkmpp_init_decoder(AVCodecContext *avctx) @@ -485,7 +487,6 @@ static int rkmpp_receive_frame(AVCodecContext *avctx, AVFrame *frame) RKMPPDecodeContext *rk_context = avctx->priv_data; RKMPPDecoder *decoder = rk_context->decoder; int ret = MPP_NOK; - AVPacket pkt = {0}; RK_S32 usedslots, freeslots; if (!decoder->eos_reached) { @@ -498,17 +499,22 @@ static int rkmpp_receive_frame(AVCodecContext *avctx, AVFrame *frame) freeslots = INPUT_MAX_PACKETS - usedslots; if (freeslots > 0) { - ret = ff_decode_get_packet(avctx, &pkt); - if (ret < 0 && ret != AVERROR_EOF) { - return ret; + if (!decoder->pkt.size) { + ret = ff_decode_get_packet(avctx, &decoder->pkt); + if (ret < 0 && ret != AVERROR_EOF) { + return ret; + } } - ret = rkmpp_send_packet(avctx, &pkt); - av_packet_unref(&pkt); - - if (ret < 0) { + ret = rkmpp_send_packet(avctx, &decoder->pkt); + if (ret < 0 && ret != AVERROR(EAGAIN)) { av_log(avctx, AV_LOG_ERROR, "Failed to send packet to decoder (code = %d)\n", ret); return ret; + } else if (ret == AVERROR(EAGAIN)) { + // Input queue is full, don't queue more packet. + freeslots = 0; + } else { + av_packet_unref(&decoder->pkt); } } -- 2.49.1 >From 13a3e7f31b9d3bf50f67fbad94029ba9f8dfe430 Mon Sep 17 00:00:00 2001 From: Zhao Zhili <zhiliz...@tencent.com> Date: Sat, 13 Sep 2025 13:31:17 +0800 Subject: [PATCH 2/2] avcodec/rkmppdec: fix return EAGAIN during flushing --- libavcodec/rkmppdec.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c index c4bceb4dc4..8307f03456 100644 --- a/libavcodec/rkmppdec.c +++ b/libavcodec/rkmppdec.c @@ -519,11 +519,15 @@ static int rkmpp_receive_frame(AVCodecContext *avctx, AVFrame *frame) } // make sure we keep decoder full - if (freeslots > 1) + if (freeslots > 1 && !decoder->eos_reached) return AVERROR(EAGAIN); } - return rkmpp_retrieve_frame(avctx, frame); + do { + ret = rkmpp_retrieve_frame(avctx, frame); + } while (decoder->eos_reached && ret == AVERROR(EAGAIN)); + + return ret; } static av_cold void rkmpp_flush(AVCodecContext *avctx) -- 2.49.1 _______________________________________________ ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org To unsubscribe send an email to ffmpeg-devel-le...@ffmpeg.org