vo_opengl: disable interpolation without display-sync

Without display-sync mode, our guesses wrt. vsync phase etc. are much
worse, and I see no reason to keep the complicated "vsync_timed" code.
This commit is contained in:
wm4 2015-11-25 22:10:55 +01:00
parent 772961f0ce
commit 1fe64c61be
5 changed files with 14 additions and 33 deletions

View File

@ -491,6 +491,10 @@ Available video output drivers are:
Reduce stuttering caused by mismatches in the video fps and display Reduce stuttering caused by mismatches in the video fps and display
refresh rate (also known as judder). refresh rate (also known as judder).
.. warning:: This requires setting the ``--video-sync`` option to one
of the ``display-`` modes, or it will be silently disabled.
This was not required before mpv 0.14.0.
This essentially attempts to interpolate the missing frames by This essentially attempts to interpolate the missing frames by
convoluting the video along the temporal axis. The filter used can be convoluting the video along the temporal axis. The filter used can be
controlled using the ``tscale`` setting. controlled using the ``tscale`` setting.

View File

@ -2160,7 +2160,9 @@ void gl_video_render_frame(struct gl_video *p, struct vo_frame *frame, int fbo)
if (has_frame) { if (has_frame) {
gl_sc_set_vao(p->sc, &p->vao); gl_sc_set_vao(p->sc, &p->vao);
if (p->opts.interpolation && (p->frames_drawn || !frame->still)) { if (p->opts.interpolation && frame->display_synced &&
(p->frames_drawn || !frame->still))
{
gl_video_interpolate_frame(p, frame, fbo); gl_video_interpolate_frame(p, frame, fbo);
} else { } else {
bool is_new = !frame->redraw && !frame->repeat; bool is_new = !frame->redraw && !frame->repeat;
@ -2872,7 +2874,7 @@ void gl_video_configure_queue(struct gl_video *p, struct vo *vo)
} }
} }
vo_set_queue_params(vo, 0, p->opts.interpolation, queue_size); vo_set_queue_params(vo, 0, queue_size);
} }
struct mp_csp_equalizer *gl_video_eq_ptr(struct gl_video *p) struct mp_csp_equalizer *gl_video_eq_ptr(struct gl_video *p)

View File

