From 63b7d5b0892e0903c775908d6b032ac18e923450 Mon Sep 17 00:00:00 2001 From: Niklas Haas <git@haasn.dev> Date: Mon, 25 Sep 2023 19:56:54 +0200 Subject: [PATCH 1/4] filters: move helper function to filters.h --- src/filters.c | 12 ++---------- src/filters.h | 6 ++++++ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/filters.c b/src/filters.c index 86332900..9103a47c 100644 --- a/src/filters.c +++ b/src/filters.c @@ -75,17 +75,9 @@ bool pl_filter_config_eq(const struct pl_filter_config *a, return eq; } -static inline float filter_radius(const struct pl_filter_config *c) -{ - float radius = c->radius && c->kernel->resizable ? c->radius : c->kernel->radius; - if (c->blur > 0.0) - radius *= c->blur; - return radius; -} - double pl_filter_sample(const struct pl_filter_config *c, double x) { - const float radius = filter_radius(c); + const float radius = pl_filter_radius_bound(c); // All filters are symmetric, and in particular only need to be defined // for [0, radius]. @@ -130,7 +122,7 @@ double pl_filter_sample(const struct pl_filter_config *c, double x) static void filter_cutoffs(const struct pl_filter_config *c, float cutoff, float *out_radius, float *out_radius_zero) { - const float bound = filter_radius(c); + const float bound = pl_filter_radius_bound(c); float prev = 0.0, fprev = pl_filter_sample(c, prev); bool found_root = false; diff --git a/src/filters.h b/src/filters.h index 10da0fad..c3227db4 100644 --- a/src/filters.h +++ b/src/filters.h @@ -19,6 +19,12 @@ #include <libplacebo/filters.h> +static inline float pl_filter_radius_bound(const struct pl_filter_config *c) +{ + const float r = c->radius && c->kernel->resizable ? c->radius : c->kernel->radius; + return c->blur > 0.0 ? r * c->blur : r; +} + #define COMMON_FILTER_PRESETS \ /* Highest priority / recommended filters */ \ {"bilinear", &pl_filter_bilinear, "Bilinear"}, \ -- GitLab From faee50cfcd3530e7295e71107f8b6de6768ea1cf Mon Sep 17 00:00:00 2001 From: Niklas Haas <git@haasn.dev> Date: Mon, 25 Sep 2023 19:57:08 +0200 Subject: [PATCH 2/4] renderer: add missing validation check --- src/renderer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/renderer.c b/src/renderer.c index 9fc1aa82..fdab0a93 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -3265,6 +3265,7 @@ bool pl_render_image_mix(pl_renderer rr, const struct pl_frame_mix *images, pl_dispatch_mark_dynamic(rr->dp, params->dynamic_constants); require(images->num_frames >= 1); + require(images->vsync_duration > 0.0); for (int i = 0; i < images->num_frames - 1; i++) require(images->timestamps[i] <= images->timestamps[i+1]); -- GitLab From 7872af19ccc88da39cf64ddc9beb3df68e888d89 Mon Sep 17 00:00:00 2001 From: Niklas Haas <git@haasn.dev> Date: Mon, 25 Sep 2023 19:58:21 +0200 Subject: [PATCH 3/4] renderer: properly blur frame mixer Fixes: https://code.videolan.org/videolan/libplacebo/-/issues/309 --- src/include/libplacebo/renderer.h | 5 ++++- src/renderer.c | 28 +++++++++++++++++++++------- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/include/libplacebo/renderer.h b/src/include/libplacebo/renderer.h index 9c21840f..49255e5b 100644 --- a/src/include/libplacebo/renderer.h +++ b/src/include/libplacebo/renderer.h @@ -785,7 +785,10 @@ struct pl_frame_mix { // "next" frames. }; -// Helper function to calculate the frame mixing radius. +// Helper function to calculate the base frame mixing radius. +// +// Note: When the source FPS exceeds the display FPS, this radius must be +// increased by the corresponding ratio. static inline float pl_frame_mix_radius(const struct pl_render_params *params) { // For backwards compatibility, allow !frame_mixer->kernel diff --git a/src/renderer.c b/src/renderer.c index fdab0a93..cc39eed8 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -3301,6 +3301,21 @@ bool pl_render_image_mix(pl_renderer rr, const struct pl_frame_mix *images, for (int i = 0; i < rr->frames.num; i++) rr->frames.elem[i].evict = true; + // Blur frame mixer according to vsync ratio (source / display) + struct pl_filter_config mixer; + if (params->frame_mixer) { + mixer = *params->frame_mixer; + mixer.blur = PL_DEF(mixer.blur, 1.0); + for (int i = 1; i < images->num_frames; i++) { + if (images->timestamps[i] >= 0.0 && images->timestamps[i - 1] < 0) { + float frame_dur = images->timestamps[i] - images->timestamps[i - 1]; + if (!params->skip_anti_aliasing) + mixer.blur *= images->vsync_duration / frame_dur; + break; + } + } + } + // Traverse the input frames and determine/prepare the ones we need bool single_frame = !params->frame_mixer || images->num_frames == 1; retry: @@ -3318,7 +3333,6 @@ retry: } float weight; - const struct pl_filter_config *mixer = params->frame_mixer; if (single_frame) { // Only render the refimg, ignore others @@ -3330,7 +3344,7 @@ retry: } // For backwards compatibility, treat !kernel as oversample - } else if (!mixer->kernel || mixer->kernel == &pl_filter_function_oversample) { + } else if (!mixer.kernel || mixer.kernel == &pl_filter_function_oversample) { // Compute the visible interval [rts, end] of this frame float end = i+1 < images->num_frames ? images->timestamps[i+1] : INFINITY; @@ -3348,21 +3362,21 @@ retry: PL_TRACE(rr, " -> Frame [%f, %f] intersects [%f, %f] = weight %f", rts, end, 0.0, images->vsync_duration, weight); - if (weight < mixer->kernel->params[0]) { + if (weight < mixer.kernel->params[0]) { PL_TRACE(rr, " (culling due to threshold)"); weight = 0.0; } } else { - if (fabsf(rts) >= mixer->kernel->radius) { - PL_TRACE(rr, " -> Skipping: outside filter radius (%f)", - mixer->kernel->radius); + const float radius = pl_filter_radius_bound(&mixer); + if (fabsf(rts) >= radius) { + PL_TRACE(rr, " -> Skipping: outside filter radius (%f)", radius); continue; } // Weight is directly sampled from the filter - weight = pl_filter_sample(mixer, rts); + weight = pl_filter_sample(&mixer, rts); PL_TRACE(rr, " -> Filter offset %f = weight %f", rts, weight); } -- GitLab From ebd131621e7dc391b65d249279bcc455036aa88a Mon Sep 17 00:00:00 2001 From: Niklas Haas <git@haasn.dev> Date: Mon, 25 Sep 2023 20:06:14 +0200 Subject: [PATCH 4/4] utils/frame_queue: increase queue size based on fps ratio Add extra frames when FPS is larger than VPS. --- src/utils/frame_queue.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/utils/frame_queue.c b/src/utils/frame_queue.c index 7078391a..01559839 100644 --- a/src/utils/frame_queue.c +++ b/src/utils/frame_queue.c @@ -809,8 +809,10 @@ static enum pl_queue_status interpolate(pl_queue p, struct pl_frame_mix *mix, if (!params->radius) return oversample(p, mix, params); - double min_pts = params->pts - params->radius * p->fps.estimate, - max_pts = params->pts + params->radius * p->fps.estimate; + pl_assert(p->fps.estimate && p->vps.estimate); + float radius = params->radius * fmaxf(1.0f, p->vps.estimate / p->fps.estimate); + double min_pts = params->pts - radius * p->fps.estimate, + max_pts = params->pts + radius * p->fps.estimate; enum pl_queue_status ret; switch ((ret = advance(p, min_pts, params))) { -- GitLab