From 7ea22fe889fececeb653daa5f957ae600d7bb616 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 22 Jun 2016 21:37:36 +0200 Subject: [PATCH] ad_lavc: resume from mid-stream EOF conditions with new decode API Workaround for an awful corner-case. The new decode API "locks" the decoder into the EOF state once a drain packet has been sent. The problem starts with a file containing a 0-sized packet, which is interpreted as drain packet. This should probably be changed in libavcodec (not treating 0-sized packets as drain packets with the new API) or in libavformat (discard 0-sized packets as invalid), but efforts to do so have been fruitless. Note that vd_lavc.c already does something similar, but originally for other reasons. Fixes #3106. --- audio/decode/ad_lavc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c index 8a6bb4061b..f48993f81f 100644 --- a/audio/decode/ad_lavc.c +++ b/audio/decode/ad_lavc.c @@ -45,6 +45,7 @@ struct priv { uint32_t skip_samples, trim_samples; bool preroll_done; double next_pts; + bool needs_reset; AVRational codec_timebase; }; @@ -173,6 +174,7 @@ static int control(struct dec_audio *da, int cmd, void *arg) ctx->trim_samples = 0; ctx->preroll_done = false; ctx->next_pts = MP_NOPTS_VALUE; + ctx->needs_reset = false; return CONTROL_TRUE; } return CONTROL_UNKNOWN; @@ -192,6 +194,9 @@ static int decode_packet(struct dec_audio *da, struct demux_packet *mpkt, int got_frame = 0; av_frame_unref(priv->avframe); + if (priv->needs_reset) + control(da, ADCTRL_RESET, NULL); + #if HAVE_AVCODEC_NEW_CODEC_API int ret = avcodec_send_packet(avctx, &pkt); if (ret >= 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { @@ -200,6 +205,8 @@ static int decode_packet(struct dec_audio *da, struct demux_packet *mpkt, ret = avcodec_receive_frame(avctx, priv->avframe); if (ret >= 0) got_frame = 1; + if (ret == AVERROR_EOF) + priv->needs_reset = true; if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) ret = 0; }