chore(licensing): LGPL FFmpeg swap, third-party notices, attribution hygiene
The MIT OR Apache-2.0 SOURCE license is clean (audit found no copied copyleft); the
gaps were all binary-distribution (Layer-2). This makes the shipped artifacts honest:
- Windows host + client: bundled FFmpeg BtbN gpl-shared -> lgpl-shared (AMF/QSV/decode
unaffected; the GPL-only x264/x265 were never used), and ship the FFmpeg LGPL notice
+ license text in the installer + MSIX (licenses/).
- THIRD-PARTY-NOTICES.txt generated + bundled into installer/MSIX/deb/rpm. Offline
generator (scripts/gen-third-party-notices.{py,sh}) + cargo-about config (about.toml/
.hbs) with a permissive-only accepted-license allow-list as a copyleft regression gate.
- Reword the win32u GPU-preference hook comments to reflect independent reimplementation
(no Apollo/Sunshine GPL-3.0 source copied).
- README dual-license + inbound=outbound contributor clause + non-affiliation trademark
disclaimer; new CONTRIBUTING.md.
- LICENSE files into the standalone driver + vk-layer workspaces; deb copyright holder
aligned to "unom and the punktfunk contributors".
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -24,8 +24,9 @@
|
|||||||
# GPU backends: the host builds with --features nvenc,amf-qsv = all three vendors in one installer.
|
# GPU backends: the host builds with --features nvenc,amf-qsv = all three vendors in one installer.
|
||||||
# - NVENC (NVIDIA, direct SDK): the only link need is nvencodeapi.lib, synthesised from a 2-export
|
# - NVENC (NVIDIA, direct SDK): the only link need is nvencodeapi.lib, synthesised from a 2-export
|
||||||
# .def with llvm-dlltool (no GPU/SDK at build time).
|
# .def with llvm-dlltool (no GPU/SDK at build time).
|
||||||
# - AMF/QSV (AMD/Intel, libavcodec): link-imports the FFmpeg libs from FFMPEG_DIR (the BtbN gpl-shared
|
# - AMF/QSV (AMD/Intel, libavcodec): link-imports the FFmpeg libs from FFMPEG_DIR (the BtbN lgpl-shared
|
||||||
# tree the client uses; includes the *_amf/*_qsv encoders) and bundles its DLLs into the installer.
|
# tree the client uses; includes the *_amf/*_qsv encoders) and bundles its DLLs into the installer.
|
||||||
|
# lgpl-shared (not gpl-shared) keeps those bundled DLLs LGPL (we never use the GPL-only x264/x265).
|
||||||
# CI never launches the exe, so no GPU is needed here — this is build + Windows clippy coverage only.
|
# CI never launches the exe, so no GPU is needed here — this is build + Windows clippy coverage only.
|
||||||
name: windows-host
|
name: windows-host
|
||||||
|
|
||||||
@@ -80,7 +81,7 @@ jobs:
|
|||||||
# (pwsh Out-File utf8 = no BOM, unlike Windows PowerShell 5.1 — keeps the first line clean).
|
# (pwsh Out-File utf8 = no BOM, unlike Windows PowerShell 5.1 — keeps the first line clean).
|
||||||
"CARGO_TARGET_DIR=C:\t" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
|
"CARGO_TARGET_DIR=C:\t" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
|
||||||
"CARGO_WORKSPACE_DIR=$env:GITHUB_WORKSPACE" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
|
"CARGO_WORKSPACE_DIR=$env:GITHUB_WORKSPACE" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
|
||||||
# FFMPEG_DIR: the same BtbN gpl-shared x64 tree the Windows CLIENT links against (provisioned
|
# FFMPEG_DIR: the same BtbN lgpl-shared x64 tree the Windows CLIENT links against (provisioned
|
||||||
# by scripts/ci/setup-windows-runner.ps1). The host's AMD/Intel AMF/QSV encode backend
|
# by scripts/ci/setup-windows-runner.ps1). The host's AMD/Intel AMF/QSV encode backend
|
||||||
# (--features amf-qsv) link-imports avcodec/avutil/swscale from it; pack-host-installer.ps1
|
# (--features amf-qsv) link-imports avcodec/avutil/swscale from it; pack-host-installer.ps1
|
||||||
# then bundles its bin\*.dll into the installer. LIBCLANG_PATH is in the runner daemon env.
|
# then bundles its bin\*.dll into the installer. LIBCLANG_PATH is in the runner daemon env.
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
# Contributing to punktfunk
|
||||||
|
|
||||||
|
Thanks for your interest in contributing!
|
||||||
|
|
||||||
|
## Licensing of contributions (inbound = outbound)
|
||||||
|
|
||||||
|
punktfunk is dual-licensed under **MIT OR Apache-2.0**.
|
||||||
|
|
||||||
|
> Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in
|
||||||
|
> the work by you, as defined in the Apache-2.0 license, shall be dual licensed as **MIT OR
|
||||||
|
> Apache-2.0**, without any additional terms or conditions.
|
||||||
|
|
||||||
|
By opening a pull request you agree to license your contribution under these terms. This is the
|
||||||
|
standard Rust-ecosystem "inbound = outbound" model; it keeps the project's licensing unambiguous
|
||||||
|
(including the Apache-2.0 §5 contributor patent grant) and any future relicensing clean. You retain
|
||||||
|
the copyright to your contributions.
|
||||||
|
|
||||||
|
### Do not paste copyleft (or otherwise incompatibly-licensed) code
|
||||||
|
|
||||||
|
The single thing that could poison the permissive license is **copied source from a copyleft
|
||||||
|
project**. Several adjacent projects (Sunshine, Apollo, Moonlight) are GPL-3.0. You may study them
|
||||||
|
and reimplement a *technique*, protocol, or wire format — those are not copyrightable — but **never
|
||||||
|
paste their code**, and do not translate a GPL implementation line-by-line. When a comment credits
|
||||||
|
prior art, make clear it is an independent reimplementation, not a copy. The same applies to any
|
||||||
|
third party's code under a license incompatible with MIT/Apache.
|
||||||
|
|
||||||
|
If you add a new third-party dependency, it must be permissive (MIT / Apache-2.0 / BSD / ISC / Zlib /
|
||||||
|
Unicode-3.0 / etc.). `about.toml` holds the accepted-license allow-list; regenerate the attribution
|
||||||
|
file with `scripts/gen-third-party-notices.sh` when the dependency tree changes.
|
||||||
|
|
||||||
|
## Before you push
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cargo fmt --all --check
|
||||||
|
cargo clippy --workspace --all-targets -- -D warnings
|
||||||
|
cargo test --workspace
|
||||||
|
```
|
||||||
|
|
||||||
|
Generated artifacts are checked in and CI fails on drift: `include/punktfunk_core.h` (cbindgen) and
|
||||||
|
`api/openapi.json` (`cargo run -p punktfunk-host -- openapi`). Match the surrounding code's comment
|
||||||
|
density and naming. Commit messages end with the `Co-Authored-By` trailer (see `git log`).
|
||||||
|
|
||||||
|
See [`CLAUDE.md`](CLAUDE.md) for the full build/test/run guide and design invariants.
|
||||||
@@ -155,4 +155,31 @@ tools/ latency-probe · loss-harness (measurement)
|
|||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
MIT OR Apache-2.0.
|
Licensed under either of
|
||||||
|
|
||||||
|
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
|
||||||
|
<https://www.apache.org/licenses/LICENSE-2.0>)
|
||||||
|
- MIT license ([LICENSE-MIT](LICENSE-MIT) or <https://opensource.org/licenses/MIT>)
|
||||||
|
|
||||||
|
at your option — `SPDX-License-Identifier: MIT OR Apache-2.0`.
|
||||||
|
|
||||||
|
### Contribution
|
||||||
|
|
||||||
|
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in
|
||||||
|
the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
|
||||||
|
additional terms or conditions. See [CONTRIBUTING.md](CONTRIBUTING.md).
|
||||||
|
|
||||||
|
### Third-party components
|
||||||
|
|
||||||
|
punktfunk's own source is MIT/Apache-2.0. Shipped binaries additionally link third-party components
|
||||||
|
under their own (permissive) licenses — see [`THIRD-PARTY-NOTICES.txt`](THIRD-PARTY-NOTICES.txt)
|
||||||
|
(regenerate with `scripts/gen-third-party-notices.sh`). The Windows host and client builds also
|
||||||
|
bundle FFmpeg under the **LGPL v2.1+** (dynamically linked, replaceable DLLs; the license text and
|
||||||
|
notice ship in the installed `licenses/` folder).
|
||||||
|
|
||||||
|
### Trademarks
|
||||||
|
|
||||||
|
punktfunk is an independent project and is **not affiliated with, endorsed by, or sponsored by**
|
||||||
|
NVIDIA, Microsoft, Sony, Valve, or the Moonlight project. "GameStream", "Moonlight", "Xbox",
|
||||||
|
"DualSense", "DualShock", and "PlayStation" are trademarks of their respective owners and are used
|
||||||
|
here only to describe interoperability.
|
||||||
|
|||||||
+16154
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,23 @@
|
|||||||
|
THIRD-PARTY SOFTWARE NOTICES
|
||||||
|
============================================================================
|
||||||
|
|
||||||
|
punktfunk (https://git.unom.io/unom/punktfunk) is licensed under MIT OR Apache-2.0.
|
||||||
|
The binaries it ships statically/dynamically link the third-party Rust crates below.
|
||||||
|
Each is distributed under its own permissive license; full texts follow.
|
||||||
|
Generated by `cargo about generate about.hbs` (see about.toml) — do not edit by hand.
|
||||||
|
|
||||||
|
Overview:
|
||||||
|
{{#each overview}}
|
||||||
|
{{name}} ({{id}}): {{count}} crate(s)
|
||||||
|
{{/each}}
|
||||||
|
|
||||||
|
{{#each licenses}}
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
{{name}} ({{id}})
|
||||||
|
Used by:
|
||||||
|
{{#each used_by}} - {{crate.name}} {{crate.version}}{{#if crate.repository}} ({{crate.repository}}){{/if}}
|
||||||
|
{{/each}}
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
{{text}}
|
||||||
|
|
||||||
|
{{/each}}
|
||||||
+49
@@ -0,0 +1,49 @@
|
|||||||
|
# cargo-about config — full-fidelity third-party license harvest for CI.
|
||||||
|
#
|
||||||
|
# cargo install cargo-about
|
||||||
|
# cargo about generate about.hbs > THIRD-PARTY-NOTICES.txt # (or use scripts/gen-third-party-notices.sh)
|
||||||
|
#
|
||||||
|
# `accepted` is the allow-list of SPDX licenses permitted in the dependency tree. CI fails if a crate
|
||||||
|
# carries anything not listed here — which is exactly the regression guard we want against a copyleft
|
||||||
|
# dependency silently entering the linked set. All entries
|
||||||
|
# below are permissive / attribution-only; deliberately NO GPL/LGPL/AGPL/MPL-link/SSPL/EPL.
|
||||||
|
#
|
||||||
|
# The dependency-free fallback is scripts/gen-third-party-notices.py (reads the cargo registry cache),
|
||||||
|
# which is what produced the committed baseline when cargo-about is unavailable offline.
|
||||||
|
|
||||||
|
accepted = [
|
||||||
|
"MIT",
|
||||||
|
"MIT-0",
|
||||||
|
"Apache-2.0",
|
||||||
|
"Apache-2.0 WITH LLVM-exception",
|
||||||
|
"BSD-2-Clause",
|
||||||
|
"BSD-3-Clause",
|
||||||
|
"ISC",
|
||||||
|
"Zlib",
|
||||||
|
"0BSD",
|
||||||
|
"BSL-1.0",
|
||||||
|
"Unicode-3.0",
|
||||||
|
"Unicode-DFS-2016",
|
||||||
|
"CDLA-Permissive-2.0",
|
||||||
|
"CC0-1.0",
|
||||||
|
"Unlicense",
|
||||||
|
"WTFPL",
|
||||||
|
"OpenSSL",
|
||||||
|
]
|
||||||
|
|
||||||
|
# cbindgen is MPL-2.0 but it is a BUILD-ONLY codegen tool that never links into a shipped artifact
|
||||||
|
# (its generated header is not a derivative work), so it is excluded from the notices rather than
|
||||||
|
# accepted as a linked license.
|
||||||
|
ignore-build-dependencies = true
|
||||||
|
ignore-dev-dependencies = true
|
||||||
|
|
||||||
|
# r-efi offers an LGPL-2.1-or-later arm but is tri-licensed; take a permissive arm. (It is also
|
||||||
|
# UEFI-target-gated out of every shipped build.)
|
||||||
|
[r-efi.clarify]
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
|
||||||
|
[ring.clarify]
|
||||||
|
license = "MIT AND ISC AND OpenSSL"
|
||||||
|
|
||||||
|
[aws-lc-sys.clarify]
|
||||||
|
license = "ISC AND Apache-2.0 AND MIT AND BSD-3-Clause AND OpenSSL"
|
||||||
@@ -76,11 +76,29 @@ foreach ($f in $required) {
|
|||||||
Copy-Item $src (Join-Path $layout $f) -Force
|
Copy-Item $src (Join-Path $layout $f) -Force
|
||||||
}
|
}
|
||||||
|
|
||||||
# FFmpeg runtime DLLs (the exe link-imports the decode set; copy them all — small and correct)
|
# FFmpeg runtime DLLs (the exe link-imports the decode set; copy them all — small and correct).
|
||||||
|
# These are unmodified BtbN *lgpl-shared* builds, linked dynamically (replaceable DLLs) — FFmpeg is
|
||||||
|
# used under the LGPL v2.1+; the license text + notice ship in licenses\ below.
|
||||||
$ff = Get-ChildItem -Path $FfmpegBin -Filter *.dll -ErrorAction SilentlyContinue
|
$ff = Get-ChildItem -Path $FfmpegBin -Filter *.dll -ErrorAction SilentlyContinue
|
||||||
if (-not $ff) { throw "no FFmpeg DLLs in $FfmpegBin" }
|
if (-not $ff) { throw "no FFmpeg DLLs in $FfmpegBin" }
|
||||||
$ff | ForEach-Object { Copy-Item $_.FullName (Join-Path $layout $_.Name) -Force }
|
$ff | ForEach-Object { Copy-Item $_.FullName (Join-Path $layout $_.Name) -Force }
|
||||||
|
|
||||||
|
# license/attribution payload (MSIX has no installer EULA page, so ship them as files): FFmpeg's LGPL
|
||||||
|
# notice + license text, the project's own MIT/Apache texts, and the generated third-party notices.
|
||||||
|
$licDir = Join-Path $layout 'licenses'
|
||||||
|
New-Item -ItemType Directory -Force -Path $licDir | Out-Null
|
||||||
|
$repoRoot = (Resolve-Path (Join-Path $PSScriptRoot '..\..\..')).Path
|
||||||
|
Copy-Item (Join-Path $repoRoot 'packaging\windows\licenses\FFmpeg-LGPL-NOTICE.txt') $licDir -Force -ErrorAction SilentlyContinue
|
||||||
|
foreach ($n in @('THIRD-PARTY-NOTICES.txt', 'LICENSE-MIT', 'LICENSE-APACHE')) {
|
||||||
|
$p = Join-Path $repoRoot $n
|
||||||
|
if (Test-Path $p) { Copy-Item $p $licDir -Force }
|
||||||
|
}
|
||||||
|
$ffRoot = Split-Path $FfmpegBin -Parent
|
||||||
|
foreach ($lic in @('LICENSE.txt', 'LICENSE', 'COPYING.LGPLv2.1', 'COPYING.LGPLv3', 'COPYING.txt')) {
|
||||||
|
$p = Join-Path $ffRoot $lic
|
||||||
|
if (Test-Path $p) { Copy-Item $p $licDir -Force }
|
||||||
|
}
|
||||||
|
|
||||||
# tile/store assets
|
# tile/store assets
|
||||||
Copy-Item (Join-Path $assets '*') (Join-Path $layout 'Assets') -Force
|
Copy-Item (Join-Path $assets '*') (Join-Path $layout 'Assets') -Force
|
||||||
|
|
||||||
|
|||||||
@@ -217,6 +217,7 @@ bytemuck = { version = "1.19", features = ["derive"] }
|
|||||||
# nvEncodeAPI64.dll) on the linker path. Build the GPU host with `--features nvenc`.
|
# nvEncodeAPI64.dll) on the linker path. Build the GPU host with `--features nvenc`.
|
||||||
nvenc = ["dep:nvidia-video-codec-sdk"]
|
nvenc = ["dep:nvidia-video-codec-sdk"]
|
||||||
# AMD/Intel hardware encode on Windows (AMF/QSV via ffmpeg-next). OFF by default: it needs a
|
# AMD/Intel hardware encode on Windows (AMF/QSV via ffmpeg-next). OFF by default: it needs a
|
||||||
# `FFMPEG_DIR` (BtbN gpl-shared, includes `*_amf`/`*_qsv`) at build time and bundles the FFmpeg
|
# `FFMPEG_DIR` (BtbN lgpl-shared — includes `*_amf`/`*_qsv`; the GPL-only x264/x265 are never used,
|
||||||
# DLLs at runtime. Build the all-vendor GPU host with `--features nvenc,amf-qsv`.
|
# so the LGPL build suffices and keeps the bundled DLLs LGPL, not GPL) at build time and bundles the
|
||||||
|
# FFmpeg DLLs at runtime. Build the all-vendor GPU host with `--features nvenc,amf-qsv`.
|
||||||
amf-qsv = ["dep:ffmpeg-next"]
|
amf-qsv = ["dep:ffmpeg-next"]
|
||||||
|
|||||||
@@ -188,7 +188,8 @@ pub(crate) unsafe fn make_device(
|
|||||||
let device = device.context("null D3D11 device")?;
|
let device = device.context("null D3D11 device")?;
|
||||||
let context = context.context("null D3D11 context")?;
|
let context = context.context("null D3D11 context")?;
|
||||||
|
|
||||||
// Apollo-style GPU scheduling hardening (Sunshine display_base.cpp:599-709). Our capture+encode
|
// GPU scheduling hardening — the same approach Sunshine/Apollo use, reimplemented here via the
|
||||||
|
// documented D3DKMT/DXGI APIs (no GPL source copied). Our capture+encode
|
||||||
// shares the GPU with the streamed game; when the game saturates the GPU our process is starved of
|
// shares the GPU with the streamed game; when the game saturates the GPU our process is starved of
|
||||||
// GPU time slices, so NVENC sits near-idle yet `lock_bitstream` waits ~20 ms for our context to be
|
// GPU time slices, so NVENC sits near-idle yet `lock_bitstream` waits ~20 ms for our context to be
|
||||||
// scheduled — capping the stream (~47 fps measured at 5K@240) and stuttering. Per-frame copy/convert
|
// scheduled — capping the stream (~47 fps measured at 5K@240) and stuttering. Per-frame copy/convert
|
||||||
@@ -197,7 +198,7 @@ pub(crate) unsafe fn make_device(
|
|||||||
// GPU thread priority and a 1-frame latency cap.
|
// GPU thread priority and a 1-frame latency cap.
|
||||||
elevate_process_gpu_priority();
|
elevate_process_gpu_priority();
|
||||||
if let Ok(dxgi_dev) = device.cast::<IDXGIDevice>() {
|
if let Ok(dxgi_dev) = device.cast::<IDXGIDevice>() {
|
||||||
// Apollo's absolute max GPU thread priority (0x4000001E); fall back to relative +7.
|
// The absolute max GPU thread priority (0x4000001E; the same value Sunshine/Apollo use); fall back to relative +7.
|
||||||
if dxgi_dev.SetGPUThreadPriority(0x4000_001E).is_err()
|
if dxgi_dev.SetGPUThreadPriority(0x4000_001E).is_err()
|
||||||
&& dxgi_dev.SetGPUThreadPriority(7).is_err()
|
&& dxgi_dev.SetGPUThreadPriority(7).is_err()
|
||||||
{
|
{
|
||||||
@@ -291,7 +292,8 @@ unsafe fn d3dkmt_set_scheduling_priority_class(
|
|||||||
Some(f(process, prio))
|
Some(f(process, prio))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Apollo-style GPU scheduling-priority hardening (Sunshine `display_base.cpp:599-709`). On a
|
/// GPU scheduling-priority hardening — the same approach as Sunshine/Apollo, independently
|
||||||
|
/// implemented via the documented D3DKMT APIs (no GPL source copied). On a
|
||||||
/// GPU-saturated game our capture+encode process is starved of GPU time slices — NVENC sits ~idle but
|
/// GPU-saturated game our capture+encode process is starved of GPU time slices — NVENC sits ~idle but
|
||||||
/// `lock_bitstream` waits ~20 ms for our context to be scheduled. Elevating the PROCESS GPU scheduling
|
/// `lock_bitstream` waits ~20 ms for our context to be scheduled. Elevating the PROCESS GPU scheduling
|
||||||
/// priority class (the strong cross-process lever — far more effective than `SetGPUThreadPriority`
|
/// priority class (the strong cross-process lever — far more effective than `SetGPUThreadPriority`
|
||||||
@@ -532,7 +534,9 @@ const ES_DISPLAY_REQUIRED: u32 = 0x0000_0002;
|
|||||||
|
|
||||||
/// Replacement for `win32u.dll!NtGdiDdDDIGetCachedHybridQueryValue`: always report
|
/// Replacement for `win32u.dll!NtGdiDdDDIGetCachedHybridQueryValue`: always report
|
||||||
/// `D3DKMT_GPU_PREFERENCE_STATE_UNSPECIFIED` (3). We fully replace the function (never call the
|
/// `D3DKMT_GPU_PREFERENCE_STATE_UNSPECIFIED` (3). We fully replace the function (never call the
|
||||||
/// original), so no trampoline is needed. (Ported verbatim from Apollo's MinHook hook.)
|
/// original), so no trampoline is needed. (Independent reimplementation of the same technique Apollo
|
||||||
|
/// uses: Apollo installs its hook via the MinHook library; this is an original inline byte-patch and
|
||||||
|
/// copies no Apollo/GPL source.)
|
||||||
unsafe extern "system" fn hybrid_query_hook(gpu_preference: *mut u32) -> i32 {
|
unsafe extern "system" fn hybrid_query_hook(gpu_preference: *mut u32) -> i32 {
|
||||||
HYBRID_HOOK_HITS.fetch_add(1, Ordering::Relaxed);
|
HYBRID_HOOK_HITS.fetch_add(1, Ordering::Relaxed);
|
||||||
if gpu_preference.is_null() {
|
if gpu_preference.is_null() {
|
||||||
@@ -542,7 +546,8 @@ unsafe extern "system" fn hybrid_query_hook(gpu_preference: *mut u32) -> i32 {
|
|||||||
0 // STATUS_SUCCESS
|
0 // STATUS_SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Apollo's win32u GPU-preference hook, ported. On a HYBRID-GPU box DXGI resolves a GPU preference
|
/// The win32u GPU-preference hook (the same technique Apollo applies, reimplemented here from the
|
||||||
|
/// documented DDI — no GPL source copied). On a HYBRID-GPU box DXGI resolves a GPU preference
|
||||||
/// (registry + power settings + the hybrid-adapter DDI) and REPARENTS outputs onto the chosen render
|
/// (registry + power settings + the hybrid-adapter DDI) and REPARENTS outputs onto the chosen render
|
||||||
/// GPU — which constantly invalidates Desktop Duplication (DXGI_ERROR_ACCESS_LOST 0x887A0026, the
|
/// GPU — which constantly invalidates Desktop Duplication (DXGI_ERROR_ACCESS_LOST 0x887A0026, the
|
||||||
/// freeze/churn observed on the RTX 4090 + AMD iGPU box; `SET_RENDER_ADAPTER` is ignored there). Faking
|
/// freeze/churn observed on the RTX 4090 + AMD iGPU box; `SET_RENDER_ADAPTER` is ignored there). Faking
|
||||||
@@ -555,7 +560,7 @@ pub(crate) fn install_gpu_pref_hook() {
|
|||||||
// SAFETY: this one-time hook install only touches a region it has just validated.
|
// SAFETY: this one-time hook install only touches a region it has just validated.
|
||||||
// `LoadLibraryA("win32u.dll")` + `GetProcAddress("NtGdiDdDDIGetCachedHybridQueryValue")` yield the
|
// `LoadLibraryA("win32u.dll")` + `GetProcAddress("NtGdiDdDDIGetCachedHybridQueryValue")` yield the
|
||||||
// live base of the real exported function, so `target` is a valid executable code pointer to at
|
// live base of the real exported function, so `target` is a valid executable code pointer to at
|
||||||
// least the 12 bytes the patch overwrites (an x64 prologue, per Apollo's verified hook). The two
|
// least the 12 bytes the patch overwrites (an x64 prologue). The two
|
||||||
// `ptr::copy_nonoverlapping`s each move exactly 12 bytes between the 12-byte stack arrays
|
// `ptr::copy_nonoverlapping`s each move exactly 12 bytes between the 12-byte stack arrays
|
||||||
// (`patch`/`readback`) and `target`, which `VirtualProtect(target, 12, PAGE_EXECUTE_READWRITE, …)`
|
// (`patch`/`readback`) and `target`, which `VirtualProtect(target, 12, PAGE_EXECUTE_READWRITE, …)`
|
||||||
// has just made writable (and is restored to `old` after) — source and dest never overlap (stack
|
// has just made writable (and is restored to `old` after) — source and dest never overlap (stack
|
||||||
|
|||||||
@@ -121,7 +121,8 @@ fn real_main() -> Result<()> {
|
|||||||
punktfunk_core::ABI_VERSION
|
punktfunk_core::ABI_VERSION
|
||||||
);
|
);
|
||||||
|
|
||||||
// Install Apollo's win32u GPU-preference hook BEFORE anything touches DXGI (the SudoVDA
|
// Install the win32u GPU-preference hook (same technique as Apollo, reimplemented — no GPL source
|
||||||
|
// copied) BEFORE anything touches DXGI (the virtual-display
|
||||||
// render-adapter selection creates a DXGI factory during virtual-display setup, well before
|
// render-adapter selection creates a DXGI factory during virtual-display setup, well before
|
||||||
// capture). On a hybrid-GPU box this stops DXGI from reparenting the virtual output off the
|
// capture). On a hybrid-GPU box this stops DXGI from reparenting the virtual output off the
|
||||||
// capture GPU — the ACCESS_LOST churn fix. Idempotent (Once); harmless on non-hybrid boxes.
|
// capture GPU — the ACCESS_LOST churn fix. Idempotent (Once); harmless on non-hybrid boxes.
|
||||||
|
|||||||
@@ -43,6 +43,10 @@ install -Dm0644 scripts/99-punktfunk-client-net.conf \
|
|||||||
install -Dm0644 LICENSE-MIT "$DOCDIR/LICENSE-MIT"
|
install -Dm0644 LICENSE-MIT "$DOCDIR/LICENSE-MIT"
|
||||||
install -Dm0644 LICENSE-APACHE "$DOCDIR/LICENSE-APACHE"
|
install -Dm0644 LICENSE-APACHE "$DOCDIR/LICENSE-APACHE"
|
||||||
install -Dm0644 README.md "$DOCDIR/README.md"
|
install -Dm0644 README.md "$DOCDIR/README.md"
|
||||||
|
# Third-party crate attributions (regenerate with scripts/gen-third-party-notices.sh).
|
||||||
|
if [ -f THIRD-PARTY-NOTICES.txt ]; then
|
||||||
|
install -Dm0644 THIRD-PARTY-NOTICES.txt "$DOCDIR/THIRD-PARTY-NOTICES.txt"
|
||||||
|
fi
|
||||||
|
|
||||||
cat > "$DOCDIR/copyright" <<EOF
|
cat > "$DOCDIR/copyright" <<EOF
|
||||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||||
@@ -50,7 +54,7 @@ Upstream-Name: punktfunk
|
|||||||
Source: https://git.unom.io/unom/punktfunk
|
Source: https://git.unom.io/unom/punktfunk
|
||||||
|
|
||||||
Files: *
|
Files: *
|
||||||
Copyright: punktfunk contributors
|
Copyright: unom and the punktfunk contributors
|
||||||
License: MIT or Apache-2.0
|
License: MIT or Apache-2.0
|
||||||
Dual-licensed. Full texts in /usr/share/doc/$PKG/LICENSE-MIT and
|
Dual-licensed. Full texts in /usr/share/doc/$PKG/LICENSE-MIT and
|
||||||
/usr/share/doc/$PKG/LICENSE-APACHE.
|
/usr/share/doc/$PKG/LICENSE-APACHE.
|
||||||
|
|||||||
@@ -68,6 +68,10 @@ install -Dm0644 api/openapi.json "$SHAREDIR/openapi.json"
|
|||||||
install -Dm0644 LICENSE-MIT "$DOCDIR/LICENSE-MIT"
|
install -Dm0644 LICENSE-MIT "$DOCDIR/LICENSE-MIT"
|
||||||
install -Dm0644 LICENSE-APACHE "$DOCDIR/LICENSE-APACHE"
|
install -Dm0644 LICENSE-APACHE "$DOCDIR/LICENSE-APACHE"
|
||||||
install -Dm0644 README.md "$DOCDIR/README.md"
|
install -Dm0644 README.md "$DOCDIR/README.md"
|
||||||
|
# Third-party crate attributions (regenerate with scripts/gen-third-party-notices.sh).
|
||||||
|
if [ -f THIRD-PARTY-NOTICES.txt ]; then
|
||||||
|
install -Dm0644 THIRD-PARTY-NOTICES.txt "$DOCDIR/THIRD-PARTY-NOTICES.txt"
|
||||||
|
fi
|
||||||
|
|
||||||
# Debian copyright + changelog (cheap, keeps the package well-formed).
|
# Debian copyright + changelog (cheap, keeps the package well-formed).
|
||||||
cat > "$DOCDIR/copyright" <<EOF
|
cat > "$DOCDIR/copyright" <<EOF
|
||||||
@@ -76,7 +80,7 @@ Upstream-Name: punktfunk
|
|||||||
Source: https://git.unom.io/unom/punktfunk
|
Source: https://git.unom.io/unom/punktfunk
|
||||||
|
|
||||||
Files: *
|
Files: *
|
||||||
Copyright: punktfunk contributors
|
Copyright: unom and the punktfunk contributors
|
||||||
License: MIT or Apache-2.0
|
License: MIT or Apache-2.0
|
||||||
Dual-licensed. Full texts in /usr/share/doc/$PKG/LICENSE-MIT and
|
Dual-licensed. Full texts in /usr/share/doc/$PKG/LICENSE-MIT and
|
||||||
/usr/share/doc/$PKG/LICENSE-APACHE.
|
/usr/share/doc/$PKG/LICENSE-APACHE.
|
||||||
|
|||||||
@@ -261,7 +261,7 @@ install -Dm0644 web/web.env.example %{buildroot}%{_datadir}/punkt
|
|||||||
%endif
|
%endif
|
||||||
|
|
||||||
%files
|
%files
|
||||||
%license LICENSE-MIT LICENSE-APACHE
|
%license LICENSE-MIT LICENSE-APACHE THIRD-PARTY-NOTICES.txt
|
||||||
%doc README.md design/implementation-plan.md packaging/README.md
|
%doc README.md design/implementation-plan.md packaging/README.md
|
||||||
%{_bindir}/punktfunk-host
|
%{_bindir}/punktfunk-host
|
||||||
%{_udevrulesdir}/60-punktfunk.rules
|
%{_udevrulesdir}/60-punktfunk.rules
|
||||||
@@ -276,7 +276,7 @@ install -Dm0644 web/web.env.example %{buildroot}%{_datadir}/punkt
|
|||||||
%{_datadir}/%{name}/*
|
%{_datadir}/%{name}/*
|
||||||
|
|
||||||
%files client
|
%files client
|
||||||
%license LICENSE-MIT LICENSE-APACHE
|
%license LICENSE-MIT LICENSE-APACHE THIRD-PARTY-NOTICES.txt
|
||||||
%{_bindir}/punktfunk-client
|
%{_bindir}/punktfunk-client
|
||||||
%{_datadir}/applications/io.unom.Punktfunk.desktop
|
%{_datadir}/applications/io.unom.Punktfunk.desktop
|
||||||
%{_udevrulesdir}/70-punktfunk-client.rules
|
%{_udevrulesdir}/70-punktfunk-client.rules
|
||||||
@@ -284,7 +284,7 @@ install -Dm0644 web/web.env.example %{buildroot}%{_datadir}/punkt
|
|||||||
|
|
||||||
%if %{with web}
|
%if %{with web}
|
||||||
%files web
|
%files web
|
||||||
%license LICENSE-MIT LICENSE-APACHE
|
%license LICENSE-MIT LICENSE-APACHE THIRD-PARTY-NOTICES.txt
|
||||||
%{_bindir}/punktfunk-web-server
|
%{_bindir}/punktfunk-web-server
|
||||||
%dir %{_datadir}/punktfunk-web
|
%dir %{_datadir}/punktfunk-web
|
||||||
%{_datadir}/punktfunk-web/.output
|
%{_datadir}/punktfunk-web/.output
|
||||||
|
|||||||
@@ -0,0 +1,201 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or Derivative
|
||||||
|
Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright 2026 unom
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2026 unom
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
FFmpeg — third-party component notice
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
This product bundles unmodified shared libraries from the FFmpeg project
|
||||||
|
(avcodec / avutil / avformat / swscale / swresample and their dependencies) as
|
||||||
|
separate dynamic-link libraries (DLLs). punktfunk uses them only for hardware
|
||||||
|
video encode (AMD AMF / Intel QSV) on the host and hardware/software video
|
||||||
|
decode on the client.
|
||||||
|
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
The bundled FFmpeg libraries are distributed under the GNU Lesser General Public
|
||||||
|
License (LGPL), version 2.1 or later. The bundled builds are the "lgpl-shared"
|
||||||
|
configuration — they do NOT include any GPL-licensed components (notably they do
|
||||||
|
not include libx264 or libx265; punktfunk does not use them). The full text of
|
||||||
|
the LGPL accompanies this notice (see the COPYING.LGPLv2.1 / LICENSE files in
|
||||||
|
this directory; if absent, see https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html).
|
||||||
|
|
||||||
|
How punktfunk complies (dynamic linking)
|
||||||
|
----------------------------------------
|
||||||
|
punktfunk links FFmpeg only dynamically: the FFmpeg DLLs are shipped as separate
|
||||||
|
files alongside the application and are not statically combined into the
|
||||||
|
punktfunk executable. You may replace these DLLs with your own ABI-compatible
|
||||||
|
build of FFmpeg, which satisfies LGPL section 6 (the right to relink the work
|
||||||
|
against a modified version of the library).
|
||||||
|
|
||||||
|
Source code
|
||||||
|
-----------
|
||||||
|
The bundled binaries are unmodified builds produced by the BtbN/FFmpeg-Builds
|
||||||
|
project. The exact source for the FFmpeg release used is available from:
|
||||||
|
|
||||||
|
* FFmpeg project source: https://ffmpeg.org/download.html (release n7.1)
|
||||||
|
* Exact build recipe: https://github.com/BtbN/FFmpeg-Builds
|
||||||
|
|
||||||
|
A copy of the corresponding FFmpeg source for the version shipped here is
|
||||||
|
available on request from the punktfunk maintainers (https://git.unom.io/unom/punktfunk).
|
||||||
|
|
||||||
|
Trademark
|
||||||
|
---------
|
||||||
|
FFmpeg is a trademark of Fabrice Bellard, originator of the FFmpeg project.
|
||||||
|
punktfunk is not affiliated with or endorsed by the FFmpeg project.
|
||||||
@@ -132,12 +132,25 @@ Copy-Item -LiteralPath $hostEnvSrc -Destination $hostEnv -Force
|
|||||||
Copy-Item -LiteralPath $readmeSrc -Destination $readme -Force
|
Copy-Item -LiteralPath $readmeSrc -Destination $readme -Force
|
||||||
Copy-Item -LiteralPath $iss -Destination $issLocal -Force
|
Copy-Item -LiteralPath $iss -Destination $issLocal -Force
|
||||||
|
|
||||||
|
# License/attribution payload bundled into {app}\licenses: the project's own MIT/Apache texts and the
|
||||||
|
# generated third-party crate notices. The FFmpeg LGPL notice + license text are added to this same
|
||||||
|
# dir below when the AMF/QSV FFmpeg DLLs are bundled. (THIRD-PARTY-NOTICES.txt is committed; CI may
|
||||||
|
# regenerate it via scripts/gen-third-party-notices.sh before packaging.)
|
||||||
|
$licStage = Join-Path $OutDir 'licenses'
|
||||||
|
New-Item -ItemType Directory -Force -Path $licStage | Out-Null
|
||||||
|
foreach ($n in @('LICENSE-MIT', 'LICENSE-APACHE', 'THIRD-PARTY-NOTICES.txt')) {
|
||||||
|
$p = Join-Path $repoRoot $n
|
||||||
|
if (Test-Path $p) { Copy-Item $p -Destination $licStage -Force }
|
||||||
|
else { Write-Warning "license payload missing (skipped): $p" }
|
||||||
|
}
|
||||||
|
|
||||||
$defines = @(
|
$defines = @(
|
||||||
"/DMyAppVersion=$Version",
|
"/DMyAppVersion=$Version",
|
||||||
"/DBinDir=$TargetDir",
|
"/DBinDir=$TargetDir",
|
||||||
"/DOutputDir=$OutDir",
|
"/DOutputDir=$OutDir",
|
||||||
"/DHostEnv=$hostEnv",
|
"/DHostEnv=$hostEnv",
|
||||||
"/DReadme=$readme"
|
"/DReadme=$readme",
|
||||||
|
"/DLicensesDir=$licStage"
|
||||||
)
|
)
|
||||||
|
|
||||||
# --- build (from source) + stage the pf-vdisplay virtual-display driver -----------------------
|
# --- build (from source) + stage the pf-vdisplay virtual-display driver -----------------------
|
||||||
@@ -179,7 +192,7 @@ if (-not $NoDriver) {
|
|||||||
# --- stage the FFmpeg shared DLLs (AMD/Intel AMF/QSV build) ------------------------------------
|
# --- stage the FFmpeg shared DLLs (AMD/Intel AMF/QSV build) ------------------------------------
|
||||||
# A host built with --features amf-qsv link-imports avcodec/avutil/swscale/... so the shared DLLs
|
# A host built with --features amf-qsv link-imports avcodec/avutil/swscale/... so the shared DLLs
|
||||||
# MUST sit next to the exe (it won't start otherwise). Bundle them from $FfmpegDir\bin - the same
|
# MUST sit next to the exe (it won't start otherwise). Bundle them from $FfmpegDir\bin - the same
|
||||||
# BtbN gpl-shared tree the build linked against. A nvenc/software-only build doesn't import them, so
|
# BtbN lgpl-shared tree the build linked against. A nvenc/software-only build doesn't import them, so
|
||||||
# this is a harmless extra there; skipped entirely when $FfmpegDir is unset.
|
# this is a harmless extra there; skipped entirely when $FfmpegDir is unset.
|
||||||
$ffmpegBinSrc = if ($FfmpegDir) { Join-Path $FfmpegDir 'bin' } else { $null }
|
$ffmpegBinSrc = if ($FfmpegDir) { Join-Path $FfmpegDir 'bin' } else { $null }
|
||||||
if ($ffmpegBinSrc -and (Test-Path $ffmpegBinSrc)) {
|
if ($ffmpegBinSrc -and (Test-Path $ffmpegBinSrc)) {
|
||||||
@@ -190,6 +203,16 @@ if ($ffmpegBinSrc -and (Test-Path $ffmpegBinSrc)) {
|
|||||||
$dlls | ForEach-Object { Copy-Item $_.FullName -Destination $ffmpegStage -Force }
|
$dlls | ForEach-Object { Copy-Item $_.FullName -Destination $ffmpegStage -Force }
|
||||||
$defines += "/DFfmpegBin=$ffmpegStage"
|
$defines += "/DFfmpegBin=$ffmpegStage"
|
||||||
Write-Host "bundling $($dlls.Count) FFmpeg DLL(s) from $ffmpegBinSrc"
|
Write-Host "bundling $($dlls.Count) FFmpeg DLL(s) from $ffmpegBinSrc"
|
||||||
|
# LGPL compliance: add FFmpeg's own license text (preserved in the BtbN tree root) + our
|
||||||
|
# attribution notice to the {app}\licenses payload so the conveyed installer carries the
|
||||||
|
# LGPLv2.1+ terms. FFmpeg is linked dynamically (separate, user-replaceable DLLs), which
|
||||||
|
# satisfies the LGPL relink requirement.
|
||||||
|
Copy-Item (Join-Path $here 'licenses\FFmpeg-LGPL-NOTICE.txt') -Destination $licStage -Force -ErrorAction SilentlyContinue
|
||||||
|
foreach ($lic in @('LICENSE.txt', 'LICENSE', 'COPYING.LGPLv2.1', 'COPYING.LGPLv3', 'COPYING.txt')) {
|
||||||
|
$p = Join-Path $FfmpegDir $lic
|
||||||
|
if (Test-Path $p) { Copy-Item $p -Destination (Join-Path $licStage "FFmpeg-$lic") -Force }
|
||||||
|
}
|
||||||
|
Write-Host "added FFmpeg license/notice to $licStage"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { Write-Host "no FFMPEG_DIR\bin -> installer built WITHOUT FFmpeg DLLs (nvenc/software-only host)" }
|
else { Write-Host "no FFMPEG_DIR\bin -> installer built WITHOUT FFmpeg DLLs (nvenc/software-only host)" }
|
||||||
|
|||||||
@@ -0,0 +1,201 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or Derivative
|
||||||
|
Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright 2026 unom
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2026 unom
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -102,10 +102,17 @@ Name: "startservice"; Description: "Start the punktfunk host service now (also s
|
|||||||
Source: "{#BinDir}\punktfunk-host.exe"; DestDir: "{app}"; Flags: ignoreversion
|
Source: "{#BinDir}\punktfunk-host.exe"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
Source: "{#HostEnv}"; DestDir: "{app}"; Flags: ignoreversion
|
Source: "{#HostEnv}"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
Source: "{#Readme}"; DestDir: "{app}"; DestName: "README.txt"; Flags: ignoreversion
|
Source: "{#Readme}"; DestDir: "{app}"; DestName: "README.txt"; Flags: ignoreversion
|
||||||
|
#ifdef LicensesDir
|
||||||
|
; License/attribution payload -> {app}\licenses: the project's MIT/Apache texts, the generated
|
||||||
|
; THIRD-PARTY-NOTICES (permissive crate attributions), and (on an amf-qsv build) the FFmpeg LGPL
|
||||||
|
; notice + license text. Staged by pack-host-installer.ps1.
|
||||||
|
Source: "{#LicensesDir}\*"; DestDir: "{app}\licenses"; Flags: ignoreversion
|
||||||
|
#endif
|
||||||
#ifdef WithFfmpeg
|
#ifdef WithFfmpeg
|
||||||
; FFmpeg shared DLLs (avcodec/avutil/swscale/...) laid down next to the exe - the AMD/Intel
|
; 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-
|
; (AMF/QSV) encode backend link-imports them, so the exe won't start without them. NVENC/software-
|
||||||
; only builds simply omit this block.
|
; only builds simply omit this block. These are unmodified BtbN *lgpl-shared* builds, linked
|
||||||
|
; dynamically (replaceable DLLs) - FFmpeg is used under the LGPL v2.1+; see {app}\licenses.
|
||||||
Source: "{#FfmpegBin}\*.dll"; DestDir: "{app}"; Flags: ignoreversion
|
Source: "{#FfmpegBin}\*.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
#endif
|
#endif
|
||||||
#ifdef WithWeb
|
#ifdef WithWeb
|
||||||
|
|||||||
@@ -102,22 +102,35 @@ if (Test-Path $rustup) {
|
|||||||
& $rustup target add aarch64-pc-windows-msvc
|
& $rustup target add aarch64-pc-windows-msvc
|
||||||
} else { Write-Warning "rustup not found - install rustup then re-run (needed for the aarch64 target)." }
|
} else { Write-Warning "rustup not found - install rustup then re-run (needed for the aarch64 target)." }
|
||||||
|
|
||||||
$ffArm = "C:\Users\Public\ffmpeg-arm64"
|
# FFmpeg shared trees for the host (amf-qsv encode) + clients (decode). We use BtbN **lgpl-shared**
|
||||||
if (-not (Test-Path (Join-Path $ffArm 'lib\avcodec.lib'))) {
|
# builds: the AMD/Intel AMF + Intel QSV encoders, swscale, and the HEVC decoder are all present in the
|
||||||
# BtbN winarm64 shared, FFmpeg 7.x (avcodec-61) to match the x64 tree's ABI. MSVC-linkable .lib
|
# LGPL build, and punktfunk never calls the GPL-only encoders (x264/x265 — software encode is the
|
||||||
# import libs + headers + bin\*.dll — exactly what ffmpeg-sys-next + pack-msix.ps1 consume.
|
# separate BSD-2 openh264 crate; NVENC is the direct NVIDIA SDK). lgpl-shared keeps the bundled DLLs
|
||||||
Write-Host "==> fetching ARM64 FFmpeg (BtbN winarm64 shared)"
|
# LGPL-2.1+ (dynamic linking satisfies the relink duty) rather than GPL, so the shipped installer/MSIX
|
||||||
$ffUrl = 'https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-n7.1-latest-winarm64-gpl-shared-7.1.zip'
|
# stay consistent with punktfunk's MIT OR Apache-2.0 posture.
|
||||||
$ffZip = "C:\Users\Public\ffmpeg-arm64.zip"
|
# MIGRATION: a runner previously provisioned with the old *gpl-shared* trees must be re-provisioned —
|
||||||
$ffTmp = "C:\Users\Public\ffmpeg-arm64-extract"
|
# delete C:\Users\Public\ffmpeg and C:\Users\Public\ffmpeg-arm64, then re-run this script.
|
||||||
Invoke-WebRequest -Uri $ffUrl -OutFile $ffZip -UseBasicParsing
|
function Get-BtbnFfmpeg {
|
||||||
if (Test-Path $ffTmp) { Remove-Item -Recurse -Force $ffTmp }
|
param([string]$Dir, [string]$ZipTag) # ZipTag: 'win64' (x64) or 'winarm64' (ARM64 cross tree)
|
||||||
Expand-Archive -Path $ffZip -DestinationPath $ffTmp -Force # BtbN zips have one top-level folder
|
if (Test-Path (Join-Path $Dir 'lib\avcodec.lib')) { return }
|
||||||
$inner = Get-ChildItem $ffTmp -Directory | Select-Object -First 1
|
# FFmpeg 7.x (avcodec-61); MSVC-linkable .lib import libs + headers + bin\*.dll — exactly what
|
||||||
if (Test-Path $ffArm) { Remove-Item -Recurse -Force $ffArm }
|
# ffmpeg-sys-next + pack-host-installer.ps1 + pack-msix.ps1 consume. The extracted top-level folder
|
||||||
Move-Item -Path $inner.FullName -Destination $ffArm
|
# also carries FFmpeg's own LICENSE/COPYING text, preserved in $Dir for the packagers to bundle.
|
||||||
Remove-Item -Force $ffZip; Remove-Item -Recurse -Force $ffTmp -ErrorAction SilentlyContinue
|
Write-Host "==> fetching FFmpeg ($ZipTag, BtbN lgpl-shared)"
|
||||||
|
$url = "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-n7.1-latest-$ZipTag-lgpl-shared-7.1.zip"
|
||||||
|
$zip = "$Dir.zip"; $tmp = "$Dir-extract"
|
||||||
|
Invoke-WebRequest -Uri $url -OutFile $zip -UseBasicParsing
|
||||||
|
if (Test-Path $tmp) { Remove-Item -Recurse -Force $tmp }
|
||||||
|
Expand-Archive -Path $zip -DestinationPath $tmp -Force # BtbN zips have one top-level folder
|
||||||
|
$inner = Get-ChildItem $tmp -Directory | Select-Object -First 1
|
||||||
|
if (Test-Path $Dir) { Remove-Item -Recurse -Force $Dir }
|
||||||
|
Move-Item -Path $inner.FullName -Destination $Dir
|
||||||
|
Remove-Item -Force $zip; Remove-Item -Recurse -Force $tmp -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
# x64 host+client tree (the workflow's default FFMPEG_DIR = C:\Users\Public\ffmpeg) and the ARM64 cross
|
||||||
|
# tree (the aarch64 leg points FFMPEG_DIR at C:\Users\Public\ffmpeg-arm64).
|
||||||
|
Get-BtbnFfmpeg -Dir "C:\Users\Public\ffmpeg" -ZipTag 'win64'
|
||||||
|
Get-BtbnFfmpeg -Dir "C:\Users\Public\ffmpeg-arm64" -ZipTag 'winarm64'
|
||||||
|
|
||||||
# Inno Setup (ISCC.exe) for the host installer build (windows-host.yml). pack-host-installer.ps1
|
# Inno Setup (ISCC.exe) for the host installer build (windows-host.yml). pack-host-installer.ps1
|
||||||
# locates it at its fixed Program Files path, so it need not be on PATH — just present.
|
# locates it at its fixed Program Files path, so it need not be on PATH — just present.
|
||||||
|
|||||||
Executable
+134
@@ -0,0 +1,134 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Generate THIRD-PARTY-NOTICES.txt for the Rust workspace.
|
||||||
|
|
||||||
|
Offline, dependency-free attribution generator. It reads `cargo metadata`, then for every
|
||||||
|
third-party crate (everything that is NOT a first-party workspace member) it pulls the crate's
|
||||||
|
*actual* LICENSE/COPYING/NOTICE text out of the local cargo registry cache (or the in-tree
|
||||||
|
vendored source for path deps), deduplicates identical license texts, and emits a single
|
||||||
|
notices file: a per-crate manifest followed by the verbatim license texts.
|
||||||
|
|
||||||
|
This satisfies the binary-distribution attribution duty for the permissive (MIT/BSD/ISC/Zlib/
|
||||||
|
Apache/Unicode/etc.) crates linked into shipped punktfunk artifacts. `cargo about` (see
|
||||||
|
about.toml) produces an equivalent, network-augmented result in CI; this is the dependency-free
|
||||||
|
fallback that also runs locally and is committed as a baseline.
|
||||||
|
|
||||||
|
Usage: python3 scripts/gen-third-party-notices.py [--out THIRD-PARTY-NOTICES.txt]
|
||||||
|
"""
|
||||||
|
import argparse
|
||||||
|
import hashlib
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
LICENSE_GLOBS = ("license", "licence", "copying", "notice", "unlicense", "copyright")
|
||||||
|
|
||||||
|
|
||||||
|
def find_license_files(pkg_dir):
|
||||||
|
out = []
|
||||||
|
try:
|
||||||
|
names = sorted(os.listdir(pkg_dir))
|
||||||
|
except OSError:
|
||||||
|
return out
|
||||||
|
for n in names:
|
||||||
|
low = n.lower()
|
||||||
|
if any(low == g or low.startswith(g + ".") or low.startswith(g + "-") or g in low for g in LICENSE_GLOBS):
|
||||||
|
p = os.path.join(pkg_dir, n)
|
||||||
|
if os.path.isfile(p):
|
||||||
|
try:
|
||||||
|
with open(p, "r", encoding="utf-8", errors="replace") as f:
|
||||||
|
txt = f.read().strip()
|
||||||
|
if txt:
|
||||||
|
out.append((n, txt))
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
ap = argparse.ArgumentParser()
|
||||||
|
ap.add_argument("--out", default="THIRD-PARTY-NOTICES.txt")
|
||||||
|
ap.add_argument("--manifest", default="Cargo.toml")
|
||||||
|
args = ap.parse_args()
|
||||||
|
|
||||||
|
meta = json.loads(subprocess.check_output(
|
||||||
|
["cargo", "metadata", "--format-version", "1", "--offline", "--manifest-path", args.manifest],
|
||||||
|
text=True))
|
||||||
|
ws_members = set(meta.get("workspace_members", []))
|
||||||
|
|
||||||
|
pkgs = []
|
||||||
|
for p in meta["packages"]:
|
||||||
|
if p["id"] in ws_members:
|
||||||
|
continue # first-party (covered by the root LICENSE-MIT / LICENSE-APACHE)
|
||||||
|
pkgs.append(p)
|
||||||
|
pkgs.sort(key=lambda p: (p["name"].lower(), p["version"]))
|
||||||
|
|
||||||
|
# Group license texts: text-hash -> {text, name, crates[]}
|
||||||
|
texts = {}
|
||||||
|
no_text = []
|
||||||
|
for p in pkgs:
|
||||||
|
pkg_dir = os.path.dirname(p["manifest_path"])
|
||||||
|
files = find_license_files(pkg_dir)
|
||||||
|
label = f'{p["name"]} {p["version"]}'
|
||||||
|
if not files:
|
||||||
|
no_text.append(p)
|
||||||
|
continue
|
||||||
|
for fname, txt in files:
|
||||||
|
h = hashlib.sha256(txt.encode("utf-8", "replace")).hexdigest()
|
||||||
|
ent = texts.setdefault(h, {"text": txt, "filename": fname, "crates": set()})
|
||||||
|
ent["crates"].add(label)
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
w = lines.append
|
||||||
|
w("THIRD-PARTY SOFTWARE NOTICES")
|
||||||
|
w("=" * 76)
|
||||||
|
w("")
|
||||||
|
w("punktfunk (https://git.unom.io/unom/punktfunk) is licensed under MIT OR Apache-2.0.")
|
||||||
|
w("The binaries it ships statically/dynamically link the third-party Rust crates listed")
|
||||||
|
w("below. Each is distributed under its own permissive license; the full license texts")
|
||||||
|
w("follow the manifest. This file is generated by scripts/gen-third-party-notices.py")
|
||||||
|
w("(or `cargo about`, see about.toml) — do not edit by hand.")
|
||||||
|
w("")
|
||||||
|
w(f"Total third-party crates: {len(pkgs)}")
|
||||||
|
w("")
|
||||||
|
w("-" * 76)
|
||||||
|
w("MANIFEST (crate version — SPDX license — source)")
|
||||||
|
w("-" * 76)
|
||||||
|
for p in pkgs:
|
||||||
|
lic = p.get("license") or (("file: " + p["license_file"]) if p.get("license_file") else "UNKNOWN")
|
||||||
|
repo = p.get("repository") or ""
|
||||||
|
w(f' {p["name"]} {p["version"]} — {lic}' + (f' — {repo}' if repo else ""))
|
||||||
|
w("")
|
||||||
|
|
||||||
|
if no_text:
|
||||||
|
w("-" * 76)
|
||||||
|
w("Crates whose package did not embed a license file (SPDX + source only)")
|
||||||
|
w("-" * 76)
|
||||||
|
for p in no_text:
|
||||||
|
lic = p.get("license") or "UNKNOWN"
|
||||||
|
repo = p.get("repository") or ""
|
||||||
|
w(f' {p["name"]} {p["version"]} — {lic}' + (f' — {repo}' if repo else ""))
|
||||||
|
w("")
|
||||||
|
|
||||||
|
w("=" * 76)
|
||||||
|
w("FULL LICENSE TEXTS (deduplicated)")
|
||||||
|
w("=" * 76)
|
||||||
|
# Stable order: by first crate name covered.
|
||||||
|
for h, ent in sorted(texts.items(), key=lambda kv: sorted(kv[1]["crates"])[0].lower()):
|
||||||
|
crates = ", ".join(sorted(ent["crates"]))
|
||||||
|
w("")
|
||||||
|
w("-" * 76)
|
||||||
|
w(f"The following license ({ent['filename']}) applies to: {crates}")
|
||||||
|
w("-" * 76)
|
||||||
|
w(ent["text"])
|
||||||
|
w("")
|
||||||
|
|
||||||
|
text = "\n".join(lines) + "\n"
|
||||||
|
with open(args.out, "w", encoding="utf-8") as f:
|
||||||
|
f.write(text)
|
||||||
|
print(f"wrote {args.out}: {len(pkgs)} crates, {len(texts)} distinct license texts, "
|
||||||
|
f"{len(no_text)} without embedded text", file=sys.stderr)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Executable
+21
@@ -0,0 +1,21 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Regenerate THIRD-PARTY-NOTICES.txt for the Rust workspace.
|
||||||
|
#
|
||||||
|
# Prefers `cargo about` (full, network-augmented license harvest; see about.toml) and falls back to
|
||||||
|
# the dependency-free offline generator (scripts/gen-third-party-notices.py, reads the cargo registry
|
||||||
|
# cache). Run this when the dependency tree changes; CI also runs it before packaging.
|
||||||
|
#
|
||||||
|
# Usage: scripts/gen-third-party-notices.sh [output-file]
|
||||||
|
set -euo pipefail
|
||||||
|
cd "$(dirname "$0")/.."
|
||||||
|
OUT="${1:-THIRD-PARTY-NOTICES.txt}"
|
||||||
|
|
||||||
|
if command -v cargo-about >/dev/null 2>&1; then
|
||||||
|
echo "==> cargo about generate -> $OUT" >&2
|
||||||
|
cargo about generate about.hbs --output-file "$OUT"
|
||||||
|
else
|
||||||
|
echo "==> cargo-about not installed; using offline fallback" >&2
|
||||||
|
echo " (install the full generator with: cargo install cargo-about)" >&2
|
||||||
|
python3 scripts/gen-third-party-notices.py --out "$OUT"
|
||||||
|
fi
|
||||||
|
echo "==> wrote $OUT" >&2
|
||||||
Reference in New Issue
Block a user