scuffle_av1/obu/
utils.rs

1use std::io;
2
3use scuffle_bytes_util::BitReader;
4
5/// Read a little-endian variable-length integer.
6/// AV1-Spec-2 - 4.10.5
7pub(crate) fn read_leb128<T: io::Read>(reader: &mut BitReader<T>) -> io::Result<u64> {
8    let mut result = 0;
9    for i in 0..8 {
10        let byte = reader.read_bits(8)?;
11        result |= (byte & 0x7f) << (i * 7);
12        if byte & 0x80 == 0 {
13            break;
14        }
15    }
16    Ok(result)
17}
18
19/// Read a variable-length unsigned integer.
20/// AV1-Spec-2 - 4.10.3
21pub(crate) fn read_uvlc<T: io::Read>(reader: &mut BitReader<T>) -> io::Result<u64> {
22    let mut leading_zeros = 0;
23    while !reader.read_bit()? {
24        leading_zeros += 1;
25    }
26
27    if leading_zeros >= 32 {
28        return Ok((1 << 32) - 1);
29    }
30
31    let value = reader.read_bits(leading_zeros)?;
32    Ok(value + (1 << leading_zeros) - 1)
33}
34
35#[cfg(test)]
36#[cfg_attr(all(test, coverage_nightly), coverage(off))]
37mod tests {
38    use super::*;
39
40    #[test]
41    fn test_read_leb128() {
42        let mut cursor = std::io::Cursor::new([0b11010101, 0b00101010]);
43        let mut reader = BitReader::new(&mut cursor);
44        assert_eq!(read_leb128(&mut reader).unwrap(), 0b1010101010101);
45
46        let mut cursor = std::io::Cursor::new([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]);
47        let mut reader = BitReader::new(&mut cursor);
48
49        // 8 bits less because we lose 1 bit from each byte with 8 bytes this means the
50        // max we can read is 2^56 - 1
51        assert_eq!(read_leb128(&mut reader).unwrap(), (1 << 56) - 1);
52    }
53
54    #[test]
55    fn test_read_uvlc() {
56        let mut cursor = std::io::Cursor::new([0x01, 0xff]);
57        let mut reader = BitReader::new(&mut cursor);
58        assert_eq!(read_uvlc(&mut reader).unwrap(), 0xfe);
59
60        let mut cursor = std::io::Cursor::new([0x00, 0x00, 0x00, 0x00, 0x01]);
61        let mut reader = BitReader::new(&mut cursor);
62        assert_eq!(read_uvlc(&mut reader).unwrap(), (1 << 32) - 1);
63    }
64}