mirror of
https://github.com/mpv-player/mpv
synced 2024-12-27 01:22:30 +00:00
core: fix backstepping with ordered chapters
There were two problems. First, frames past the end of the current segment were added to the index, which messed up backstepping. Check for the endpts before added a frame to the index. Second, it wasn't possible to step over segments which change the file. Changing a file causes decoder reinitialization, which (rightfully) is treated as discontinuity (and vo_pts_history_seek_ts was changed). Add some extra code to pretend that a segment-switching seek/reinit does not introduce discontinuities. There's still a weird corner case: sometimes, you can frame step forward on the last frame of a segment without reaching the next segment immediately. This is because the playloop switches into audio-only mode. The segment is switched when both audio and video have ended, so the frame stepping will play random sized chunks of audio until the segment will be switched. This gives the impression that backstepping doesn't work perfectly, even though it's the other way around and frame stepping behaves weird. This is a consequence of wanting to make frame stepping work with audio, and is not really a bug.
This commit is contained in:
parent
55262a4427
commit
9d9d6517d2
@ -2549,7 +2549,7 @@ static void determine_frame_pts(struct MPContext *mpctx)
|
||||
sh_video->codec_reordered_pts : sh_video->sorted_pts;
|
||||
}
|
||||
|
||||
static double update_video(struct MPContext *mpctx)
|
||||
static double update_video(struct MPContext *mpctx, double endpts)
|
||||
{
|
||||
struct sh_video *sh_video = mpctx->sh_video;
|
||||
struct vo *video_out = mpctx->video_out;
|
||||
@ -2606,7 +2606,8 @@ static double update_video(struct MPContext *mpctx)
|
||||
if (pts == MP_NOPTS_VALUE)
|
||||
pts = sh_video->last_pts;
|
||||
}
|
||||
add_frame_pts(mpctx, pts);
|
||||
if (endpts != MP_NOPTS_VALUE && pts < endpts)
|
||||
add_frame_pts(mpctx, pts);
|
||||
if (mpctx->hrseek_active && pts < mpctx->hrseek_pts - .005) {
|
||||
vo_skip_frame(video_out);
|
||||
return 0;
|
||||
@ -2745,8 +2746,6 @@ static void seek_reset(struct MPContext *mpctx, bool reset_ao, bool reset_ac)
|
||||
mpctx->drop_frame_cnt = 0;
|
||||
mpctx->dropped_frames = 0;
|
||||
mpctx->playback_pts = MP_NOPTS_VALUE;
|
||||
mpctx->vo_pts_history_seek_ts++;
|
||||
mpctx->backstep_active = false;
|
||||
|
||||
#ifdef CONFIG_ENCODING
|
||||
encode_lavc_discontinuity(mpctx->encode_lavc_ctx);
|
||||
@ -2809,6 +2808,7 @@ static int seek(MPContext *mpctx, struct seek_params seek,
|
||||
bool timeline_fallthrough)
|
||||
{
|
||||
struct MPOpts *opts = &mpctx->opts;
|
||||
uint64_t prev_seek_ts = mpctx->vo_pts_history_seek_ts;
|
||||
|
||||
if (!mpctx->demuxer)
|
||||
return -1;
|
||||
@ -2915,6 +2915,14 @@ static int seek(MPContext *mpctx, struct seek_params seek,
|
||||
* and resetting could lose audio some decoders produce during init. */
|
||||
seek_reset(mpctx, !timeline_fallthrough, !need_reset);
|
||||
|
||||
if (timeline_fallthrough) {
|
||||
// Important if video reinit happens.
|
||||
mpctx->vo_pts_history_seek_ts = prev_seek_ts;
|
||||
} else {
|
||||
mpctx->vo_pts_history_seek_ts++;
|
||||
mpctx->backstep_active = false;
|
||||
}
|
||||
|
||||
/* Use the target time as "current position" for further relative
|
||||
* seeks etc until a new video frame has been decoded */
|
||||
if (seek.type == MPSEEK_ABSOLUTE) {
|
||||
@ -3266,7 +3274,7 @@ static void run_playloop(struct MPContext *mpctx)
|
||||
|
||||
video_left = vo->hasframe || vo->frame_loaded;
|
||||
if (!vo->frame_loaded && (!mpctx->paused || mpctx->restart_playback)) {
|
||||
double frame_time = update_video(mpctx);
|
||||
double frame_time = update_video(mpctx, endpts);
|
||||
mp_dbg(MSGT_AVSYNC, MSGL_DBG2, "*** ftime=%5.3f ***\n", frame_time);
|
||||
if (mpctx->sh_video->vf_initialized < 0) {
|
||||
mp_tmsg(MSGT_CPLAYER, MSGL_FATAL,
|
||||
|
Loading…
Reference in New Issue
Block a user