diff --git a/.gitmodules b/.gitmodules
index 2f71ef8..8ae5c00 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -4,6 +4,3 @@
[submodule "dovi_tool"]
path = dovi_tool
url = https://github.com/quietvoid/dovi_tool
-[submodule "libp2p"]
- path = libp2p
- url = https://github.com/sekrit-twc/libp2p
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d24ff95..c8f7aeb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,15 @@
+##### 1.2.0:
+ Shader/Tonemap: added trc ST428.
+ Tonemap: added parameters percentile, metadata, visualize_lut, show_clipping.
+ Tonemap: added tone_mapping_function st2094_40, st2094_10.
+ Shader/Tonemap: improved speed. (based on https://github.com/Lypheo/vs-placebo/commit/09075cf2a3768b7c87903bb23640916b0b3b68cc)
+ Tonemap: added support for libdovi 3. (based on https://github.com/Lypheo/vs-placebo/commit/f65161b7dd167b60e7af4670a692c6df3c40de6e)
+ Removed libp2p dependency.
+ Tonemap: fixed wrong levels when output is SDR.
+ Tonemap: remove HDR frame props when output is SDR.
+ Tonemap: added support for libplacebo v5.264.0. (based on https://github.com/Lypheo/vs-placebo/commit/4a42255c880572d75c8b50b69b784a67fd93e241)
+ Shader: removed shader_param limit.
+
##### 1.1.5:
libplacebo_Tonemap: fixed `dst_min`.
diff --git a/README.md b/README.md
index 99f743d..9b9845f 100644
--- a/README.md
+++ b/README.md
@@ -260,14 +260,15 @@ libplacebo_Resample(clip input, int width, int height, string "filter", float "r
7: GAMMA24 (Pure power gamma 2.4)\
8: GAMMA26 (Pure power gamma 2.6)\
9: GAMMA28 (Pure power gamma 2.8)\
- 10: PRO_PHOTO (ProPhoto RGB (ROMM))
+ 10: PRO_PHOTO (ProPhoto RGB (ROMM))\
+ 11: ST428 (Digital Cinema Distribution Master (XYZ))
High dynamic range:\
- 11: PQ (ITU-R BT.2100 PQ (perceptual quantizer), aka SMPTE ST2048)\
- 12: HLG (ITU-R BT.2100 HLG (hybrid log-gamma), aka ARIB STD-B67)\
- 13: V_LOG (Panasonic V-Log (VARICAM))\
- 14: S_LOG1 (Sony S-Log1)\
- 15: S_LOG2 (Sony S-Log2)
+ 12: PQ (ITU-R BT.2100 PQ (perceptual quantizer), aka SMPTE ST2048)\
+ 13: HLG (ITU-R BT.2100 HLG (hybrid log-gamma), aka ARIB STD-B67)\
+ 14: V_LOG (Panasonic V-Log (VARICAM))\
+ 15: S_LOG1 (Sony S-Log1)\
+ 16: S_LOG2 (Sony S-Log2)
Default: 1.
@@ -363,14 +364,15 @@ libplacebo_Shader(clip input, string shader, int "width", int "height", int "chr
7: GAMMA24 (Pure power gamma 2.4)\
8: GAMMA26 (Pure power gamma 2.6)\
9: GAMMA28 (Pure power gamma 2.8)\
- 10: PRO_PHOTO (ProPhoto RGB (ROMM))
+ 10: PRO_PHOTO (ProPhoto RGB (ROMM))\
+ 11: ST428 (Digital Cinema Distribution Master (XYZ))
High dynamic range:\
- 11: PQ (ITU-R BT.2100 PQ (perceptual quantizer), aka SMPTE ST2048)\
- 12: HLG (ITU-R BT.2100 HLG (hybrid log-gamma), aka ARIB STD-B67)\
- 13: V_LOG (Panasonic V-Log (VARICAM))\
- 14: S_LOG1 (Sony S-Log1)\
- 15: S_LOG2 (Sony S-Log2)
+ 12: PQ (ITU-R BT.2100 PQ (perceptual quantizer), aka SMPTE ST2048)\
+ 13: HLG (ITU-R BT.2100 HLG (hybrid log-gamma), aka ARIB STD-B67)\
+ 14: V_LOG (Panasonic V-Log (VARICAM))\
+ 15: S_LOG1 (Sony S-Log1)\
+ 16: S_LOG2 (Sony S-Log2)
Default: 1.
@@ -535,6 +537,12 @@ libplacebo_Tonemap(clip input, int "src_csp", float "dst_csp", float "src_max",
To disable this logic entirely, set either one to a negative value.\
Default: scene_threshold_low = 5.5; scene_threshold_high = 10.0
+- percentile\
+ Which percentile of the input image brightness histogram to consider as the true peak of the scene.\
+ If this is set to 100 (or 0), the brightest pixel is measured. Otherwise, the top of the frequency distribution is progressively cut off.\
+ Setting this too low will cause clipping of very bright details, but can improve the dynamic brightness range of scenes with very bright isolated highlights.\
+ The default of 99.995% is very conservative and should cause no major issues in typical content.
+
- intent\
The rendering intent to use for gamut mapping.\
0: PERCEPTUAL\
@@ -557,32 +565,43 @@ libplacebo_Tonemap(clip input, int "src_csp", float "dst_csp", float "src_max",
1: clip (Performs no tone-mapping, just clips out-of-range colors.\
Retains perfect color accuracy for in-range colors but completely destroys out-of-range information.\
Does not perform any black point adaptation.)\
- 2: bt2390 (EETF from the ITU-R Report BT.2390, a hermite spline roll-off with linear segment.\
+ 2: st2094_40 (EETF from SMPTE ST 2094-40 Annex B, which uses the provided OOTF based on Bezier curves to perform tone-mapping.\
+ The OOTF used is adjusted based on the ratio between the targeted and actual display peak luminances.\
+ In the absence of HDR10+ metadata, falls back to a simple constant bezier curve with tunable knee point.\
+ The `tone_mapping_param` gives the target brightness adaptation strength for the knee point, defaulting to 0.7.)\
+ 3: st2094_10 (EETF from SMPTE ST 2094-10 Annex B.2, which takes into account the input signal average luminance in addition to the maximum/minimum.\
+ The `tone_mapping_param` gives the target brightness adaptation strength for the knee point, defaulting to 0.5.\
+ Note: This does *not* currently include the subjective gain/offset/gamma controls defined in Annex B.3.)\
+ 4: bt2390 (EETF from the ITU-R Report BT.2390, a hermite spline roll-off with linear segment.\
The knee point offset is configurable. Note that this defaults to 1.0, rather than the value of 0.5 from the ITU-R spec.)\
- 3: bt2446a (EETF from ITU-R Report BT.2446, method A.\
+ 5: bt2446a (EETF from ITU-R Report BT.2446, method A.\
Can be used for both forward and inverse tone mapping. Not configurable.)\
- 4: spline (Simple spline consisting of two polynomials, joined by a single pivot point.\
- The `tone_mapping_param` gives the pivot point (in PQ space), defaulting to 0.30.\
- Can be used for both forward and inverse tone mapping.)\
- 5: reinhard (Simple non-linear, global tone mapping algorithm.\
+ 6: spline (Simple spline consisting of two polynomials, joined by a single pivot point.\
+ Simple spline consisting of two polynomials, joined by a single pivot point, which is tuned based on the source scene average brightness (taking into account HDR10+ metadata if available).\
+ The `tone_mapping_param` can be used to tune the desired subjective contrast characteristics.\
+ Higher values make the curve steeper (closer to `clip`), preserving midtones at the cost of losing shadow/highlight details, while lower values make the curve shallower (closer to `linear`), preserving highlights at the cost of losing midtone contrast.\
+ Values above 1.0 are possible, resulting in an output with more contrast than the input.\
+ The default value is 0.5.\
+ This function can be used for both forward and inverse tone mapping.
+ 7: reinhard (Simple non-linear, global tone mapping algorithm.\
Named after Erik Reinhard.\
The `tone_mapping_param` specifies the local contrast coefficient at the display peak.\
Essentially, a value of param=0.5 implies that the reference white will be about half as bright as when clipping.\
Defaults to 0.5, which results in the simplest formulation of this function.)\
- 6: mobius (Generalization of the reinhard tone mapping algorithm to support an additional linear slope near black.\
+ 8: mobius (Generalization of the reinhard tone mapping algorithm to support an additional linear slope near black.\
The tone mapping `tone_mapping_param` indicates the trade-off between the linear section and the non-linear section.\
Essentially, for param=0.5, every color value below 0.5 will be mapped linearly, with the higher values being non-linearly tone mapped.\
Values near 1.0 make this curve behave like `clip`, and values near 0.0 make this curve behave like `reinhard`.\
The default value is 0.3, which provides a good balance between colorimetric accuracy and preserving out-of-gamut details.\
The name is derived from its function shape (ax+b)/(cx+d), which is known as a Möbius transformation in mathematics.)\
- 7: hable (Piece-wise, filmic tone-mapping algorithm developed by John Hable for use in Uncharted 2, inspired by a similar tone-mapping algorithm used by Kodak.\
+ 9: hable (Piece-wise, filmic tone-mapping algorithm developed by John Hable for use in Uncharted 2, inspired by a similar tone-mapping algorithm used by Kodak.\
Popularized by its use in video games with HDR rendering.\
Preserves both dark and bright details very well, but comes with the drawback of changing the average brightness quite significantly.\
This is sort of similar to `reinhard` with `tone_mapping_param` 0.24.)\
- 8: gamma (Fits a gamma (power) function to transfer between the source and target color spaces, effectively resulting in a perceptual hard-knee joining two roughly linear sections.\
+ 10: gamma (Fits a gamma (power) function to transfer between the source and target color spaces, effectively resulting in a perceptual hard-knee joining two roughly linear sections.\
This preserves details at all scales fairly accurately, but can result in an image with a muted or dull appearance.\
The `tone_mapping_param` is used as the cutoff point, defaulting to 0.5.)\
- 9: linear (Linearly stretches the input range to the output range, in PQ space.\
+ 11: linear (Linearly stretches the input range to the output range, in PQ space.\
This will preserve all details accurately, but results in a significantly different average brightness.\
Can be used for inverse tone-mapping in addition to regular tone-mapping.\
The parameter can be used as an additional linear gain coefficient (defaulting to 1.0).)\
@@ -607,6 +626,24 @@ libplacebo_Tonemap(clip input, int "src_csp", float "dst_csp", float "src_max",
May help to improve the appearance of very bright, monochromatic highlights.\
Default: 0.04.
+- metadata\
+ Data source to use when tone-mapping.\
+ Setting this to a specific value allows overriding the default metadata preference logic.\
+ 0: ANY\
+ 1: NONE\
+ 2: HDR10 (HDR10 static mastering display metadata)\
+ 3: HDR10PLUS (HDR10+ dynamic metadata)\
+ 4: CIE_Y (CIE Y derived dynamic luminance metadata)
+
+- visualize_lut\
+ Visualize the tone-mapping curve / LUT. (PQ-PQ graph)\
+ Default: False.
+
+- show_clipping\
+ Graphically highlight hard-clipped pixels during tone-mapping (i.e. pixels that exceed the claimed source luminance range).\
+ Note that the difference between this and `gamut_mode=1` is that the latter only shows out-of-gamut colors (that are inside the monitor brightness range), while this shows out-of-range colors (regardless of whether or not they're in-gamut).\
+ Default: False.
+
- use_dovi\
Whether to use the Dolby Vision RPU for ST2086 metadata.\
Defaults to true when tonemapping from Dolby Vision.
@@ -629,18 +666,16 @@ libplacebo_Tonemap(clip input, int "src_csp", float "dst_csp", float "src_max",
Requirements:
- Clang-cl (https://github.com/llvm/llvm-project/releases)
- Vulkan SDK (https://vulkan.lunarg.com/sdk/home#windows)
- - libp2p (https://github.com/sekrit-twc/libp2p)
- dolby_vision C-lib (https://github.com/quietvoid/dovi_tool/blob/main/dolby_vision/README.md)
- libplacebo (https://gitlab.com/uvz/libplacebo)
```
```
Steps:
Install Vulkan SDk.
- Build libp2p.
Build dolby_vision.
Building libplacebo:
- set LIB=%LIB%;C:\VulkanSDK\1.3.224.1\Lib
- meson build -Dvulkan-registry=C:\VulkanSDK\1.3.224.1\share\vulkan\registry\vk.xml --default-library=static --buildtype=release -Ddemos=false -Dopengl=disabled -Dd3d11=disabled
+ set LIB=%LIB%;C:\VulkanSDK\1.3.239.0\Lib
+ meson build -Dvulkan-registry=C:\VulkanSDK\1.3.239.0\share\vulkan\registry\vk.xml --default-library=static --buildtype=release -Ddemos=false -Dopengl=disabled -Dd3d11=disabled
Use solution files to build avs_libplacebo.
```
@@ -648,7 +683,6 @@ libplacebo_Tonemap(clip input, int "src_csp", float "dst_csp", float "src_max",
```
Requirements:
- Vulkan lib
- - libp2p (https://github.com/sekrit-twc/libp2p)
- dolby_vision C-lib (https://github.com/quietvoid/dovi_tool/blob/main/dolby_vision/README.md)
- libplacebo (https://code.videolan.org/videolan/libplacebo)
- AviSynth lib
diff --git a/dovi_tool b/dovi_tool
index 8992e80..e150367 160000
--- a/dovi_tool
+++ b/dovi_tool
@@ -1 +1 @@
-Subproject commit 8992e809590b3a25fecca030ca851ccca8295856
+Subproject commit e1503671bb76ef5904fee74d0ac433044f13c335
diff --git a/libp2p b/libp2p
deleted file mode 160000
index 5e65679..0000000
--- a/libp2p
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 5e65679ae54d0f9fa412ab36289eb2255e341625
diff --git a/libplacebo b/libplacebo
index c87c74a..7b585bf 160000
--- a/libplacebo
+++ b/libplacebo
@@ -1 +1 @@
-Subproject commit c87c74a0852c60ad1a9b64d5679b8fbf9a344a89
+Subproject commit 7b585bf1d353d1984c03620bb2c2cb3f19ffa5f6
diff --git a/msvc/avs_libplacebo.vcxproj b/msvc/avs_libplacebo.vcxproj
index f07052d..e54d32f 100644
--- a/msvc/avs_libplacebo.vcxproj
+++ b/msvc/avs_libplacebo.vcxproj
@@ -39,7 +39,7 @@
DynamicLibrary
true
- llvm
+ v143
DynamicLibrary
@@ -73,13 +73,13 @@
..\..\libplacebo\build_x86\src;..\..\dovi_tool\target\i686-pc-windows-msvc\release;C:\Users\asdq\Downloads\dep_libs\lib;..\..\libp2p\_msvc\Release;..\..\Avisynth_3.7.3_20220419_test1\x86_xp\c_api;$(LibraryPath)
- ..\..\libp2p;..\..\dovi_tool\target\x86_64-pc-windows-msvc\debug\include;D:\libplacebo\build_x64_debug\src\include;C:\VulkanSDK\1.3.231.1\Include;..\..\libplacebo\src\include;..\..\AviSynthPlus\avs_core\include;$(IncludePath)
- ..\..\dovi_tool\target\x86_64-pc-windows-msvc\debug;..\..\libp2p\_msvc\x64\Debug;..\..\AviSynthPlus\build_test\Output\c_api;C:\VulkanSDK\1.3.231.1\Lib;..\..\libplacebo\build_x64_debug\src;$(LibraryPath)
+ ..\..\libp2p;..\..\dovi_tool\dolby_vision\target\x86_64-pc-windows-msvc\release\include;D:\libplacebo\build_x64\src\include;C:\VulkanSDK\1.3.239.0\Include;..\..\libplacebo\src\include;..\..\AviSynthPlus\avs_core\include;$(IncludePath)
+ ..\..\dovi_tool\dolby_vision\target\x86_64-pc-windows-msvc\debug;..\..\libp2p\_msvc\x64\Debug;..\..\AviSynthPlus\build_test\Output\c_api;C:\VulkanSDK\1.3.239.0\Lib;..\..\libplacebo\build_x64\src;$(LibraryPath)
false
- ..\..\libplacebo\build_x64\src\include;..\..\libplacebo\src\include;..\..\dovi_tool\target_\x86_64-pc-windows-msvc\release\include;..\..\libp2p;C:\VulkanSDK\1.3.236.0\Include;..\..\AviSynthPlus\avs_core\include;$(IncludePath)
- ..\..\dovi_tool\target_\x86_64-pc-windows-msvc\release;..\..\libplacebo\build_x64\src;..\..\libp2p\_msvc\x64\Release;C:\VulkanSDK\1.3.236.0\Lib;..\..\AviSynthPlus\build_x64\Output\c_api;$(LibraryPath)
+ ..\libplacebo\build\src\include;..\libplacebo\src\include;..\..\dovi_tool\dolby_vision\target\x86_64-pc-windows-msvc\release\include;C:\VulkanSDK\1.3.239.0\Include;..\..\AviSynthPlus\avs_core\include;$(IncludePath)
+ ..\..\dovi_tool\dolby_vision\target\x86_64-pc-windows-msvc\release;..\libplacebo\build\src;C:\VulkanSDK\1.3.239.0\Lib;..\..\AviSynthPlus\build_x64_clang\Output\c_api;$(LibraryPath)
true
@@ -147,7 +147,7 @@
true
- libplacebo.a;vulkan-1.lib;shaderc_combined.lib;AviSynth.lib;p2p_simd.lib;dovi.lib;ws2_32.lib;bcrypt.lib;Userenv.lib;%(AdditionalDependencies)
+ libplacebo.a;vulkan-1.lib;shaderc_combined.lib;AviSynth.lib;dovi.lib;ws2_32.lib;bcrypt.lib;Userenv.lib;%(AdditionalDependencies)
diff --git a/src/avs_libplacebo.h b/src/avs_libplacebo.h
index 986f5af..9e73b11 100644
--- a/src/avs_libplacebo.h
+++ b/src/avs_libplacebo.h
@@ -6,7 +6,8 @@
#include "avisynth_c.h"
-extern "C" {
+extern "C"
+{
#include
#include
#include
@@ -19,29 +20,6 @@ void avs_libplacebo_uninit(std::unique_ptr p);
AVS_Value devices_info(AVS_Clip* clip, AVS_ScriptEnvironment* env, std::vector& devices, VkInstance& inst, std::string& msg, std::string name, const int device, const int list_device);
-struct format
-{
- int num_comps;
- int bitdepth;
-};
-
-struct plane
-{
- int subx, suby; // subsampling shift
- struct format fmt;
- size_t stride;
- void* data;
-};
-
-#define MAX_PLANES 4
-
-struct image
-{
- int width, height;
- int num_planes;
- struct plane planes[MAX_PLANES];
-};
-
struct priv
{
pl_log log;
@@ -51,8 +29,8 @@ struct priv
pl_shader_obj dither_state;
pl_renderer rr;
- pl_tex tex_in[MAX_PLANES];
- pl_tex tex_out[MAX_PLANES];
+ pl_tex tex_in[4];
+ pl_tex tex_out[4];
};
AVS_Value AVSC_CC create_deband(AVS_ScriptEnvironment* env, AVS_Value args, void* param);
@@ -60,6 +38,7 @@ AVS_Value AVSC_CC create_resample(AVS_ScriptEnvironment* env, AVS_Value args, vo
AVS_Value AVSC_CC create_shader(AVS_ScriptEnvironment* env, AVS_Value args, void* param);
AVS_Value AVSC_CC create_tonemap(AVS_ScriptEnvironment* env, AVS_Value args, void* param);
+[[maybe_unused]]
static AVS_FORCEINLINE AVS_Value set_error(AVS_Clip* clip, const char* error_message)
{
avs_release_clip(clip);
diff --git a/src/avs_libplacebo.rc b/src/avs_libplacebo.rc
index 5eecb64..17a003d 100644
--- a/src/avs_libplacebo.rc
+++ b/src/avs_libplacebo.rc
@@ -1,8 +1,8 @@
#include
VS_VERSION_INFO VERSIONINFO
-FILEVERSION 1,1,5,0
-PRODUCTVERSION 1,1,5,0
+FILEVERSION 1,2,0,0
+PRODUCTVERSION 1,2,0,0
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
FILEFLAGS 0x0L
FILEOS VOS__WINDOWS32
@@ -15,11 +15,11 @@ BEGIN
BEGIN
VALUE "Comments", "AviSynth+ plugin interface to libplacebo."
VALUE "FileDescription", "avs_libplacebo for AviSynth+."
- VALUE "FileVersion", "1.1.5"
+ VALUE "FileVersion", "1.2.0"
VALUE "InternalName", "avs_libplacebo"
VALUE "OriginalFilename", "avs_libplacebo.dll"
VALUE "ProductName", "avs_libplacebo"
- VALUE "ProductVersion", "1.1.5"
+ VALUE "ProductVersion", "1.2.0"
END
END
BLOCK "VarFileInfo"
diff --git a/src/common.cpp b/src/common.cpp
index c93bdea..323be78 100644
--- a/src/common.cpp
+++ b/src/common.cpp
@@ -62,7 +62,7 @@ std::unique_ptr avs_libplacebo_init(VkPhysicalDevice device)
void avs_libplacebo_uninit(std::unique_ptr p)
{
- for (int i{ 0 }; i < MAX_PLANES; ++i)
+ for (int i{ 0 }; i < 4; ++i)
{
pl_tex_destroy(p->gpu, &p->tex_in[i]);
pl_tex_destroy(p->gpu, &p->tex_out[i]);
diff --git a/src/deband.cpp b/src/deband.cpp
index 96854b5..8a1e153 100644
--- a/src/deband.cpp
+++ b/src/deband.cpp
@@ -18,13 +18,11 @@ struct deband
static bool deband_do_plane(priv& p, deband& data, const int planeIdx) noexcept
{
- deband* d{ &data };
-
pl_shader sh{ pl_dispatch_begin(p.dp) };
pl_shader_params sh_p{};
sh_p.gpu = p.gpu;
- sh_p.index = d->frame_index++;
+ sh_p.index = data.frame_index++;
pl_shader_reset(sh, &sh_p);
@@ -32,10 +30,10 @@ static bool deband_do_plane(priv& p, deband& data, const int planeIdx) noexcept
src.tex = p.tex_in[0];
pl_shader_deband(sh, &src, ((planeIdx == AVS_PLANAR_U || planeIdx == AVS_PLANAR_V) &&
- d->deband_params1) ? d->deband_params1.get() : d->deband_params.get());
+ data.deband_params1) ? data.deband_params1.get() : data.deband_params.get());
- if (d->dither)
- pl_shader_dither(sh, p.tex_out[0]->params.format->component_depth[0], &p.dither_state, d->dither_params.get());
+ if (data.dither)
+ pl_shader_dither(sh, p.tex_out[0]->params.format->component_depth[0], &p.dither_state, data.dither_params.get());
pl_dispatch_params d_p{};
d_p.target = p.tex_out[0];
@@ -44,11 +42,9 @@ static bool deband_do_plane(priv& p, deband& data, const int planeIdx) noexcept
return pl_dispatch_finish(p.dp, &d_p);
}
-static int deband_reconfig(priv& priv_, const pl_plane_data& data, AVS_VideoFrame* dst, const int planeIdx)
+static int deband_reconfig(priv& p, const pl_plane_data& data, AVS_VideoFrame* dst, const int planeIdx)
{
- priv* p{ &priv_ };
-
- pl_fmt fmt{ pl_plane_find_fmt(p->gpu, nullptr, &data) };
+ pl_fmt fmt{ pl_plane_find_fmt(p.gpu, nullptr, &data) };
if (!fmt)
return -1;
@@ -59,16 +55,16 @@ static int deband_reconfig(priv& priv_, const pl_plane_data& data, AVS_VideoFram
t_r.sampleable = true;
t_r.host_writable = true;
- if (pl_tex_recreate(p->gpu, &p->tex_in[0], &t_r))
+ if (pl_tex_recreate(p.gpu, &p.tex_in[0], &t_r))
{
- pl_tex_params t_r1{};
- t_r1.w = avs_get_row_size_p(dst, planeIdx) / data.pixel_stride;
- t_r1.h = avs_get_height_p(dst, planeIdx);
- t_r1.format = fmt;
- t_r1.renderable = true;
- t_r1.host_readable = true;
-
- if (!pl_tex_recreate(p->gpu, &p->tex_out[0], &t_r1))
+ t_r.w = avs_get_row_size_p(dst, planeIdx) / data.pixel_stride;
+ t_r.h = avs_get_height_p(dst, planeIdx);
+ t_r.sampleable = false;
+ t_r.host_writable = false;
+ t_r.renderable = true;
+ t_r.host_readable = true;
+
+ if (!pl_tex_recreate(p.gpu, &p.tex_out[0], &t_r))
return -2;
}
else
@@ -77,30 +73,27 @@ static int deband_reconfig(priv& priv_, const pl_plane_data& data, AVS_VideoFram
return 0;
}
-static int deband_filter(priv& priv_, AVS_VideoFrame* dst, const pl_plane_data& data, deband& d, const int planeIdx)
+static int deband_filter(priv& p, AVS_VideoFrame* dst, const pl_plane_data& data, deband& d, const int planeIdx)
{
- priv* p{ &priv_ };
-
// Upload planes
pl_tex_transfer_params ttr{};
- ttr.tex = p->tex_in[0];
+ ttr.tex = p.tex_in[0];
ttr.row_pitch = data.row_stride;
ttr.ptr = const_cast(data.pixels);
- if (!pl_tex_upload(p->gpu, &ttr))
+ if (!pl_tex_upload(p.gpu, &ttr))
return -1;
// Process plane
- if (!deband_do_plane(*p, d, planeIdx))
+ if (!deband_do_plane(p, d, planeIdx))
return -2;
- pl_tex_transfer_params ttr1{};
- ttr1.tex = p->tex_out[0];
- ttr1.row_pitch = avs_get_pitch_p(dst, planeIdx);
- ttr1.ptr = reinterpret_cast(avs_get_write_ptr_p(dst, planeIdx));
+ ttr.tex = p.tex_out[0];
+ ttr.row_pitch = avs_get_pitch_p(dst, planeIdx);
+ ttr.ptr = reinterpret_cast(avs_get_write_ptr_p(dst, planeIdx));
// Download planes
- if (!pl_tex_download(p->gpu, &ttr1))
+ if (!pl_tex_download(p.gpu, &ttr))
return -3;
return 0;
diff --git a/src/plugin.cpp b/src/plugin.cpp
index 4a11fd8..d2ba9e8 100644
--- a/src/plugin.cpp
+++ b/src/plugin.cpp
@@ -5,7 +5,7 @@ static const char* AVSC_CC avisynth_c_plugin_init(AVS_ScriptEnvironment* env)
avs_add_function(env, "libplacebo_Deband", "c[iterations]i[threshold]f[radius]f[grainY]f[grainC]f[dither]i[lut_size]i[temporal]b[planes]i*[device]i[list_device]b[grain_neutral]f*", create_deband, 0);
avs_add_function(env, "libplacebo_Resample", "cii[filter]s[radius]f[clamp]f[taper]f[blur]f[param1]f[param2]f[sx]f[sy]f[antiring]f[lut_entries]i[cutoff]f[sigmoidize]b[linearize]b[sigmoid_center]f[sigmoid_slope]f[trc]i[cplace]i[device]i[list_device]b[src_width]f[src_height]f", create_resample, 0);
avs_add_function(env, "libplacebo_Shader", "cs[width]i[height]i[chroma_loc]i[matrix]i[trc]i[filter]s[radius]f[clamp]f[taper]f[blur]f[param1]f[param2]f[antiring]f[lut_entries]i[cutoff]f[sigmoidize]b[linearize]b[sigmoid_center]f[sigmoid_slope]f[shader_param]s[device]i[list_device]b", create_shader, 0);
- avs_add_function(env, "libplacebo_Tonemap", "c[src_csp]i[dst_csp]i[src_max]f[src_min]f[dst_max]f[dst_min]f[dynamic_peak_detection]b[smoothing_period]f[scene_threshold_low]f[scene_threshold_high]f[intent]i[gamut_mode]i[tone_mapping_function]i[tone_mapping_mode]i[tone_mapping_param]f[tone_mapping_crosstalk]f[use_dovi]b[device]i[list_device]b", create_tonemap, 0);
+ avs_add_function(env, "libplacebo_Tonemap", "c[src_csp]i[dst_csp]i[src_max]f[src_min]f[dst_max]f[dst_min]f[dynamic_peak_detection]b[smoothing_period]f[scene_threshold_low]f[scene_threshold_high]f[percentile]f[intent]i[gamut_mode]i[tone_mapping_function]i[tone_mapping_mode]i[tone_mapping_param]f[tone_mapping_crosstalk]f[metadata]i[visualize_lut]b[show_clipping]b[use_dovi]b[device]i[list_device]b", create_tonemap, 0);
return "avslibplacebo";
}
diff --git a/src/resample.cpp b/src/resample.cpp
index 0e8bd42..e6020e7 100644
--- a/src/resample.cpp
+++ b/src/resample.cpp
@@ -27,17 +27,15 @@ struct resample
static int resample_do_plane(priv& p, resample& data, const int w, const int h, const float sx, const float sy, const int planeIdx)
{
- resample* d{ &data };
-
pl_shader sh{ pl_dispatch_begin(p.dp) };
pl_tex sample_fbo{};
pl_tex sep_fbo{};
- pl_sample_filter_params sample_params{ *d->sample_params.get() };
- sample_params.lut = &d->lut;
+ pl_sample_filter_params sample_params{ *data.sample_params.get() };
+ sample_params.lut = &data.lut;
pl_color_space cs{};
- cs.transfer = d->trc;
+ cs.transfer = data.trc;
pl_sample_src src{};
src.tex = p.tex_in[0];
@@ -59,11 +57,11 @@ static int resample_do_plane(priv& p, resample& data, const int w, const int h,
pl_shader_sample_direct(ish, &src);
- if (d->linear)
+ if (data.linear)
pl_shader_linearize(ish, &cs);
- if (d->sigmoid_params.get())
- pl_shader_sigmoidize(ish, d->sigmoid_params.get());
+ if (data.sigmoid_params.get())
+ pl_shader_sigmoidize(ish, data.sigmoid_params.get());
pl_dispatch_params dp{};
dp.target = sample_fbo;
@@ -78,16 +76,16 @@ static int resample_do_plane(priv& p, resample& data, const int w, const int h,
const float src_w{ [&]()
{
- if (d->src_width > -1.0f)
- return (planeIdx == AVS_PLANAR_U || planeIdx == AVS_PLANAR_V) ? (d->src_width / d->subw) : d->src_width;
+ if (data.src_width > -1.0f)
+ return (planeIdx == AVS_PLANAR_U || planeIdx == AVS_PLANAR_V) ? (data.src_width / data.subw) : data.src_width;
else
return static_cast(p.tex_in[0]->params.w);
}() };
const float src_h{ [&]()
{
- if (d->src_height > -1.0f)
- return (planeIdx == AVS_PLANAR_U || planeIdx == AVS_PLANAR_V) ? (d->src_height / d->subh) : d->src_height;
+ if (data.src_height > -1.0f)
+ return (planeIdx == AVS_PLANAR_U || planeIdx == AVS_PLANAR_V) ? (data.src_height / data.subh) : data.src_height;
else
return static_cast(p.tex_in[0]->params.h);
}() };
@@ -99,7 +97,7 @@ static int resample_do_plane(priv& p, resample& data, const int w, const int h,
src.new_h = h;
src.new_w = w;
- if (d->sample_params->filter.polar)
+ if (data.sample_params->filter.polar)
{
if (!pl_shader_sample_polar(sh, &src, &sample_params))
return 3;
@@ -114,42 +112,33 @@ static int resample_do_plane(priv& p, resample& data, const int w, const int h,
return 4;
}
- pl_sample_src src2{ src };
-
- pl_tex_params tp1{};
- tp1.w = src.tex->params.w;
- tp1.h = src.new_h;
- tp1.renderable = true;
- tp1.sampleable = true;
- tp1.format = src.tex->params.format;
+ tp.h = src.new_h;
- if (!pl_tex_recreate(p.gpu, &sep_fbo, &tp1))
+ if (!pl_tex_recreate(p.gpu, &sep_fbo, &tp))
return 5;
- src2.tex = sep_fbo;
+ src.tex = sep_fbo;
- pl_dispatch_params dp1{};
- dp1.target = sep_fbo;
- dp1.shader = &tsh;
+ dp.target = sep_fbo;
+ dp.shader = &tsh;
- if (!pl_dispatch_finish(p.dp, &dp1))
+ if (!pl_dispatch_finish(p.dp, &dp))
return 6;
- if (!pl_shader_sample_ortho(sh, PL_SEP_HORIZ, &src2, &sample_params))
+ if (!pl_shader_sample_ortho(sh, PL_SEP_HORIZ, &src, &sample_params))
return 7;
}
- if (d->sigmoid_params.get())
- pl_shader_unsigmoidize(sh, d->sigmoid_params.get());
+ if (data.sigmoid_params.get())
+ pl_shader_unsigmoidize(sh, data.sigmoid_params.get());
- if (d->linear)
+ if (data.linear)
pl_shader_delinearize(sh, &cs);
- pl_dispatch_params dp2{};
- dp2.target = p.tex_out[0];
- dp2.shader = &sh;
+ dp.target = p.tex_out[0];
+ dp.shader = &sh;
- if (!pl_dispatch_finish(p.dp, &dp2))
+ if (!pl_dispatch_finish(p.dp, &dp))
return 8;
pl_tex_destroy(p.gpu, &sep_fbo);
@@ -158,11 +147,9 @@ static int resample_do_plane(priv& p, resample& data, const int w, const int h,
return 0;
}
-static int resample_reconfig(priv& priv_, const pl_plane_data& data, const int w, const int h)
+static int resample_reconfig(priv& p, const pl_plane_data& data, const int w, const int h)
{
- priv* p{ &priv_ };
-
- pl_fmt fmt{ pl_plane_find_fmt(p->gpu, nullptr, &data) };
+ pl_fmt fmt{ pl_plane_find_fmt(p.gpu, nullptr, &data) };
if (!fmt)
return -1;
@@ -173,17 +160,17 @@ static int resample_reconfig(priv& priv_, const pl_plane_data& data, const int w
t_r.sampleable = true;
t_r.host_writable = true;
- if (pl_tex_recreate(p->gpu, &p->tex_in[0], &t_r))
+ if (pl_tex_recreate(p.gpu, &p.tex_in[0], &t_r))
{
- pl_tex_params t_r1{};
- t_r1.w = w;
- t_r1.h = h;
- t_r1.format = fmt;
- t_r1.renderable = true;
- t_r1.host_readable = true;
- t_r1.storable = true;
-
- if (!pl_tex_recreate(p->gpu, &p->tex_out[0], &t_r1))
+ t_r.w = w;
+ t_r.h = h;
+ t_r.sampleable = false;
+ t_r.host_writable = false;
+ t_r.renderable = true;
+ t_r.host_readable = true;
+ t_r.storable = true;
+
+ if (!pl_tex_recreate(p.gpu, &p.tex_out[0], &t_r))
return -2;
}
else
@@ -192,31 +179,28 @@ static int resample_reconfig(priv& priv_, const pl_plane_data& data, const int w
return 0;
}
-static int resample_filter(priv& priv_, AVS_VideoFrame* dst, const pl_plane_data& src, resample& d, const int w, const int h, const float sx, const float sy, const int planeIdx)
+static int resample_filter(priv& p, AVS_VideoFrame* dst, const pl_plane_data& src, resample& d, const int w, const int h, const float sx, const float sy, const int planeIdx)
{
- priv* p{ &priv_ };
-
// Upload planes
pl_tex_transfer_params ttr{};
- ttr.tex = p->tex_in[0];
+ ttr.tex = p.tex_in[0];
ttr.row_pitch = src.row_stride;
ttr.ptr = const_cast(src.pixels);
- if (!pl_tex_upload(p->gpu, &ttr))
+ if (!pl_tex_upload(p.gpu, &ttr))
return -1;
// Process plane
- const int proc{ resample_do_plane(*p, d, w, h, sx, sy, planeIdx) };
+ const int proc{ resample_do_plane(p, d, w, h, sx, sy, planeIdx) };
if (proc)
return proc;
- pl_tex_transfer_params ttr1{};
- ttr1.tex = p->tex_out[0];
- ttr1.row_pitch = avs_get_pitch_p(dst, planeIdx);
- ttr1.ptr = reinterpret_cast(avs_get_write_ptr_p(dst, planeIdx));
+ ttr.tex = p.tex_out[0];
+ ttr.row_pitch = avs_get_pitch_p(dst, planeIdx);
+ ttr.ptr = reinterpret_cast(avs_get_write_ptr_p(dst, planeIdx));
// Download planes
- if (!pl_tex_download(p->gpu, &ttr1))
+ if (!pl_tex_download(p.gpu, &ttr))
return -3;
return 0;
diff --git a/src/shader.cpp b/src/shader.cpp
index 64081a8..ebd871f 100644
--- a/src/shader.cpp
+++ b/src/shader.cpp
@@ -26,31 +26,28 @@ struct shader
std::string msg;
};
-static bool shader_do_plane(priv& p, shader& data, const pl_plane& planes_) noexcept
+static bool shader_do_plane(priv& p, const shader& data, const pl_plane* planes) noexcept
{
- shader* d{ &data };
- const pl_plane* pl{ &planes_ };
-
pl_color_repr crpr{};
crpr.bits.bit_shift = 0;
crpr.bits.color_depth = 16;
crpr.bits.sample_depth = 16;
- crpr.sys = d->matrix;
- crpr.levels = d->range;
+ crpr.sys = data.matrix;
+ crpr.levels = data.range;
pl_color_space csp{};
- csp.transfer = d->trc;
+ csp.transfer = data.trc;
pl_frame img{};
img.num_planes = 3;
img.repr = crpr;
- img.planes[0] = pl[0];
- img.planes[1] = pl[1];
- img.planes[2] = pl[2];
+ img.planes[0] = planes[0];
+ img.planes[1] = planes[1];
+ img.planes[2] = planes[2];
img.color = csp;
- if (d->subw || d->subh)
- pl_frame_set_chroma_location(&img, d->chromaLocation);
+ if (data.subw || data.subh)
+ pl_frame_set_chroma_location(&img, data.chromaLocation);
pl_frame out{};
out.num_planes = 3;
@@ -65,97 +62,75 @@ static bool shader_do_plane(priv& p, shader& data, const pl_plane& planes_) noex
}
pl_render_params renderParams{};
- renderParams.hooks = &d->shader;
+ renderParams.hooks = &data.shader;
renderParams.num_hooks = 1;
- renderParams.sigmoid_params = d->sigmoid_params.get();
- renderParams.disable_linear_scaling = !d->linear;
- renderParams.upscaler = &d->sample_params->filter;
- renderParams.downscaler = &d->sample_params->filter;
- renderParams.antiringing_strength = d->sample_params->antiring;
- renderParams.lut_entries = d->sample_params->lut_entries;
- renderParams.polar_cutoff = d->sample_params->cutoff;
+ renderParams.sigmoid_params = data.sigmoid_params.get();
+ renderParams.disable_linear_scaling = !data.linear;
+ renderParams.upscaler = &data.sample_params->filter;
+ renderParams.downscaler = &data.sample_params->filter;
+ renderParams.antiringing_strength = data.sample_params->antiring;
+ renderParams.lut_entries = data.sample_params->lut_entries;
+ renderParams.polar_cutoff = data.sample_params->cutoff;
return pl_render_image(p.rr, &img, &out, &renderParams);
}
-static int shader_reconfig(priv& priv_, const pl_plane_data& data_, shader& d, const int w, const int h)
+static int shader_reconfig(priv& p, const pl_plane_data* data, const shader& d, const int w, const int h)
{
- priv* p{ &priv_ };
- const pl_plane_data* data{ &data_ };
-
- pl_fmt fmt[3];
for (int i{ 0 }; i < 3; ++i)
{
- fmt[i] = pl_plane_find_fmt(p->gpu, nullptr, &data[i]);
- if (!fmt[i])
+ pl_fmt fmt{ pl_plane_find_fmt(p.gpu, nullptr, &data[i]) };
+ if (!fmt)
return -1;
- }
- for (int i{ 0 }; i < 3; ++i)
- {
pl_tex_params t_r{};
t_r.w = data[i].width;
t_r.h = data[i].height;
- t_r.format = fmt[i];
+ t_r.format = fmt;
t_r.sampleable = true;
t_r.host_writable = true;
- if (!pl_tex_recreate(p->gpu, &p->tex_in[i], &t_r))
+ if (!pl_tex_recreate(p.gpu, &p.tex_in[i], &t_r))
return -2;
- }
- for (int i{ 0 }; i < 3; ++i)
- {
- pl_plane_data plane_data{};
- plane_data.type = PL_FMT_UNORM;
- plane_data.component_map[0] = i;
- plane_data.component_pad[0] = 0;
- plane_data.component_size[0] = 16;
- plane_data.pixel_stride = 2;
-
- const pl_fmt out{ pl_plane_find_fmt(p->gpu, nullptr, &plane_data) };
-
- pl_tex_params t_r1{};
- t_r1.w = w;
- t_r1.h = h;
- t_r1.format = out;
- t_r1.renderable = true;
- t_r1.host_readable = true;
-
- if (!pl_tex_recreate(p->gpu, &p->tex_out[i], &t_r1))
+ t_r.w = w;
+ t_r.h = h;
+ t_r.sampleable = false;
+ t_r.host_writable = false;
+ t_r.renderable = true;
+ t_r.host_readable = true;
+
+ if (!pl_tex_recreate(p.gpu, &p.tex_out[i], &t_r))
return -2;
}
return 0;
}
-static int shader_filter(priv& priv_, pl_buf* dst, const pl_plane_data& src_, shader& d, const int dst_stride)
+static int shader_filter(priv& p, const pl_buf* dst, const pl_plane_data* src, shader& d, const int dst_stride)
{
- priv* p{ &priv_ };
- const pl_plane_data* src{ &src_ };
-
// Upload planes
pl_plane planes[3]{};
for (int i{ 0 }; i < 3; ++i)
{
- if (!pl_upload_plane(p->gpu, &planes[i], &p->tex_in[i], &src[i]))
+ if (!pl_upload_plane(p.gpu, &planes[i], &p.tex_in[i], &src[i]))
return -1;
}
// Process plane
- if (!shader_do_plane(*p, d, *planes))
+ if (!shader_do_plane(p, d, planes))
return -2;
// Download planes
for (int i{ 0 }; i < 3; ++i)
{
pl_tex_transfer_params ttr1{};
- ttr1.tex = p->tex_out[i];
+ ttr1.tex = p.tex_out[i];
ttr1.row_pitch = dst_stride;
ttr1.buf = dst[i];
- if (!pl_tex_download(p->gpu, &ttr1))
+ if (!pl_tex_download(p.gpu, &ttr1))
return -3;
}
@@ -187,8 +162,8 @@ static AVS_VideoFrame* AVSC_CC shader_get_frame(AVS_FilterInfo* fi, int n)
constexpr int planes[3]{ AVS_PLANAR_Y, AVS_PLANAR_U, AVS_PLANAR_V };
const int dst_stride = ((avs_get_pitch(dst)) + (d->vf->gpu->limits.align_tex_xfer_pitch) - 1) & ~((d->vf->gpu->limits.align_tex_xfer_pitch) - 1);
- pl_plane_data pl[3]{};
- pl_buf dst_buf[3]{};
+ pl_plane_data pl[4]{};
+ pl_buf dst_buf[4]{};
pl_buf_params buf_params{};
buf_params.size = dst_stride * fi->vi.height;
buf_params.host_mapped = true;
@@ -211,10 +186,10 @@ static AVS_VideoFrame* AVSC_CC shader_get_frame(AVS_FilterInfo* fi, int n)
{
std::lock_guard lck(mtx);
- const int reconf{ shader_reconfig(*d->vf.get(), *pl, *d, fi->vi.width, fi->vi.height) };
+ const int reconf{ shader_reconfig(*d->vf.get(), pl, *d, fi->vi.width, fi->vi.height) };
if (reconf == 0)
{
- const int filt{ shader_filter(*d->vf.get(), dst_buf, *pl, *d, dst_stride) };
+ const int filt{ shader_filter(*d->vf.get(), dst_buf, pl, *d, dst_stride) };
if (filt)
{
diff --git a/src/tonemap.cpp b/src/tonemap.cpp
index 09d9400..5c8d042 100644
--- a/src/tonemap.cpp
+++ b/src/tonemap.cpp
@@ -1,11 +1,10 @@
#include
#include "avs_libplacebo.h"
-#include "p2p_api.h"
-extern "C" {
+extern "C"
#include "libdovi/rpu_parser.h"
-}
+
static std::mutex mtx;
@@ -16,9 +15,9 @@ static std::unique_ptr create_dovi_meta(DoviRpuOpaque& rpu, co
goto done;
{
- const DoviRpuDataMapping* vdm{ dovi_rpu_get_data_mapping(&rpu) };
- if (!vdm)
- goto skip_vdm;
+ const DoviRpuDataMapping* mapping = dovi_rpu_get_data_mapping(&rpu);
+ if (!mapping)
+ goto skip_mapping;
{
const uint64_t bits{ hdr.bl_bit_depth_minus8 + 8 };
@@ -26,53 +25,60 @@ static std::unique_ptr create_dovi_meta(DoviRpuOpaque& rpu, co
for (int c{ 0 }; c < 3; ++c)
{
+ const DoviReshapingCurve curve{ mapping->curves[c] };
+
pl_dovi_metadata::pl_reshape_data* cmp{ &dovi_meta->comp[c] };
+ cmp->num_pivots = curve.pivots.len;
+ memset(cmp->method, curve.mapping_idc, sizeof(cmp->method));
+
uint16_t pivot{ 0 };
- cmp->num_pivots = hdr.num_pivots_minus_2[c] + 2;
for (int pivot_idx{ 0 }; pivot_idx < cmp->num_pivots; ++pivot_idx)
{
- pivot += hdr.pred_pivot_value[c].data[pivot_idx];
+ pivot += curve.pivots.data[pivot_idx];
cmp->pivots[pivot_idx] = static_cast(pivot) / ((1 << bits) - 1);
}
for (int i{ 0 }; i < cmp->num_pivots - 1; ++i)
{
memset(cmp->poly_coeffs[i], 0, sizeof(cmp->poly_coeffs[i]));
- cmp->method[i] = vdm->mapping_idc[c].data[i];
- switch (cmp->method[i])
+ if (curve.polynomial)
{
- case 0: // polynomial
- for (int k{ 0 }; k <= vdm->poly_order_minus1[c].data[i] + 1; ++k)
- {
- int64_t ipart{ vdm->poly_coef_int[c].list[i]->data[k] };
- uint64_t fpart{ vdm->poly_coef[c].list[i]->data[k] };
- cmp->poly_coeffs[i][k] = ipart + scale * fpart;
- }
- break;
- case 1: // MMR
- int64_t ipart{ vdm->mmr_constant_int[c].data[i] };
- uint64_t fpart{ vdm->mmr_constant[c].data[i] };
- cmp->mmr_constant[i] = ipart + scale * fpart;
- cmp->mmr_order[i] = vdm->mmr_order_minus1[c].data[i] + 1;
- for (int j{ 1 }; j <= cmp->mmr_order[i]; ++j)
+ const DoviPolynomialCurve* poly_curve = curve.polynomial;
+
+ for (int k{ 0 }; k <= poly_curve->poly_order_minus1.data[i] + 1; ++k)
+ {
+ int64_t ipart{ poly_curve->poly_coef_int.list[i]->data[k] };
+ uint64_t fpart{ poly_curve->poly_coef.list[i]->data[k] };
+ cmp->poly_coeffs[i][k] = ipart + scale * fpart;
+ }
+ }
+ else if (curve.mmr)
+ {
+ const DoviMMRCurve* mmr_curve = curve.mmr;
+
+ int64_t ipart{ mmr_curve->mmr_constant_int.data[i] };
+ uint64_t fpart{ mmr_curve->mmr_constant.data[i] };
+ cmp->mmr_constant[i] = ipart + scale * fpart;
+ cmp->mmr_order[i] = mmr_curve->mmr_order_minus1.data[i] + 1;
+
+ for (int j{ 0 }; j < cmp->mmr_order[i]; ++j)
+ {
+ for (int k{ 0 }; k < 7; ++k)
{
- for (int k{ 0 }; k < 7; ++k)
- {
- ipart = vdm->mmr_coef_int[c].list[i]->list[j]->data[k];
- fpart = vdm->mmr_coef[c].list[i]->list[j]->data[k];
- cmp->mmr_coeffs[i][j - 1][k] = ipart + scale * fpart;
- }
+ ipart = mmr_curve->mmr_coef_int.list[i]->list[j]->data[k];
+ fpart = mmr_curve->mmr_coef.list[i]->list[j]->data[k];
+ cmp->mmr_coeffs[i][j][k] = ipart + scale * fpart;
}
- break;
+ }
}
}
}
}
- dovi_rpu_free_data_mapping(vdm);
+ dovi_rpu_free_data_mapping(mapping);
}
-skip_vdm:
+skip_mapping:
if (hdr.vdr_dm_metadata_present_flag)
{
@@ -87,12 +93,12 @@ static std::unique_ptr create_dovi_meta(DoviRpuOpaque& rpu, co
const int16_t* src{ &dm_data->ycc_to_rgb_coef0 };
float* dst{ &dovi_meta->nonlinear.m[0][0] };
for (int i{ 0 }; i < 9; ++i)
- dst[i] = src[i] / 8192.0;
+ dst[i] = src[i] / 8192.0f;
src = &dm_data->rgb_to_lms_coef0;
dst = &dovi_meta->linear.m[0][0];
for (int i{ 0 }; i < 9; ++i)
- dst[i] = src[i] / 16384.0;
+ dst[i] = src[i] / 16384.0f;
dovi_rpu_free_vdr_dm_data(dm_data);
}
@@ -131,120 +137,99 @@ struct tonemap
std::unique_ptr dovi_meta;
};
-static bool tonemap_do_plane(priv& p, tonemap& data, const pl_plane& planes_, const pl_color_repr& src_repr, const pl_color_repr& dst_repr) noexcept
+static bool tonemap_do_plane(priv& p, const tonemap& data, const pl_plane* planes, const pl_color_repr& src_repr, const pl_color_repr& dst_repr) noexcept
{
- tonemap* d{ &data };
- const pl_plane* planes{ &planes_ };
-
pl_frame img{};
img.num_planes = 3;
img.repr = src_repr;
img.planes[0] = planes[0];
img.planes[1] = planes[1];
img.planes[2] = planes[2];
- img.color = *d->src_pl_csp;
+ img.color = *data.src_pl_csp;
- if (d->is_subsampled)
- pl_frame_set_chroma_location(&img, d->chromaLocation);
+ if (data.is_subsampled)
+ pl_frame_set_chroma_location(&img, data.chromaLocation);
pl_frame out{};
- out.num_planes = 1;
+ out.num_planes = 3;
out.repr = dst_repr;
- out.color = *d->dst_pl_csp;
+ out.color = *data.dst_pl_csp;
for (int i{ 0 }; i < 3; ++i)
{
- out.planes[i].texture = p.tex_out[0];
- out.planes[i].components = p.tex_out[0]->params.format->num_components;
- out.planes[i].component_mapping[0] = 0;
- out.planes[i].component_mapping[1] = 1;
- out.planes[i].component_mapping[2] = 2;
+ out.planes[i].texture = p.tex_out[i];
+ out.planes[i].components = 1;
+ out.planes[i].component_mapping[0] = i;
}
- return pl_render_image(p.rr, &img, &out, d->render_params.get());
+ return pl_render_image(p.rr, &img, &out, data.render_params.get());
}
-static int tonemap_reconfig(priv& priv_, const pl_plane_data& data)
+static int tonemap_reconfig(priv& p, const pl_plane_data* data)
{
- priv* p{ &priv_ };
-
- pl_fmt fmt{ pl_plane_find_fmt(p->gpu, nullptr, &data) };
- if (!fmt)
- return -1;
-
for (int i{ 0 }; i < 3; ++i)
{
+ pl_fmt fmt{ pl_plane_find_fmt(p.gpu, nullptr, &data[i]) };
+ if (!fmt)
+ return -1;
+
pl_tex_params t_r{};
- t_r.w = data.width;
- t_r.h = data.height;
+ t_r.w = data[i].width;
+ t_r.h = data[i].height;
t_r.format = fmt;
t_r.sampleable = true;
t_r.host_writable = true;
- if (!pl_tex_recreate(p->gpu, &p->tex_in[i], &t_r))
+ if (!pl_tex_recreate(p.gpu, &p.tex_in[i], &t_r))
return -2;
- }
-
- pl_plane_data plane_data{};
- plane_data.type = PL_FMT_UNORM;
- plane_data.pixel_stride = 6;
- plane_data.width = 10;
- plane_data.height = 10;
- plane_data.row_stride = 60;
- plane_data.pixel_stride = 6;
- for (int i{ 0 }; i < 3; ++i)
- {
- plane_data.component_map[i] = i;
- plane_data.component_pad[i] = 0;
- plane_data.component_size[i] = 16;
- }
+ pl_plane_data data1{ data[i] };
+ data1.width = data[0].width;
+ data1.height = data[0].height;
- const pl_fmt out{ pl_plane_find_fmt(p->gpu, nullptr, &plane_data) };
+ const pl_fmt out{ pl_plane_find_fmt(p.gpu, nullptr, &data1) };
- pl_tex_params t_r1{};
- t_r1.w = data.width;
- t_r1.h = data.height;
- t_r1.format = out;
- t_r1.renderable = true;
- t_r1.host_readable = true;
- t_r1.storable = true;
- t_r1.blit_dst = true;
+ t_r.w = data->width;
+ t_r.h = data->height;
+ t_r.format = out;
+ t_r.sampleable = false;
+ t_r.host_writable = false;
+ t_r.renderable = true;
+ t_r.host_readable = true;
- if (!pl_tex_recreate(p->gpu, &p->tex_out[0], &t_r1))
- return -2;
+ if (!pl_tex_recreate(p.gpu, &p.tex_out[i], &t_r))
+ return -2;
+ }
return 0;
}
-static int tonemap_filter(priv& priv_, void* dst, const pl_plane_data& src_, tonemap& d, const pl_color_repr& src_repr, const pl_color_repr& dst_repr)
+static int tonemap_filter(priv& p, const pl_buf* dst, const pl_plane_data* src, const tonemap& d, const pl_color_repr& src_repr, const pl_color_repr& dst_repr, const int dst_stride)
{
- priv* p{ &priv_ };
- const pl_plane_data* src{ &src_ };
-
// Upload planes
pl_plane planes[4]{};
for (int i{ 0 }; i < 3; ++i)
{
- if (!pl_upload_plane(p->gpu, &planes[i], &p->tex_in[i], &src[i]))
+ if (!pl_upload_plane(p.gpu, &planes[i], &p.tex_in[i], &src[i]))
return -1;
}
// Process plane
- if (!tonemap_do_plane(*p, d, *planes, src_repr, dst_repr))
+ if (!tonemap_do_plane(p, d, planes, src_repr, dst_repr))
return -2;
- pl_fmt out_fmt = p->tex_out[0]->params.format;
-
// Download planes
- pl_tex_transfer_params ttr1{};
- ttr1.tex = p->tex_out[0];
- ttr1.row_pitch = (src->row_stride / src->pixel_stride) * out_fmt->texel_size;
- ttr1.ptr = dst;
+ for (int i{ 0 }; i < 3; ++i)
+ {
+ pl_tex_transfer_params ttr1{};
+ ttr1.tex = p.tex_out[i];
+ ttr1.row_pitch = dst_stride;
+ ttr1.buf = dst[i];
- if (!pl_tex_download(p->gpu, &ttr1))
- return -3;
+ if (!pl_tex_download(p.gpu, &ttr1))
+ return -3;
+ }
return 0;
}
@@ -253,13 +238,30 @@ static AVS_VideoFrame* AVSC_CC tonemap_get_frame(AVS_FilterInfo* fi, int n)
{
tonemap* d{ reinterpret_cast(fi->user_data) };
- const char* ErrorText{ 0 };
AVS_VideoFrame* src{ avs_get_frame(fi->child, n) };
if (!src)
return nullptr;
AVS_VideoFrame* dst{ avs_new_video_frame_p(fi->env, &fi->vi, src) };
+ const auto error{ [&](const std::string msg, pl_buf* dst_buf)
+ {
+ avs_release_video_frame(src);
+ avs_release_video_frame(dst);
+
+ if (dst_buf)
+ {
+ for (int i{ 0 }; i < 3; ++i)
+ pl_buf_destroy(d->vf->gpu, &dst_buf[i]);
+ }
+
+ d->msg = msg;
+ fi->error = d->msg.c_str();
+
+ return nullptr;
+ }
+ };
+
int err;
const AVS_Map* props{ avs_get_frame_props_ro(fi->env, src) };
@@ -288,8 +290,6 @@ static AVS_VideoFrame* AVSC_CC tonemap_get_frame(AVS_FilterInfo* fi, int n)
if (d->original_src_min <= 0)
d->src_pl_csp->hdr.min_luma = avs_prop_get_float(fi->env, props, "MasteringDisplayMinLuminance", 0, &err);
- pl_color_space_infer(d->src_pl_csp.get());
-
const double* primariesX{ avs_prop_get_float_array(fi->env, props, "MasteringDisplayPrimariesX", &err) };
const double* primariesY{ avs_prop_get_float_array(fi->env, props, "MasteringDisplayPrimariesY", &err) };
@@ -333,63 +333,66 @@ static AVS_VideoFrame* AVSC_CC tonemap_get_frame(AVS_FilterInfo* fi, int n)
if (doviRpu && doviRpuSize)
{
- // fprintf(stderr, "Got Dolby Vision RPU, size %"PRIi64" at %"PRIxPTR"\n", doviRpuSize, (uintptr_t) doviRpu);
-
DoviRpuOpaque* rpu{ dovi_parse_unspec62_nalu(doviRpu, doviRpuSize) };
const DoviRpuDataHeader* header{ dovi_rpu_get_header(rpu) };
if (!header)
{
- d->msg = "libplacebo_Tonemap: failed parsing RPU: " + std::string(dovi_rpu_get_error(rpu));
- ErrorText = d->msg.c_str();
+ dovi_rpu_free(rpu);
+ return error("libplacebo_Tonemap: failed parsing RPU: " + std::string(dovi_rpu_get_error(rpu)), nullptr);
}
else
{
dovi_profile = header->guessed_profile;
-
d->dovi_meta = create_dovi_meta(*rpu, *header);
dovi_rpu_free_header(header);
}
- if (!ErrorText)
+ // Profile 5, 7 or 8 mapping
+ d->src_repr->sys = PL_COLOR_SYSTEM_DOLBYVISION;
+ d->src_repr->dovi = d->dovi_meta.get();
+
+ if (dovi_profile == 5)
+ d->dst_repr->levels = PL_COLOR_LEVELS_FULL;
+
+ // Update mastering display from RPU
+ if (header->vdr_dm_metadata_present_flag)
{
- // Profile 5, 7 or 8 mapping
- d->src_repr->sys = PL_COLOR_SYSTEM_DOLBYVISION;
- d->src_repr->dovi = d->dovi_meta.get();
+ const DoviVdrDmData* vdr_dm_data{ dovi_rpu_get_vdr_dm_data(rpu) };
- if (dovi_profile == 5)
- d->dst_repr->levels = PL_COLOR_LEVELS_FULL;
+ // Should avoid changing the source black point when mapping to PQ
+ // As the source image already has a specific black point,
+ // and the RPU isn't necessarily ground truth on the actual coded values
- // Update mastering display from RPU
- if (header->vdr_dm_metadata_present_flag)
- {
- const DoviVdrDmData* vdr_dm_data{ dovi_rpu_get_vdr_dm_data(rpu) };
+ // Set target black point to the same as source
+ if (d->dst_csp == CSP_HDR10)
+ d->dst_pl_csp->hdr.min_luma = d->src_pl_csp->hdr.min_luma;
+ else
+ d->src_pl_csp->hdr.min_luma = pl_hdr_rescale(PL_HDR_PQ, PL_HDR_NITS, vdr_dm_data->source_min_pq / 4095.0f);
- // Should avoid changing the source black point when mapping to PQ
- // As the source image already has a specific black point,
- // and the RPU isn't necessarily ground truth on the actual coded values
+ d->src_pl_csp->hdr.max_luma = pl_hdr_rescale(PL_HDR_PQ, PL_HDR_NITS, vdr_dm_data->source_max_pq / 4095.0f);
- // Set target black point to the same as source
- if (d->dst_csp == CSP_HDR10)
- d->dst_pl_csp->hdr.min_luma = d->src_pl_csp->hdr.min_luma;
- else
- d->src_pl_csp->hdr.min_luma = pl_hdr_rescale(PL_HDR_PQ, PL_HDR_NITS, vdr_dm_data->source_min_pq / 4095.0f);
+ if (vdr_dm_data->dm_data.level1)
+ {
+ const DoviExtMetadataBlockLevel1* l1{ vdr_dm_data->dm_data.level1 };
+ d->src_pl_csp->hdr.avg_pq_y = l1->avg_pq / 4095.0f;
+ d->src_pl_csp->hdr.max_pq_y = l1->max_pq / 4095.0f;
+ d->src_pl_csp->hdr.scene_avg = pl_hdr_rescale(PL_HDR_PQ, PL_HDR_NITS, l1->avg_pq / 4095.0f);
+ d->src_pl_csp->hdr.scene_max[0] = d->src_pl_csp->hdr.scene_max[1] = d->src_pl_csp->hdr.scene_max[2] = pl_hdr_rescale(PL_HDR_PQ, PL_HDR_NITS, l1->max_pq / 4095.0f);
+ }
- d->src_pl_csp->hdr.max_luma = pl_hdr_rescale(PL_HDR_PQ, PL_HDR_NITS, vdr_dm_data->source_max_pq / 4095.0f);
+ if (vdr_dm_data->dm_data.level6)
+ {
+ const DoviExtMetadataBlockLevel6* meta{ vdr_dm_data->dm_data.level6 };
- if (vdr_dm_data->dm_data.level6)
+ if (!maxCll || !maxFall)
{
- const DoviExtMetadataBlockLevel6* meta{ vdr_dm_data->dm_data.level6 };
-
- if (!maxCll || !maxFall)
- {
- d->src_pl_csp->hdr.max_cll = meta->max_content_light_level;
- d->src_pl_csp->hdr.max_fall = meta->max_frame_average_light_level;
- }
+ d->src_pl_csp->hdr.max_cll = meta->max_content_light_level;
+ d->src_pl_csp->hdr.max_fall = meta->max_frame_average_light_level;
}
-
- dovi_rpu_free_vdr_dm_data(vdr_dm_data);
}
+
+ dovi_rpu_free_vdr_dm_data(vdr_dm_data);
}
dovi_rpu_free(rpu);
@@ -397,112 +400,109 @@ static AVS_VideoFrame* AVSC_CC tonemap_get_frame(AVS_FilterInfo* fi, int n)
}
}
else
- ErrorText = "libplacebo_Tonemap: DolbyVisionRPU frame property is required for src_csp=3!";
+ return error("libplacebo_Tonemap: DolbyVisionRPU frame property is required for src_csp=3!", nullptr);
}
- if (!ErrorText)
+ pl_color_space_infer_map(d->src_pl_csp.get(), d->dst_pl_csp.get());
+
+ constexpr int planes_y[3]{ AVS_PLANAR_Y, AVS_PLANAR_U, AVS_PLANAR_V };
+ constexpr int planes_r[3]{ AVS_PLANAR_R, AVS_PLANAR_G, AVS_PLANAR_B };
+ const int* planes{ (avs_is_rgb(&fi->vi)) ? planes_r : planes_y };
+ const int dst_stride = ((avs_get_pitch(dst)) + (d->vf->gpu->limits.align_tex_xfer_pitch) - 1) & ~((d->vf->gpu->limits.align_tex_xfer_pitch) - 1);
+ pl_plane_data pl[4]{};
+ pl_buf dst_buf[4]{};
+ pl_buf_params buf_params{};
+ buf_params.size = dst_stride * fi->vi.height;
+ buf_params.host_mapped = true;
+
+ for (int i{ 0 }; i < 3; ++i)
{
- constexpr int planes_y[3]{ AVS_PLANAR_Y, AVS_PLANAR_U, AVS_PLANAR_V };
- constexpr int planes_r[3]{ AVS_PLANAR_R, AVS_PLANAR_G, AVS_PLANAR_B };
- const int* planes{ (avs_is_rgb(&fi->vi)) ? planes_r : planes_y };
- pl_plane_data pl[3]{};
+ pl[i].type = PL_FMT_UNORM;
+ pl[i].width = avs_get_row_size_p(src, planes[i]) / avs_component_size(&fi->vi);
+ pl[i].height = avs_get_height_p(src, planes[i]);
+ pl[i].pixel_stride = 2;
+ pl[i].row_stride = avs_get_pitch_p(src, planes[i]);
+ pl[i].pixels = avs_get_read_ptr_p(src, planes[i]);
+ pl[i].component_size[0] = 16;
+ pl[i].component_pad[0] = 0;
+ pl[i].component_map[0] = i;
+
+ dst_buf[i] = pl_buf_create(d->vf->gpu, &buf_params);
+ }
- for (int i{ 0 }; i < 3; ++i)
- {
- pl[i].type = PL_FMT_UNORM;
- pl[i].width = avs_get_row_size_p(src, planes[i]) / avs_component_size(&fi->vi);
- pl[i].height = avs_get_height_p(src, planes[i]);
- pl[i].pixel_stride = 2;
- pl[i].row_stride = avs_get_pitch_p(src, planes[i]);
- pl[i].pixels = avs_get_read_ptr_p(src, planes[i]);
- pl[i].component_size[0] = 16;
- pl[i].component_pad[0] = 0;
- pl[i].component_map[0] = i;
- }
+ {
+ std::lock_guard lck(mtx);
+ const int reconf{ tonemap_reconfig(*d->vf.get(), pl) };
+ if (reconf == 0)
{
- std::lock_guard lck(mtx);
-
- const int reconf{ tonemap_reconfig(*d->vf.get(), *pl) };
- if (reconf == 0)
- {
- const int filt{ tonemap_filter(*d->vf.get(), d->packed_dst, *pl, *d, *d->src_repr.get(), *d->dst_repr.get()) };
+ const int filt{ tonemap_filter(*d->vf.get(), dst_buf, pl, *d, *d->src_repr.get(), *d->dst_repr.get(), dst_stride) };
- if (filt)
- {
- switch (filt)
- {
- case -1: ErrorText = "libplacebo_Tonemap: failed uploading data to the GPU!"; break;
- case -2: ErrorText = "libplacebo_Tonemap: failed processing planes!"; break;
- default: ErrorText = "libplacebo_Tonemap: failed downloading data from the GPU!";
- }
- }
- }
- else
+ if (filt)
{
- switch (reconf)
+ switch (filt)
{
- case -1: ErrorText = "libplacebo_Tonemap: failed configuring filter: no good texture format!"; break;
- default: ErrorText = "libplacebo_Tonemap: failed creating GPU textures!";
+ case -1: return error("libplacebo_Tonemap: failed uploading data to the GPU!", dst_buf);
+ case -2: return error("libplacebo_Tonemap: failed processing planes!", dst_buf);
+ default: return error("libplacebo_Tonemap: failed downloading data from the GPU!", dst_buf);
}
}
}
-
- if (!ErrorText)
+ else
{
- p2p_buffer_param pack_params{};
- pack_params.width = fi->vi.width;
- pack_params.height = fi->vi.height;
- pack_params.packing = p2p_bgr48_le;
- pack_params.src[0] = d->packed_dst;
- pack_params.src_stride[0] = fi->vi.width * 2 * 3;
-
- for (int k = 0; k < 3; ++k)
+ switch (reconf)
{
- pack_params.dst[k] = avs_get_write_ptr_p(dst, planes[k]);
- pack_params.dst_stride[k] = avs_get_pitch_p(dst, planes[k]);
- }
-
- p2p_unpack_frame(&pack_params, 0);
-
- AVS_Map* props{ avs_get_frame_props_rw(fi->env, dst) };
- avs_prop_set_int(fi->env, props, "_ColorRange", (d->dst_repr->levels = PL_COLOR_LEVELS_FULL) ? 0 : 1, 0);
-
- if (d->dst_pl_csp->transfer == PL_COLOR_TRC_BT_1886)
- {
- avs_prop_set_int(fi->env, props, "_Matrix", (d->dst_repr->sys == PL_COLOR_SYSTEM_RGB) ? 0 : 1, 0);
- avs_prop_set_int(fi->env, props, "_Transfer", 1, 0);
- avs_prop_set_int(fi->env, props, "_Primaries", 1, 0);
- }
- else if (d->dst_pl_csp->transfer == PL_COLOR_TRC_PQ)
- {
- avs_prop_set_int(fi->env, props, "_Matrix", (d->dst_repr->sys == PL_COLOR_SYSTEM_RGB) ? 0 : 9, 0);
- avs_prop_set_int(fi->env, props, "_Transfer", 16, 0);
- avs_prop_set_int(fi->env, props, "_Primaries", 9, 0);
- }
- else
- {
- avs_prop_set_int(fi->env, props, "_Matrix", (d->dst_repr->sys == PL_COLOR_SYSTEM_RGB) ? 0 : 9, 0);
- avs_prop_set_int(fi->env, props, "_Transfer", 18, 0);
- avs_prop_set_int(fi->env, props, "_Primaries", 9, 0);
+ case -1: return error("libplacebo_Tonemap: failed configuring filter: no good texture format!", dst_buf);
+ default: return error("libplacebo_Tonemap: failed creating GPU textures!", dst_buf);
}
+ }
+ }
- if (avs_num_components(&fi->vi) > 3)
- avs_bit_blt(fi->env, avs_get_write_ptr_p(dst, AVS_PLANAR_A), avs_get_pitch_p(dst, AVS_PLANAR_A), avs_get_read_ptr_p(src, AVS_PLANAR_A), avs_get_pitch_p(src, AVS_PLANAR_A),
- avs_get_row_size_p(src, AVS_PLANAR_A), avs_get_height_p(src, AVS_PLANAR_A));
+ for (int i{ 0 }; i < 3; ++i)
+ {
+ while (pl_buf_poll(d->vf->gpu, dst_buf[i], 0));
+ memcpy(avs_get_write_ptr_p(dst, planes[i]), dst_buf[i]->data, dst_buf[i]->params.size);
+ pl_buf_destroy(d->vf->gpu, &dst_buf[i]);
+ }
- avs_release_video_frame(src);
+ AVS_Map* dst_props{ avs_get_frame_props_rw(fi->env, dst) };
+ avs_prop_set_int(fi->env, dst_props, "_ColorRange", (d->dst_repr->levels == PL_COLOR_LEVELS_FULL) ? 0 : 1, 0);
- return dst;
- }
+ if (d->dst_pl_csp->transfer == PL_COLOR_TRC_BT_1886)
+ {
+ avs_prop_set_int(fi->env, dst_props, "_Matrix", (d->dst_repr->sys == PL_COLOR_SYSTEM_RGB) ? 0 : 1, 0);
+ avs_prop_set_int(fi->env, dst_props, "_Transfer", 1, 0);
+ avs_prop_set_int(fi->env, dst_props, "_Primaries", 1, 0);
+
+ avs_prop_delete_key(fi->env, dst_props, "ContentLightLevelMax");
+ avs_prop_delete_key(fi->env, dst_props, "ContentLightLevelAverage");
+ avs_prop_delete_key(fi->env, dst_props, "MasteringDisplayMaxLuminance");
+ avs_prop_delete_key(fi->env, dst_props, "MasteringDisplayMinLuminance");
+ avs_prop_delete_key(fi->env, dst_props, "MasteringDisplayPrimariesX");
+ avs_prop_delete_key(fi->env, dst_props, "MasteringDisplayPrimariesY");
+ avs_prop_delete_key(fi->env, dst_props, "MasteringDisplayWhitePointX");
+ avs_prop_delete_key(fi->env, dst_props, "MasteringDisplayWhitePointY");
+ }
+ else if (d->dst_pl_csp->transfer == PL_COLOR_TRC_PQ)
+ {
+ avs_prop_set_int(fi->env, dst_props, "_Matrix", (d->dst_repr->sys == PL_COLOR_SYSTEM_RGB) ? 0 : 9, 0);
+ avs_prop_set_int(fi->env, dst_props, "_Transfer", 16, 0);
+ avs_prop_set_int(fi->env, dst_props, "_Primaries", 9, 0);
+ }
+ else
+ {
+ avs_prop_set_int(fi->env, dst_props, "_Matrix", (d->dst_repr->sys == PL_COLOR_SYSTEM_RGB) ? 0 : 9, 0);
+ avs_prop_set_int(fi->env, dst_props, "_Transfer", 18, 0);
+ avs_prop_set_int(fi->env, dst_props, "_Primaries", 9, 0);
}
- avs_release_video_frame(src);
- avs_release_video_frame(dst);
+ if (avs_num_components(&fi->vi) > 3)
+ avs_bit_blt(fi->env, avs_get_write_ptr_p(dst, AVS_PLANAR_A), avs_get_pitch_p(dst, AVS_PLANAR_A), avs_get_read_ptr_p(src, AVS_PLANAR_A), avs_get_pitch_p(src, AVS_PLANAR_A),
+ avs_get_row_size_p(src, AVS_PLANAR_A), avs_get_height_p(src, AVS_PLANAR_A));
- fi->error = ErrorText;
+ avs_release_video_frame(src);
- return nullptr;
+ return dst;
}
static void AVSC_CC free_tonemap(AVS_FilterInfo* fi)
@@ -523,8 +523,8 @@ AVS_Value AVSC_CC create_tonemap(AVS_ScriptEnvironment* env, AVS_Value args, voi
{
enum
{
- Clip, Src_csp, Dst_csp, Src_max, Src_min, Dst_max, Dst_min, Dynamic_peak_detection, Smoothing_period, Scene_threshold_low, Scene_threshold_high, Intent, Gamut_mode, Tone_mapping_function, Tone_mapping_mode, Tone_mapping_param,
- Tone_mapping_crosstalk, Use_dovi, Device, List_device
+ Clip, Src_csp, Dst_csp, Src_max, Src_min, Dst_max, Dst_min, Dynamic_peak_detection, Smoothing_period, Scene_threshold_low, Scene_threshold_high, Percentile, Intent, Gamut_mode, Tone_mapping_function, Tone_mapping_mode, Tone_mapping_param,
+ Tone_mapping_crosstalk, Metadata, Visualize_lut, Show_clipping, Use_dovi, Device, List_device
};
AVS_FilterInfo* fi;
@@ -588,6 +588,12 @@ AVS_Value AVSC_CC create_tonemap(AVS_ScriptEnvironment* env, AVS_Value args, voi
params->colorMapParams->tone_mapping_mode = static_cast(avs_as_int(avs_array_elt(args, Tone_mapping_mode)));
if (avs_defined(avs_array_elt(args, Tone_mapping_crosstalk)))
params->colorMapParams->tone_mapping_crosstalk = avs_as_float(avs_array_elt(args, Tone_mapping_crosstalk));
+ if (avs_defined(avs_array_elt(args, Metadata)))
+ params->colorMapParams->metadata = static_cast(avs_as_int(avs_array_elt(args, Metadata)));
+ if (avs_defined(avs_array_elt(args, Visualize_lut)))
+ params->colorMapParams->visualize_lut = avs_as_bool(avs_array_elt(args, Visualize_lut));
+ if (avs_defined(avs_array_elt(args, Show_clipping)))
+ params->colorMapParams->show_clipping = avs_as_bool(avs_array_elt(args, Show_clipping));
params->peakDetectParams = std::make_unique(pl_peak_detect_default_params);
if (avs_defined(avs_array_elt(args, Smoothing_period)))
@@ -596,6 +602,8 @@ AVS_Value AVSC_CC create_tonemap(AVS_ScriptEnvironment* env, AVS_Value args, voi
params->peakDetectParams->scene_threshold_low = avs_as_float(avs_array_elt(args, Scene_threshold_low));
if (avs_defined(avs_array_elt(args, Scene_threshold_high)))
params->peakDetectParams->scene_threshold_high = avs_as_float(avs_array_elt(args, Scene_threshold_high));
+ if (avs_defined(avs_array_elt(args, Percentile)))
+ params->peakDetectParams->percentile = avs_as_float(avs_array_elt(args, Percentile));
params->src_csp = static_cast(avs_defined(avs_array_elt(args, Src_csp)) ? avs_as_int(avs_array_elt(args, Src_csp)) : 1);
@@ -637,15 +645,11 @@ AVS_Value AVSC_CC create_tonemap(AVS_ScriptEnvironment* env, AVS_Value args, voi
params->src_pl_csp->hdr.min_luma = params->original_src_min;
}
- pl_color_space_infer(params->src_pl_csp.get());
-
if (avs_defined(avs_array_elt(args, Dst_max)))
params->dst_pl_csp->hdr.max_luma = avs_as_float(avs_array_elt(args, Dst_max));
if (avs_defined(avs_array_elt(args, Dst_min)))
params->dst_pl_csp->hdr.min_luma = avs_as_float(avs_array_elt(args, Dst_min));
- pl_color_space_infer(params->dst_pl_csp.get());
-
const int peak_detection{ avs_defined(avs_array_elt(args, Dynamic_peak_detection)) ? avs_as_bool(avs_array_elt(args, Dynamic_peak_detection)) : 1 };
params->use_dovi = avs_defined(avs_array_elt(args, Use_dovi)) ? avs_as_bool(avs_array_elt(args, Use_dovi)) : params->src_csp == CSP_DOVI;