summaryrefslogtreecommitdiffstats
path: root/audio/decode
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2016-06-22 21:37:36 +0200
committerwm4 <wm4@nowhere>2016-06-22 21:37:36 +0200
commit7ea22fe889fececeb653daa5f957ae600d7bb616 (patch)
treef67c9c1ec8d1fdaf7782e45be111ddc4149fff53 /audio/decode
parent9d0af0681191823608d9bbc290f5f30fc60e228e (diff)
downloadmpv-7ea22fe889fececeb653daa5f957ae600d7bb616.tar.bz2
mpv-7ea22fe889fececeb653daa5f957ae600d7bb616.tar.xz
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.
Diffstat (limited to 'audio/decode')
-rw-r--r--audio/decode/ad_lavc.c7
1 files changed, 7 insertions, 0 deletions
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;
}