mirror of
https://github.com/mpv-player/mpv
synced 2024-12-25 08:12:17 +00:00
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:
parent
772961f0ce
commit
1fe64c61be
@ -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.
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user