#![allow(
clippy::unwrap_used,
clippy::expect_used,
reason = "test modules may unwrap / expect"
)]
use super::*;
fn pack_bits(bits: &[u8]) -> Vec<u8> {
let mut out = vec![0u8; bits.len().div_ceil(8)];
for (i, &bit) in bits.iter().enumerate() {
if bit != 0 {
out[i / 8] |= 1 << (7 - (i % 8));
}
}
out
}
fn push_bits(bits: &mut Vec<u8>, value: u32, width: u32) {
for i in (0..width).rev() {
bits.push(u8::from((value >> i) & 1 != 0));
}
}
fn key_frame_bits() -> Vec<u8> {
let mut bits = Vec::new();
push_bits(&mut bits, 0b10, 2); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 1, 1); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 0x49, 8); push_bits(&mut bits, 0x83, 8); push_bits(&mut bits, 0x42, 8); push_bits(&mut bits, 1, 3); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 63, 16); push_bits(&mut bits, 63, 16); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 1, 1); push_bits(&mut bits, 0, 2); push_bits(&mut bits, 0, 6); push_bits(&mut bits, 0, 3); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 10, 8); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 5, 16); bits
}
#[test]
fn parse_accepts_minimal_key_frame_and_reads_every_field_correctly() {
let data = pack_bits(&key_frame_bits());
assert_eq!(data.len(), 14); let ref_table = RefTable::new();
let header = Header::parse(&data, &ref_table).unwrap();
assert!(header.is_key);
assert!(!header.error_resilient_mode);
assert_eq!(header.refresh_frame_flags, 0xff);
assert_eq!(header.ref_frame_idx, [0, 0, 0]);
assert_eq!(header.width, 64);
assert_eq!(header.height, 64);
assert!(!header.refresh_frame_context);
assert!(header.frame_parallel_decoding_mode);
assert_eq!(header.frame_context_idx, 0);
assert_eq!(header.reset_frame_context, 0);
assert_eq!(header.loop_filter.level, 0);
assert_eq!(header.loop_filter.sharpness, 0);
assert_eq!(header.quantization.base_q_idx, 10);
assert!(!header.quantization.lossless);
assert_eq!(header.first_partition_size, 5);
assert_eq!(header.frame_header_length_in_bytes, 14);
}
#[test]
fn parse_rejects_non_zero_profile() {
let mut bits = Vec::new();
push_bits(&mut bits, 0b10, 2); push_bits(&mut bits, 1, 1); push_bits(&mut bits, 0, 1); let data = pack_bits(&bits);
let ref_table = RefTable::new();
assert_eq!(
Header::parse(&data, &ref_table),
Err(DecodeError::Unsupported)
);
}
#[test]
fn parse_rejects_show_existing_frame() {
let mut bits = Vec::new();
push_bits(&mut bits, 0b10, 2);
push_bits(&mut bits, 0, 1);
push_bits(&mut bits, 0, 1);
push_bits(&mut bits, 1, 1); let data = pack_bits(&bits);
let ref_table = RefTable::new();
assert_eq!(
Header::parse(&data, &ref_table),
Err(DecodeError::Unsupported)
);
}
#[test]
fn parse_rejects_hidden_frame_show_frame_zero() {
let mut bits = Vec::new();
push_bits(&mut bits, 0b10, 2);
push_bits(&mut bits, 0, 1);
push_bits(&mut bits, 0, 1);
push_bits(&mut bits, 0, 1); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 0, 1); let data = pack_bits(&bits);
let ref_table = RefTable::new();
assert_eq!(
Header::parse(&data, &ref_table),
Err(DecodeError::Unsupported)
);
}
#[test]
fn parse_rejects_lossless_frame() {
let mut bits = Vec::new();
push_bits(&mut bits, 0b10, 2);
push_bits(&mut bits, 0, 1);
push_bits(&mut bits, 0, 1);
push_bits(&mut bits, 0, 1); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 1, 1); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 0x49, 8);
push_bits(&mut bits, 0x83, 8);
push_bits(&mut bits, 0x42, 8);
push_bits(&mut bits, 1, 3); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 63, 16);
push_bits(&mut bits, 63, 16);
push_bits(&mut bits, 0, 1); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 1, 1); push_bits(&mut bits, 0, 2); push_bits(&mut bits, 0, 6); push_bits(&mut bits, 0, 3); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 0, 8); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 0, 1); let data = pack_bits(&bits);
let ref_table = RefTable::new();
assert_eq!(
Header::parse(&data, &ref_table),
Err(DecodeError::Unsupported)
);
}
#[test]
fn parse_rejects_segmentation_enabled() {
let mut bits = Vec::new();
push_bits(&mut bits, 0b10, 2);
push_bits(&mut bits, 0, 1);
push_bits(&mut bits, 0, 1);
push_bits(&mut bits, 0, 1);
push_bits(&mut bits, 0, 1);
push_bits(&mut bits, 1, 1);
push_bits(&mut bits, 0, 1);
push_bits(&mut bits, 0x49, 8);
push_bits(&mut bits, 0x83, 8);
push_bits(&mut bits, 0x42, 8);
push_bits(&mut bits, 1, 3);
push_bits(&mut bits, 0, 1);
push_bits(&mut bits, 63, 16);
push_bits(&mut bits, 63, 16);
push_bits(&mut bits, 0, 1);
push_bits(&mut bits, 0, 1);
push_bits(&mut bits, 1, 1);
push_bits(&mut bits, 0, 2);
push_bits(&mut bits, 0, 6);
push_bits(&mut bits, 0, 3);
push_bits(&mut bits, 0, 1);
push_bits(&mut bits, 10, 8);
push_bits(&mut bits, 0, 1);
push_bits(&mut bits, 0, 1);
push_bits(&mut bits, 0, 1);
push_bits(&mut bits, 1, 1); let data = pack_bits(&bits);
let ref_table = RefTable::new();
assert_eq!(
Header::parse(&data, &ref_table),
Err(DecodeError::Unsupported)
);
}
#[test]
fn parse_inter_frame_uses_ref_table_for_frame_size_with_refs() {
let mut ref_table = RefTable::new();
ref_table.refresh(0b0000_0001, 0, 64, 64);
let mut bits = Vec::new();
push_bits(&mut bits, 0b10, 2); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 1, 1); push_bits(&mut bits, 1, 1); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 1, 2); push_bits(&mut bits, 0b0000_0010, 8); push_bits(&mut bits, 0, 3); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 0, 3); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 0, 3); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 1, 1); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 1, 1); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 1, 1); push_bits(&mut bits, 0, 2); push_bits(&mut bits, 0, 6); push_bits(&mut bits, 0, 3); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 10, 8); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 7, 16);
let data = pack_bits(&bits);
let header = Header::parse(&data, &ref_table).unwrap();
assert!(!header.is_key);
assert_eq!(header.refresh_frame_flags, 0b0000_0010);
assert_eq!(header.ref_frame_idx, [0, 0, 0]);
assert_eq!(header.width, 64);
assert_eq!(header.height, 64);
assert_eq!(header.reset_frame_context, 1);
assert_eq!(header.interpolation_filter, INTERPOLATION_FILTER_SWITCHABLE);
assert_eq!(header.first_partition_size, 7);
}
#[test]
fn parse_inter_frame_errors_when_referencing_an_empty_ref_slot() {
let ref_table = RefTable::new();
let mut bits = Vec::new();
push_bits(&mut bits, 0b10, 2);
push_bits(&mut bits, 0, 1);
push_bits(&mut bits, 0, 1);
push_bits(&mut bits, 0, 1); push_bits(&mut bits, 1, 1); push_bits(&mut bits, 1, 1); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 0, 2); push_bits(&mut bits, 0, 8); push_bits(&mut bits, 0, 3); push_bits(&mut bits, 0, 1); push_bits(&mut bits, 0, 3);
push_bits(&mut bits, 0, 1);
push_bits(&mut bits, 0, 3);
push_bits(&mut bits, 0, 1);
push_bits(&mut bits, 1, 1);
let data = pack_bits(&bits);
assert_eq!(
Header::parse(&data, &ref_table),
Err(DecodeError::InvalidInput)
);
}