diff --git a/crates/punktfunk-host/src/encode/vaapi.rs b/crates/punktfunk-host/src/encode/vaapi.rs
index 18a593a..837d6eb 100644
--- a/crates/punktfunk-host/src/encode/vaapi.rs
+++ b/crates/punktfunk-host/src/encode/vaapi.rs
@@ -134,11 +134,19 @@ pub fn probe_can_encode(codec: Codec) -> bool {
return false;
}
unsafe {
- let hw = match VaapiHw::new(ffi::AVPixelFormat::AV_PIX_FMT_NV12, 640, 480, 2) {
- Ok(hw) => hw,
- Err(_) => return false,
+ // A missing VA device (non-VAAPI host, GPU-less CI) is an expected probe outcome — quiet
+ // ffmpeg's "No VA display found" error for the probe, then restore the level.
+ let prev = ffi::av_log_get_level();
+ ffi::av_log_set_level(ffi::AV_LOG_FATAL);
+ let ok = match VaapiHw::new(ffi::AVPixelFormat::AV_PIX_FMT_NV12, 640, 480, 2) {
+ Ok(hw) => {
+ open_vaapi_encoder(codec, 640, 480, 30, 2_000_000, hw.device_ref, hw.frames_ref)
+ .is_ok()
+ }
+ Err(_) => false,
};
- open_vaapi_encoder(codec, 640, 480, 30, 2_000_000, hw.device_ref, hw.frames_ref).is_ok()
+ ffi::av_log_set_level(prev);
+ ok
}
}
diff --git a/crates/punktfunk-host/src/gamestream/serverinfo.rs b/crates/punktfunk-host/src/gamestream/serverinfo.rs
index f90d4f4..b75f4f9 100644
--- a/crates/punktfunk-host/src/gamestream/serverinfo.rs
+++ b/crates/punktfunk-host/src/gamestream/serverinfo.rs
@@ -61,7 +61,13 @@ fn codec_mode_support() -> u32 {
if caps.av1 {
m |= SCM_AV1_MAIN8;
}
- return m;
+ // Only trust a probe that actually found an encoder. An empty result means VAAPI wasn't
+ // usable at probe time (no VA display — a GPU-less CI box, or a misconfigured host), NOT
+ // that the GPU encodes nothing; advertise the static superset (pre-probe behaviour) rather
+ // than claiming zero codecs.
+ if m != 0 {
+ return m;
+ }
}
SERVER_CODEC_MODE_SUPPORT
}
@@ -99,6 +105,13 @@ mod tests {
https_port: 47984,
};
let xml = serverinfo_xml(&host, false);
- assert!(xml.contains("65793"));
+ // The mask is the GPU-aware value (NVENC/no-GPU → the static 65793; a VAAPI host →
+ // whatever it probes). Assert the XML embeds exactly what `codec_mode_support()` returns,
+ // so the test is deterministic regardless of the build host's GPU.
+ let mask = codec_mode_support();
+ assert!(mask != 0, "must advertise at least one codec");
+ assert!(xml.contains(&format!(
+ "{mask}"
+ )));
}
}