diff --git a/NVEncC_Options.en.md b/NVEncC_Options.en.md index cd43a8d2..e2b4fdc6 100644 --- a/NVEncC_Options.en.md +++ b/NVEncC_Options.en.md @@ -211,6 +211,7 @@ - [--vpp-pmd \[\=\\]\[,\=\\],...](#--vpp-pmd-param1value1param2value2) - [--vpp-gauss \](#--vpp-gauss-int) - [--vpp-subburn \[\=\\]\[,\=\\],...](#--vpp-subburn-param1value1param2value2) + - [--vpp-libplacebo-shader \[\=\\]\[,\=\\],...](#--vpp-libplacebo-shader-param1value1param2value2) - [--vpp-resize \ or \[\=\\]\[,\=\\],...](#--vpp-resize-string-or-param1value1param2value2) - [--vpp-unsharp \[\=\\]\[,\=\\],...](#--vpp-unsharp-param1value1param2value2) - [--vpp-edgelevel \[\=\\]\[,\=\\],...](#--vpp-edgelevel-param1value1param2value2) @@ -1655,6 +1656,7 @@ Vpp filters will be applied in fixed order, regardless of the order in the comma - [--vpp-pmd](#--vpp-pmd-param1value1param2value2) - [--vpp-gauss](#--vpp-gauss-int) - [--vpp-subburn](#--vpp-subburn-param1value1param2value2) +- [--vpp-libplacebo-shader](#--vpp-libplacebo-shader-param1value1param2value2) - [--vpp-resize](#--vpp-resize-string-or-param1value1param2value2) - [--vpp-unsharp](#--vpp-unsharp-param1value1param2value2) - [--vpp-edgelevel](#--vpp-edgelevel-param1value1param2value2) @@ -2551,6 +2553,68 @@ The npp dlls can be downloaded from [this link](https://github.com/rigaya/NVEnc/ --vpp-subburn filename="subtitle.sjis.ass",charcode=sjis,shaping=complex ``` +### --vpp-libplacebo-shader [<param1>=<value1>][,<param2>=<value2>],... + +Apply custom shaders in the specified path using [libplacebo](https://code.videolan.org/videolan/libplacebo). + +- **Parameters** + - shader=<string> + Target shader file path. + + - res=<int>x<int> + Output resolution of the filter. + + - colorsystem=<int> + Color system to use. Default: bt709. + ``` + unknown, bt601, bt709, smpte240m, bt2020nc, bt2020c, bt2100pq, bt2100hlg, dolbyvision, ycgco, rgb, xyz + ``` + + - transfer=<string> + Output transfer function. + ``` + unknown, srgb, bt1886, linear, + gamma18, gamma20, gamma22, gamma24, gamma26, gamma28, + prophoto, st428, pq, hlg, vlog, slog1, slog2 + ``` + + - resampler=<string> + Filter function to use when resample is required. Default: libplacebo-ewa-lanczos. + ``` + libplacebo-spline16, libplacebo-spline36, libplacebo-spline64, libplacebo-nearest, + libplacebo-bilinear, libplacebo-gaussian, libplacebo-sinc, libplacebo-lanczos, + libplacebo-ginseng, libplacebo-ewa-jinc, libplacebo-ewa-lanczos, + libplacebo-ewa-lanczossharp, libplacebo-ewa-lanczos4sharpest, + libplacebo-ewa-ginseng, libplacebo-ewa-hann, libplacebo-ewa-hanning, + libplacebo-bicubic, libplacebo-triangle, libplacebo-hermite, libplacebo-catmull-rom, + libplacebo-mitchell, libplacebo-mitchell-clamp, libplacebo-robidoux, + libplacebo-robidouxsharp, libplacebo-ewa-robidoux, libplacebo-ewa-robidouxsharp + ``` + + - radius=<float> + Adjust the function's radius. Default: auto. Must be between 0.0 and 16.0. + + - clamp=<float> + Clamping coefficient for negative weights. Default: 0.0. Must be between 0.0 and 1.0. + + - taper=<float> + Additional taper coefficient. Default: 0.0. Must be between 0.0 and 1.0. + + - blur=<float> + Additional blur coefficient. Default: 0.0. Must be between 0.0 and 100.0. + + - antiring=<float> + Antiringing strength. Default: 0.0. Must be between 0.0 and 1.0. + + - linear=<bool> + linearize image bdfore processing. + +- **Examples** + ``` + Example: Apply a custom shader with specific parameters + --vpp-libplacebo-shader-params + ``` + ### --vpp-resize <string> or [<param1>=<value1>][,<param2>=<value2>],... Specify the resizing algorithm. @@ -2691,7 +2755,6 @@ Specify the resizing algorithm. --vpp-resize algo=libplacebo-sinc,pl-radius=3.0,pl-antiring=0.5 ``` - ### --vpp-unsharp [<param1>=<value1>][,<param2>=<value2>],... unsharp filter, for edge and detail enhancement. diff --git a/NVEncC_Options.ja.md b/NVEncC_Options.ja.md index 38861b95..c5643762 100644 --- a/NVEncC_Options.ja.md +++ b/NVEncC_Options.ja.md @@ -207,6 +207,7 @@ - [--vpp-pmd \[\=\\]\[,\=\\],...](#--vpp-pmd-param1value1param2value2) - [--vpp-gauss \](#--vpp-gauss-int) - [--vpp-subburn \[\=\\]\[,\=\\],...](#--vpp-subburn-param1value1param2value2) + - [--vpp-libplacebo-shader \[\=\\]\[,\=\\],...](#--vpp-libplacebo-shader-param1value1param2value2) - [--vpp-resize \ or \[\=\\]\[,\=\\],...](#--vpp-resize-string-or-param1value1param2value2) - [--vpp-unsharp \[\=\\]\[,\=\\],...](#--vpp-unsharp-param1value1param2value2) - [--vpp-edgelevel \[\=\\]\[,\=\\],...](#--vpp-edgelevel-param1value1param2value2) @@ -1649,6 +1650,7 @@ vppフィルタの適用順は固定で、コマンドラインの順序によ - [--vpp-pmd](#--vpp-pmd-param1value1param2value2) - [--vpp-gauss](#--vpp-gauss-int) - [--vpp-subburn](#--vpp-subburn-param1value1param2value2) +- [--vpp-libplacebo-shader](#--vpp-libplacebo-shader-param1value1param2value2) - [--vpp-resize](#--vpp-resize-string-or-param1value1param2value2) - [--vpp-unsharp](#--vpp-unsharp-param1value1param2value2) - [--vpp-edgelevel](#--vpp-edgelevel-param1value1param2value2) @@ -2608,6 +2610,68 @@ nppc64_10.dll, nppif64_10.dll, nppig64_10.dllをNVEncC64と同じフォルダに 例3: Shift-JISな文字コードのassファイルの焼きこみ --vpp-subburn filename="subtitle.sjis.ass",charcode=sjis,shaping=complex ``` + +### --vpp-libplacebo-shader [<param1>=<value1>][,<param2>=<value2>],... + +[libplacebo](https://code.videolan.org/videolan/libplacebo)を使用して指定されたパスのカスタムシェーダーを適用します。 + +- **パラメータ** + - shader=<string> + 対象のshaderファイルのパス。 + + - res=<int>x<int> + フィルタの出力解像度。 + + - colorsystem=<int> + 使用する色空間を指定。デフォルトはbt709。 + ``` + unknown, bt601, bt709, smpte240m, bt2020nc, bt2020c, bt2100pq, bt2100hlg, dolbyvision, ycgco, rgb, xyz + ``` + + - transfer=<string> + 出力のトランスファ関数を指定。 + ``` + unknown, srgb, bt1886, linear, + gamma18, gamma20, gamma22, gamma24, gamma26, gamma28, + prophoto, st428, pq, hlg, vlog, slog1, slog2 + ``` + + - resampler=<string> + リサンプルが必要な場合に使用するフィルタ関数を指定。デフォルトは libplacebo-ewa-lanczos 。 + ``` + libplacebo-spline16, libplacebo-spline36, libplacebo-spline64, libplacebo-nearest, + libplacebo-bilinear, libplacebo-gaussian, libplacebo-sinc, libplacebo-lanczos, + libplacebo-ginseng, libplacebo-ewa-jinc, libplacebo-ewa-lanczos, + libplacebo-ewa-lanczossharp, libplacebo-ewa-lanczos4sharpest, + libplacebo-ewa-ginseng, libplacebo-ewa-hann, libplacebo-ewa-hanning, + libplacebo-bicubic, libplacebo-triangle, libplacebo-hermite, libplacebo-catmull-rom, + libplacebo-mitchell, libplacebo-mitchell-clamp, libplacebo-robidoux, + libplacebo-robidouxsharp, libplacebo-ewa-robidoux, libplacebo-ewa-robidouxsharp + ``` + + - radius=<float> + Adjust the function's radius. Default: auto. Must be between 0.0 and 16.0. + + - clamp=<float> + Clamping coefficient for negative weights. Default: 0.0. Must be between 0.0 and 1.0. + + - taper=<float> + Additional taper coefficient. Default: 0.0. Must be between 0.0 and 1.0. + + - blur=<float> + Additional blur coefficient. Default: 0.0. Must be between 0.0 and 100.0. + + - antiring=<float> + Antiringing strength. Default: 0.0. Must be between 0.0 and 1.0. + + - linear=<bool> + linearize image before processing. + +- 使用例 + ``` + Example: Apply a custom shader with specific parameters + --vpp-libplacebo-shader-params + ``` ### --vpp-resize <string> or [<param1>=<value1>][,<param2>=<value2>],... リサイズのアルゴリズムを指定する。 diff --git a/NVEncCore/NVEncCore.cpp b/NVEncCore/NVEncCore.cpp index 9bf491a9..ff5fee81 100644 --- a/NVEncCore/NVEncCore.cpp +++ b/NVEncCore/NVEncCore.cpp @@ -1422,6 +1422,7 @@ bool NVEncCore::enableCuvidResize(const InEncodeVideoParam *inputParam) { || inputParam->vpp.colorspace.enable || inputParam->vpp.libplacebo_tonemapping.enable || inputParam->vpp.subburn.size() > 0 + || inputParam->vpp.libplacebo_shader.size() > 0 || inputParam->vpp.pad.enable || inputParam->vpp.selectevery.enable || inputParam->vpp.decimate.enable @@ -2329,28 +2330,21 @@ RGY_ERR NVEncCore::InitFilters(const InEncodeVideoParam *inputParam) { } //リサイザの出力すべきサイズ - int resizeWidth = croppedWidth; - int resizeHeight = croppedHeight; - m_uEncWidth = resizeWidth; - m_uEncHeight = resizeHeight; - if (inputParam->vpp.pad.enable) { - m_uEncWidth += inputParam->vpp.pad.right + inputParam->vpp.pad.left; - m_uEncHeight += inputParam->vpp.pad.bottom + inputParam->vpp.pad.top; - } + int resizeWidth = 0; + int resizeHeight = 0; //指定のリサイズがあればそのサイズに設定する if (inputParam->input.dstWidth > 0 && inputParam->input.dstHeight > 0) { - m_uEncWidth = inputParam->input.dstWidth; - m_uEncHeight = inputParam->input.dstHeight; - resizeWidth = m_uEncWidth; - resizeHeight = m_uEncHeight; + resizeWidth = inputParam->input.dstWidth; + resizeHeight = inputParam->input.dstHeight; if (inputParam->vpp.pad.enable) { resizeWidth -= (inputParam->vpp.pad.right + inputParam->vpp.pad.left); resizeHeight -= (inputParam->vpp.pad.bottom + inputParam->vpp.pad.top); } } bool resizeRequired = false; - if (croppedWidth != resizeWidth || croppedHeight != resizeHeight) { + if ((resizeWidth > 0 && resizeHeight > 0) && + (croppedWidth != resizeWidth || croppedHeight != resizeHeight)) { resizeRequired = true; } //avhw読みではデコード直後にリサイズが可能 @@ -2424,6 +2418,7 @@ RGY_ERR NVEncCore::InitFilters(const InEncodeVideoParam *inputParam) { || inputParam->vpp.libplacebo_tonemapping.enable || inputParam->vpp.pad.enable || inputParam->vpp.subburn.size() > 0 + || inputParam->vpp.libplacebo_shader.size() > 0 || inputParam->vpp.rff.enable || inputParam->vpp.decimate.enable || inputParam->vpp.mpdecimate.enable @@ -3088,8 +3083,40 @@ RGY_ERR NVEncCore::InitFilters(const InEncodeVideoParam *inputParam) { return RGY_ERR_UNSUPPORTED; #endif } + //libplacebo-shader + for (const auto& shader : inputParam->vpp.libplacebo_shader) { + unique_ptr filter(new NVEncFilterLibplaceboShader()); + shared_ptr param(new NVEncFilterParamLibplaceboShader()); + param->shader = shader; + param->frameIn = inputFrame; + param->frameOut = inputFrame; + if (shader.width > 0) { + param->frameOut.width = shader.width; + } + if (shader.height > 0) { + param->frameOut.height = shader.height; + } + param->dx11 = m_dev->dx11(); + param->vk = m_dev->vulkan(); + param->baseFps = m_encFps; + param->bOutOverwrite = false; + NVEncCtxAutoLock(cxtlock(m_dev->vidCtxLock())); + auto sts = filter->init(param, m_pNVLog); + if (sts != RGY_ERR_NONE) { + return sts; + } + //フィルタチェーンに追加 + m_vpFilters.push_back(std::move(filter)); + //パラメータ情報を更新 + m_pLastFilterParam = std::dynamic_pointer_cast(param); + //入力フレーム情報を更新 + inputFrame = param->frameOut; + m_encFps = param->baseFps; + } + //リサイズ - if (resizeRequired) { + if (resizeWidth > 0 && resizeHeight > 0 && + (inputFrame.width != resizeWidth || inputFrame.height != resizeHeight)) { unique_ptr filterCrop(new NVEncFilterResize()); shared_ptr param(new NVEncFilterParamResize()); if (inputParam->vpp.resize_algo == RGY_VPP_RESIZE_AUTO) { @@ -3471,6 +3498,8 @@ RGY_ERR NVEncCore::InitFilters(const InEncodeVideoParam *inputParam) { filter->setCheckPerformance(inputParam->vpp.checkPerformance); } } + m_uEncWidth = inputFrame.width; + m_uEncHeight = inputFrame.height; m_encVUI = inputParam->common.out_vui; if (m_rgbAsYUV444) { m_encVUI.descriptpresent = 1; diff --git a/NVEncCore/NVEncFilterLibplacebo.cpp b/NVEncCore/NVEncFilterLibplacebo.cpp index 8e4eee57..aa9a1524 100644 --- a/NVEncCore/NVEncFilterLibplacebo.cpp +++ b/NVEncCore/NVEncFilterLibplacebo.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include "convert_csp.h" #include "NVEncFilter.h" #include "NVEncFilterParam.h" @@ -54,6 +55,10 @@ tstring NVEncFilterParamLibplaceboToneMapping::print() const { return toneMapping.print(); } +tstring NVEncFilterParamLibplaceboShader::print() const { + return shader.print(); +} + #if ENABLE_LIBPLACEBO #if ENABLE_VULKAN @@ -1683,6 +1688,207 @@ VideoVUIInfo NVEncFilterLibplaceboToneMapping::VuiOut() const { return m_tonemap.outVui; } +NVEncFilterLibplaceboShader::NVEncFilterLibplaceboShader() : + NVEncFilterLibplacebo(), + m_shader(), + m_colorsystem(), + m_transfer(), + m_range(), + m_chromaloc(), + m_sample_params(), + m_sigmoid_params(), + m_linear() +{ + m_name = _T("libplacebo-shader"); + m_procByFrame = true; +} +NVEncFilterLibplaceboShader::~NVEncFilterLibplaceboShader() {}; + +RGY_CSP NVEncFilterLibplaceboShader::getTextureCsp(const RGY_CSP csp) { + const auto inChromaFmt = RGY_CSP_CHROMA_FORMAT[csp]; + return (inChromaFmt == RGY_CHROMAFMT_RGB) ? RGY_CSP_RGB_16 : RGY_CSP_YUV444_16; +} + +CUDAInteropDataFormat NVEncFilterLibplaceboShader::getTextureDataFormat([[maybe_unused]] const RGY_CSP csp) { +#if ENABLE_D3D11 + return DXGI_FORMAT_R16_UNORM; +#elif ENABLE_VULKAN + return VK_FORMAT_R16_UNORM; +#else + static_assert(false); +#endif +} + +RGY_ERR NVEncFilterLibplaceboShader::checkParam(const NVEncFilterParam *param) { + auto prm = dynamic_cast(param); + if (!prm) { + AddMessage(RGY_LOG_ERROR, _T("Invalid parameter type.\n")); + return RGY_ERR_INVALID_PARAM; + } + + if (prm->shader.shader.length() == 0) { + AddMessage(RGY_LOG_ERROR, _T("No shader file specified.\n")); + return RGY_ERR_INVALID_PARAM; + } + if (!rgy_file_exists(prm->shader.shader.c_str())) { + AddMessage(RGY_LOG_ERROR, _T("Shader file not found: %s\n"), prm->shader.shader.c_str()); + return RGY_ERR_FILE_OPEN; + } + + // prm->resampleの各値の範囲をチェック + if (prm->shader.width < 0 || prm->shader.height < 0) { + AddMessage(RGY_LOG_ERROR, _T("width and height must be greater than 0.\n")); + return RGY_ERR_INVALID_PARAM; + } + if (prm->shader.radius > 16.0f) { + AddMessage(RGY_LOG_ERROR, _T("radius must be between 0.0f and 16.0f.\n")); + return RGY_ERR_INVALID_PARAM; + } + if (prm->shader.blur < 0.0f || prm->shader.blur > 100.0f) { + AddMessage(RGY_LOG_ERROR, _T("blur must be between 0.0f and 100.0f.\n")); + return RGY_ERR_INVALID_PARAM; + } + if (prm->shader.taper < 0.0f || prm->shader.taper > 1.0f) { + AddMessage(RGY_LOG_ERROR, _T("taper must be between 0.0f and 1.0f.\n")); + return RGY_ERR_INVALID_PARAM; + } + if (prm->shader.clamp_ < 0.0f || prm->shader.clamp_ > 1.0f) { + AddMessage(RGY_LOG_ERROR, _T("clamp must be between 0.0f and 1.0f.\n")); + return RGY_ERR_INVALID_PARAM; + } + if (prm->shader.antiring < 0.0f || prm->shader.antiring > 1.0f) { + AddMessage(RGY_LOG_ERROR, _T("antiring must be between 0.0f and 1.0f.\n")); + return RGY_ERR_INVALID_PARAM; + } + return RGY_ERR_NONE; +} + +RGY_ERR NVEncFilterLibplaceboShader::setLibplaceboParam(const NVEncFilterParam *param) { + auto prm = dynamic_cast(param); + if (!prm) { + AddMessage(RGY_LOG_ERROR, _T("Invalid parameter type.\n")); + return RGY_ERR_INVALID_PARAM; + } + + std::ifstream shader_file(prm->shader.shader, std::ios::binary | std::ios_base::in); + if (!shader_file.is_open()) { + AddMessage(RGY_LOG_ERROR, _T("Failed to open shader file.\n")); + return RGY_ERR_FILE_OPEN; + } + shader_file.seekg(0, std::ios::end); + std::vector shader_data_buf(shader_file.tellg()); + shader_file.seekg(0, std::ios::beg); + shader_file.read(shader_data_buf.data(), shader_data_buf.size()); + if (shader_data_buf.size() == 0) { + AddMessage(RGY_LOG_ERROR, _T("Failed to read shader file.\n")); + return RGY_ERR_NULL_PTR; + } + auto shader_data = std::string(shader_data_buf.data(), shader_data_buf.size()); + + for (const auto& shader_prm : prm->shader.params) { + auto prm1 = tchar_to_string(shader_prm.first); + auto prm2 = tchar_to_string(shader_prm.second); + shader_data = std::regex_replace(shader_data, std::regex(std::string("(#define\\s") + prm1 + std::string("\\s+)(.+?)(?=\\/\\/|\\s)")), "$01" + prm2); + } + + m_shader = std::unique_ptr>( + (pl_hook *)m_pl->p_mpv_user_shader_parse()(m_pldevice->gpu, shader_data.c_str(), shader_data.size()), + RGYLibplaceboDeleter(m_pl->p_mpv_user_shader_destroy())); + if (!m_shader) { + AddMessage(RGY_LOG_ERROR, _T("Failed to parse shader.\n")); + return RGY_ERR_UNKNOWN; + } + + const auto vuiIn = prm->vui; + + m_colorsystem = (pl_color_system)prm->shader.colorsystem; + m_transfer = (pl_color_transfer)(prm->shader.transfer); + m_range = (vuiIn.colorrange == RGY_COLORRANGE_FULL) ? PL_COLOR_LEVELS_FULL : PL_COLOR_LEVELS_LIMITED; + m_linear = prm->shader.linear; + m_chromaloc = chromaloc_rgy_to_libplacebo(prm->shader.chromaloc); + + m_sample_params = std::make_unique(); + m_sample_params->antiring = prm->shader.antiring; + + auto resample_filter_name = resize_algo_rgy_to_libplacebo(prm->shader.resize_algo); + if (resample_filter_name == nullptr) { + AddMessage(RGY_LOG_ERROR, _T("unsupported resize algorithm.\n")); + return RGY_ERR_UNSUPPORTED; + } + + auto filter_config = m_pl->p_find_filter_config()(resample_filter_name, PL_FILTER_UPSCALING); + if (!filter_config) { + AddMessage(RGY_LOG_ERROR, _T("unsupported resample filter type.\n")); + return RGY_ERR_UNSUPPORTED; + } + m_sample_params->filter = *filter_config; + m_sample_params->filter.clamp = prm->shader.clamp_; + m_sample_params->filter.blur = prm->shader.blur; + m_sample_params->filter.taper = prm->shader.taper; + if (prm->shader.radius >= 0.0) { + if (!m_sample_params->filter.kernel->resizable) { + AddMessage(RGY_LOG_WARN, _T("radius %.1f ignored for non-resizable filter: %s.\n"), char_to_tstring(resample_filter_name).c_str()); + } else { + m_sample_params->filter.radius = prm->shader.radius; + } + } + return RGY_ERR_NONE; +} + +RGY_ERR NVEncFilterLibplaceboShader::procFrame(pl_tex texOut[RGY_MAX_PLANES], const RGYFrameInfo *pDstFrame, pl_tex texIn[RGY_MAX_PLANES], const RGYFrameInfo *pSrcFrame) { + pl_color_repr crpr = { }; + crpr.bits.bit_shift = 0; + crpr.bits.color_depth = 16; + crpr.bits.sample_depth = 16; + crpr.sys = m_colorsystem; + crpr.levels = m_range; + + pl_color_space csp = {}; + csp.transfer = m_transfer; + + pl_frame img = {}; + img.num_planes = 3; + img.repr = crpr; + img.color = csp; + for (int i = 0; i < RGY_CSP_PLANES[pSrcFrame->csp]; i++) { + img.planes[i].texture = texIn[i]; + img.planes[i].components = 1; + img.planes[i].component_mapping[0] = i; + } + + if (RGY_CSP_CHROMA_FORMAT[pSrcFrame->csp] == RGY_CHROMAFMT_YUV420) { + m_pl->p_frame_set_chroma_location()(&img, m_chromaloc); + } + + pl_frame out = { 0 }; + out.num_planes = 3; + out.repr = crpr; + out.color = csp; + + for (int i = 0; i < RGY_CSP_PLANES[pDstFrame->csp]; i++) { + out.planes[i].texture = texOut[i]; + out.planes[i].components = 1; + out.planes[i].component_mapping[0] = i; + } + + auto shader = m_shader.get(); + + pl_render_params renderParams = { 0 }; + renderParams.hooks = &shader; + renderParams.num_hooks = 1; + renderParams.sigmoid_params = m_sigmoid_params.get(); + renderParams.disable_linear_scaling = !m_linear; + renderParams.upscaler = &m_sample_params->filter; + renderParams.downscaler = &m_sample_params->filter; + renderParams.antiringing_strength = m_sample_params->antiring; + + if (!m_pl->p_render_image()(m_renderer.get(), &img, &out, &renderParams)) { + AddMessage(RGY_LOG_ERROR, _T("Failed to render image.\n")); + return RGY_ERR_UNKNOWN; + } + return RGY_ERR_NONE; +} + #else NVEncFilterLibplaceboResample::NVEncFilterLibplaceboResample() : NVEncFilterDisabled() { m_name = _T("libplacebo-resample"); } @@ -1694,4 +1900,7 @@ NVEncFilterLibplaceboDeband::~NVEncFilterLibplaceboDeband() {}; NVEncFilterLibplaceboToneMapping::NVEncFilterLibplaceboToneMapping() : NVEncFilterDisabled() { m_name = _T("libplacebo-tonemapping"); } NVEncFilterLibplaceboToneMapping::~NVEncFilterLibplaceboToneMapping() {}; +NVEncFilterLibplaceboShader::NVEncFilterLibplaceboShader() : NVEncFilterDisabled() { m_name = _T("libplacebo-shader"); } +NVEncFilterLibplaceboShader::~NVEncFilterLibplaceboShader() {}; + #endif //#if ENABLE_LIBPLACEBO diff --git a/NVEncCore/NVEncFilterLibplacebo.h b/NVEncCore/NVEncFilterLibplacebo.h index e19ff009..897ff42b 100644 --- a/NVEncCore/NVEncFilterLibplacebo.h +++ b/NVEncCore/NVEncFilterLibplacebo.h @@ -75,6 +75,14 @@ class NVEncFilterParamLibplaceboToneMapping : public NVEncFilterParamLibplacebo virtual tstring print() const override; }; +class NVEncFilterParamLibplaceboShader : public NVEncFilterParamLibplacebo { +public: + VppLibplaceboShader shader; + NVEncFilterParamLibplaceboShader() : NVEncFilterParamLibplacebo(), shader() {}; + virtual ~NVEncFilterParamLibplaceboShader() {}; + virtual tstring print() const override; +}; + #if ENABLE_LIBPLACEBO #include "rgy_libplacebo.h" @@ -225,6 +233,32 @@ class NVEncFilterLibplaceboToneMapping : public NVEncFilterLibplacebo { RGYLibplaceboToneMappingParams m_tonemap; }; +class NVEncFilterLibplaceboShader : public NVEncFilterLibplacebo { +public: + NVEncFilterLibplaceboShader(); + virtual ~NVEncFilterLibplaceboShader(); +protected: + virtual RGY_ERR checkParam(const NVEncFilterParam *param) override; + virtual RGY_ERR setLibplaceboParam(const NVEncFilterParam *param) override; + virtual RGY_ERR procPlane(pl_tex texOut, const RGYFrameInfo *pDstPlane, pl_tex texIn, const RGYFrameInfo *pSrcPlane, const RGY_PLANE planeIdx) override { + UNREFERENCED_PARAMETER(texOut); UNREFERENCED_PARAMETER(pDstPlane); UNREFERENCED_PARAMETER(texIn); UNREFERENCED_PARAMETER(pSrcPlane); UNREFERENCED_PARAMETER(planeIdx); + return RGY_ERR_UNSUPPORTED; + }; + virtual RGY_ERR procFrame(pl_tex texOut[RGY_MAX_PLANES], const RGYFrameInfo *pDstFrame, pl_tex texIn[RGY_MAX_PLANES], const RGYFrameInfo *pSrcFrame) override; + + virtual RGY_CSP getTextureCsp(const RGY_CSP csp) override; + virtual CUDAInteropDataFormat getTextureDataFormat([[maybe_unused]] const RGY_CSP csp) override; + + std::unique_ptr> m_shader; + pl_color_system m_colorsystem; + pl_color_transfer m_transfer; + pl_color_levels m_range; + pl_chroma_location m_chromaloc; + std::unique_ptr m_sample_params; + std::unique_ptr m_sigmoid_params; + int m_linear; +}; + #else class NVEncFilterLibplaceboResample : public NVEncFilterDisabled { @@ -245,6 +279,12 @@ class NVEncFilterLibplaceboToneMapping : public NVEncFilterDisabled { virtual ~NVEncFilterLibplaceboToneMapping(); }; +class NVEncFilterLibplaceboShader : public NVEncFilterDisabled { +public: + NVEncFilterLibplaceboShader(); + virtual ~NVEncFilterLibplaceboShader(); +}; + #endif #endif //#ifndef __NVENC_FILTER_LIBPLACEBO_H__ \ No newline at end of file diff --git a/NVEncCore/rgy_cmd.cpp b/NVEncCore/rgy_cmd.cpp index 5131f75c..39c1c8f2 100644 --- a/NVEncCore/rgy_cmd.cpp +++ b/NVEncCore/rgy_cmd.cpp @@ -386,6 +386,17 @@ static int getAttachmentTrackIdx(const RGYParamCommon *common, const int iTrack) return -1; } +static std::vector get_libplacebo_only_resize_list() { + std::vector libplacebo_resize_list; + for (size_t i = 0; list_vpp_resize[i].desc; i++) { + if (_tcsncmp(list_vpp_resize[i].desc, _T("libplacebo-"), _tcslen(_T("libplacebo-"))) == 0) { + libplacebo_resize_list.push_back(list_vpp_resize[i]); + } + } + libplacebo_resize_list.push_back({ nullptr, 0 }); + return libplacebo_resize_list; +} + #pragma warning(disable: 4100) //warning C4100: 'argData': 引数は関数の本体部で 1 度も参照されません。 #pragma warning(disable: 4127) //warning C4127: 条件式が定数です。 @@ -3160,6 +3171,176 @@ int parse_one_vpp_option(const TCHAR *option_name, const TCHAR *strInput[], int return 0; } + if (IS_OPTION("vpp-libplacebo-shader") && ENABLE_VPP_FILTER_LIBPLACEBO) { + VppLibplaceboShader shader; + shader.enable = true; + if (i + 1 >= nArgNum || strInput[i + 1][0] == _T('-')) { + vpp->libplacebo_shader.push_back(shader); + return 0; + } + i++; + const auto paramList = std::vector{ + "shader", "res", "width", "height", "chromaloc", "colorsystem", "transfer", "resampler", + "radius", "clamp", "taper", "blur", "antiring", "linear" + }; + for (const auto ¶m : split(strInput[i], _T(","))) { + auto pos = param.find_first_of(_T("=")); + if (pos != std::string::npos) { + auto param_arg = param.substr(0, pos); + auto param_val = param.substr(pos + 1); + param_arg = tolowercase(param_arg); + if (param_arg == _T("enable")) { + bool b = false; + if (!cmd_string_to_bool(&b, param_val)) { + shader.enable = b; + } else { + print_cmd_error_invalid_value(tstring(option_name) + _T(" ") + param_arg + _T("="), param_val); + return 1; + } + continue; + } + if (param_arg == _T("shader")) { + shader.shader = trim(param_val, _T("\"")); + continue; + } + if (param_arg == _T("res")) { + int width = 0, height = 0; + if (2 == _stscanf_s(param_val.c_str(), _T("%dx%d"), &width, &height)) { + shader.width = width; + shader.height = height; + } else { + print_cmd_error_invalid_value(tstring(option_name) + _T(" ") + param_arg + _T("="), param_val); + return 1; + } + continue; + } + if (param_arg == _T("width")) { + try { + shader.width = std::stoi(param_val); + } catch (...) { + print_cmd_error_invalid_value(tstring(option_name) + _T(" ") + param_arg + _T("="), param_val); + return 1; + } + continue; + } + if (param_arg == _T("height")) { + try { + shader.height = std::stoi(param_val); + } catch (...) { + print_cmd_error_invalid_value(tstring(option_name) + _T(" ") + param_arg + _T("="), param_val); + return 1; + } + continue; + } + if (param_arg == _T("chromaloc")) { + int value = 0; + if (get_list_value(list_chromaloc_str, param_val.c_str(), &value)) { + shader.chromaloc = (CspChromaloc)value; + } else if (get_list_value(list_chromaloc, param_val.c_str(), &value)) { + shader.chromaloc = (CspChromaloc)value; + } else { + print_cmd_error_invalid_value(tstring(option_name) + _T(" ") + param_arg + _T("="), param_val, list_chromaloc_str); + return 1; + } + continue; + } + if (param_arg == _T("colorsystem")) { + int value = 0; + if (get_list_value(list_vpp_libplacebo_colorsystem, param_val.c_str(), &value)) { + shader.colorsystem = (VppLibplaceboColorsystem)value; + } else { + print_cmd_error_invalid_value(tstring(option_name) + _T(" ") + param_arg + _T("="), param_val, list_vpp_libplacebo_colorsystem); + return 1; + } + continue; + } + if (param_arg == _T("transfer")) { + int value = 0; + if (get_list_value(list_vpp_libplacebo_tone_mapping_transfer, param_val.c_str(), &value)) { + shader.transfer = (VppLibplaceboToneMappingTransfer)value; + } else { + print_cmd_error_invalid_value(tstring(option_name) + _T(" ") + param_arg + _T("="), param_val, list_vpp_libplacebo_tone_mapping_transfer); + return 1; + } + continue; + } + if (param_arg == _T("resampler")) { + int value = 0; + const auto libplacebo_resize_list = get_libplacebo_only_resize_list(); + if (get_list_value(libplacebo_resize_list.data(), param_val.c_str(), &value)) { + shader.resize_algo = (RGY_VPP_RESIZE_ALGO)value; + } else { + print_cmd_error_invalid_value(tstring(option_name) + _T(" ") + param_arg + _T("="), param_val, libplacebo_resize_list.data()); + return 1; + } + continue; + } + if (param_arg == _T("radius")) { + try { + shader.radius = std::stof(param_val); + } catch (...) { + print_cmd_error_invalid_value(tstring(option_name) + _T(" ") + param_arg + _T("="), param_val); + return 1; + } + continue; + } + if (param_arg == _T("clamp")) { + try { + shader.clamp_ = std::stof(param_val); + } catch (...) { + print_cmd_error_invalid_value(tstring(option_name) + _T(" ") + param_arg + _T("="), param_val); + return 1; + } + continue; + } + if (param_arg == _T("taper")) { + try { + shader.taper = std::stof(param_val); + } catch (...) { + print_cmd_error_invalid_value(tstring(option_name) + _T(" ") + param_arg + _T("="), param_val); + return 1; + } + continue; + } + if (param_arg == _T("blur")) { + try { + shader.blur = std::stof(param_val); + } catch (...) { + print_cmd_error_invalid_value(tstring(option_name) + _T(" ") + param_arg + _T("="), param_val); + return 1; + } + continue; + } + if (param_arg == _T("antiring")) { + try { + shader.antiring = std::stof(param_val); + } catch (...) { + print_cmd_error_invalid_value(tstring(option_name) + _T(" ") + param_arg + _T("="), param_val); + return 1; + } + continue; + } + if (param_arg == _T("linear")) { + bool b = false; + if (!cmd_string_to_bool(&b, param_val)) { + shader.linear = b; + } else { + print_cmd_error_invalid_value(tstring(option_name) + _T(" ") + param_arg + _T("="), param_val); + return 1; + } + continue; + } + shader.params.push_back(std::make_pair(param_arg, param_val)); + continue; + } else { + print_cmd_error_unknown_opt_param(option_name, param, paramList); + return 1; + } + } + vpp->libplacebo_shader.push_back(shader); + return 0; + } + if (IS_OPTION("vpp-unsharp") && ENABLE_VPP_FILTER_UNSHARP) { vpp->unsharp.enable = true; if (i + 1 >= nArgNum || strInput[i + 1][0] == _T('-')) { @@ -5911,10 +6092,12 @@ int parse_one_common_option(const TCHAR *option_name, const TCHAR *strInput[], i if (IS_OPTION("chromaloc") || IS_OPTION("chromaloc:h264") || IS_OPTION("chromaloc:hevc")) { i++; int value = 0; - if (get_list_value(list_chromaloc, strInput[i], &value)) { + if (get_list_value(list_chromaloc_str, strInput[i], &value)) { + common->out_vui.chromaloc = (CspChromaloc)value; + } else if (get_list_value(list_chromaloc, strInput[i], &value)) { common->out_vui.chromaloc = (CspChromaloc)value; } else { - print_cmd_error_invalid_value(option_name, strInput[i], list_chromaloc); + print_cmd_error_invalid_value(option_name, strInput[i], list_chromaloc_str); return 1; } return 0; @@ -7373,6 +7556,37 @@ tstring gen_cmd(const RGYParamVpp *param, const RGYParamVpp *defaultPrm, bool sa } } } + for (size_t i = 0; i < param->libplacebo_shader.size(); i++) { + const auto shaderDefault = VppLibplaceboShader(); + if (param->libplacebo_shader[i] != shaderDefault) { + tmp.str(tstring()); + if (!param->libplacebo_shader[i].enable && save_disabled_prm) { + tmp << _T(",enable=false"); + } + if (param->libplacebo_shader[i].enable || save_disabled_prm) { + ADD_PATH2(_T("shader"), param->libplacebo_shader[i], shader.c_str()); + if (param->libplacebo_shader[i].width > 0 && param->libplacebo_shader[i].height > 0) { + tmp << _T(",res=") << param->libplacebo_shader[i].width << _T("x") << param->libplacebo_shader[i].height; + } + ADD_LST2(_T("chromaloc"), param->libplacebo_shader[i], shaderDefault, chromaloc, list_chromaloc_str); + ADD_LST2(_T("colorsystem"), param->libplacebo_shader[i], shaderDefault, colorsystem, list_vpp_libplacebo_colorsystem); + ADD_LST2(_T("transfer"), param->libplacebo_shader[i], shaderDefault, transfer, list_vpp_libplacebo_tone_mapping_transfer); + ADD_LST2(_T("filter"), param->libplacebo_shader[i], shaderDefault, resize_algo, list_vpp_resize); + ADD_FLOAT2(_T("radius"), param->libplacebo_shader[i], shaderDefault, radius, 3); + ADD_FLOAT2(_T("clamp"), param->libplacebo_shader[i], shaderDefault, clamp_, 3); + ADD_FLOAT2(_T("taper"), param->libplacebo_shader[i], shaderDefault, taper, 3); + ADD_FLOAT2(_T("blur"), param->libplacebo_shader[i], shaderDefault, blur, 3); + ADD_FLOAT2(_T("antiring"), param->libplacebo_shader[i], shaderDefault, antiring, 3); + ADD_BOOL2(_T("linear"), param->libplacebo_shader[i], shaderDefault, linear); + } + if (!tmp.str().empty()) { + cmd << _T(" --vpp-libplacebo-shader \"") << tmp.str().substr(1) << _T("\""); + } else if (param->libplacebo_shader[i].enable) { + cmd << _T(" --vpp-libplacebo-shader"); + } + } + } + if (param->unsharp != defaultPrm->unsharp) { tmp.str(tstring()); if (!param->unsharp.enable && save_disabled_prm) { @@ -8929,6 +9143,44 @@ tstring gen_cmd_help_vpp() { _T(" fontsdir= directory with fonts used.\n") _T(" forced_subs_only= render forced subs only.\n"), FILTER_DEFAULT_TWEAK_BRIGHTNESS, FILTER_DEFAULT_TWEAK_CONTRAST); +#if ENABLE_LIBPLACEBO + str += strsprintf(_T("\n") + _T(" --vpp-libplacebo-shader [=][,=][...]\n") + _T(" Apply custom shader using libplacebo.\n") + _T(" params\n") + _T(" shader= Target shader file path.\n") + _T(" res=x Output resolution of filter, must be positive value.\n") + //_T(" chromaloc= Chroma location to derive chroma shift from.\n") + //_T(" default: %s\n"), get_cx_desc(list_chromaloc_str, FILTER_DEFAULT_LIBPLACEBO_SHADER_CHROMALOC) + ) + print_list(list_chromaloc_str) + _T("\n"); + str += strsprintf(_T("") + _T(" colorsystem= Color matrix to use.\n") + _T(" default: %s\n"), get_cx_desc(list_vpp_libplacebo_colorsystem, FILTER_DEFAULT_LIBPLACEBO_SHADER_COLORSYSTEM) + ) + print_list(list_vpp_libplacebo_colorsystem) + _T("\n"); + str += strsprintf(_T("") + _T(" transfer= Output transfer function.\n") + _T(" default: %s\n"), get_cx_desc(list_vpp_libplacebo_tone_mapping_transfer, FILTER_DEFAULT_LIBPLACEBO_SHADER_TRANSFER) + ) + print_list(list_vpp_libplacebo_tone_mapping_transfer) + _T("\n"); + str += strsprintf(_T("") + _T(" resampler= Filter function to use when resample is required.\n") + _T(" default: %s\n"), FILTER_DEFAULT_LIBPLACEBO_SHADER_RESAMPLER_NAME + ) + print_list(get_libplacebo_only_resize_list().data()) + _T("\n"); + str += strsprintf(_T("") + _T(" radius= Adjust the function's radius.\n") + _T(" default: %.2f, 0.0 - 16.0\n") + _T(" clamp= Clamping coefficient for negative weights.\n") + _T(" default: %.2f, 0.0 - 1.0\n") + _T(" taper= Additional taper coefficient.\n") + _T(" default: %.2f, 0.0 - 1.0\n") + _T(" blur= Additional blur coefficient.\n") + _T(" default: %.2f, 0.0 - 100.0\n") + _T(" antiring= Antiringing strength.\n") + _T(" default: %.2f, 0.0 - 1.0\n") + _T(" linear= Linearize image before processing.\n"), + FILTER_DEFAULT_LIBPLACEBO_SHADER_RADIUS, FILTER_DEFAULT_LIBPLACEBO_SHADER_CLAMP, FILTER_DEFAULT_LIBPLACEBO_SHADER_TAPER, + FILTER_DEFAULT_LIBPLACEBO_SHADER_BLUR, FILTER_DEFAULT_LIBPLACEBO_SHADER_ANTIRING + ); +#endif #if ENABLE_VPP_FILTER_UNSHARP str += strsprintf(_T("\n") _T(" --vpp-unsharp [=][,=][...]\n") diff --git a/NVEncCore/rgy_libplacebo.cpp b/NVEncCore/rgy_libplacebo.cpp index b94ea4d7..947e810f 100644 --- a/NVEncCore/rgy_libplacebo.cpp +++ b/NVEncCore/rgy_libplacebo.cpp @@ -85,7 +85,12 @@ RGYLibplaceboLoader::RGYLibplaceboLoader() : m_pl_find_gamut_map_function(nullptr), m_pl_raw_primaries_get(nullptr), m_pl_raw_primaries_merge(nullptr), - m_pl_color_space_infer_map(nullptr) { + m_pl_color_space_infer_map(nullptr), + m_pl_frame_set_chroma_location(nullptr), + m_pl_shader_custom(nullptr), + m_pl_mpv_user_shader_parse(nullptr), + m_pl_mpv_user_shader_destroy(nullptr) +{ } RGYLibplaceboLoader::~RGYLibplaceboLoader() { @@ -162,6 +167,12 @@ bool RGYLibplaceboLoader::load() { if (!loadFunc("pl_raw_primaries_merge", (void**)&m_pl_raw_primaries_merge)) return false; if (!loadFunc("pl_color_space_infer_map", (void**)&m_pl_color_space_infer_map)) return false; + if (!loadFunc("pl_frame_set_chroma_location", (void**)&m_pl_frame_set_chroma_location)) return false; + + if (!loadFunc("pl_shader_custom", (void**)&m_pl_shader_custom)) return false; + if (!loadFunc("pl_mpv_user_shader_parse", (void**)&m_pl_mpv_user_shader_parse)) return false; + if (!loadFunc("pl_mpv_user_shader_destroy", (void**)&m_pl_mpv_user_shader_destroy)) return false; + return true; } @@ -261,6 +272,18 @@ static const auto RGY_COLORPRIM_TO_LIBPLACEBO = make_array>( + std::make_pair(RGY_CHROMALOC_UNSPECIFIED, PL_CHROMA_UNKNOWN), + std::make_pair(RGY_CHROMALOC_LEFT, PL_CHROMA_LEFT), + std::make_pair(RGY_CHROMALOC_CENTER, PL_CHROMA_CENTER), + std::make_pair(RGY_CHROMALOC_TOPLEFT, PL_CHROMA_TOP_LEFT), + std::make_pair(RGY_CHROMALOC_TOP, PL_CHROMA_TOP_CENTER), + std::make_pair(RGY_CHROMALOC_BOTTOMLEFT, PL_CHROMA_BOTTOM_LEFT), + std::make_pair(RGY_CHROMALOC_BOTTOM, PL_CHROMA_BOTTOM_CENTER) +); + +MAP_PAIR_0_1(chromaloc, rgy, CspChromaloc, libplacebo, pl_chroma_location, RGY_CHROMALOC_TO_LIBPLACEBO, RGY_CHROMALOC_UNSPECIFIED, PL_CHROMA_UNKNOWN); + std::unique_ptr::type, RGYLibplaceboTexDeleter> rgy_pl_tex_recreate(const RGYLibplaceboLoader *pl, pl_gpu gpu, const pl_tex_params& tex_params) { pl_tex tex_tmp = { 0 }; if (!pl->p_tex_recreate()(gpu, &tex_tmp, &tex_params)) { diff --git a/NVEncCore/rgy_libplacebo.h b/NVEncCore/rgy_libplacebo.h index 4c2b11b1..ccec5ee1 100644 --- a/NVEncCore/rgy_libplacebo.h +++ b/NVEncCore/rgy_libplacebo.h @@ -45,7 +45,7 @@ #include #include #include -#include +#include #if ENABLE_D3D11 #include #elif ENABLE_VULKAN @@ -117,6 +117,12 @@ class RGYLibplaceboLoader { decltype(&pl_raw_primaries_merge) m_pl_raw_primaries_merge; decltype(&pl_color_space_infer_map) m_pl_color_space_infer_map; + decltype(&pl_frame_set_chroma_location) m_pl_frame_set_chroma_location; + + decltype(&pl_shader_custom) m_pl_shader_custom; + decltype(&pl_mpv_user_shader_parse) m_pl_mpv_user_shader_parse; + decltype(&pl_mpv_user_shader_destroy) m_pl_mpv_user_shader_destroy; + public: RGYLibplaceboLoader(); ~RGYLibplaceboLoader(); @@ -171,6 +177,12 @@ class RGYLibplaceboLoader { auto p_raw_primaries_get() const { return m_pl_raw_primaries_get; } auto p_raw_primaries_merge() const { return m_pl_raw_primaries_merge; } auto p_color_space_infer_map() const { return m_pl_color_space_infer_map; } + + auto p_frame_set_chroma_location() const { return m_pl_frame_set_chroma_location; } + + auto p_shader_custom() const { return m_pl_shader_custom; } + auto p_mpv_user_shader_parse() const { return m_pl_mpv_user_shader_parse; } + auto p_mpv_user_shader_destroy() const { return m_pl_mpv_user_shader_destroy; } }; @@ -197,6 +209,7 @@ MAP_PAIR_0_1_PROTO(resize_algo, rgy, RGY_VPP_RESIZE_ALGO, libplacebo, const char MAP_PAIR_0_1_PROTO(tone_map_metadata, rgy, VppLibplaceboToneMappingMetadata, libplacebo, pl_hdr_metadata_type); MAP_PAIR_0_1_PROTO(transfer, rgy, CspTransfer, libplacebo, pl_color_transfer); MAP_PAIR_0_1_PROTO(colorprim, rgy, CspColorprim, libplacebo, pl_color_primaries); +MAP_PAIR_0_1_PROTO(chromaloc, rgy, CspChromaloc, libplacebo, pl_chroma_location); static void libplacebo_log_func(void *private_data, pl_log_level level, const char* msg) { auto log = static_cast(private_data); diff --git a/NVEncCore/rgy_prm.cpp b/NVEncCore/rgy_prm.cpp index 99085a29..012053b9 100644 --- a/NVEncCore/rgy_prm.cpp +++ b/NVEncCore/rgy_prm.cpp @@ -93,6 +93,7 @@ static const auto VPPTYPE_TO_STR = make_array>( std::make_pair(VppType::CL_DENOISE_DCT, _T("denoise-dct")), std::make_pair(VppType::CL_DENOISE_SMOOTH, _T("smooth")), std::make_pair(VppType::CL_DENOISE_FFT3D, _T("fft3d")), + std::make_pair(VppType::CL_LIBPLACEBO_SHADER, _T("libplacebo-shader")), std::make_pair(VppType::CL_RESIZE, _T("resize")), std::make_pair(VppType::CL_UNSHARP, _T("unsharp")), std::make_pair(VppType::CL_EDGELEVEL, _T("edgelevel")), @@ -587,6 +588,69 @@ tstring VppLibplaceboToneMapping::print() const { return str; } +VppLibplaceboShader::VppLibplaceboShader() : + enable(false), + shader(), + width(0), + height(0), + params(), + resize_algo((RGY_VPP_RESIZE_ALGO)get_cx_value(list_vpp_resize, FILTER_DEFAULT_LIBPLACEBO_SHADER_RESAMPLER_NAME)), + colorsystem((VppLibplaceboColorsystem)FILTER_DEFAULT_LIBPLACEBO_SHADER_COLORSYSTEM), + transfer((VppLibplaceboToneMappingTransfer)FILTER_DEFAULT_LIBPLACEBO_SHADER_TRANSFER), + chromaloc((CspChromaloc)FILTER_DEFAULT_LIBPLACEBO_SHADER_CHROMALOC), + radius(FILTER_DEFAULT_LIBPLACEBO_SHADER_RADIUS), + clamp_(FILTER_DEFAULT_LIBPLACEBO_SHADER_CLAMP), + taper(FILTER_DEFAULT_LIBPLACEBO_SHADER_TAPER), + blur(FILTER_DEFAULT_LIBPLACEBO_SHADER_BLUR), + antiring(FILTER_DEFAULT_LIBPLACEBO_SHADER_ANTIRING), + linear(FILTER_DEFAULT_LIBPLACEBO_SHADER_LINEAR) { +} + +bool VppLibplaceboShader::operator==(const VppLibplaceboShader &x) const { + return enable == x.enable + && shader == x.shader + && width == x.width + && height == x.height + && params == x.params + && resize_algo == x.resize_algo + && colorsystem == x.colorsystem + && transfer == x.transfer + && chromaloc == x.chromaloc + && radius == x.radius + && clamp_ == x.clamp_ + && taper == x.taper + && blur == x.blur + && antiring == x.antiring + && linear == x.linear; +} + +bool VppLibplaceboShader::operator!=(const VppLibplaceboShader &x) const { + return !(*this == x); +} + +tstring VppLibplaceboShader::print() const { + tstring str; + str += strsprintf(_T("%s, "), shader.c_str()); + for (const auto& param : params) { + str += strsprintf(_T("%s=%s, "), param.first.c_str(), param.second.c_str()); + } + if (width > 0 && height > 0) { + str += strsprintf(_T("res=%dx%d, "), width, height); + } + str += strsprintf(_T("resampler=%s, "), get_cx_desc(list_vpp_resize, (int)resize_algo)); + str += strsprintf(_T("colorsystem=%s, "), get_cx_desc(list_vpp_libplacebo_colorsystem, (int)colorsystem)); + str += strsprintf(_T("transfer=%s, "), get_cx_desc(list_vpp_libplacebo_tone_mapping_transfer, (int)transfer)); + str += strsprintf(_T("chromaloc=%s, "), get_cx_desc(list_chromaloc_str, (int)chromaloc)); + str += strsprintf(_T("radius=%.2f, "), radius); + str += strsprintf(_T("clamp=%.2f, "), clamp_); + str += strsprintf(_T("taper=%.2f, "), taper); + str += strsprintf(_T("blur=%.2f, "), blur); + str += strsprintf(_T("antiring=%.2f, "), antiring); + str += strsprintf(_T("linear=%s"), linear ? _T("on") : _T("off")); + + return str; +} + ColorspaceConv::ColorspaceConv() : from(), to(), @@ -1981,6 +2045,7 @@ RGYParamVpp::RGYParamVpp() : smooth(), fft3d(), subburn(), + libplacebo_shader(), unsharp(), edgelevel(), warpsharp(), @@ -2018,6 +2083,7 @@ bool RGYParamVpp::operator==(const RGYParamVpp& x) const { && smooth == x.smooth && subburn == x.subburn && unsharp == x.unsharp + && libplacebo_shader == x.libplacebo_shader && edgelevel == x.edgelevel && warpsharp == x.warpsharp && curves == x.curves diff --git a/NVEncCore/rgy_prm.h b/NVEncCore/rgy_prm.h index 350f5987..7f6d7d87 100644 --- a/NVEncCore/rgy_prm.h +++ b/NVEncCore/rgy_prm.h @@ -151,6 +151,8 @@ enum class VppType : int { CL_DENOISE_SMOOTH, CL_DENOISE_FFT3D, + CL_LIBPLACEBO_SHADER, + CL_RESIZE, CL_SUBBURN, @@ -231,8 +233,8 @@ static const float FILTER_DEFAULT_LIBPLACEBO_TONEMAPPING_REINHARD_CONTRAST = 0.5 static const float FILTER_DEFAULT_LIBPLACEBO_TONEMAPPING_LINEAR_KNEE = 0.3f; static const float FILTER_DEFAULT_LIBPLACEBO_TONEMAPPING_EXPOSURE = 1.0f; -static const int FILTER_DEFAULT_LIBPLACEBO_TONEMAPPING_SRC_CSP = 1; -static const int FILTER_DEFAULT_LIBPLACEBO_TONEMAPPING_DST_CSP = 0; +static const int FILTER_DEFAULT_LIBPLACEBO_TONEMAPPING_SRC_CSP = -1; +static const int FILTER_DEFAULT_LIBPLACEBO_TONEMAPPING_DST_CSP = -1; static const float FILTER_DEFAULT_LIBPLACEBO_TONEMAPPING_SRC_MAX = -1.0f; static const float FILTER_DEFAULT_LIBPLACEBO_TONEMAPPING_SRC_MIN = -1.0f; static const float FILTER_DEFAULT_LIBPLACEBO_TONEMAPPING_DST_MAX = -1.0f; @@ -376,6 +378,17 @@ static const float FILTER_DEFAULT_EDGELEVEL_THRESHOLD = 20.0f; static const float FILTER_DEFAULT_EDGELEVEL_BLACK = 0.0f; static const float FILTER_DEFAULT_EDGELEVEL_WHITE = 0.0f; +static const TCHAR *FILTER_DEFAULT_LIBPLACEBO_SHADER_RESAMPLER_NAME = _T("libplacebo-ewa-lanczos"); +static const int FILTER_DEFAULT_LIBPLACEBO_SHADER_COLORSYSTEM = 0; +static const int FILTER_DEFAULT_LIBPLACEBO_SHADER_TRANSFER = 0; +static const int FILTER_DEFAULT_LIBPLACEBO_SHADER_CHROMALOC = 0; +static const float FILTER_DEFAULT_LIBPLACEBO_SHADER_RADIUS = FILTER_DEFAULT_LIBPLACEBO_RESAMPLE_RADIUS; +static const float FILTER_DEFAULT_LIBPLACEBO_SHADER_CLAMP = FILTER_DEFAULT_LIBPLACEBO_RESAMPLE_CLAMP; +static const float FILTER_DEFAULT_LIBPLACEBO_SHADER_TAPER = FILTER_DEFAULT_LIBPLACEBO_RESAMPLE_TAPER; +static const float FILTER_DEFAULT_LIBPLACEBO_SHADER_BLUR = FILTER_DEFAULT_LIBPLACEBO_RESAMPLE_BLUR; +static const float FILTER_DEFAULT_LIBPLACEBO_SHADER_ANTIRING = FILTER_DEFAULT_LIBPLACEBO_RESAMPLE_ANTIRING; +static const bool FILTER_DEFAULT_LIBPLACEBO_SHADER_LINEAR = false; + static const int FILTER_DEFAULT_UNSHARP_RADIUS = 3; static const float FILTER_DEFAULT_UNSHARP_WEIGHT = 0.5f; static const float FILTER_DEFAULT_UNSHARP_THRESHOLD = 10.0f; @@ -1117,6 +1130,38 @@ struct VppLibplaceboDeband { tstring print() const; }; +enum class VppLibplaceboColorsystem { + UNKNOWN, + BT_601, + BT_709, + SMPTE_240M, + BT_2020_NC, + BT_2020_C, + BT_2100_PQ, + BT_2100_HLG, + DOLBYVISION, + YCGCO, + RGB, + XYZ, + COUNT +}; + +const CX_DESC list_vpp_libplacebo_colorsystem[] = { + { _T("unknown"), (int)VppLibplaceboColorsystem::UNKNOWN }, + { _T("bt601"), (int)VppLibplaceboColorsystem::BT_601 }, + { _T("bt709"), (int)VppLibplaceboColorsystem::BT_709 }, + { _T("smpte240m"), (int)VppLibplaceboColorsystem::SMPTE_240M }, + { _T("bt2020nc"), (int)VppLibplaceboColorsystem::BT_2020_NC }, + { _T("bt2020c"), (int)VppLibplaceboColorsystem::BT_2020_C }, + { _T("bt2100pq"), (int)VppLibplaceboColorsystem::BT_2100_PQ }, + { _T("bt2100hlg"), (int)VppLibplaceboColorsystem::BT_2100_HLG }, + { _T("dolbyvision"), (int)VppLibplaceboColorsystem::DOLBYVISION }, + { _T("ycgco"), (int)VppLibplaceboColorsystem::YCGCO }, + { _T("rgb"), (int)VppLibplaceboColorsystem::RGB }, + { _T("xyz"), (int)VppLibplaceboColorsystem::XYZ }, + { NULL, 0 } +}; + enum class VppLibplaceboToneMappingCSP { Auto = -1, SDR, @@ -1415,6 +1460,29 @@ struct VppLibplaceboToneMapping { tstring print() const; }; +struct VppLibplaceboShader { + bool enable; + tstring shader; + int width; + int height; + std::vector> params; + RGY_VPP_RESIZE_ALGO resize_algo; + VppLibplaceboColorsystem colorsystem; + VppLibplaceboToneMappingTransfer transfer; + CspChromaloc chromaloc; + float radius; + float clamp_; + float taper; + float blur; + float antiring; + bool linear; + + VppLibplaceboShader(); + bool operator==(const VppLibplaceboShader &x) const; + bool operator!=(const VppLibplaceboShader &x) const; + tstring print() const; +}; + struct ColorspaceConv { VideoVUIInfo from, to; double sdr_source_peak; @@ -2164,6 +2232,7 @@ struct RGYParamVpp { VppSmooth smooth; VppDenoiseFFT3D fft3d; std::vector subburn; + std::vector libplacebo_shader; VppUnsharp unsharp; VppEdgelevel edgelevel; VppWarpsharp warpsharp;