mirror of
https://github.com/LizardByte/Sunshine.git
synced 2025-02-11 06:40:28 +00:00
nvenc: new config page
This commit is contained in:
parent
11ebb47b3e
commit
8b40fa6dd5
133
src/config.cpp
133
src/config.cpp
@ -24,6 +24,11 @@
|
||||
#include <shellapi.h>
|
||||
#endif
|
||||
|
||||
#ifndef __APPLE__
|
||||
// For NVENC legacy constants
|
||||
#include <ffnvcodec/nvEncodeAPI.h>
|
||||
#endif
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
using namespace std::literals;
|
||||
|
||||
@ -35,96 +40,16 @@ 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 <ffnvcodec/nvEncodeAPI.h>
|
||||
#endif
|
||||
|
||||
enum preset_e : int {
|
||||
p1 = 12, // PRESET_P1, // must be kept in sync with <libavcodec/nvenc.h>
|
||||
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 = 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 = NV_ENC_H264_ENTROPY_CODING_MODE_CABAC,
|
||||
cavlc = NV_ENC_H264_ENTROPY_CODING_MODE_CAVLC,
|
||||
};
|
||||
|
||||
std::optional<preset_e>
|
||||
preset_from_view(const std::string_view &preset) {
|
||||
#define _CONVERT_(x) \
|
||||
if (preset == #x##sv) return x
|
||||
_CONVERT_(p1);
|
||||
_CONVERT_(p2);
|
||||
_CONVERT_(p3);
|
||||
_CONVERT_(p4);
|
||||
_CONVERT_(p5);
|
||||
_CONVERT_(p6);
|
||||
_CONVERT_(p7);
|
||||
#undef _CONVERT_
|
||||
return std::nullopt;
|
||||
nvenc::nvenc_two_pass
|
||||
twopass_from_view(const std::string_view &preset) {
|
||||
if (preset == "disabled") return nvenc::nvenc_two_pass::disabled;
|
||||
if (preset == "quarter_res") return nvenc::nvenc_two_pass::quarter_resolution;
|
||||
if (preset == "full_res") return nvenc::nvenc_two_pass::full_resolution;
|
||||
BOOST_LOG(warning) << "config: unknown nvenc_twopass value: " << preset;
|
||||
return nvenc::nvenc_two_pass::quarter_resolution;
|
||||
}
|
||||
|
||||
std::optional<tune_e>
|
||||
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;
|
||||
}
|
||||
|
||||
std::optional<rc_e>
|
||||
rc_from_view(const std::string_view &rc) {
|
||||
#define _CONVERT_(x) \
|
||||
if (rc == #x##sv) return x
|
||||
_CONVERT_(constqp);
|
||||
_CONVERT_(vbr);
|
||||
_CONVERT_(cbr);
|
||||
#undef _CONVERT_
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
int
|
||||
coder_from_view(const std::string_view &coder) {
|
||||
if (coder == "auto"sv) return _auto;
|
||||
if (coder == "cabac"sv || coder == "ac"sv) return cabac;
|
||||
if (coder == "cavlc"sv || coder == "vlc"sv) return cavlc;
|
||||
|
||||
return -1;
|
||||
}
|
||||
} // namespace nv
|
||||
|
||||
namespace amd {
|
||||
@ -400,12 +325,8 @@ namespace config {
|
||||
11, // superfast
|
||||
}, // software
|
||||
|
||||
{
|
||||
nv::p4, // preset
|
||||
nv::ull, // tune
|
||||
nv::cbr, // rc
|
||||
nv::_auto // coder
|
||||
}, // nv
|
||||
{}, // nv
|
||||
{}, // nv_legacy
|
||||
|
||||
{
|
||||
qsv::medium, // preset
|
||||
@ -640,6 +561,16 @@ namespace config {
|
||||
vars.erase(it);
|
||||
}
|
||||
|
||||
template <typename T, typename F>
|
||||
void
|
||||
generic_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, T &input, F &&f) {
|
||||
std::string tmp;
|
||||
string_f(vars, name, tmp);
|
||||
if (!tmp.empty()) {
|
||||
input = f(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
string_restricted_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, std::string &input, const std::vector<std::string_view> &allowed_vals) {
|
||||
std::string temp;
|
||||
@ -989,10 +920,18 @@ namespace config {
|
||||
video.sw.svtav1_preset = sw::svtav1_preset_from_view(video.sw.sw_preset);
|
||||
}
|
||||
string_f(vars, "sw_tune", video.sw.sw_tune);
|
||||
int_f(vars, "nv_preset", video.nv.nv_preset, nv::preset_from_view);
|
||||
int_f(vars, "nv_tune", video.nv.nv_tune, nv::tune_from_view);
|
||||
int_f(vars, "nv_rc", video.nv.nv_rc, nv::rc_from_view);
|
||||
int_f(vars, "nv_coder", video.nv.nv_coder, nv::coder_from_view);
|
||||
|
||||
int_between_f(vars, "nvenc_preset", video.nv.quality_preset, { 1, 7 });
|
||||
generic_f(vars, "nvenc_twopass", video.nv.two_pass, nv::twopass_from_view);
|
||||
bool_f(vars, "nvenc_h264_cavlc", video.nv.h264_cavlc);
|
||||
|
||||
#ifndef __APPLE__
|
||||
video.nv_legacy.preset = video.nv.quality_preset + 11;
|
||||
video.nv_legacy.multipass = video.nv.two_pass == nvenc::nvenc_two_pass::quarter_resolution ? NV_ENC_TWO_PASS_QUARTER_RESOLUTION :
|
||||
video.nv.two_pass == nvenc::nvenc_two_pass::full_resolution ? NV_ENC_TWO_PASS_FULL_RESOLUTION :
|
||||
NV_ENC_MULTI_PASS_DISABLED;
|
||||
video.nv_legacy.h264_coder = video.nv.h264_cavlc ? NV_ENC_H264_ENTROPY_CODING_MODE_CAVLC : NV_ENC_H264_ENTROPY_CODING_MODE_CABAC;
|
||||
#endif
|
||||
|
||||
int_f(vars, "qsv_preset", video.qsv.qsv_preset, qsv::preset_from_view);
|
||||
int_f(vars, "qsv_coder", video.qsv.qsv_cavlc, qsv::coder_from_view);
|
||||
|
13
src/config.h
13
src/config.h
@ -11,6 +11,8 @@
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "nvenc/nvenc_config.h"
|
||||
|
||||
namespace config {
|
||||
struct video_t {
|
||||
// ffmpeg params
|
||||
@ -26,12 +28,13 @@ namespace config {
|
||||
std::optional<int> svtav1_preset;
|
||||
} sw;
|
||||
|
||||
nvenc::nvenc_config nv;
|
||||
|
||||
struct {
|
||||
std::optional<int> nv_preset;
|
||||
std::optional<int> nv_tune;
|
||||
std::optional<int> nv_rc;
|
||||
int nv_coder;
|
||||
} nv;
|
||||
int preset;
|
||||
int multipass;
|
||||
int h264_coder;
|
||||
} nv_legacy;
|
||||
|
||||
struct {
|
||||
std::optional<int> qsv_preset;
|
||||
|
@ -15,10 +15,10 @@ namespace nvenc {
|
||||
|
||||
struct nvenc_config {
|
||||
// Quality preset from 1 to 7, higher is slower
|
||||
unsigned quality_preset = 1;
|
||||
int quality_preset = 1;
|
||||
|
||||
// Use optional preliminary pass for better motion vectors, bitrate distribution and stricter VBV(HRD), uses CUDA cores
|
||||
nvenc_two_pass two_pass = nvenc_two_pass::disabled;
|
||||
nvenc_two_pass two_pass = nvenc_two_pass::quarter_resolution;
|
||||
|
||||
// Improves fades compression, uses CUDA cores
|
||||
bool weighted_prediction = false;
|
||||
|
@ -874,12 +874,8 @@ namespace platf::dxgi {
|
||||
init_encoder(const ::video::config_t &client_config, const ::video::sunshine_colorspace_t &colorspace) override {
|
||||
if (!nvenc_d3d) return false;
|
||||
|
||||
nvenc::nvenc_config nvenc_config;
|
||||
nvenc_config.quality_preset = config::video.nv.nv_preset ? (*config::video.nv.nv_preset - 11) : 1;
|
||||
nvenc_config.h264_cavlc = (config::video.nv.nv_coder == NV_ENC_H264_ENTROPY_CODING_MODE_CAVLC);
|
||||
|
||||
auto nvenc_colorspace = nvenc::nvenc_colorspace_from_sunshine_colorspace(colorspace);
|
||||
if (!nvenc_d3d->create_encoder(nvenc_config, client_config, nvenc_colorspace, buffer_format)) return false;
|
||||
if (!nvenc_d3d->create_encoder(config::video.nv, client_config, nvenc_colorspace, buffer_format)) return false;
|
||||
|
||||
base.apply_colorspace(colorspace);
|
||||
return base.init_output(nvenc_d3d->get_input_texture(), client_config.width, client_config.height) == 0;
|
||||
|
@ -601,7 +601,7 @@ namespace video {
|
||||
},
|
||||
PARALLEL_ENCODING | REF_FRAMES_INVALIDATION // flags
|
||||
};
|
||||
#else
|
||||
#elif !defined(__APPLE__)
|
||||
static encoder_t nvenc {
|
||||
"nvenc"sv,
|
||||
std::make_unique<encoder_platform_formats_avcodec>(
|
||||
@ -625,9 +625,10 @@ namespace video {
|
||||
{ "delay"s, 0 },
|
||||
{ "forced-idr"s, 1 },
|
||||
{ "zerolatency"s, 1 },
|
||||
{ "preset"s, &config::video.nv.nv_preset },
|
||||
{ "tune"s, &config::video.nv.nv_tune },
|
||||
{ "rc"s, &config::video.nv.nv_rc },
|
||||
{ "preset"s, &config::video.nv_legacy.preset },
|
||||
{ "tune"s, NV_ENC_TUNING_INFO_ULTRA_LOW_LATENCY },
|
||||
{ "rc"s, NV_ENC_PARAMS_RC_CBR },
|
||||
{ "multipass"s, &config::video.nv_legacy.multipass },
|
||||
},
|
||||
// SDR-specific options
|
||||
{},
|
||||
@ -642,9 +643,10 @@ namespace video {
|
||||
{ "delay"s, 0 },
|
||||
{ "forced-idr"s, 1 },
|
||||
{ "zerolatency"s, 1 },
|
||||
{ "preset"s, &config::video.nv.nv_preset },
|
||||
{ "tune"s, &config::video.nv.nv_tune },
|
||||
{ "rc"s, &config::video.nv.nv_rc },
|
||||
{ "preset"s, &config::video.nv_legacy.preset },
|
||||
{ "tune"s, NV_ENC_TUNING_INFO_ULTRA_LOW_LATENCY },
|
||||
{ "rc"s, NV_ENC_PARAMS_RC_CBR },
|
||||
{ "multipass"s, &config::video.nv_legacy.multipass },
|
||||
},
|
||||
// SDR-specific options
|
||||
{
|
||||
@ -662,10 +664,11 @@ namespace video {
|
||||
{ "delay"s, 0 },
|
||||
{ "forced-idr"s, 1 },
|
||||
{ "zerolatency"s, 1 },
|
||||
{ "preset"s, &config::video.nv.nv_preset },
|
||||
{ "tune"s, &config::video.nv.nv_tune },
|
||||
{ "rc"s, &config::video.nv.nv_rc },
|
||||
{ "coder"s, &config::video.nv.nv_coder },
|
||||
{ "preset"s, &config::video.nv_legacy.preset },
|
||||
{ "tune"s, NV_ENC_TUNING_INFO_ULTRA_LOW_LATENCY },
|
||||
{ "rc"s, NV_ENC_PARAMS_RC_CBR },
|
||||
{ "coder"s, &config::video.nv_legacy.h264_coder },
|
||||
{ "multipass"s, &config::video.nv_legacy.multipass },
|
||||
},
|
||||
// SDR-specific options
|
||||
{
|
||||
|
@ -872,41 +872,60 @@
|
||||
<div v-if="currentTab === 'nv'" class="config-page">
|
||||
<!--NVENC SETTINGS-->
|
||||
<div class="mb-3">
|
||||
<label for="nv_preset" class="form-label">NVENC Preset</label>
|
||||
<select id="nv_preset" class="form-select" v-model="config.nv_preset">
|
||||
<option value="p1">p1 -- fastest (lowest quality)</option>
|
||||
<option value="p2">p2 -- faster (lower quality)</option>
|
||||
<option value="p3">p3 -- fast (low quality)</option>
|
||||
<option value="p4">p4 -- medium (default)</option>
|
||||
<option value="p5">p5 -- slow (good quality)</option>
|
||||
<option value="p6">p6 -- slower (better quality)</option>
|
||||
<option value="p7">p7 -- slowest (best quality)</option>
|
||||
<label for="nvenc_preset" class="form-label">Performance preset</label>
|
||||
<select id="nvenc_preset" class="form-select" v-model="config.nvenc_preset">
|
||||
<option value="1">P1 (fastest, default)</option>
|
||||
<option value="2">P2</option>
|
||||
<option value="3">P3</option>
|
||||
<option value="4">P4</option>
|
||||
<option value="5">P5</option>
|
||||
<option value="6">P6</option>
|
||||
<option value="7">P7 (slowest)</option>
|
||||
</select>
|
||||
<div class="form-text">Higher numbers improve compression (quality at given bitrate) at the cost of
|
||||
<strong>increased encoding latency</strong>.<br>
|
||||
Recommended to change only when limited by network or decoder, otherwise similar effect can be accomplished by
|
||||
increasing bitrate.
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="nv_tune" class="form-label">NVENC Tune</label>
|
||||
<select id="nv_tune" class="form-select" v-model="config.nv_tune">
|
||||
<option value="hq">hq -- high quality</option>
|
||||
<option value="ll">ll -- low latency</option>
|
||||
<option value="ull">ull -- ultra low latency (default)</option>
|
||||
<option value="lossless">lossless -- lossless</option>
|
||||
<label for="nvenc_twopass" class="form-label">Two-pass mode</label>
|
||||
<select id="nvenc_twopass" class="form-select" v-model="config.nvenc_twopass">
|
||||
<option value="disabled">Disabled (fastest, not recommended)</option>
|
||||
<option value="quarter_res">Quarter resolution (faster, default)</option>
|
||||
<option value="full_res">Full resolution (slower)</option>
|
||||
</select>
|
||||
<div class="form-text">Adds preliminary encoding pass.<br>
|
||||
This allows to detect more motion vectors, better distribute bitrate across the frame and more strictly adhere to
|
||||
bitrate limits.<br>
|
||||
Disabling it is not recommended since this can lead to occasional bitrate overshoot and subsequent packet loss.
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="nv_rc" class="form-label">NVENC Rate Control</label>
|
||||
<select id="nv_rc" class="form-select" v-model="config.nv_rc">
|
||||
<option value="constqp">constqp -- constant qp mode</option>
|
||||
<option value="vbr">vbr -- variable bitrate</option>
|
||||
<option value="cbr">cbr -- constant bitrate (default)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="nv_coder" class="form-label">NVENC Coder (H264)</label>
|
||||
<select id="nv_coder" class="form-select" v-model="config.nv_coder">
|
||||
<option value="auto">auto -- let ffmpeg decide (default)</option>
|
||||
<option value="cabac">cabac -- context adaptive binary arithmetic coding - higher quality</option>
|
||||
<option value="cavlc">cavlc -- context adaptive variable-length coding - faster decode</option>
|
||||
</select>
|
||||
<div class="accordion">
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button" type="button" data-bs-toggle="collapse"
|
||||
data-bs-target="#panelsStayOpen-collapseOne">
|
||||
Miscellaneous options
|
||||
</button>
|
||||
</h2>
|
||||
<div id="panelsStayOpen-collapseOne" class="accordion-collapse collapse show"
|
||||
aria-labelledby="panelsStayOpen-headingOne">
|
||||
<div class="accordion-body">
|
||||
<div>
|
||||
<label for="nvenc_h264_cavlc" class="form-label">Prefer CAVLC over CABAC in H.264</label>
|
||||
<select id="nvenc_h264_cavlc" class="form-select" v-model="config.nvenc_h264_cavlc">
|
||||
<option value="disabled">Disabled (default)</option>
|
||||
<option value="enabled">Enabled</option>
|
||||
</select>
|
||||
<div class="form-text">Simpler form of entropy coding.<br>
|
||||
CAVLC needs around 10% more bitrate for same quality.<br>
|
||||
Only relevant for really old decoding devices.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--Intel Encoder Settings-->
|
||||
@ -1061,10 +1080,9 @@
|
||||
"keyboard": "enabled",
|
||||
"min_log_level": 2,
|
||||
"mouse": "enabled",
|
||||
"nv_coder": "auto",
|
||||
"nv_preset": "p4",
|
||||
"nv_rc": "cbr",
|
||||
"nv_tune": "ull",
|
||||
"nvenc_preset": "1",
|
||||
"nvenc_twopass": "quarter_res",
|
||||
"nvenc_h264_cavlc": "disabled",
|
||||
"origin_pin_allowed": "pc",
|
||||
"origin_web_ui_allowed": "lan",
|
||||
"qsv_coder": "auto",
|
||||
|
Loading…
x
Reference in New Issue
Block a user