mirror of https://github.com/mpv-player/mpv
player: show subtitles on VO if --force-window is used
If a VO is created, but no video is playing (i.e. --force-window is used), then until now no subtitles were shown. This is because VO subtitle display normally depends on video frame timing. If there are no video frames, there can be no subtitles. Change this and add some code to handle this situation specifically. Set a subtitle PTS manually and request VO redrawing manually, which gets the subtitles rendered somehow. This is kind of shaky. The subtitles are essentially sampled at arbitrary times (such as when new audio data is decoded and pushed to the AO, or on user interaction). To make a it slightly more consistent, force a completely arbitrary minimum FPS of 10. Other solutions (such as creating fake video) would be more intrusive or would require VO-level API changes. Fixes #3684.
This commit is contained in:
parent
fc4318d23e
commit
90b968a67a
|
@ -1095,7 +1095,7 @@ void run_playloop(struct MPContext *mpctx)
|
|||
handle_dummy_ticks(mpctx);
|
||||
|
||||
update_osd_msg(mpctx);
|
||||
if (!mpctx->video_out)
|
||||
if (!mpctx->vo_chain)
|
||||
update_subtitles(mpctx, mpctx->playback_pts);
|
||||
|
||||
handle_eof(mpctx);
|
||||
|
|
13
player/sub.c
13
player/sub.c
|
@ -112,6 +112,19 @@ static bool update_subtitle(struct MPContext *mpctx, double video_pts,
|
|||
if (mpctx->current_track[0][STREAM_SUB] == track && !mpctx->video_out)
|
||||
term_osd_set_subs(mpctx, sub_get_text(dec_sub, video_pts));
|
||||
|
||||
// Handle displaying subtitles on VO with no video being played. This is
|
||||
// quite differently, because normally subtitles are redrawn on new video
|
||||
// frames, using the video frames' timestamps.
|
||||
if (mpctx->video_out && !mpctx->vo_chain) {
|
||||
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);
|
||||
vo_redraw(mpctx->video_out);
|
||||
}
|
||||
// Force an arbitrary minimum FPS
|
||||
mp_set_timeout(mpctx, 0.1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -482,6 +482,9 @@ int reinit_video_chain_src(struct MPContext *mpctx, struct lavfi_pad *src)
|
|||
|
||||
update_window_title(mpctx, true);
|
||||
|
||||
// Undo what the subtitle path does if mpctx->vo_chain is unset.
|
||||
osd_set_force_video_pts(mpctx->osd, MP_NOPTS_VALUE);
|
||||
|
||||
struct vo_chain *vo_c = talloc_zero(NULL, struct vo_chain);
|
||||
mpctx->vo_chain = vo_c;
|
||||
vo_c->log = mpctx->log;
|
||||
|
|
19
sub/osd.c
19
sub/osd.c
|
@ -119,6 +119,7 @@ struct osd_state *osd_create(struct mpv_global *global)
|
|||
.opts = global->opts,
|
||||
.global = global,
|
||||
.log = mp_log_new(osd, global->log, "osd"),
|
||||
.force_video_pts = MP_NOPTS_VALUE,
|
||||
};
|
||||
pthread_mutex_init(&osd->lock, NULL);
|
||||
|
||||
|
@ -190,6 +191,21 @@ void osd_set_render_subs_in_filter(struct osd_state *osd, bool s)
|
|||
pthread_mutex_unlock(&osd->lock);
|
||||
}
|
||||
|
||||
void osd_set_force_video_pts(struct osd_state *osd, double video_pts)
|
||||
{
|
||||
pthread_mutex_lock(&osd->lock);
|
||||
osd->force_video_pts = video_pts;
|
||||
pthread_mutex_unlock(&osd->lock);
|
||||
}
|
||||
|
||||
double osd_get_force_video_pts(struct osd_state *osd)
|
||||
{
|
||||
pthread_mutex_lock(&osd->lock);
|
||||
double pts = osd->force_video_pts;
|
||||
pthread_mutex_unlock(&osd->lock);
|
||||
return pts;
|
||||
}
|
||||
|
||||
void osd_set_progbar(struct osd_state *osd, struct osd_progbar_state *s)
|
||||
{
|
||||
pthread_mutex_lock(&osd->lock);
|
||||
|
@ -288,6 +304,9 @@ void osd_draw(struct osd_state *osd, struct mp_osd_res res,
|
|||
{
|
||||
pthread_mutex_lock(&osd->lock);
|
||||
|
||||
if (osd->force_video_pts != MP_NOPTS_VALUE)
|
||||
video_pts = osd->force_video_pts;
|
||||
|
||||
if (draw_flags & OSD_DRAW_SUB_FILTER)
|
||||
draw_flags |= OSD_DRAW_SUB_ONLY;
|
||||
|
||||
|
|
|
@ -155,6 +155,8 @@ void osd_set_sub(struct osd_state *osd, int index, struct dec_sub *dec_sub);
|
|||
|
||||
bool osd_get_render_subs_in_filter(struct osd_state *osd);
|
||||
void osd_set_render_subs_in_filter(struct osd_state *osd, bool s);
|
||||
void osd_set_force_video_pts(struct osd_state *osd, double video_pts);
|
||||
double osd_get_force_video_pts(struct osd_state *osd);
|
||||
|
||||
struct osd_progbar_state {
|
||||
int type; // <0: disabled, 1-255: symbol, else: no symbol
|
||||
|
|
|
@ -67,6 +67,7 @@ struct osd_state {
|
|||
struct osd_object *objs[MAX_OSD_PARTS];
|
||||
|
||||
bool render_subs_in_filter;
|
||||
double force_video_pts;
|
||||
|
||||
bool want_redraw;
|
||||
bool want_redraw_notification;
|
||||
|
|
Loading…
Reference in New Issue