summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-11-14 23:52:47 +0100
committerwm4 <wm4@nowhere>2014-11-15 00:55:30 +0100
commita6694d27889b4b65ab6d05641396724ae9696f77 (patch)
tree3c41306de3089dedd84378c7c3c3c8632ffdfe3a
parentd484cb3f3245573ec024d6a50099d9a5a5e4400d (diff)
downloadmpv-a6694d27889b4b65ab6d05641396724ae9696f77.tar.bz2
mpv-a6694d27889b4b65ab6d05641396724ae9696f77.tar.xz
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.
-rw-r--r--DOCS/man/options.rst19
-rw-r--r--demux/demux_mkv.c15
-rw-r--r--options/options.c3
-rw-r--r--options/options.h1
4 files changed, 35 insertions, 3 deletions
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst
index 8cd30d7fcf..feaeac6b30 100644
--- a/DOCS/man/options.rst
+++ b/DOCS/man/options.rst
@@ -2038,6 +2038,22 @@ Demuxer
and hr-seeks, and this option changes behavior with relative or imprecise
seeks only.
+ You can use the ``--demuxer-mkv-subtitle-preroll-secs`` option to specify
+ how mach data the demuxer should pre-read at most in order to find subtitle
+ packets that may overlap. Setting this to 0 will effectively disable this
+ preroll mechanism. Setting a very large value can make seeking very slow,
+ and an extremely large value would completely reread the entire file from
+ start to seek target on every seek - seeking can become slower towards the
+ end of the file. The details are messy, and the value is actually rounded
+ down to the cluster with the previous video keyframe.
+
+ Some files, especially files muxed with newer mkvmerge versions, have
+ information embedded that can be used to determine what subtitle packets
+ overlap with a seek target. In these cases, mpv will reduce the amount
+ of data read to a minimum. (Although it will still read *all* data between
+ the cluster that contains the first wanted subtitle packet, and the seek
+ target.)
+
See also ``--hr-seek-demuxer-offset`` option. This option can achieve a
similar effect, but only if hr-seek is active. It works with any demuxer,
but makes seeking much slower, as it has to decode audio and video data
@@ -2045,6 +2061,9 @@ Demuxer
``--mkv-subtitle-preroll`` is a deprecated alias.
+``--demuxer-mkv-subtitle-preroll-secs=<value>``
+ See ``--demuxer-mkv-subtitle-preroll``.
+
``--demuxer-rawaudio-channels=<value>``
Number of channels (or channel layout) if ``--demuxer=rawaudio`` is used
(default: stereo).
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) {
diff --git a/options/options.c b/options/options.c
index c15482fd05..ba251f6216 100644
--- a/options/options.c
+++ b/options/options.c
@@ -301,6 +301,8 @@ const m_option_t mp_opts[] = {
OPT_FLAG("demuxer-mkv-subtitle-preroll", mkv_subtitle_preroll, 0),
OPT_FLAG("mkv-subtitle-preroll", mkv_subtitle_preroll, 0), // old alias
+ OPT_DOUBLE("demuxer-mkv-subtitle-preroll-secs", mkv_subtitle_preroll_secs,
+ M_OPT_MIN, .min = 0),
// ------------------------- subtitles options --------------------
@@ -670,6 +672,7 @@ const struct MPOpts mp_default_opts = {
.use_embedded_fonts = 1,
.sub_fix_timing = 1,
.sub_cp = "auto",
+ .mkv_subtitle_preroll_secs = 1.0,
.hwdec_codecs = "h264,vc1,wmv3",
diff --git a/options/options.h b/options/options.h
index f67a3a5c95..9284320f40 100644
--- a/options/options.h
+++ b/options/options.h
@@ -194,6 +194,7 @@ typedef struct MPOpts {
char *audio_demuxer_name;
char *sub_demuxer_name;
int mkv_subtitle_preroll;
+ double mkv_subtitle_preroll_secs;
double demuxer_min_secs_cache;
int cache_pausing;