From 215c86455f5856eb85b2781c5218b3a0ce87fe65 Mon Sep 17 00:00:00 2001 From: Conn O'Griofa Date: Wed, 28 Dec 2022 02:27:47 +0000 Subject: [PATCH] nvenc, amdvce: rework all user presets/options (#623) --- docs/source/about/advanced_usage.rst | 92 ++++++----- src/config.cpp | 198 ++++++++++++++--------- src/config.h | 4 +- src/video.cpp | 6 +- src_assets/common/assets/web/config.html | 83 +++++----- 5 files changed, 224 insertions(+), 159 deletions(-) diff --git a/docs/source/about/advanced_usage.rst b/docs/source/about/advanced_usage.rst index 4f1455c3..aa43d2e8 100644 --- a/docs/source/about/advanced_usage.rst +++ b/docs/source/about/advanced_usage.rst @@ -824,27 +824,52 @@ nv_preset ========== =========== Value Description ========== =========== - default let ffmpeg decide - hp high performance - hq high quality - slow high quality, 2 passes - medium high quality, 1 pass - fast high performance, 1 pass - bd - ll low latency - llhq low latency, high quality - llhp low latency, high performance - lossless lossless - losslesshp lossless, high performance + p1 fastest (lowest quality) + p2 faster (lower quality) + p3 fast (low quality) + p4 medium (default) + p5 slow (good quality) + p6 slower (better quality) + p7 slowest (best quality) ========== =========== **Default** - ``llhq`` + ``p4`` **Example** .. code-block:: text - nv_preset = llhq + nv_preset = p4 + +nv_tune +^^^^^^^ + +**Description** + The encoder tuning profile. + + .. Note:: This option only applies when using nvenc `encoder`_. + +**Choices** + +.. table:: + :widths: auto + + ========== =========== + Value Description + ========== =========== + hq high quality + ll low latency + ull ultra low latency + lossless lossless + ========== =========== + +**Default** + ``ull`` + +**Example** + .. code-block:: text + + nv_tune = ull nv_rc ^^^^^ @@ -854,8 +879,6 @@ nv_rc .. Note:: This option only applies when using nvenc `encoder`_. - .. Note:: Moonlight does not currently support variable bitrate, although it can still be selected here. - **Choices** .. table:: @@ -864,22 +887,18 @@ nv_rc ========== =========== Value Description ========== =========== - auto let ffmpeg decide constqp constant QP mode - cbr constant bitrate - cbr_hq constant bitrate, high quality - cbr_ld_hq constant bitrate, low delay, high quality vbr variable bitrate - vbr_hq variable bitrate, high quality + cbr constant bitrate ========== =========== **Default** - ``auto`` + ``cbr`` **Example** .. code-block:: text - nv_rc = auto + nv_rc = cbr nv_coder ^^^^^^^^ @@ -887,7 +906,7 @@ nv_coder **Description** The entropy encoding to use. - .. Note:: This option only applies when using nvenc `encoder`_. + .. Note:: This option only applies when using H264 with nvenc `encoder`_. **Choices** @@ -898,8 +917,8 @@ nv_coder Value Description ========== =========== auto let ffmpeg decide - cabac - cavlc + cabac context adaptive binary arithmetic coding - higher quality + cavlc context adaptive variable-length coding - faster decode ========== =========== **Default** @@ -926,9 +945,9 @@ amd_quality ========== =========== Value Description ========== =========== - default let ffmpeg decide - speed fast - balanced balance performance and speed + speed prefer speed + balanced balanced + quality prefer quality ========== =========== **Default** @@ -947,8 +966,6 @@ amd_rc .. Note:: This option only applies when using amdvce `encoder`_. - .. Note:: Moonlight does not currently support variable bitrate, although it can still be selected here. - **Choices** .. table:: @@ -957,20 +974,19 @@ amd_rc =========== =========== Value Description =========== =========== - auto let ffmpeg decide - cqp constant QP mode + cqp constant qp mode cbr constant bitrate vbr_latency variable bitrate, latency constrained vbr_peak variable bitrate, peak constrained =========== =========== **Default** - ``auto`` + ``vbr_latency`` **Example** .. code-block:: text - amd_rc = auto + amd_rc = vbr_latency amd_coder ^^^^^^^^^ @@ -978,7 +994,7 @@ amd_coder **Description** The entropy encoding to use. - .. Note:: This option only applies when using nvenc `encoder`_. + .. Note:: This option only applies when using H264 with amdvce `encoder`_. **Choices** @@ -989,8 +1005,8 @@ amd_coder Value Description ========== =========== auto let ffmpeg decide - cabac - cavlc + cabac context adaptive variable-length coding - higher quality + cavlc context adaptive binary arithmetic coding - faster decode ========== =========== **Default** diff --git a/src/config.cpp b/src/config.cpp index 00e47681..bc387d97 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -25,50 +25,71 @@ using namespace std::literals; namespace config { namespace nv { +#ifdef __APPLE__ +// values accurate as of 27/12/2022, but aren't strictly necessary for MacOS build +#define NV_ENC_TUNING_INFO_HIGH_QUALITY 1 +#define NV_ENC_TUNING_INFO_LOW_LATENCY 2 +#define NV_ENC_TUNING_INFO_ULTRA_LOW_LATENCY 3 +#define NV_ENC_TUNING_INFO_LOSSLESS 4 +#define NV_ENC_PARAMS_RC_CONSTQP 0x0 +#define NV_ENC_PARAMS_RC_VBR 0x1 +#define NV_ENC_PARAMS_RC_CBR 0x2 +#define NV_ENC_H264_ENTROPY_CODING_MODE_CABAC 1 +#define NV_ENC_H264_ENTROPY_CODING_MODE_CAVLC 2 +#else +#include +#endif + enum preset_e : int { - _default = 0, - slow, - medium, - fast, - hp, - hq, - bd, - ll_default, - llhq, - llhp, - lossless_default, // lossless presets must be the last ones - lossless_hp, + p1 = 12, // PRESET_P1, // must be kept in sync with + p2, // PRESET_P2, + p3, // PRESET_P3, + p4, // PRESET_P4, + p5, // PRESET_P5, + p6, // PRESET_P6, + p7 // PRESET_P7 +}; + +enum tune_e : int { + hq = NV_ENC_TUNING_INFO_HIGH_QUALITY, + ll = NV_ENC_TUNING_INFO_LOW_LATENCY, + ull = NV_ENC_TUNING_INFO_ULTRA_LOW_LATENCY, + lossless = NV_ENC_TUNING_INFO_LOSSLESS }; enum rc_e : int { - constqp = 0x0, /**< Constant QP mode */ - vbr = 0x1, /**< Variable bitrate mode */ - cbr = 0x2, /**< Constant bitrate mode */ - cbr_ld_hq = 0x8, /**< low-delay CBR, high quality */ - cbr_hq = 0x10, /**< CBR, high quality (slower) */ - vbr_hq = 0x20 /**< VBR, high quality (slower) */ + constqp = NV_ENC_PARAMS_RC_CONSTQP, /**< Constant QP mode */ + vbr = NV_ENC_PARAMS_RC_VBR, /**< Variable bitrate mode */ + cbr = NV_ENC_PARAMS_RC_CBR /**< Constant bitrate mode */ }; enum coder_e : int { _auto = 0, - cabac, - cavlc + cabac = NV_ENC_H264_ENTROPY_CODING_MODE_CABAC, + cavlc = NV_ENC_H264_ENTROPY_CODING_MODE_CAVLC, }; std::optional preset_from_view(const std::string_view &preset) { #define _CONVERT_(x) \ if(preset == #x##sv) return x - _CONVERT_(slow); - _CONVERT_(medium); - _CONVERT_(fast); - _CONVERT_(hp); - _CONVERT_(bd); - _CONVERT_(ll_default); - _CONVERT_(llhq); - _CONVERT_(llhp); - _CONVERT_(lossless_default); - _CONVERT_(lossless_hp); - if(preset == "default"sv) return _default; + _CONVERT_(p1); + _CONVERT_(p2); + _CONVERT_(p3); + _CONVERT_(p4); + _CONVERT_(p5); + _CONVERT_(p6); + _CONVERT_(p7); +#undef _CONVERT_ + return std::nullopt; +} + +std::optional tune_from_view(const std::string_view &tune) { +#define _CONVERT_(x) \ + if(tune == #x##sv) return x + _CONVERT_(hq); + _CONVERT_(ll); + _CONVERT_(ull); + _CONVERT_(lossless); #undef _CONVERT_ return std::nullopt; } @@ -79,9 +100,6 @@ std::optional rc_from_view(const std::string_view &rc) { _CONVERT_(constqp); _CONVERT_(vbr); _CONVERT_(cbr); - _CONVERT_(cbr_hq); - _CONVERT_(vbr_hq); - _CONVERT_(cbr_ld_hq); #undef _CONVERT_ return std::nullopt; } @@ -96,56 +114,75 @@ int coder_from_view(const std::string_view &coder) { } // namespace nv namespace amd { -enum quality_e : int { - _default = 0, - speed, - balanced, +#ifdef __APPLE__ +// values accurate as of 27/12/2022, but aren't strictly necessary for MacOS build +#define AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_SPEED 10 +#define AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_QUALITY 0 +#define AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_BALANCED 5 +#define AMF_VIDEO_ENCODER_QUALITY_PRESET_SPEED 1 +#define AMF_VIDEO_ENCODER_QUALITY_PRESET_QUALITY 2 +#define AMF_VIDEO_ENCODER_QUALITY_PRESET_BALANCED 0 +#define AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP 0 +#define AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR 3 +#define AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR 2 +#define AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR 1 +#define AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP 0 +#define AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR 1 +#define AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR 2 +#define AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR 3 +#define AMF_VIDEO_ENCODER_UNDEFINED 0 +#define AMF_VIDEO_ENCODER_CABAC 1 +#define AMF_VIDEO_ENCODER_CALV 2 +#else +#include +#include +#endif + +enum class quality_hevc_e : int { + speed = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_SPEED, + quality = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_QUALITY, + balanced = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_BALANCED +}; + +enum class quality_h264_e : int { + speed = AMF_VIDEO_ENCODER_QUALITY_PRESET_SPEED, + quality = AMF_VIDEO_ENCODER_QUALITY_PRESET_QUALITY, + balanced = AMF_VIDEO_ENCODER_QUALITY_PRESET_BALANCED }; enum class rc_hevc_e : int { - cqp, /**< Constant QP mode */ - vbr_latency, /**< Latency Constrained Variable Bitrate */ - vbr_peak, /**< Peak Constrained Variable Bitrate */ - cbr, /**< Constant bitrate mode */ + cqp = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP, + vbr_latency = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR, + vbr_peak = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR, + cbr = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR }; enum class rc_h264_e : int { - cqp, /**< Constant QP mode */ - cbr, /**< Constant bitrate mode */ - vbr_peak, /**< Peak Constrained Variable Bitrate */ - vbr_latency, /**< Latency Constrained Variable Bitrate */ + cqp = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP, + vbr_latency = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR, + vbr_peak = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR, + cbr = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR }; enum coder_e : int { - _auto = 0, - cabac, - cavlc + _auto = AMF_VIDEO_ENCODER_UNDEFINED, + cabac = AMF_VIDEO_ENCODER_CABAC, + cavlc = AMF_VIDEO_ENCODER_CALV }; -std::optional quality_from_view(const std::string_view &quality) { +std::optional quality_from_view(const std::string_view &quality_type, int codec) { #define _CONVERT_(x) \ - if(quality == #x##sv) return x + if(quality_type == #x##sv) return codec == 0 ? (int)quality_hevc_e::x : (int)quality_h264_e::x + _CONVERT_(quality); _CONVERT_(speed); _CONVERT_(balanced); - if(quality == "default"sv) return _default; #undef _CONVERT_ return std::nullopt; } -std::optional rc_h264_from_view(const std::string_view &rc) { +std::optional rc_from_view(const std::string_view &rc, int codec) { #define _CONVERT_(x) \ - if(rc == #x##sv) return (int)rc_h264_e::x - _CONVERT_(cqp); - _CONVERT_(vbr_latency); - _CONVERT_(vbr_peak); - _CONVERT_(cbr); -#undef _CONVERT_ - return std::nullopt; -} - -std::optional rc_hevc_from_view(const std::string_view &rc) { -#define _CONVERT_(x) \ - if(rc == #x##sv) return (int)rc_hevc_e::x + if(rc == #x##sv) return codec == 0 ? (int)rc_hevc_e::x : (int)rc_h264_e::x _CONVERT_(cqp); _CONVERT_(vbr_latency); _CONVERT_(vbr_peak); @@ -211,16 +248,19 @@ video_t video { }, // software { - nv::llhq, - std::nullopt, - -1 }, // nv + nv::p4, // preset + nv::ull, // tune + nv::cbr, // rc + nv::_auto // coder + }, // nv { - amd::balanced, - std::nullopt, - std::nullopt, - -1 }, // amd - + (int)amd::quality_h264_e::balanced, // quality (h264) + (int)amd::quality_hevc_e::balanced, // quality (hevc) + (int)amd::rc_h264_e::vbr_latency, // rate control (h264) + (int)amd::rc_hevc_e::vbr_latency, // rate control (hevc) + (int)amd::coder_e::_auto, // coder + }, // amd { 0, 0, @@ -716,17 +756,23 @@ void apply_config(std::unordered_map &&vars) { string_f(vars, "sw_preset", video.sw.preset); string_f(vars, "sw_tune", video.sw.tune); int_f(vars, "nv_preset", video.nv.preset, nv::preset_from_view); + int_f(vars, "nv_tune", video.nv.tune, nv::tune_from_view); int_f(vars, "nv_rc", video.nv.rc, nv::rc_from_view); int_f(vars, "nv_coder", video.nv.coder, nv::coder_from_view); - int_f(vars, "amd_quality", video.amd.quality, amd::quality_from_view); + std::string quality; + string_f(vars, "amd_quality", quality); + if(!quality.empty()) { + video.amd.quality_h264 = amd::quality_from_view(quality, 1); + video.amd.quality_hevc = amd::quality_from_view(quality, 0); + } std::string rc; string_f(vars, "amd_rc", rc); int_f(vars, "amd_coder", video.amd.coder, amd::coder_from_view); if(!rc.empty()) { - video.amd.rc_h264 = amd::rc_h264_from_view(rc); - video.amd.rc_hevc = amd::rc_hevc_from_view(rc); + video.amd.rc_h264 = amd::rc_from_view(rc, 1); + video.amd.rc_hevc = amd::rc_from_view(rc, 0); } int_f(vars, "vt_coder", video.vt.coder, vt::coder_from_view); diff --git a/src/config.h b/src/config.h index 4ecb9f32..6d4d69be 100644 --- a/src/config.h +++ b/src/config.h @@ -23,12 +23,14 @@ struct video_t { struct { std::optional preset; + std::optional tune; std::optional rc; int coder; } nv; struct { - std::optional quality; + std::optional quality_h264; + std::optional quality_hevc; std::optional rc_h264; std::optional rc_hevc; int coder; diff --git a/src/video.cpp b/src/video.cpp index 70d7a6c4..5d353a38 100644 --- a/src/video.cpp +++ b/src/video.cpp @@ -422,6 +422,7 @@ static encoder_t nvenc { { "forced-idr"s, 1 }, { "zerolatency"s, 1 }, { "preset"s, &config::video.nv.preset }, + { "tune"s, &config::video.nv.tune }, { "rc"s, &config::video.nv.rc }, }, std::nullopt, @@ -433,6 +434,7 @@ static encoder_t nvenc { { "forced-idr"s, 1 }, { "zerolatency"s, 1 }, { "preset"s, &config::video.nv.preset }, + { "tune"s, &config::video.nv.tune }, { "rc"s, &config::video.nv.rc }, { "coder"s, &config::video.nv.coder }, }, @@ -462,7 +464,7 @@ static encoder_t amdvce { { "header_insertion_mode"s, "idr"s }, { "qmax"s, 51 }, { "qmin"s, 0 }, - { "quality"s, &config::video.amd.quality }, + { "quality"s, &config::video.amd.quality_hevc }, { "rc"s, &config::video.amd.rc_hevc }, { "usage"s, "ultralowlatency"s }, { "vbaq"s, true }, @@ -476,7 +478,7 @@ static encoder_t amdvce { { "log_to_dbg"s, "1"s }, { "qmax"s, 51 }, { "qmin"s, 0 }, - { "quality"s, &config::video.amd.quality }, + { "quality"s, &config::video.amd.quality_h264 }, { "rc"s, &config::video.amd.rc_h264 }, { "usage"s, "ultralowlatency"s }, { "vbaq"s, true }, diff --git a/src_assets/common/assets/web/config.html b/src_assets/common/assets/web/config.html index 95d17f0d..7475ad83 100644 --- a/src_assets/common/assets/web/config.html +++ b/src_assets/common/assets/web/config.html @@ -644,40 +644,40 @@
- + +
+
+ +
- +
- +
@@ -685,33 +685,31 @@
- +
- +
- +
@@ -851,12 +849,13 @@ this.config.origin_web_manager_allowed || "lan"; this.config.hevc_mode = this.config.hevc_mode || 0; this.config.encoder = this.config.encoder || ""; - this.config.nv_preset = this.config.nv_preset || "default"; - this.config.nv_rc = this.config.nv_rc || "auto"; + this.config.nv_preset = this.config.nv_preset || "p4"; + this.config.nv_tune = this.config.nv_tune || "ull"; this.config.nv_coder = this.config.nv_coder || "auto"; + this.config.nv_rc = this.config.nv_rc || "cbr"; this.config.amd_coder = this.config.amd_coder || "auto" - this.config.amd_quality = this.config.amd_quality || "default"; - this.config.amd_rc = this.config.amd_rc || "auto"; + this.config.amd_quality = this.config.amd_quality || "balanced"; + this.config.amd_rc = this.config.amd_rc || "vbr_latency"; this.config.vt_coder = this.config.vt_coder || "auto"; this.config.vt_software = this.config.vt_software || "auto"; this.config.vt_realtime = this.config.vt_realtime || "enabled";