From a6694d27889b4b65ab6d05641396724ae9696f77 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 14 Nov 2014 23:52:47 +0100 Subject: demux_mkv: adjust subtitle preroll again (2) Make the changes started in commit c827ae5f more eloborate, and provide an option to control the amount of data read before the seek-target. To achieve this, rewrite the loop that finds the lowest still acceptable target cluster. It is now searched by time instead of file position. The behavior (both with and without preroll option) may be different from before this change, although it shouldn't be worse. The change demux_mkv_read_cues() fixes a bug: when seeking after playing normally, the code would erroneously assume that durations are set. This doesn't happen if the first operation after loading was a seek instead of playback. --- demux/demux_mkv.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'demux/demux_mkv.c') diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index 79e62a112c..100447d1f7 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -717,6 +717,7 @@ static int demux_mkv_read_cues(demuxer_t *demuxer) 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]; @@ -2714,12 +2715,20 @@ static struct mkv_index *seek_with_cues(struct demuxer *demuxer, int seek_id, if (index) { /* We've found an entry. */ uint64_t seek_pos = index->filepos; if (flags & SEEK_SUBPREROLL) { + // Find the cluster with the highest filepos, that has a timestamp + // still lower than min_tc. + double secs = demuxer->opts->mkv_subtitle_preroll_secs; + uint64_t pre = MPMIN(INT64_MAX, secs * 1e9 / mkv_d->tc_scale); + uint64_t min_tc = pre < index->timecode ? index->timecode - pre : 0; uint64_t prev_target = 0; + uint64_t prev_tc = 0; for (size_t i = 0; i < mkv_d->num_indexes; i++) { if (seek_id < 0 || mkv_d->indexes[i].tnum == seek_id) { - uint64_t index_pos = mkv_d->indexes[i].filepos; - if (index_pos > prev_target && index_pos < seek_pos) - prev_target = index_pos; + struct mkv_index *cur = &mkv_d->indexes[i]; + if (cur->timecode <= min_tc && cur->timecode >= prev_tc) { + prev_tc = cur->timecode; + prev_target = cur->filepos; + } } } if (mkv_d->index_has_durations) { -- cgit v1.2.3