1
0
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:
wm4 2014-09-19 23:46:20 +02:00
parent 65e816b3fe
commit 4047e7e6cb

View File

@ -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;
}