From 7cab30cec77b3fe4b8ca85b37664a3dc9b270aee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Fri, 10 Nov 2023 18:19:04 +0100 Subject: [PATCH] vo_gpu_next: fix interpolation Fixes gpu-next completely ignoring any speed adjustment, either DS or playback. Frames in pl_queue have raw PTS values, so when querying them we have to use the same time base. There was misunderstanding between mpv and libplacebo, where the former was querying the frames based on display vblank timeline, but this cannot work if the playback speed is adjusted and display timeline is not aligned with video timelien. In which case we have to schedule "video vsync" points that we want to display. Previous code was working only when playback speed was 1.0x, but since DS almost always changes the speed the interpolation was mostly not timied correctly. --- video/out/vo_gpu_next.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/video/out/vo_gpu_next.c b/video/out/vo_gpu_next.c index 6878dc1615..eba1214d63 100644 --- a/video/out/vo_gpu_next.c +++ b/video/out/vo_gpu_next.c @@ -903,7 +903,6 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) pl_queue_push(p->queue, &(struct pl_source_frame) { .pts = mpi->pts, - .duration = frame->ideal_frame_duration, .frame_data = mpi, .map = map_frame, .unmap = unmap_frame, @@ -929,13 +928,13 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) struct pl_swapchain_frame swframe; struct ra_swapchain *sw = p->ra_ctx->swapchain; - double vsync_offset = can_interpolate ? frame->vsync_offset : 0; + double pts_offset = can_interpolate ? frame->ideal_frame_vsync : 0; bool should_draw = sw->fns->start_frame(sw, NULL); // for wayland logic if (!should_draw || !pl_swapchain_start_frame(p->sw, &swframe)) { if (frame->current) { // Advance the queue state to the current PTS to discard unused frames pl_queue_update(p->queue, NULL, pl_queue_params( - .pts = frame->current->pts + vsync_offset, + .pts = frame->current->pts + pts_offset, .radius = pl_frame_mix_radius(¶ms), )); } @@ -959,9 +958,9 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) if (frame->current) { // Update queue state struct pl_queue_params qparams = *pl_queue_params( - .pts = frame->current->pts + vsync_offset, + .pts = frame->current->pts + pts_offset, .radius = pl_frame_mix_radius(¶ms), - .vsync_duration = frame->vsync_interval, + .vsync_duration = frame->ideal_frame_vsync_duration, .interpolation_threshold = opts->interpolation_threshold, ); @@ -1047,7 +1046,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) pl_renderer_get_hdr_metadata(p->rr, &vo->params->color.hdr); } - p->is_interpolated = vsync_offset != 0 && mix.num_frames > 1; + p->is_interpolated = pts_offset != 0 && mix.num_frames > 1; valid = true; // fall through