From 3b5777d86a62b9975c4c0fd224140e494db66ada Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 19 Dec 2016 21:29:46 +0100 Subject: demux_mkv: fix seeking in some broken files Some files have audio tracks with packets that do not have a keyframe flag set at all. I don't think there's any audio codec which actually needs keyframe flags, so always assume an audio packet is a keyframe (which, in Matroska terminology, means it can start decoding from that packet). The file in question had these set: | + Multiplexing application: Lavf57.56.100 at 313 | + Writing application: Lavf57.56.100 at 329 Garbage produced by garbage... There are other such files produced by mkvmerge, though. It's not perfectly sure whether these have been produced by FFmpeg as well (mkvmerge often trusts the information in the source file, even if it's wrong - so other samples could have been remuxed from FFmpeg). Fixes #3920. --- demux/demux_mkv.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'demux') diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index 5598cf8374..d127e517dc 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -128,6 +128,8 @@ typedef struct mkv_track { AVCodecParserContext *av_parser; AVCodecContext *av_parser_codec; + bool require_keyframes; + /* stuff for realaudio braincancer */ double ra_pts; /* previous audio timestamp */ uint32_t sub_packet_size; ///< sub packet size, per stream @@ -200,7 +202,7 @@ typedef struct mkv_demuxer { bool index_has_durations; - bool eof_warning; + bool eof_warning, keyframe_warning; struct block_info tmp_block; } mkv_demuxer_t; @@ -1752,6 +1754,10 @@ static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track) if (sh_a->samplerate == 8000 && strcmp(codec, "ac3") == 0) track->default_duration = 0; + // Deal with some FFmpeg-produced garbage, and assume all audio codecs can + // start decoding from anywhere. + track->require_keyframes = true; + sh_a->extradata = extradata; sh_a->extradata_size = extradata_len; @@ -2474,6 +2480,15 @@ static int handle_block(demuxer_t *demuxer, struct block_info *block_info) current_pts = tc / 1e9 - track->codec_delay; + if (track->require_keyframes && !keyframe) { + keyframe = true; + if (!mkv_d->keyframe_warning) { + MP_WARN(demuxer, "This is a broken file! Packets with incorrect " + "keyframe flag found. Enabling workaround.\n"); + mkv_d->keyframe_warning = true; + } + } + if (track->type == MATROSKA_TRACK_AUDIO) { if (mkv_d->a_skip_to_keyframe) use_this_block &= keyframe; -- cgit v1.2.3