|
|
cmake/compile_definitions/common.cmake
|
+4
−7
|
@@ -110,10 +110,12 @@ add_nvenc_sdk_implementation(nvenc_sdk_1100 1100 "${NV_CODEC_HEADERS_11_INCLUDE_DIR}") add_nvenc_sdk_implementation(nvenc_sdk_1200 1200 "${NV_CODEC_HEADERS_12_INCLUDE_DIR}") add_nvenc_sdk_implementation(nvenc_sdk_1300 1300 "${NV_CODEC_HEADERS_13_INCLUDE_DIR}") add_nvenc_sdk_implementation(nvenc_sdk_1301 1301 "${NV_CODEC_HEADERS_13_1_INCLUDE_DIR}")
list(APPEND NVENC_SOURCES $<TARGET_OBJECTS:nvenc_sdk_1100> $<TARGET_OBJECTS:nvenc_sdk_1200> $<TARGET_OBJECTS:nvenc_sdk_1300> $<TARGET_OBJECTS:nvenc_sdk_1301> ) endif() @@ -209,13 +211,8 @@ ${Boost_INCLUDE_DIRS} # has to be the last, or we get runtime error on macOS ffmpeg encoder )
if(WIN32) include_directories(BEFORE SYSTEM "${NV_CODEC_HEADERS_13_INCLUDE_DIR}") if(NOT APPLE) include_directories(BEFORE SYSTEM "${NV_CODEC_HEADERS_13_1_INCLUDE_DIR}") else() include_directories( BEFORE SYSTEM "${CMAKE_SOURCE_DIR}/third-party/build-deps/third-party/FFmpeg/nv-codec-headers/include" ) endif()
list(APPEND SUNSHINE_EXTERNAL_LIBRARIES
|
|
|
cmake/dependencies/nv_codec_headers.cmake
|
+23
−0
|
@@ -1,3 +1,23 @@ # Keep build-deps-owned declarations out of Sunshine's generated package lock. set(SUNSHINE_CPM_PACKAGE_LOCK_ENABLED "${CPM_PACKAGE_LOCK_ENABLED}") set(CPM_PACKAGE_LOCK_ENABLED OFF)
if(NOT APPLE) set(SUNSHINE_PREPARED_NV_CODEC_HEADERS "${FFMPEG_PREPARED_BINARIES}/include/ffnvcodec/nvEncodeAPI.h")
if(DEFINED FFMPEG_PREPARED_BINARIES AND EXISTS "${SUNSHINE_PREPARED_NV_CODEC_HEADERS}") # Prepared FFmpeg bundles include the NV codec headers used to build them. set(NV_CODEC_HEADERS_13_1_INCLUDE_DIR "${FFMPEG_PREPARED_BINARIES}/include") message(STATUS "Using NV codec headers from prepared FFmpeg binaries") else() CPMGetPackage(nv_codec_headers_13_1) set(NV_CODEC_HEADERS_13_1_INCLUDE_DIR "${nv_codec_headers_13_1_SOURCE_DIR}/include") endif()
unset(SUNSHINE_PREPARED_NV_CODEC_HEADERS) endif()
if(WIN32) CPMGetPackage(nv_codec_headers_13) CPMGetPackage(nv_codec_headers_11) @@ -7,3 +27,6 @@ set(NV_CODEC_HEADERS_12_INCLUDE_DIR "${nv_codec_headers_12_SOURCE_DIR}/include") set(NV_CODEC_HEADERS_13_INCLUDE_DIR "${nv_codec_headers_13_SOURCE_DIR}/include") endif()
set(CPM_PACKAGE_LOCK_ENABLED "${SUNSHINE_CPM_PACKAGE_LOCK_ENABLED}") unset(SUNSHINE_CPM_PACKAGE_LOCK_ENABLED)
|
|
|
CMakeLists.txt
|
+5
−0
|
@@ -68,5 +68,10 @@ return() endif()
# Build-deps owns the dependency versions shared with its FFmpeg builds. # Include its lock only for full builds so manifest-only configurations do not # require the build-deps submodule. include(${CMAKE_CURRENT_SOURCE_DIR}/third-party/build-deps/package-lock.cmake)
# project constants include(${CMAKE_MODULE_PATH}/prep/constants.cmake)
|
|
|
package-lock.cmake
|
+1
−34
|
@@ -31,37 +31,4 @@ # - `set(EXAMPLE_SHA256 <sha256>)` # - `CPMDeclarePackage(...)`
set(PATCH_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/patches")
# NVENC SDK 11.0 headers # renovate: datasource=github-tags depName=FFmpeg/nv-codec-headers # versioning=regex:^n(?<major>11)\.(?<minor>0)\.(?<patch>\d+)\.(?<build>\d+)$ set(NV_CODEC_HEADERS_11_TAG n11.0.10.3) CPMDeclarePackage(nv_codec_headers_11 NAME nv_codec_headers_11 GIT_REPOSITORY https://github.com/FFmpeg/nv-codec-headers.git GIT_TAG ${NV_CODEC_HEADERS_11_TAG} DOWNLOAD_ONLY YES )
# NVENC SDK 12.0 headers # renovate: datasource=github-tags depName=FFmpeg/nv-codec-headers # versioning=regex:^n(?<major>12)\.(?<minor>0)\.(?<patch>\d+)\.(?<build>\d+)$ set(NV_CODEC_HEADERS_12_TAG n12.0.16.2) CPMDeclarePackage(nv_codec_headers_12 NAME nv_codec_headers_12 GIT_REPOSITORY https://github.com/FFmpeg/nv-codec-headers.git GIT_TAG ${NV_CODEC_HEADERS_12_TAG} DOWNLOAD_ONLY YES )
# NVENC SDK 13.0 headers # renovate: datasource=github-tags depName=FFmpeg/nv-codec-headers # versioning=regex:^n(?<major>13)\.(?<minor>0)\.(?<patch>\d+)\.(?<build>\d+)$ set(NV_CODEC_HEADERS_13_TAG n13.0.19.1) CPMDeclarePackage(nv_codec_headers_13 NAME nv_codec_headers_13 GIT_REPOSITORY https://github.com/FFmpeg/nv-codec-headers.git GIT_TAG ${NV_CODEC_HEADERS_13_TAG} DOWNLOAD_ONLY YES ) set(PATCH_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/patches")
|
|
|
packaging/linux/flatpak/modules/ffmpeg.json
|
+4
−4
|
@@ -8,8 +8,8 @@ "sources": [ { "type": "file", "url": "https://github.com/LizardByte/build-deps/releases/download/v2026.905.170812/Linux-x86_64-ffmpeg.tar.gz", "sha256": "880f0b9983ea9b55a6cceb2e5afa6388e256751f3cac2baf4ef0cf6eedc57aea", "url": "https://github.com/LizardByte/build-deps/releases/download/v2026.910.121303/Linux-x86_64-ffmpeg.tar.gz", "sha256": "496d2bbb674d01e6033e31b9dfc15cbc9dc1494e882a4505f6ab1e03f75b385c", "dest-filename": "ffmpeg.tar.gz", "only-arches": [ "x86_64" @@ -23,8 +23,8 @@ }, { "type": "file", "url": "https://github.com/LizardByte/build-deps/releases/download/v2026.905.170812/Linux-aarch64-ffmpeg.tar.gz", "sha256": "096069f2737a93ff44ba6445b700213708ab1fec01fd015e528a47845b5fde46", "url": "https://github.com/LizardByte/build-deps/releases/download/v2026.910.121303/Linux-aarch64-ffmpeg.tar.gz", "sha256": "21f99409e1aba09191f9df28688fb7f9d44f98e65378a651324c632c19823aa0", "dest-filename": "ffmpeg.tar.gz", "only-arches": [ "aarch64"
|
|
|
src/config.cpp
|
+6
−2
|
@@ -64,6 +64,10 @@
namespace nv {
std::string ffmpeg_preset_from_quality(const int quality_preset) { return std::format("p{}", quality_preset); }
/** * @brief Parse the `nvenc_twopass` configuration value. * @@ -1619,11 +1623,11 @@ bool_f(vars, "nvenc_latency_over_power", video.nv_sunshine_high_power_mode);
#if !defined(__ANDROID__) && !defined(__APPLE__) video.nv_legacy.preset = video.nv.quality_preset + 11; video.nv_legacy.preset = nv::ffmpeg_preset_from_quality(video.nv.quality_preset); 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; video.nv_legacy.aq = video.nv.adaptive_quantization; video.nv_legacy.spatial_aq = video.nv.adaptive_quantization; video.nv_legacy.vbv_percentage_increase = video.nv.vbv_percentage_increase; #endif
|
|
|
src/config.h
|
+12
−2
|
@@ -17,6 +17,16 @@ #include "nvenc/nvenc_config.h"
namespace config { namespace nv { /** * @brief Convert Sunshine's NVENC quality preset number to FFmpeg's stable symbolic name. * * @param quality_preset Validated Sunshine quality preset in the range 1 through 7. * @return FFmpeg preset name from `p1` through `p7`. */ std::string ffmpeg_preset_from_quality(int quality_preset); } // namespace nv
// Valid range for the packetsize limit constexpr int PACKETSIZE_MIN = 200; ///< Lowest accepted configured packet size in bytes. constexpr int PACKETSIZE_MAX = 65535; ///< Highest accepted configured packet size in bytes. @@ -73,9 +83,9 @@ bool nv_sunshine_high_power_mode; ///< Request NVIDIA high-power mode for Sunshine.
struct { std::string preset; ///< FFmpeg NVENC preset name shared by supported FFmpeg versions. int preset; ///< Legacy NVENC preset selection. int multipass; ///< Legacy NVENC multipass mode. int h264_coder; ///< Legacy NVENC H.264 entropy-coding mode. int spatial_aq; ///< FFmpeg NVENC spatial adaptive-quantization mode. int aq; ///< Legacy NVENC adaptive-quantization mode. int vbv_percentage_increase; ///< Legacy NVENC VBV buffer-size percentage increase. } nv_legacy; ///< Legacy NVIDIA encoder options kept for config compatibility.
|
|
|
src/nvenc/nvenc_dynamic_factory.cpp
|
+8
−0
|
@@ -78,6 +78,14 @@ const auto max_version = decode_nvenc_driver_version(packed_max_version); const auto sdk_version = select_nvenc_sdk_version(max_version); switch (sdk_version) { case nvenc_sdk_version::sdk_13_1: return std::make_shared<nvenc_dynamic_factory>( std::move(dll), sdk_version, detail::create_nvenc_d3d11_native_1301, detail::create_nvenc_d3d11_on_cuda_1301 );
case nvenc_sdk_version::sdk_13_0: return std::make_shared<nvenc_dynamic_factory>( std::move(dll),
|
|
|
src/nvenc/nvenc_dynamic_factory_versions.h
|
+16
−0
|
@@ -62,6 +62,22 @@ * @return SDK-neutral encoder instance. */ std::unique_ptr<nvenc_d3d11_interface> create_nvenc_d3d11_on_cuda_1300(ID3D11Device *device, shared_dll dll); /** * @brief Create an SDK 13.1 native Direct3D11 encoder. * * @param device Direct3D11 device used for encoding. * @param dll Shared NVENC driver module. * @return SDK-neutral encoder instance. */ std::unique_ptr<nvenc_d3d11_interface> create_nvenc_d3d11_native_1301(ID3D11Device *device, shared_dll dll); /** * @brief Create an SDK 13.1 CUDA-interoperability encoder. * * @param device Direct3D11 device used for input surfaces. * @param dll Shared NVENC driver module. * @return SDK-neutral encoder instance. */ std::unique_ptr<nvenc_d3d11_interface> create_nvenc_d3d11_on_cuda_1301(ID3D11Device *device, shared_dll dll);
} // namespace nvenc::detail #endif
|
|
|
src/nvenc/nvenc_sdk.h
|
+1
−1
|
@@ -16,7 +16,7 @@ * @brief NVENC SDK version used while generating documentation. */ // Doxygen must select the same preprocessor interface used by versioned build targets. #define NVENC_SDK_VERSION 1300 // NOSONAR(cpp:S5028) #define NVENC_SDK_VERSION 1301 // NOSONAR(cpp:S5028) #endif
#ifndef NVENC_NAMESPACE
|
|
|
src/nvenc/nvenc_version.h
|
+4
−0
|
@@ -18,6 +18,7 @@ sdk_11_0 = 1100U, ///< Video Codec SDK 11.0. sdk_12_0 = 1200U, ///< Video Codec SDK 12.0. sdk_13_0 = 1300U, ///< Video Codec SDK 13.0. sdk_13_1 = 1301U, ///< Video Codec SDK 13.1. };
/** @@ -38,6 +39,9 @@ */ constexpr nvenc_sdk_version select_nvenc_sdk_version(std::uint32_t max_version) { using enum nvenc_sdk_version; if (max_version >= std::to_underlying(sdk_13_1)) { return sdk_13_1; } if (max_version >= std::to_underlying(sdk_13_0)) { return sdk_13_0; }
|
|
|
src/video.cpp
|
+3
−3
|
@@ -786,7 +786,7 @@ {"tune"s, NV_ENC_TUNING_INFO_ULTRA_LOW_LATENCY}, {"rc"s, NV_ENC_PARAMS_RC_CBR}, {"multipass"s, &config::video.nv_legacy.multipass}, {"aq"s, &config::video.nv_legacy.aq}, {"spatial-aq"s, &config::video.nv_legacy.spatial_aq}, }, {}, // SDR-specific options {}, // HDR-specific options @@ -807,7 +807,7 @@ {"tune"s, NV_ENC_TUNING_INFO_ULTRA_LOW_LATENCY}, {"rc"s, NV_ENC_PARAMS_RC_CBR}, {"multipass"s, &config::video.nv_legacy.multipass}, {"aq"s, &config::video.nv_legacy.aq}, {"spatial-aq"s, &config::video.nv_legacy.spatial_aq}, }, { // SDR-specific options @@ -834,7 +834,7 @@ {"rc"s, NV_ENC_PARAMS_RC_CBR}, {"coder"s, &config::video.nv_legacy.h264_coder}, {"multipass"s, &config::video.nv_legacy.multipass}, {"spatial-aq"s, &config::video.nv_legacy.spatial_aq}, {"aq"s, &config::video.nv_legacy.aq}, }, { // SDR-specific options
|
|
|
tests/unit/test_config.cpp
|
+29
−0
|
@@ -15,6 +15,35 @@ #include <src/config.h> #include <src/file_handler.h>
using namespace std::literals;
using NvencPresetNameParam = std::pair<int, std::string_view>;
/** * @brief Parameterized coverage for FFmpeg's symbolic NVENC preset names. */ struct NvencPresetNameTest: testing::TestWithParam<NvencPresetNameParam> {};
TEST_P(NvencPresetNameTest, UsesStableSymbolicName) { const auto &[quality_preset, expected] = GetParam();
EXPECT_EQ(expected, config::nv::ffmpeg_preset_from_quality(quality_preset)); }
INSTANTIATE_TEST_SUITE_P( NvencQualityPresets, NvencPresetNameTest, testing::Values( NvencPresetNameParam {1, "p1"sv}, NvencPresetNameParam {2, "p2"sv}, NvencPresetNameParam {3, "p3"sv}, NvencPresetNameParam {4, "p4"sv}, NvencPresetNameParam {5, "p5"sv}, NvencPresetNameParam {6, "p6"sv}, NvencPresetNameParam {7, "p7"sv} ) );
namespace {
/**
|
|
|
tests/unit/test_nvenc_dynamic_factory.cpp
|
+4
−3
|
@@ -145,6 +145,7 @@ std::pair {11U << 4U, sdk_11_0}, std::pair {12U << 4U, sdk_12_0}, std::pair {13U << 4U, sdk_13_0}, std::pair {14U << 4U, sdk_13_0}, std::pair {(13U << 4U) | 1U, sdk_13_1}, std::pair {14U << 4U, sdk_13_1}, }; reported_status = 0U; @@ -163,7 +164,7 @@ const auto dll = make_fake_dll(); nvenc::nvenc_dynamic_factory factory { dll, nvenc::nvenc_sdk_version::sdk_13_1, nvenc::nvenc_sdk_version::sdk_13_0, [&created_native, &dll](ID3D11Device *, nvenc::shared_dll callback_dll) { created_native = true; EXPECT_EQ(callback_dll, dll); @@ -176,7 +177,7 @@ }, };
EXPECT_EQ(factory.sdk_version(), nvenc::nvenc_sdk_version::sdk_13_1); EXPECT_EQ(factory.sdk_version(), nvenc::nvenc_sdk_version::sdk_13_0); EXPECT_TRUE(factory.create_nvenc_d3d11_native(nullptr)); EXPECT_TRUE(factory.create_nvenc_d3d11_on_cuda(nullptr)); EXPECT_TRUE(created_native);
|
|
|
tests/unit/test_nvenc_version.cpp
|
+2
−2
|
@@ -40,8 +40,8 @@ nvenc_version_test_case {1201U, sdk_12_0}, nvenc_version_test_case {1299U, sdk_12_0}, nvenc_version_test_case {1300U, sdk_13_0}, nvenc_version_test_case {1301U, sdk_13_0}, nvenc_version_test_case {1400U, sdk_13_0}, nvenc_version_test_case {1301U, sdk_13_1}, nvenc_version_test_case {1400U, sdk_13_1}, };
for (const auto &[max_version, expected] : test_cases) {
|
|
|
tests/unit/test_video.cpp
|
+28
−0
|
@@ -7,6 +7,7 @@
// standard includes #include <algorithm> #include <array> #include <limits> #include <optional> #include <tuple> @@ -64,6 +65,33 @@ return std::string(info.param->name); } );
#if !defined(_WIN32) && !defined(__APPLE__) TEST(NvencAvcodecOptionsTest, UsesVersionStablePresetAndSpatialAqNames) { const std::array codecs { &video::nvenc.av1, &video::nvenc.hevc, &video::nvenc.h264, };
for (const auto *codec : codecs) { const auto preset = std::ranges::find(codec->common_options, "preset"sv, &video::encoder_t::option_t::name); ASSERT_NE(codec->common_options.end(), preset); ASSERT_TRUE(std::holds_alternative<std::string *>(preset->value)); EXPECT_EQ(&config::video.nv_legacy.preset, std::get<std::string *>(preset->value));
const auto spatial_aq = std::ranges::find(codec->common_options, "spatial-aq"sv, &video::encoder_t::option_t::name); ASSERT_NE(codec->common_options.end(), spatial_aq); ASSERT_TRUE(std::holds_alternative<int *>(spatial_aq->value)); EXPECT_EQ(&config::video.nv_legacy.spatial_aq, std::get<int *>(spatial_aq->value));
EXPECT_EQ( codec->common_options.end(), std::ranges::find(codec->common_options, "aq"sv, &video::encoder_t::option_t::name) ); } } #endif
TEST_P(EncoderTest, ValidateEncoder) { // todo:: test something besides fixture setup
|
|
|
third-party/build-deps
|
+0
−0
|
|
|