mirror of
https://github.com/mpv-player/mpv
synced 2025-04-10 19:51:43 +00:00
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:
parent
9570976255
commit
9d5d031b6d
@ -142,21 +142,45 @@ void reset_audio_state(struct MPContext *mpctx)
|
|||||||
mpctx->audio_status = mpctx->d_audio ? STATUS_SYNCING : STATUS_EOF;
|
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)
|
void reinit_audio_chain(struct MPContext *mpctx)
|
||||||
{
|
{
|
||||||
struct MPOpts *opts = mpctx->opts;
|
struct MPOpts *opts = mpctx->opts;
|
||||||
struct track *track = mpctx->current_track[0][STREAM_AUDIO];
|
struct track *track = mpctx->current_track[0][STREAM_AUDIO];
|
||||||
struct sh_stream *sh = track ? track->stream : NULL;
|
struct sh_stream *sh = track ? track->stream : NULL;
|
||||||
if (!sh) {
|
if (!sh) {
|
||||||
uninit_player(mpctx, INITIALIZED_AO);
|
uninit_audio_out(mpctx);
|
||||||
goto no_audio;
|
goto no_audio;
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_notify(mpctx, MPV_EVENT_AUDIO_RECONFIG, NULL);
|
mp_notify(mpctx, MPV_EVENT_AUDIO_RECONFIG, NULL);
|
||||||
|
|
||||||
if (!(mpctx->initialized_flags & INITIALIZED_ACODEC)) {
|
if (!mpctx->d_audio) {
|
||||||
mpctx->initialized_flags |= INITIALIZED_ACODEC;
|
|
||||||
assert(!mpctx->d_audio);
|
|
||||||
mpctx->d_audio = talloc_zero(NULL, struct dec_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->log = mp_log_new(mpctx->d_audio, mpctx->log, "!ad");
|
||||||
mpctx->d_audio->global = mpctx->global;
|
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
|
// Weak gapless audio: drain AO on decoder format changes
|
||||||
if (mpctx->ao_decoder_fmt && (mpctx->initialized_flags & INITIALIZED_AO) &&
|
if (mpctx->ao_decoder_fmt && mpctx->ao && opts->gapless_audio < 0 &&
|
||||||
!mp_audio_config_equals(mpctx->ao_decoder_fmt, &in_format) &&
|
!mp_audio_config_equals(mpctx->ao_decoder_fmt, &in_format))
|
||||||
opts->gapless_audio < 0)
|
|
||||||
{
|
{
|
||||||
uninit_player(mpctx, INITIALIZED_AO);
|
uninit_audio_out(mpctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct af_stream *afs = mpctx->d_audio->afilter;
|
struct af_stream *afs = mpctx->d_audio->afilter;
|
||||||
|
|
||||||
if (mpctx->initialized_flags & INITIALIZED_AO) {
|
if (mpctx->ao) {
|
||||||
ao_get_format(mpctx->ao, &afs->output);
|
ao_get_format(mpctx->ao, &afs->output);
|
||||||
} else {
|
} else {
|
||||||
afs->output = (struct mp_audio){0};
|
afs->output = (struct mp_audio){0};
|
||||||
@ -219,8 +242,7 @@ void reinit_audio_chain(struct MPContext *mpctx)
|
|||||||
goto init_error;
|
goto init_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(mpctx->initialized_flags & INITIALIZED_AO)) {
|
if (!mpctx->ao) {
|
||||||
mpctx->initialized_flags |= INITIALIZED_AO;
|
|
||||||
afs->initialized = 0; // do it again
|
afs->initialized = 0; // do it again
|
||||||
|
|
||||||
mp_chmap_remove_useless_channels(&afs->output.channels,
|
mp_chmap_remove_useless_channels(&afs->output.channels,
|
||||||
@ -260,7 +282,8 @@ void reinit_audio_chain(struct MPContext *mpctx)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
init_error:
|
init_error:
|
||||||
uninit_player(mpctx, INITIALIZED_ACODEC | INITIALIZED_AO);
|
uninit_audio_chain(mpctx);
|
||||||
|
uninit_audio_out(mpctx);
|
||||||
no_audio:
|
no_audio:
|
||||||
mp_deselect_track(mpctx, track);
|
mp_deselect_track(mpctx, track);
|
||||||
if (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.
|
* while displaying video, then doing the output format switch.
|
||||||
*/
|
*/
|
||||||
if (mpctx->opts->gapless_audio < 1)
|
if (mpctx->opts->gapless_audio < 1)
|
||||||
uninit_player(mpctx, INITIALIZED_AO);
|
uninit_audio_out(mpctx);
|
||||||
reinit_audio_chain(mpctx);
|
reinit_audio_chain(mpctx);
|
||||||
mpctx->sleeptime = 0;
|
mpctx->sleeptime = 0;
|
||||||
return; // retry on next iteration
|
return; // retry on next iteration
|
||||||
|
@ -1686,10 +1686,10 @@ static int mp_property_hwdec(void *ctx, struct m_property *prop,
|
|||||||
int new = *(int *)arg;
|
int new = *(int *)arg;
|
||||||
if (current == new)
|
if (current == new)
|
||||||
return M_PROPERTY_OK;
|
return M_PROPERTY_OK;
|
||||||
if (!(mpctx->initialized_flags & INITIALIZED_VCODEC))
|
if (!mpctx->d_video)
|
||||||
return M_PROPERTY_ERROR;
|
return M_PROPERTY_ERROR;
|
||||||
double last_pts = mpctx->last_vo_pts;
|
double last_pts = mpctx->last_vo_pts;
|
||||||
uninit_player(mpctx, INITIALIZED_VCODEC);
|
uninit_video_chain(mpctx);
|
||||||
opts->hwdec_api = new;
|
opts->hwdec_api = new;
|
||||||
reinit_video_chain(mpctx);
|
reinit_video_chain(mpctx);
|
||||||
if (last_pts != MP_NOPTS_VALUE)
|
if (last_pts != MP_NOPTS_VALUE)
|
||||||
|
@ -29,19 +29,6 @@
|
|||||||
|
|
||||||
// definitions used internally by the core player code
|
// 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 {
|
enum stop_play_reason {
|
||||||
KEEP_PLAYING = 0, // must be 0, numeric values of others do not matter
|
KEEP_PLAYING = 0, // must be 0, numeric values of others do not matter
|
||||||
AT_END_OF_FILE, // file has ended, prepare to play next
|
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)
|
char *filename; // always the same as playing->filename (or NULL)
|
||||||
struct mp_resolve_result *resolve_result;
|
struct mp_resolve_result *resolve_result;
|
||||||
enum stop_play_reason stop_play;
|
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
|
// Return code to use with PT_QUIT
|
||||||
enum exit_reason quit_player_rc;
|
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);
|
double written_audio_pts(struct MPContext *mpctx);
|
||||||
void clear_audio_output_buffers(struct MPContext *mpctx);
|
void clear_audio_output_buffers(struct MPContext *mpctx);
|
||||||
void set_playback_speed(struct MPContext *mpctx, double new_speed);
|
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
|
// configfiles.c
|
||||||
void mp_parse_cfgfiles(struct MPContext *mpctx);
|
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_set_playlist_entry(struct MPContext *mpctx, struct playlist_entry *e);
|
||||||
void mp_play_files(struct MPContext *mpctx);
|
void mp_play_files(struct MPContext *mpctx);
|
||||||
void update_demuxer_properties(struct MPContext *mpctx);
|
void update_demuxer_properties(struct MPContext *mpctx);
|
||||||
|
void reselect_demux_streams(struct MPContext *mpctx);
|
||||||
|
|
||||||
// main.c
|
// main.c
|
||||||
int mpv_main(int argc, char *argv[]);
|
int mpv_main(int argc, char *argv[]);
|
||||||
@ -473,8 +463,10 @@ void mp_load_scripts(struct MPContext *mpctx);
|
|||||||
// sub.c
|
// sub.c
|
||||||
void reset_subtitle_state(struct MPContext *mpctx);
|
void reset_subtitle_state(struct MPContext *mpctx);
|
||||||
void reset_subtitles(struct MPContext *mpctx, int order);
|
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 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_osd_msg(struct MPContext *mpctx);
|
||||||
void update_subtitles(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 write_video(struct MPContext *mpctx, double endpts);
|
||||||
void mp_force_video_refresh(struct MPContext *mpctx);
|
void mp_force_video_refresh(struct MPContext *mpctx);
|
||||||
void update_fps(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 */
|
#endif /* MPLAYER_MP_CORE_H */
|
||||||
|
@ -60,133 +60,44 @@
|
|||||||
#include "command.h"
|
#include "command.h"
|
||||||
#include "libmpv/client.h"
|
#include "libmpv/client.h"
|
||||||
|
|
||||||
static void reselect_demux_streams(struct MPContext *mpctx);
|
static void uninit_demuxer(struct MPContext *mpctx)
|
||||||
|
|
||||||
static void uninit_sub(struct MPContext *mpctx, int order)
|
|
||||||
{
|
{
|
||||||
mpctx->d_sub[order] = NULL; // Note: not free'd.
|
assert(!mpctx->d_video && !mpctx->d_audio &&
|
||||||
int obj = order ? OSDTYPE_SUB2 : OSDTYPE_SUB;
|
!mpctx->d_sub[0] && !mpctx->d_sub[1]);
|
||||||
osd_set_sub(mpctx->osd, obj, NULL);
|
for (int i = 0; i < mpctx->num_tracks; i++) {
|
||||||
reset_subtitles(mpctx, order);
|
talloc_free(mpctx->tracks[i]);
|
||||||
reselect_demux_streams(mpctx);
|
}
|
||||||
|
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;
|
free_stream(mpctx->stream);
|
||||||
|
mpctx->stream = NULL;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define APPEND(s, ...) mp_snprintf_cat(s, sizeof(s), __VA_ARGS__)
|
#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)
|
// can be important, because reading from a demuxer stream (e.g. during init)
|
||||||
// will implicitly discard interleaved packets from unselected streams.
|
// will implicitly discard interleaved packets from unselected streams.
|
||||||
// Also initializes position for external 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.
|
// Note: we assume that all demuxer streams are covered by the track list.
|
||||||
for (int t = 0; t < mpctx->num_tracks; t++) {
|
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;
|
enum stop_play_reason orig_stop_play = mpctx->stop_play;
|
||||||
if (!mpctx->d_video && mpctx->stop_play == KEEP_PLAYING)
|
if (!mpctx->d_video && mpctx->stop_play == KEEP_PLAYING)
|
||||||
mpctx->stop_play = AT_END_OF_FILE; // let audio uninit drain data
|
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;
|
mpctx->stop_play = orig_stop_play;
|
||||||
|
|
||||||
if (mpctx->demuxer) {
|
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 (order == 0) {
|
||||||
if (type == STREAM_VIDEO) {
|
if (type == STREAM_VIDEO) {
|
||||||
int uninit = INITIALIZED_VCODEC;
|
uninit_video_chain(mpctx);
|
||||||
if (!mpctx->opts->force_vo)
|
if (!mpctx->opts->fixed_vo || !track)
|
||||||
uninit |= mpctx->opts->fixed_vo && track ? 0 : INITIALIZED_VO;
|
handle_force_window(mpctx, false);
|
||||||
uninit_player(mpctx, uninit);
|
|
||||||
} else if (type == STREAM_AUDIO) {
|
} else if (type == STREAM_AUDIO) {
|
||||||
clear_audio_output_buffers(mpctx);
|
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) {
|
} else if (type == STREAM_SUB) {
|
||||||
uninit_player(mpctx, INITIALIZED_SUB);
|
uninit_sub(mpctx, 0);
|
||||||
}
|
}
|
||||||
} else if (order == 1) {
|
} else if (order == 1) {
|
||||||
if (type == STREAM_SUB)
|
if (type == STREAM_SUB)
|
||||||
uninit_player(mpctx, INITIALIZED_SUB2);
|
uninit_sub(mpctx, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current)
|
if (current)
|
||||||
@ -870,18 +787,26 @@ static void add_subtitle_fonts_from_sources(struct MPContext *mpctx)
|
|||||||
#endif
|
#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)
|
static void init_sub_renderer(struct MPContext *mpctx)
|
||||||
{
|
{
|
||||||
#if HAVE_LIBASS
|
#if HAVE_LIBASS
|
||||||
assert(!(mpctx->initialized_flags & INITIALIZED_LIBASS));
|
uninit_libass(mpctx);
|
||||||
assert(!mpctx->ass_renderer);
|
|
||||||
|
|
||||||
mpctx->ass_renderer = ass_renderer_init(mpctx->ass_library);
|
mpctx->ass_renderer = ass_renderer_init(mpctx->ass_library);
|
||||||
if (mpctx->ass_renderer) {
|
if (mpctx->ass_renderer) {
|
||||||
mp_ass_configure_fonts(mpctx->ass_renderer, mpctx->opts->sub_text_style,
|
mp_ass_configure_fonts(mpctx->ass_renderer, mpctx->opts->sub_text_style,
|
||||||
mpctx->global, mpctx->ass_log);
|
mpctx->global, mpctx->ass_log);
|
||||||
}
|
}
|
||||||
mpctx->initialized_flags |= INITIALIZED_LIBASS;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1093,7 +1018,6 @@ static void play_current_file(struct MPContext *mpctx)
|
|||||||
mp_process_input(mpctx);
|
mp_process_input(mpctx);
|
||||||
goto terminate_playback;
|
goto terminate_playback;
|
||||||
}
|
}
|
||||||
mpctx->initialized_flags |= INITIALIZED_STREAM;
|
|
||||||
|
|
||||||
if (opts->stream_dump && opts->stream_dump[0]) {
|
if (opts->stream_dump && opts->stream_dump[0]) {
|
||||||
stream_dump(mpctx);
|
stream_dump(mpctx);
|
||||||
@ -1127,8 +1051,6 @@ goto_reopen_demuxer: ;
|
|||||||
|
|
||||||
MP_TARRAY_APPEND(NULL, mpctx->sources, mpctx->num_sources, mpctx->demuxer);
|
MP_TARRAY_APPEND(NULL, mpctx->sources, mpctx->num_sources, mpctx->demuxer);
|
||||||
|
|
||||||
mpctx->initialized_flags |= INITIALIZED_DEMUXER;
|
|
||||||
|
|
||||||
if (mpctx->demuxer->playlist) {
|
if (mpctx->demuxer->playlist) {
|
||||||
int entry_stream_flags =
|
int entry_stream_flags =
|
||||||
(mpctx->demuxer->stream->safe_origin ? 0 : STREAM_SAFE_ONLY) |
|
(mpctx->demuxer->stream->safe_origin ? 0 : STREAM_SAFE_ONLY) |
|
||||||
@ -1276,7 +1198,7 @@ goto_reopen_demuxer: ;
|
|||||||
if (mpctx->opts->pause)
|
if (mpctx->opts->pause)
|
||||||
pause_player(mpctx);
|
pause_player(mpctx);
|
||||||
|
|
||||||
mpctx->initialized_flags |= INITIALIZED_PLAYBACK;
|
mpctx->playback_initialized = true;
|
||||||
mp_notify(mpctx, MPV_EVENT_FILE_LOADED, NULL);
|
mp_notify(mpctx, MPV_EVENT_FILE_LOADED, NULL);
|
||||||
|
|
||||||
playback_start = mp_time_sec();
|
playback_start = mp_time_sec();
|
||||||
@ -1288,9 +1210,11 @@ goto_reopen_demuxer: ;
|
|||||||
|
|
||||||
if (mpctx->stop_play == PT_RELOAD_DEMUXER) {
|
if (mpctx->stop_play == PT_RELOAD_DEMUXER) {
|
||||||
mpctx->stop_play = KEEP_PLAYING;
|
mpctx->stop_play = KEEP_PLAYING;
|
||||||
uninit_player(mpctx, INITIALIZED_ALL -
|
mpctx->playback_initialized = false;
|
||||||
(INITIALIZED_PLAYBACK | INITIALIZED_STREAM |
|
uninit_audio_chain(mpctx);
|
||||||
(opts->fixed_vo ? INITIALIZED_VO : 0)));
|
uninit_video_chain(mpctx);
|
||||||
|
uninit_sub_all(mpctx);
|
||||||
|
uninit_demuxer(mpctx);
|
||||||
goto goto_reopen_demuxer;
|
goto goto_reopen_demuxer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1315,15 +1239,18 @@ terminate_playback:
|
|||||||
MP_INFO(mpctx, "\n");
|
MP_INFO(mpctx, "\n");
|
||||||
|
|
||||||
// time to uninit all, except global stuff:
|
// time to uninit all, except global stuff:
|
||||||
int uninitialize_parts = INITIALIZED_ALL;
|
uninit_audio_chain(mpctx);
|
||||||
if (opts->fixed_vo)
|
uninit_video_chain(mpctx);
|
||||||
uninitialize_parts -= INITIALIZED_VO;
|
uninit_sub_all(mpctx);
|
||||||
if ((opts->gapless_audio && mpctx->stop_play == AT_END_OF_FILE) ||
|
uninit_libass(mpctx);
|
||||||
mpctx->encode_lavc_ctx)
|
uninit_demuxer(mpctx);
|
||||||
uninitialize_parts -= INITIALIZED_AO;
|
uninit_stream(mpctx);
|
||||||
uninit_player(mpctx, uninitialize_parts);
|
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)
|
if (mpctx->stop_play != PT_RESTART)
|
||||||
m_config_restore_backups(mpctx->mconfig);
|
m_config_restore_backups(mpctx->mconfig);
|
||||||
|
|
||||||
|
@ -118,8 +118,8 @@ static void shutdown_clients(struct MPContext *mpctx)
|
|||||||
|
|
||||||
void mp_destroy(struct MPContext *mpctx)
|
void mp_destroy(struct MPContext *mpctx)
|
||||||
{
|
{
|
||||||
if (mpctx->initialized)
|
uninit_audio_out(mpctx);
|
||||||
uninit_player(mpctx, INITIALIZED_ALL);
|
uninit_video_out(mpctx);
|
||||||
|
|
||||||
#if HAVE_ENCODING
|
#if HAVE_ENCODING
|
||||||
encode_lavc_finish(mpctx->encode_lavc_ctx);
|
encode_lavc_finish(mpctx->encode_lavc_ctx);
|
||||||
@ -439,7 +439,6 @@ int mp_initialize(struct MPContext *mpctx)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
mpctx->mouse_cursor_visible = true;
|
mpctx->mouse_cursor_visible = true;
|
||||||
mpctx->initialized_flags |= INITIALIZED_VO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lua user scripts (etc.) can call arbitrary functions. Load them at a point
|
// Lua user scripts (etc.) can call arbitrary functions. Load them at a point
|
||||||
|
@ -156,8 +156,7 @@ static void print_status(struct MPContext *mpctx)
|
|||||||
if (!opts->use_terminal)
|
if (!opts->use_terminal)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (opts->quiet || !(mpctx->initialized_flags & INITIALIZED_PLAYBACK) ||
|
if (opts->quiet || !mpctx->playback_initialized || !mpctx->playing_msg_shown)
|
||||||
!mpctx->playing_msg_shown)
|
|
||||||
{
|
{
|
||||||
term_osd_set_status(mpctx, "");
|
term_osd_set_status(mpctx, "");
|
||||||
return;
|
return;
|
||||||
|
@ -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
|
// 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)
|
// 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.
|
// 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)
|
void handle_force_window(struct MPContext *mpctx, bool reconfig)
|
||||||
{
|
{
|
||||||
// Don't interfere with real video playback
|
// Don't interfere with real video playback
|
||||||
if (mpctx->d_video)
|
if (mpctx->d_video)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
struct vo *vo = mpctx->video_out;
|
if (!mpctx->opts->force_vo)
|
||||||
if (!vo)
|
uninit_video_out(mpctx);
|
||||||
return;
|
|
||||||
|
|
||||||
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");
|
MP_INFO(mpctx, "Creating non-video VO window.\n");
|
||||||
// Pick whatever works
|
// Pick whatever works
|
||||||
int config_format = 0;
|
int config_format = 0;
|
||||||
@ -974,10 +975,7 @@ void idle_loop(struct MPContext *mpctx)
|
|||||||
{
|
{
|
||||||
if (need_reinit) {
|
if (need_reinit) {
|
||||||
mp_notify(mpctx, MPV_EVENT_IDLE, NULL);
|
mp_notify(mpctx, MPV_EVENT_IDLE, NULL);
|
||||||
int uninit = INITIALIZED_AO;
|
uninit_audio_out(mpctx);
|
||||||
if (!mpctx->opts->force_vo)
|
|
||||||
uninit |= INITIALIZED_VO;
|
|
||||||
uninit_player(mpctx, uninit);
|
|
||||||
handle_force_window(mpctx, true);
|
handle_force_window(mpctx, true);
|
||||||
mpctx->sleeptime = 0;
|
mpctx->sleeptime = 0;
|
||||||
need_reinit = false;
|
need_reinit = false;
|
||||||
|
51
player/sub.c
51
player/sub.c
@ -38,7 +38,7 @@
|
|||||||
|
|
||||||
#include "core.h"
|
#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++) {
|
for (int i = 0; i < demuxer->num_streams; i++) {
|
||||||
struct sh_stream *sh = demuxer->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
|
// When reading subtitles from a demuxer, and we read video or audio from the
|
||||||
// demuxer, we should not explicitly read subtitle packets. (With external
|
// demuxer, we should not explicitly read subtitle packets. (With external
|
||||||
// subs, we have to.)
|
// subs, we have to.)
|
||||||
@ -85,17 +102,13 @@ void reset_subtitle_state(struct MPContext *mpctx)
|
|||||||
static void update_subtitle(struct MPContext *mpctx, int order)
|
static void update_subtitle(struct MPContext *mpctx, int order)
|
||||||
{
|
{
|
||||||
struct MPOpts *opts = mpctx->opts;
|
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 track *track = mpctx->current_track[order][STREAM_SUB];
|
||||||
struct dec_sub *dec_sub = mpctx->d_sub[order];
|
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;
|
int obj = order ? OSDTYPE_SUB2 : OSDTYPE_SUB;
|
||||||
|
|
||||||
if (mpctx->d_video) {
|
if (mpctx->d_video) {
|
||||||
@ -190,30 +203,20 @@ void reinit_subs(struct MPContext *mpctx, int order)
|
|||||||
struct MPOpts *opts = mpctx->opts;
|
struct MPOpts *opts = mpctx->opts;
|
||||||
struct track *track = mpctx->current_track[order][STREAM_SUB];
|
struct track *track = mpctx->current_track[order][STREAM_SUB];
|
||||||
int obj = order ? OSDTYPE_SUB2 : OSDTYPE_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;
|
struct sh_stream *sh = track ? track->stream : NULL;
|
||||||
if (!sh)
|
if (!sh)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!sh->sub->dec_sub) {
|
// The decoder is cached in the stream header in order to make ordered
|
||||||
assert(!mpctx->d_sub[order]);
|
// chapters work better.
|
||||||
|
if (!sh->sub->dec_sub)
|
||||||
sh->sub->dec_sub = sub_create(mpctx->global);
|
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->d_sub[order] = sh->sub->dec_sub;
|
||||||
|
|
||||||
mpctx->initialized_flags |= init_flag;
|
|
||||||
|
|
||||||
struct dec_sub *dec_sub = mpctx->d_sub[order];
|
struct dec_sub *dec_sub = mpctx->d_sub[order];
|
||||||
assert(dec_sub);
|
|
||||||
|
|
||||||
reinit_subdec(mpctx, track, dec_sub);
|
reinit_subdec(mpctx, track, dec_sub);
|
||||||
|
|
||||||
struct osd_sub_state state = {
|
struct osd_sub_state state = {
|
||||||
|
@ -229,10 +229,29 @@ void reset_video_state(struct MPContext *mpctx)
|
|||||||
mpctx->video_status = mpctx->d_video ? STATUS_SYNCING : STATUS_EOF;
|
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)
|
int reinit_video_chain(struct MPContext *mpctx)
|
||||||
{
|
{
|
||||||
struct MPOpts *opts = mpctx->opts;
|
struct MPOpts *opts = mpctx->opts;
|
||||||
assert(!(mpctx->initialized_flags & INITIALIZED_VCODEC));
|
|
||||||
assert(!mpctx->d_video);
|
assert(!mpctx->d_video);
|
||||||
struct track *track = mpctx->current_track[0][STREAM_VIDEO];
|
struct track *track = mpctx->current_track[0][STREAM_VIDEO];
|
||||||
struct sh_stream *sh = track ? track->stream : NULL;
|
struct sh_stream *sh = track ? track->stream : NULL;
|
||||||
@ -245,7 +264,7 @@ int reinit_video_chain(struct MPContext *mpctx)
|
|||||||
sh->video->fps);
|
sh->video->fps);
|
||||||
|
|
||||||
//================== Init VIDEO (codec & libvo) ==========================
|
//================== 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->video_out = init_best_video_out(mpctx->global, mpctx->input,
|
||||||
mpctx->osd,
|
mpctx->osd,
|
||||||
mpctx->encode_lavc_ctx);
|
mpctx->encode_lavc_ctx);
|
||||||
@ -255,7 +274,6 @@ int reinit_video_chain(struct MPContext *mpctx)
|
|||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
mpctx->mouse_cursor_visible = true;
|
mpctx->mouse_cursor_visible = true;
|
||||||
mpctx->initialized_flags |= INITIALIZED_VO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
update_window_title(mpctx, true);
|
update_window_title(mpctx, true);
|
||||||
@ -268,7 +286,6 @@ int reinit_video_chain(struct MPContext *mpctx)
|
|||||||
d_video->header = sh;
|
d_video->header = sh;
|
||||||
d_video->fps = sh->video->fps;
|
d_video->fps = sh->video->fps;
|
||||||
d_video->vo = mpctx->video_out;
|
d_video->vo = mpctx->video_out;
|
||||||
mpctx->initialized_flags |= INITIALIZED_VCODEC;
|
|
||||||
|
|
||||||
vo_control(mpctx->video_out, VOCTRL_GET_HWDEC_INFO, &d_video->hwdec_info);
|
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:
|
err_out:
|
||||||
no_video:
|
no_video:
|
||||||
uninit_player(mpctx, INITIALIZED_VCODEC | (opts->force_vo ? 0 : INITIALIZED_VO));
|
uninit_video_chain(mpctx);
|
||||||
if (track)
|
if (track)
|
||||||
mp_deselect_track(mpctx, track);
|
mp_deselect_track(mpctx, track);
|
||||||
handle_force_window(mpctx, true);
|
handle_force_window(mpctx, true);
|
||||||
@ -811,10 +828,7 @@ void write_video(struct MPContext *mpctx, double endpts)
|
|||||||
|
|
||||||
error:
|
error:
|
||||||
MP_FATAL(mpctx, "Could not initialize video chain.\n");
|
MP_FATAL(mpctx, "Could not initialize video chain.\n");
|
||||||
int uninit = INITIALIZED_VCODEC;
|
uninit_video_chain(mpctx);
|
||||||
if (!opts->force_vo)
|
|
||||||
uninit |= INITIALIZED_VO;
|
|
||||||
uninit_player(mpctx, uninit);
|
|
||||||
if (!mpctx->current_track[STREAM_AUDIO])
|
if (!mpctx->current_track[STREAM_AUDIO])
|
||||||
mpctx->stop_play = PT_NEXT_ENTRY;
|
mpctx->stop_play = PT_NEXT_ENTRY;
|
||||||
mpctx->error_playing = true;
|
mpctx->error_playing = true;
|
||||||
|
Loading…
Reference in New Issue
Block a user