use super::*;
use mediaway_common::CodecKind;
fn tb(num: u64, den: u32) -> Rational {
Rational::new(num, den)
}
#[test]
fn cmtime_from_ticks_num_one() {
let (value, timescale) = cmtime_value_from_ticks(90, tb(1, 30));
assert_eq!(value, 90);
assert_eq!(timescale, 30);
}
#[test]
fn cmtime_from_ticks_arbitrary_num() {
let (value, timescale) = cmtime_value_from_ticks(3, tb(1001, 30_000));
assert_eq!(value, 3003);
assert_eq!(timescale, 30_000);
}
#[test]
fn cmtime_from_ticks_negative() {
let (value, timescale) = cmtime_value_from_ticks(-5, tb(1, 90_000));
assert_eq!(value, -5);
assert_eq!(timescale, 90_000);
}
#[test]
fn cmtime_round_trip_num_one() {
let time_base = tb(1, 30);
for ticks in [0_i64, 1, 30, 12_345, -7] {
let (value, timescale) = cmtime_value_from_ticks(ticks, time_base);
assert_eq!(ticks_from_cmtime_value(value, timescale, time_base), ticks);
}
}
#[test]
fn cmtime_round_trip_arbitrary_num() {
let time_base = tb(1001, 30_000);
for ticks in [0_i64, 1, 100, 999_999] {
let (value, timescale) = cmtime_value_from_ticks(ticks, time_base);
assert_eq!(ticks_from_cmtime_value(value, timescale, time_base), ticks);
}
}
#[test]
fn ticks_from_cmtime_zero_timescale_is_zero() {
assert_eq!(ticks_from_cmtime_value(1000, 0, tb(1, 30)), 0);
}
#[test]
fn ticks_from_cmtime_zero_num_is_zero() {
assert_eq!(ticks_from_cmtime_value(1000, 30, tb(0, 30)), 0);
}
#[test]
fn duration_from_cmtime_clamps_negative_to_zero() {
assert_eq!(duration_ticks_from_cmtime_value(-100, 30, tb(1, 30)), 0);
}
#[test]
fn duration_from_cmtime_positive() {
assert_eq!(duration_ticks_from_cmtime_value(30, 30, tb(1, 30)), 30);
}
#[test]
fn copy_nv12_planes_packs_tight_and_strips_stride() {
let y_plane: [u8; 8] = [1, 2, 0xAA, 0xAA, 3, 4, 0xAA, 0xAA];
let uv_plane: [u8; 4] = [9, 10, 0xAA, 0xAA];
let out = copy_nv12_planes(&y_plane, 4, &uv_plane, 4, 2, 2);
assert_eq!(out.as_ref(), &[1, 2, 3, 4, 9, 10]);
}
#[test]
fn copy_nv12_planes_truncated_input_zero_fills_rest() {
let y_plane: [u8; 2] = [1, 2];
let uv_plane: [u8; 2] = [9, 10];
let out = copy_nv12_planes(&y_plane, 2, &uv_plane, 2, 2, 2);
assert_eq!(out.as_ref(), &[1, 2, 0, 0, 9, 10]);
}
#[test]
fn copy_nv12_planes_empty_input_is_all_zero() {
let out = copy_nv12_planes(&[], 2, &[], 2, 2, 2);
assert_eq!(out.len(), 6);
assert!(out.iter().all(|&b| b == 0));
}
#[test]
fn validate_parameter_sets_accepts_single_sps_pps_4_byte_length() {
let config = AvcDecoderConfig {
nal_length_size: 4,
sps: vec![Bytes::from_static(&[0x67, 0x00])],
pps: vec![Bytes::from_static(&[0x68, 0x00])],
};
assert!(validate_parameter_sets(&config).is_ok());
}
#[test]
fn validate_parameter_sets_rejects_non_4_byte_length() {
let config = AvcDecoderConfig {
nal_length_size: 2,
sps: vec![Bytes::from_static(&[0x67])],
pps: vec![Bytes::from_static(&[0x68])],
};
assert_eq!(
validate_parameter_sets(&config),
Err(DecodeError::Unsupported)
);
}
#[test]
fn validate_parameter_sets_rejects_multiple_sps() {
let config = AvcDecoderConfig {
nal_length_size: 4,
sps: vec![
Bytes::from_static(&[0x67]),
Bytes::from_static(&[0x67, 0x01]),
],
pps: vec![Bytes::from_static(&[0x68])],
};
assert_eq!(
validate_parameter_sets(&config),
Err(DecodeError::Unsupported)
);
}
#[test]
fn validate_parameter_sets_rejects_zero_pps() {
let config = AvcDecoderConfig {
nal_length_size: 4,
sps: vec![Bytes::from_static(&[0x67])],
pps: vec![],
};
assert_eq!(
validate_parameter_sets(&config),
Err(DecodeError::Unsupported)
);
}
#[test]
fn is_supported_video_codec_h264_hevc_vp9_av1_prores() {
assert!(is_supported_video_codec(CodecKind::H264));
assert!(is_supported_video_codec(CodecKind::Hevc));
assert!(is_supported_video_codec(CodecKind::Vp9));
assert!(is_supported_video_codec(CodecKind::Av1));
assert!(is_supported_video_codec(CodecKind::ProRes422Proxy));
assert!(is_supported_video_codec(CodecKind::ProRes422Lt));
assert!(is_supported_video_codec(CodecKind::ProRes422));
assert!(is_supported_video_codec(CodecKind::ProRes422Hq));
assert!(is_supported_video_codec(CodecKind::ProRes4444));
assert!(is_supported_video_codec(CodecKind::ProRes4444Xq));
assert!(!is_supported_video_codec(CodecKind::Opus));
}
#[test]
fn is_prores_only_the_six_prores_variants() {
assert!(is_prores(CodecKind::ProRes422Proxy));
assert!(is_prores(CodecKind::ProRes422Lt));
assert!(is_prores(CodecKind::ProRes422));
assert!(is_prores(CodecKind::ProRes422Hq));
assert!(is_prores(CodecKind::ProRes4444));
assert!(is_prores(CodecKind::ProRes4444Xq));
assert!(!is_prores(CodecKind::H264));
assert!(!is_prores(CodecKind::Hevc));
assert!(!is_prores(CodecKind::Vp9));
assert!(!is_prores(CodecKind::Av1));
}
#[test]
fn requires_extra_data_at_open_only_vp9_av1() {
assert!(!requires_extra_data_at_open(CodecKind::H264));
assert!(!requires_extra_data_at_open(CodecKind::Hevc));
assert!(requires_extra_data_at_open(CodecKind::Vp9));
assert!(requires_extra_data_at_open(CodecKind::Av1));
assert!(!requires_extra_data_at_open(CodecKind::ProRes422));
}
#[test]
fn raw_atom_key_matches_codec() {
assert_eq!(raw_atom_key(CodecKind::Vp9), Some("vpcC"));
assert_eq!(raw_atom_key(CodecKind::Av1), Some("av1C"));
assert_eq!(raw_atom_key(CodecKind::H264), None);
assert_eq!(raw_atom_key(CodecKind::Hevc), None);
assert_eq!(raw_atom_key(CodecKind::ProRes422), None);
}
#[test]
fn validate_hevc_parameter_sets_accepts_single_vps_sps_pps_4_byte_length() {
let config = HevcDecoderConfig {
nal_length_size: 4,
vps: vec![Bytes::from_static(&[0x40, 0x01])],
sps: vec![Bytes::from_static(&[0x42, 0x01])],
pps: vec![Bytes::from_static(&[0x44, 0x01])],
};
assert!(validate_hevc_parameter_sets(&config).is_ok());
}
#[test]
fn validate_hevc_parameter_sets_rejects_non_4_byte_length() {
let config = HevcDecoderConfig {
nal_length_size: 2,
vps: vec![Bytes::from_static(&[0x40])],
sps: vec![Bytes::from_static(&[0x42])],
pps: vec![Bytes::from_static(&[0x44])],
};
assert_eq!(
validate_hevc_parameter_sets(&config),
Err(DecodeError::Unsupported)
);
}
#[test]
fn validate_hevc_parameter_sets_rejects_zero_vps() {
let config = HevcDecoderConfig {
nal_length_size: 4,
vps: vec![],
sps: vec![Bytes::from_static(&[0x42])],
pps: vec![Bytes::from_static(&[0x44])],
};
assert_eq!(
validate_hevc_parameter_sets(&config),
Err(DecodeError::Unsupported)
);
}