diff options
author | wm4 <wm4@nowhere> | 2013-06-11 21:41:50 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2013-06-23 22:33:59 +0200 |
commit | 64b1374a4456435cc4486a8153703fa89af58e31 (patch) | |
tree | de0a0d9a04431856544ef1dc47398ca75f0ad383 /sub/dec_sub.c | |
parent | a70d575291d48289669ee8989e0597a94189dd8d (diff) | |
download | mpv-64b1374a4456435cc4486a8153703fa89af58e31.tar.bz2 mpv-64b1374a4456435cc4486a8153703fa89af58e31.tar.xz |
sub: do some timing postprocessing on preloaded subs
This fixes the -subfps option (which unfortunately is still useful),
and fixes minor annoying timing errors (which unfortunately still
happen).
Note that none of these affect ASS or image subtitles. ASS is specially
handled: libass loads subtitles as ASS_Track. There are no actual
packets passed around, and sd_ass just uses the ASS_Track.
Disable the --sub-no-text-pp option. It's misleading now and always was
completely useless.
Diffstat (limited to 'sub/dec_sub.c')
-rw-r--r-- | sub/dec_sub.c | 45 |
1 files changed, 45 insertions, 0 deletions
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); |