aa45757a726a0b7dee3d31c2eb7a676b9b04094a
9 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
cab6350723 |
feat(client): shared clipboard on Windows
The protocol half has been in punktfunk-core since the clipboard work landed -- the per-session fetch task, plus clip_control/clip_offer/ clip_fetch/clip_serve/next_clip on NativeClient -- but only the Apple client ever drove it, through the C ABI. The Windows and Linux clients link the core directly and simply never wired it, so copy-paste between host and client worked on a Mac and nowhere else. This adds the missing half: the OS-clipboard bridge, on its own session thread beside the audio one. Local -> remote stays lazy by construction, as the design asks: a GetClipboardSequenceNumber poll spots a local copy and we announce only the FORMAT LIST; bytes are read when (and only when) the host actually pastes and sends a FetchRequest. Remote -> local is EAGER in this first cut, which is a deliberate deviation worth naming. macOS gets laziness free from NSPasteboardItemDataProvider; the Windows equivalent is delayed rendering, which needs a clipboard-owning window running its own message pump. So we fetch on the offer and place real bytes under a 4 MB cap -- text always crosses, a large image is skipped rather than pulled for a paste that may never come. Delayed rendering lifts the cap later. Echo suppression is the design's Windows rule verbatim (capture the sequence number right after our own SetClipboardData); without it every copy ping-pongs between the machines forever. Content marked ExcludeClipboardContentFromMonitorProcessing -- what password managers set -- is never announced and never served. Text and PNG for now. Apps that publish only CF_DIB need the conversion the host already has. Linux keeps a stub: the bridge itself is platform-neutral and will drive a data-control seam unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
1ef0229bd9 |
feat(client/windows): PyroWave decode + surface it in the GUI codec picker
The decoder was gated to Linux because, when it landed, the Windows client still had its own in-process WinUI/D3D11 presenter and the PyroWave present path there was an open question. That client has since been retired: Windows now spawns the SAME Vulkan session presenter as Linux, and the decoder is plain Vulkan compute on the presenter's device (no fds, no dmabuf, no D3D11 interop), so the question that gated it answered itself. pyrowave-sys already builds on Windows too -- the Windows HOST encoder ships on it. So this is a port by un-gating: every cfg(all(target_os = "linux", feature = "pyrowave")) becomes any(linux, windows) -- decoder module, backend variant, Decoder::new_pyrowave, the CODEC_PYROWAVE advertisement, the session pump's opt-in/build/label arms, and the presenter's planar CSC pass. No new code. Then offer it in the Windows GUI, which is what prompted this. It stays preference-only (resolve_codec never auto-picks it) and a host or device that can't do PyroWave just falls back down the ladder to HEVC. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
4d2632a845 |
fix(client/deps): ring-only rustls in pf-client-core — finish dropping aws-lc-sys
apple / swift (push) Successful in 1m25s
audit / bun-audit (push) Successful in 16s
ci / web (push) Successful in 48s
ci / docs-site (push) Successful in 57s
audit / cargo-audit (push) Successful in 2m30s
ci / bench (push) Successful in 6m1s
android-screenshots / screenshots (push) Successful in 3m59s
apple / screenshots (push) Successful in 6m27s
decky / build-publish (push) Successful in 24s
ci / rust (push) Failing after 17m36s
linux-client-screenshots / screenshots (push) Successful in 7m54s
arch / build-publish (push) Successful in 13m5s
android / android (push) Successful in 13m44s
release / apple (push) Successful in 10m22s
deb / build-publish (push) Successful in 13m42s
web-screenshots / screenshots (push) Successful in 2m47s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 15m46s
docker / deploy-docs (push) Successful in 11s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 13s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 12s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 12s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 12s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 11s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 15m2s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 8m21s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 9m18s
windows-host / package (push) Successful in 20m17s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 7m5s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 7m17s
flatpak / build-publish (push) Successful in 6m2s
Companion to the host ring fix: pf-client-core declared rustls with features=["ring"] but WITHOUT default-features=false, so rustls's default aws-lc-rs backend came along too (feature tree: aws-lc-rs <- rustls default <- pf-client-core default) — pulling aws-lc-sys 0.41.0 into the Windows client + session + presenter builds, the same C dep that fails on the CI runner. Pin default-features=false + [ring, logging, std, tls12] (matching the tray/host/core pattern). aws-lc-sys now gone from EVERY windows-built crate (host, client-windows, client-session, tray — all 'cargo tree -i aws-lc-sys' => no match). Code already used rustls::crypto::ring::default_provider (library.rs); no behaviour change. Validated: cargo tree (all 4 windows crates aws-lc-free) + .21 clippy -D warnings (pf-client-core, pf-presenter, punktfunk-client-session) clean. |
||
|
|
f24379c2f8 |
feat(host,clients): PyroWave ships in default builds; NVIDIA hosts advertise it
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 4m7s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 4m14s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 5m16s
ci / web (push) Successful in 55s
ci / docs-site (push) Successful in 1m7s
decky / build-publish (push) Successful in 19s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 9s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 9s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 8s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 7s
android / android (push) Successful in 12m17s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 51s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 6m28s
arch / build-publish (push) Successful in 13m54s
ci / bench (push) Successful in 6m18s
docker / deploy-docs (push) Successful in 22s
flatpak / build-publish (push) Successful in 6m50s
apple / swift (push) Successful in 5m8s
deb / build-publish (push) Successful in 12m0s
ci / rust (push) Successful in 24m15s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 13m2s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 14m29s
windows-host / package (push) Successful in 16m45s
apple / screenshots (push) Successful in 23m19s
Flip the `pyrowave` cargo feature into the default set across punktfunk-host, pf-client-core, pf-presenter and the session client — every packaged build (flatpak, arch/rpm/copr, windows x64 client) now carries the codec. Selection stays strictly per-session opt-in: a client must pick "PyroWave (wired LAN)" in Settings (or PUNKTFUNK_PREFER_PYROWAVE=1); nothing changes for normal HEVC/AV1 sessions. The Windows ARM64 client leg builds --no-default-features and keeps skipping it (decode is Linux-native + Apple Metal today). Advertisement no longer waits for the PUNKTFUNK_ENCODER=pyrowave lab override on NVIDIA: host_wire_caps sets the bit whenever the feature is present and the host isn't the GPU-less software pref, and SessionPlan::output_format flips a PyroWave session on the NVIDIA-auto capture path to CPU RGB frames (the EGL→CUDA import only NVENC consumes; the wavelet backend ingests raw dmabufs or CPU RGB). AMD/Intel keep their raw-dmabuf zero-copy unchanged; per-session raw-dmabuf passthrough on NVIDIA (true zero-copy without the env's global capture policy) stays a follow-up. On-glass on .21 (RTX 5070 Ti, default-features binaries, NO env overrides): host advertises + negotiates PyroWave, the CPU-capture fallback engages, 60 fps at e2e 3.2-5.7 ms p50, and a mid-stream 1080p→720p resize rides on top cleanly. Workspace clippy --locked clean; 33 client + 314 host tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
575975687c |
feat(client): PyroWave decode backend on the presenter's device (Phase 2b, part 1)
ci / web (push) Successful in 55s
ci / docs-site (push) Successful in 1m2s
ci / rust (push) Failing after 4m1s
decky / build-publish (push) Successful in 18s
arch / build-publish (push) Failing after 4m45s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 9s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 9s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 8s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 8s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 7s
deb / build-publish (push) Failing after 4m46s
ci / bench (push) Successful in 5m12s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Failing after 3m47s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Failing after 4m39s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 3m41s
flatpak / build-publish (push) Successful in 6m20s
android / android (push) Successful in 13m47s
docker / deploy-docs (push) Successful in 28s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 3m59s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 4m55s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 6m50s
apple / swift (push) Successful in 4m45s
apple / screenshots (push) Successful in 20m33s
The presenter's device creation now probes + enables the PyroWave compute feature set alongside the Vulkan Video probe (shaderInt16, storageBuffer8BitAccess, subgroup size control — gated on support, harmless when unused) and exports the facts through VulkanDecodeDevice (pyrowave_decode capability + feature bools + apiVersion + the queue- family shape). pf-client-core (feature `pyrowave`, Linux): video_pyrowave.rs — the decoder runs pyrowave compute on the PRESENTER's own VkDevice, zero interop (plan §4.5): pinned content-equivalent create-info reconstruction satisfies pyrowave 0.4.0's lifetime rule without refactoring the presenter's creation; queue access rides the existing device-wide QueueLock (the FFmpeg/Skia contract); decode records into our command buffer, fence-synchronous (sub-ms), into a 4-deep ring of 3xR8 plane sets (decode REQUIRES storage usage + identity swizzles, so the encoder's RG8 trick doesn't apply). Backend::PyroWave + DecodedImage::PyroWave + Decoder::new_pyrowave + decodable_codecs_for (advertisement gated on the device probe) wired through the decode dispatch; no demote ladder (nothing else decodes it — fallback is session renegotiation, plan §4.6). Still to come for a live session: the presenter's planar-CSC render path for the new variant, pump/shell opt-in (preferred_codec) wiring, and the on-glass .21 run. Validated on .21: pf-client-core + pf-presenter compile with and without the feature, clippy clean, 26 client-core tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
a69a83b545 |
feat(clients/windows): D3D11VA hardware decode in the session client — Vulkan chain becomes vulkan → d3d11va → software
The vendor-agnostic DXVA path for GPUs without Vulkan Video (Intel's Windows driver foremost, which previously landed on CPU decode). Ported from the retired WinUI presenter's decoder with its Intel-safe discipline intact (decode pool stays libavcodec-derived — a hand-built pool broke Intel at the first SubmitDecoderBuffers), on a decode device LUID-matched to the presenter's adapter. Hand-off is a ring of shareable BGRA8 textures (SHARED_NTHANDLE | SHARED_KEYEDMUTEX) filled by the fixed-function ID3D11VideoProcessor (NV12/P010 → BGRA8, colour spaces from the per-frame CICP; PQ is tone-mapped to SDR by the processor — HDR-first boxes take Vulkan Video). BGRA is deliberate: importing a multiplanar NV12 D3D11 texture device-losts on NVIDIA however it is consumed (plane-view sampling and DMA copy both validation-clean, both TDR — bisected), while single-plane RGBA D3D11↔Vulkan interop is the path Chromium/ANGLE exercise on every driver. The presenter imports a slot's NT handle per frame (VK_KHR_external_memory_win32, gated on the spec-required external-format probe) and blits it into the video image — no CSC pass; the DXGI keyed mutex (key 0 both sides, drop-tolerant) is the cross-API lock and visibility barrier. Verified live vs a real host at 5120x1440@240 HEVC on an RTX 4090: 240 fps, e2e 2.7/3.0 ms p50/p95 under the Khronos validation layer — parity with Vulkan Video (2.6 ms); auto still resolves vulkan on NVIDIA. PUNKTFUNK_DECODER=d3d11va forces it; import/present failures demote to software on the existing streak contract. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
d6647b9183 |
feat(clients/windows): port the Vulkan session client to Windows — session-always
The punktfunk-session Vulkan client (clients/linux-session, now clients/session) builds and runs on Windows; the WinUI shell spawns it for every stream. Verified live: 10-bit HEVC via Vulkan Video on both AMD (iGPU) and NVIDIA, 5120x1440 at 130 fps / 8 ms end-to-end on the RTX 4090. - pf-ffvk: Windows bindgen branch (FFMPEG_DIR + PF_FFVK_VULKAN_INCLUDE, no pkg-config); provisioning fetches Vulkan-Headers (pinned v1.4.309). - pf-client-core: builds on Windows — WASAPI audio (audio_wasapi.rs, cfg-swapped via #[path], same surface as the PipeWire twin), VAAPI/dmabuf gated inline (chain = vulkan -> software), trust reads the WinUI shell's %APPDATA% stores (parity tests pin both serialized shapes), Settings gains adapter/hdr_enabled (serde-defaulted; Linux stores unaffected). - pf-presenter: builds on Windows — dmabuf module Linux-gated; SDL keyboard grab while captured (Alt+Tab/Win reach the host); pick_device ranks discrete over integrated (device 0 was the iGPU on hybrid boxes — the silent footgun) and honors PUNKTFUNK_VK_ADAPTER (the Settings GPU pick, exported by the session). - run loop: block in one SDL wait woken by input AND decoded frames (a per- session forwarder pushes a FrameWake user event) instead of a 1 ms poll — measured 111%% -> 5%% of a core (NVIDIA), 86%% -> 3.5%% (AMD), stats unchanged. The pump's decode-fence wait became once-per-window sampling (no per-frame pipeline stall; the stat now shows true backlog). - pf-console-ui: builds on Windows (skia-safe msvc prebuilts); font lookup falls through fontconfig aliases to concrete DirectWrite families (Consolas/Segoe UI) — browse/coverflow works, verified against a live host. - WinUI shell: session-always via new src/spawn.rs (GTK spawn.rs port — CREATE_NO_WINDOW, stdout contract, kill handle); the Stream screen is a status card (chips + stage lines from the child's stats). The legacy in-process D3D11VA path stays behind Settings "Streaming engine" / PUNKTFUNK_BUILTIN_ STREAM=1 as the A/B baseline until Phase 8 deletes it. SessionParams.video_caps makes the HDR toggle real. - clients/linux-session renamed to clients/session (builds for both OSes). - CI/MSIX: both workflows build/test both bins with widened path filters; the MSIX ships punktfunk-session.exe. ARM64 session builds --no-default-features (rust-skia has no aarch64-pc-windows-msvc prebuilts; flip when it does). A/B on this box (5120x1440 HEVC vs home-worker-5): NVIDIA Vulkan 130 fps / 8 ms e2e / 1.6 ms decode — clearly better than the built-in path. The AMD iGPU VCN saturates at ~52 fps where its own D3D11VA does ~70 — Adrenalin Vulkan decode is slower on APU silicon; discrete RDNA validation gates Phase 8. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
c78ddc40cb |
feat(video): Vulkan Video decode on the presenter's device (NVIDIA hw decode)
FFmpeg's Vulkan Video decoder now runs on the PRESENTER's own VkDevice — the decoded VkImage feeds the existing CICP CSC pass directly: zero copy, no interop, and NVIDIA gets hardware decode for the first time (its VAAPI is unusable by design). One decode architecture for every vendor going forward; VAAPI-dmabuf and software remain the fallbacks (auto: vulkan → vaapi → software; PUNKTFUNK_DECODER=vulkan pins it). Presenter: instance 1.3; probes VK_KHR_video_queue/decode_queue + codec extensions, a VIDEO_DECODE queue family (+ its codec caps via QueueFamilyVideoPropertiesKHR), and the samplerYcbcrConversion/ timelineSemaphore/synchronization2 features — all enabled at device creation when present, exported as a VulkanDecodeDevice handle bundle. Decoder: AVVulkanDeviceContext built over those handles via pf-ffvk (features chain, extension lists, deprecated queue indices + the qf[] map); get_format supplies OUR frames context with MUTABLE_FORMAT so the presenter's per-plane views are legal; output is DecodedImage::VkFrame carrying AVVkFrame/frames-ctx pointers plus the lock fns. Present: R8+R8G8 plane views over the multiplanar image, the live sync state read under the AVVulkanFramesContext lock, a timeline-semaphore wait(sem_value)/signal(sem_value+1) folded into the submit, layout/ queue-family/sem_value written back per FFmpeg's contract, and the frame guard parked in the retire queue until the fence. CSC pass + video framebuffer are now unconditional (NVIDIA has no dmabuf-import path). Verified on the RTX 5070 Ti: device creates with decode_qf=3, caps=DECODE_H264|H265|AV1|VP9; swapchain unaffected. Live stream validation next. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
0ab97b597c |
refactor(client): extract UI-agnostic plumbing into pf-client-core (phase 0)
Session pump, FFmpeg decode, PipeWire audio, SDL3 gamepads, keymap, trust store, mDNS discovery, library client and Wake-on-LAN move verbatim from clients/linux into crates/pf-client-core, shared with the upcoming Vulkan session binary (punktfunk-planning: linux-client-rearchitecture.md). The GTK client re-exports them at the crate root so every existing crate::-path keeps resolving; its manifest drops the moved-only deps. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |