path: root/player/video.c
diff options
authorwm4 <wm4@nowhere>2014-09-19 23:46:20 +0200
committerwm4 <wm4@nowhere>2014-09-20 00:45:11 +0200
commit4047e7e6cb8db776dd771d1dd6ef0b58f20e063a (patch)
treec66443f6b2aa6a84b3df213cef96fdba9050aedd /player/video.c
parent65e816b3fe0dae5aa21e4211ef0192b762636e2d (diff)
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.
Diffstat (limited to 'player/video.c')
1 files changed, 5 insertions, 6 deletions
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)
+ {
- 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);