fix: allow proven software HEVC handoff

This commit is contained in:
Brad Stein 2026-05-19 12:54:29 -03:00
parent 2d79a3144a
commit e4a4ca1c9d
7 changed files with 53 additions and 12 deletions

6
Cargo.lock generated
View File

@ -1658,7 +1658,7 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
[[package]]
name = "lesavka_client"
version = "0.26.0"
version = "0.26.1"
dependencies = [
"anyhow",
"async-stream",
@ -1692,7 +1692,7 @@ dependencies = [
[[package]]
name = "lesavka_common"
version = "0.26.0"
version = "0.26.1"
dependencies = [
"anyhow",
"base64",
@ -1704,7 +1704,7 @@ dependencies = [
[[package]]
name = "lesavka_server"
version = "0.26.0"
version = "0.26.1"
dependencies = [
"anyhow",
"base64",

View File

@ -4,7 +4,7 @@ path = "src/main.rs"
[package]
name = "lesavka_client"
version = "0.26.0"
version = "0.26.1"
edition = "2024"
[dependencies]

View File

@ -1,6 +1,6 @@
[package]
name = "lesavka_common"
version = "0.26.0"
version = "0.26.1"
edition = "2024"
build = "build.rs"

View File

@ -110,6 +110,8 @@ if [[ -n "${LESAVKA_INSTALL_CAM_CODEC+x}" || -n "${LESAVKA_CAM_CODEC+x}" ]]; the
fi
REQUESTED_CAM_CODEC=${LESAVKA_INSTALL_CAM_CODEC:-${LESAVKA_CAM_CODEC:-hevc}}
INSTALL_CAM_CODEC=$(normalize_cam_codec "${REQUESTED_CAM_CODEC}")
INSTALL_HEVC_DECODER=${LESAVKA_INSTALL_HEVC_DECODER:-${LESAVKA_HEVC_DECODER:-}}
INSTALL_ALLOW_SOFTWARE_VIDEO=${LESAVKA_INSTALL_ALLOW_SOFTWARE_VIDEO:-${LESAVKA_ALLOW_SOFTWARE_VIDEO:-0}}
INSTALL_UPLINK_AUDIO_CODEC=${LESAVKA_INSTALL_UPLINK_AUDIO_CODEC:-${LESAVKA_UPLINK_AUDIO_CODEC:-pcm}}
INSTALL_UVC_FRAME_META=${LESAVKA_INSTALL_UVC_FRAME_META:-${LESAVKA_UVC_FRAME_META:-0}}
INSTALL_UVC_FRAME_META_LOG_PATH=${LESAVKA_INSTALL_UVC_FRAME_META_LOG_PATH:-${LESAVKA_UVC_FRAME_META_LOG_PATH:-/tmp/lesavka-uvc-frame-meta.jsonl}}
@ -288,6 +290,29 @@ ensure_hevc_decode_support() {
echo "✅ hardware HEVC decoder passed a real 1280x720 decode smoke: $hevc_decoder"
else
if [[ "$INSTALL_CAM_CODEC" == "hevc" ]]; then
local software_hevc_decoder=""
local software_hevc_smoke_log
software_hevc_smoke_log=$(mktemp "${TMPDIR}/lesavka-hevc-software-decode-smoke.XXXXXX.log")
for candidate in avdec_h265 libde265dec; do
if gst-inspect-1.0 "$candidate" >/dev/null 2>&1 && timeout 20 bash -o pipefail -c \
"gst-launch-1.0 -q videotestsrc num-buffers=30 ! video/x-raw,format=I420,width=1280,height=720,framerate=30/1 ! x265enc speed-preset=ultrafast tune=zerolatency key-int-max=30 ! h265parse disable-passthrough=true config-interval=-1 ! video/x-h265,stream-format=byte-stream,alignment=au ! ${candidate} ! videoconvert ! fakesink sync=false" \
>"$software_hevc_smoke_log" 2>&1; then
software_hevc_decoder=$candidate
break
fi
done
if [[ -n "$software_hevc_decoder" && "$INSTALL_CAM_CODEC_EXPLICIT" == "0" ]]; then
echo "⚠️ hardware HEVC decoder is exposed but the synthetic 1280x720 decode smoke failed: $hevc_decoder" >&2
echo " smoke log: $hevc_smoke_log" >&2
sed -n '1,120p' "$hevc_smoke_log" >&2 || true
echo " Software HEVC decoder passed the same 1280x720 smoke: $software_hevc_decoder" >&2
echo " Keeping default HEVC upstream to avoid direct-MJPEG UVC artifacts; monitor CPU/RSS during field runs." >&2
INSTALL_HEVC_DECODER=$software_hevc_decoder
INSTALL_ALLOW_SOFTWARE_VIDEO=1
return 0
fi
if [[ "$INSTALL_CAM_CODEC_EXPLICIT" == "0" ]]; then
echo "⚠️ hardware HEVC decoder is exposed but the synthetic 1280x720 decode smoke failed: $hevc_decoder" >&2
echo " smoke log: $hevc_smoke_log" >&2
@ -299,6 +324,10 @@ ensure_hevc_decode_support() {
echo "❌ hardware HEVC decoder is exposed but failed a real 1280x720 decode smoke: $hevc_decoder" >&2
echo " smoke log: $hevc_smoke_log" >&2
sed -n '1,120p' "$hevc_smoke_log" >&2 || true
if [[ -n "$software_hevc_decoder" ]]; then
echo " Software HEVC decoder passed: $software_hevc_decoder" >&2
echo " To explicitly use it, rerun with LESAVKA_ALLOW_SOFTWARE_VIDEO=1 LESAVKA_HEVC_DECODER=$software_hevc_decoder." >&2
fi
echo " Refusing HEVC upstream install because production video decode must be hardware-accelerated and proven." >&2
echo " Use LESAVKA_INSTALL_CAM_CODEC=mjpeg while the HEVC decoder stack is repaired." >&2
exit 1
@ -1604,6 +1633,10 @@ SERVER_ENV_TMP=$(mktemp)
printf 'LESAVKA_CAM_OUTPUT=%s\n' "${LESAVKA_INSTALL_CAM_OUTPUT:-uvc}"
printf 'LESAVKA_CAM_CODEC=%s\n' "${INSTALL_CAM_CODEC}"
printf 'LESAVKA_UPLINK_CAMERA_CODEC=%s\n' "${INSTALL_CAM_CODEC}"
if [[ -n "$INSTALL_HEVC_DECODER" ]]; then
printf 'LESAVKA_HEVC_DECODER=%s\n' "$INSTALL_HEVC_DECODER"
fi
printf 'LESAVKA_ALLOW_SOFTWARE_VIDEO=%s\n' "${INSTALL_ALLOW_SOFTWARE_VIDEO}"
printf 'LESAVKA_UPLINK_AUDIO_CODEC=%s\n' "${INSTALL_UPLINK_AUDIO_CODEC}"
printf 'LESAVKA_CAM_WIDTH=%s\n' "${LESAVKA_CAM_WIDTH:-1920}"
printf 'LESAVKA_CAM_HEIGHT=%s\n' "${LESAVKA_CAM_HEIGHT:-1080}"

View File

@ -16,7 +16,7 @@ bench = false
[package]
name = "lesavka_server"
version = "0.26.0"
version = "0.26.1"
edition = "2024"
autobins = false

View File

@ -263,8 +263,10 @@ fn server_install_pins_hdmi_camera_and_display_defaults() {
"install script should try the Raspberry Pi HEVC decoder before requiring another hardware decoder"
);
assert!(
SERVER_INSTALL.contains("will not fall back to avdec_h265 in production"),
"install script should fail loud instead of silently using software HEVC decode"
SERVER_INSTALL.contains("Software HEVC decoder passed the same 1280x720 smoke")
&& SERVER_INSTALL.contains("LESAVKA_HEVC_DECODER")
&& SERVER_INSTALL.contains("LESAVKA_ALLOW_SOFTWARE_VIDEO"),
"install script should make software HEVC fallback explicit and smoke-proven"
);
assert!(
SERVER_INSTALL.contains("hardware HEVC decoder passed a real 1280x720 decode smoke")
@ -288,7 +290,7 @@ fn server_install_pins_hdmi_camera_and_display_defaults() {
SERVER_INSTALL.contains("Refusing HEVC upstream install because production video decode must be hardware-accelerated and proven")
&& SERVER_INSTALL.contains("Use LESAVKA_INSTALL_CAM_CODEC=mjpeg while the HEVC decoder stack is repaired")
&& SERVER_INSTALL.contains("Default HEVC upstream cannot be proven on this host; falling back to MJPEG ingress."),
"explicit HEVC installs should fail loud while default HEVC installs can safely fall back"
"explicit HEVC installs should fail loud while default HEVC installs can use proven fallback paths"
);
assert!(
!SERVER_INSTALL

View File

@ -4,8 +4,8 @@
// explicit, while still allowing operator-provided install overrides.
// Targets: server/client install scripts and client camera capture defaults.
// Why: Lesavka now supports both MJPEG and HEVC upstream media, and installer
// reruns may prefer HEVC only when hardware decode is proven, and must fall
// back to MJPEG instead of producing black frames when it is not.
// reruns may prefer HEVC when decode is proven, falling back to either a
// smoke-tested software HEVC decoder or MJPEG instead of producing black frames.
const SERVER_INSTALL: &str = include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
@ -27,8 +27,13 @@ fn server_install_defaults_to_hevc_ingress_with_mjpeg_fallback_and_mjpeg_uvc_out
"REQUESTED_CAM_CODEC=${LESAVKA_INSTALL_CAM_CODEC:-${LESAVKA_CAM_CODEC:-hevc}}",
"INSTALL_CAM_CODEC=$(normalize_cam_codec \"${REQUESTED_CAM_CODEC}\")",
"INSTALL_CAM_CODEC_EXPLICIT=0",
"INSTALL_HEVC_DECODER=${LESAVKA_INSTALL_HEVC_DECODER:-${LESAVKA_HEVC_DECODER:-}}",
"INSTALL_ALLOW_SOFTWARE_VIDEO=${LESAVKA_INSTALL_ALLOW_SOFTWARE_VIDEO:-${LESAVKA_ALLOW_SOFTWARE_VIDEO:-0}}",
"Software HEVC decoder passed the same 1280x720 smoke",
"Default HEVC upstream cannot be proven on this host; falling back to MJPEG ingress.",
"printf 'LESAVKA_CAM_CODEC=%s\\n' \"${INSTALL_CAM_CODEC}\"",
"printf 'LESAVKA_HEVC_DECODER=%s\\n' \"$INSTALL_HEVC_DECODER\"",
"printf 'LESAVKA_ALLOW_SOFTWARE_VIDEO=%s\\n' \"${INSTALL_ALLOW_SOFTWARE_VIDEO}\"",
"printf 'LESAVKA_UVC_CODEC=%s\\n' \"${INSTALL_UVC_CODEC}\"",
"\"LESAVKA_UVC_CODEC=${INSTALL_UVC_CODEC}\"",
"uvc_env_value LESAVKA_UVC_WIDTH 1280",
@ -83,7 +88,8 @@ fn hevc_prerequisites_are_rechecked_idempotently() {
"modprobe rpi_hevc_dec",
"/etc/modules-load.d/lesavka-hevc.conf",
"gst-inspect-1.0 v4l2slh265dec",
"will not fall back to avdec_h265 in production",
"avdec_h265 libde265dec",
"Keeping default HEVC upstream to avoid direct-MJPEG UVC artifacts",
"Refusing HEVC upstream install because production video decode must be hardware-accelerated and proven",
] {
assert!(