From patchwork Mon May 15 08:59:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 41621 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:ba91:b0:105:feb:71f2 with SMTP id fb17csp1456377pzb; Mon, 15 May 2023 01:59:57 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ6UpqD5fZ29Ulf9XsI8MdsGO2+axggNO7jxTs10OoqXQZUepOcqb8hA3OPUXAAF9HWfVrIF X-Received: by 2002:a17:907:3e27:b0:957:758e:df57 with SMTP id hp39-20020a1709073e2700b00957758edf57mr36261603ejc.65.1684141197418; Mon, 15 May 2023 01:59:57 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1684141197; cv=none; d=google.com; s=arc-20160816; b=bp4IoOqJbKwKUegflTqZVGA3OtyIEez/AYjihl4Sh+sPeuUe8eH9a/iZPTxBkYvjze xlj4mY15kakM3DAy7JLf95K9Uj4JtuQJhjQqyV3z3JzAWEHjKtsJ0poY/sHDxbbuNNwu rIeUSiog992ZshHXO6UtcHhzLCGmbvPogyybiHVNcFW1kCgX6EuD1q010civYncyM2en oeWZkCg+IacxFOjr8kLhimTos1YSrQ+6d9Z7i3ft9UM+lgsFsDJxt5BLOXZ8oXBIEmjN iie2CS5EuNBdHg/ujjo5hMgCMcXT7nu5UnFVq7rGmgbAFy5p5hyjg6Xh/0KIrwhHU6au b5dQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:message-id:date:to:from :dkim-signature:delivered-to; bh=TBaqS7y1g8rvaO84GijMAsWA1pe3foe/oJLGfJDRO8E=; b=UN4cmtmqFot0xP+Bby3kpaEJhOMdJQ9kZ6gFUL29V9Ijc1V5KxVriBRXp53REkrxUW RE3Xl5f8G6S2ZDBNlu7fKI67qt6antBg4xuQd9wptskYi9AzrcGw2yMas99h+Bq5Ly0n xTHoHbXyi98NI7hiLkhgkU9OCpBI/Lg5WVzTi2G7Gcyx//6UIntGq/zs/Wz8ZiEVYp9o jDOgfdXFSTHrhhAtrtPfRa/pXPqmKj+RyFdl8igILrTcR8ELz34VgVuy0rmIFZuCM5YQ 9iFpClPkHmeQb7TRrE8b02oPxsTEG6JdSk11ssl8uINifoRiILBNyIVmJoDY9YEPooSX CFQg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b=MbPXi2Le; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id y4-20020a17090614c400b0096978b2b5b0si11259888ejc.494.2023.05.15.01.59.56; Mon, 15 May 2023 01:59:57 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b=MbPXi2Le; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id DF01668C0AE; Mon, 15 May 2023 11:59:52 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 87B9168C005 for ; Mon, 15 May 2023 11:59:46 +0300 (EEST) Received: from localhost (217-74-0-168.hsi.r-kom.net [217.74.0.168]) by haasn.dev (Postfix) with ESMTPSA id 80D4541EC3; Mon, 15 May 2023 10:59:45 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=haasn.xyz; s=mail; t=1684141185; bh=L74fNTclzytk9xn1KsJXZvCwiRR65dELmszAsEE2zWY=; h=From:To:Cc:Subject:Date:From; b=MbPXi2LeRxN4UdvpcG0s3EjAHlcpr5tOeT6mwN/DArX7UCthMbaQACbBLet5jG2ud Wy/5viGxYL4xxga3RVbZc8fPxXp5e3Lz8bsDtZ4C0LazHEGyYG+fsG7To7YJqusPAp f6F4sNZ3C7NgK0TBv9TofVjaoD+rrywv7dfKrggU= From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Mon, 15 May 2023 10:59:41 +0200 Message-Id: <20230515085943.31760-1-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.40.1 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 1/3] lavfi/vf_libplacebo: switch to new gamut mapping API X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: DKEEg8pSGBAP From: Niklas Haas Upstream deprecated the old ad-hoc, enum/intent-based gamut mapping API and added a new API based on colorimetrically accurate gamut mapping functions. The relevant change for us is the addition of several new modes, as well as deprecation of the old options. Update the documentation accordingly. --- doc/filters.texi | 47 ++++++++++--------- libavfilter/vf_libplacebo.c | 92 ++++++++++++++++++++++++++++++------- 2 files changed, 98 insertions(+), 41 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index d935e62b3f..14cb31b95c 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -16332,37 +16332,36 @@ gamut-mapping when dealing with mismatches between wide-gamut or HDR content. In general, libplacebo relies on accurate source tagging and mastering display gamut information to produce the best results. @table @option -@item intent -Rendering intent to use when adapting between different primary color gamuts -(after tone-mapping). -@table @samp -@item perceptual -Perceptual gamut mapping. Currently equivalent to relative colorimetric. -@item relative -Relative colorimetric. This is the default. -@item absolute -Absolute colorimetric. -@item saturation -Saturation mapping. Forcibly stretches the source gamut to the target gamut. -@end table - @item gamut_mode How to handle out-of-gamut colors that can occur as a result of colorimetric gamut mapping. @table @samp @item clip -Do nothing, simply clip out-of-range colors to the RGB volume. This is the -default. -@item warn -Highlight out-of-gamut pixels (by coloring them pink). -@item darken -Linearly reduces content brightness to preserves saturated details, followed by -clipping the remaining out-of-gamut colors. As the name implies, this makes -everything darker, but provides a good balance between preserving details and -colors. +Do nothing, simply clip out-of-range colors to the RGB volume. Low quality but +extremely fast. +@item perceptual +Perceptually soft-clip colors to the gamut volume. This is the default. +@item relative +Relative colorimetric hard-clip. Similar to @code{perceptual} but without +the soft knee. +@item saturation +Saturation mapping, maps primaries directly to primaries in RGB space. +Not recommended except for artificial computer graphics for which a bright, +saturated display is desired. +@item absolute +Absolute colorimetric hard-clip. Performs no adjustment of the white point. @item desaturate Hard-desaturates out-of-gamut colors towards white, while preserving the -luminance. Has a tendency to shift colors. +luminance. Has a tendency to distort the visual appearance of bright objects. +@item darken +Linearly reduces content brightness to preserves saturated details, followed by +clipping the remaining out-of-gamut colors. +@item warn +Highlight out-of-gamut pixels (by inverting/marking them). +@item linear +Linearly reduces chromaticity of the entire image to make it fit within the +target color volume. Be careful when using this on BT.2020 sources without +proper mastering metadata, as doing so will lead to excessive desaturation. @end table @item tonemapping diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 94e49aa465..fde8da0b9b 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -56,6 +56,19 @@ enum { TONE_MAP_COUNT, }; +enum { + GAMUT_MAP_CLIP, + GAMUT_MAP_PERCEPTUAL, + GAMUT_MAP_RELATIVE, + GAMUT_MAP_SATURATION, + GAMUT_MAP_ABSOLUTE, + GAMUT_MAP_DESATURATE, + GAMUT_MAP_DARKEN, + GAMUT_MAP_HIGHLIGHT, + GAMUT_MAP_LINEAR, + GAMUT_MAP_COUNT, +}; + static const struct pl_tone_map_function * const tonemapping_funcs[TONE_MAP_COUNT] = { [TONE_MAP_AUTO] = &pl_tone_map_auto, [TONE_MAP_CLIP] = &pl_tone_map_clip, @@ -73,6 +86,36 @@ static const struct pl_tone_map_function * const tonemapping_funcs[TONE_MAP_COUN [TONE_MAP_LINEAR] = &pl_tone_map_linear, }; +#if PL_API_VER >= 269 +static const struct pl_gamut_map_function * const gamut_funcs[GAMUT_MAP_COUNT] = { + [GAMUT_MAP_CLIP] = &pl_gamut_map_clip, + [GAMUT_MAP_PERCEPTUAL] = &pl_gamut_map_perceptual, + [GAMUT_MAP_RELATIVE] = &pl_gamut_map_relative, + [GAMUT_MAP_SATURATION] = &pl_gamut_map_saturation, + [GAMUT_MAP_ABSOLUTE] = &pl_gamut_map_absolute, + [GAMUT_MAP_DESATURATE] = &pl_gamut_map_desaturate, + [GAMUT_MAP_DARKEN] = &pl_gamut_map_darken, + [GAMUT_MAP_HIGHLIGHT] = &pl_gamut_map_highlight, + [GAMUT_MAP_LINEAR] = &pl_gamut_map_linear, +}; +#else +static const enum pl_gamut_mode gamut_modes[GAMUT_MAP_COUNT] = { + [GAMUT_MAP_CLIP] = PL_GAMUT_CLIP, + [GAMUT_MAP_PERCEPTUAL] = PL_GAMUT_CLIP, + [GAMUT_MAP_DESATURATE] = PL_GAMUT_DESATURATE, + [GAMUT_MAP_DARKEN] = PL_GAMUT_DARKEN, + [GAMUT_MAP_HIGHLIGHT] = PL_GAMUT_WARN, + /* Everything else defaults to PL_GAMUT_CLIP */ +}; + +static const enum pl_rendering_intent intents[GAMUT_MAP_COUNT] = { + [GAMUT_MAP_SATURATION] = PL_INTENT_SATURATION, + [GAMUT_MAP_RELATIVE] = PL_INTENT_RELATIVE_COLORIMETRIC, + [GAMUT_MAP_ABSOLUTE] = PL_INTENT_ABSOLUTE_COLORIMETRIC, + /* Everything else defaults to PL_INTENT_PERCEPTUAL */ +}; +#endif + static const char *const var_names[] = { "in_w", "iw", ///< width of the input video frame "in_h", "ih", ///< height of the input video frame @@ -203,7 +246,6 @@ typedef struct LibplaceboContext { /* pl_color_map_params */ struct pl_color_map_params color_map_params; - int intent; int gamut_mode; int tonemapping; float tonemapping_param; @@ -219,6 +261,7 @@ typedef struct LibplaceboContext { int gamut_warning; int gamut_clipping; int force_icc_lut; + int intent; #endif /* pl_dither_params */ @@ -314,7 +357,7 @@ static int update_settings(AVFilterContext *ctx) int err = 0; LibplaceboContext *s = ctx->priv; enum pl_tone_map_mode tonemapping_mode = s->tonemapping_mode; - enum pl_gamut_mode gamut_mode = s->gamut_mode; + int gamut_mode = s->gamut_mode; uint8_t color_rgba[4]; RET(av_parse_color(color_rgba, s->fillcolor, -1, s)); @@ -333,10 +376,16 @@ static int update_settings(AVFilterContext *ctx) } } + switch (s->intent) { + case PL_INTENT_SATURATION: gamut_mode = GAMUT_MAP_SATURATION; break; + case PL_INTENT_RELATIVE_COLORIMETRIC: gamut_mode = GAMUT_MAP_RELATIVE; break; + case PL_INTENT_ABSOLUTE_COLORIMETRIC: gamut_mode = GAMUT_MAP_ABSOLUTE; break; + } + if (s->gamut_warning) - gamut_mode = PL_GAMUT_WARN; + gamut_mode = GAMUT_MAP_HIGHLIGHT; if (s->gamut_clipping) - gamut_mode = PL_GAMUT_DESATURATE; + gamut_mode = GAMUT_MAP_DESATURATE; #endif s->deband_params = *pl_deband_params( @@ -363,8 +412,12 @@ static int update_settings(AVFilterContext *ctx) ); s->color_map_params = *pl_color_map_params( - .intent = s->intent, - .gamut_mode = gamut_mode, +#if PL_API_VER >= 269 + .gamut_mapping = gamut_funcs[gamut_mode], +#else + .gamut_mode = gamut_modes[gamut_mode], + .intent = intents[gamut_mode], +#endif .tone_mapping_function = tonemapping_funcs[s->tonemapping], .tone_mapping_param = s->tonemapping_param, .tone_mapping_mode = tonemapping_mode, @@ -1140,16 +1193,16 @@ static const AVOption libplacebo_options[] = { { "scene_threshold_high", "Scene change high threshold", OFFSET(scene_high), AV_OPT_TYPE_FLOAT, {.dbl = 10.0}, -1.0, 100.0, DYNAMIC }, { "overshoot", "Tone-mapping overshoot margin", OFFSET(overshoot), AV_OPT_TYPE_FLOAT, {.dbl = 0.05}, 0.0, 1.0, DYNAMIC }, - { "intent", "Rendering intent", OFFSET(intent), AV_OPT_TYPE_INT, {.i64 = PL_INTENT_RELATIVE_COLORIMETRIC}, 0, 3, DYNAMIC, "intent" }, - { "perceptual", "Perceptual", 0, AV_OPT_TYPE_CONST, {.i64 = PL_INTENT_PERCEPTUAL}, 0, 0, STATIC, "intent" }, - { "relative", "Relative colorimetric", 0, AV_OPT_TYPE_CONST, {.i64 = PL_INTENT_RELATIVE_COLORIMETRIC}, 0, 0, STATIC, "intent" }, - { "absolute", "Absolute colorimetric", 0, AV_OPT_TYPE_CONST, {.i64 = PL_INTENT_ABSOLUTE_COLORIMETRIC}, 0, 0, STATIC, "intent" }, - { "saturation", "Saturation mapping", 0, AV_OPT_TYPE_CONST, {.i64 = PL_INTENT_SATURATION}, 0, 0, STATIC, "intent" }, - { "gamut_mode", "Gamut-mapping mode", OFFSET(gamut_mode), AV_OPT_TYPE_INT, {.i64 = PL_GAMUT_CLIP}, 0, PL_GAMUT_MODE_COUNT - 1, DYNAMIC, "gamut_mode" }, - { "clip", "Hard-clip gamut boundary", 0, AV_OPT_TYPE_CONST, {.i64 = PL_GAMUT_CLIP}, 0, 0, STATIC, "gamut_mode" }, - { "warn", "Highlight out-of-gamut colors", 0, AV_OPT_TYPE_CONST, {.i64 = PL_GAMUT_WARN}, 0, 0, STATIC, "gamut_mode" }, - { "darken", "Darken image to fit gamut", 0, AV_OPT_TYPE_CONST, {.i64 = PL_GAMUT_DARKEN}, 0, 0, STATIC, "gamut_mode" }, - { "desaturate", "Colorimetrically desaturate colors", 0, AV_OPT_TYPE_CONST, {.i64 = PL_GAMUT_DESATURATE}, 0, 0, STATIC, "gamut_mode" }, + { "gamut_mode", "Gamut-mapping mode", OFFSET(gamut_mode), AV_OPT_TYPE_INT, {.i64 = GAMUT_MAP_PERCEPTUAL}, 0, GAMUT_MAP_COUNT - 1, DYNAMIC, "gamut_mode" }, + { "clip", "Hard-clip (RGB per-channel)", 0, AV_OPT_TYPE_CONST, {.i64 = GAMUT_MAP_CLIP}, 0, 0, STATIC, "gamut_mode" }, + { "perceptual", "Colorimetric soft clipping", 0, AV_OPT_TYPE_CONST, {.i64 = GAMUT_MAP_PERCEPTUAL}, 0, 0, STATIC, "gamut_mode" }, + { "relative", "Relative colorimetric clipping", 0, AV_OPT_TYPE_CONST, {.i64 = GAMUT_MAP_RELATIVE}, 0, 0, STATIC, "gamut_mode" }, + { "saturation", "Saturation mapping (RGB -> RGB)", 0, AV_OPT_TYPE_CONST, {.i64 = GAMUT_MAP_SATURATION}, 0, 0, STATIC, "gamut_mode" }, + { "absolute", "Absolute colorimetric clipping", 0, AV_OPT_TYPE_CONST, {.i64 = GAMUT_MAP_ABSOLUTE}, 0, 0, STATIC, "gamut_mode" }, + { "desaturate", "Colorimetrically desaturate colors towards white", 0, AV_OPT_TYPE_CONST, {.i64 = GAMUT_MAP_DESATURATE}, 0, 0, STATIC, "gamut_mode" }, + { "darken", "Colorimetric clip with bias towards darkening image to fit gamut", 0, AV_OPT_TYPE_CONST, {.i64 = GAMUT_MAP_DARKEN}, 0, 0, STATIC, "gamut_mode" }, + { "warn", "Highlight out-of-gamut colors", 0, AV_OPT_TYPE_CONST, {.i64 = GAMUT_MAP_HIGHLIGHT}, 0, 0, STATIC, "gamut_mode" }, + { "linear", "Linearly reduce chromaticity to fit gamut", 0, AV_OPT_TYPE_CONST, {.i64 = GAMUT_MAP_LINEAR}, 0, 0, STATIC, "gamut_mode" }, { "tonemapping", "Tone-mapping algorithm", OFFSET(tonemapping), AV_OPT_TYPE_INT, {.i64 = TONE_MAP_AUTO}, 0, TONE_MAP_COUNT - 1, DYNAMIC, "tonemap" }, { "auto", "Automatic selection", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_AUTO}, 0, 0, STATIC, "tonemap" }, { "clip", "No tone mapping (clip", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_CLIP}, 0, 0, STATIC, "tonemap" }, @@ -1181,7 +1234,12 @@ static const AVOption libplacebo_options[] = { { "desaturation_strength", "Desaturation strength", OFFSET(desat_str), AV_OPT_TYPE_FLOAT, {.dbl = -1.0}, -1.0, 1.0, DYNAMIC | AV_OPT_FLAG_DEPRECATED }, { "desaturation_exponent", "Desaturation exponent", OFFSET(desat_exp), AV_OPT_TYPE_FLOAT, {.dbl = -1.0}, -1.0, 10.0, DYNAMIC | AV_OPT_FLAG_DEPRECATED }, { "gamut_warning", "Highlight out-of-gamut colors", OFFSET(gamut_warning), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC | AV_OPT_FLAG_DEPRECATED }, - { "gamut_clipping", "Enable colorimetric gamut clipping", OFFSET(gamut_clipping), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC | AV_OPT_FLAG_DEPRECATED }, + { "gamut_clipping", "Enable desaturating colorimetric gamut clipping", OFFSET(gamut_clipping), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC | AV_OPT_FLAG_DEPRECATED }, + { "intent", "Rendering intent", OFFSET(intent), AV_OPT_TYPE_INT, {.i64 = PL_INTENT_PERCEPTUAL}, 0, 3, DYNAMIC | AV_OPT_FLAG_DEPRECATED, "intent" }, + { "perceptual", "Perceptual", 0, AV_OPT_TYPE_CONST, {.i64 = PL_INTENT_PERCEPTUAL}, 0, 0, STATIC, "intent" }, + { "relative", "Relative colorimetric", 0, AV_OPT_TYPE_CONST, {.i64 = PL_INTENT_RELATIVE_COLORIMETRIC}, 0, 0, STATIC, "intent" }, + { "absolute", "Absolute colorimetric", 0, AV_OPT_TYPE_CONST, {.i64 = PL_INTENT_ABSOLUTE_COLORIMETRIC}, 0, 0, STATIC, "intent" }, + { "saturation", "Saturation mapping", 0, AV_OPT_TYPE_CONST, {.i64 = PL_INTENT_SATURATION}, 0, 0, STATIC, "intent" }, #endif { "dithering", "Dither method to use", OFFSET(dithering), AV_OPT_TYPE_INT, {.i64 = PL_DITHER_BLUE_NOISE}, -1, PL_DITHER_METHOD_COUNT - 1, DYNAMIC, "dither" }, From patchwork Mon May 15 08:59:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 41622 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:ba91:b0:105:feb:71f2 with SMTP id fb17csp1456461pzb; Mon, 15 May 2023 02:00:07 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ6z6Crxrg6xekLQvPaVgFYpMHOtYO+RyevhfQ7Mp1pt7iuzkIutqkYne8KH9gbKkkRaVfKO X-Received: by 2002:aa7:c597:0:b0:508:3b23:d84c with SMTP id g23-20020aa7c597000000b005083b23d84cmr28301389edq.1.1684141207178; Mon, 15 May 2023 02:00:07 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1684141207; cv=none; d=google.com; s=arc-20160816; b=0xkzJCy+ALekqPL5r/miOuBjx4UJl+rDA+X4zlPwn3tNUgU/2PlrMQwsNJJ7MaSakn n4uA7PW227Iw7y7r30LuHpL4M5xO1iL4qmZUwyzyTMRdMmmEP0QFeNXuvrNwF4RCJ2Ms J7yqw0cVOHD4QFJG5CZ+M206fR9ym9ioOt3NuhRmuUVtD5gBkCF2lvBXMkww6zwRFwm/ IvEKslsBnVljCX0DR2ciuRuVhkUAmuZ1gLznIrx1mLP4x9qSh130ZMQGlYWZR8mCdh9Z HAS9Jy1mlqgHcd+ySwXjF6zJEl1BhcACP4s04cI3v5AgwcnUkIogpJDVjsOghH+hDcBu +ebQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=5ysZZnfLnPg4tNdqVRD5APPBH/cWNTW+SXY41XHtmeQ=; b=G6RfCKndllXMPqJ5fgQK1NGMFM+GuKtmBuQ7q0HTNdO2SP2msas8Vp1KI7ae6uzHpy 7pkHO8d3o4M+oxN/W3ateCcDLqmF4Fw+9GFBWTZWExCR12ylYbnNE3EYd9l6NqSAujJS 9cclDRmBNf1upuZ20JYVapb4/sdSk44ksWylDoie7i5VzrQpXUfwdX6OIRI1/VmmtBHR 3z/MvhiL790rt94E4bFQ/1hmJ/3VHIyXklqY7l6OfGM5A1Qqr+Sd/EcoALa1wIZdjvfv IvM7Uqfhe8T/lWurCLgqKN2BpGx0GvaUdZmYktV0rCAOBe2D6LsYNIwk0hi8sDojZnOG a6Sg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b=r3Yb9U0j; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id v17-20020aa7cd51000000b0050d83ee816asi11394026edw.494.2023.05.15.02.00.06; Mon, 15 May 2023 02:00:07 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b=r3Yb9U0j; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id E86B468C0B8; Mon, 15 May 2023 11:59:53 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 8518C68B43E for ; Mon, 15 May 2023 11:59:46 +0300 (EEST) Received: from localhost (217-74-0-168.hsi.r-kom.net [217.74.0.168]) by haasn.dev (Postfix) with ESMTPSA id 299A147052; Mon, 15 May 2023 10:59:46 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=haasn.xyz; s=mail; t=1684141186; bh=IWM24/NbnoKN1kyrx6I3xb7e3bF3XKb13brsvl75dDs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=r3Yb9U0jxSekZ0zMirg+a0X0vb5teqolQ+Jkg93M0O154SqIP4a/so3R4yE0k4qq2 sTBRzO0vHPqJljmp760FBIc4okhCOMflNWby9R3bYe9WjibneeakaUVU1iYXw8PypG qhdcMEQG9vHay+STGpdPHWABuuv9yTOPj+ECk2/g= From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Mon, 15 May 2023 10:59:42 +0200 Message-Id: <20230515085943.31760-2-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230515085943.31760-1-ffmpeg@haasn.xyz> References: <20230515085943.31760-1-ffmpeg@haasn.xyz> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 2/3] lavfi/vf_libplacebo: update for new tone mapping API X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: QxgqWIzIV2XI From: Niklas Haas This algorithm has once again been refactored, this time leading to a dropping of the old `tone_mapping_mode` field, to be replaced by a single tunable hybrid mode with configurable strength. We can approximately map the old modes onto the new API for backwards compatibility. Replace deprecated enums by their integer equivalents to safely preserve this API until the next bump. --- doc/filters.texi | 34 +++++--------------------- libavfilter/vf_libplacebo.c | 48 ++++++++++++++++++++----------------- 2 files changed, 32 insertions(+), 50 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 14cb31b95c..510aefc6c9 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -16440,42 +16440,20 @@ For tunable tone mapping functions, this parameter can be used to fine-tune the curve behavior. Refer to the documentation of @code{tonemapping}. The default value of @code{0.0} is replaced by the curve's preferred default setting. -@item tonemapping_mode -This option determines how the tone mapping function specified by -@code{tonemapping} is applied to the colors in a scene. Possible values are: -@table @samp -@item auto -Automatic selection based on internal heuristics. This is the default. -@item rgb -Apply the function per-channel in the RGB colorspace. -Per-channel tone-mapping in RGB. Guarantees no clipping and heavily desaturates -the output, but distorts the colors quite significantly. Very similar to the -"Hollywood" look and feel. -@item max -Tone-mapping is performed on the brightest component found in the signal. Good -at preserving details in highlights, but has a tendency to crush blacks. -@item hybrid -Tone-map per-channel for highlights and linearly (luma-based) for -midtones/shadows, based on a fixed gamma @code{2.4} coefficient curve. -@item luma -Tone-map linearly on the luma component (CIE Y), and adjust (desaturate) the -chromaticities to compensate using a simple constant factor. This is -essentially the mode used in ITU-R BT.2446 method A. -@end table - @item inverse_tonemapping If enabled, this filter will also attempt stretching SDR signals to fill HDR output color volumes. Disabled by default. -@item tonemapping_crosstalk -Extra tone-mapping crosstalk factor, between @code{0.0} and @code{0.3}. This -can help reduce issues tone-mapping certain bright spectral colors. Defaults to -@code{0.04}. - @item tonemapping_lut_size Size of the tone-mapping LUT, between @code{2} and @code{1024}. Defaults to @code{256}. Note that this figure is squared when combined with @code{peak_detect}. + +@item hybrid_mix +If nonzero, this much of the upper range of the tone-mapped result is smoothly +mixed with a per-channel (LMS) tone-mapped version. Helps avoid unnatural +blown-out highlights when tone-mapping very bright, strongly saturated colors. +Defaults to @code{0.2}. @end table @subsubsection Dithering diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index fde8da0b9b..85e431402f 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -249,10 +249,9 @@ typedef struct LibplaceboContext { int gamut_mode; int tonemapping; float tonemapping_param; - int tonemapping_mode; int inverse_tonemapping; - float crosstalk; int tonemapping_lut_size; + float hybrid_mix; #if FF_API_LIBPLACEBO_OPTS /* for backwards compatibility */ @@ -262,6 +261,8 @@ typedef struct LibplaceboContext { int gamut_clipping; int force_icc_lut; int intent; + int tonemapping_mode; + float crosstalk; #endif /* pl_dither_params */ @@ -356,24 +357,23 @@ static int update_settings(AVFilterContext *ctx) { int err = 0; LibplaceboContext *s = ctx->priv; - enum pl_tone_map_mode tonemapping_mode = s->tonemapping_mode; int gamut_mode = s->gamut_mode; + float hybrid_mix = s->hybrid_mix; uint8_t color_rgba[4]; RET(av_parse_color(color_rgba, s->fillcolor, -1, s)); #if FF_API_LIBPLACEBO_OPTS /* backwards compatibility with older API */ - if (!tonemapping_mode && (s->desat_str >= 0.0f || s->desat_exp >= 0.0f)) { - float str = s->desat_str < 0.0f ? 0.9f : s->desat_str; - float exp = s->desat_exp < 0.0f ? 0.2f : s->desat_exp; - if (str >= 0.9f && exp <= 0.1f) { - tonemapping_mode = PL_TONE_MAP_RGB; - } else if (str > 0.1f) { - tonemapping_mode = PL_TONE_MAP_HYBRID; - } else { - tonemapping_mode = PL_TONE_MAP_LUMA; - } + switch (s->tonemapping_mode) { + case 0: /*PL_TONE_MAP_AUTO*/ + if (s->desat_str >= 0.0f) + hybrid_mix = s->desat_str; + break; + case 1: /*PL_TONE_MAP_RGB*/ hybrid_mix = 1.0f; break; + case 2: /*PL_TONE_MAP_HYBRID*/ hybrid_mix = 0.2f; break; + case 3: /*PL_TONE_MAP_LUMA*/ hybrid_mix = 0.0f; break; + case 4: /*PL_TONE_MAP_MAX*/ hybrid_mix = 0.0f; break; } switch (s->intent) { @@ -414,15 +414,18 @@ static int update_settings(AVFilterContext *ctx) s->color_map_params = *pl_color_map_params( #if PL_API_VER >= 269 .gamut_mapping = gamut_funcs[gamut_mode], + .hybrid_mix = hybrid_mix, #else .gamut_mode = gamut_modes[gamut_mode], .intent = intents[gamut_mode], +# if FF_API_LIBPLACEBO_OPTS + .tone_mapping_mode = s->tonemapping_mode, + .tone_mapping_crosstalk = s->crosstalk, +# endif #endif .tone_mapping_function = tonemapping_funcs[s->tonemapping], .tone_mapping_param = s->tonemapping_param, - .tone_mapping_mode = tonemapping_mode, .inverse_tone_mapping = s->inverse_tonemapping, - .tone_mapping_crosstalk = s->crosstalk, .lut_size = s->tonemapping_lut_size, ); @@ -1219,15 +1222,9 @@ static const AVOption libplacebo_options[] = { { "gamma", "Gamma function with knee", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_GAMMA}, 0, 0, STATIC, "tonemap" }, { "linear", "Perceptually linear stretch", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_LINEAR}, 0, 0, STATIC, "tonemap" }, { "tonemapping_param", "Tunable parameter for some tone-mapping functions", OFFSET(tonemapping_param), AV_OPT_TYPE_FLOAT, {.dbl = 0.0}, 0.0, 100.0, .flags = DYNAMIC }, - { "tonemapping_mode", "Tone-mapping mode", OFFSET(tonemapping_mode), AV_OPT_TYPE_INT, {.i64 = PL_TONE_MAP_AUTO}, 0, PL_TONE_MAP_MODE_COUNT - 1, DYNAMIC, "tonemap_mode" }, - { "auto", "Automatic selection", 0, AV_OPT_TYPE_CONST, {.i64 = PL_TONE_MAP_AUTO}, 0, 0, STATIC, "tonemap_mode" }, - { "rgb", "Per-channel (RGB)", 0, AV_OPT_TYPE_CONST, {.i64 = PL_TONE_MAP_RGB}, 0, 0, STATIC, "tonemap_mode" }, - { "max", "Maximum component", 0, AV_OPT_TYPE_CONST, {.i64 = PL_TONE_MAP_MAX}, 0, 0, STATIC, "tonemap_mode" }, - { "hybrid", "Hybrid of Luma/RGB", 0, AV_OPT_TYPE_CONST, {.i64 = PL_TONE_MAP_HYBRID}, 0, 0, STATIC, "tonemap_mode" }, - { "luma", "Luminance", 0, AV_OPT_TYPE_CONST, {.i64 = PL_TONE_MAP_LUMA}, 0, 0, STATIC, "tonemap_mode" }, { "inverse_tonemapping", "Inverse tone mapping (range expansion)", OFFSET(inverse_tonemapping), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC }, - { "tonemapping_crosstalk", "Crosstalk factor for tone-mapping", OFFSET(crosstalk), AV_OPT_TYPE_FLOAT, {.dbl = 0.04}, 0.0, 0.30, DYNAMIC }, { "tonemapping_lut_size", "Tone-mapping LUT size", OFFSET(tonemapping_lut_size), AV_OPT_TYPE_INT, {.i64 = 256}, 2, 1024, DYNAMIC }, + { "hybrid_mix", "Tone-mapping hybrid LMS mixing coefficient", OFFSET(hybrid_mix), AV_OPT_TYPE_FLOAT, {.dbl = 0.20}, 0.0, 1.00, DYNAMIC }, #if FF_API_LIBPLACEBO_OPTS /* deprecated options for backwards compatibility, defaulting to -1 to not override the new defaults */ @@ -1240,6 +1237,13 @@ static const AVOption libplacebo_options[] = { { "relative", "Relative colorimetric", 0, AV_OPT_TYPE_CONST, {.i64 = PL_INTENT_RELATIVE_COLORIMETRIC}, 0, 0, STATIC, "intent" }, { "absolute", "Absolute colorimetric", 0, AV_OPT_TYPE_CONST, {.i64 = PL_INTENT_ABSOLUTE_COLORIMETRIC}, 0, 0, STATIC, "intent" }, { "saturation", "Saturation mapping", 0, AV_OPT_TYPE_CONST, {.i64 = PL_INTENT_SATURATION}, 0, 0, STATIC, "intent" }, + { "tonemapping_mode", "Tone-mapping mode", OFFSET(tonemapping_mode), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 4, DYNAMIC | AV_OPT_FLAG_DEPRECATED, "tonemap_mode" }, + { "auto", "Automatic selection", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, STATIC, "tonemap_mode" }, + { "rgb", "Per-channel (RGB)", 0, AV_OPT_TYPE_CONST, {.i64 = 1}, 0, 0, STATIC, "tonemap_mode" }, + { "max", "Maximum component", 0, AV_OPT_TYPE_CONST, {.i64 = 2}, 0, 0, STATIC, "tonemap_mode" }, + { "hybrid", "Hybrid of Luma/RGB", 0, AV_OPT_TYPE_CONST, {.i64 = 3}, 0, 0, STATIC, "tonemap_mode" }, + { "luma", "Luminance", 0, AV_OPT_TYPE_CONST, {.i64 = 4}, 0, 0, STATIC, "tonemap_mode" }, + { "tonemapping_crosstalk", "Crosstalk factor for tone-mapping", OFFSET(crosstalk), AV_OPT_TYPE_FLOAT, {.dbl = 0.04}, 0.0, 0.30, DYNAMIC | AV_OPT_FLAG_DEPRECATED }, #endif { "dithering", "Dither method to use", OFFSET(dithering), AV_OPT_TYPE_INT, {.i64 = PL_DITHER_BLUE_NOISE}, -1, PL_DITHER_METHOD_COUNT - 1, DYNAMIC, "dither" }, From patchwork Mon May 15 08:59:43 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 41623 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:ba91:b0:105:feb:71f2 with SMTP id fb17csp1456552pzb; Mon, 15 May 2023 02:00:17 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ4sQcuVB6bkKLUM/a2xrlB/J+HnZuQkbrwOJxlLDHXssQKioH+yOBeUR/Dcmwf9O2g1Y4bC X-Received: by 2002:a05:6402:100b:b0:50b:81bf:9e4f with SMTP id c11-20020a056402100b00b0050b81bf9e4fmr23502316edu.12.1684141217182; Mon, 15 May 2023 02:00:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1684141217; cv=none; d=google.com; s=arc-20160816; b=scQ/JjX2y81SlMbxU4bUnVDZGFnSP02IjVGZmztv2jRXNEFqN77CTrk2L6zHck5mc7 bjMZDlUJvyivq95jI6HHM3NbNr7rCmWuel4U9lj0McYGOiXcwwZ3QFadDXKcB0Z9uVX5 S2GTdgv9zy3afJ2QfU8ON/VS4gA1baL4VDaRJeHbOmDDTfcJp1hHgVLb5SOkmk+zy3KZ IXosvM8Moa6DMvzS1RtoIFDnW64u2I70uRLsHh2gp9JivLjxcZRtpZWEJGOlWcuUhLNN 3syps3ho7h/qgpXt3U0GdYbQHilK0mM/YgXvAdP91OjTAR6Orlx2CSrzmHgDXIV4246z UXOA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=KSRPIDKNjJGRzZadAcc50xaSf0e9RDhVnx8p5Y6iwaw=; b=MclSVw84bS9paiDwhDkRouzNkfW4IVWbLJYXeAKMLjo2fnKwv9i0exQfdfcwkDDkKW WowhBS6m99CsLnn2TAqlE4vpJHgCtftO0QoXb2PfIGogui98CAIkRQuBUYa9u847PUXP CwVB2txnCM1Xj7ZTedcAa8+HTLHiH96HOntJiZJJYPkT2ILj2e6KSLTliCVUJX6FrktE PjDufGfrcOp+HNxUewsWiIe1fsjjC7qZjDopwY2ZeQ82bZtQddU4Cjv5v8uAsU1tsuUi lLufHIFpIZJ6BVUD5x8k6zmEYZaTEXHZtgI8UF441WgJJgDdg3ut70Sx8U++kdU7Vtse mhCA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b=rvRoviy1; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id d22-20020aa7ce16000000b0050db7e5fdd4si11422591edv.245.2023.05.15.02.00.16; Mon, 15 May 2023 02:00:17 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b=rvRoviy1; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id F0EF068C0CD; Mon, 15 May 2023 11:59:54 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 1BB6268B43E for ; Mon, 15 May 2023 11:59:47 +0300 (EEST) Received: from localhost (217-74-0-168.hsi.r-kom.net [217.74.0.168]) by haasn.dev (Postfix) with ESMTPSA id CA4864994A; Mon, 15 May 2023 10:59:46 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=haasn.xyz; s=mail; t=1684141186; bh=ZiSg6ezniR/DA+HaO1XEd39xDbh97hbbRVdZWci4NBc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=rvRoviy1uGv8LkNvqI9fulOwPXuO6THLP9QvfC0YtSk0ikWka2CB4PfBQDbrYqDqt TL0eBJe+APbBKb3PUmiueUsbwoe/L8feBAUKkctW1HCDsoMj/0StjflqTis1gjTm7H fXWW+t6iCu+GbG64570g+mqUD1jEyIY7O8AGhVxA= From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Mon, 15 May 2023 10:59:43 +0200 Message-Id: <20230515085943.31760-3-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230515085943.31760-1-ffmpeg@haasn.xyz> References: <20230515085943.31760-1-ffmpeg@haasn.xyz> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 3/3] lavfi/vf_libplacebo: update peak detection options X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: X/WZiw/0E1gh From: Niklas Haas Upstream peak detection lost one option and gained one option. Update code and documentation as required. --- doc/filters.texi | 9 +++++---- libavfilter/vf_libplacebo.c | 11 +++++++++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 510aefc6c9..3cd978e751 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -16320,10 +16320,11 @@ logarithmic scale between @code{0.0} and @code{100.0}. Default to @code{5.5} and @code{10.0}, respectively. Setting either to a negative value disables this functionality. -@item overshoot -Peak smoothing overshoot margin, between @code{0.0} and @code{1.0}. Provides a -safety margin to prevent clipping as a result of peak smoothing. Defaults to -@code{0.05}, corresponding to a margin of 5%. +@item percentile +Which percentile of the frame brightness histogram to use as the source peak +for tone-mapping. Defaults to @code{99.995}, a fairly conservative value. +Setting this to @code{100.0} disables frame histogram measurement and instead +uses the true peak brightness for tone-mapping. @end table @subsubsection Tone mapping diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 85e431402f..96822d0e57 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -242,7 +242,7 @@ typedef struct LibplaceboContext { float min_peak; float scene_low; float scene_high; - float overshoot; + float percentile; /* pl_color_map_params */ struct pl_color_map_params color_map_params; @@ -263,6 +263,7 @@ typedef struct LibplaceboContext { int intent; int tonemapping_mode; float crosstalk; + float overshoot; #endif /* pl_dither_params */ @@ -408,7 +409,12 @@ static int update_settings(AVFilterContext *ctx) .minimum_peak = s->min_peak, .scene_threshold_low = s->scene_low, .scene_threshold_high = s->scene_high, +#if PL_API_VER >= 263 + .percentile = s->percentile, +#endif +#if FF_API_LIBPLACEBO_OPTS && PL_API_VER < 256 .overshoot_margin = s->overshoot, +#endif ); s->color_map_params = *pl_color_map_params( @@ -1194,7 +1200,7 @@ static const AVOption libplacebo_options[] = { { "minimum_peak", "Peak detection minimum peak", OFFSET(min_peak), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 0.0, 100.0, DYNAMIC }, { "scene_threshold_low", "Scene change low threshold", OFFSET(scene_low), AV_OPT_TYPE_FLOAT, {.dbl = 5.5}, -1.0, 100.0, DYNAMIC }, { "scene_threshold_high", "Scene change high threshold", OFFSET(scene_high), AV_OPT_TYPE_FLOAT, {.dbl = 10.0}, -1.0, 100.0, DYNAMIC }, - { "overshoot", "Tone-mapping overshoot margin", OFFSET(overshoot), AV_OPT_TYPE_FLOAT, {.dbl = 0.05}, 0.0, 1.0, DYNAMIC }, + { "percentile", "Peak detection percentile", OFFSET(percentile), AV_OPT_TYPE_FLOAT, {.dbl = 99.995}, 0.0, 100.0, DYNAMIC }, { "gamut_mode", "Gamut-mapping mode", OFFSET(gamut_mode), AV_OPT_TYPE_INT, {.i64 = GAMUT_MAP_PERCEPTUAL}, 0, GAMUT_MAP_COUNT - 1, DYNAMIC, "gamut_mode" }, { "clip", "Hard-clip (RGB per-channel)", 0, AV_OPT_TYPE_CONST, {.i64 = GAMUT_MAP_CLIP}, 0, 0, STATIC, "gamut_mode" }, @@ -1244,6 +1250,7 @@ static const AVOption libplacebo_options[] = { { "hybrid", "Hybrid of Luma/RGB", 0, AV_OPT_TYPE_CONST, {.i64 = 3}, 0, 0, STATIC, "tonemap_mode" }, { "luma", "Luminance", 0, AV_OPT_TYPE_CONST, {.i64 = 4}, 0, 0, STATIC, "tonemap_mode" }, { "tonemapping_crosstalk", "Crosstalk factor for tone-mapping", OFFSET(crosstalk), AV_OPT_TYPE_FLOAT, {.dbl = 0.04}, 0.0, 0.30, DYNAMIC | AV_OPT_FLAG_DEPRECATED }, + { "overshoot", "Tone-mapping overshoot margin", OFFSET(overshoot), AV_OPT_TYPE_FLOAT, {.dbl = 0.05}, 0.0, 1.0, DYNAMIC | AV_OPT_FLAG_DEPRECATED }, #endif { "dithering", "Dither method to use", OFFSET(dithering), AV_OPT_TYPE_INT, {.i64 = PL_DITHER_BLUE_NOISE}, -1, PL_DITHER_METHOD_COUNT - 1, DYNAMIC, "dither" },