@@ -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;
@@ -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);
@@ -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.
*/
Signed-off-by: James Almer <jamrial@gmail.com> --- libavcodec/avcodec.c | 1 + libavcodec/decode.c | 17 ++++++++++++++++- libavcodec/internal.h | 5 +++++ 3 files changed, 22 insertions(+), 1 deletion(-)