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.)
This commit is contained in:
wm4 2019-05-27 02:12:26 +02:00
parent c7269e4e84
commit a11aad4964
1 changed files with 9 additions and 4 deletions

View File

@ -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);
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;
}
}