summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/en/options.rst15
-rw-r--r--core/options.c6
-rw-r--r--sub/dec_sub.c45
3 files changed, 53 insertions, 13 deletions
diff --git a/DOCS/man/en/options.rst b/DOCS/man/en/options.rst
index 304eeba464..b9068b1562 100644
--- a/DOCS/man/en/options.rst
+++ b/DOCS/man/en/options.rst
@@ -1447,11 +1447,6 @@
``show_progress`` command (by default mapped to ``P``), or in some
non-default cases when seeking. Expands properties. See property_expansion_.
---overlapsub
- Allows the next subtitle to be displayed while the current one is still
- visible (default is to enable the support only for specific formats). This
- only matters for subtitles loaded with ``-sub``.
-
--panscan=<0.0-1.0>
Enables pan-and-scan functionality (cropping the sides of e.g. a 16:9
movie to make it fit a 4:3 display without black bands). The range
@@ -1996,15 +1991,17 @@
Use/display these subtitle files. Only one file can be displayed at the
same time.
+--sub-fix-timing, --no-sub-fix-timing
+ By default, external text subtitles are preprocessed to remove minor gaps
+ or overlaps between subtitles (if the difference is smaller than 200 ms,
+ the gap or overlap is removed). This does not affect image subtitles,
+ subtitles muxed with audio/video, or subtitles in the ASS format.
+
--sub-demuxer=<[+]name>
Force subtitle demuxer type for ``--subfile``. Using a '+' before the name
will force it, this will skip some checks! Give the demuxer name as
printed by ``--sub-demuxer=help``.
---sub-no-text-pp
- Disables any kind of text post processing done after loading the
- subtitles. Used for debug purposes.
-
--sub-paths=<path1:path2:...>
Specify extra directories where to search for subtitles matching the
video. Multiple directories can be separated by ":" (";" on Windows).
diff --git a/core/options.c b/core/options.c
index f3e262fc17..2e0d32bb60 100644
--- a/core/options.c
+++ b/core/options.c
@@ -496,9 +496,7 @@ const m_option_t mp_opts[] = {
OPT_FLAG("autosub", sub_auto, 0),
OPT_FLAG("sub-visibility", sub_visibility, 0),
OPT_FLAG("sub-forced-only", forced_subs_only, 0),
- // enable Closed Captioning display
- OPT_FLAG_CONSTANTS("overlapsub", suboverlap_enabled, 0, 0, 2),
- OPT_FLAG_STORE("sub-no-text-pp", sub_no_text_pp, 0, 1),
+ OPT_FLAG_CONSTANTS("sub-fix-timing", suboverlap_enabled, 0, 1, 0),
OPT_CHOICE("autosub-match", sub_match_fuzziness, 0,
({"exact", 0}, {"fuzzy", 1}, {"all", 2})),
OPT_INTRANGE("sub-pos", sub_pos, 0, 0, 100),
@@ -804,7 +802,7 @@ const struct MPOpts mp_default_opts = {
.ass_vsfilter_aspect_compat = 1,
.ass_style_override = 1,
.use_embedded_fonts = 1,
- .suboverlap_enabled = 1,
+ .suboverlap_enabled = 0,
.hwdec_codecs = "all",
diff --git a/sub/dec_sub.c b/sub/dec_sub.c
index 187ae5f22c..230dfa2f55 100644
--- a/sub/dec_sub.c
+++ b/sub/dec_sub.c
@@ -261,6 +261,43 @@ void sub_init_from_sh(struct dec_sub *sub, struct sh_sub *sh)
sh->gsh->codec ? sh->gsh->codec : "<unknown>");
}
+static void multiply_timings(struct packet_list *subs, double factor)
+{
+ for (int n = 0; n < subs->num_packets; n++) {
+ struct demux_packet *pkt = subs->packets[n];
+ if (pkt->pts != MP_NOPTS_VALUE)
+ pkt->pts *= factor;
+ if (pkt->duration > 0)
+ pkt->duration *= factor;
+ }
+}
+
+// Remove overlaps and fill gaps between adjacent subtitle packets. This is done
+// by adjusting the duration of the earlier packet. If the gaps or overlap are
+// larger than the threshold, or if the durations are close to the threshold,
+// don't change the events.
+// The algorithm is maximally naive and doesn't work if there are multiple
+// overlapping lines. (It's not worth the trouble.)
+static void fix_overlaps_and_gaps(struct packet_list *subs)
+{
+ double threshold = 0.2; // up to 200 ms overlaps or gaps are removed
+ double keep = threshold * 2;// don't change timings if durations are smaller
+ for (int i = 0; i < subs->num_packets - 1; i++) {
+ struct demux_packet *cur = subs->packets[i];
+ struct demux_packet *next = subs->packets[i + 1];
+ if (cur->pts != MP_NOPTS_VALUE && cur->duration > 0 &&
+ next->pts != MP_NOPTS_VALUE && next->duration > 0)
+ {
+ double end = cur->pts + cur->duration;
+ if (fabs(next->pts - end) <= threshold && cur->duration >= keep &&
+ next->duration >= keep)
+ {
+ cur->duration = next->pts - cur->pts;
+ }
+ }
+ }
+}
+
static void add_sub_list(struct dec_sub *sub, struct packet_list *subs)
{
struct sd *sd = sub_get_last_sd(sub);
@@ -285,6 +322,8 @@ static void add_sub_list(struct dec_sub *sub, struct packet_list *subs)
// there are circumstances which makes this not possible.
bool sub_read_all_packets(struct dec_sub *sub, struct sh_sub *sh)
{
+ struct MPOpts *opts = sub->opts;
+
if (!sub_accept_packets_in_advance(sub) || sh->track)
return false;
@@ -301,6 +340,12 @@ bool sub_read_all_packets(struct dec_sub *sub, struct sh_sub *sh)
MP_TARRAY_APPEND(tmp, subs.packets, subs.num_packets, pkt);
}
+ if (opts->sub_fps && sub->video_fps)
+ multiply_timings(&subs, opts->sub_fps / sub->video_fps);
+
+ if (!opts->suboverlap_enabled)
+ fix_overlaps_and_gaps(&subs);
+
add_sub_list(sub, &subs);
talloc_free(tmp);