player: clamp relative seek base time to nominal duration

Since b74c09efbf, audio-only files let you seek to arbitrary points
beyond the end of the file (but still displayed the time clamped to the
nominal file duration). This was confusing and just not wanted. The
reason is probably that the commit removed setting the audio PTS for
data before the seek target, so if you seek past the end of the file,
the audio PTS is never set. This in turn means the logic to determine
the current playback time has no PTS at all, and thus falls back to the
seek PTS.

This happened in the past for other reasons (like efe43d768f). I have
enough of this, so I'm just changing the code to clamp the seek
timestamp to a "known" range. Do this when seeking ends, because in the
fallback case, the playback time shouldn't be stuck at e.g. "end +
seek_argument". Also do it when initiating a new seek (mp_seek), because
if the previous seek hasn't finished yet, it shouldn't add them up and
allow it to go "out of range" either. The latter is especially relevant
for hr-seeks.

Doing this clamping is problematic because the duration is a possibly
invalid value from the demuxer, or just missing. Especially with
timestamp resets, fun sometimes happens, and in these situations it
might be better not to clamp.

One could argue you should just use the last audio timestamp returned by
the decoder or demuxer (even if that directly conflicts with --end), but
that sounds even more hairy.

In summary: what a dumb waste of time, what the fuck.
This commit is contained in:
wm4 2020-09-10 23:24:35 +02:00
parent 78bbd62d3b
commit 09d3a4d39d
1 changed files with 7 additions and 1 deletions

View File

@ -261,7 +261,7 @@ static void mp_seek(MPContext *mpctx, struct seek_params seek)
return;
bool hr_seek_very_exact = seek.exact == MPSEEK_VERY_EXACT;
double current_time = get_current_time(mpctx);
double current_time = get_playback_time(mpctx);
if (current_time == MP_NOPTS_VALUE && seek.type == MPSEEK_RELATIVE)
return;
if (current_time == MP_NOPTS_VALUE)
@ -1150,6 +1150,12 @@ static void handle_playback_restart(struct MPContext *mpctx)
mpctx->playback_pts, mp_status_str(mpctx->audio_status),
mp_status_str(mpctx->video_status));
// To avoid strange effects when using relative seeks, especially if
// there are no proper audio & video timestamps (seeks after EOF).
double length = get_time_length(mpctx);
if (mpctx->last_seek_pts != MP_NOPTS_VALUE && length >= 0)
mpctx->last_seek_pts = MPCLAMP(mpctx->last_seek_pts, 0, length);
// Continuous seeks past EOF => treat as EOF instead of repeating seek.
if (mpctx->seek.type == MPSEEK_RELATIVE && mpctx->seek.amount > 0 &&
mpctx->video_status == STATUS_EOF &&