pub fn find_start_code(data: &[u8], from: usize) -> Option<usize> {
if data.len() < from + 3 {
return None;
}
memchr::memmem::find(&data[from..], b"\x00\x00\x01").map(|rel| from + rel)
}
pub fn skip_start_code(data: &[u8], pos: usize) -> Option<usize> {
if pos + 2 >= data.len() {
return None;
}
if data[pos] == 0x00 && data[pos + 1] == 0x00 {
if pos + 3 < data.len() && data[pos + 2] == 0x00 && data[pos + 3] == 0x01 {
return Some(pos + 4); }
if data[pos + 2] == 0x01 {
return Some(pos + 3); }
}
None
}
pub(crate) struct BitReader<'a> {
data: &'a [u8],
bit: usize,
}
impl<'a> BitReader<'a> {
pub fn new(data: &'a [u8]) -> Self {
Self { data, bit: 0 }
}
pub fn read_bit(&mut self) -> Option<u32> {
let byte = self.bit / 8;
if byte >= self.data.len() {
return None;
}
let b = (self.data[byte] >> (7 - (self.bit & 7))) & 1;
self.bit += 1;
Some(b as u32)
}
pub fn read_bits(&mut self, n: u32) -> Option<u32> {
let mut v = 0u32;
for _ in 0..n {
v = (v << 1) | self.read_bit()?;
}
Some(v)
}
pub fn skip_bits(&mut self, n: u32) -> Option<()> {
for _ in 0..n {
self.read_bit()?;
}
Some(())
}
pub fn read_ue(&mut self) -> Option<u32> {
let mut leading_zeros = 0u32;
while self.read_bit()? == 0 {
leading_zeros += 1;
if leading_zeros > 31 {
return None;
}
}
let mut info = 0u32;
for _ in 0..leading_zeros {
info = (info << 1) | self.read_bit()?;
}
Some((1u32 << leading_zeros) - 1 + info)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn bit_reader_read_ue_exp_golomb_table() {
assert_eq!(BitReader::new(&[0x80]).read_ue(), Some(0)); assert_eq!(BitReader::new(&[0x40]).read_ue(), Some(1)); assert_eq!(BitReader::new(&[0x60]).read_ue(), Some(2)); assert_eq!(BitReader::new(&[0x20]).read_ue(), Some(3)); assert_eq!(BitReader::new(&[0x28]).read_ue(), Some(4)); }
#[test]
fn bit_reader_read_ue_sequence_and_bits() {
let mut br = BitReader::new(&[0xB2, 0x80]);
assert_eq!(br.read_ue(), Some(0));
assert_eq!(br.read_ue(), Some(2));
assert_eq!(br.read_ue(), Some(4));
}
#[test]
fn bit_reader_truncation_and_skip() {
assert_eq!(BitReader::new(&[]).read_ue(), None);
let mut br = BitReader::new(&[0xFF]);
assert_eq!(br.skip_bits(9), None);
let mut b = BitReader::new(&[0b1010_0000]);
assert_eq!(b.read_bit(), Some(1));
assert_eq!(b.read_bit(), Some(0));
assert_eq!(b.read_bit(), Some(1));
}
#[test]
fn find_start_code_3byte() {
let data = [0x00, 0x00, 0x01, 0x65];
assert_eq!(find_start_code(&data, 0), Some(0));
}
#[test]
fn find_start_code_4byte() {
let data = [0x00, 0x00, 0x00, 0x01, 0x65];
assert_eq!(find_start_code(&data, 0), Some(1));
}
#[test]
fn find_start_code_offset() {
let data = [0xFF, 0xFF, 0x00, 0x00, 0x01, 0x09];
assert_eq!(find_start_code(&data, 0), Some(2));
}
#[test]
fn find_start_code_none() {
let data = [0x00, 0x00, 0x00, 0x00];
assert_eq!(find_start_code(&data, 0), None);
}
#[test]
fn find_start_code_too_short() {
let data = [0x00, 0x00];
assert_eq!(find_start_code(&data, 0), None);
}
#[test]
fn skip_3byte() {
let data = [0x00, 0x00, 0x01, 0x65];
assert_eq!(skip_start_code(&data, 0), Some(3));
}
#[test]
fn skip_4byte() {
let data = [0x00, 0x00, 0x00, 0x01, 0x65];
assert_eq!(skip_start_code(&data, 0), Some(4));
}
#[test]
fn skip_not_a_start_code() {
let data = [0xFF, 0x00, 0x01, 0x65];
assert_eq!(skip_start_code(&data, 0), None);
}
#[test]
fn find_start_code_skips_before_from() {
let data = [0x00, 0x00, 0x01, 0x65, 0xFF, 0x00, 0x00, 0x01, 0x09];
assert_eq!(find_start_code(&data, 0), Some(0));
assert_eq!(find_start_code(&data, 1), Some(5));
}
#[test]
fn find_start_code_from_equals_len_minus_3_exact_boundary() {
let data = [0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x01];
assert_eq!(find_start_code(&data, 3), Some(3));
}
#[test]
fn find_start_code_from_too_close_to_end_returns_none() {
let data = [0x00, 0x00, 0x01, 0xFF];
assert_eq!(find_start_code(&data, 2), None);
}
#[test]
fn find_start_code_from_past_end_returns_none() {
let data = [0x00, 0x00, 0x01];
assert_eq!(find_start_code(&data, 100), None);
}
#[test]
fn find_start_code_empty_buffer() {
let data: [u8; 0] = [];
assert_eq!(find_start_code(&data, 0), None);
}
#[test]
fn find_start_code_four_byte_reports_inner_triple_not_first_zero() {
let data = [0xAB, 0x00, 0x00, 0x00, 0x01, 0x67];
assert_eq!(find_start_code(&data, 0), Some(2));
}
#[test]
fn find_start_code_long_zero_run_then_one() {
let data = [0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x42];
assert_eq!(find_start_code(&data, 0), Some(3));
}
#[test]
fn find_start_code_two_byte_zero_not_a_match() {
let data = [0x00, 0x00, 0x02, 0x00, 0x00, 0x00];
assert_eq!(find_start_code(&data, 0), None);
}
#[test]
fn skip_start_code_at_nonzero_pos() {
let data = [0xFF, 0xFF, 0x00, 0x00, 0x01, 0x67, 0x88];
assert_eq!(skip_start_code(&data, 2), Some(5));
}
#[test]
fn skip_start_code_too_short_for_3byte() {
let data = [0x00, 0x00];
assert_eq!(skip_start_code(&data, 0), None);
}
#[test]
fn skip_4byte_with_01_as_last_byte_returns_one_past_end() {
let data = [0x00, 0x00, 0x00, 0x01];
assert_eq!(skip_start_code(&data, 0), Some(4));
}
#[test]
fn skip_3byte_with_exactly_three_bytes() {
let data = [0x00, 0x00, 0x01];
assert_eq!(skip_start_code(&data, 0), Some(3));
}
#[test]
fn skip_start_code_first_byte_nonzero() {
let data = [0x01, 0x00, 0x01, 0x65];
assert_eq!(skip_start_code(&data, 0), None);
}
#[test]
fn skip_start_code_second_byte_nonzero() {
let data = [0x00, 0x01, 0x01, 0x65];
assert_eq!(skip_start_code(&data, 0), None);
}
}