diff --git a/.gitmodules b/.gitmodules index 41352019857..61313fd2963 100644 --- a/.gitmodules +++ b/.gitmodules @@ -37,6 +37,10 @@ path = third-party/plasma-wayland-protocols url = https://github.com/KDE/plasma-wayland-protocols.git branch = master +[submodule "third-party/pyrowave"] + path = third-party/pyrowave + url = https://github.com/Themaister/pyrowave.git + branch = master [submodule "third-party/Simple-Web-Server"] path = third-party/Simple-Web-Server url = https://github.com/LizardByte-infrastructure/Simple-Web-Server.git diff --git a/cmake/compile_definitions/common.cmake b/cmake/compile_definitions/common.cmake index e3292b9a7ff..5e17789cc1a 100644 --- a/cmake/compile_definitions/common.cmake +++ b/cmake/compile_definitions/common.cmake @@ -106,6 +106,7 @@ if(WIN32) # add_nvenc_sdk_implementation: args = `target_name`, `sdk_version`, `sdk_include_dir` function(add_nvenc_sdk_implementation target_name sdk_version sdk_include_dir) add_library(${target_name} OBJECT ${NVENC_IMPLEMENTATION_SOURCES}) + target_link_libraries(${target_name} PRIVATE sunshine_pyrowave) target_include_directories(${target_name} BEFORE PRIVATE "${sdk_include_dir}") target_compile_definitions(${target_name} PRIVATE NVENC_FACTORY_SUFFIX=${sdk_version} diff --git a/cmake/dependencies/common.cmake b/cmake/dependencies/common.cmake index 9c050969f49..5d833355f18 100644 --- a/cmake/dependencies/common.cmake +++ b/cmake/dependencies/common.cmake @@ -98,6 +98,7 @@ include_directories(SYSTEM ${MINIUPNP_INCLUDE_DIRS}) # ffmpeg pre-compiled binaries include("${CMAKE_MODULE_PATH}/dependencies/ffmpeg.cmake") +include("${CMAKE_MODULE_PATH}/dependencies/pyrowave.cmake") # Opus if(TARGET PkgConfig::SUNSHINE_BUNDLED_OPUS) diff --git a/cmake/dependencies/pyrowave.cmake b/cmake/dependencies/pyrowave.cmake new file mode 100644 index 00000000000..9e8744d030c --- /dev/null +++ b/cmake/dependencies/pyrowave.cmake @@ -0,0 +1,60 @@ +# Build the pinned PyroWave C API into Sunshine. +include_guard(GLOBAL) + +# Build the codec and C API without exposing upstream options to Sunshine. +function(sunshine_add_pyrowave) + set(pyrowave_source_dir "${CMAKE_SOURCE_DIR}/third-party/pyrowave") + # Defer configuring Granite until the options below are set, including local source overrides. + CPMAddPackage(NAME pyrowave_granite DOWNLOAD_ONLY YES) + + # Scope upstream options to the dependency build and use its precompiled shaders. + # cmake-lint: disable=C0103 + set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) + set(GRANITE_SHARED OFF) + set(GRANITE_TOOLS OFF) + set(GRANITE_RENDERER OFF) + set(GRANITE_PLATFORM "null") + set(GRANITE_INSTALL_TARGETS OFF) + set(GRANITE_HIDDEN ON) + set(GRANITE_POSITION_INDEPENDENT ON) + set(GRANITE_SHIPPING ON) + set(GRANITE_FFMPEG OFF) + set(GRANITE_FFMPEG_VULKAN OFF) + set(GRANITE_SHADER_COMPILER_OPTIMIZE OFF) + set(GRANITE_VULKAN_SHADER_MANAGER_RUNTIME_COMPILER OFF) + set(GRANITE_VULKAN_SPIRV_CROSS OFF) + set(GRANITE_VULKAN_FOSSILIZE OFF) + set(GRANITE_VULKAN_SYSTEM_HANDLES OFF) + set(GRANITE_VULKAN_DXGI_INTEROP OFF) + set(GRANITE_RENDERDOC_CAPTURE OFF) + add_subdirectory("${pyrowave_granite_SOURCE_DIR}" "${pyrowave_granite_BINARY_DIR}" EXCLUDE_FROM_ALL) + + # Keep Volk's function pointers distinct from the Vulkan loader used by FFmpeg. + target_compile_definitions(granite-volk-headers INTERFACE VOLK_NAMESPACE) + set_source_files_properties("${pyrowave_granite_SOURCE_DIR}/third_party/volk/volk.c" + TARGET_DIRECTORY granite-volk PROPERTIES LANGUAGE CXX) + + set(PYROWAVE_DEVEL OFF) + set(PYROWAVE_UTILS OFF) + add_subdirectory("${pyrowave_source_dir}" "${CMAKE_BINARY_DIR}/third-party/pyrowave" EXCLUDE_FROM_ALL) + + # Upstream exposes the C API only for standalone builds; add its wrapper here. + add_library(sunshine_pyrowave STATIC + "${pyrowave_source_dir}/pyrowave_c.cpp" + "${pyrowave_granite_SOURCE_DIR}/video/scaler.cpp") + target_include_directories(sunshine_pyrowave PRIVATE + "${pyrowave_source_dir}/shaders" "${pyrowave_granite_SOURCE_DIR}/video") + target_include_directories(sunshine_pyrowave SYSTEM INTERFACE + "${pyrowave_source_dir}" + "${pyrowave_granite_SOURCE_DIR}/third_party/khronos/vulkan-headers/include") + target_link_libraries(sunshine_pyrowave PRIVATE pyrowave granite-vulkan granite-math Threads::Threads) + + # Clients use the vendored revision to diagnose bitstream compatibility. + execute_process(COMMAND git -C "${pyrowave_source_dir}" rev-parse --short=8 HEAD + OUTPUT_VARIABLE pyrowave_bitstream_id OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) + target_compile_definitions(sunshine_pyrowave INTERFACE + SUNSHINE_PYROWAVE_BITSTREAM_ID="${pyrowave_bitstream_id}") +endfunction() + +sunshine_add_pyrowave() +list(APPEND SUNSHINE_EXTERNAL_LIBRARIES sunshine_pyrowave) diff --git a/docs/configuration.md b/docs/configuration.md index 2d81d8c0dd0..5c6bb1c6bec 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -2096,6 +2096,7 @@ consent prompt for directory ACLs, so the Web UI shows setup steps for correctin
0 to disable forward error correction.
+ PyroWave protects only critical data when the client supports record framing.
@warning{Higher values can correct for more network packet loss,
but at the cost of increasing bandwidth usage.}
| Description | ++ Allows compatible clients to request PyroWave 8-bit or 10-bit 4:2:0 or 4:4:4 video streams. + Support is advertised based on encoder capabilities. HDR requires a supported capture backend + and HDR enabled on the host display and client. + Transport framing is negotiated with the client. + @warning{PyroWave consumes a significant amount of bandwidth. Not recommended unless on LAN and utilizing a hardwired connection.} + | +|
| Default | +@code{} + enabled + @endcode | +|
| Example | +@code{} + pyrowave = disabled + @endcode | +|