summaryrefslogtreecommitdiffstats
path: root/player/loadfile.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-07-29 17:55:28 +0200
committerwm4 <wm4@nowhere>2014-07-29 17:55:28 +0200
commit862d7d8a1a852fc6bb6dd13ca5db90f83b676579 (patch)
tree1872938f935623b207cc9fd03ac3fa2e33176d41 /player/loadfile.c
parent6d15c491b063736d6915e74a9134d1cabde9a663 (diff)
downloadmpv-862d7d8a1a852fc6bb6dd13ca5db90f83b676579.tar.bz2
mpv-862d7d8a1a852fc6bb6dd13ca5db90f83b676579.tar.xz
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.
Diffstat (limited to 'player/loadfile.c')
-rw-r--r--player/loadfile.c46
1 files changed, 24 insertions, 22 deletions
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)