From 4047e7e6cb8db776dd771d1dd6ef0b58f20e063a Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 19 Sep 2014 23:46:20 +0200 Subject: 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. --- player/video.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'player/video.c') diff --git a/player/video.c b/player/video.c index 865b38be43..3332aca737 100644 --- a/player/video.c +++ b/player/video.c @@ -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; } -- cgit v1.2.3