diff options
Diffstat (limited to 'player/playloop.c')
-rw-r--r-- | player/playloop.c | 116 |
1 files changed, 18 insertions, 98 deletions
diff --git a/player/playloop.c b/player/playloop.c index 4d3e70b4f7..5226103733 100644 --- a/player/playloop.c +++ b/player/playloop.c @@ -133,9 +133,8 @@ void add_step_frame(struct MPContext *mpctx, int dir) mpctx->step_frames += 1; unpause_player(mpctx); } else if (dir < 0) { - if (!mpctx->backstep_active && !mpctx->hrseek_active) { - mpctx->backstep_active = true; - mpctx->backstep_start_seek_ts = mpctx->vo_pts_history_seek_ts; + if (!mpctx->hrseek_backstep || !mpctx->hrseek_active) { + queue_seek(mpctx, MPSEEK_BACKSTEP, 0, MPSEEK_VERY_EXACT, true); pause_player(mpctx); } } @@ -151,6 +150,7 @@ void reset_playback_state(struct MPContext *mpctx) mpctx->hrseek_active = false; mpctx->hrseek_framedrop = false; mpctx->hrseek_lastframe = false; + mpctx->hrseek_backstep = false; mpctx->playback_pts = MP_NOPTS_VALUE; mpctx->last_seek_pts = MP_NOPTS_VALUE; mpctx->cache_wait_time = 0; @@ -167,7 +167,6 @@ static int mp_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; int prev_step = mpctx->step_frames; if (!mpctx->demuxer) @@ -192,11 +191,20 @@ static int mp_seek(MPContext *mpctx, struct seek_params seek, double target_time = MP_NOPTS_VALUE; int direction = 0; + bool backstep = false; switch (seek.type) { case MPSEEK_ABSOLUTE: target_time = seek.amount; break; + case MPSEEK_BACKSTEP: + seek.type = MPSEEK_ABSOLUTE; + seek.amount = get_current_time(mpctx); + if (seek.amount == MP_NOPTS_VALUE) + seek.amount = 0; + target_time = seek.amount; + backstep = true; + break; case MPSEEK_RELATIVE: direction = seek.amount > 0 ? 1 : -1; double cur = get_current_time(mpctx); @@ -272,14 +280,8 @@ static int mp_seek(MPContext *mpctx, struct seek_params seek, reset_playback_state(mpctx); - if (timeline_fallthrough) { - // Important if video reinit happens. - mpctx->vo_pts_history_seek_ts = prev_seek_ts; + if (timeline_fallthrough) mpctx->step_frames = prev_step; - } 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 */ @@ -294,11 +296,13 @@ static int mp_seek(MPContext *mpctx, struct seek_params seek, if (hr_seek || mpctx->timeline) { mpctx->hrseek_active = true; mpctx->hrseek_framedrop = !hr_seek_very_exact && opts->hr_seek_framedrop; + mpctx->hrseek_backstep = backstep; mpctx->hrseek_pts = hr_seek ? seek.amount : mpctx->timeline[mpctx->timeline_part].start; - MP_VERBOSE(mpctx, "hr-seek, skipping to %f%s\n", mpctx->hrseek_pts, - mpctx->hrseek_framedrop ? "" : " (no framedrop)"); + MP_VERBOSE(mpctx, "hr-seek, skipping to %f%s%s\n", mpctx->hrseek_pts, + mpctx->hrseek_framedrop ? "" : " (no framedrop)", + mpctx->hrseek_backstep ? " (backstep)" : ""); } mpctx->start_timestamp = mp_time_sec(); @@ -334,6 +338,7 @@ void queue_seek(struct MPContext *mpctx, enum seek_type type, double amount, return; case MPSEEK_ABSOLUTE: case MPSEEK_FACTOR: + case MPSEEK_BACKSTEP: *seek = (struct seek_params) { .type = type, .amount = amount, @@ -670,89 +675,6 @@ static void handle_vo_events(struct MPContext *mpctx) mp_notify(mpctx, MP_EVENT_WIN_STATE, NULL); } -void add_frame_pts(struct MPContext *mpctx, double pts) -{ - if (pts == MP_NOPTS_VALUE || mpctx->hrseek_framedrop) { - mpctx->vo_pts_history_seek_ts++; // mark discontinuity - return; - } - if (mpctx->vo_pts_history_pts[0] == pts) // may be called multiple times - return; - for (int n = MAX_NUM_VO_PTS - 1; n >= 1; n--) { - mpctx->vo_pts_history_seek[n] = mpctx->vo_pts_history_seek[n - 1]; - mpctx->vo_pts_history_pts[n] = mpctx->vo_pts_history_pts[n - 1]; - } - mpctx->vo_pts_history_seek[0] = mpctx->vo_pts_history_seek_ts; - mpctx->vo_pts_history_pts[0] = pts; -} - -static double find_previous_pts(struct MPContext *mpctx, double pts) -{ - for (int n = 0; n < MAX_NUM_VO_PTS - 1; n++) { - if (pts == mpctx->vo_pts_history_pts[n] && - mpctx->vo_pts_history_seek[n] != 0 && - mpctx->vo_pts_history_seek[n] == mpctx->vo_pts_history_seek[n + 1]) - { - return mpctx->vo_pts_history_pts[n + 1]; - } - } - return MP_NOPTS_VALUE; -} - -static double get_last_frame_pts(struct MPContext *mpctx) -{ - if (mpctx->vo_pts_history_seek[0] == mpctx->vo_pts_history_seek_ts) - return mpctx->vo_pts_history_pts[0]; - return MP_NOPTS_VALUE; -} - -static void handle_backstep(struct MPContext *mpctx) -{ - if (!mpctx->backstep_active) - return; - - double current_pts = mpctx->last_vo_pts; - mpctx->backstep_active = false; - if (mpctx->d_video && current_pts != MP_NOPTS_VALUE) { - double seek_pts = find_previous_pts(mpctx, current_pts); - if (seek_pts != MP_NOPTS_VALUE) { - queue_seek(mpctx, MPSEEK_ABSOLUTE, seek_pts, MPSEEK_VERY_EXACT, true); - } else { - double last = get_last_frame_pts(mpctx); - if (last != MP_NOPTS_VALUE && last >= current_pts && - mpctx->backstep_start_seek_ts != mpctx->vo_pts_history_seek_ts) - { - MP_ERR(mpctx, "Backstep failed.\n"); - queue_seek(mpctx, MPSEEK_ABSOLUTE, current_pts, - MPSEEK_VERY_EXACT, true); - } else if (!mpctx->hrseek_active) { - MP_VERBOSE(mpctx, "Start backstep indexing.\n"); - // Force it to index the video up until current_pts. - // The whole point is getting frames _before_ that PTS, - // so apply an arbitrary offset. (In theory the offset - // has to be large enough to reach the previous frame.) - mp_seek(mpctx, (struct seek_params){ - .type = MPSEEK_ABSOLUTE, - .amount = current_pts - 1.0, - }, false); - // Don't leave hr-seek mode. If all goes right, hr-seek - // mode is cancelled as soon as the frame before - // current_pts is found during hr-seeking. - // Note that current_pts should be part of the index, - // otherwise we can't find the previous frame, so set the - // seek target an arbitrary amount of time after it. - if (mpctx->hrseek_active) { - mpctx->hrseek_pts = current_pts + 10.0; - mpctx->hrseek_framedrop = false; - mpctx->backstep_active = true; - } - } else { - mpctx->backstep_active = true; - } - } - } -} - static void handle_sstep(struct MPContext *mpctx) { struct MPOpts *opts = mpctx->opts; @@ -1061,8 +983,6 @@ void run_playloop(struct MPContext *mpctx) mp_process_input(mpctx); - handle_backstep(mpctx); - handle_chapter_change(mpctx); handle_force_window(mpctx, false); |