lavfi/vf_libplacebo: add frame_mixer option

Fairly straightforward. We just need to modify the scaler handling code
slightly to support looking at a different list of filter presets.
This commit is contained in:
Niklas Haas 2023-05-10 14:42:22 +02:00
parent 02f3b9312a
commit 30c71ef98e
2 changed files with 42 additions and 6 deletions

View File

@ -16177,6 +16177,31 @@ Cubic BC spline with parameters recommended by Mitchell and Netravali. Very
little ringing. little ringing.
@end table @end table
@item frame_mixer
Controls the kernel used for mixing frames temporally. The default value is
@code{none}, which disables frame mixing. For a full list of possible values,
pass @code{help} to this option. The most important values are:
@table @samp
@item none
Disables frame mixing, giving a result equivalent to "nearest neighbour"
semantics.
@item oversample
Oversamples the input video to create a "Smooth Motion"-type effect: if an
output frame would exactly fall on the transition between two video frames, it
is blended according to the relative overlap. This is the recommended option
whenever preserving the original subjective appearance is desired.
@item mitchell_clamp
Larger filter kernel that smoothly interpolates multiple frames in a manner
designed to eliminate ringing and other artefacts as much as possible. This is
the recommended option wherever maximum visual smoothness is desired.
@item linear
Linear blend/fade between frames. Especially useful for constructing e.g.
slideshows.
@end table
@item lut_entries @item lut_entries
Configures the size of scaler LUTs, ranging from @code{1} to @code{256}. The Configures the size of scaler LUTs, ranging from @code{1} to @code{256}. The
default of @code{0} will pick libplacebo's internal default, typically default of @code{0} will pick libplacebo's internal default, typically
@ -16534,6 +16559,12 @@ Rescale input to fit into standard 1080p, with high quality scaling:
libplacebo=w=1920:h=1080:force_original_aspect_ratio=decrease:normalize_sar=true:upscaler=ewa_lanczos:downscaler=ewa_lanczos libplacebo=w=1920:h=1080:force_original_aspect_ratio=decrease:normalize_sar=true:upscaler=ewa_lanczos:downscaler=ewa_lanczos
@end example @end example
@item
Interpolate low FPS / VFR input to smoothed constant 60 fps output:
@example
libplacebo=fps=60:frame_mixer=mitchell_clamp
@end example
@item @item
Convert input to standard sRGB JPEG: Convert input to standard sRGB JPEG:
@example @example

View File

@ -164,6 +164,7 @@ typedef struct LibplaceboContext {
struct pl_render_params params; struct pl_render_params params;
char *upscaler; char *upscaler;
char *downscaler; char *downscaler;
char *frame_mixer;
int lut_entries; int lut_entries;
float antiringing; float antiringing;
int sigmoid; int sigmoid;
@ -285,17 +286,19 @@ static int parse_shader(AVFilterContext *avctx, const void *shader, size_t len)
static int find_scaler(AVFilterContext *avctx, static int find_scaler(AVFilterContext *avctx,
const struct pl_filter_config **opt, const struct pl_filter_config **opt,
const char *name) const char *name, int frame_mixing)
{ {
const struct pl_filter_preset *preset; const struct pl_filter_preset *preset, *presets_avail;
presets_avail = frame_mixing ? pl_frame_mixers : pl_scale_filters;
if (!strcmp(name, "help")) { if (!strcmp(name, "help")) {
av_log(avctx, AV_LOG_INFO, "Available scaler presets:\n"); av_log(avctx, AV_LOG_INFO, "Available scaler presets:\n");
for (preset = pl_scale_filters; preset->name; preset++) for (preset = presets_avail; preset->name; preset++)
av_log(avctx, AV_LOG_INFO, " %s\n", preset->name); av_log(avctx, AV_LOG_INFO, " %s\n", preset->name);
return AVERROR_EXIT; return AVERROR_EXIT;
} }
for (preset = pl_scale_filters; preset->name; preset++) { for (preset = presets_avail; preset->name; preset++) {
if (!strcmp(name, preset->name)) { if (!strcmp(name, preset->name)) {
*opt = preset->filter; *opt = preset->filter;
return 0; return 0;
@ -411,8 +414,9 @@ static int update_settings(AVFilterContext *ctx)
.disable_fbos = s->disable_fbos, .disable_fbos = s->disable_fbos,
); );
RET(find_scaler(ctx, &s->params.upscaler, s->upscaler)); RET(find_scaler(ctx, &s->params.upscaler, s->upscaler, 0));
RET(find_scaler(ctx, &s->params.downscaler, s->downscaler)); RET(find_scaler(ctx, &s->params.downscaler, s->downscaler, 0));
RET(find_scaler(ctx, &s->params.frame_mixer, s->frame_mixer, 1));
return 0; return 0;
fail: fail:
@ -1110,6 +1114,7 @@ static const AVOption libplacebo_options[] = {
{ "upscaler", "Upscaler function", OFFSET(upscaler), AV_OPT_TYPE_STRING, {.str = "spline36"}, .flags = DYNAMIC }, { "upscaler", "Upscaler function", OFFSET(upscaler), AV_OPT_TYPE_STRING, {.str = "spline36"}, .flags = DYNAMIC },
{ "downscaler", "Downscaler function", OFFSET(downscaler), AV_OPT_TYPE_STRING, {.str = "mitchell"}, .flags = DYNAMIC }, { "downscaler", "Downscaler function", OFFSET(downscaler), AV_OPT_TYPE_STRING, {.str = "mitchell"}, .flags = DYNAMIC },
{ "frame_mixer", "Frame mixing function", OFFSET(frame_mixer), AV_OPT_TYPE_STRING, {.str = "none"}, .flags = DYNAMIC },
{ "lut_entries", "Number of scaler LUT entries", OFFSET(lut_entries), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 256, DYNAMIC }, { "lut_entries", "Number of scaler LUT entries", OFFSET(lut_entries), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 256, DYNAMIC },
{ "antiringing", "Antiringing strength (for non-EWA filters)", OFFSET(antiringing), AV_OPT_TYPE_FLOAT, {.dbl = 0.0}, 0.0, 1.0, DYNAMIC }, { "antiringing", "Antiringing strength (for non-EWA filters)", OFFSET(antiringing), AV_OPT_TYPE_FLOAT, {.dbl = 0.0}, 0.0, 1.0, DYNAMIC },
{ "sigmoid", "Enable sigmoid upscaling", OFFSET(sigmoid), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, DYNAMIC }, { "sigmoid", "Enable sigmoid upscaling", OFFSET(sigmoid), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, DYNAMIC },