mirror of
https://github.com/mpv-player/mpv
synced 2024-12-18 12:55:16 +00:00
video: improve decoder-based framedropping mode
This is the "old" framedropping mode (derived from MPlayer). At least in the mplayer2/mpv source base, it stopped working properly years ago (or maybe it never worked properly). For one, it depends on the video framerate, which assume constant framerate. Another problem was that it could lead to freezing video display: video could get so much behind that it couldn't recover from framedrop. Make some small changes to improve this. Don't use the current audio position to check how much we are behind. Instead, use the last known A/V difference. last_av_difference is updated only when a video frame is scheduled for display. This means we can keep stop dropping once we're done catching up, even if video is technically still behind. What helps us here that this forces a video frame to be displayed after a while. Likewise, we reset the dropped_frames count only when scheduling a new frame for display as well. Some inspiration was taken from earlier work by xnor (see issue #620), although the implementation turned out quite different. This still uses the demuxer-reported (possibly broken) FPS value. It also doesn't account for filters changing FPS. We can't do much about this, because without decoding _and_ filtering, we just can't know how long a frame is. In theory, you could derive that from the raw packet timestamps and the filter chain contents, but actually doing this is too involved. Fortunately, the main thing the FPS affects is actually the displayed framedrop count.
This commit is contained in:
parent
65e816b3fe
commit
4047e7e6cb
@ -339,18 +339,16 @@ static int check_framedrop(struct MPContext *mpctx)
|
||||
if (mpctx->video_status == STATUS_PLAYING && !mpctx->paused &&
|
||||
mpctx->audio_status == STATUS_PLAYING && !ao_untimed(mpctx->ao))
|
||||
{
|
||||
float delay = opts->playback_speed * ao_get_delay(mpctx->ao);
|
||||
float d = delay - mpctx->delay;
|
||||
float fps = mpctx->d_video->fps;
|
||||
double frame_time = fps > 0 ? 1.0 / fps : 0;
|
||||
// we should avoid dropping too many frames in sequence unless we
|
||||
// are too late. and we allow 100ms A-V delay here:
|
||||
if (d < -mpctx->dropped_frames * frame_time - 0.100) {
|
||||
if (mpctx->last_av_difference - 0.100 > mpctx->dropped_frames * frame_time)
|
||||
{
|
||||
mpctx->drop_frame_cnt++;
|
||||
mpctx->dropped_frames++;
|
||||
return !!(mpctx->opts->frame_dropping & 2);
|
||||
} else
|
||||
mpctx->dropped_frames = 0;
|
||||
return !!(opts->frame_dropping & 2);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -557,6 +555,7 @@ static int video_output_image(struct MPContext *mpctx, double endpts)
|
||||
mpctx->time_frame += frame_time / mpctx->opts->playback_speed;
|
||||
adjust_sync(mpctx, pts, frame_time);
|
||||
}
|
||||
mpctx->dropped_frames = 0;
|
||||
MP_TRACE(mpctx, "frametime=%5.3f\n", frame_time);
|
||||
r = VD_PROGRESS;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user