sub: by default, don't render timestamps after video EOF

This fixes a long-standing apparent issue where mpv would display the last
frame with no subtitles at EOF. This is caused by sub rendering switching from
video timestamps to audio timestamps when the video ends, and audio streams
often running past the timestamp of the last video frame. However, authoring
tools (most notably Aegisub) don't tend to provide easy ways to add meaningful
subtitles after the end of the video, so this is rarely actually useful.
This commit is contained in:
rcombs 2020-12-23 00:40:32 -06:00 committed by Leo Izen
parent cb56c2f888
commit 11423acf30
4 changed files with 11 additions and 1 deletions

View File

@ -2597,6 +2597,13 @@ Subtitles
This works for ``dvb_teletext`` subtitle streams, and if FFmpeg has been
compiled with support for it.
``--sub-past-video-end``
After the last frame of video, if this option is enabled, subtitles will
continue to update based on audio timestamps. Otherwise, the subtitles
for the last video frame will stay onscreen.
Default: disabled
``--sub-font=<name>``
Specify font to use for subtitles that do not themselves
specify a particular font. The default is ``sans-serif``.

View File

@ -275,6 +275,7 @@ const struct m_sub_options mp_subtitle_sub_opts = {
{"sub", OPT_SUBSTRUCT(sub_style, sub_style_conf)},
{"sub-clear-on-seek", OPT_FLAG(sub_clear_on_seek)},
{"teletext-page", OPT_INT(teletext_page), M_RANGE(1, 999)},
{"sub-past-video-end", OPT_FLAG(sub_past_video_end)},
{0}
},
.size = sizeof(OPT_BASE_STRUCT),

View File

@ -107,6 +107,7 @@ struct mp_subtitle_opts {
int ass_justify;
int sub_clear_on_seek;
int teletext_page;
int sub_past_video_end;
};
struct mp_sub_filter_opts {

View File

@ -114,7 +114,8 @@ static bool update_subtitle(struct MPContext *mpctx, double video_pts,
// Handle displaying subtitles on VO with no video being played. This is
// quite different, because normally subtitles are redrawn on new video
// frames, using the video frames' timestamps.
if (mpctx->video_out && mpctx->video_status == STATUS_EOF) {
if (mpctx->video_out && mpctx->video_status == STATUS_EOF &&
mpctx->opts->subs_rend->sub_past_video_end) {
if (osd_get_force_video_pts(mpctx->osd) != video_pts) {
osd_set_force_video_pts(mpctx->osd, video_pts);
osd_query_and_reset_want_redraw(mpctx->osd);