Skip to main content

media_codec_bitstream/
reader.rs

1use std::io::{Cursor, Error, ErrorKind, Read, Result, Seek, SeekFrom};
2
3use bitstream_io::{BigEndian, BitRead, Endianness, Integer};
4
5pub struct BitReader<R: Read, E: Endianness> {
6    inner: bitstream_io::BitReader<R, E>,
7    total_bits: usize,
8}
9
10impl<R: Read, E: Endianness> BitReader<R, E> {
11    /// Create a new `BitReader` wrapping the given reader
12    #[inline]
13    pub fn new(reader: R) -> Self {
14        Self {
15            inner: bitstream_io::BitReader::new(reader),
16            total_bits: 0,
17        }
18    }
19
20    /// Reads a single bit from the stream
21    #[inline]
22    pub fn read_bit(&mut self) -> Result<bool> {
23        self.inner.read_bit()
24    }
25
26    /// Reads up to `BITS` bits as a value of type `T`
27    #[inline]
28    pub fn read<const BITS: u32, T: Integer>(&mut self) -> Result<T> {
29        self.inner.read::<BITS, T>()
30    }
31
32    /// Reads `bits` number of bits as a value of type `T`
33    #[inline]
34    pub fn read_var<T: Integer>(&mut self, bits: u32) -> Result<T> {
35        self.inner.read_var(bits)
36    }
37
38    /// Skips the given number of bits
39    #[inline]
40    pub fn skip(&mut self, bits: u32) -> Result<()> {
41        self.inner.skip(bits)
42    }
43
44    /// Returns true if the stream is byte-aligned
45    #[inline]
46    pub fn byte_aligned(&self) -> bool {
47        self.inner.byte_aligned()
48    }
49
50    /// Discards any remaining bits until the stream is byte-aligned
51    #[inline]
52    pub fn byte_align(&mut self) {
53        self.inner.byte_align()
54    }
55
56    /// Reads exactly `buf.len()` bytes into the buffer
57    #[inline]
58    pub fn read_bytes(&mut self, buf: &mut [u8]) -> Result<()> {
59        self.inner.read_bytes(buf)
60    }
61
62    /// Reads `bytes` number of bytes into a vector
63    #[inline]
64    pub fn read_to_vec(&mut self, bytes: usize) -> Result<Vec<u8>> {
65        self.inner.read_to_vec(bytes)
66    }
67
68    /// Reads bits until a stop bit is encountered
69    #[inline]
70    pub fn read_unary<const STOP_BIT: u8>(&mut self) -> Result<u32> {
71        self.inner.read_unary::<STOP_BIT>()
72    }
73}
74
75impl<R: Read + Seek, E: Endianness> BitReader<R, E> {
76    /// Returns the number of bits left in the stream
77    pub fn bits_left(&mut self) -> Result<usize> {
78        Ok(self.total_bits.saturating_sub(self.inner.position_in_bits()? as usize))
79    }
80}
81
82impl<'a, E: Endianness> BitReader<Cursor<&'a [u8]>, E> {
83    /// Create a BitReader from a byte slice, automatically tracking length
84    pub fn from_slice(data: &'a [u8]) -> Self {
85        Self {
86            inner: bitstream_io::BitReader::new(Cursor::new(data)),
87            total_bits: data.len() * 8,
88        }
89    }
90
91    /// Get the remaining data as a byte-aligned slice
92    pub fn remaining_slice(&mut self) -> &'a [u8] {
93        let cursor = self.inner.aligned_reader();
94        let pos = cursor.position() as usize;
95        let data = *cursor.get_ref();
96        &data[pos..]
97    }
98}
99
100// Exp-Golomb methods for BigEndian
101impl<R: Read> BitReader<R, BigEndian> {
102    /// Reads an unsigned Exp-Golomb coded value (ue(v))
103    pub fn read_ue(&mut self) -> Result<u32> {
104        // Count leading zeros until stop bit 1
105        let leading_zeros = self.inner.read_unary::<1>()?;
106
107        if leading_zeros == 0 {
108            return Ok(0);
109        } else if leading_zeros <= 31 {
110            // Read the suffix bits
111            let suffix: u32 = self.inner.read_var(leading_zeros)?;
112            return Ok((1 << leading_zeros) - 1 + suffix);
113        }
114
115        Err(Error::new(ErrorKind::InvalidData, "Exp-Golomb code overflow"))
116    }
117
118    /// Reads a signed Exp-Golomb coded value (se(v))
119    pub fn read_se(&mut self) -> Result<i32> {
120        let unsigned = self.read_ue()?;
121        Ok(((unsigned >> 1) as i32 + (unsigned & 1) as i32) * ((((unsigned & 1) as i32) << 1) - 1))
122    }
123}
124
125// Peek functionality requires Seek support
126impl<R: Read + Seek, E: Endianness> BitReader<R, E> {
127    /// Gets the current position in bits from the start of the stream
128    #[inline]
129    pub fn position_in_bits(&mut self) -> Result<u64> {
130        self.inner.position_in_bits()
131    }
132
133    /// Seeks to a position in the stream by bits
134    #[inline]
135    pub fn seek_bits(&mut self, from: SeekFrom) -> Result<u64> {
136        self.inner.seek_bits(from)
137    }
138
139    /// Peeks the next `BITS` bits without consuming them
140    pub fn peek<const BITS: u32, T: Integer>(&mut self) -> Result<T> {
141        let pos = self.inner.position_in_bits()?;
142        let value = self.inner.read::<BITS, T>()?;
143        self.inner.seek_bits(SeekFrom::Start(pos))?;
144        Ok(value)
145    }
146
147    /// Peeks `bits` number of bits without consuming them
148    pub fn peek_var<T: Integer>(&mut self, bits: u32) -> Result<T> {
149        let pos = self.inner.position_in_bits()?;
150        let value = self.inner.read_var(bits)?;
151        self.inner.seek_bits(SeekFrom::Start(pos))?;
152        Ok(value)
153    }
154
155    /// Peeks a single bit without consuming it
156    pub fn peek_bit(&mut self) -> Result<bool> {
157        let pos = self.inner.position_in_bits()?;
158        let value = self.inner.read_bit()?;
159        self.inner.seek_bits(SeekFrom::Start(pos))?;
160        Ok(value)
161    }
162}
163
164// Peek with Exp-Golomb for BigEndian + Seek
165impl<R: Read + Seek> BitReader<R, BigEndian> {
166    /// Peeks an unsigned Exp-Golomb coded value without consuming it
167    pub fn peek_ue(&mut self) -> Result<u32> {
168        let pos = self.inner.position_in_bits()?;
169        let value = self.read_ue()?;
170        self.inner.seek_bits(SeekFrom::Start(pos))?;
171        Ok(value)
172    }
173
174    /// Peeks a signed Exp-Golomb coded value without consuming it
175    pub fn peek_se(&mut self) -> Result<i32> {
176        let pos = self.inner.position_in_bits()?;
177        let value = self.read_se()?;
178        self.inner.seek_bits(SeekFrom::Start(pos))?;
179        Ok(value)
180    }
181}