summaryrefslogtreecommitdiffstats
path: root/video/decode
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2017-12-26 06:09:26 +0100
committerKevin Mitchell <kevmitch@gmail.com>2017-12-28 00:59:22 -0700
commit5e50fe30492cd593ba33d3daa846b650c7d302ca (patch)
tree4fb3f8cb14b7be66dea30a42ece3302b6eb42acf /video/decode
parentd480b1261b92fcf2ba08bd0934a86e65220d8950 (diff)
downloadmpv-5e50fe30492cd593ba33d3daa846b650c7d302ca.tar.bz2
mpv-5e50fe30492cd593ba33d3daa846b650c7d302ca.tar.xz
demux_mkv: add hack to pass along x264 version to decoder
This fixes when resuming certain broken h264 files encoded by x264. See FFmpeg commit 840b41b2a643fc8f0617c0370125a19c02c6b586 about the x264 bug itself. Normally, the unregistered user data SEI (that contains the x264 version string) is informational only. But libavcodec uses it to workaround a x264 bug, which was recently fixed in both libavcodec and x264. The fact that both encoder and decoder were buggy is the reason that it was not found earlier, and there are apparently a lot of files around created by the broken decoder. If libavcodec sees the SEI, this bug can be worked around by using the old behavior. If you resume a file with mpv (i.e. seeking when the file loads), libavcodec never sees the first video packet. Consequently it has to assume the file is not broken, and never applies the workaround, resulting in garbage being played. Fix this by always feeding the first video packet to the decoder on init, and then flushing the codec (to avoid that an unwanted image is output). Flushing the codec does not remove info such as the x264 version. We also abuse the fact that the first avcodec_send_packet() always pushes the frame into the decoder (so we don't have to trigger the decoder by requsting an output frame).
Diffstat (limited to 'video/decode')
-rw-r--r--video/decode/vd_lavc.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c
index 0f31de9f02..79adc311a9 100644
--- a/video/decode/vd_lavc.c
+++ b/video/decode/vd_lavc.c
@@ -666,6 +666,19 @@ static void init_avctx(struct dec_video *vd)
if (avcodec_open2(avctx, lavc_codec, NULL) < 0)
goto error;
+ // Sometimes, the first packet contains information required for correct
+ // decoding of the rest of the stream. The only currently known case is the
+ // x264 build number (encoded in a SEI element), needed to enable a
+ // workaround for broken 4:4:4 streams produced by older x264 versions.
+ if (lavc_codec->id == AV_CODEC_ID_H264 && c->first_packet) {
+ AVPacket avpkt;
+ mp_set_av_packet(&avpkt, c->first_packet, &ctx->codec_timebase);
+ avcodec_send_packet(avctx, &avpkt);
+ avcodec_receive_frame(avctx, ctx->pic);
+ av_frame_unref(ctx->pic);
+ avcodec_flush_buffers(ctx->avctx);
+ }
+
return;
error: