summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/en/options.rst23
-rw-r--r--core/cfg-mplayer.h1
-rw-r--r--core/mplayer.c2
-rw-r--r--core/options.h1
-rw-r--r--demux/demux.h1
-rw-r--r--demux/demux_mkv.c40
6 files changed, 59 insertions, 9 deletions
diff --git a/DOCS/man/en/options.rst b/DOCS/man/en/options.rst
index cc55c3a40e..5faf3cdb7e 100644
--- a/DOCS/man/en/options.rst
+++ b/DOCS/man/en/options.rst
@@ -1173,6 +1173,29 @@
:fps=<value>: output fps (default: 25)
:type=<value>: input file type (available: jpeg, png, tga, sgi)
+--mkv-subtitle-preroll
+ Try harder to show embedded soft subtitles when seeking somewhere. Normally,
+ it can happen that the subtitle at the seek target is not shown due to how
+ some container file formats are designed. The subtitles appear only if
+ seeking before or exactly to the position a subtitle first appears. To
+ make this worse, subtitles are often timed to appear a very small amount
+ before the associated video frame, so that seeking to the video frame
+ typically does not demux the subtitle at that position.
+
+ Enabling this option makes the demuxer start reading data a bit before the
+ seek target, so that subtitles appear correctly. Note that this makes
+ seeking slower, and is not guaranteed to always work. It only works if the
+ subtitle is close enough to the seek target.
+
+ Works with the internal Matroska demuxer only. Always enabled for absolute
+ and hr-seeks, and this option changes behavior with relative or imprecise
+ seeks only.
+
+ 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,
+ instead of just skipping over it.
+
--mixer=<device>
Use a mixer device different from the default ``/dev/mixer``. For ALSA
this is the mixer name.
diff --git a/core/cfg-mplayer.h b/core/cfg-mplayer.h
index 4bdead1be1..a85f83ac36 100644
--- a/core/cfg-mplayer.h
+++ b/core/cfg-mplayer.h
@@ -391,6 +391,7 @@ const m_option_t common_opts[] = {
OPT_STRING("audio-demuxer", audio_demuxer_name, 0),
OPT_STRING("sub-demuxer", sub_demuxer_name, 0),
OPT_FLAG("extbased", extension_parsing, 0),
+ OPT_FLAG("mkv-subtitle-preroll", mkv_subtitle_preroll, 0),
{"mf", (void *) mfopts_conf, CONF_TYPE_SUBCONFIG, 0,0,0, NULL},
#ifdef CONFIG_RADIO
diff --git a/core/mplayer.c b/core/mplayer.c
index 21af9ca57a..3833d0a7da 100644
--- a/core/mplayer.c
+++ b/core/mplayer.c
@@ -2821,6 +2821,8 @@ static int seek(MPContext *mpctx, struct seek_params seek,
demuxer_style |= SEEK_BACKWARD;
else if (seek.direction > 0)
demuxer_style |= SEEK_FORWARD;
+ if (hr_seek || opts->mkv_subtitle_preroll)
+ demuxer_style |= SEEK_SUBPREROLL;
if (hr_seek)
demuxer_amount -= opts->hr_seek_demuxer_offset;
diff --git a/core/options.h b/core/options.h
index 0f1df17ba5..716ad5c357 100644
--- a/core/options.h
+++ b/core/options.h
@@ -140,6 +140,7 @@ typedef struct MPOpts {
char *audio_demuxer_name;
char *sub_demuxer_name;
int extension_parsing;
+ int mkv_subtitle_preroll;
struct image_writer_opts *screenshot_image_opts;
char *screenshot_template;
diff --git a/demux/demux.h b/demux/demux.h
index 41551975cc..debd0f55b1 100644
--- a/demux/demux.h
+++ b/demux/demux.h
@@ -103,6 +103,7 @@ enum timestamp_type {
#define SEEK_FACTOR (1 << 1)
#define SEEK_FORWARD (1 << 2)
#define SEEK_BACKWARD (1 << 3)
+#define SEEK_SUBPREROLL (1 << 4)
// demux_lavf can pass lavf buffers using FF_INPUT_BUFFER_PADDING_SIZE instead
#define MP_INPUT_BUFFER_PADDING_SIZE 16
diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c
index 5b178d66b9..0171b1e9a2 100644
--- a/demux/demux_mkv.c
+++ b/demux/demux_mkv.c
@@ -178,6 +178,7 @@ typedef struct mkv_demuxer {
uint64_t skip_to_timecode;
int v_skip_to_keyframe, a_skip_to_keyframe;
+ bool subtitle_preroll;
int num_audio_tracks;
int num_video_tracks;
@@ -2114,6 +2115,18 @@ static int handle_block(demuxer_t *demuxer, uint8_t *block, uint64_t length,
track->fix_i_bps = 0;
}
}
+ } else if (track->type == MATROSKA_TRACK_SUBTITLE
+ && track->id == demuxer->sub->id) {
+ if (tc < mkv_d->skip_to_timecode && !mkv_d->subtitle_preroll)
+ use_this_block = 0;
+ if (use_this_block) {
+ ds = demuxer->sub;
+ if (laces > 1) {
+ mp_msg(MSGT_DEMUX, MSGL_WARN, "[mkv] Subtitles use Matroska "
+ "lacing. This is abnormal and not supported.\n");
+ use_this_block = 0;
+ }
+ }
} else if (tc < mkv_d->skip_to_timecode)
use_this_block = 0;
else if (track->type == MATROSKA_TRACK_VIDEO
@@ -2121,14 +2134,6 @@ static int handle_block(demuxer_t *demuxer, uint8_t *block, uint64_t length,
ds = demuxer->video;
if (mkv_d->v_skip_to_keyframe)
use_this_block = keyframe;
- } else if (track->type == MATROSKA_TRACK_SUBTITLE
- && track->id == demuxer->sub->id) {
- ds = demuxer->sub;
- if (laces > 1) {
- mp_msg(MSGT_DEMUX, MSGL_WARN, "[mkv] Subtitles use Matroska "
- "lacing. This is abnormal and not supported.\n");
- use_this_block = 0;
- }
} else
use_this_block = 0;
@@ -2170,6 +2175,7 @@ static int handle_block(demuxer_t *demuxer, uint8_t *block, uint64_t length,
if (ds == demuxer->video) {
mkv_d->v_skip_to_keyframe = 0;
mkv_d->skip_to_timecode = 0;
+ mkv_d->subtitle_preroll = false;
} else if (ds == demuxer->audio)
mkv_d->a_skip_to_keyframe = 0;
@@ -2410,6 +2416,7 @@ static struct mkv_index *seek_with_cues(struct demuxer *demuxer, int seek_id,
if (flags & SEEK_BACKWARD)
min_diff = -min_diff;
min_diff = FFMAX(min_diff, 1);
+
for (int i = 0; i < mkv_d->num_indexes; i++)
if (seek_id < 0 || mkv_d->indexes[i].tnum == seek_id) {
int64_t diff =
@@ -2427,8 +2434,22 @@ 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 (mkv_d->subtitle_preroll && demuxer->sub->id >= 0) {
+ uint64_t prev_target = 0;
+ for (int 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;
+ }
+ }
+ if (prev_target)
+ seek_pos = prev_target;
+ }
+
mkv_d->cluster_size = mkv_d->blockgroup_size = 0;
- stream_seek(demuxer->stream, index->filepos);
+ stream_seek(demuxer->stream, seek_pos);
}
return index;
}
@@ -2445,6 +2466,7 @@ static void demux_mkv_seek(demuxer_t *demuxer, float rel_seek_secs,
if (demuxer->audio->id >= 0)
a_tnum = find_track_by_num(mkv_d, demuxer->audio->id,
MATROSKA_TRACK_AUDIO)->tnum;
+ mkv_d->subtitle_preroll = !!(flags & SEEK_SUBPREROLL);
if (!(flags & (SEEK_BACKWARD | SEEK_FORWARD))) {
if (flags & SEEK_ABSOLUTE || rel_seek_secs < 0)
flags |= SEEK_BACKWARD;