diff --git a/.github/workflows/ci-bundle.yml b/.github/workflows/ci-bundle.yml
index d9edfd7c791..3a7df39e6f0 100644
--- a/.github/workflows/ci-bundle.yml
+++ b/.github/workflows/ci-bundle.yml
@@ -23,6 +23,10 @@ jobs:
- name: Install npm dependencies
run: npm install --ignore-scripts
+ - name: Debug install
+ if: always()
+ run: cat "${HOME}/.npm/_logs/*-debug-0.log" || true
+
- name: Build
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
diff --git a/.github/workflows/ci-windows.yml b/.github/workflows/ci-windows.yml
index 2164df0c41f..be8392cca48 100644
--- a/.github/workflows/ci-windows.yml
+++ b/.github/workflows/ci-windows.yml
@@ -29,6 +29,11 @@ jobs:
arch: x86_64
msystem: ucrt64
toolchain: ucrt-x86_64
+ - name: Windows-ARM64
+ os: windows-11-arm
+ arch: aarch64
+ msystem: clangarm64
+ toolchain: clang-aarch64
steps:
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
@@ -62,17 +67,22 @@ jobs:
"mingw-w64-${TOOLCHAIN}-curl-winssl"
"mingw-w64-${TOOLCHAIN}-gcc"
"mingw-w64-${TOOLCHAIN}-graphviz"
- "mingw-w64-${TOOLCHAIN}-MinHook"
"mingw-w64-${TOOLCHAIN}-miniupnpc"
"mingw-w64-${TOOLCHAIN}-nlohmann-json"
"mingw-w64-${TOOLCHAIN}-nodejs"
- "mingw-w64-${TOOLCHAIN}-nsis"
"mingw-w64-${TOOLCHAIN}-onevpl"
"mingw-w64-${TOOLCHAIN}-openssl"
"mingw-w64-${TOOLCHAIN}-opus"
"mingw-w64-${TOOLCHAIN}-toolchain"
)
+ if [[ "${MSYSTEM}" == "ucrt64" ]]; then
+ dependencies+=(
+ "mingw-w64-${TOOLCHAIN}-MinHook"
+ "mingw-w64-${TOOLCHAIN}-nsis"
+ )
+ fi
+
# do not modify below this line
ignore_packages=()
@@ -129,6 +139,11 @@ jobs:
# Clean up
Remove-Item -Path doxygen-setup.exe
+ - name: Setup dotnet # needed for wix
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: '9.x'
+
- name: Setup python
id: setup-python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
@@ -169,19 +184,33 @@ jobs:
echo "::remove-matcher owner=gcc::"
- name: Package Windows
+ env:
+ # if MSYSTEM is used, it interferes with environment and cpack cannot be found
+ MATRIX_MSYSTEM: ${{ matrix.msystem }}
shell: msys2 {0}
run: |
mkdir -p artifacts
cd build
- # package
- cpack -G NSIS
- cpack -G ZIP
+ # nsis installer
+ if [[ "${MATRIX_MSYSTEM}" == "ucrt64" ]]; then
+ cpack -G NSIS
+ mv ./cpack_artifacts/Sunshine.exe ../artifacts/Sunshine-${{ matrix.name }}-installer.exe
+ fi
+
+ # wix installer
+ cpack -G WIX
+ mv ./cpack_artifacts/Sunshine.msi ../artifacts/Sunshine-${{ matrix.name }}-installer.msi
- # move
- mv ./cpack_artifacts/Sunshine.exe ../artifacts/Sunshine-${{ matrix.name }}-installer.exe
+ # portable version
+ cpack -G ZIP
mv ./cpack_artifacts/Sunshine.zip ../artifacts/Sunshine-${{ matrix.name }}-portable.zip
+ - name: Debug wix
+ if: always()
+ shell: msys2 {0}
+ run: cat ./build/cpack_artifacts/_CPack_Packages/win64/WIX/wix.log || true
+
- name: Run tests
id: test
shell: msys2 {0}
diff --git a/cmake/compile_definitions/windows.cmake b/cmake/compile_definitions/windows.cmake
index c1a2c95fc45..57af5e2a435 100644
--- a/cmake/compile_definitions/windows.cmake
+++ b/cmake/compile_definitions/windows.cmake
@@ -9,6 +9,13 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
# gcc complains about misleading indentation in some mingw includes
list(APPEND SUNSHINE_COMPILE_OPTIONS -Wno-misleading-indentation)
+# Disable warnings for Windows ARM64
+if(CMAKE_SYSTEM_PROCESSOR MATCHES "ARM64")
+ list(APPEND SUNSHINE_COMPILE_OPTIONS -Wno-dll-attribute-on-redeclaration) # Boost
+ list(APPEND SUNSHINE_COMPILE_OPTIONS -Wno-unknown-warning-option) # ViGEmClient
+ list(APPEND SUNSHINE_COMPILE_OPTIONS -Wno-unused-variable) # Boost
+endif()
+
# see gcc bug 98723
add_definitions(-DUSE_BOOST_REGEX)
diff --git a/cmake/dependencies/windows.cmake b/cmake/dependencies/windows.cmake
index 3faad7dfd41..a9e5630d971 100644
--- a/cmake/dependencies/windows.cmake
+++ b/cmake/dependencies/windows.cmake
@@ -1,9 +1,35 @@
# windows specific dependencies
-# Make sure MinHook is installed
-find_library(MINHOOK_LIBRARY libMinHook.a REQUIRED)
-find_path(MINHOOK_INCLUDE_DIR MinHook.h PATH_SUFFIXES include REQUIRED)
+# MinHook setup - use installed minhook for AMD64, otherwise download minhook-detours for ARM64
+if(CMAKE_SYSTEM_PROCESSOR MATCHES "AMD64")
+ # Make sure MinHook is installed for x86/x64
+ find_library(MINHOOK_LIBRARY libMinHook.a REQUIRED)
+ find_path(MINHOOK_INCLUDE_DIR MinHook.h PATH_SUFFIXES include REQUIRED)
-add_library(minhook::minhook STATIC IMPORTED)
-set_property(TARGET minhook::minhook PROPERTY IMPORTED_LOCATION ${MINHOOK_LIBRARY})
-target_include_directories(minhook::minhook INTERFACE ${MINHOOK_INCLUDE_DIR})
+ add_library(minhook::minhook STATIC IMPORTED)
+ set_property(TARGET minhook::minhook PROPERTY IMPORTED_LOCATION ${MINHOOK_LIBRARY})
+ target_include_directories(minhook::minhook INTERFACE ${MINHOOK_INCLUDE_DIR})
+else()
+ # Download pre-built minhook-detours for ARM64
+ message(STATUS "Downloading minhook-detours pre-built binaries for ARM64")
+ include(FetchContent)
+
+ FetchContent_Declare(
+ minhook-detours
+ URL https://github.com/m417z/minhook-detours/releases/download/v1.0.6/minhook-detours-1.0.6.zip
+ URL_HASH SHA256=E719959D824511E27395A82AEDA994CAAD53A67EE5894BA5FC2F4BF1FA41E38E
+ )
+ FetchContent_MakeAvailable(minhook-detours)
+
+ # Create imported library for the pre-built DLL
+ set(_MINHOOK_DLL
+ "${minhook-detours_SOURCE_DIR}/Release/minhook-detours.ARM64.Release.dll"
+ CACHE INTERNAL "Path to minhook-detours DLL")
+ add_library(minhook::minhook SHARED IMPORTED GLOBAL)
+ set_property(TARGET minhook::minhook PROPERTY IMPORTED_LOCATION "${_MINHOOK_DLL}")
+ set_property(TARGET minhook::minhook PROPERTY IMPORTED_IMPLIB
+ "${minhook-detours_SOURCE_DIR}/Release/minhook-detours.ARM64.Release.lib")
+ set_target_properties(minhook::minhook PROPERTIES
+ INTERFACE_INCLUDE_DIRECTORIES "${minhook-detours_SOURCE_DIR}/src"
+ )
+endif()
diff --git a/cmake/packaging/windows.cmake b/cmake/packaging/windows.cmake
index 069fd85154b..0dbed2b6e7b 100644
--- a/cmake/packaging/windows.cmake
+++ b/cmake/packaging/windows.cmake
@@ -4,6 +4,11 @@ install(TARGETS sunshine RUNTIME DESTINATION "." COMPONENT application)
# Hardening: include zlib1.dll (loaded via LoadLibrary() in openssl's libcrypto.a)
install(FILES "${ZLIB}" DESTINATION "." COMPONENT application)
+# ARM64: include minhook-detours DLL (shared library for ARM64)
+if(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "AMD64" AND DEFINED _MINHOOK_DLL)
+ install(FILES "${_MINHOOK_DLL}" DESTINATION "." COMPONENT application)
+endif()
+
# ViGEmBus installer
set(VIGEMBUS_INSTALLER "${CMAKE_BINARY_DIR}/scripts/vigembus_installer.exe")
set(VIGEMBUS_DOWNLOAD_URL_1 "https://github.com/nefarius/ViGEmBus/releases/download")
diff --git a/cmake/packaging/windows_wix.cmake b/cmake/packaging/windows_wix.cmake
index bc956182f06..5f1393bd8a7 100644
--- a/cmake/packaging/windows_wix.cmake
+++ b/cmake/packaging/windows_wix.cmake
@@ -1,4 +1,92 @@
# WIX Packaging
# see options at: https://cmake.org/cmake/help/latest/cpack_gen/wix.html
-# TODO: Replace nsis with wix
+set(CPACK_WIX_VERSION 4)
+set(WIX_VERSION 4.0.4)
+set(WIX_UI_VERSION 4.0.4) # extension versioning is independent of the WiX version
+set(WIX_BUILD_PARENT_DIRECTORY "${CMAKE_BINARY_DIR}/wix_packaging")
+set(WIX_BUILD_DIRECTORY "${CPACK_PACKAGE_DIRECTORY}/_CPack_Packages/win64/WIX")
+
+# Download and install WiX tools locally in the build directory
+set(WIX_TOOL_PATH "${CMAKE_BINARY_DIR}/.wix")
+file(MAKE_DIRECTORY ${WIX_TOOL_PATH})
+
+# find dotnet
+find_program(DOTNET_EXECUTABLE dotnet REQUIRED HINTS "C:/Program Files/dotnet")
+
+# Install WiX locally using dotnet
+execute_process(
+ COMMAND ${DOTNET_EXECUTABLE} tool install --tool-path ${WIX_TOOL_PATH} wix --version ${WIX_VERSION}
+ ERROR_VARIABLE WIX_INSTALL_OUTPUT
+ RESULT_VARIABLE WIX_INSTALL_RESULT
+)
+
+if(NOT WIX_INSTALL_RESULT EQUAL 0)
+ message(FATAL_ERROR "Failed to install WiX tools locally.
+ WiX packaging may not work correctly, error: ${WIX_INSTALL_OUTPUT}")
+endif()
+
+# Install WiX UI Extension
+execute_process(
+ COMMAND "${WIX_TOOL_PATH}/wix" extension add WixToolset.UI.wixext/${WIX_UI_VERSION}
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+ ERROR_VARIABLE WIX_UI_INSTALL_OUTPUT
+ RESULT_VARIABLE WIX_UI_INSTALL_RESULT
+)
+
+if(NOT WIX_UI_INSTALL_RESULT EQUAL 0)
+ message(FATAL_ERROR "Failed to install WiX UI extension, error: ${WIX_UI_INSTALL_OUTPUT}")
+endif()
+
+# Install WiX Util Extension
+execute_process(
+ COMMAND "${WIX_TOOL_PATH}/wix" extension add WixToolset.Util.wixext/${WIX_UI_VERSION}
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+ ERROR_VARIABLE WIX_UTIL_INSTALL_OUTPUT
+ RESULT_VARIABLE WIX_UTIL_INSTALL_RESULT
+)
+
+if(NOT WIX_UTIL_INSTALL_RESULT EQUAL 0)
+ message(FATAL_ERROR "Failed to install WiX Util extension, error: ${WIX_UTIL_INSTALL_OUTPUT}")
+endif()
+
+# Set WiX-specific variables
+set(CPACK_WIX_ROOT "${WIX_TOOL_PATH}")
+set(CPACK_WIX_UPGRADE_GUID "512A3D1B-BE16-401B-A0D1-59BBA3942FB8")
+
+# Installer metadata
+set(CPACK_WIX_HELP_LINK "https://docs.lizardbyte.dev/projects/sunshine/latest/md_docs_2getting__started.html")
+set(CPACK_WIX_PRODUCT_ICON "${SUNSHINE_ICON_PATH}")
+set(CPACK_WIX_PRODUCT_URL "${CMAKE_PROJECT_HOMEPAGE_URL}")
+set(CPACK_WIX_PROGRAM_MENU_FOLDER "LizardByte")
+
+set(CPACK_WIX_EXTENSIONS
+ "WixToolset.UI.wixext"
+ "WixToolset.Util.wixext"
+)
+
+message(STATUS "cpack package directory: ${CPACK_PACKAGE_DIRECTORY}")
+
+# copy custom wxs files to the build directory
+file(COPY "${CMAKE_CURRENT_LIST_DIR}/wix_resources/"
+ DESTINATION "${WIX_BUILD_PARENT_DIRECTORY}/")
+
+set(CPACK_WIX_EXTRA_SOURCES
+ "${WIX_BUILD_PARENT_DIRECTORY}/sunshine-installer.wxs"
+)
+set(CPACK_WIX_PATCH_FILE
+ "${WIX_BUILD_PARENT_DIRECTORY}/patch.xml"
+)
+
+# Copy root LICENSE and rename to have .txt extension
+file(COPY "${CMAKE_SOURCE_DIR}/LICENSE"
+ DESTINATION "${CMAKE_BINARY_DIR}")
+file(RENAME "${CMAKE_BINARY_DIR}/LICENSE" "${CMAKE_BINARY_DIR}/LICENSE.txt")
+set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_BINARY_DIR}/LICENSE.txt") # cpack will covert this to an RTF if it is txt
+
+# https://cmake.org/cmake/help/latest/cpack_gen/wix.html#variable:CPACK_WIX_ARCHITECTURE
+if(CMAKE_SYSTEM_PROCESSOR MATCHES "ARM64")
+ set(CPACK_WIX_ARCHITECTURE "arm64")
+else()
+ set(CPACK_WIX_ARCHITECTURE "x64")
+endif()
diff --git a/cmake/packaging/wix_resources/patch.xml b/cmake/packaging/wix_resources/patch.xml
new file mode 100644
index 00000000000..e85c3581dee
--- /dev/null
+++ b/cmake/packaging/wix_resources/patch.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/cmake/packaging/wix_resources/sunshine-installer.wxs b/cmake/packaging/wix_resources/sunshine-installer.wxs
new file mode 100644
index 00000000000..aaec41a9ac2
--- /dev/null
+++ b/cmake/packaging/wix_resources/sunshine-installer.wxs
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cmake/prep/build_version.cmake b/cmake/prep/build_version.cmake
index 7c10dde2414..91209922066 100644
--- a/cmake/prep/build_version.cmake
+++ b/cmake/prep/build_version.cmake
@@ -56,11 +56,11 @@ else()
if(NOT GIT_DESCRIBE_ERROR_CODE)
MESSAGE("Sunshine Branch: ${GIT_DESCRIBE_BRANCH}")
if(NOT GIT_DESCRIBE_BRANCH STREQUAL "master")
- set(PROJECT_VERSION ${PROJECT_VERSION}.${GIT_DESCRIBE_VERSION})
+ set(PROJECT_VERSION ${PROJECT_VERSION}-${GIT_DESCRIBE_VERSION})
MESSAGE("Sunshine Version: ${GIT_DESCRIBE_VERSION}")
endif()
if(GIT_IS_DIRTY)
- set(PROJECT_VERSION ${PROJECT_VERSION}.dirty)
+ set(PROJECT_VERSION ${PROJECT_VERSION}-dirty)
MESSAGE("Git tree is dirty!")
endif()
else()
diff --git a/cmake/prep/options.cmake b/cmake/prep/options.cmake
index 6b732a957e6..f8973ea4899 100644
--- a/cmake/prep/options.cmake
+++ b/cmake/prep/options.cmake
@@ -9,6 +9,7 @@ set(SUNSHINE_PUBLISHER_ISSUE_URL "https://app.lizardbyte.dev/support"
option(BUILD_DOCS "Build documentation" ON)
option(BUILD_TESTS "Build tests" ON)
+
option(NPM_OFFLINE "Use offline npm packages. You must ensure packages are in your npm cache." OFF)
option(BUILD_WERROR "Enable -Werror flag." OFF)
diff --git a/docs/building.md b/docs/building.md
index 67b2066cd49..05870ab51b3 100644
--- a/docs/building.md
+++ b/docs/building.md
@@ -126,33 +126,52 @@ sudo port install "${dependencies[@]}"
```
#### Windows
-First you need to install [MSYS2](https://www.msys2.org), then startup "MSYS2 UCRT64" and execute the following
-commands.
+
+@warning{Cross-compilation is not supported on Windows. You must build on the target architecture.}
+
+First, you need to install [MSYS2](https://www.msys2.org).
+
+For AMD64 startup "MSYS2 UCRT64" (or for ARM64 startup "MSYS2 CLANGARM64") then execute the following commands.
##### Update all packages
```bash
pacman -Syu
```
+##### Set toolchain variable
+For UCRT64:
+```bash
+export TOOLCHAIN="ucrt-x86_64"
+```
+
+For CLANGARM64:
+```bash
+export TOOLCHAIN="clang-aarch64"
+```
+
##### Install dependencies
```bash
dependencies=(
"git"
- "mingw-w64-ucrt-x86_64-boost" # Optional
- "mingw-w64-ucrt-x86_64-cmake"
- "mingw-w64-ucrt-x86_64-cppwinrt"
- "mingw-w64-ucrt-x86_64-curl-winssl"
- "mingw-w64-ucrt-x86_64-doxygen" # Optional, for docs... better to install official Doxygen
- "mingw-w64-ucrt-x86_64-graphviz" # Optional, for docs
- "mingw-w64-ucrt-x86_64-MinHook"
- "mingw-w64-ucrt-x86_64-miniupnpc"
- "mingw-w64-ucrt-x86_64-nodejs"
- "mingw-w64-ucrt-x86_64-nsis"
- "mingw-w64-ucrt-x86_64-onevpl"
- "mingw-w64-ucrt-x86_64-openssl"
- "mingw-w64-ucrt-x86_64-opus"
- "mingw-w64-ucrt-x86_64-toolchain"
+ "mingw-w64-${TOOLCHAIN}-boost" # Optional
+ "mingw-w64-${TOOLCHAIN}-cmake"
+ "mingw-w64-${TOOLCHAIN}-cppwinrt"
+ "mingw-w64-${TOOLCHAIN}-curl-winssl"
+ "mingw-w64-${TOOLCHAIN}-doxygen" # Optional, for docs
+ "mingw-w64-${TOOLCHAIN}-graphviz" # Optional, for docs
+ "mingw-w64-${TOOLCHAIN}-miniupnpc"
+ "mingw-w64-${TOOLCHAIN}-nodejs"
+ "mingw-w64-${TOOLCHAIN}-onevpl"
+ "mingw-w64-${TOOLCHAIN}-openssl"
+ "mingw-w64-${TOOLCHAIN}-opus"
+ "mingw-w64-${TOOLCHAIN}-toolchain"
)
+if [[ ${MSYSTEM} == "ucrt64" ]]; then
+ dependencies+=(
+ "mingw-w64-${TOOLCHAIN}-MinHook"
+ "mingw-w64-${TOOLCHAIN}-nsis"
+ )
+fi
pacman -S "${dependencies[@]}"
```
@@ -198,9 +217,12 @@ ninja -C build
```}
}}
@tab{Windows | @tabs{
- @tab{Installer | ```bash
+ @tab{NSIS Installer | ```bash
cpack -G NSIS --config ./build/CPackConfig.cmake
```}
+ @tab{WiX Installer | ```bash
+ cpack -G WIX --config ./build/CPackConfig.cmake
+ ```}
@tab{Portable | ```bash
cpack -G ZIP --config ./build/CPackConfig.cmake
```}
diff --git a/docs/getting_started.md b/docs/getting_started.md
index d2afb2b9354..978a0b832d5 100644
--- a/docs/getting_started.md
+++ b/docs/getting_started.md
@@ -329,10 +329,17 @@ brew uninstall sunshine
### Windows
+Sunshine now supports ARM64 on Windows; however this should be considered experimental. This version does not properly
+support GPU scheduling and any hardware acceleration.
+
#### Installer (recommended)
-1. Download and install
- [Sunshine-Windows-AMD64-installer.exe](https://github.com/LizardByte/Sunshine/releases/latest/download/Sunshine-Windows-AMD64-installer.exe)
+1. Download and install based on your architecture:
+
+ | Architecture | Installer |
+ |-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------|
+ | AMD64/x64 (Intel/AMD) | [Sunshine-Windows-AMD64-installer.exe](https://github.com/LizardByte/Sunshine/releases/latest/download/Sunshine-Windows-AMD64-installer.exe) |
+ | ARM64 | [Sunshine-Windows-ARM64-installer.exe](https://github.com/LizardByte/Sunshine/releases/latest/download/Sunshine-Windows-ARM64-installer.exe) |
> [!CAUTION]
> You should carefully select or unselect the options you want to install. Do not blindly install or
@@ -347,8 +354,13 @@ overflow menu. Different versions of Windows may provide slightly different step
> By using this package instead of the installer, performance will be reduced. This package is not
> recommended for most users. No support will be provided!
-1. Download and extract
- [Sunshine-Windows-AMD64-portable.zip](https://github.com/LizardByte/Sunshine/releases/latest/download/Sunshine-Windows-AMD64-portable.zip)
+1. Download and extract based on your architecture:
+
+ | Architecture | Installer |
+ |-----------------------|--------------------------------------------------------------------------------------------------------------------------------------------|
+ | AMD64/x64 (Intel/AMD) | [Sunshine-Windows-AMD64-portable.exe](https://github.com/LizardByte/Sunshine/releases/latest/download/Sunshine-Windows-AMD64-portable.zip) |
+ | ARM64 | [Sunshine-Windows-ARM64-portable.exe](https://github.com/LizardByte/Sunshine/releases/latest/download/Sunshine-Windows-ARM64-portable.zip) |
+
2. Open command prompt as administrator
3. Firewall rules
diff --git a/package.json b/package.json
index 065fc6d3340..56df3046fff 100644
--- a/package.json
+++ b/package.json
@@ -22,6 +22,10 @@
"@vitejs/plugin-vue": "6.0.1",
"serve": "14.2.5",
"vite": "6.3.6",
- "vite-plugin-ejs": "1.7.0"
+ "vite-plugin-ejs": "1.7.0",
+ "@rollup/wasm-node": "4.57.1"
+ },
+ "overrides": {
+ "rollup": "npm:@rollup/wasm-node@4.57.1"
}
}
diff --git a/scripts/linux_build.sh b/scripts/linux_build.sh
index 2b1d705ee7b..312c74fdec5 100755
--- a/scripts/linux_build.sh
+++ b/scripts/linux_build.sh
@@ -695,7 +695,7 @@ elif grep -q "Debian GNU/Linux 12 (bookworm)" /etc/os-release; then
cuda_version="12.9.1"
cuda_build="575.57.08"
gcc_version="13"
- nvm_node=0
+ nvm_node=1
elif grep -q "Debian GNU/Linux 13 (trixie)" /etc/os-release; then
distro="debian"
version="13"
@@ -704,7 +704,7 @@ elif grep -q "Debian GNU/Linux 13 (trixie)" /etc/os-release; then
cuda_version="12.9.1"
cuda_build="575.57.08"
gcc_version="14"
- nvm_node=0
+ nvm_node=1
elif grep -q "PLATFORM_ID=\"platform:f41\"" /etc/os-release; then
distro="fedora"
version="41"
diff --git a/src/config.cpp b/src/config.cpp
index e5d58f3eccc..c320ed6dccf 100644
--- a/src/config.cpp
+++ b/src/config.cpp
@@ -187,7 +187,7 @@ namespace config {
};
template
- std::optional quality_from_view(const std::string_view &quality_type, const std::optional(&original)) {
+ ::std::optional quality_from_view(const ::std::string_view &quality_type, const ::std::optional(&original)) {
#define _CONVERT_(x) \
if (quality_type == #x##sv) \
return (int) T::x
@@ -199,7 +199,7 @@ namespace config {
}
template
- std::optional rc_from_view(const std::string_view &rc, const std::optional(&original)) {
+ ::std::optional rc_from_view(const ::std::string_view &rc, const ::std::optional(&original)) {
#define _CONVERT_(x) \
if (rc == #x##sv) \
return (int) T::x
@@ -212,7 +212,7 @@ namespace config {
}
template
- std::optional usage_from_view(const std::string_view &usage, const std::optional(&original)) {
+ ::std::optional usage_from_view(const ::std::string_view &usage, const ::std::optional(&original)) {
#define _CONVERT_(x) \
if (usage == #x##sv) \
return (int) T::x
@@ -225,7 +225,7 @@ namespace config {
return original;
}
- int coder_from_view(const std::string_view &coder) {
+ int coder_from_view(const ::std::string_view &coder) {
if (coder == "auto"sv) {
return _auto;
}
diff --git a/src/nvenc/nvenc_d3d11_on_cuda.h b/src/nvenc/nvenc_d3d11_on_cuda.h
index 102e18097d1..80aeb9ed8f9 100644
--- a/src/nvenc/nvenc_d3d11_on_cuda.h
+++ b/src/nvenc/nvenc_d3d11_on_cuda.h
@@ -56,7 +56,6 @@ namespace nvenc {
autopop_context push_context();
- HMODULE dll = nullptr;
const ID3D11DevicePtr d3d_device;
ID3D11Texture2DPtr d3d_input_texture;
diff --git a/src/platform/windows/audio.cpp b/src/platform/windows/audio.cpp
index d7d4680edfd..b26f91a811b 100644
--- a/src/platform/windows/audio.cpp
+++ b/src/platform/windows/audio.cpp
@@ -32,14 +32,14 @@ DEFINE_PROPERTYKEY(PKEY_DeviceInterface_FriendlyName, 0x026e516e, 0xb814, 0x414b
#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64)
#define STEAM_DRIVER_SUBDIR L"x64"
-#else
- #warning No known Steam audio driver for this architecture
#endif
namespace {
constexpr auto SAMPLE_RATE = 48000;
+#ifdef STEAM_DRIVER_SUBDIR
constexpr auto STEAM_AUDIO_DRIVER_PATH = L"%CommonProgramFiles(x86)%\\Steam\\drivers\\Windows10\\" STEAM_DRIVER_SUBDIR L"\\SteamStreamingSpeakers.inf";
+#endif
constexpr auto waveformat_mask_stereo = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
diff --git a/src/platform/windows/display_vram.cpp b/src/platform/windows/display_vram.cpp
index c6b694f0a35..52a87c7817d 100644
--- a/src/platform/windows/display_vram.cpp
+++ b/src/platform/windows/display_vram.cpp
@@ -1907,6 +1907,12 @@ namespace platf::dxgi {
if (!boost::algorithm::ends_with(name, "_nvenc")) {
return false;
}
+ } else if (adapter_desc.VendorId == 0x4D4F4351 || // Qualcomm (QCOM as MOQC reversed)
+ adapter_desc.VendorId == 0x5143) { // Qualcomm alternate ID
+ // If it's not a MediaFoundation encoder, it's not compatible with a Qualcomm GPU
+ if (!boost::algorithm::ends_with(name, "_mf")) {
+ return false;
+ }
} else {
BOOST_LOG(warning) << "Unknown GPU vendor ID: " << util::hex(adapter_desc.VendorId).to_string_view();
}
diff --git a/src/platform/windows/input.cpp b/src/platform/windows/input.cpp
index 85273609ec5..533e3790013 100644
--- a/src/platform/windows/input.cpp
+++ b/src/platform/windows/input.cpp
@@ -10,6 +10,7 @@
// standard includes
#include
#include
+#include
// lib includes
#include
@@ -1134,9 +1135,9 @@ namespace platf {
void unicode(input_t &input, char *utf8, int size) {
// We can do no worse than one UTF-16 character per byte of UTF-8
- WCHAR wide[size];
+ std::vector wide(size);
- int chars = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8, size, wide, size);
+ int chars = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8, size, wide.data(), size);
if (chars <= 0) {
return;
}
diff --git a/src/platform/windows/misc.cpp b/src/platform/windows/misc.cpp
index 5a4ea26e709..4736a4c731c 100644
--- a/src/platform/windows/misc.cpp
+++ b/src/platform/windows/misc.cpp
@@ -9,6 +9,7 @@
#include
#include
#include
+#include
// lib includes
#include
@@ -1383,7 +1384,7 @@ namespace platf {
auto const max_bufs_per_msg = send_info.payload_buffers.size() + (send_info.headers ? 1 : 0);
- WSABUF bufs[(send_info.headers ? send_info.block_count : 1) * max_bufs_per_msg];
+ std::vector bufs((send_info.headers ? send_info.block_count : 1) * max_bufs_per_msg);
DWORD bufcount = 0;
if (send_info.headers) {
// Interleave buffers for headers and payloads
@@ -1409,7 +1410,7 @@ namespace platf {
}
}
- msg.lpBuffers = bufs;
+ msg.lpBuffers = bufs.data();
msg.dwBufferCount = bufcount;
msg.dwFlags = 0;
diff --git a/src/platform/windows/windows.rc b/src/platform/windows/windows.rc
index 8f1c2bf767a..417fcf0d047 100644
--- a/src/platform/windows/windows.rc
+++ b/src/platform/windows/windows.rc
@@ -41,4 +41,4 @@ BEGIN
END
END
-SuperDuperAmazing ICON DISCARDABLE PROJECT_ICON_PATH
+SuperDuperAmazing ICON DISCARDABLE TOSTRING(PROJECT_ICON_PATH)
diff --git a/src/video.cpp b/src/video.cpp
index 0290fd95002..7487e1278e6 100644
--- a/src/video.cpp
+++ b/src/video.cpp
@@ -300,6 +300,7 @@ namespace video {
ALWAYS_REPROBE = 1 << 9, ///< This is an encoder of last resort and we want to aggressively probe for a better one
YUV444_SUPPORT = 1 << 10, ///< Encoder may support 4:4:4 chroma sampling depending on hardware
ASYNC_TEARDOWN = 1 << 11, ///< Encoder supports async teardown on a different thread
+ FIXED_GOP_SIZE = 1 << 12, ///< Use fixed small GOP size (encoder doesn't support on-demand IDR frames)
};
class avcodec_encode_session_t: public encode_session_t {
@@ -825,6 +826,63 @@ namespace video {
},
PARALLEL_ENCODING
};
+
+ encoder_t mediafoundation {
+ "mediafoundation"sv,
+ std::make_unique(
+ AV_HWDEVICE_TYPE_D3D11VA,
+ AV_HWDEVICE_TYPE_NONE,
+ AV_PIX_FMT_D3D11,
+ AV_PIX_FMT_NV12, // SDR 4:2:0 8-bit (only format Qualcomm supports)
+ AV_PIX_FMT_NONE, // No HDR - Qualcomm MF only supports 8-bit
+ AV_PIX_FMT_NONE, // No YUV444 SDR
+ AV_PIX_FMT_NONE, // No YUV444 HDR
+ dxgi_init_avcodec_hardware_input_buffer
+ ),
+ {
+ // Common options for AV1 - Qualcomm MF encoder
+ {
+ {"hw_encoding"s, 1},
+ {"rate_control"s, "cbr"s},
+ {"scenario"s, "display_remoting"s},
+ },
+ {}, // SDR-specific options
+ {}, // HDR-specific options
+ {}, // YUV444 SDR-specific options
+ {}, // YUV444 HDR-specific options
+ {}, // Fallback options
+ "av1_mf"s,
+ },
+ {
+ // Common options for HEVC - Qualcomm MF encoder
+ {
+ {"hw_encoding"s, 1},
+ {"rate_control"s, "cbr"s},
+ {"scenario"s, "display_remoting"s},
+ },
+ {}, // SDR-specific options
+ {}, // HDR-specific options
+ {}, // YUV444 SDR-specific options
+ {}, // YUV444 HDR-specific options
+ {}, // Fallback options
+ "hevc_mf"s,
+ },
+ {
+ // Common options for H.264 - Qualcomm MF encoder
+ {
+ {"hw_encoding"s, 1},
+ {"rate_control"s, "cbr"s},
+ {"scenario"s, "display_remoting"s},
+ },
+ {}, // SDR-specific options
+ {}, // HDR-specific options
+ {}, // YUV444 SDR-specific options
+ {}, // YUV444 HDR-specific options
+ {}, // Fallback options
+ "h264_mf"s,
+ },
+ PARALLEL_ENCODING | FIXED_GOP_SIZE // MF encoder doesn't support on-demand IDR frames
+ };
#endif
encoder_t software {
@@ -1031,6 +1089,7 @@ namespace video {
#ifdef _WIN32
&quicksync,
&amdvce,
+ &mediafoundation,
#endif
#if defined(__linux__) || defined(linux) || defined(__linux) || defined(__FreeBSD__)
&vaapi,
@@ -1566,11 +1625,17 @@ namespace video {
ctx->max_b_frames = 0;
// Use an infinite GOP length since I-frames are generated on demand
- ctx->gop_size = encoder.flags & LIMITED_GOP_SIZE ?
- std::numeric_limits::max() :
- std::numeric_limits::max();
-
- ctx->keyint_min = std::numeric_limits::max();
+ // Exception: encoders with FIXED_GOP_SIZE flag don't support on-demand IDR
+ if (encoder.flags & FIXED_GOP_SIZE) {
+ // Fixed GOP for encoders that don't support on-demand IDR (e.g. Media Foundation)
+ ctx->gop_size = 120; // ~2 seconds at 60 FPS - larger to reduce oversized IDR frame frequency
+ ctx->keyint_min = 120;
+ } else {
+ ctx->gop_size = encoder.flags & LIMITED_GOP_SIZE ?
+ std::numeric_limits::max() :
+ std::numeric_limits::max();
+ ctx->keyint_min = std::numeric_limits::max();
+ }
// Some client decoders have limits on the number of reference frames
if (config.numRefFrames) {
diff --git a/src/video.h b/src/video.h
index 8dbf76e27bd..eb8bb46f0dd 100644
--- a/src/video.h
+++ b/src/video.h
@@ -220,6 +220,7 @@ namespace video {
#ifdef _WIN32
extern encoder_t amdvce;
extern encoder_t quicksync;
+ extern encoder_t mediafoundation;
#endif
#if defined(__linux__) || defined(linux) || defined(__linux) || defined(__FreeBSD__)
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 9a570fd3e7f..1d9bdad4424 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -163,4 +163,15 @@ if (WIN32)
# prefer static libraries since we're linking statically
# this fixes libcurl linking errors when using non MSYS2 version of CMake
set_target_properties(${PROJECT_NAME} PROPERTIES LINK_SEARCH_START_STATIC 1)
+
+ # Copy minhook-detours DLL to test binary directory for ARM64
+ if(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "AMD64" AND DEFINED _MINHOOK_DLL)
+ add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ "${_MINHOOK_DLL}"
+ "${CMAKE_CURRENT_BINARY_DIR}"
+ COMMENT "Copying minhook-detours DLL to test binary directory"
+ VERBATIM
+ )
+ endif()
endif ()