diff --git a/src/sync_logic.rs b/src/sync_logic.rs index fc8536d..aec434e 100644 --- a/src/sync_logic.rs +++ b/src/sync_logic.rs @@ -312,6 +312,54 @@ mod tests { ); } + #[test] + fn test_average_frames_with_different_framerates() { + let mut state = LtcState::new(); + state.record_offset(60); // average jitter is 60ms + + // Test with 25fps + state.latest = Some(LtcFrame { + status: "LOCK".to_string(), + hours: 1, + minutes: 1, + seconds: 1, + frames: 0, + frame_rate: 25.0, + timestamp: Utc::now(), + }); + // ms_per_frame = 1000.0 / 25.0 = 40ms. + // average_frames = round(60 / 40) = round(1.5) = 2 frames + assert_eq!(state.average_frames(), 2); + + // Test with 24fps + state.latest = Some(LtcFrame { + status: "LOCK".to_string(), + hours: 1, + minutes: 1, + seconds: 1, + frames: 0, + frame_rate: 24.0, + timestamp: Utc::now(), + }); + // ms_per_frame = 1000.0 / 24.0 = 41.666...ms + // average_frames = round(60 / 41.666) = round(1.44) = 1 frame + assert_eq!(state.average_frames(), 1); + + // Test with 29.97fps + state.latest = Some(LtcFrame { + status: "LOCK".to_string(), + hours: 1, + minutes: 1, + seconds: 1, + frames: 0, + frame_rate: 29.97, + timestamp: Utc::now(), + }); + // ms_per_frame = 1000.0 / 29.97 = 33.366...ms + // average_frames = round(60 / 33.366) = round(1.798) = 2 frames + assert_eq!(state.average_frames(), 2); + } + #[test] fn test_ewma_clock_delta() { let mut state = LtcState::new(); diff --git a/src/system.rs b/src/system.rs index c3918f6..2ebeefd 100644 --- a/src/system.rs +++ b/src/system.rs @@ -209,6 +209,46 @@ mod tests { assert_eq!(target_time.nanosecond(), 920_000_000); } + #[test] + fn test_calculate_target_time_different_framerates() { + let config = Config::default(); + + // 25fps, 12 frames -> 480ms. + let mut frame = get_test_frame(10, 20, 30, 12); + let target_time_25 = calculate_target_time(&frame, &config); + assert_eq!(target_time_25.hour(), 10); + assert_eq!(target_time_25.minute(), 20); + assert_eq!(target_time_25.second(), 30); + assert_eq!(target_time_25.nanosecond(), 480_000_000); + + // 24fps, 12 frames -> 500ms + frame.frame_rate = 24.0; + let target_time_24 = calculate_target_time(&frame, &config); + assert_eq!(target_time_24.hour(), 10); + assert_eq!(target_time_24.minute(), 20); + assert_eq!(target_time_24.second(), 30); + assert_eq!(target_time_24.nanosecond(), 500_000_000); + + // 29.97fps, 15 frames -> 501ms + frame.frame_rate = 29.97; + frame.frames = 15; + // (15 / 29.97) * 1000 = 500.500... -> round() -> 501 + let target_time_2997 = calculate_target_time(&frame, &config); + assert_eq!(target_time_2997.hour(), 10); + assert_eq!(target_time_2997.minute(), 20); + assert_eq!(target_time_2997.second(), 30); + assert_eq!(target_time_2997.nanosecond(), 501_000_000); + + // 30fps, 15 frames -> 500ms + frame.frame_rate = 30.0; + // frames is still 15 + let target_time_30 = calculate_target_time(&frame, &config); + assert_eq!(target_time_30.hour(), 10); + assert_eq!(target_time_30.minute(), 20); + assert_eq!(target_time_30.second(), 30); + assert_eq!(target_time_30.nanosecond(), 500_000_000); + } + #[test] fn test_nudge_clock_on_non_linux() { #[cfg(not(target_os = "linux"))]