[FFmpeg-devel] [PATCH 2/4] avcodec/decode: allow the decoder to signal an unrecoverable error was found
James Almer
jamrial at gmail.com
Tue Nov 22 15:07:30 EET 2022
Signed-off-by: James Almer <jamrial at gmail.com>
---
libavcodec/avcodec.c | 1 +
libavcodec/decode.c | 17 ++++++++++++++++-
libavcodec/internal.h | 5 +++++
3 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/libavcodec/avcodec.c b/libavcodec/avcodec.c
index a85d3c2309..7818b6e33b 100644
--- a/libavcodec/avcodec.c
+++ b/libavcodec/avcodec.c
@@ -397,6 +397,7 @@ void avcodec_flush_buffers(AVCodecContext *avctx)
av_bsf_flush(avci->bsf);
}
+ avci->fatal = 0;
avci->draining = 0;
avci->draining_done = 0;
avci->nb_draining_errors = 0;
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index 6be2d3d6ed..04c9d374ce 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -576,7 +576,9 @@ 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) {
+ if (avci->fatal) {
+ ret = avci->draining ? AVERROR_EOF : AVERROR_UNRECOVERABLE;
+ } else if (codec->cb_type == FF_CODEC_CB_TYPE_RECEIVE_FRAME) {
ret = codec->cb.receive_frame(avctx, frame);
if (ret != AVERROR(EAGAIN))
av_packet_unref(avci->last_pkt_props);
@@ -586,6 +588,9 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame)
if (ret == AVERROR_EOF)
avci->draining_done = 1;
+ if (ret == AVERROR_UNRECOVERABLE)
+ avci->fatal = 1;
+
/* preserve ret */
ok = detect_colorspace(avctx, frame);
if (ok < 0) {
@@ -648,6 +653,16 @@ int attribute_align_arg avcodec_send_packet(AVCodecContext *avctx, const AVPacke
if (avpkt && !avpkt->size && avpkt->data)
return AVERROR(EINVAL);
+ if (avctx->internal->fatal) {
+ /* The API expects EOF signaling to always be handled even with
+ * decoding errors */
+ if (!avpkt || (!avpkt->data && !avpkt->side_data_elems)) {
+ avctx->internal->draining = 1;
+ return 0;
+ }
+ return AVERROR_UNRECOVERABLE;
+ }
+
av_packet_unref(avci->buffer_pkt);
if (avpkt && (avpkt->data || avpkt->side_data_elems)) {
ret = av_packet_ref(avci->buffer_pkt, avpkt);
diff --git a/libavcodec/internal.h b/libavcodec/internal.h
index 76a6ea6bc6..622f5728e2 100644
--- a/libavcodec/internal.h
+++ b/libavcodec/internal.h
@@ -142,6 +142,11 @@ typedef struct AVCodecInternal {
*/
int draining;
+ /**
+ * An unrecoverable error was found, decoding can't proceed normally
+ */
+ int fatal;
+
/**
* Temporary buffers for newly received or not yet output packets/frames.
*/
--
2.38.1
More information about the ffmpeg-devel
mailing list