From 862d7d8a1a852fc6bb6dd13ca5db90f83b676579 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 29 Jul 2014 17:55:28 +0200 Subject: player: fix desync when seeking and switching external tracks If you for example use --audio-file, disable the external track, seek, and enable the external track again, the playback position of the external file was off, and you would get major A/V desync. This was actually supposed to work, but broke at some time ago (probably commit 2b87415f). It didn't work, because it attempted to seek the stream if it was already selected, which was always true due to reselect_demux_streams() being called before that. Fix by putting the initial selection and the seek together. --- player/loadfile.c | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) (limited to 'player/loadfile.c') diff --git a/player/loadfile.c b/player/loadfile.c index 657e50f6da..6c89057432 100644 --- a/player/loadfile.c +++ b/player/loadfile.c @@ -60,6 +60,8 @@ #include "command.h" #include "libmpv/client.h" +static void reselect_demux_streams(struct MPContext *mpctx); + static void uninit_sub(struct MPContext *mpctx, int order) { if (mpctx->d_sub[order]) @@ -264,41 +266,41 @@ void update_demuxer_properties(struct MPContext *mpctx) demuxer->events = 0; } +static bool need_init_seek(struct demuxer *demux) +{ + for (int n = 0; n < demux->num_streams; n++) { + struct sh_stream *stream = demux->streams[n]; + // Subtitle streams are not properly interleaved -> force init. seek. + if (stream->type != STREAM_SUB && demux_stream_is_selected(stream)) + return false; + } + return true; +} + // Enable needed streams, disable others. // 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) +// Also initializes position for external streams. +static 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++) { struct track *track = mpctx->tracks[t]; - if (track->demuxer && track->stream) + if (track->demuxer && track->stream) { + bool need_init = track->selected && + mpctx->demuxer != track->demuxer && + need_init_seek(track->demuxer); demuxer_select_track(track->demuxer, track->stream, track->selected); - } -} - -// External demuxers might need a seek to the current playback position. -static void external_track_seek(struct MPContext *mpctx, struct track *track) -{ - if (track && track->demuxer && track->selected && track->is_external) { - for (int t = 0; t < mpctx->num_tracks; t++) { - struct track *other = mpctx->tracks[t]; - if (other->demuxer == track->demuxer && - demux_stream_is_selected(other->stream)) - return; + if (need_init) { + double pts = get_main_demux_pts(mpctx); + if (pts != MP_NOPTS_VALUE) + demux_seek(track->demuxer, pts, SEEK_ABSOLUTE); + } } - double pts = get_main_demux_pts(mpctx); - demux_seek(track->demuxer, pts, SEEK_ABSOLUTE); } } -struct sh_stream *init_demux_stream(struct MPContext *mpctx, struct track *track) -{ - external_track_seek(mpctx, track); - return track ? track->stream : NULL; -} - static struct sh_stream *select_fallback_stream(struct demuxer *d, enum stream_type type, int index) -- cgit v1.2.3