From 9d5d031b6d23402a465618892a40b7af6d4e3c28 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 3 Oct 2014 19:57:49 +0200 Subject: player: remove central uninit_player() function and flags mess Each subsystem (or similar thing) had an INITIALIZED_ flag assigned. The main use of this was that you could pass a bitmask of these flags to uninit_player(). Except in some situations where you wanted to uninitialize nearly everything, this wasn't really useful. Moreover, it was quite annoying that subsystems had most of the code in a specific file, but the uninit code in loadfile.c (because that's where uninit_player() was implemented). Simplify all this. Remove the flags; e.g. instead of testing for the INITIALIZED_AO flag, test whether mpctx->ao is set. Move uninit code to separate functions, e.g. uninit_audio_out(). --- player/audio.c | 49 ++++++++---- player/command.c | 4 +- player/core.h | 24 +++--- player/loadfile.c | 229 +++++++++++++++++++----------------------------------- player/main.c | 5 +- player/osd.c | 3 +- player/playloop.c | 14 ++-- player/sub.c | 51 ++++++------ player/video.c | 32 +++++--- 9 files changed, 184 insertions(+), 227 deletions(-) (limited to 'player') diff --git a/player/audio.c b/player/audio.c index 69510ae205..e8fa4f3592 100644 --- a/player/audio.c +++ b/player/audio.c @@ -142,21 +142,45 @@ void reset_audio_state(struct MPContext *mpctx) mpctx->audio_status = mpctx->d_audio ? STATUS_SYNCING : STATUS_EOF; } +void uninit_audio_out(struct MPContext *mpctx) +{ + if (mpctx->ao) { + // Note: with gapless_audio, stop_play is not correctly set + if (mpctx->opts->gapless_audio || mpctx->stop_play == AT_END_OF_FILE) + ao_drain(mpctx->ao); + ao_uninit(mpctx->ao); + } + mpctx->ao = NULL; + talloc_free(mpctx->ao_decoder_fmt); + mpctx->ao_decoder_fmt = NULL; +} + +void uninit_audio_chain(struct MPContext *mpctx) +{ + if (mpctx->d_audio) { + mixer_uninit_audio(mpctx->mixer); + audio_uninit(mpctx->d_audio); + mpctx->d_audio = NULL; + talloc_free(mpctx->ao_buffer); + mpctx->ao_buffer = NULL; + mpctx->audio_status = STATUS_EOF; + reselect_demux_streams(mpctx); + } +} + void reinit_audio_chain(struct MPContext *mpctx) { struct MPOpts *opts = mpctx->opts; struct track *track = mpctx->current_track[0][STREAM_AUDIO]; struct sh_stream *sh = track ? track->stream : NULL; if (!sh) { - uninit_player(mpctx, INITIALIZED_AO); + uninit_audio_out(mpctx); goto no_audio; } mp_notify(mpctx, MPV_EVENT_AUDIO_RECONFIG, NULL); - if (!(mpctx->initialized_flags & INITIALIZED_ACODEC)) { - mpctx->initialized_flags |= INITIALIZED_ACODEC; - assert(!mpctx->d_audio); + if (!mpctx->d_audio) { mpctx->d_audio = talloc_zero(NULL, struct dec_audio); mpctx->d_audio->log = mp_log_new(mpctx->d_audio, mpctx->log, "!ad"); mpctx->d_audio->global = mpctx->global; @@ -188,16 +212,15 @@ void reinit_audio_chain(struct MPContext *mpctx) } // Weak gapless audio: drain AO on decoder format changes - if (mpctx->ao_decoder_fmt && (mpctx->initialized_flags & INITIALIZED_AO) && - !mp_audio_config_equals(mpctx->ao_decoder_fmt, &in_format) && - opts->gapless_audio < 0) + if (mpctx->ao_decoder_fmt && mpctx->ao && opts->gapless_audio < 0 && + !mp_audio_config_equals(mpctx->ao_decoder_fmt, &in_format)) { - uninit_player(mpctx, INITIALIZED_AO); + uninit_audio_out(mpctx); } struct af_stream *afs = mpctx->d_audio->afilter; - if (mpctx->initialized_flags & INITIALIZED_AO) { + if (mpctx->ao) { ao_get_format(mpctx->ao, &afs->output); } else { afs->output = (struct mp_audio){0}; @@ -219,8 +242,7 @@ void reinit_audio_chain(struct MPContext *mpctx) goto init_error; } - if (!(mpctx->initialized_flags & INITIALIZED_AO)) { - mpctx->initialized_flags |= INITIALIZED_AO; + if (!mpctx->ao) { afs->initialized = 0; // do it again mp_chmap_remove_useless_channels(&afs->output.channels, @@ -260,7 +282,8 @@ void reinit_audio_chain(struct MPContext *mpctx) return; init_error: - uninit_player(mpctx, INITIALIZED_ACODEC | INITIALIZED_AO); + uninit_audio_chain(mpctx); + uninit_audio_out(mpctx); no_audio: mp_deselect_track(mpctx, track); if (track) @@ -466,7 +489,7 @@ void fill_audio_out_buffers(struct MPContext *mpctx, double endpts) * while displaying video, then doing the output format switch. */ if (mpctx->opts->gapless_audio < 1) - uninit_player(mpctx, INITIALIZED_AO); + uninit_audio_out(mpctx); reinit_audio_chain(mpctx); mpctx->sleeptime = 0; return; // retry on next iteration diff --git a/player/command.c b/player/command.c index 9818385abc..8d4e3170a9 100644 --- a/player/command.c +++ b/player/command.c @@ -1686,10 +1686,10 @@ static int mp_property_hwdec(void *ctx, struct m_property *prop, int new = *(int *)arg; if (current == new) return M_PROPERTY_OK; - if (!(mpctx->initialized_flags & INITIALIZED_VCODEC)) + if (!mpctx->d_video) return M_PROPERTY_ERROR; double last_pts = mpctx->last_vo_pts; - uninit_player(mpctx, INITIALIZED_VCODEC); + uninit_video_chain(mpctx); opts->hwdec_api = new; reinit_video_chain(mpctx); if (last_pts != MP_NOPTS_VALUE) diff --git a/player/core.h b/player/core.h index cff468c0cd..bcd0116bd4 100644 --- a/player/core.h +++ b/player/core.h @@ -29,19 +29,6 @@ // definitions used internally by the core player code -#define INITIALIZED_VO 1 -#define INITIALIZED_AO 2 -#define INITIALIZED_PLAYBACK 16 -#define INITIALIZED_LIBASS 32 -#define INITIALIZED_STREAM 64 -#define INITIALIZED_DEMUXER 512 -#define INITIALIZED_ACODEC 1024 -#define INITIALIZED_VCODEC 2048 -#define INITIALIZED_SUB 4096 -#define INITIALIZED_SUB2 8192 -#define INITIALIZED_ALL 0xFFFF - - enum stop_play_reason { KEEP_PLAYING = 0, // must be 0, numeric values of others do not matter AT_END_OF_FILE, // file has ended, prepare to play next @@ -194,7 +181,7 @@ typedef struct MPContext { char *filename; // always the same as playing->filename (or NULL) struct mp_resolve_result *resolve_result; enum stop_play_reason stop_play; - unsigned int initialized_flags; // which subsystems have been initialized + bool playback_initialized; // playloop can be run/is running // Return code to use with PT_QUIT enum exit_reason quit_player_rc; @@ -368,6 +355,8 @@ void fill_audio_out_buffers(struct MPContext *mpctx, double endpts); double written_audio_pts(struct MPContext *mpctx); void clear_audio_output_buffers(struct MPContext *mpctx); void set_playback_speed(struct MPContext *mpctx, double new_speed); +void uninit_audio_out(struct MPContext *mpctx); +void uninit_audio_chain(struct MPContext *mpctx); // configfiles.c void mp_parse_cfgfiles(struct MPContext *mpctx); @@ -407,6 +396,7 @@ struct playlist_entry *mp_next_file(struct MPContext *mpctx, int direction, void mp_set_playlist_entry(struct MPContext *mpctx, struct playlist_entry *e); void mp_play_files(struct MPContext *mpctx); void update_demuxer_properties(struct MPContext *mpctx); +void reselect_demux_streams(struct MPContext *mpctx); // main.c int mpv_main(int argc, char *argv[]); @@ -473,8 +463,10 @@ void mp_load_scripts(struct MPContext *mpctx); // sub.c void reset_subtitle_state(struct MPContext *mpctx); void reset_subtitles(struct MPContext *mpctx, int order); -void uninit_subs(struct demuxer *demuxer); +void uninit_stream_sub_decoders(struct demuxer *demuxer); 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); @@ -492,5 +484,7 @@ int reinit_video_filters(struct MPContext *mpctx); void write_video(struct MPContext *mpctx, double endpts); void mp_force_video_refresh(struct MPContext *mpctx); void update_fps(struct MPContext *mpctx); +void uninit_video_out(struct MPContext *mpctx); +void uninit_video_chain(struct MPContext *mpctx); #endif /* MPLAYER_MP_CORE_H */ diff --git a/player/loadfile.c b/player/loadfile.c index 23d6a4aeb4..5cd77efc1f 100644 --- a/player/loadfile.c +++ b/player/loadfile.c @@ -60,133 +60,44 @@ #include "command.h" #include "libmpv/client.h" -static void reselect_demux_streams(struct MPContext *mpctx); - -static void uninit_sub(struct MPContext *mpctx, int order) +static void uninit_demuxer(struct MPContext *mpctx) { - mpctx->d_sub[order] = NULL; // Note: not free'd. - int obj = order ? OSDTYPE_SUB2 : OSDTYPE_SUB; - osd_set_sub(mpctx->osd, obj, NULL); - reset_subtitles(mpctx, order); - reselect_demux_streams(mpctx); + assert(!mpctx->d_video && !mpctx->d_audio && + !mpctx->d_sub[0] && !mpctx->d_sub[1]); + for (int i = 0; i < mpctx->num_tracks; i++) { + talloc_free(mpctx->tracks[i]); + } + mpctx->num_tracks = 0; + for (int r = 0; r < NUM_PTRACKS; r++) { + for (int t = 0; t < STREAM_TYPE_COUNT; t++) + mpctx->current_track[r][t] = NULL; + } + mpctx->master_demuxer = NULL; + for (int i = 0; i < mpctx->num_sources; i++) { + uninit_stream_sub_decoders(mpctx->sources[i]); + struct demuxer *demuxer = mpctx->sources[i]; + struct stream *stream = demuxer->stream; + free_demuxer(demuxer); + if (stream != mpctx->stream) + free_stream(stream); + } + talloc_free(mpctx->sources); + mpctx->sources = NULL; + mpctx->demuxer = NULL; + mpctx->num_sources = 0; + talloc_free(mpctx->timeline); + mpctx->timeline = NULL; + mpctx->num_timeline_parts = 0; + talloc_free(mpctx->chapters); + mpctx->chapters = NULL; + mpctx->num_chapters = 0; + mpctx->video_offset = 0; } -void uninit_player(struct MPContext *mpctx, unsigned int mask) +static void uninit_stream(struct MPContext *mpctx) { - struct MPOpts *opts = mpctx->opts; - - mask &= mpctx->initialized_flags; - - MP_DBG(mpctx, "\n*** uninit(0x%X)\n", mask); - - if (mask & INITIALIZED_ACODEC) { - mpctx->initialized_flags &= ~INITIALIZED_ACODEC; - mixer_uninit_audio(mpctx->mixer); - audio_uninit(mpctx->d_audio); - mpctx->d_audio = NULL; - talloc_free(mpctx->ao_buffer); - mpctx->ao_buffer = NULL; - mpctx->audio_status = STATUS_EOF; - reselect_demux_streams(mpctx); - } - - if (mask & INITIALIZED_SUB) { - mpctx->initialized_flags &= ~INITIALIZED_SUB; - uninit_sub(mpctx, 0); - } - if (mask & INITIALIZED_SUB2) { - mpctx->initialized_flags &= ~INITIALIZED_SUB2; - uninit_sub(mpctx, 1); - } - - if (mask & INITIALIZED_LIBASS) { - mpctx->initialized_flags &= ~INITIALIZED_LIBASS; -#if HAVE_LIBASS - if (mpctx->ass_renderer) - ass_renderer_done(mpctx->ass_renderer); - mpctx->ass_renderer = NULL; - ass_clear_fonts(mpctx->ass_library); -#endif - } - - if (mask & INITIALIZED_VCODEC) { - mpctx->initialized_flags &= ~INITIALIZED_VCODEC; - reset_video_state(mpctx); - if (mpctx->d_video) - video_uninit(mpctx->d_video); - mpctx->d_video = NULL; - mpctx->video_status = STATUS_EOF; - mpctx->sync_audio_to_video = false; - reselect_demux_streams(mpctx); - } - - if (mask & INITIALIZED_DEMUXER) { - mpctx->initialized_flags &= ~INITIALIZED_DEMUXER; - assert(!(mpctx->initialized_flags & - (INITIALIZED_VCODEC | INITIALIZED_ACODEC | - INITIALIZED_SUB2 | INITIALIZED_SUB))); - for (int i = 0; i < mpctx->num_tracks; i++) { - talloc_free(mpctx->tracks[i]); - } - mpctx->num_tracks = 0; - for (int r = 0; r < NUM_PTRACKS; r++) { - for (int t = 0; t < STREAM_TYPE_COUNT; t++) - mpctx->current_track[r][t] = NULL; - } - assert(!mpctx->d_video && !mpctx->d_audio && - !mpctx->d_sub[0] && !mpctx->d_sub[1]); - mpctx->master_demuxer = NULL; - for (int i = 0; i < mpctx->num_sources; i++) { - uninit_subs(mpctx->sources[i]); - struct demuxer *demuxer = mpctx->sources[i]; - struct stream *stream = demuxer->stream; - free_demuxer(demuxer); - if (stream != mpctx->stream) - free_stream(stream); - } - talloc_free(mpctx->sources); - mpctx->sources = NULL; - mpctx->demuxer = NULL; - mpctx->num_sources = 0; - talloc_free(mpctx->timeline); - mpctx->timeline = NULL; - mpctx->num_timeline_parts = 0; - talloc_free(mpctx->chapters); - mpctx->chapters = NULL; - mpctx->num_chapters = 0; - mpctx->video_offset = 0; - } - - // kill the cache process: - if (mask & INITIALIZED_STREAM) { - mpctx->initialized_flags &= ~INITIALIZED_STREAM; - if (mpctx->stream) - free_stream(mpctx->stream); - mpctx->stream = NULL; - } - - if (mask & INITIALIZED_VO) { - mpctx->initialized_flags &= ~INITIALIZED_VO; - vo_destroy(mpctx->video_out); - mpctx->video_out = NULL; - } - - if (mask & INITIALIZED_AO) { - struct ao *ao = mpctx->ao; - mpctx->initialized_flags &= ~INITIALIZED_AO; - if (ao) { - // Note: with gapless_audio, stop_play is not correctly set - if (opts->gapless_audio || mpctx->stop_play == AT_END_OF_FILE) - ao_drain(ao); - ao_uninit(ao); - } - mpctx->ao = NULL; - talloc_free(mpctx->ao_decoder_fmt); - mpctx->ao_decoder_fmt = NULL; - } - - if (mask & INITIALIZED_PLAYBACK) - mpctx->initialized_flags &= ~INITIALIZED_PLAYBACK; + free_stream(mpctx->stream); + mpctx->stream = NULL; } #define APPEND(s, ...) mp_snprintf_cat(s, sizeof(s), __VA_ARGS__) @@ -283,7 +194,7 @@ static bool need_init_seek(struct demuxer *demux) // can be important, because reading from a demuxer stream (e.g. during init) // will implicitly discard interleaved packets from unselected streams. // Also initializes position for external streams. -static void reselect_demux_streams(struct MPContext *mpctx) +void reselect_demux_streams(struct MPContext *mpctx) { // Note: we assume that all demuxer streams are covered by the track list. for (int t = 0; t < mpctx->num_tracks; t++) { @@ -345,7 +256,13 @@ bool timeline_set_part(struct MPContext *mpctx, int i, bool force) enum stop_play_reason orig_stop_play = mpctx->stop_play; if (!mpctx->d_video && mpctx->stop_play == KEEP_PLAYING) mpctx->stop_play = AT_END_OF_FILE; // let audio uninit drain data - uninit_player(mpctx, INITIALIZED_VCODEC | (mpctx->opts->fixed_vo ? 0 : INITIALIZED_VO) | (mpctx->opts->gapless_audio ? 0 : INITIALIZED_AO) | INITIALIZED_ACODEC | INITIALIZED_SUB | INITIALIZED_SUB2); + uninit_audio_chain(mpctx); + uninit_video_chain(mpctx); + uninit_sub_all(mpctx); + if (!mpctx->opts->fixed_vo) + uninit_video_out(mpctx); + if (!mpctx->opts->gapless_audio) + uninit_audio_out(mpctx); mpctx->stop_play = orig_stop_play; if (mpctx->demuxer) { @@ -580,19 +497,19 @@ void mp_switch_track_n(struct MPContext *mpctx, int order, enum stream_type type if (order == 0) { if (type == STREAM_VIDEO) { - int uninit = INITIALIZED_VCODEC; - if (!mpctx->opts->force_vo) - uninit |= mpctx->opts->fixed_vo && track ? 0 : INITIALIZED_VO; - uninit_player(mpctx, uninit); + uninit_video_chain(mpctx); + if (!mpctx->opts->fixed_vo || !track) + handle_force_window(mpctx, false); } else if (type == STREAM_AUDIO) { clear_audio_output_buffers(mpctx); - uninit_player(mpctx, INITIALIZED_AO | INITIALIZED_ACODEC); + uninit_audio_chain(mpctx); + uninit_audio_out(mpctx); } else if (type == STREAM_SUB) { - uninit_player(mpctx, INITIALIZED_SUB); + uninit_sub(mpctx, 0); } } else if (order == 1) { if (type == STREAM_SUB) - uninit_player(mpctx, INITIALIZED_SUB2); + uninit_sub(mpctx, 1); } if (current) @@ -870,18 +787,26 @@ static void add_subtitle_fonts_from_sources(struct MPContext *mpctx) #endif } +static void uninit_libass(struct MPContext *mpctx) +{ +#if HAVE_LIBASS + if (mpctx->ass_renderer) + ass_renderer_done(mpctx->ass_renderer); + mpctx->ass_renderer = NULL; + ass_clear_fonts(mpctx->ass_library); +#endif +} + static void init_sub_renderer(struct MPContext *mpctx) { #if HAVE_LIBASS - assert(!(mpctx->initialized_flags & INITIALIZED_LIBASS)); - assert(!mpctx->ass_renderer); + uninit_libass(mpctx); mpctx->ass_renderer = ass_renderer_init(mpctx->ass_library); if (mpctx->ass_renderer) { mp_ass_configure_fonts(mpctx->ass_renderer, mpctx->opts->sub_text_style, mpctx->global, mpctx->ass_log); } - mpctx->initialized_flags |= INITIALIZED_LIBASS; #endif } @@ -1093,7 +1018,6 @@ static void play_current_file(struct MPContext *mpctx) mp_process_input(mpctx); goto terminate_playback; } - mpctx->initialized_flags |= INITIALIZED_STREAM; if (opts->stream_dump && opts->stream_dump[0]) { stream_dump(mpctx); @@ -1127,8 +1051,6 @@ goto_reopen_demuxer: ; MP_TARRAY_APPEND(NULL, mpctx->sources, mpctx->num_sources, mpctx->demuxer); - mpctx->initialized_flags |= INITIALIZED_DEMUXER; - if (mpctx->demuxer->playlist) { int entry_stream_flags = (mpctx->demuxer->stream->safe_origin ? 0 : STREAM_SAFE_ONLY) | @@ -1276,7 +1198,7 @@ goto_reopen_demuxer: ; if (mpctx->opts->pause) pause_player(mpctx); - mpctx->initialized_flags |= INITIALIZED_PLAYBACK; + mpctx->playback_initialized = true; mp_notify(mpctx, MPV_EVENT_FILE_LOADED, NULL); playback_start = mp_time_sec(); @@ -1288,9 +1210,11 @@ goto_reopen_demuxer: ; if (mpctx->stop_play == PT_RELOAD_DEMUXER) { mpctx->stop_play = KEEP_PLAYING; - uninit_player(mpctx, INITIALIZED_ALL - - (INITIALIZED_PLAYBACK | INITIALIZED_STREAM | - (opts->fixed_vo ? INITIALIZED_VO : 0))); + mpctx->playback_initialized = false; + uninit_audio_chain(mpctx); + uninit_video_chain(mpctx); + uninit_sub_all(mpctx); + uninit_demuxer(mpctx); goto goto_reopen_demuxer; } @@ -1315,15 +1239,18 @@ terminate_playback: MP_INFO(mpctx, "\n"); // time to uninit all, except global stuff: - int uninitialize_parts = INITIALIZED_ALL; - if (opts->fixed_vo) - uninitialize_parts -= INITIALIZED_VO; - if ((opts->gapless_audio && mpctx->stop_play == AT_END_OF_FILE) || - mpctx->encode_lavc_ctx) - uninitialize_parts -= INITIALIZED_AO; - uninit_player(mpctx, uninitialize_parts); - - // xxx handle this as INITIALIZED_CONFIG? + uninit_audio_chain(mpctx); + uninit_video_chain(mpctx); + uninit_sub_all(mpctx); + uninit_libass(mpctx); + uninit_demuxer(mpctx); + uninit_stream(mpctx); + if (!opts->fixed_vo) + uninit_video_out(mpctx); + if (!(opts->gapless_audio && mpctx->stop_play == AT_END_OF_FILE) && + !mpctx->encode_lavc_ctx) + uninit_audio_out(mpctx); + if (mpctx->stop_play != PT_RESTART) m_config_restore_backups(mpctx->mconfig); diff --git a/player/main.c b/player/main.c index ff3b8ab7fe..2a05d3b4f4 100644 --- a/player/main.c +++ b/player/main.c @@ -118,8 +118,8 @@ static void shutdown_clients(struct MPContext *mpctx) void mp_destroy(struct MPContext *mpctx) { - if (mpctx->initialized) - uninit_player(mpctx, INITIALIZED_ALL); + uninit_audio_out(mpctx); + uninit_video_out(mpctx); #if HAVE_ENCODING encode_lavc_finish(mpctx->encode_lavc_ctx); @@ -439,7 +439,6 @@ int mp_initialize(struct MPContext *mpctx) return -1; } mpctx->mouse_cursor_visible = true; - mpctx->initialized_flags |= INITIALIZED_VO; } // Lua user scripts (etc.) can call arbitrary functions. Load them at a point diff --git a/player/osd.c b/player/osd.c index 15cceab95f..2d15c9b904 100644 --- a/player/osd.c +++ b/player/osd.c @@ -156,8 +156,7 @@ static void print_status(struct MPContext *mpctx) if (!opts->use_terminal) return; - if (opts->quiet || !(mpctx->initialized_flags & INITIALIZED_PLAYBACK) || - !mpctx->playing_msg_shown) + if (opts->quiet || !mpctx->playback_initialized || !mpctx->playing_msg_shown) { term_osd_set_status(mpctx, ""); return; diff --git a/player/playloop.c b/player/playloop.c index de1165e963..5cefcb8ac5 100644 --- a/player/playloop.c +++ b/player/playloop.c @@ -789,17 +789,18 @@ static void handle_chapter_change(struct MPContext *mpctx) // Execute a forceful refresh of the VO window, if it hasn't had a valid frame // for a while. The problem is that a VO with no valid frame (vo->hasframe==0) // doesn't redraw video and doesn't OSD interaction. So screw it, hard. +// It also closes the VO if force_window or video display is not active. void handle_force_window(struct MPContext *mpctx, bool reconfig) { // Don't interfere with real video playback if (mpctx->d_video) return; - struct vo *vo = mpctx->video_out; - if (!vo) - return; + if (!mpctx->opts->force_vo) + uninit_video_out(mpctx); - if (!vo->config_ok || reconfig) { + if (mpctx->video_out && (!mpctx->video_out->config_ok || reconfig)) { + struct vo *vo = mpctx->video_out; MP_INFO(mpctx, "Creating non-video VO window.\n"); // Pick whatever works int config_format = 0; @@ -974,10 +975,7 @@ void idle_loop(struct MPContext *mpctx) { if (need_reinit) { mp_notify(mpctx, MPV_EVENT_IDLE, NULL); - int uninit = INITIALIZED_AO; - if (!mpctx->opts->force_vo) - uninit |= INITIALIZED_VO; - uninit_player(mpctx, uninit); + uninit_audio_out(mpctx); handle_force_window(mpctx, true); mpctx->sleeptime = 0; need_reinit = false; diff --git a/player/sub.c b/player/sub.c index 8f5f8ad8ac..6d2c5f06a5 100644 --- a/player/sub.c +++ b/player/sub.c @@ -38,7 +38,7 @@ #include "core.h" -void uninit_subs(struct demuxer *demuxer) +void uninit_stream_sub_decoders(struct demuxer *demuxer) { for (int i = 0; i < demuxer->num_streams; i++) { struct sh_stream *sh = demuxer->streams[i]; @@ -49,6 +49,23 @@ void uninit_subs(struct demuxer *demuxer) } } +void uninit_sub(struct MPContext *mpctx, int order) +{ + if (mpctx->d_sub[order]) { + mpctx->d_sub[order] = NULL; // Note: not free'd. + int obj = order ? OSDTYPE_SUB2 : OSDTYPE_SUB; + osd_set_sub(mpctx->osd, obj, NULL); + reset_subtitles(mpctx, order); + reselect_demux_streams(mpctx); + } +} + +void uninit_sub_all(struct MPContext *mpctx) +{ + uninit_sub(mpctx, 0); + 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.) @@ -85,17 +102,13 @@ void reset_subtitle_state(struct MPContext *mpctx) static void update_subtitle(struct MPContext *mpctx, int order) { struct MPOpts *opts = mpctx->opts; - if (order == 0) { - if (!(mpctx->initialized_flags & INITIALIZED_SUB)) - return; - } else { - if (!(mpctx->initialized_flags & INITIALIZED_SUB2)) - return; - } - struct track *track = mpctx->current_track[order][STREAM_SUB]; struct dec_sub *dec_sub = mpctx->d_sub[order]; - assert(track && dec_sub); + + if (!track) + return; + + assert(dec_sub); int obj = order ? OSDTYPE_SUB2 : OSDTYPE_SUB; if (mpctx->d_video) { @@ -190,30 +203,20 @@ void reinit_subs(struct MPContext *mpctx, int order) struct MPOpts *opts = mpctx->opts; struct track *track = mpctx->current_track[order][STREAM_SUB]; int obj = order ? OSDTYPE_SUB2 : OSDTYPE_SUB; - int init_flag = order ? INITIALIZED_SUB2 : INITIALIZED_SUB; - assert(!(mpctx->initialized_flags & init_flag)); + assert(!mpctx->d_sub[order]); struct sh_stream *sh = track ? track->stream : NULL; if (!sh) return; - if (!sh->sub->dec_sub) { - assert(!mpctx->d_sub[order]); + // The decoder is cached in the stream header in order to make ordered + // chapters work better. + if (!sh->sub->dec_sub) sh->sub->dec_sub = sub_create(mpctx->global); - } - - assert(!mpctx->d_sub[order] || sh->sub->dec_sub == mpctx->d_sub[order]); - - // The decoder is kept in the stream header in order to make ordered - // chapters work well. mpctx->d_sub[order] = sh->sub->dec_sub; - mpctx->initialized_flags |= init_flag; - struct dec_sub *dec_sub = mpctx->d_sub[order]; - assert(dec_sub); - reinit_subdec(mpctx, track, dec_sub); struct osd_sub_state state = { diff --git a/player/video.c b/player/video.c index 80acbf7b72..c4acb0734e 100644 --- a/player/video.c +++ b/player/video.c @@ -229,10 +229,29 @@ void reset_video_state(struct MPContext *mpctx) mpctx->video_status = mpctx->d_video ? STATUS_SYNCING : STATUS_EOF; } +void uninit_video_out(struct MPContext *mpctx) +{ + uninit_video_chain(mpctx); + if (mpctx->video_out) + vo_destroy(mpctx->video_out); + mpctx->video_out = NULL; +} + +void uninit_video_chain(struct MPContext *mpctx) +{ + if (mpctx->d_video) { + reset_video_state(mpctx); + video_uninit(mpctx->d_video); + mpctx->d_video = NULL; + mpctx->video_status = STATUS_EOF; + mpctx->sync_audio_to_video = false; + reselect_demux_streams(mpctx); + } +} + int reinit_video_chain(struct MPContext *mpctx) { struct MPOpts *opts = mpctx->opts; - assert(!(mpctx->initialized_flags & INITIALIZED_VCODEC)); assert(!mpctx->d_video); struct track *track = mpctx->current_track[0][STREAM_VIDEO]; struct sh_stream *sh = track ? track->stream : NULL; @@ -245,7 +264,7 @@ int reinit_video_chain(struct MPContext *mpctx) sh->video->fps); //================== Init VIDEO (codec & libvo) ========================== - if (!opts->fixed_vo || !(mpctx->initialized_flags & INITIALIZED_VO)) { + if (!opts->fixed_vo || !mpctx->video_out) { mpctx->video_out = init_best_video_out(mpctx->global, mpctx->input, mpctx->osd, mpctx->encode_lavc_ctx); @@ -255,7 +274,6 @@ int reinit_video_chain(struct MPContext *mpctx) goto err_out; } mpctx->mouse_cursor_visible = true; - mpctx->initialized_flags |= INITIALIZED_VO; } update_window_title(mpctx, true); @@ -268,7 +286,6 @@ int reinit_video_chain(struct MPContext *mpctx) d_video->header = sh; d_video->fps = sh->video->fps; d_video->vo = mpctx->video_out; - mpctx->initialized_flags |= INITIALIZED_VCODEC; vo_control(mpctx->video_out, VOCTRL_GET_HWDEC_INFO, &d_video->hwdec_info); @@ -307,7 +324,7 @@ int reinit_video_chain(struct MPContext *mpctx) err_out: no_video: - uninit_player(mpctx, INITIALIZED_VCODEC | (opts->force_vo ? 0 : INITIALIZED_VO)); + uninit_video_chain(mpctx); if (track) mp_deselect_track(mpctx, track); handle_force_window(mpctx, true); @@ -811,10 +828,7 @@ void write_video(struct MPContext *mpctx, double endpts) error: MP_FATAL(mpctx, "Could not initialize video chain.\n"); - int uninit = INITIALIZED_VCODEC; - if (!opts->force_vo) - uninit |= INITIALIZED_VO; - uninit_player(mpctx, uninit); + uninit_video_chain(mpctx); if (!mpctx->current_track[STREAM_AUDIO]) mpctx->stop_play = PT_NEXT_ENTRY; mpctx->error_playing = true; -- cgit v1.2.3