chore(encode/windows): AMF forensics knobs — PUNKTFUNK_AMF_USAGE + PUNKTFUNK_FFWIN_POLL_MS
apple / swift (push) Successful in 1m6s
ci / web (push) Successful in 53s
deb / build-publish (push) Failing after 44s
windows-host / package (push) Failing after 10s
ci / rust (push) Failing after 49s
android / android (push) Successful in 3m33s
apple / screenshots (push) Successful in 5m18s
ci / docs-site (push) Successful in 57s
decky / build-publish (push) Successful in 11s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 4s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
ci / bench (push) Successful in 5m0s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Failing after 3m27s
docker / deploy-docs (push) Successful in 18s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Failing after 3m18s

The blocking poll landed but wait_us pegs at exactly the 2-frame-period cap:
AMF holds the AU ~2 frame periods regardless of retrieval. Field knobs to
bisect on-box (usage preset × poll cap) without rebuild cycles.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-03 14:39:36 +00:00
parent 51a6ca7e02
commit 24fa018c70
@@ -215,7 +215,12 @@ unsafe fn open_win_encoder(
let mut opts = Dictionary::new(); let mut opts = Dictionary::new();
match vendor { match vendor {
WinVendor::Amf => { WinVendor::Amf => {
opts.set("usage", "ultralowlatency"); // Field-tuning override (ultralowlatency | lowlatency | lowlatency_high_quality |
// transcoding): AMF usage presets bundle driver-side pipeline behavior that varies by
// VCN generation/driver — measured on-box rather than assumed.
let usage =
std::env::var("PUNKTFUNK_AMF_USAGE").unwrap_or_else(|_| "ultralowlatency".into());
opts.set("usage", &usage);
opts.set("rc", "cbr"); opts.set("rc", "cbr");
// Streaming is latency-first: `speed` trims per-frame motion-estimation depth — the // Streaming is latency-first: `speed` trims per-frame motion-estimation depth — the
// difference between ~encode-time and ~frame-budget on iGPU-class VCN (matches the // difference between ~encode-time and ~frame-budget on iGPU-class VCN (matches the
@@ -1317,10 +1322,15 @@ impl Encoder for FfmpegWinEncoder {
Some(Inner::ZeroCopy(z)) => &mut z.enc, Some(Inner::ZeroCopy(z)) => &mut z.enc,
None => return Ok(None), None => return Ok(None),
}; };
let deadline = (self.in_flight > 0).then(|| { // Default cap: ~2 frame periods. `PUNKTFUNK_FFWIN_POLL_MS` overrides for on-box latency
std::time::Instant::now() // forensics (e.g. 150 to see WHEN the AU really lands vs. being gated on the next submit).
+ std::time::Duration::from_micros((2_000_000 / fps.max(1) as u64).max(10_000)) let cap_us = std::env::var("PUNKTFUNK_FFWIN_POLL_MS")
}); .ok()
.and_then(|s| s.parse::<u64>().ok())
.map(|ms| ms * 1000)
.unwrap_or_else(|| (2_000_000 / fps.max(1) as u64).max(10_000));
let deadline = (self.in_flight > 0)
.then(|| std::time::Instant::now() + std::time::Duration::from_micros(cap_us));
loop { loop {
match poll_encoder(enc, fps)? { match poll_encoder(enc, fps)? {
PollOutcome::Packet(au) => { PollOutcome::Packet(au) => {