// Unit coverage for HEVC recovery state in the client upstream path. // // Scope: include the client HEVC keyframe helpers with a tiny camera-config // shim so the logic can be tested without GTK/GStreamer capture hardware. // Targets: `client/src/app/uplink_media/video_keyframes.rs`. // Why: freshness-first dropping is only safe for predictive codecs when the // next emitted video frame is a clean recovery point. mod input { pub mod camera { #[derive(Clone, Copy)] pub enum CameraCodec { Mjpeg, Hevc, } #[derive(Clone, Copy)] pub struct CameraConfig { pub codec: CameraCodec, } } } use lesavka_common::lesavka::{UpstreamMediaBundle, VideoPacket}; use temp_env::with_vars; include!("../../../../client/src/app/uplink_media/video_keyframes.rs"); fn video_bundle(data: Vec) -> UpstreamMediaBundle { UpstreamMediaBundle { video: Some(VideoPacket { data, ..Default::default() }), ..Default::default() } } #[test] fn annex_b_irap_detection_handles_three_and_four_byte_start_codes() { assert!(contains_hevc_irap(&[0, 0, 0, 1, 0x26, 0x01, 0xaa])); assert!(contains_hevc_irap(&[0, 0, 1, 0x28, 0x01, 0xbb])); assert!(contains_hevc_irap(&[ 0, 0, 1, 0x02, 0x01, 0xcc, 0, 0, 0, 1, 0x2e, 0x01, 0xdd ])); assert!(!contains_hevc_irap(&[0, 0, 0, 1, 0x02, 0x01, 0xee])); assert!(!contains_hevc_irap(&[0x26, 0x01, 0xaa])); } #[test] fn recovery_wait_holds_delta_bundles_and_releases_on_irap() { let delta = video_bundle(vec![0, 0, 0, 1, 0x02, 0x01, 0xaa]); let irap = video_bundle(vec![0, 0, 0, 1, 0x26, 0x01, 0xbb]); assert!(!should_hold_hevc_bundle_for_keyframe_recovery( false, &delta )); assert!(should_hold_hevc_bundle_for_keyframe_recovery(true, &delta)); assert!(!should_hold_hevc_bundle_for_keyframe_recovery(true, &irap)); assert!(bundle_has_hevc_recovery_keyframe(&irap)); assert!(!bundle_has_hevc_recovery_keyframe(&delta)); } #[test] fn capture_gap_only_enters_wait_state_when_hevc_recovery_applies() { let mut waiting = false; note_hevc_capture_gap(false, &mut waiting); assert!(!waiting); note_hevc_capture_gap(true, &mut waiting); assert!(waiting); } #[test] fn codec_selection_enables_recovery_for_hevc_only() { use input::camera::{CameraCodec, CameraConfig}; assert!(upstream_camera_uses_hevc(Some(CameraConfig { codec: CameraCodec::Hevc, }))); assert!(!upstream_camera_uses_hevc(Some(CameraConfig { codec: CameraCodec::Mjpeg, }))); with_vars([("LESAVKA_CAM_CODEC", Some("h.265"))], || { assert!(upstream_camera_uses_hevc(None)); }); with_vars([("LESAVKA_CAM_CODEC", Some("mjpeg"))], || { assert!(!upstream_camera_uses_hevc(None)); }); }