From 639e672bd153e06cfc01ced6c2a48b45870e8f31 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 23 Nov 2013 21:37:15 +0100 Subject: player: rearrange how subtitle context and stream headers are used Use sh_stream over sh_sub. Use dec_sub (and mpctx->d_sub) instead of the stream header. This aligns the subtitle code with the recent audio and video refactoring. sh_sub still has the decoder context, though. This is because we want to avoid reinit when switching segments with ordered chapters. (Reinit is fast, except for creating the ASS_Renderer, which in turn triggers fontconfig.) Not sure how much this matters, though, because the initial segment switch will lazily initialize the decoder anyway. --- mpvcore/player/loadfile.c | 27 ++++++++++--------------- mpvcore/player/mp_core.h | 2 +- mpvcore/player/sub.c | 50 +++++++++++++++++++++++++++-------------------- 3 files changed, 40 insertions(+), 39 deletions(-) (limited to 'mpvcore') diff --git a/mpvcore/player/loadfile.c b/mpvcore/player/loadfile.c index 51d3f2ec7e..33ee770b08 100644 --- a/mpvcore/player/loadfile.c +++ b/mpvcore/player/loadfile.c @@ -80,9 +80,10 @@ void uninit_player(struct MPContext *mpctx, unsigned int mask) if (mask & INITIALIZED_SUB) { mpctx->initialized_flags &= ~INITIALIZED_SUB; - if (mpctx->sh_sub) - sub_reset(mpctx->sh_sub->dec_sub); + if (mpctx->d_sub) + sub_reset(mpctx->d_sub); cleanup_demux_stream(mpctx, STREAM_SUB); + mpctx->d_sub = NULL; // Note: not free'd. mpctx->osd->dec_sub = NULL; reset_subtitles(mpctx); } @@ -108,13 +109,15 @@ void uninit_player(struct MPContext *mpctx, unsigned int mask) if (mask & INITIALIZED_DEMUXER) { mpctx->initialized_flags &= ~INITIALIZED_DEMUXER; + assert(!(mpctx->initialized_flags & + (INITIALIZED_VCODEC | INITIALIZED_ACODEC | INITIALIZED_SUB))); for (int i = 0; i < mpctx->num_tracks; i++) { talloc_free(mpctx->tracks[i]); } mpctx->num_tracks = 0; for (int t = 0; t < STREAM_TYPE_COUNT; t++) mpctx->current_track[t] = NULL; - assert(!mpctx->d_video && !mpctx->d_audio && !mpctx->sh_sub); + assert(!mpctx->d_video && !mpctx->d_audio && !mpctx->d_sub); mpctx->master_demuxer = NULL; for (int i = 0; i < mpctx->num_sources; i++) { uninit_subs(mpctx->sources[i]); @@ -264,22 +267,12 @@ static void print_file_properties(struct MPContext *mpctx) } } -static void set_demux_field(struct MPContext *mpctx, enum stream_type type, - struct sh_stream *s) -{ - mpctx->sh[type] = s; - // redundant fields for convenience access - switch(type) { - case STREAM_SUB: mpctx->sh_sub = s ? s->sub : NULL; break; - } -} - struct sh_stream *init_demux_stream(struct MPContext *mpctx, enum stream_type type) { struct track *track = mpctx->current_track[type]; - set_demux_field(mpctx, type, track ? track->stream : NULL); - struct sh_stream *stream = mpctx->sh[type]; + struct sh_stream *stream = track ? track->stream : NULL; + mpctx->sh[type] = stream; if (stream) { demuxer_switch_track(stream->demuxer, type, stream); if (track->is_external) { @@ -295,7 +288,7 @@ void cleanup_demux_stream(struct MPContext *mpctx, enum stream_type type) struct sh_stream *stream = mpctx->sh[type]; if (stream) demuxer_switch_track(stream->demuxer, type, NULL); - set_demux_field(mpctx, type, NULL); + mpctx->sh[type] = NULL; } // Switch the demuxers to current track selection. This is possibly important @@ -1051,7 +1044,7 @@ static void play_current_file(struct MPContext *mpctx) assert(mpctx->demuxer == NULL); assert(mpctx->d_audio == NULL); assert(mpctx->d_video == NULL); - assert(mpctx->sh_sub == NULL); + assert(mpctx->d_sub == NULL); char *stream_filename = mpctx->filename; mpctx->resolve_result = resolve_url(stream_filename, opts); diff --git a/mpvcore/player/mp_core.h b/mpvcore/player/mp_core.h index f372c4e137..0be7e1df1f 100644 --- a/mpvcore/player/mp_core.h +++ b/mpvcore/player/mp_core.h @@ -199,10 +199,10 @@ typedef struct MPContext { struct track *current_track[STREAM_TYPE_COUNT]; struct sh_stream *sh[STREAM_TYPE_COUNT]; - struct sh_sub *sh_sub; // same as sh[STREAM_SUB]->sub struct dec_video *d_video; struct dec_audio *d_audio; + struct dec_sub *d_sub; // Uses: accessing metadata (consider ordered chapters case, where the main // demuxer defines metadata), or special purpose demuxers like TV. diff --git a/mpvcore/player/sub.c b/mpvcore/player/sub.c index d659e74851..bdcb9def09 100644 --- a/mpvcore/player/sub.c +++ b/mpvcore/player/sub.c @@ -67,8 +67,8 @@ static bool is_interleaved(struct MPContext *mpctx, struct track *track) void reset_subtitles(struct MPContext *mpctx) { - if (mpctx->sh_sub) - sub_reset(mpctx->sh_sub->dec_sub); + if (mpctx->d_sub) + sub_reset(mpctx->d_sub); set_osd_subtitle(mpctx, NULL); osd_changed(mpctx->osd, OSDTYPE_SUB); } @@ -80,9 +80,8 @@ void update_subtitles(struct MPContext *mpctx) return; struct track *track = mpctx->current_track[STREAM_SUB]; - struct sh_sub *sh_sub = mpctx->sh_sub; - assert(track && sh_sub); - struct dec_sub *dec_sub = sh_sub->dec_sub; + struct dec_sub *dec_sub = mpctx->d_sub; + assert(track && dec_sub); if (mpctx->d_video && mpctx->d_video->vf_input) { struct mp_image_params params = *mpctx->d_video->vf_input; @@ -94,14 +93,17 @@ void update_subtitles(struct MPContext *mpctx) double refpts_s = mpctx->playback_pts - mpctx->osd->video_offset; double curpts_s = refpts_s + opts->sub_delay; - if (!track->preloaded) { + if (!track->preloaded && track->stream) { + struct sh_stream *sh_stream = track->stream; bool interleaved = is_interleaved(mpctx, track); + assert(sh_stream->sub->dec_sub == dec_sub); + while (1) { - if (interleaved && !demux_has_packet(sh_sub->gsh)) + if (interleaved && !demux_has_packet(sh_stream)) break; - double subpts_s = demux_get_next_pts(sh_sub->gsh); - if (!demux_has_packet(sh_sub->gsh)) + double subpts_s = demux_get_next_pts(sh_stream); + if (!demux_has_packet(sh_stream)) break; if (subpts_s > curpts_s) { mp_dbg(MSGT_CPLAYER, MSGL_DBG2, @@ -114,7 +116,7 @@ void update_subtitles(struct MPContext *mpctx) if (subpts_s > curpts_s + 1 && !interleaved) break; } - struct demux_packet *pkt = demux_read_packet(sh_sub->gsh); + struct demux_packet *pkt = demux_read_packet(sh_stream); mp_dbg(MSGT_CPLAYER, MSGL_V, "Sub: c_pts=%5.3f s_pts=%5.3f " "duration=%5.3f len=%d\n", curpts_s, pkt->pts, pkt->duration, pkt->len); @@ -177,21 +179,27 @@ void reinit_subs(struct MPContext *mpctx) assert(!(mpctx->initialized_flags & INITIALIZED_SUB)); init_demux_stream(mpctx, STREAM_SUB); - if (!mpctx->sh_sub) + struct sh_stream *sh = mpctx->sh[STREAM_SUB]; + + // No track selected, or lazily added DVD track (will actually be created + // on first sub packet) + if (!sh) return; - if (!mpctx->sh_sub->dec_sub) - mpctx->sh_sub->dec_sub = sub_create(opts); + if (!sh->sub->dec_sub) { + assert(!mpctx->d_sub); + sh->sub->dec_sub = sub_create(opts); + } - assert(track->demuxer); - // Lazily added DVD track - will be created on first sub packet - if (!track->stream) - return; + assert(!mpctx->d_sub || sh->sub->dec_sub == mpctx->d_sub); + + // The decoder is kept in the stream header in order to make ordered + // chapters work well. + mpctx->d_sub = sh->sub->dec_sub; mpctx->initialized_flags |= INITIALIZED_SUB; - struct sh_sub *sh_sub = mpctx->sh_sub; - struct dec_sub *dec_sub = sh_sub->dec_sub; + struct dec_sub *dec_sub = mpctx->d_sub; assert(dec_sub); if (!sub_is_initialized(dec_sub)) { @@ -206,14 +214,14 @@ void reinit_subs(struct MPContext *mpctx) sub_set_video_fps(dec_sub, fps); sub_set_ass_renderer(dec_sub, mpctx->osd->ass_library, mpctx->osd->ass_renderer); - sub_init_from_sh(dec_sub, sh_sub); + sub_init_from_sh(dec_sub, sh); // Don't do this if the file has video/audio streams. Don't do it even // if it has only sub streams, because reading packets will change the // demuxer position. if (!track->preloaded && track->is_external) { demux_seek(track->demuxer, 0, SEEK_ABSOLUTE); - track->preloaded = sub_read_all_packets(dec_sub, sh_sub); + track->preloaded = sub_read_all_packets(dec_sub, sh); } } -- cgit v1.2.3