Skip to content

Commit

Permalink
feat(win/nvenc): add split-frame encoding option
Browse files Browse the repository at this point in the history
  • Loading branch information
ns6089 committed Aug 23, 2024
1 parent e06db26 commit 2ddf1b8
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 2 deletions.
40 changes: 40 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -1774,6 +1774,46 @@ editing the `conf` file in a text editor. Use the examples as reference.
</tr>
</table>

### [nvenc_split_encode](https://localhost:47990/config/#nvenc_split_encode)

<table>
<tr>
<td>Description</td>
<td colspan="2">
Split the encoding of each video frame over multiple NVENC hardware units.
Significantly reduces encoding latency with a marginal compression efficiency penalty.
This option is ignored if your GPU has a singular NVENC unit.
@note{This option only applies when using NVENC [encoder](#encoderhttpslocalhost47990configencoder).}
@note{Applies to Windows only.}
</td>
</tr>
<tr>
<td>Default</td>
<td colspan="2">@code{}
driver_decides
@endcode</td>
</tr>
<tr>
<td>Example</td>
<td colspan="2">@code{}
nvenc_split_encode = driver_decides
@endcode</td>
</tr>
<tr>
<td rowspan="3">Choices</td>
<td>disabled</td>
<td>Disabled</td>
</tr>
<tr>
<td>driver_decides</td>
<td>NVIDIA driver makes the decision whether to enable it</td>
</tr>
<tr>
<td>enabled</td>
<td>Enabled</td>
</tr>
</table>

### [nvenc_latency_over_power](https://localhost:47990/config/#nvenc_latency_over_power)

<table>
Expand Down
11 changes: 11 additions & 0 deletions src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ namespace config {
return nvenc::nvenc_two_pass::quarter_resolution;
}

nvenc::nvenc_split_frame_encoding
split_encode_from_view(const std::string_view &preset) {
using enum nvenc::nvenc_split_frame_encoding;
if (preset == "disabled") return disabled;
if (preset == "driver_decides") return driver_decides;
if (preset == "enabled") return force_enabled;
BOOST_LOG(warning) << "config: unknown nvenc_split_encode value: " << preset;
return driver_decides;
}

} // namespace nv

namespace amd {
Expand Down Expand Up @@ -960,6 +970,7 @@ namespace config {
bool_f(vars, "nvenc_spatial_aq", video.nv.adaptive_quantization);
generic_f(vars, "nvenc_twopass", video.nv.two_pass, nv::twopass_from_view);
bool_f(vars, "nvenc_h264_cavlc", video.nv.h264_cavlc);
generic_f(vars, "nvenc_split_encode", video.nv.split_frame_encoding, nv::split_encode_from_view);
bool_f(vars, "nvenc_realtime_hags", video.nv_realtime_hags);
bool_f(vars, "nvenc_opengl_vulkan_on_dxgi", video.nv_opengl_vulkan_on_dxgi);
bool_f(vars, "nvenc_latency_over_power", video.nv_sunshine_high_power_mode);
Expand Down
17 changes: 15 additions & 2 deletions src/nvenc/common_impl/nvenc_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,15 @@ namespace nvenc {
init_params.frameRateNum = client_config.framerate;
init_params.frameRateDen = 1;

#if NVENC_INT_VERSION >= 1202
{
using enum nvenc_split_frame_encoding;
init_params.splitEncodeMode = config.split_frame_encoding == disabled ? NV_ENC_SPLIT_DISABLE_MODE :
config.split_frame_encoding == force_enabled ? NV_ENC_SPLIT_AUTO_FORCED_MODE :
NV_ENC_SPLIT_AUTO_MODE;
}
#endif

NV_ENC_PRESET_CONFIG preset_config = {
.version = NV_ENC_PRESET_CONFIG_VER,
.presetCfg = { .version = NV_ENC_CONFIG_VER },
Expand Down Expand Up @@ -257,8 +266,12 @@ namespace nvenc {
auto set_h264_hevc_common_format_config = [&](auto &format_config) {
format_config.repeatSPSPPS = 1;
format_config.idrPeriod = NVENC_INFINITE_GOPLENGTH;
format_config.sliceMode = 3;
format_config.sliceModeData = client_config.slicesPerFrame;
if (client_config.slicesPerFrame > 1 ||
NVENC_INT_VERSION < 1202 ||
config.split_frame_encoding == nvenc_split_frame_encoding::disabled) {
format_config.sliceMode = 3;
format_config.sliceModeData = client_config.slicesPerFrame;
}
if (buffer_is_yuv444()) {
format_config.chromaFormatIDC = 3;
}
Expand Down
9 changes: 9 additions & 0 deletions src/nvenc/nvenc_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ namespace nvenc {
full_resolution, ///< Better overall statistics, slower and uses more extra vram
};

enum class nvenc_split_frame_encoding {
disabled, ///< Disable
driver_decides, ///< Let driver decide
force_enabled, ///< Force-enable
};

/**
* @brief NVENC encoder configuration.
*/
Expand Down Expand Up @@ -48,6 +54,9 @@ namespace nvenc {

// Add filler data to encoded frames to stay at target bitrate, mainly for testing
bool insert_filler_data = false;

// Enable split-frame encoding if the gpu has multiple NVENC hardware clusters
nvenc_split_frame_encoding split_frame_encoding = nvenc_split_frame_encoding::driver_decides;
};

} // namespace nvenc
1 change: 1 addition & 0 deletions src_assets/common/assets/web/config.html
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ <h1 class="my-4">{{ $t('config.configuration') }}</h1>
"nvenc_spatial_aq": "disabled",
"nvenc_vbv_increase": 0,
"nvenc_realtime_hags": "enabled",
"nvenc_split_encode": "driver_decides",
"nvenc_latency_over_power": "enabled",
"nvenc_opengl_vulkan_on_dxgi": "enabled",
"nvenc_h264_cavlc": "disabled",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,17 @@ const config = ref(props.config)
</div>
</div>

<!-- Split frame encoding -->
<div class="mb-3" v-if="platform === 'windows'">
<label for="nvenc_split_encode" class="form-label">{{ $t('config.nvenc_split_encode') }}</label>
<select id="nvenc_split_encode" class="form-select" v-model="config.nvenc_split_encode">
<option value="disabled">{{ $t('_common.disabled') }}</option>
<option value="driver_decides">{{ $t('config.nvenc_split_encode_driver_decides_def') }}</option>
<option value="enabled">{{ $t('_common.enabled') }}</option>
</select>
<div class="form-text">{{ $t('config.nvenc_split_encode_desc') }}</div>
</div>

<!-- Prefer lower encoding latency over power savings -->
<div class="mb-3" v-if="platform === 'windows'">
<label for="nvenc_latency_over_power" class="form-label">{{ $t('config.nvenc_latency_over_power') }}</label>
Expand Down
3 changes: 3 additions & 0 deletions src_assets/common/assets/web/public/assets/locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,9 @@
"nvenc_spatial_aq_desc": "Assign higher QP values to flat regions of the video. Recommended to enable when streaming at lower bitrates.",
"nvenc_spatial_aq_disabled": "Disabled (faster, default)",
"nvenc_spatial_aq_enabled": "Enabled (slower)",
"nvenc_split_encode": "Split frame encoding",
"nvenc_split_encode_desc": "Split the encoding of each video frame over multiple NVENC hardware units. Significantly reduces encoding latency with a marginal compression efficiency penalty. This option is ignored if your GPU has a singular NVENC unit.",
"nvenc_split_encode_driver_decides_def": "Driver decides (default)",
"nvenc_twopass": "Two-pass mode",
"nvenc_twopass_desc": "Adds preliminary encoding pass. This allows to detect more motion vectors, better distribute bitrate across the frame and more strictly adhere to bitrate limits. Disabling it is not recommended since this can lead to occasional bitrate overshoot and subsequent packet loss.",
"nvenc_twopass_disabled": "Disabled (fastest, not recommended)",
Expand Down

0 comments on commit 2ddf1b8

Please sign in to comment.