mirror of
https://github.com/mpv-player/mpv
synced 2025-03-21 02:41:13 +00:00
player: make refresh seeks slightly more robust
Refresh seeks are automatically issued when changing filters, which improves user experience if these filters change buffering or such. The refresh seek could actually overwrite a previously ongoing seek: set pause yes set time-pos 10 set vf "" Here, the video code issued a refresh seek to the previous video position, which could be different from the previously triggered (and still ongoing) seek, this overwriting the seek. Factor all refresh seek handling into a new function, and make it handle ongoing seeks correctly. Remove the weird new canonical_pts field, which actually had no use. Fixes #4757.
This commit is contained in:
parent
b6d79deebb
commit
68201f4591
@ -279,12 +279,8 @@ int reinit_audio_filters(struct MPContext *mpctx)
|
||||
|
||||
// Only force refresh if the amount of dropped buffered data is going to
|
||||
// cause "issues" for the A/V sync logic.
|
||||
if (mpctx->audio_status == STATUS_PLAYING &&
|
||||
mpctx->playback_pts != MP_NOPTS_VALUE && delay > 0.2)
|
||||
{
|
||||
queue_seek(mpctx, MPSEEK_ABSOLUTE, mpctx->playback_pts,
|
||||
MPSEEK_EXACT, 0);
|
||||
}
|
||||
if (mpctx->audio_status == STATUS_PLAYING && delay > 0.2)
|
||||
issue_refresh_seek(mpctx, MPSEEK_EXACT);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -73,8 +73,8 @@ enum seek_type {
|
||||
};
|
||||
|
||||
enum seek_precision {
|
||||
MPSEEK_DEFAULT = 0,
|
||||
// The following values are numerically sorted by increasing precision
|
||||
MPSEEK_DEFAULT = 0,
|
||||
MPSEEK_KEYFRAME,
|
||||
MPSEEK_EXACT,
|
||||
MPSEEK_VERY_EXACT,
|
||||
@ -85,6 +85,13 @@ enum seek_flags {
|
||||
MPSEEK_FLAG_NOFLUSH = 1 << 1, // keeping remaining data for seamless loops
|
||||
};
|
||||
|
||||
struct seek_params {
|
||||
enum seek_type type;
|
||||
enum seek_precision exact;
|
||||
double amount;
|
||||
unsigned flags; // MPSEEK_FLAG_*
|
||||
};
|
||||
|
||||
enum video_sync {
|
||||
VS_DEFAULT = 0,
|
||||
VS_DISP_RESAMPLE,
|
||||
@ -339,6 +346,7 @@ typedef struct MPContext {
|
||||
bool hrseek_lastframe; // drop everything until last frame reached
|
||||
bool hrseek_backstep; // go to frame before seek target
|
||||
double hrseek_pts;
|
||||
struct seek_params current_seek;
|
||||
bool ab_loop_clip; // clip to the "b" part of an A-B loop if available
|
||||
// AV sync: the next frame should be shown when the audio out has this
|
||||
// much (in seconds) buffered data left. Increased when more data is
|
||||
@ -367,8 +375,6 @@ typedef struct MPContext {
|
||||
double last_frame_duration;
|
||||
// Video PTS, or audio PTS if video has ended.
|
||||
double playback_pts;
|
||||
// Last known "good" PTS
|
||||
double canonical_pts;
|
||||
// audio stats only
|
||||
int64_t audio_stat_start;
|
||||
double written_audio;
|
||||
@ -398,13 +404,7 @@ typedef struct MPContext {
|
||||
// Used to turn a new time value to a delta from last time.
|
||||
int64_t last_time;
|
||||
|
||||
// Used to communicate the parameters of a seek between parts
|
||||
struct seek_params {
|
||||
enum seek_type type;
|
||||
enum seek_precision exact;
|
||||
double amount;
|
||||
unsigned flags; // MPSEEK_FLAG_*
|
||||
} seek;
|
||||
struct seek_params seek;
|
||||
|
||||
// Allow audio to issue a second seek if audio is too far ahead (for non-hr
|
||||
// seeks with external audio tracks).
|
||||
@ -532,6 +532,7 @@ struct MPContext *mp_create(void);
|
||||
void mp_destroy(struct MPContext *mpctx);
|
||||
void mp_print_version(struct mp_log *log, int always);
|
||||
void mp_update_logging(struct MPContext *mpctx, bool preinit);
|
||||
void issue_refresh_seek(struct MPContext *mpctx, enum seek_precision min_prec);
|
||||
|
||||
// misc.c
|
||||
double rel_time_to_abs(struct MPContext *mpctx, struct m_rel_time t);
|
||||
|
@ -1127,13 +1127,8 @@ done:
|
||||
void update_lavfi_complex(struct MPContext *mpctx)
|
||||
{
|
||||
if (mpctx->playback_initialized) {
|
||||
if (reinit_complex_filters(mpctx, false) != 0 &&
|
||||
mpctx->canonical_pts != MP_NOPTS_VALUE)
|
||||
{
|
||||
// Refresh seek to avoid weird situations.
|
||||
queue_seek(mpctx, MPSEEK_ABSOLUTE, mpctx->canonical_pts,
|
||||
MPSEEK_EXACT, 0);
|
||||
}
|
||||
if (reinit_complex_filters(mpctx, false) != 0)
|
||||
issue_refresh_seek(mpctx, MPSEEK_EXACT);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1166,7 +1161,6 @@ static void play_current_file(struct MPContext *mpctx)
|
||||
mpctx->speed_factor_a = mpctx->speed_factor_v = 1.0;
|
||||
mpctx->display_sync_error = 0.0;
|
||||
mpctx->display_sync_active = false;
|
||||
mpctx->canonical_pts = MP_NOPTS_VALUE;
|
||||
mpctx->seek = (struct seek_params){ 0 };
|
||||
|
||||
reset_playback_state(mpctx);
|
||||
|
@ -111,6 +111,25 @@ double get_track_seek_offset(struct MPContext *mpctx, struct track *track)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void issue_refresh_seek(struct MPContext *mpctx, enum seek_precision min_prec)
|
||||
{
|
||||
// let queued seeks execute at a slightly later point
|
||||
if (mpctx->seek.type) {
|
||||
mp_wakeup_core(mpctx);
|
||||
return;
|
||||
}
|
||||
// repeat currently ongoing seeks
|
||||
if (mpctx->current_seek.type) {
|
||||
mpctx->seek = mpctx->current_seek;
|
||||
mp_wakeup_core(mpctx);
|
||||
return;
|
||||
}
|
||||
// maybe happens when changing filters while file is loaded - ignore for now
|
||||
if (mpctx->playback_pts == MP_NOPTS_VALUE)
|
||||
return;
|
||||
queue_seek(mpctx, MPSEEK_ABSOLUTE, mpctx->playback_pts, min_prec, 0);
|
||||
}
|
||||
|
||||
float mp_get_cache_percent(struct MPContext *mpctx)
|
||||
{
|
||||
struct stream_cache_info info = {0};
|
||||
|
@ -232,6 +232,7 @@ void reset_playback_state(struct MPContext *mpctx)
|
||||
mpctx->hrseek_framedrop = false;
|
||||
mpctx->hrseek_lastframe = false;
|
||||
mpctx->hrseek_backstep = false;
|
||||
mpctx->current_seek = (struct seek_params){0};
|
||||
mpctx->playback_pts = MP_NOPTS_VALUE;
|
||||
mpctx->last_seek_pts = MP_NOPTS_VALUE;
|
||||
mpctx->cache_wait_time = 0;
|
||||
@ -377,7 +378,7 @@ static void mp_seek(MPContext *mpctx, struct seek_params seek)
|
||||
|
||||
mpctx->ab_loop_clip = mpctx->last_seek_pts < opts->ab_loop[1];
|
||||
|
||||
mpctx->canonical_pts = mpctx->last_seek_pts;
|
||||
mpctx->current_seek = seek;
|
||||
}
|
||||
|
||||
// This combines consecutive seek requests.
|
||||
@ -958,8 +959,6 @@ static void handle_playback_time(struct MPContext *mpctx)
|
||||
{
|
||||
mpctx->playback_pts = playing_audio_pts(mpctx);
|
||||
}
|
||||
if (mpctx->playback_pts != MP_NOPTS_VALUE)
|
||||
mpctx->canonical_pts = mpctx->playback_pts;
|
||||
}
|
||||
|
||||
// We always make sure audio and video buffers are filled before actually
|
||||
@ -993,6 +992,7 @@ static void handle_playback_restart(struct MPContext *mpctx)
|
||||
if (!mpctx->restart_complete) {
|
||||
mpctx->hrseek_active = false;
|
||||
mpctx->restart_complete = true;
|
||||
mpctx->current_seek = (struct seek_params){0};
|
||||
mpctx->audio_allow_second_chance_seek = false;
|
||||
handle_playback_time(mpctx);
|
||||
mp_notify(mpctx, MPV_EVENT_PLAYBACK_RESTART, NULL);
|
||||
|
@ -551,13 +551,10 @@ void mp_force_video_refresh(struct MPContext *mpctx)
|
||||
return;
|
||||
|
||||
// If not paused, the next frame should come soon enough.
|
||||
if ((opts->pause || mpctx->time_frame >= 0.5) &&
|
||||
(mpctx->video_status >= STATUS_PLAYING ||
|
||||
mpctx->video_status <= STATUS_DRAINING) &&
|
||||
mpctx->last_vo_pts != MP_NOPTS_VALUE)
|
||||
if (opts->pause || mpctx->time_frame >= 0.5 ||
|
||||
mpctx->video_status == STATUS_EOF)
|
||||
{
|
||||
queue_seek(mpctx, MPSEEK_ABSOLUTE, mpctx->last_vo_pts,
|
||||
MPSEEK_VERY_EXACT, 0);
|
||||
issue_refresh_seek(mpctx, MPSEEK_VERY_EXACT);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user