install: default upstream camera to mjpeg
This commit is contained in:
parent
d9cc0d2237
commit
0ef34da971
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -1652,7 +1652,7 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lesavka_client"
|
name = "lesavka_client"
|
||||||
version = "0.22.19"
|
version = "0.22.20"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-stream",
|
"async-stream",
|
||||||
@ -1686,7 +1686,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lesavka_common"
|
name = "lesavka_common"
|
||||||
version = "0.22.19"
|
version = "0.22.20"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64",
|
"base64",
|
||||||
@ -1698,7 +1698,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lesavka_server"
|
name = "lesavka_server"
|
||||||
version = "0.22.19"
|
version = "0.22.20"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64",
|
"base64",
|
||||||
|
|||||||
@ -4,7 +4,7 @@ path = "src/main.rs"
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "lesavka_client"
|
name = "lesavka_client"
|
||||||
version = "0.22.19"
|
version = "0.22.20"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "lesavka_common"
|
name = "lesavka_common"
|
||||||
version = "0.22.19"
|
version = "0.22.20"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
|
|||||||
@ -39,6 +39,22 @@ normalize_uvc_codec() {
|
|||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
normalize_cam_codec() {
|
||||||
|
local raw=${1:-mjpeg}
|
||||||
|
case "${raw,,}" in
|
||||||
|
mjpeg|mjpg|jpeg|"")
|
||||||
|
echo "mjpeg"
|
||||||
|
;;
|
||||||
|
hevc|h265|h.265)
|
||||||
|
echo "hevc"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "❌ unsupported upstream camera codec '${raw}'. Use mjpeg or hevc." >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
uvc_env_value() {
|
uvc_env_value() {
|
||||||
local key=$1
|
local key=$1
|
||||||
local default=$2
|
local default=$2
|
||||||
@ -61,7 +77,7 @@ if [[ "${REQUESTED_UVC_CODEC,,}" != "${INSTALL_UVC_CODEC}" ]]; then
|
|||||||
echo "⚠️ UVC gadget output codec '${REQUESTED_UVC_CODEC}' is not supported by the MJPEG UVC helper; using '${INSTALL_UVC_CODEC}' for the host-facing gadget."
|
echo "⚠️ UVC gadget output codec '${REQUESTED_UVC_CODEC}' is not supported by the MJPEG UVC helper; using '${INSTALL_UVC_CODEC}' for the host-facing gadget."
|
||||||
echo " Use LESAVKA_INSTALL_CAM_CODEC=hevc to choose HEVC for the client-to-server upstream transport."
|
echo " Use LESAVKA_INSTALL_CAM_CODEC=hevc to choose HEVC for the client-to-server upstream transport."
|
||||||
fi
|
fi
|
||||||
INSTALL_CAM_CODEC=${LESAVKA_INSTALL_CAM_CODEC:-${LESAVKA_CAM_CODEC:-hevc}}
|
INSTALL_CAM_CODEC=$(normalize_cam_codec "${LESAVKA_INSTALL_CAM_CODEC:-${LESAVKA_CAM_CODEC:-mjpeg}}")
|
||||||
INSTALL_UPLINK_AUDIO_CODEC=${LESAVKA_INSTALL_UPLINK_AUDIO_CODEC:-${LESAVKA_UPLINK_AUDIO_CODEC:-pcm}}
|
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=${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}}
|
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}}
|
||||||
@ -214,7 +230,7 @@ ensure_hevc_decode_support() {
|
|||||||
else
|
else
|
||||||
echo "❌ no hardware HEVC decoder exposed to GStreamer; Lesavka will not fall back to avdec_h265 in production." >&2
|
echo "❌ no hardware HEVC decoder exposed to GStreamer; Lesavka will not fall back to avdec_h265 in production." >&2
|
||||||
if [[ "$INSTALL_UVC_CODEC" == "hevc" || "$INSTALL_CAM_CODEC" == "hevc" ]]; then
|
if [[ "$INSTALL_UVC_CODEC" == "hevc" || "$INSTALL_CAM_CODEC" == "hevc" ]]; then
|
||||||
echo " Install/repair v4l2slh265dec or set a non-HEVC UVC codec before running the server installer." >&2
|
echo " Install/repair v4l2slh265dec or set LESAVKA_INSTALL_CAM_CODEC=mjpeg before running the server installer." >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@ -232,11 +248,19 @@ ensure_hevc_decode_support() {
|
|||||||
>"$hevc_smoke_log" 2>&1; then
|
>"$hevc_smoke_log" 2>&1; then
|
||||||
echo "✅ hardware HEVC decoder passed a real 1280x720 decode smoke: $hevc_decoder"
|
echo "✅ hardware HEVC decoder passed a real 1280x720 decode smoke: $hevc_decoder"
|
||||||
else
|
else
|
||||||
|
if [[ "$INSTALL_CAM_CODEC" == "hevc" ]]; then
|
||||||
|
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
|
||||||
|
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
|
||||||
|
fi
|
||||||
echo "⚠️ hardware HEVC decoder is exposed but the synthetic 1280x720 decode smoke failed: $hevc_decoder" >&2
|
echo "⚠️ hardware HEVC decoder is exposed but the synthetic 1280x720 decode smoke failed: $hevc_decoder" >&2
|
||||||
echo " smoke log: $hevc_smoke_log" >&2
|
echo " smoke log: $hevc_smoke_log" >&2
|
||||||
sed -n '1,120p' "$hevc_smoke_log" >&2 || true
|
sed -n '1,120p' "$hevc_smoke_log" >&2 || true
|
||||||
echo " Continuing because gst-launch synthetic streams can be a false negative on the Pi stateless decoder." >&2
|
echo " Continuing because this install is not selecting HEVC upstream." >&2
|
||||||
echo " Runtime still requires a buildable hardware HEVC decoder and will not use software fallback in production." >&2
|
echo " Explicit HEVC installs require a passing hardware decode smoke and will not use software fallback in production." >&2
|
||||||
echo " Use scripts/manual/run_hardware_media_smoke.sh for artifact-backed follow-up evidence." >&2
|
echo " Use scripts/manual/run_hardware_media_smoke.sh for artifact-backed follow-up evidence." >&2
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|||||||
@ -10,7 +10,7 @@ bench = false
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "lesavka_server"
|
name = "lesavka_server"
|
||||||
version = "0.22.19"
|
version = "0.22.20"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
autobins = false
|
autobins = false
|
||||||
|
|
||||||
|
|||||||
@ -60,7 +60,10 @@ fn server_install_pins_hdmi_camera_and_display_defaults() {
|
|||||||
assert!(SERVER_INSTALL.contains("${LESAVKA_CAM_HEIGHT:-1080}"));
|
assert!(SERVER_INSTALL.contains("${LESAVKA_CAM_HEIGHT:-1080}"));
|
||||||
assert!(SERVER_INSTALL.contains("${LESAVKA_CAM_FPS:-30}"));
|
assert!(SERVER_INSTALL.contains("${LESAVKA_CAM_FPS:-30}"));
|
||||||
assert!(SERVER_INSTALL.contains("${LESAVKA_INSTALL_CAM_OUTPUT:-uvc}"));
|
assert!(SERVER_INSTALL.contains("${LESAVKA_INSTALL_CAM_OUTPUT:-uvc}"));
|
||||||
assert!(SERVER_INSTALL.contains("${LESAVKA_INSTALL_CAM_CODEC:-${LESAVKA_CAM_CODEC:-hevc}}"));
|
assert!(SERVER_INSTALL.contains("normalize_cam_codec()"));
|
||||||
|
assert!(SERVER_INSTALL.contains(
|
||||||
|
"INSTALL_CAM_CODEC=$(normalize_cam_codec \"${LESAVKA_INSTALL_CAM_CODEC:-${LESAVKA_CAM_CODEC:-mjpeg}}\")"
|
||||||
|
));
|
||||||
assert!(
|
assert!(
|
||||||
SERVER_INSTALL
|
SERVER_INSTALL
|
||||||
.contains("${LESAVKA_INSTALL_UPLINK_AUDIO_CODEC:-${LESAVKA_UPLINK_AUDIO_CODEC:-pcm}}")
|
.contains("${LESAVKA_INSTALL_UPLINK_AUDIO_CODEC:-${LESAVKA_UPLINK_AUDIO_CODEC:-pcm}}")
|
||||||
@ -194,7 +197,7 @@ fn server_install_pins_hdmi_camera_and_display_defaults() {
|
|||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
SERVER_INSTALL.contains("ensure_hevc_decode_support"),
|
SERVER_INSTALL.contains("ensure_hevc_decode_support"),
|
||||||
"install script should prepare HEVC decode dependencies for the default uplink codec"
|
"install script should prepare HEVC decode dependencies when HEVC is selected"
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
SERVER_INSTALL.contains("rpi_hevc_dec"),
|
SERVER_INSTALL.contains("rpi_hevc_dec"),
|
||||||
@ -215,10 +218,17 @@ fn server_install_pins_hdmi_camera_and_display_defaults() {
|
|||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
SERVER_INSTALL.contains("synthetic 1280x720 decode smoke failed")
|
SERVER_INSTALL.contains("synthetic 1280x720 decode smoke failed")
|
||||||
&& SERVER_INSTALL.contains("false negative on the Pi stateless decoder")
|
&& SERVER_INSTALL
|
||||||
&& SERVER_INSTALL.contains("Runtime still requires a buildable hardware HEVC decoder")
|
.contains("Continuing because this install is not selecting HEVC upstream")
|
||||||
|
&& SERVER_INSTALL
|
||||||
|
.contains("Explicit HEVC installs require a passing hardware decode smoke")
|
||||||
&& SERVER_INSTALL.contains("scripts/manual/run_hardware_media_smoke.sh"),
|
&& SERVER_INSTALL.contains("scripts/manual/run_hardware_media_smoke.sh"),
|
||||||
"install script should keep HEVC smoke failures diagnostic instead of blocking known-good Pi runtime paths"
|
"install script should keep non-HEVC installs safe while warning about a broken HEVC stack"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
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"),
|
||||||
|
"explicit HEVC installs should fail loud instead of producing a black UVC webcam feed"
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
!SERVER_INSTALL
|
!SERVER_INSTALL
|
||||||
@ -349,8 +359,11 @@ fn server_install_pins_hdmi_camera_and_display_defaults() {
|
|||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
SERVER_INSTALL.contains("1920x1080) frame_root=\"$function_root/streaming/mjpeg/m/1080p\"")
|
SERVER_INSTALL.contains("1920x1080) frame_root=\"$function_root/streaming/mjpeg/m/1080p\"")
|
||||||
&& SERVER_INSTALL.contains("1280x720) frame_root=\"$function_root/streaming/mjpeg/m/720p\"")
|
&& SERVER_INSTALL
|
||||||
&& SERVER_INSTALL.contains("grep -qx \"${LESAVKA_UVC_INTERVAL:-333333}\" \"$frame_root/dwFrameInterval\""),
|
.contains("1280x720) frame_root=\"$function_root/streaming/mjpeg/m/720p\"")
|
||||||
|
&& SERVER_INSTALL.contains(
|
||||||
|
"grep -qx \"${LESAVKA_UVC_INTERVAL:-333333}\" \"$frame_root/dwFrameInterval\""
|
||||||
|
),
|
||||||
"live descriptor matching should recognize all supported MJPEG UVC profiles instead of collapsing to one 720p frame"
|
"live descriptor matching should recognize all supported MJPEG UVC profiles instead of collapsing to one 720p frame"
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
// Regression contract for preserving codec settings across upgrades.
|
// Regression contract for preserving codec settings across upgrades.
|
||||||
//
|
//
|
||||||
// Scope: keep HEVC ingress and MJPEG UVC output defaults explicit, while still
|
// Scope: keep safe MJPEG ingress and MJPEG UVC output defaults explicit, while still
|
||||||
// allowing operator-provided install overrides.
|
// allowing operator-provided install overrides.
|
||||||
// Targets: server/client install scripts and client camera capture defaults.
|
// Targets: server/client install scripts and client camera capture defaults.
|
||||||
// Why: Lesavka now supports both MJPEG and HEVC upstream media, and installer
|
// Why: Lesavka now supports both MJPEG and HEVC upstream media, and installer
|
||||||
// reruns must not silently revert the working profile.
|
// reruns must not silently select a HEVC profile that produces black frames
|
||||||
|
// when hardware decode is not proven.
|
||||||
|
|
||||||
const SERVER_INSTALL: &str = include_str!(concat!(
|
const SERVER_INSTALL: &str = include_str!(concat!(
|
||||||
env!("CARGO_MANIFEST_DIR"),
|
env!("CARGO_MANIFEST_DIR"),
|
||||||
@ -16,13 +17,14 @@ const CLIENT_CAMERA: &str = include_str!(concat!(
|
|||||||
));
|
));
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn server_install_defaults_to_hevc_ingress_and_mjpeg_uvc_output() {
|
fn server_install_defaults_to_mjpeg_ingress_and_mjpeg_uvc_output() {
|
||||||
for marker in [
|
for marker in [
|
||||||
"PERSISTED_UVC_CODEC=$(persisted_uvc_value LESAVKA_UVC_CODEC || true)",
|
"PERSISTED_UVC_CODEC=$(persisted_uvc_value LESAVKA_UVC_CODEC || true)",
|
||||||
"normalize_uvc_codec()",
|
"normalize_uvc_codec()",
|
||||||
|
"normalize_cam_codec()",
|
||||||
"REQUESTED_UVC_CODEC=${LESAVKA_INSTALL_UVC_CODEC:-${PERSISTED_UVC_CODEC:-mjpeg}}",
|
"REQUESTED_UVC_CODEC=${LESAVKA_INSTALL_UVC_CODEC:-${PERSISTED_UVC_CODEC:-mjpeg}}",
|
||||||
"INSTALL_UVC_CODEC=$(normalize_uvc_codec \"$REQUESTED_UVC_CODEC\")",
|
"INSTALL_UVC_CODEC=$(normalize_uvc_codec \"$REQUESTED_UVC_CODEC\")",
|
||||||
"INSTALL_CAM_CODEC=${LESAVKA_INSTALL_CAM_CODEC:-${LESAVKA_CAM_CODEC:-hevc}}",
|
"INSTALL_CAM_CODEC=$(normalize_cam_codec \"${LESAVKA_INSTALL_CAM_CODEC:-${LESAVKA_CAM_CODEC:-mjpeg}}\")",
|
||||||
"printf 'LESAVKA_CAM_CODEC=%s\\n' \"${INSTALL_CAM_CODEC}\"",
|
"printf 'LESAVKA_CAM_CODEC=%s\\n' \"${INSTALL_CAM_CODEC}\"",
|
||||||
"printf 'LESAVKA_UVC_CODEC=%s\\n' \"${INSTALL_UVC_CODEC}\"",
|
"printf 'LESAVKA_UVC_CODEC=%s\\n' \"${INSTALL_UVC_CODEC}\"",
|
||||||
"\"LESAVKA_UVC_CODEC=${INSTALL_UVC_CODEC}\"",
|
"\"LESAVKA_UVC_CODEC=${INSTALL_UVC_CODEC}\"",
|
||||||
@ -79,6 +81,7 @@ fn hevc_prerequisites_are_rechecked_idempotently() {
|
|||||||
"/etc/modules-load.d/lesavka-hevc.conf",
|
"/etc/modules-load.d/lesavka-hevc.conf",
|
||||||
"gst-inspect-1.0 v4l2slh265dec",
|
"gst-inspect-1.0 v4l2slh265dec",
|
||||||
"will not fall back to avdec_h265 in production",
|
"will not fall back to avdec_h265 in production",
|
||||||
|
"Refusing HEVC upstream install because production video decode must be hardware-accelerated and proven",
|
||||||
] {
|
] {
|
||||||
assert!(
|
assert!(
|
||||||
SERVER_INSTALL.contains(marker),
|
SERVER_INSTALL.contains(marker),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user