summaryrefslogtreecommitdiffstats
path: root/player/video.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2016-01-12 23:49:00 +0100
committerwm4 <wm4@nowhere>2016-01-12 23:49:00 +0100
commite420464ba693a5920d4dc172b3f7e9a0c725e3d4 (patch)
treee149445377e94da3274f7d3f588449ed24ece3c1 /player/video.c
parent6fc0fe4426c1b71630d281cbc9e0406f8ad7deee (diff)
downloadmpv-e420464ba693a5920d4dc172b3f7e9a0c725e3d4.tar.bz2
mpv-e420464ba693a5920d4dc172b3f7e9a0c725e3d4.tar.xz
player: simplify backstepping
Basically reimplement it. The old implementation was quite stupid, and was probably done this way because video filtering and output used to be way less decoupled. Now we can reimplement it in a very simple way: when backstepping, seek to current time, but keep the last frame that was supposed to be discarded when reaching the target time. When the seek finishes, prepend the saved frame to the video frame queue. A disadvantage is that the new implementation fails to skip over timeline boundaries (ordered chapters etc.), but this never worked properly anyway. It's possible that this will be fixed some time in the future.
Diffstat (limited to 'player/video.c')
-rw-r--r--player/video.c21
1 files changed, 14 insertions, 7 deletions
diff --git a/player/video.c b/player/video.c
index 28c6ac4d5c..33f3b4b970 100644
--- a/player/video.c
+++ b/player/video.c
@@ -310,7 +310,6 @@ int reinit_video_chain(struct MPContext *mpctx)
vo_set_paused(mpctx->video_out, mpctx->paused);
mpctx->sync_audio_to_video = !sh->attached_picture;
- mpctx->vo_pts_history_seek_ts++;
// If we switch on video again, ensure audio position matches up.
if (mpctx->d_audio)
@@ -603,7 +602,7 @@ static int get_req_frames(struct MPContext *mpctx, bool eof)
return mpctx->opts->video_sync == VS_DEFAULT ? 1 : 2;
int req = vo_get_num_req_frames(mpctx->video_out);
- return MPCLAMP(req, 2, MP_ARRAY_SIZE(mpctx->next_frames));
+ return MPCLAMP(req, 2, MP_ARRAY_SIZE(mpctx->next_frames) - 1);
}
// Whether it's fine to call add_new_frame() now.
@@ -615,7 +614,7 @@ static bool needs_new_frame(struct MPContext *mpctx)
// Queue a frame to mpctx->next_frames[]. Call only if needs_new_frame() signals ok.
static void add_new_frame(struct MPContext *mpctx, struct mp_image *frame)
{
- assert(needs_new_frame(mpctx));
+ assert(mpctx->num_next_frames < MP_ARRAY_SIZE(mpctx->next_frames));
assert(frame);
mpctx->next_frames[mpctx->num_next_frames++] = frame;
if (mpctx->num_next_frames == 1)
@@ -662,9 +661,6 @@ static int video_output_image(struct MPContext *mpctx, double endpts)
return r; // error
struct mp_image *img = vf_read_output_frame(mpctx->d_video->vfilter);
if (img) {
- // Always add these; they make backstepping after seeking faster.
- add_frame_pts(mpctx, img->pts);
-
if (endpts != MP_NOPTS_VALUE && img->pts >= endpts) {
r = VD_EOF;
} else if (mpctx->max_frames == 0) {
@@ -672,8 +668,19 @@ static int video_output_image(struct MPContext *mpctx, double endpts)
} else if (hrseek && mpctx->hrseek_lastframe) {
mp_image_setrefp(&mpctx->saved_frame, img);
} else if (hrseek && img->pts < mpctx->hrseek_pts - .005) {
- /* just skip */
+ /* just skip - but save if backstep active */
+ if (mpctx->hrseek_backstep)
+ mp_image_setrefp(&mpctx->saved_frame, img);
} else {
+ if (mpctx->hrseek_backstep) {
+ if (mpctx->saved_frame) {
+ add_new_frame(mpctx, mpctx->saved_frame);
+ mpctx->saved_frame = NULL;
+ } else {
+ MP_WARN(mpctx, "Backstep failed.\n");
+ }
+ mpctx->hrseek_backstep = false;
+ }
add_new_frame(mpctx, img);
img = NULL;
}