mirror of https://github.com/mpv-player/mpv
vo_gpu_next: add validation for invalid pl_queue usage
This is mainly for debugging purposes, as it should't happen in normal use. If it does, it needs fixing.
This commit is contained in:
parent
fe748e54f1
commit
ba5071a7ef
|
@ -874,6 +874,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||||
bool cache_frame = will_redraw || frame->still;
|
bool cache_frame = will_redraw || frame->still;
|
||||||
bool can_interpolate = opts->interpolation && frame->display_synced &&
|
bool can_interpolate = opts->interpolation && frame->display_synced &&
|
||||||
!frame->still && frame->num_frames > 1;
|
!frame->still && frame->num_frames > 1;
|
||||||
|
double pts_offset = can_interpolate ? frame->ideal_frame_vsync : 0;
|
||||||
params.info_callback = info_callback;
|
params.info_callback = info_callback;
|
||||||
params.info_priv = vo;
|
params.info_priv = vo;
|
||||||
params.skip_caching_single_frame = !cache_frame;
|
params.skip_caching_single_frame = !cache_frame;
|
||||||
|
@ -881,6 +882,27 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||||
if (frame->still)
|
if (frame->still)
|
||||||
params.frame_mixer = NULL;
|
params.frame_mixer = NULL;
|
||||||
|
|
||||||
|
// pl_queue advances its internal virtual PTS and culls available frames
|
||||||
|
// based on this value and the VPS/FPS ratio. Requesting a non-monotonic PTS
|
||||||
|
// is an invalid use of pl_queue. Reset it if this happens in an attempt to
|
||||||
|
// recover as much as possible. Ideally, this should never occur, and if it
|
||||||
|
// does, it should be corrected. The ideal_frame_vsync may be negative if
|
||||||
|
// the last draw did not align perfectly with the vsync. In this case, we
|
||||||
|
// should have the previous frame available in pl_queue, or a reset is
|
||||||
|
// already requested. Clamp the check to 0, as we don't have the previous
|
||||||
|
// frame in vo_frame anyway.
|
||||||
|
struct pl_source_frame vpts;
|
||||||
|
if (frame->current && !p->want_reset) {
|
||||||
|
if (pl_queue_peek(p->queue, 0, &vpts) &&
|
||||||
|
frame->current->pts + MPMAX(0, pts_offset) < vpts.pts)
|
||||||
|
{
|
||||||
|
MP_VERBOSE(vo, "Forcing queue refill, PTS(%f + %f | %f) < VPTS(%f)\n",
|
||||||
|
frame->current->pts, pts_offset,
|
||||||
|
frame->ideal_frame_vsync_duration, vpts.pts);
|
||||||
|
p->want_reset = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Push all incoming frames into the frame queue
|
// Push all incoming frames into the frame queue
|
||||||
for (int n = 0; n < frame->num_frames; n++) {
|
for (int n = 0; n < frame->num_frames; n++) {
|
||||||
int id = frame->frame_id + n;
|
int id = frame->frame_id + n;
|
||||||
|
@ -929,7 +951,6 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||||
|
|
||||||
struct pl_swapchain_frame swframe;
|
struct pl_swapchain_frame swframe;
|
||||||
struct ra_swapchain *sw = p->ra_ctx->swapchain;
|
struct ra_swapchain *sw = p->ra_ctx->swapchain;
|
||||||
double pts_offset = can_interpolate ? frame->ideal_frame_vsync : 0;
|
|
||||||
bool should_draw = sw->fns->start_frame(sw, NULL); // for wayland logic
|
bool should_draw = sw->fns->start_frame(sw, NULL); // for wayland logic
|
||||||
if (!should_draw || !pl_swapchain_start_frame(p->sw, &swframe)) {
|
if (!should_draw || !pl_swapchain_start_frame(p->sw, &swframe)) {
|
||||||
if (frame->current) {
|
if (frame->current) {
|
||||||
|
|
Loading…
Reference in New Issue