72eeedc4da
The Windows host was NVIDIA-only (NVENC) with an openh264 software fallback. Add
AMD AMF and Intel QSV via libavcodec — the Windows analogue of the Linux VAAPI
backend — so one installer serves all three GPU vendors.
- encode/ffmpeg_win.rs: new WinVendor{Amf,Qsv} encoder. System-memory NV12/P010
readback (default, robust) + opt-in zero-copy D3D11 (PUNKTFUNK_ZEROCOPY: shares
the capturer's ID3D11Device; AMF takes AV_PIX_FMT_D3D11, QSV derives a QSV frames
ctx and maps) with a system fallback for the format-group mismatch the capturer's
video-processor fallback can produce. HDR Main10 (P010 + BT.2020/PQ VUI; an
Rgb10a2->P010 swscale covers the shader fallback).
- encode.rs: Codec::amf_name/qsv_name; open_video + windows_resolved_backend()
resolve PUNKTFUNK_ENCODER=auto|nvenc|amf|qsv|sw via a DXGI adapter VendorId probe.
- capture/dxgi.rs: gpu_mode mirrors the resolved backend (D3D11 NV12/P010 for AMF/QSV).
- gamestream/serverinfo.rs: GPU-aware codec advertisement (windows_codec_support;
AV1 gated to RDNA3+/Arc, like the VAAPI path).
- Cargo.toml: amf-qsv feature (optional ffmpeg-next in the windows target block).
- CI/installer: windows-host.yml sets FFMPEG_DIR + builds --features nvenc,amf-qsv;
the Inno installer bundles the FFmpeg DLLs; host.env default nvenc -> auto.
CI-green target; AMF/QSV not yet on-glass validated (no AMD/Intel Windows box in the
lab) — NVENC stays live-validated. An adversarial-review pass caught + fixed real
FFI bugs (AV_PIX_FMT_P010 is a macro -> P010LE; windows-rs 0.62 GetImmediateContext/
GetDesc1 return Result; AV_HWFRAME_MAP_* is a bindgen enum with no BitOr).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
126 lines
5.3 KiB
Plaintext
126 lines
5.3 KiB
Plaintext
; punktfunk host installer (Inno Setup 6).
|
|
;
|
|
; Produces a signed setup.exe that lays the host into Program Files, optionally installs the bundled
|
|
; SudoVDA virtual-display driver, and DELEGATES service registration to `punktfunk-host service
|
|
; install`. The real, idempotent install logic (SCM registration, firewall rules, default host.env,
|
|
; the SYSTEM->interactive-session CreateProcessAsUserW supervisor for secure-desktop capture) lives in
|
|
; crates/punktfunk-host/src/service.rs - this script does NOT duplicate it. That SYSTEM service model
|
|
; is exactly why MSIX is unusable here and we ship a classic elevated installer instead.
|
|
;
|
|
; Built by pack-host-installer.ps1, e.g.:
|
|
; ISCC.exe /DMyAppVersion=0.2.123 /DBinDir=C:\t\release /DStageDir=C:\t\out\stage \
|
|
; /DOutputDir=C:\t\out packaging\windows\punktfunk-host.iss
|
|
; Omit /DStageDir to build an installer WITHOUT the bundled driver (driver becomes a prerequisite).
|
|
|
|
#ifndef MyAppVersion
|
|
#define MyAppVersion "0.0.0"
|
|
#endif
|
|
#ifndef BinDir
|
|
#define BinDir "."
|
|
#endif
|
|
#ifndef OutputDir
|
|
#define OutputDir "."
|
|
#endif
|
|
; Absolute paths to the two extra payload files, passed by pack-host-installer.ps1 (validated there).
|
|
#ifndef HostEnv
|
|
#define HostEnv "..\..\scripts\windows\host.env.example"
|
|
#endif
|
|
#ifndef Readme
|
|
#define Readme "README.md"
|
|
#endif
|
|
; StageDir (the staged SudoVDA payload + nefconc.exe + install-sudovda.ps1) is optional.
|
|
#ifdef StageDir
|
|
#define WithDriver
|
|
#endif
|
|
; FfmpegBin (a dir of FFmpeg shared DLLs) is optional — present when the host is built with
|
|
; --features amf-qsv (the AMD/Intel AMF/QSV encode backend link-imports the FFmpeg libs).
|
|
#ifdef FfmpegBin
|
|
#define WithFfmpeg
|
|
#endif
|
|
|
|
[Setup]
|
|
AppId={{7C9E6A52-1F4B-4E8D-A3C7-2B5D8F1E0A93}
|
|
AppName=punktfunk host
|
|
AppVersion={#MyAppVersion}
|
|
AppPublisher=unom
|
|
AppPublisherURL=https://git.unom.io/unom/punktfunk
|
|
DefaultDirName={autopf}\punktfunk
|
|
DefaultGroupName=punktfunk
|
|
DisableProgramGroupPage=yes
|
|
UsePreviousAppDir=yes
|
|
PrivilegesRequired=admin
|
|
MinVersion=10.0
|
|
ArchitecturesAllowed=x64
|
|
ArchitecturesInstallIn64BitMode=x64
|
|
OutputDir={#OutputDir}
|
|
OutputBaseFilename=punktfunk-host-setup-{#MyAppVersion}
|
|
Compression=lzma2/max
|
|
SolidCompression=yes
|
|
WizardStyle=modern
|
|
UninstallDisplayName=punktfunk host {#MyAppVersion}
|
|
UninstallDisplayIcon={app}\punktfunk-host.exe
|
|
|
|
[Languages]
|
|
Name: "english"; MessagesFile: "compiler:Default.isl"
|
|
|
|
[Tasks]
|
|
#ifdef WithDriver
|
|
Name: "installdriver"; Description: "Install the SudoVDA virtual display driver (required for native-resolution streaming)"
|
|
#endif
|
|
Name: "startservice"; Description: "Start the punktfunk host service now (also starts on every boot)"
|
|
|
|
[Files]
|
|
Source: "{#BinDir}\punktfunk-host.exe"; DestDir: "{app}"; Flags: ignoreversion
|
|
Source: "{#HostEnv}"; DestDir: "{app}"; Flags: ignoreversion
|
|
Source: "{#Readme}"; DestDir: "{app}"; DestName: "README.txt"; Flags: ignoreversion
|
|
#ifdef WithFfmpeg
|
|
; FFmpeg shared DLLs (avcodec/avutil/swscale/...) laid down next to the exe — the AMD/Intel
|
|
; (AMF/QSV) encode backend link-imports them, so the exe won't start without them. NVENC/software-
|
|
; only builds simply omit this block.
|
|
Source: "{#FfmpegBin}\*.dll"; DestDir: "{app}"; Flags: ignoreversion
|
|
#endif
|
|
#ifdef WithDriver
|
|
; The driver payload + nefconc.exe + install-sudovda.ps1, extracted to {tmp} and removed after install.
|
|
Source: "{#StageDir}\*"; DestDir: "{tmp}\sudovda"; Flags: deleteafterinstall recursesubdirs createallsubdirs; Tasks: installdriver
|
|
#endif
|
|
|
|
[Run]
|
|
#ifdef WithDriver
|
|
Filename: "powershell.exe"; \
|
|
Parameters: "-NoProfile -ExecutionPolicy Bypass -File ""{tmp}\sudovda\install-sudovda.ps1"" -Dir ""{tmp}\sudovda"""; \
|
|
StatusMsg: "Installing the SudoVDA virtual display driver..."; \
|
|
Flags: runhidden waituntilterminated; Tasks: installdriver
|
|
#endif
|
|
; Register (or re-point, on upgrade - idempotent) the SYSTEM service from its FINAL {app} location:
|
|
; service install records current_exe() as the SCM binPath, so it must run from {app}, not {tmp}.
|
|
Filename: "{app}\punktfunk-host.exe"; Parameters: "service install"; WorkingDir: "{app}"; \
|
|
StatusMsg: "Registering the punktfunk host service..."; Flags: runhidden waituntilterminated
|
|
Filename: "{app}\punktfunk-host.exe"; Parameters: "service start"; WorkingDir: "{app}"; \
|
|
StatusMsg: "Starting the punktfunk host service..."; Flags: runhidden waituntilterminated; Tasks: startservice
|
|
|
|
[UninstallRun]
|
|
Filename: "{app}\punktfunk-host.exe"; Parameters: "service uninstall"; Flags: runhidden waituntilterminated; RunOnceId: "PunktfunkHostServiceUninstall"
|
|
|
|
[Code]
|
|
{ On upgrade the running service locks punktfunk-host.exe (and the supervisor would respawn it from
|
|
the OLD binary), so stop it and WAIT for STOPPED before files are copied. Best-effort; a fresh
|
|
install is a no-op (the service doesn't exist yet). }
|
|
procedure StopHostServiceAndWait;
|
|
var
|
|
ResultCode: Integer;
|
|
begin
|
|
Exec('powershell.exe',
|
|
'-NoProfile -ExecutionPolicy Bypass -Command "' +
|
|
'$ErrorActionPreference=''SilentlyContinue''; ' +
|
|
'$s=Get-Service -Name ''PunktfunkHost''; ' +
|
|
'if($s -and $s.Status -ne ''Stopped''){Stop-Service -Name ''PunktfunkHost'' -Force; ' +
|
|
'try{$s.WaitForStatus(''Stopped'',[TimeSpan]::FromSeconds(30))}catch{}}"',
|
|
'', SW_HIDE, ewWaitUntilTerminated, ResultCode);
|
|
end;
|
|
|
|
procedure CurStepChanged(CurStep: TSetupStep);
|
|
begin
|
|
if CurStep = ssInstall then
|
|
StopHostServiceAndWait;
|
|
end;
|