use videocall_codecs::encoder::{Encodable, EncoderConfig};
use videocall_codecs::vp9::Vp9Encoder;
fn i420(w: u32, h: u32, t: u32) -> Vec<u8> {
let (yw, yh) = (w as usize, h as usize);
let (cw, ch) = (w.div_ceil(2) as usize, h.div_ceil(2) as usize);
let mut v = Vec::with_capacity(yw * yh + 2 * cw * ch);
for r in 0..yh {
for c in 0..yw {
v.push(((r + c + t as usize * 3) & 0xff) as u8);
}
}
v.extend(std::iter::repeat_n(128u8, 2 * cw * ch));
v
}
fn base(w: u32, h: u32) -> EncoderConfig {
EncoderConfig {
width: w,
height: h,
framerate: 30,
bitrate_kbps: 500,
keyframe_interval: 150,
min_quantizer: 40,
max_quantizer: 60,
cpu_used: 7,
}
}
fn drive(cfg: EncoderConfig, frames: u32) {
let (w, h) = (cfg.width, cfg.height);
let mut enc = Vp9Encoder::new(cfg).expect("encoder init");
for t in 0..frames {
let ef = enc
.encode(t as i64, &i420(w, h, t))
.unwrap_or_else(|e| panic!("{w}x{h} t{t}: encode error: {e}"))
.unwrap_or_else(|| panic!("{w}x{h} t{t}: no frame emitted"));
assert!(!ef.data.is_empty(), "{w}x{h} t{t}: empty frame");
assert_eq!(ef.data[0] >> 6, 0b10, "{w}x{h} t{t}: frame marker missing");
assert_eq!(ef.is_keyframe, t == 0, "{w}x{h} t{t}: keyframe cadence");
}
}
#[test]
fn tiny_and_odd_dimensions_do_not_panic() {
for &(w, h) in &[
(2u32, 2u32),
(2, 480),
(640, 2),
(8, 8),
(16, 16),
(18, 18),
(66, 66), (328, 248), (330, 250),
] {
drive(base(w, h), 4);
}
}
#[test]
fn quantizer_extremes_do_not_panic() {
for &(minq, maxq) in &[(0u32, 0u32), (63, 63), (60, 40), (0, 63), (1000, 5)] {
let mut cfg = base(160, 120);
cfg.min_quantizer = minq;
cfg.max_quantizer = maxq;
drive(cfg, 6);
}
}
#[test]
fn bitrate_extremes_and_updates_do_not_panic() {
for &kbps in &[1u32, 10, 100_000, 1_000_000] {
let mut cfg = base(160, 120);
cfg.bitrate_kbps = kbps;
drive(cfg, 4);
}
let (w, h) = (160u32, 120u32);
let mut enc = Vp9Encoder::new(base(w, h)).expect("encoder init");
for (t, &kbps) in [50u32, 5_000, 20, 500_000, 1].iter().enumerate() {
enc.update_bitrate_kbps(kbps).expect("bitrate update");
let ef = enc
.encode(t as i64, &i420(w, h, t as u32))
.expect("encode")
.expect("frame");
assert!(!ef.data.is_empty());
}
}
#[test]
fn cpu_used_presets_all_encode() {
for cpu in [0u8, 4, 5, 6, 7, 8, 200] {
let mut cfg = base(328, 248);
cfg.cpu_used = cpu;
drive(cfg, 3);
}
}
#[test]
fn keyframe_interval_one_and_forced_keyframes() {
let (w, h) = (160u32, 120u32);
let mut cfg = base(w, h);
cfg.keyframe_interval = 1;
let mut enc = Vp9Encoder::new(cfg).expect("encoder init");
for t in 0..4 {
let ef = enc.encode(t, &i420(w, h, t as u32)).unwrap().unwrap();
assert!(
ef.is_keyframe,
"kf interval 1: frame {t} must be a keyframe"
);
}
let mut enc = Vp9Encoder::new(base(w, h)).expect("encoder init");
assert!(enc.encode(0, &i420(w, h, 0)).unwrap().unwrap().is_keyframe);
assert!(!enc.encode(1, &i420(w, h, 1)).unwrap().unwrap().is_keyframe);
enc.force_keyframe();
assert!(
enc.encode(2, &i420(w, h, 2)).unwrap().unwrap().is_keyframe,
"forced frame must be a keyframe"
);
assert!(
!enc.encode(3, &i420(w, h, 3)).unwrap().unwrap().is_keyframe,
"force flag must clear after one frame"
);
}