mirror of
https://github.com/mpv-player/mpv
synced 2024-12-24 15:52:25 +00:00
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.
This commit is contained in:
parent
d484cb3f32
commit
a6694d2788
@ -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).
|
||||
|
@ -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) {
|
||||
|
@ -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",
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user