player: slightly adjust framerate guessing heuristic

Some files not only use rounded timestamps, but they also do it
incorrectly. They may jitter between up to 4 specific frame durations.
In this case, I found a file that mostly used 41ms and 42ms, but also
had 40ms and 43ms outliers (often but not always following each other).

This breaks the assumption of the framerate estimation code that the
frame duration can deviate up to 1ms. If it jitters around 4 possible
frame durations, the maximum deviation is 3ms. Increase it accordingly.

The change might make playback of "true VFR" video via display-sync mode
worse, but it's not like it was particularly good in the first place.

Also, the check whether to usen the container FPS needs to be stricter.
In the worst case, num_dur is 1, which doesn't really indicate any
evidence that the framerate is correct. Only if there are "enough"
frames the deviation check will become meaningful. 16 is an arbitrary
value that has been designated "enough" by myself.

Also otuput the frame duration values for --dump-stats.
This commit is contained in:
wm4 2016-08-29 17:15:06 +02:00
parent ae3bbc4f63
commit d223959cda
1 changed files with 8 additions and 6 deletions

View File

@ -1291,11 +1291,10 @@ static void calculate_frame_duration(struct MPContext *mpctx)
// The following code tries to compensate for rounded Matroska timestamps
// by "unrounding" frame durations, or if not possible, approximating them.
// These formats usually round on 1ms. (Some muxers do this incorrectly,
// and might be off by 2ms or more, and compensate for it later by an
// equal rounding error into the opposite direction. Don't try to deal
// with them; too much potential damage to timing.)
double tolerance = 0.0011;
// These formats usually round on 1ms. Some muxers do this incorrectly,
// and might go off by 1ms more, and compensate for it later by an equal
// rounding error into the opposite direction.
double tolerance = 0.001 * 3 + 0.0001;
double total = 0;
int num_dur = 0;
@ -1314,7 +1313,7 @@ static void calculate_frame_duration(struct MPContext *mpctx)
// Note that even if each timestamp is within rounding tolerance, it
// could literally not add up (e.g. if demuxer FPS is rounded itself).
if (fabs(duration - demux_duration) < tolerance &&
fabs(total - demux_duration * num_dur) < tolerance)
fabs(total - demux_duration * num_dur) < tolerance && num_dur >= 16)
{
approx_duration = demux_duration;
}
@ -1322,6 +1321,9 @@ static void calculate_frame_duration(struct MPContext *mpctx)
mpctx->past_frames[0].duration = duration;
mpctx->past_frames[0].approx_duration = approx_duration;
MP_STATS(mpctx, "value %f frame-duration", MPMAX(0, duration));
MP_STATS(mpctx, "value %f frame-duration-approx", MPMAX(0, approx_duration));
}
void write_video(struct MPContext *mpctx)