From ba384fffca982465e63c3ffe3a3fb34c08e75de2 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 26 Aug 2015 22:47:07 +0200 Subject: demux_mkv: discard broken index Add a simplistic heuristic for detecting broken indexes. This includes indexes with very few elements (apparently libavformat sometimes writes such indexes, or used to), and indexes with broken timestamps. The latter was apparently produced by very old HandBrake versions: | + Muxing application: libmkv 0.6.1.2 | + Writing application: HandBrake 0.9.1 These broken files seem to be common enough that libavformat added a workaround for them in 2008 (and maybe again in 2015). Apparently all timestamps are multiplied with the file's tc_scale twice, and FFmpeg attempts to fix them. We should throw away the whole thing. --- demux/demux_mkv.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index 89a7d42114..e2743d5ef8 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -735,15 +735,25 @@ static int demux_mkv_read_cues(demuxer_t *demuxer) if (ebml_read_element(s, &parse_ctx, &cues, &ebml_cues_desc) < 0) return -1; - mkv_d->num_indexes = 0; - mkv_d->index_has_durations = false; - for (int i = 0; i < cues.n_cue_point; i++) { struct ebml_cue_point *cuepoint = &cues.cue_point[i]; if (cuepoint->n_cue_time != 1 || !cuepoint->n_cue_track_positions) { MP_WARN(demuxer, "Malformed CuePoint element\n"); - continue; + goto done; } + if (cuepoint->cue_time / 1e9 > mkv_d->duration / mkv_d->tc_scale * 10 && + mkv_d->duration != 0) + goto done; + } + if (cues.n_cue_point <= 3) // probably too sparse and will just break seeking + goto done; + + // Discard incremental index. + mkv_d->num_indexes = 0; + mkv_d->index_has_durations = false; + + for (int i = 0; i < cues.n_cue_point; i++) { + struct ebml_cue_point *cuepoint = &cues.cue_point[i]; uint64_t time = cuepoint->cue_time; for (int c = 0; c < cuepoint->n_cue_track_positions; c++) { struct ebml_cue_track_positions *trackpos = @@ -763,6 +773,9 @@ static int demux_mkv_read_cues(demuxer_t *demuxer) // Do not attempt to create index on the fly. mkv_d->index_complete = true; +done: + if (!mkv_d->index_complete) + MP_WARN(demuxer, "Discarding potentially broken or useless index.\n"); talloc_free(parse_ctx.talloc_ctx); return 0; } -- cgit v1.2.3