@ -135,8 +135,6 @@ struct vo_internal {
bool want_redraw; // redraw request from VO to player bool want_redraw; // redraw request from VO to player
bool send_reset; // send VOCTRL_RESET bool send_reset; // send VOCTRL_RESET
bool paused; bool paused;
bool vsync_timed; // the VO redraws itself as fast as possible
// at every vsync
int queued_events; // event mask for the user int queued_events; // event mask for the user
int internal_events; // event mask for us int internal_events; // event mask for us
@ -586,7 +584,7 @@ bool vo_is_ready_for_frame(struct vo *vo, int64_t next_pts)
if (next_pts > now) if (next_pts > now)
r = false; r = false;
if (!in->wakeup_pts || next_pts < in->wakeup_pts) { if (!in->wakeup_pts || next_pts < in->wakeup_pts) {
in->wakeup_pts = in->vsync_timed ? 0 : next_pts; in->wakeup_pts = next_pts;
wakeup_locked(vo); wakeup_locked(vo);
} }
} }
@ -605,7 +603,7 @@ void vo_queue_frame(struct vo *vo, struct vo_frame *frame)
(!in->current_frame || in->current_frame->num_vsyncs < 1)); (!in->current_frame || in->current_frame->num_vsyncs < 1));
in->hasframe = true; in->hasframe = true;
in->frame_queued = frame; in->frame_queued = frame;
in->wakeup_pts = (frame->display_synced || in->vsync_timed) in->wakeup_pts = frame->display_synced
? 0 : frame->pts + MPMAX(frame->duration, 0); ? 0 : frame->pts + MPMAX(frame->duration, 0);
wakeup_locked(vo); wakeup_locked(vo);
pthread_mutex_unlock(&in->lock); pthread_mutex_unlock(&in->lock);
@ -669,7 +667,7 @@ static bool render_frame(struct vo *vo)
in->frame_queued = NULL; in->frame_queued = NULL;
} else if (in->paused || !in->current_frame || !in->hasframe || } else if (in->paused || !in->current_frame || !in->hasframe ||
(in->current_frame->display_synced && in->current_frame->num_vsyncs < 1) || (in->current_frame->display_synced && in->current_frame->num_vsyncs < 1) ||
(!in->vsync_timed && !in->current_frame->display_synced)) !in->current_frame->display_synced)
{ {
goto done; goto done;
} }
@ -726,25 +724,6 @@ static bool render_frame(struct vo *vo)
in->dropped_frame &= mp_time_us() - in->last_flip < 100 * 1000; in->dropped_frame &= mp_time_us() - in->last_flip < 100 * 1000;
in->dropped_frame &= in->hasframe_rendered; in->dropped_frame &= in->hasframe_rendered;
if (in->vsync_timed && !frame->display_synced) {
// this is a heuristic that wakes the thread up some
// time before the next vsync
target = next_vsync - MPMIN(in->vsync_interval / 2, 8e3);
// We are very late with the frame and using vsync timing: probably
// no new frames are coming in. This must be done whether or not
// framedrop is enabled. Also, if the frame is to be dropped, even
// though it's an interpolated frame (repeat set), exit early.
bool late = prev_vsync > pts + duration + in->vsync_interval_approx;
if (frame->repeat && ((in->hasframe_rendered && late) || in->dropped_frame))
{
in->dropped_frame = false;
goto done;
}
frame->vsync_offset = next_vsync - pts;
}
// Setup parameters for the next time this frame is drawn. ("frame" is the // Setup parameters for the next time this frame is drawn. ("frame" is the
// frame currently drawn, while in->current_frame is the potentially next.) // frame currently drawn, while in->current_frame is the potentially next.)
in->current_frame->repeat = true; in->current_frame->repeat = true;
@ -1048,16 +1027,13 @@ const char *vo_get_window_title(struct vo *vo)
// flip_page[_timed] will be called offset_us microseconds too early. // flip_page[_timed] will be called offset_us microseconds too early.
// (For vo_vdpau, which does its own timing.) // (For vo_vdpau, which does its own timing.)
// Setting vsync_timed to true redraws as fast as possible.
// num_req_frames set the requested number of requested vo_frame.frames. // num_req_frames set the requested number of requested vo_frame.frames.
// (For vo_opengl interpolation.) // (For vo_opengl interpolation.)
void vo_set_queue_params(struct vo *vo, int64_t offset_us, bool vsync_timed, void vo_set_queue_params(struct vo *vo, int64_t offset_us, int num_req_frames)
int num_req_frames)
{ {
struct vo_internal *in = vo->in; struct vo_internal *in = vo->in;
pthread_mutex_lock(&in->lock); pthread_mutex_lock(&in->lock);
in->flip_queue_offset = offset_us; in->flip_queue_offset = offset_us;
in->vsync_timed = vsync_timed;
in->req_frames = MPCLAMP(num_req_frames, 1, VO_MAX_REQ_FRAMES); in->req_frames = MPCLAMP(num_req_frames, 1, VO_MAX_REQ_FRAMES);
pthread_mutex_unlock(&in->lock); pthread_mutex_unlock(&in->lock);
} }

View File

@ -344,8 +344,7 @@ void vo_query_formats(struct vo *vo, uint8_t *list);
void vo_event(struct vo *vo, int event); void vo_event(struct vo *vo, int event);
int vo_query_and_reset_events(struct vo *vo, int events); int vo_query_and_reset_events(struct vo *vo, int events);
struct mp_image *vo_get_current_frame(struct vo *vo); struct mp_image *vo_get_current_frame(struct vo *vo);
void vo_set_queue_params(struct vo *vo, int64_t offset_us, bool vsync_timed, void vo_set_queue_params(struct vo *vo, int64_t offset_us, int num_req_frames);
int num_req_frames);
int vo_get_num_req_frames(struct vo *vo); int vo_get_num_req_frames(struct vo *vo);
int64_t vo_get_vsync_interval(struct vo *vo); int64_t vo_get_vsync_interval(struct vo *vo);
double vo_get_estimated_vsync_interval(struct vo *vo); double vo_get_estimated_vsync_interval(struct vo *vo);

View File

@ -302,7 +302,7 @@ static void resize(struct vo *vo)
vc->flip_offset_us = vo->opts->fullscreen ? vc->flip_offset_us = vo->opts->fullscreen ?
1000LL * vc->flip_offset_fs : 1000LL * vc->flip_offset_fs :
1000LL * vc->flip_offset_window; 1000LL * vc->flip_offset_window;
vo_set_queue_params(vo, vc->flip_offset_us, false, 1); vo_set_queue_params(vo, vc->flip_offset_us, 1);
if (vc->output_surface_w < vo->dwidth || vc->output_surface_h < vo->dheight) { if (vc->output_surface_w < vo->dwidth || vc->output_surface_h < vo->dheight) {
vc->output_surface_w = s_size(max_w, vc->output_surface_w, vo->dwidth); vc->output_surface_w = s_size(max_w, vc->output_surface_w, vo->dwidth);