fix(encode): classify libav-NVENC open failures by errno, not English strerror text
ci / docs-site (push) Successful in 58s
ci / web (push) Successful in 59s
apple / swift (push) Successful in 5m17s
ci / bench (push) Successful in 7m27s
deb / build-publish (push) Failing after 8m0s
ci / rust-arm64 (push) Failing after 9m1s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 12s
decky / build-publish (push) Successful in 22s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 13s
ci / rust (push) Failing after 9m31s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 10s
docker / build-push (ci, ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 9s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 10s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 11s
deb / build-publish-host (push) Successful in 10m23s
arch / build-publish (push) Successful in 12m54s
android / android (push) Successful in 15m8s
deb / build-publish-client-arm64 (push) Successful in 7m54s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Failing after 5m43s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Failing after 6m35s
windows-host / package (push) Successful in 19m10s
docker / build-push-arm64cross (push) Successful in 8s
docker / deploy-docs (push) Successful in 24s
apple / screenshots (push) Successful in 23m39s
ci / docs-site (push) Successful in 58s
ci / web (push) Successful in 59s
apple / swift (push) Successful in 5m17s
ci / bench (push) Successful in 7m27s
deb / build-publish (push) Failing after 8m0s
ci / rust-arm64 (push) Failing after 9m1s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 12s
decky / build-publish (push) Successful in 22s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 13s
ci / rust (push) Failing after 9m31s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 10s
docker / build-push (ci, ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 9s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 10s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 11s
deb / build-publish-host (push) Successful in 10m23s
arch / build-publish (push) Successful in 12m54s
android / android (push) Successful in 15m8s
deb / build-publish-client-arm64 (push) Successful in 7m54s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Failing after 5m43s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Failing after 6m35s
windows-host / package (push) Successful in 19m10s
docker / build-push-arm64cross (push) Successful in 8s
docker / deploy-docs (push) Successful in 24s
apple / screenshots (push) Successful in 23m39s
The bitrate-probe ladder stepped down on format!("{e:#}").contains(
"Invalid argument") — an English substring over the WHOLE context chain,
which also fired on any other wrapped EINVAL (e.g. a CUDA-context errno)
and gated a ~10-step ladder on strerror wording. The root ffmpeg::Error
survives the anyhow chain; downcast and match Error::Other{errno:EINVAL}
instead. Same fix for the intra-refresh ENOSYS probe in the open path.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -468,7 +468,15 @@ impl NvencEncoder {
|
||||
// sessions) and reopen this session without intra-refresh; any other failure — and
|
||||
// any failure when IR wasn't requested — propagates untouched (the bitrate probe
|
||||
// keys on EINVAL, which must not trip the latch).
|
||||
Err(e) if intra_refresh && format!("{e:#}").contains("Function not implemented") => {
|
||||
Err(e)
|
||||
if intra_refresh
|
||||
&& matches!(
|
||||
e,
|
||||
ffmpeg::Error::Other {
|
||||
errno: ffmpeg::util::error::ENOSYS
|
||||
}
|
||||
) =>
|
||||
{
|
||||
tracing::warn!(
|
||||
encoder = name,
|
||||
"NVENC intra-refresh not supported by this GPU — falling back to IDR-only \
|
||||
|
||||
@@ -897,13 +897,29 @@ fn open_nvenc_probed(
|
||||
}
|
||||
// EINVAL = above this GPU's level ceiling → step down. Any other failure (no GPU,
|
||||
// bad mode, OOM) is real — surface it rather than masking it with bitrate retries.
|
||||
Err(e) if format!("{e:#}").contains("Invalid argument") => last = Some(e),
|
||||
Err(e) if nvenc_open_einval(&e) => last = Some(e),
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
}
|
||||
Err(last.unwrap_or_else(|| anyhow::anyhow!("encoder open failed at every probed bitrate")))
|
||||
}
|
||||
|
||||
/// Whether a libav NVENC open failed with EINVAL — the "bitrate above this GPU's level ceiling"
|
||||
/// signal [`open_nvenc_probed`]'s ladder steps down on. Typed: the root `ffmpeg::Error` survives
|
||||
/// the `anyhow` context chain, so match it there instead of substring-matching the English
|
||||
/// strerror rendering of the whole chain — which also fired on any OTHER wrapped EINVAL (e.g. a
|
||||
/// CUDA-context errno) and steered the ladder on failures that have nothing to do with bitrate.
|
||||
#[cfg(target_os = "linux")]
|
||||
fn nvenc_open_einval(e: &anyhow::Error) -> bool {
|
||||
use ffmpeg_next as ffmpeg;
|
||||
matches!(
|
||||
e.downcast_ref::<ffmpeg::Error>(),
|
||||
Some(ffmpeg::Error::Other {
|
||||
errno: ffmpeg::util::error::EINVAL
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
/// Whether the direct-SDK NVENC path is active. **Default ON** — on-glass validated 2026-07-12:
|
||||
/// real RFI landed 73/73 as clean P-frame recovery anchors (never IDR) on an RTX host with a real
|
||||
/// Steam Deck client (design/linux-direct-nvenc.md §9). `PUNKTFUNK_NVENC_DIRECT=0` (also `false`/
|
||||
|
||||
Reference in New Issue
Block a user