summaryrefslogtreecommitdiffstats
path: root/player/playloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'player/playloop.c')
-rw-r--r--player/playloop.c116
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);