[PATCH] sub: add -sub-extend-* options.
These options extend the duration of subtitles without causing overlapping. They can add a little comfort to people who are slow readers, although the effect is limited in fast dialog scenes since the room for extending is small. --- DOCS/man/en/mplayer.1 | 14 ++++++++++++++ cfg-common.h | 2 ++ mencoder.c | 2 ++ mpcommon.h | 2 ++ mplayer.c | 2 ++ sub/ass_mp.c | 26 ++++++++++++++++++++++++++ sub/subreader.c | 27 +++++++++++++++++++++++---- 7 files changed, 71 insertions(+), 4 deletions(-) diff --git a/DOCS/man/en/mplayer.1 b/DOCS/man/en/mplayer.1 index 2b90878..cfba9d1 100644 --- a/DOCS/man/en/mplayer.1 +++ b/DOCS/man/en/mplayer.1 @@ -2869,6 +2869,20 @@ Delays subtitles by <sec> seconds. Can be negative. . .TP +.B \-sub\-extend\-after <sec> +Extend subtitles by delaying their disappearance by at most <sec> seconds. +It does not cause overlap if the next subtitle is less than <sec> away +and does not apply to already overlapping subtitles. +It does not work with subtitles embedded in the stream nor with bitmap +subtitles. +. +.TP +.B \-sub\-extend\-before <sec> +Extend subtitles by making them appear by at most <sec> seconds early. +See \-sub\-extend\-after for details. +If both options are specified, \-sub\-extend\-after has precedence. +. +.TP .B \-subfile <filename> (BETA CODE) Currently useless. Same as \-audiofile, but for subtitle streams (OggDS?). diff --git a/cfg-common.h b/cfg-common.h index 58748ff..e498a95 100644 --- a/cfg-common.h +++ b/cfg-common.h @@ -572,6 +572,8 @@ const m_option_t common_opts[] = { #endif {"subdelay", &sub_delay, CONF_TYPE_FLOAT, 0, 0.0, 10.0, NULL}, {"subfps", &sub_fps, CONF_TYPE_FLOAT, 0, 0.0, 10.0, NULL}, + {"sub-extend-after", &sub_extend_after, CONF_TYPE_FLOAT, 0, 0.0, 10.0, NULL}, + {"sub-extend-before", &sub_extend_before, CONF_TYPE_FLOAT, 0, 0.0, 10.0, NULL}, {"autosub", &sub_auto, CONF_TYPE_FLAG, 0, 0, 1, NULL}, {"noautosub", &sub_auto, CONF_TYPE_FLAG, 0, 1, 0, NULL}, {"unicode", &sub_unicode, CONF_TYPE_FLAG, 0, 0, 1, NULL}, diff --git a/mencoder.c b/mencoder.c index 1c34457..2548028 100644 --- a/mencoder.c +++ b/mencoder.c @@ -180,6 +180,8 @@ char **sub_name=NULL; char **sub_paths = NULL; float sub_delay=0; float sub_fps=0; +float sub_extend_after = 0; +float sub_extend_before = 0; int sub_auto = 0; char *vobsub_name = NULL; int subcc_enabled=0; diff --git a/mpcommon.h b/mpcommon.h index 8a7a334..38ee871 100644 --- a/mpcommon.h +++ b/mpcommon.h @@ -41,6 +41,8 @@ extern int forced_subs_only; extern int sub_auto; extern float sub_delay; extern float sub_fps; +extern float sub_extend_after; +extern float sub_extend_before; extern char **sub_name; extern char **sub_paths; extern char *font_name; diff --git a/mplayer.c b/mplayer.c index 527bc40..40d8bda 100644 --- a/mplayer.c +++ b/mplayer.c @@ -282,6 +282,8 @@ char **sub_name; char **sub_paths; float sub_delay; float sub_fps; +float sub_extend_after = 0; +float sub_extend_before = 0; int sub_auto = 1; char *vobsub_name; int subcc_enabled; diff --git a/sub/ass_mp.c b/sub/ass_mp.c index 60f464f..eed118b 100644 --- a/sub/ass_mp.c +++ b/sub/ass_mp.c @@ -212,6 +212,31 @@ ASS_Track* ass_read_subdata(ASS_Library* library, sub_data* subdata, double fps) return track; } +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + +static void ass_extend_subs_time(ASS_Track *track) +{ + ASS_Event *ev = track->events; + long long ext_after = sub_extend_after * 1000; + long long ext_before = sub_extend_before * 1000; + long long start, end, bound; + int i; + + for (i = 0; i < track->n_events; i++) { + start = ev[i].Start; + end = start + ev[i].Duration; + bound = i < track->n_events + 1 ? ev[i + 1].Start : LLONG_MAX; + if (end < bound) + end = MIN(bound, end + ext_after); + bound = i > 0 ? ev[i - 1].Start + ev[i - 1].Duration : LLONG_MIN; + if (start > bound) + start = MAX(bound, start - ext_before); + ev[i].Start = start; + ev[i].Duration = end - start; + } +} + ASS_Track* ass_read_stream(ASS_Library* library, const char *fname, char *charset) { char *buf = NULL; ASS_Track *track; @@ -254,6 +279,7 @@ ASS_Track* ass_read_stream(ASS_Library* library, const char *fname, char *charse track->name = strdup(fname); } free(buf); + ass_extend_subs_time(track); return track; } diff --git a/sub/subreader.c b/sub/subreader.c index ecc5ff5..15afa87 100644 --- a/sub/subreader.c +++ b/sub/subreader.c @@ -1352,13 +1352,31 @@ static int sub_fribidi (subtitle *sub, int av_unused sub_utf8, int av_unused fro return 1; } -static void adjust_subs_time(subtitle* sub, float subtime, float fps, int block, +static void extend_subs_time(subtitle *sub, int nb_sub, double one_second) +{ + unsigned long ext_after = sub_extend_after * one_second; + unsigned long ext_before = sub_extend_before * one_second; + unsigned long bound; + int i; + + for (i = 0; i < nb_sub; i++) { + bound = i < nb_sub + 1 ? sub[i + 1].start : ULONG_MAX; + if (sub[i].end < bound) + sub[i].end = FFMIN(bound, sub[i].end + ext_after); + bound = i > 0 ? sub[i - 1].end : 0; + if (sub[i].start > bound) + sub[i].start = FFMAX(bound, FFMAX(sub[i].start, ext_before) - ext_before); + } +} + +static void adjust_subs_time(subtitle *firstsub, float subtime, float fps, int block, int sub_num, int sub_uses_time) { int n,m; - subtitle* nextsub; + subtitle *sub = firstsub, *nextsub; int i = sub_num; - unsigned long subfms = (sub_uses_time ? 100 : fps) * subtime; - unsigned long overlap = (sub_uses_time ? 100 : fps) / 5; // 0.2s + double one_second = sub_uses_time ? 100 : fps; + unsigned long subfms = one_second * subtime; + unsigned long overlap = one_second / 5; // 0.2s n=m=0; if (i) for (;;){ @@ -1409,6 +1427,7 @@ static void adjust_subs_time(subtitle* sub, float subtime, float fps, int block, m = 0; } if (n) mp_msg(MSGT_SUBREADER,MSGL_V,"SUB: Adjusted %d subtitle(s).\n", n); + extend_subs_time(firstsub, sub_num, one_second); } struct subreader { -- 2.5.0
participants (1)
-
Nicolas George