mirror of
https://github.com/mpv-player/mpv
synced 2025-03-20 02:09:52 +00:00
player: redo demuxer stream selection
Use struct track to decide what stream to select. Add a "selected" field and use that in some places instead of checking mpctx->current_track.
This commit is contained in:
parent
96e6f3f4b6
commit
b796f2bb76
@ -104,7 +104,8 @@ int reinit_audio_filters(struct MPContext *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 sh_stream *sh = init_demux_stream(mpctx, STREAM_AUDIO);
|
struct track *track = mpctx->current_track[STREAM_AUDIO];
|
||||||
|
struct sh_stream *sh = init_demux_stream(mpctx, track);
|
||||||
if (!sh) {
|
if (!sh) {
|
||||||
uninit_player(mpctx, INITIALIZED_AO);
|
uninit_player(mpctx, INITIALIZED_AO);
|
||||||
goto no_audio;
|
goto no_audio;
|
||||||
@ -186,9 +187,8 @@ void reinit_audio_chain(struct MPContext *mpctx)
|
|||||||
|
|
||||||
init_error:
|
init_error:
|
||||||
uninit_player(mpctx, INITIALIZED_ACODEC | INITIALIZED_AO);
|
uninit_player(mpctx, INITIALIZED_ACODEC | INITIALIZED_AO);
|
||||||
cleanup_demux_stream(mpctx, STREAM_AUDIO);
|
|
||||||
no_audio:
|
no_audio:
|
||||||
mpctx->current_track[STREAM_AUDIO] = NULL;
|
mp_deselect_track(mpctx, track);
|
||||||
MP_INFO(mpctx, "Audio: no audio\n");
|
MP_INFO(mpctx, "Audio: no audio\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1067,10 +1067,9 @@ static int property_list_tracks(m_option_t *prop, int action, void *arg,
|
|||||||
if (track->type != type)
|
if (track->type != type)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
bool selected = mpctx->current_track[track->type] == track;
|
|
||||||
res = talloc_asprintf_append(res, "%s: ",
|
res = talloc_asprintf_append(res, "%s: ",
|
||||||
track_type_name(track->type));
|
track_type_name(track->type));
|
||||||
if (selected)
|
if (track->selected)
|
||||||
res = talloc_asprintf_append(res, "> ");
|
res = talloc_asprintf_append(res, "> ");
|
||||||
res = talloc_asprintf_append(res, "(%d) ", track->user_tid);
|
res = talloc_asprintf_append(res, "(%d) ", track->user_tid);
|
||||||
if (track->title)
|
if (track->title)
|
||||||
@ -1079,7 +1078,7 @@ static int property_list_tracks(m_option_t *prop, int action, void *arg,
|
|||||||
res = talloc_asprintf_append(res, "(%s) ", track->lang);
|
res = talloc_asprintf_append(res, "(%s) ", track->lang);
|
||||||
if (track->is_external)
|
if (track->is_external)
|
||||||
res = talloc_asprintf_append(res, "(external) ");
|
res = talloc_asprintf_append(res, "(external) ");
|
||||||
if (selected)
|
if (track->selected)
|
||||||
res = talloc_asprintf_append(res, "<");
|
res = talloc_asprintf_append(res, "<");
|
||||||
res = talloc_asprintf_append(res, "\n");
|
res = talloc_asprintf_append(res, "\n");
|
||||||
}
|
}
|
||||||
|
@ -108,6 +108,10 @@ enum seek_type {
|
|||||||
|
|
||||||
struct track {
|
struct track {
|
||||||
enum stream_type type;
|
enum stream_type type;
|
||||||
|
|
||||||
|
// Currently used for decoding.
|
||||||
|
bool selected;
|
||||||
|
|
||||||
// The type specific ID, also called aid (audio), sid (subs), vid (video).
|
// The type specific ID, also called aid (audio), sid (subs), vid (video).
|
||||||
// For UI purposes only; this ID doesn't have anything to do with any
|
// For UI purposes only; this ID doesn't have anything to do with any
|
||||||
// IDs coming from demuxers or container files.
|
// IDs coming from demuxers or container files.
|
||||||
@ -198,8 +202,6 @@ typedef struct MPContext {
|
|||||||
// Selected tracks. NULL if no track selected.
|
// Selected tracks. NULL if no track selected.
|
||||||
struct track *current_track[STREAM_TYPE_COUNT];
|
struct track *current_track[STREAM_TYPE_COUNT];
|
||||||
|
|
||||||
struct sh_stream *sh[STREAM_TYPE_COUNT];
|
|
||||||
|
|
||||||
struct dec_video *d_video;
|
struct dec_video *d_video;
|
||||||
struct dec_audio *d_audio;
|
struct dec_audio *d_audio;
|
||||||
struct dec_sub *d_sub;
|
struct dec_sub *d_sub;
|
||||||
@ -367,13 +369,13 @@ void uninit_player(struct MPContext *mpctx, unsigned int mask);
|
|||||||
struct track *mp_add_subtitles(struct MPContext *mpctx, char *filename);
|
struct track *mp_add_subtitles(struct MPContext *mpctx, char *filename);
|
||||||
void mp_switch_track(struct MPContext *mpctx, enum stream_type type,
|
void mp_switch_track(struct MPContext *mpctx, enum stream_type type,
|
||||||
struct track *track);
|
struct track *track);
|
||||||
|
void mp_deselect_track(struct MPContext *mpctx, struct track *track);
|
||||||
struct track *mp_track_by_tid(struct MPContext *mpctx, enum stream_type type,
|
struct track *mp_track_by_tid(struct MPContext *mpctx, enum stream_type type,
|
||||||
int tid);
|
int tid);
|
||||||
bool timeline_set_part(struct MPContext *mpctx, int i, bool force);
|
bool timeline_set_part(struct MPContext *mpctx, int i, bool force);
|
||||||
double timeline_set_from_time(struct MPContext *mpctx, double pts, bool *need_reset);
|
double timeline_set_from_time(struct MPContext *mpctx, double pts, bool *need_reset);
|
||||||
struct sh_stream *init_demux_stream(struct MPContext *mpctx,
|
struct sh_stream *init_demux_stream(struct MPContext *mpctx, struct track *track);
|
||||||
enum stream_type type);
|
void reselect_demux_streams(struct MPContext *mpctx);
|
||||||
void cleanup_demux_stream(struct MPContext *mpctx, enum stream_type type);
|
|
||||||
void add_demuxer_tracks(struct MPContext *mpctx, struct demuxer *demuxer);
|
void add_demuxer_tracks(struct MPContext *mpctx, struct demuxer *demuxer);
|
||||||
bool mp_remove_track(struct MPContext *mpctx, struct track *track);
|
bool mp_remove_track(struct MPContext *mpctx, struct track *track);
|
||||||
struct playlist_entry *mp_next_file(struct MPContext *mpctx, int direction,
|
struct playlist_entry *mp_next_file(struct MPContext *mpctx, int direction,
|
||||||
|
@ -75,17 +75,17 @@ void uninit_player(struct MPContext *mpctx, unsigned int mask)
|
|||||||
mixer_uninit_audio(mpctx->mixer);
|
mixer_uninit_audio(mpctx->mixer);
|
||||||
audio_uninit(mpctx->d_audio);
|
audio_uninit(mpctx->d_audio);
|
||||||
mpctx->d_audio = NULL;
|
mpctx->d_audio = NULL;
|
||||||
cleanup_demux_stream(mpctx, STREAM_AUDIO);
|
reselect_demux_streams(mpctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mask & INITIALIZED_SUB) {
|
if (mask & INITIALIZED_SUB) {
|
||||||
mpctx->initialized_flags &= ~INITIALIZED_SUB;
|
mpctx->initialized_flags &= ~INITIALIZED_SUB;
|
||||||
if (mpctx->d_sub)
|
if (mpctx->d_sub)
|
||||||
sub_reset(mpctx->d_sub);
|
sub_reset(mpctx->d_sub);
|
||||||
cleanup_demux_stream(mpctx, STREAM_SUB);
|
|
||||||
mpctx->d_sub = NULL; // Note: not free'd.
|
mpctx->d_sub = NULL; // Note: not free'd.
|
||||||
mpctx->osd->dec_sub = NULL;
|
mpctx->osd->dec_sub = NULL;
|
||||||
reset_subtitles(mpctx);
|
reset_subtitles(mpctx);
|
||||||
|
reselect_demux_streams(mpctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mask & INITIALIZED_LIBASS) {
|
if (mask & INITIALIZED_LIBASS) {
|
||||||
@ -103,8 +103,8 @@ void uninit_player(struct MPContext *mpctx, unsigned int mask)
|
|||||||
if (mpctx->d_video)
|
if (mpctx->d_video)
|
||||||
video_uninit(mpctx->d_video);
|
video_uninit(mpctx->d_video);
|
||||||
mpctx->d_video = NULL;
|
mpctx->d_video = NULL;
|
||||||
cleanup_demux_stream(mpctx, STREAM_VIDEO);
|
|
||||||
mpctx->sync_audio_to_video = false;
|
mpctx->sync_audio_to_video = false;
|
||||||
|
reselect_demux_streams(mpctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mask & INITIALIZED_DEMUXER) {
|
if (mask & INITIALIZED_DEMUXER) {
|
||||||
@ -200,8 +200,7 @@ static void print_stream(struct MPContext *mpctx, struct track *t)
|
|||||||
tname = "Subs"; selopt = "sid"; langopt = "slang"; iid = "SID";
|
tname = "Subs"; selopt = "sid"; langopt = "slang"; iid = "SID";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
MP_INFO(mpctx, "[stream] %-5s %3s",
|
MP_INFO(mpctx, "[stream] %-5s %3s", tname, t->selected ? "(+)" : "");
|
||||||
tname, mpctx->current_track[t->type] == t ? "(+)" : "");
|
|
||||||
MP_INFO(mpctx, " --%s=%d", selopt, t->user_tid);
|
MP_INFO(mpctx, " --%s=%d", selopt, t->user_tid);
|
||||||
if (t->lang && langopt)
|
if (t->lang && langopt)
|
||||||
MP_INFO(mpctx, " --%s=%s", langopt, t->lang);
|
MP_INFO(mpctx, " --%s=%s", langopt, t->lang);
|
||||||
@ -260,52 +259,29 @@ static void print_file_properties(struct MPContext *mpctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sh_stream *init_demux_stream(struct MPContext *mpctx,
|
// Enable needed streams, disable others.
|
||||||
enum stream_type type)
|
// Note that switching all tracks at once (instead when initializing something)
|
||||||
|
// can be important, because reading from a demuxer stream (e.g. during init)
|
||||||
|
// will implicitly discard interleaved packets from unselected streams.
|
||||||
|
void reselect_demux_streams(struct MPContext *mpctx)
|
||||||
{
|
{
|
||||||
struct track *track = mpctx->current_track[type];
|
// Note: we assume that all demuxer streams are covered by the track list.
|
||||||
struct sh_stream *stream = track ? track->stream : NULL;
|
for (int t = 0; t < mpctx->num_tracks; t++) {
|
||||||
mpctx->sh[type] = stream;
|
struct track *track = mpctx->tracks[t];
|
||||||
if (stream) {
|
if (track->demuxer)
|
||||||
demuxer_switch_track(stream->demuxer, type, stream);
|
demuxer_select_track(track->demuxer, track->stream, track->selected);
|
||||||
if (track->is_external) {
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// External demuxers might need a seek to the current playback position.
|
||||||
|
// Also return the stream for convenience.
|
||||||
|
struct sh_stream *init_demux_stream(struct MPContext *mpctx, struct track *track)
|
||||||
|
{
|
||||||
|
if (track && track->demuxer && track->selected && track->is_external) {
|
||||||
double pts = get_main_demux_pts(mpctx);
|
double pts = get_main_demux_pts(mpctx);
|
||||||
demux_seek(stream->demuxer, pts, SEEK_ABSOLUTE);
|
demux_seek(track->demuxer, pts, SEEK_ABSOLUTE);
|
||||||
}
|
|
||||||
}
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
mpctx->sh[type] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Switch the demuxers to current track selection. This is possibly important
|
|
||||||
// for intialization: if something reads packets from the demuxer (like at least
|
|
||||||
// reinit_audio_chain does, or when seeking), packets from the other streams
|
|
||||||
// should be queued instead of discarded. So all streams should be enabled
|
|
||||||
// before the first initialization function is called.
|
|
||||||
static void preselect_demux_streams(struct MPContext *mpctx)
|
|
||||||
{
|
|
||||||
// Disable all streams, just to be sure no unwanted streams are selected.
|
|
||||||
for (int n = 0; n < mpctx->num_sources; n++) {
|
|
||||||
for (int type = 0; type < STREAM_TYPE_COUNT; type++) {
|
|
||||||
struct track *track = mpctx->current_track[type];
|
|
||||||
if (!(track && track->demuxer == mpctx->sources[n] &&
|
|
||||||
demuxer_stream_is_selected(track->demuxer, track->stream)))
|
|
||||||
demuxer_switch_track(mpctx->sources[n], type, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int type = 0; type < STREAM_TYPE_COUNT; type++) {
|
|
||||||
struct track *track = mpctx->current_track[type];
|
|
||||||
if (track && track->stream)
|
|
||||||
demuxer_switch_track(track->stream->demuxer, type, track->stream);
|
|
||||||
}
|
}
|
||||||
|
return track ? track->stream : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct sh_stream *select_fallback_stream(struct demuxer *d,
|
static struct sh_stream *select_fallback_stream(struct demuxer *d,
|
||||||
@ -359,7 +335,7 @@ bool timeline_set_part(struct MPContext *mpctx, int i, bool force)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
preselect_demux_streams(mpctx);
|
reselect_demux_streams(mpctx);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -416,9 +392,8 @@ static struct track *add_stream_track(struct MPContext *mpctx,
|
|||||||
track->stream = stream;
|
track->stream = stream;
|
||||||
track->demuxer_id = stream->demuxer_id;
|
track->demuxer_id = stream->demuxer_id;
|
||||||
// Initialize lazily selected track
|
// Initialize lazily selected track
|
||||||
bool selected = track == mpctx->current_track[STREAM_SUB];
|
demuxer_select_track(track->demuxer, stream, track->selected);
|
||||||
demuxer_select_track(track->demuxer, stream, selected);
|
if (track->selected)
|
||||||
if (selected)
|
|
||||||
reinit_subs(mpctx);
|
reinit_subs(mpctx);
|
||||||
return track;
|
return track;
|
||||||
}
|
}
|
||||||
@ -617,8 +592,18 @@ void mp_switch_track(struct MPContext *mpctx, enum stream_type type,
|
|||||||
uninit_player(mpctx, INITIALIZED_SUB);
|
uninit_player(mpctx, INITIALIZED_SUB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (current)
|
||||||
|
current->selected = false;
|
||||||
|
|
||||||
|
reselect_demux_streams(mpctx);
|
||||||
|
|
||||||
mpctx->current_track[type] = track;
|
mpctx->current_track[type] = track;
|
||||||
|
|
||||||
|
if (track)
|
||||||
|
track->selected = true;
|
||||||
|
|
||||||
|
reselect_demux_streams(mpctx);
|
||||||
|
|
||||||
int user_tid = track ? track->user_tid : -2;
|
int user_tid = track ? track->user_tid : -2;
|
||||||
if (type == STREAM_VIDEO) {
|
if (type == STREAM_VIDEO) {
|
||||||
mpctx->opts->video_id = user_tid;
|
mpctx->opts->video_id = user_tid;
|
||||||
@ -638,6 +623,12 @@ void mp_switch_track(struct MPContext *mpctx, enum stream_type type,
|
|||||||
mpctx->track_layout_hash = talloc_steal(mpctx, track_layout_hash(mpctx));
|
mpctx->track_layout_hash = talloc_steal(mpctx, track_layout_hash(mpctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mp_deselect_track(struct MPContext *mpctx, struct track *track)
|
||||||
|
{
|
||||||
|
if (track && track->selected)
|
||||||
|
mp_switch_track(mpctx, track->type, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
struct track *mp_track_by_tid(struct MPContext *mpctx, enum stream_type type,
|
struct track *mp_track_by_tid(struct MPContext *mpctx, enum stream_type type,
|
||||||
int tid)
|
int tid)
|
||||||
{
|
{
|
||||||
@ -658,11 +649,9 @@ bool mp_remove_track(struct MPContext *mpctx, struct track *track)
|
|||||||
if (!track->is_external)
|
if (!track->is_external)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (mpctx->current_track[track->type] == track) {
|
mp_deselect_track(mpctx, track);
|
||||||
mp_switch_track(mpctx, track->type, NULL);
|
if (track->selected)
|
||||||
if (mpctx->current_track[track->type] == track)
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
while (index < mpctx->num_tracks && mpctx->tracks[index] != track)
|
while (index < mpctx->num_tracks && mpctx->tracks[index] != track)
|
||||||
@ -1157,12 +1146,15 @@ goto_reopen_demuxer: ;
|
|||||||
mpctx->current_track[STREAM_SUB] =
|
mpctx->current_track[STREAM_SUB] =
|
||||||
select_track(mpctx, STREAM_SUB, mpctx->opts->sub_id,
|
select_track(mpctx, STREAM_SUB, mpctx->opts->sub_id,
|
||||||
mpctx->opts->sub_lang);
|
mpctx->opts->sub_lang);
|
||||||
|
for (int t = 0; t < mpctx->num_tracks; t++) {
|
||||||
|
struct track *track = mpctx->tracks[t];
|
||||||
|
track->selected = track == mpctx->current_track[track->type];
|
||||||
|
}
|
||||||
|
reselect_demux_streams(mpctx);
|
||||||
|
|
||||||
demux_info_print(mpctx->master_demuxer);
|
demux_info_print(mpctx->master_demuxer);
|
||||||
print_file_properties(mpctx);
|
print_file_properties(mpctx);
|
||||||
|
|
||||||
preselect_demux_streams(mpctx);
|
|
||||||
|
|
||||||
#if HAVE_ENCODING
|
#if HAVE_ENCODING
|
||||||
if (mpctx->encode_lavc_ctx && mpctx->current_track[STREAM_VIDEO])
|
if (mpctx->encode_lavc_ctx && mpctx->current_track[STREAM_VIDEO])
|
||||||
encode_lavc_expect_stream(mpctx->encode_lavc_ctx, AVMEDIA_TYPE_VIDEO);
|
encode_lavc_expect_stream(mpctx->encode_lavc_ctx, AVMEDIA_TYPE_VIDEO);
|
||||||
|
@ -301,9 +301,10 @@ static int mp_seek(MPContext *mpctx, struct seek_params seek,
|
|||||||
|
|
||||||
// If audio or demuxer subs come from different files, seek them too:
|
// If audio or demuxer subs come from different files, seek them too:
|
||||||
bool have_external_tracks = false;
|
bool have_external_tracks = false;
|
||||||
for (int type = 0; type < STREAM_TYPE_COUNT; type++) {
|
for (int t = 0; t < mpctx->num_tracks; t++) {
|
||||||
struct track *track = mpctx->current_track[type];
|
struct track *track = mpctx->tracks[t];
|
||||||
have_external_tracks |= track && track->is_external && track->demuxer;
|
have_external_tracks |= track->selected && track->is_external &&
|
||||||
|
track->demuxer;
|
||||||
}
|
}
|
||||||
if (have_external_tracks) {
|
if (have_external_tracks) {
|
||||||
double main_new_pos;
|
double main_new_pos;
|
||||||
@ -312,9 +313,9 @@ static int mp_seek(MPContext *mpctx, struct seek_params seek,
|
|||||||
} else {
|
} else {
|
||||||
main_new_pos = get_main_demux_pts(mpctx);
|
main_new_pos = get_main_demux_pts(mpctx);
|
||||||
}
|
}
|
||||||
for (int type = 0; type < STREAM_TYPE_COUNT; type++) {
|
for (int t = 0; t < mpctx->num_tracks; t++) {
|
||||||
struct track *track = mpctx->current_track[type];
|
struct track *track = mpctx->tracks[t];
|
||||||
if (track && track->is_external && track->demuxer)
|
if (track->selected && track->is_external && track->demuxer)
|
||||||
demux_seek(track->demuxer, main_new_pos, SEEK_ABSOLUTE);
|
demux_seek(track->demuxer, main_new_pos, SEEK_ABSOLUTE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1027,7 +1028,6 @@ void run_playloop(struct MPContext *mpctx)
|
|||||||
if (!opts->force_vo)
|
if (!opts->force_vo)
|
||||||
uninit |= INITIALIZED_VO;
|
uninit |= INITIALIZED_VO;
|
||||||
uninit_player(mpctx, uninit);
|
uninit_player(mpctx, uninit);
|
||||||
mpctx->current_track[STREAM_VIDEO] = NULL;
|
|
||||||
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;
|
||||||
|
10
player/sub.c
10
player/sub.c
@ -57,9 +57,10 @@ static bool is_interleaved(struct MPContext *mpctx, struct track *track)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
struct demuxer *demuxer = track->demuxer;
|
struct demuxer *demuxer = track->demuxer;
|
||||||
for (int type = 0; type < STREAM_TYPE_COUNT; type++) {
|
for (int t = 0; t < mpctx->num_tracks; t++) {
|
||||||
struct track *other = mpctx->current_track[type];
|
struct track *other = mpctx->tracks[t];
|
||||||
if (other && other != track && other->demuxer && other->demuxer == demuxer)
|
if (other != track && other->selected && other->demuxer == demuxer &&
|
||||||
|
(other->type == STREAM_VIDEO || other->type == STREAM_AUDIO))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -175,8 +176,7 @@ void reinit_subs(struct MPContext *mpctx)
|
|||||||
|
|
||||||
assert(!(mpctx->initialized_flags & INITIALIZED_SUB));
|
assert(!(mpctx->initialized_flags & INITIALIZED_SUB));
|
||||||
|
|
||||||
init_demux_stream(mpctx, STREAM_SUB);
|
struct sh_stream *sh = init_demux_stream(mpctx, track);
|
||||||
struct sh_stream *sh = mpctx->sh[STREAM_SUB];
|
|
||||||
|
|
||||||
// No track selected, or lazily added DVD track (will actually be created
|
// No track selected, or lazily added DVD track (will actually be created
|
||||||
// on first sub packet)
|
// on first sub packet)
|
||||||
|
@ -136,8 +136,8 @@ 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->initialized_flags & INITIALIZED_VCODEC));
|
||||||
assert(!mpctx->d_video);
|
assert(!mpctx->d_video);
|
||||||
init_demux_stream(mpctx, STREAM_VIDEO);
|
struct track *track = mpctx->current_track[STREAM_VIDEO];
|
||||||
struct sh_stream *sh = mpctx->sh[STREAM_VIDEO];
|
struct sh_stream *sh = init_demux_stream(mpctx, track);
|
||||||
if (!sh)
|
if (!sh)
|
||||||
goto no_video;
|
goto no_video;
|
||||||
|
|
||||||
@ -216,8 +216,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_player(mpctx, INITIALIZED_VCODEC | (opts->force_vo ? 0 : INITIALIZED_VO));
|
||||||
cleanup_demux_stream(mpctx, STREAM_VIDEO);
|
mp_deselect_track(mpctx, track);
|
||||||
mpctx->current_track[STREAM_VIDEO] = NULL;
|
|
||||||
handle_force_window(mpctx, true);
|
handle_force_window(mpctx, true);
|
||||||
MP_INFO(mpctx, "Video: no video\n");
|
MP_INFO(mpctx, "Video: no video\n");
|
||||||
return 0;
|
return 0;
|
||||||
@ -319,9 +318,11 @@ void video_execute_format_change(struct MPContext *mpctx)
|
|||||||
static int check_framedrop(struct MPContext *mpctx, double frame_time)
|
static int check_framedrop(struct MPContext *mpctx, double frame_time)
|
||||||
{
|
{
|
||||||
struct MPOpts *opts = mpctx->opts;
|
struct MPOpts *opts = mpctx->opts;
|
||||||
|
struct track *t_audio = mpctx->current_track[STREAM_AUDIO];
|
||||||
|
struct sh_stream *sh_audio = t_audio ? t_audio->stream : NULL;
|
||||||
// check for frame-drop:
|
// check for frame-drop:
|
||||||
if (mpctx->d_audio && !mpctx->ao->untimed &&
|
if (mpctx->d_audio && !mpctx->ao->untimed && sh_audio &&
|
||||||
!demux_stream_eof(mpctx->sh[STREAM_AUDIO]))
|
!demux_stream_eof(sh_audio))
|
||||||
{
|
{
|
||||||
float delay = opts->playback_speed * ao_get_delay(mpctx->ao);
|
float delay = opts->playback_speed * ao_get_delay(mpctx->ao);
|
||||||
float d = delay - mpctx->delay;
|
float d = delay - mpctx->delay;
|
||||||
|
Loading…
Reference in New Issue
Block a user