summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--player/audio.c22
-rw-r--r--player/core.h4
-rw-r--r--player/playloop.c4
3 files changed, 30 insertions, 0 deletions
diff --git a/player/audio.c b/player/audio.c
index fd007fedf7..e186a375b6 100644
--- a/player/audio.c
+++ b/player/audio.c
@@ -268,6 +268,7 @@ void reset_audio_state(struct MPContext *mpctx)
mpctx->delay = 0;
mpctx->audio_drop_throttle = 0;
mpctx->audio_stat_start = 0;
+ mpctx->audio_allow_second_chance_seek = false;
}
void uninit_audio_out(struct MPContext *mpctx)
@@ -688,6 +689,27 @@ static bool get_sync_samples(struct MPContext *mpctx, int *skip)
}
ptsdiff = MPCLAMP(ptsdiff, -3600, 3600);
+ // Heuristic: if audio is "too far" ahead, and one of them is a separate
+ // track, allow a refresh seek to the correct position to fix it.
+ if (ptsdiff > 0.2 && mpctx->audio_allow_second_chance_seek && sync_to_video) {
+ struct ao_chain *ao_c = mpctx->ao_chain;
+ if (ao_c && ao_c->track && mpctx->vo_chain && mpctx->vo_chain->track &&
+ ao_c->track->demuxer != mpctx->vo_chain->track->demuxer)
+ {
+ struct track *track = ao_c->track;
+ double pts = mpctx->video_pts;
+ if (pts != MP_NOPTS_VALUE)
+ pts += get_track_seek_offset(mpctx, track);
+ // (disable it first to make it take any effect)
+ demuxer_select_track(track->demuxer, track->stream, pts, false);
+ demuxer_select_track(track->demuxer, track->stream, pts, true);
+ reset_audio_state(mpctx);
+ MP_VERBOSE(mpctx, "retrying audio seek\n");
+ return false;
+ }
+ }
+ mpctx->audio_allow_second_chance_seek = false;
+
int align = af_format_sample_alignment(out_format.format);
*skip = (int)(-ptsdiff * play_samplerate) / align * align;
return true;
diff --git a/player/core.h b/player/core.h
index 1dc6da7331..70570fccb3 100644
--- a/player/core.h
+++ b/player/core.h
@@ -382,6 +382,10 @@ typedef struct MPContext {
bool immediate; // disable seek delay logic
} seek;
+ // Allow audio to issue a second seek if audio is too far ahead (for non-hr
+ // seeks with external audio tracks).
+ bool audio_allow_second_chance_seek;
+
/* Heuristic for relative chapter seeks: keep track which chapter
* the user wanted to go to, even if we aren't exactly within the
* boundaries of that chapter due to an inaccurate seek. */
diff --git a/player/playloop.c b/player/playloop.c
index da3e995975..9b15ac3f50 100644
--- a/player/playloop.c
+++ b/player/playloop.c
@@ -298,6 +298,9 @@ static void mp_seek(MPContext *mpctx, struct seek_params seek)
mp_notify(mpctx, MPV_EVENT_SEEK, NULL);
mp_notify(mpctx, MPV_EVENT_TICK, NULL);
+
+ mpctx->audio_allow_second_chance_seek =
+ !hr_seek && !(demux_flags & SEEK_FORWARD);
}
// This combines consecutive seek requests.
@@ -889,6 +892,7 @@ static void handle_playback_restart(struct MPContext *mpctx)
if (!mpctx->restart_complete) {
mpctx->hrseek_active = false;
mpctx->restart_complete = true;
+ mpctx->audio_allow_second_chance_seek = false;
mp_notify(mpctx, MPV_EVENT_PLAYBACK_RESTART, NULL);
if (!mpctx->playing_msg_shown) {
if (opts->playing_msg && opts->playing_msg[0]) {