feat(presenter,docs): PyroWave mid-stream resize — HUD follows any mode switch; docs
ci / web (push) Successful in 52s
ci / docs-site (push) Successful in 54s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 8s
decky / build-publish (push) Successful in 17s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 8s
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 9s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 44s
ci / bench (push) Successful in 5m47s
flatpak / build-publish (push) Failing after 8m11s
docker / deploy-docs (push) Successful in 27s
arch / build-publish (push) Successful in 10m58s
deb / build-publish (push) Successful in 12m26s
android / android (push) Successful in 16m59s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 12m16s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 17m59s
ci / rust (push) Successful in 24m26s
windows-host / package (push) Failing after 12m3s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 3m50s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 4m16s
apple / swift (push) Successful in 4m57s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 5m14s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 6m3s
release / apple (push) Successful in 25m6s
apple / screenshots (push) Has been cancelled
ci / web (push) Successful in 52s
ci / docs-site (push) Successful in 54s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 8s
decky / build-publish (push) Successful in 17s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 8s
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 9s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 44s
ci / bench (push) Successful in 5m47s
flatpak / build-publish (push) Failing after 8m11s
docker / deploy-docs (push) Successful in 27s
arch / build-publish (push) Successful in 10m58s
deb / build-publish (push) Successful in 12m26s
android / android (push) Successful in 16m59s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 12m16s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 17m59s
ci / rust (push) Successful in 24m26s
windows-host / package (push) Failing after 12m3s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 3m50s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 4m16s
apple / swift (push) Successful in 4m57s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 5m14s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 6m3s
release / apple (push) Successful in 25m6s
apple / screenshots (push) Has been cancelled
- pf-presenter: the HUD/title mode line lived inside the match-window (D2)
gate, so an accepted switch from any OTHER trigger (the
PUNKTFUNK_DEBUG_RECONFIGURE lever, a host-side corrective rollback) left the
label stale. Hoisted into its own per-iteration tick that runs whenever a
stream is up.
- docs: pyrowave.md — the Automatic bitrate pin now follows a mid-stream
resize; drop the "resolution changes rebuild the stream" limitation.
Completes the resize-rebuild work whose core landed in 9127c346
(video_pyrowave.rs sequence-header dims sniff + in-place decoder/plane-ring
rebuild with retired-ring lifetime handling, host per-mode ~1.6 bpp re-pin,
128px floor, debug reconfigure lever). On-glass validated on .21
(RTX 5070 Ti, Mutter virtual display): 1080p->720p and 1080p->1440p
mid-stream switches, lossless AND under 2% netem loss — decoder rebuilt in
place, 60 fps sustained (partials during loss), pinned rate re-resolved
199065->88473 / ->353894 kbps, HUD flips to the new mode.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -880,10 +880,16 @@ fn run_inner(mut opts: SessionOpts, mut mode: ModeCtl) -> Result<Option<Outcome>
|
||||
}
|
||||
}
|
||||
|
||||
// --- Match-window (D2): debounced mode-follow + HUD/title refresh on a switch ----
|
||||
// HUD/title follow the live mode slot on ANY accepted switch — also when the
|
||||
// match-window follower is off (a switch can come from elsewhere, e.g. the
|
||||
// PUNKTFUNK_DEBUG_RECONFIGURE lever, or a host-side corrective rollback).
|
||||
if let Some(st) = stream.as_mut() {
|
||||
hud_mode_tick(st, &mut window, &opts.window_title);
|
||||
}
|
||||
// --- Match-window (D2): debounced mode-follow ----
|
||||
if let Some(persist) = opts.match_window.as_mut() {
|
||||
if let Some(st) = stream.as_mut() {
|
||||
resize_tick(st, &mut window, &opts.window_title, persist.as_mut());
|
||||
resize_tick(st, &mut window, persist.as_mut());
|
||||
}
|
||||
}
|
||||
// Resize overlay timeout: a switch the host rejected/capped never delivers the exact
|
||||
@@ -1201,10 +1207,23 @@ fn apply_match_window(params: &mut SessionParams, window: &sdl3::video::Window)
|
||||
);
|
||||
}
|
||||
|
||||
/// Match-window (D2) per-iteration tick: refresh the HUD line + window title when the
|
||||
/// live mode moves (an accepted switch's ack, or a corrective rollback), then fire the
|
||||
/// debounced `Reconfigure` once ~400 ms pass with no further resize events. The shared
|
||||
/// trigger discipline:
|
||||
/// Per-iteration HUD/title refresh: follow the live mode slot (updated by any accepted
|
||||
/// ack — a follower request, another trigger, or a host-side corrective rollback).
|
||||
fn hud_mode_tick(st: &mut StreamState, window: &mut sdl3::video::Window, title_base: &str) {
|
||||
let Some(c) = &st.connector else {
|
||||
return;
|
||||
};
|
||||
let m = c.mode();
|
||||
if st.shown_mode.is_some_and(|prev| prev != m) {
|
||||
st.mode_line = format!("{}×{}@{}", m.width, m.height, m.refresh_hz);
|
||||
tracing::info!(mode = %st.mode_line, "stream mode switched");
|
||||
let _ = window.set_title(&format!("{title_base} · {}", st.mode_line));
|
||||
}
|
||||
st.shown_mode = Some(m);
|
||||
}
|
||||
|
||||
/// Match-window (D2) per-iteration tick: fire the debounced `Reconfigure` once ~400 ms
|
||||
/// pass with no further resize events. The shared trigger discipline:
|
||||
/// * physical pixels, even-floored, clamped ≥ 320×200; the current refresh is kept;
|
||||
/// * ≥ 1 s between requests (the accept ack round-trips in milliseconds — it precedes
|
||||
/// the host's rebuild — so the spacing also keeps at most ~one request outstanding);
|
||||
@@ -1214,21 +1233,12 @@ fn apply_match_window(params: &mut SessionParams, window: &sdl3::video::Window)
|
||||
fn resize_tick(
|
||||
st: &mut StreamState,
|
||||
window: &mut sdl3::video::Window,
|
||||
title_base: &str,
|
||||
persist: &mut dyn FnMut(u32, u32),
|
||||
) {
|
||||
let Some(c) = &st.connector else {
|
||||
return; // not connected yet — the pending stamp survives until we are
|
||||
};
|
||||
// HUD/title follow the live mode slot (updated by any accepted ack).
|
||||
let m = c.mode();
|
||||
if st.shown_mode.is_some_and(|prev| prev != m) {
|
||||
st.mode_line = format!("{}×{}@{}", m.width, m.height, m.refresh_hz);
|
||||
tracing::info!(mode = %st.mode_line, "stream mode switched");
|
||||
let _ = window.set_title(&format!("{title_base} · {}", st.mode_line));
|
||||
}
|
||||
st.shown_mode = Some(m);
|
||||
|
||||
match resize_decision(
|
||||
Instant::now(),
|
||||
&mut st.resize_pending,
|
||||
|
||||
@@ -54,6 +54,8 @@ setting.
|
||||
your mode (≈200 Mbps at 1080p60). An explicit bitrate is honored if you set one, but the
|
||||
adaptive-bitrate controller stays off either way — this codec has no useful low-rate
|
||||
regime, so under sustained loss the right move is switching back to HEVC, not degrading.
|
||||
The pin follows the resolution: a mid-stream resize (e.g. Match window) re-pins the rate
|
||||
for the new mode, so resizing a window down also cuts the bandwidth.
|
||||
|
||||
The stats overlay shows `pyrowave` as the decode path when the mode is active.
|
||||
|
||||
@@ -62,4 +64,3 @@ The stats overlay shows `pyrowave` as the decode path when the mode is active.
|
||||
- Linux host + Linux client (including docked Deck) today; the Windows host and the Apple
|
||||
native port are tracked on the [roadmap](/docs/roadmap).
|
||||
- 8-bit SDR, 4:2:0 only.
|
||||
- Mid-stream resolution changes rebuild the stream rather than switching seamlessly.
|
||||
|
||||
Reference in New Issue
Block a user