1
0
mirror of https://github.com/mpv-player/mpv synced 2025-03-19 01:47:38 +00:00

playloop: don't read playback pos from byte stream

If a file format supports PTS resets, get_current_pos_ratio calculates
the ratio using the stored filepos in the demuxer struct instead of a
standard query of the current time in the stream and its total length.
This seems like a reasonable way to avoid weird PTS values, but in
reality this just causes problems and results in inaccurate ratio
values that can affect other parts of the player (most notably the osc
seekbar).

For libavformat formats, demux->filepos is obtained from the
demux_lavf_fill_buffer function which is called on the next packet. The
problem is that there is a slight delay between packets and in some
cases, this delay can be relatively large. That means the obtained
demuxer->filepos value will be very inaccurate since it obtains the pos
from the end of the upcoming packet and not its actual current position.

This is especially noticeable at the very beginning of playback where
get_current_pos_ratio sometimes returns a value of well over 2% despite
less than a second passing in the stream. Another telltale sign is to
simply watch the osc seekbar as a stream progresses and observe how it
loads in staggered steps as every packet is decoded. In contrast, the
seekbar progresses smoothly on the playback of a format that does not
support PTS resets. The simple solution is to instead use the query of
the current time and length of a stream and calculate the ratio that
way.

get_current_pos_ratio will still fallback on using the byte stream
position if the previous queries fail. However, get_current_time will
be more accurate in the vast majority of cases and should be the
preferred method of calculating the position ratio.
This commit is contained in:
Dudemanguy911 2019-09-21 10:03:57 -05:00
parent 685e927fbe
commit dd547ddcc2

View File

@ -550,7 +550,7 @@ double get_current_pos_ratio(struct MPContext *mpctx, bool use_range)
double pos = get_current_time(mpctx); double pos = get_current_time(mpctx);
if (len > 0) if (len > 0)
ans = MPCLAMP((pos - start) / len, 0, 1); ans = MPCLAMP((pos - start) / len, 0, 1);
if (ans < 0 || demuxer->ts_resets_possible) { if (ans < 0) {
int64_t size = demuxer->filesize; int64_t size = demuxer->filesize;
if (size > 0 && demuxer->filepos >= 0) if (size > 0 && demuxer->filepos >= 0)
ans = MPCLAMP(demuxer->filepos / (double)size, 0, 1); ans = MPCLAMP(demuxer->filepos / (double)size, 0, 1);