From b47bf06f9734c6a7c0a6b95721a9e3200d0f6bbb Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 29 Dec 2015 01:35:52 +0100 Subject: sub: change how subtitles are read Slightly change how it is decided when a new packet should be read. Switch to demux_read_packet_async(), and let the player "wait properly" until required subtitle packets arrive, instead of blocking everything. Move distinguishing the cases of passive and active reading into the demuxer, where it belongs. --- player/core.h | 2 +- player/playloop.c | 3 ++- player/sub.c | 70 +++++++++++++------------------------------------------ player/video.c | 6 ++++- 4 files changed, 24 insertions(+), 57 deletions(-) (limited to 'player') diff --git a/player/core.h b/player/core.h index 6228732bd9..fe87658d81 100644 --- a/player/core.h +++ b/player/core.h @@ -515,7 +515,7 @@ void reinit_subs(struct MPContext *mpctx, int order); void uninit_sub(struct MPContext *mpctx, int order); void uninit_sub_all(struct MPContext *mpctx); void update_osd_msg(struct MPContext *mpctx); -void update_subtitles(struct MPContext *mpctx); +bool update_subtitles(struct MPContext *mpctx, double video_pts); // video.c void reset_video_state(struct MPContext *mpctx); diff --git a/player/playloop.c b/player/playloop.c index 892baf1a09..c81f720122 100644 --- a/player/playloop.c +++ b/player/playloop.c @@ -1036,7 +1036,8 @@ void run_playloop(struct MPContext *mpctx) handle_dummy_ticks(mpctx); update_osd_msg(mpctx); - update_subtitles(mpctx); + if (!mpctx->video_out) + update_subtitles(mpctx, mpctx->playback_pts); handle_segment_switch(mpctx, end_is_new_segment); diff --git a/player/sub.c b/player/sub.c index 42f602f754..dd1ba6d384 100644 --- a/player/sub.c +++ b/player/sub.c @@ -68,32 +68,14 @@ void uninit_sub_all(struct MPContext *mpctx) uninit_sub(mpctx, 1); } -// When reading subtitles from a demuxer, and we read video or audio from the -// demuxer, we should not explicitly read subtitle packets. (With external -// subs, we have to.) -static bool is_interleaved(struct MPContext *mpctx, struct track *track) -{ - if (track->is_external || !track->demuxer) - return false; - - struct demuxer *demuxer = track->demuxer; - for (int t = 0; t < mpctx->num_tracks; t++) { - struct track *other = mpctx->tracks[t]; - if (other != track && other->selected && other->demuxer == demuxer && - (other->type == STREAM_VIDEO || other->type == STREAM_AUDIO)) - return true; - } - return track->demuxer == mpctx->demuxer; -} - -static void update_subtitle(struct MPContext *mpctx, int order) +static bool update_subtitle(struct MPContext *mpctx, double video_pts, int order) { struct MPOpts *opts = mpctx->opts; struct track *track = mpctx->current_track[order][STREAM_SUB]; struct dec_sub *dec_sub = mpctx->d_sub[order]; - if (!track || !dec_sub) - return; + if (!track || !dec_sub || video_pts == MP_NOPTS_VALUE) + return true; if (mpctx->d_video) { struct mp_image_params params = mpctx->d_video->vfilter->override_params; @@ -101,46 +83,26 @@ static void update_subtitle(struct MPContext *mpctx, int order) sub_control(dec_sub, SD_CTRL_SET_VIDEO_PARAMS, ¶ms); } - double refpts_s = mpctx->playback_pts; - double curpts_s = refpts_s - opts->sub_delay; - - if (!track->preloaded && track->stream) { - struct sh_stream *sh_stream = track->stream; - bool interleaved = is_interleaved(mpctx, track); - - while (1) { - if (interleaved && !demux_has_packet(sh_stream)) - break; - double subpts_s = demux_get_next_pts(sh_stream); - if (!demux_has_packet(sh_stream)) - break; - if (subpts_s > curpts_s) { - MP_DBG(mpctx, "Sub early: c_pts=%5.3f s_pts=%5.3f\n", - curpts_s, subpts_s); - // Often subs can be handled in advance - if (!sub_accepts_packet_in_advance(dec_sub)) - break; - // Try to avoid demuxing whole file at once - if (subpts_s > curpts_s + 1 && !interleaved) - break; - } - struct demux_packet *pkt = demux_read_packet(sh_stream); - MP_DBG(mpctx, "Sub: c_pts=%5.3f s_pts=%5.3f duration=%5.3f len=%d\n", - curpts_s, pkt->pts, pkt->duration, pkt->len); - sub_decode(dec_sub, pkt); - talloc_free(pkt); - } + video_pts -= opts->sub_delay; + + if (!track->preloaded) { + if (!sub_read_packets(dec_sub, video_pts)) + return false; } // Handle displaying subtitles on terminal; never done for secondary subs if (order == 0 && !mpctx->video_out) - term_osd_set_subs(mpctx, sub_get_text(dec_sub, curpts_s)); + term_osd_set_subs(mpctx, sub_get_text(dec_sub, video_pts)); + + return true; } -void update_subtitles(struct MPContext *mpctx) +// Return true if the subtitles for the given PTS are ready; false if the player +// should wait for new demuxer data, and then should retry. +bool update_subtitles(struct MPContext *mpctx, double video_pts) { - update_subtitle(mpctx, 0); - update_subtitle(mpctx, 1); + return update_subtitle(mpctx, video_pts, 0) & + update_subtitle(mpctx, video_pts, 1); } static bool init_subdec(struct MPContext *mpctx, struct track *track) diff --git a/player/video.c b/player/video.c index 1178557e24..84981b1144 100644 --- a/player/video.c +++ b/player/video.c @@ -1206,6 +1206,11 @@ void write_video(struct MPContext *mpctx, double endpts) mpctx->time_frame -= get_relative_time(mpctx); update_avsync_before_frame(mpctx); + if (!update_subtitles(mpctx, mpctx->next_frames[0]->pts)) { + MP_WARN(mpctx, "subt wait\n"); + return; + } + double time_frame = MPMAX(mpctx->time_frame, -1); int64_t pts = mp_time_us() + (int64_t)(time_frame * 1e6); @@ -1262,7 +1267,6 @@ void write_video(struct MPContext *mpctx, double endpts) mpctx->osd_force_update = true; update_osd_msg(mpctx); - update_subtitles(mpctx); vo_queue_frame(vo, frame); -- cgit v1.2.3