#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct SpeedFeatures {
pub search_range_px: i32,
pub zeromv_early_exit_sad: u32,
pub max_partition_16x16: bool,
pub split_16x16_sad: u32,
}
impl SpeedFeatures {
pub fn for_cpu_used(cpu_used: u8) -> Self {
let level = cpu_used.clamp(0, 8).max(5);
match level {
8 => SpeedFeatures {
search_range_px: 8,
zeromv_early_exit_sad: 256,
max_partition_16x16: true,
split_16x16_sad: u32::MAX,
},
7 => SpeedFeatures {
search_range_px: 16,
zeromv_early_exit_sad: 128,
max_partition_16x16: true,
split_16x16_sad: u32::MAX,
},
6 => SpeedFeatures {
search_range_px: 24,
zeromv_early_exit_sad: 64,
max_partition_16x16: true,
split_16x16_sad: 16 * 16 * 8,
},
_ => SpeedFeatures {
search_range_px: 24,
zeromv_early_exit_sad: 0,
max_partition_16x16: true,
split_16x16_sad: 16 * 16 * 6,
},
}
}
}
impl Default for SpeedFeatures {
fn default() -> Self {
Self::for_cpu_used(7)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_is_preset_7() {
assert_eq!(SpeedFeatures::default(), SpeedFeatures::for_cpu_used(7));
assert_eq!(SpeedFeatures::default().search_range_px, 16);
}
#[test]
fn faster_preset_narrows_search() {
let s8 = SpeedFeatures::for_cpu_used(8);
let s7 = SpeedFeatures::for_cpu_used(7);
let s5 = SpeedFeatures::for_cpu_used(5);
assert!(s8.search_range_px <= s7.search_range_px);
assert!(s7.search_range_px <= s5.search_range_px);
}
#[test]
fn faster_preset_more_aggressive_early_exit() {
let s8 = SpeedFeatures::for_cpu_used(8);
let s5 = SpeedFeatures::for_cpu_used(5);
assert!(s8.zeromv_early_exit_sad >= s5.zeromv_early_exit_sad);
}
#[test]
fn all_presets_use_16x16_partitions() {
for cpu in 0..=8u8 {
assert!(
SpeedFeatures::for_cpu_used(cpu).max_partition_16x16,
"cpu_used {cpu} should use 16x16 leaves"
);
}
}
#[test]
fn realtime_presets_never_split_16x16() {
assert_eq!(SpeedFeatures::for_cpu_used(8).split_16x16_sad, u32::MAX);
assert_eq!(SpeedFeatures::for_cpu_used(7).split_16x16_sad, u32::MAX);
assert!(SpeedFeatures::for_cpu_used(6).split_16x16_sad < u32::MAX);
assert!(SpeedFeatures::for_cpu_used(5).split_16x16_sad < u32::MAX);
}
#[test]
fn low_presets_clamp_to_5() {
for cpu in 0..=5u8 {
assert_eq!(
SpeedFeatures::for_cpu_used(cpu),
SpeedFeatures::for_cpu_used(5),
"cpu_used {cpu} should clamp to preset 5"
);
}
}
#[test]
fn out_of_range_clamps_to_8() {
assert_eq!(
SpeedFeatures::for_cpu_used(200),
SpeedFeatures::for_cpu_used(8)
);
}
}