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().
This commit is contained in:
wm4 2014-10-03 19:57:49 +02:00
parent 9570976255
commit 9d5d031b6d
9 changed files with 183 additions and 226 deletions

View File

@ -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

View File

@ -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)

View File

@ -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 */

View File

@ -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);
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);
// xxx handle this as INITIALIZED_CONFIG?
if (mpctx->stop_play != PT_RESTART)
m_config_restore_backups(mpctx->mconfig);

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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 = {

View File

@ -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;