From a11aad4964234ddb62d00678fdf241ab80983cbe Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 27 May 2019 02:12:26 +0200 Subject: [PATCH] player: partially fix seek_to_last_frame in backward mode Another shitty obscure feature that usually nobody notices. Unsurprisingly, it doesn't go well with backward playback mode. If you use --keep-open in forward playback mode, and seek past the end of the file, it tries to seek to the very last frame. The demuxer will seek to the last "keyframe" before the end (i.e. some frames to go in most cases), and trying to hr-seek to the file duration often won't cut it, so this requires some special code. The function at hand seeks "close" to the end, and then stops hr-seek when the last frame us encountered (simple enough and very effective). In backward playback mode, start and end are reversed, and we need to seek "close" to the start of the file instead. Simple enough to do, and it works. One problem is that command.c has some weird logic to make going beyond the last chapter either end playback (--keep-open=no), or jump to the last frame. Now this will jump to the first frame, which is weird, but let's ignore this. Another problem is that seeking before playback start position hits EOF in backward playback mode, which is a demuxer bug, and has nothing to do with this code. But it triggers this code, so seeking before the start will show the "last" frame. (My description is a mess with directions. Figure it out yourself.) --- player/playloop.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/player/playloop.c b/player/playloop.c index 30c1bbb5d6..c415e5a90d 100644 --- a/player/playloop.c +++ b/player/playloop.c @@ -864,9 +864,14 @@ void seek_to_last_frame(struct MPContext *mpctx) MP_VERBOSE(mpctx, "seeking to last frame...\n"); // Approximately seek close to the end of the file. // Usually, it will seek some seconds before end. - double end = get_play_end_pts(mpctx); - if (end == MP_NOPTS_VALUE) - end = get_time_length(mpctx); + double end = MP_NOPTS_VALUE; + if (mpctx->play_dir > 0) { + end = get_play_end_pts(mpctx); + if (end == MP_NOPTS_VALUE) + end = get_time_length(mpctx); + } else { + end = get_start_time(mpctx, 1); + } mp_seek(mpctx, (struct seek_params){ .type = MPSEEK_ABSOLUTE, .amount = end, @@ -874,7 +879,7 @@ void seek_to_last_frame(struct MPContext *mpctx) }); // Make it exact: stop seek only if last frame was reached. if (mpctx->hrseek_active) { - mpctx->hrseek_pts = INFINITY; + mpctx->hrseek_pts = INFINITY * mpctx->play_dir; mpctx->hrseek_lastframe = true; } }