rusty_h264_common/
bit_reader.rs1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub struct OutOfData;
9
10impl core::fmt::Display for OutOfData {
11 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
12 f.write_str("bit reader ran out of data")
13 }
14}
15
16impl std::error::Error for OutOfData {}
17
18#[derive(Debug, Clone)]
20pub struct BitReader<'a> {
21 data: &'a [u8],
22 pos: usize,
24}
25
26impl<'a> BitReader<'a> {
27 pub fn new(data: &'a [u8]) -> Self {
29 Self { data, pos: 0 }
30 }
31
32 pub fn data(&self) -> &'a [u8] {
34 self.data
35 }
36
37 pub fn bit_pos(&self) -> usize {
39 self.pos
40 }
41
42 pub fn bit_len(&self) -> usize {
44 self.data.len() * 8
45 }
46
47 pub fn bits_left(&self) -> usize {
49 self.bit_len().saturating_sub(self.pos)
50 }
51
52 pub fn more_rbsp_data(&self) -> bool {
56 let stop = self
59 .data
60 .iter()
61 .enumerate()
62 .rev()
63 .find(|(_, &b)| b != 0)
64 .map(|(bi, &b)| bi * 8 + (7 - b.trailing_zeros() as usize));
65 match stop {
66 Some(s) => self.pos < s,
67 None => false,
68 }
69 }
70
71 pub fn is_byte_aligned(&self) -> bool {
73 self.pos % 8 == 0
74 }
75
76 pub fn align_to_byte(&mut self) -> Result<(), OutOfData> {
79 while self.pos % 8 != 0 {
80 self.read_bit()?;
81 }
82 Ok(())
83 }
84
85 pub fn read_bit(&mut self) -> Result<bool, OutOfData> {
87 if self.pos >= self.bit_len() {
88 return Err(OutOfData);
89 }
90 let byte = self.data[self.pos / 8];
91 let bit = (byte >> (7 - (self.pos % 8))) & 1;
92 self.pos += 1;
93 Ok(bit == 1)
94 }
95
96 pub fn read_bits(&mut self, n: u32) -> Result<u32, OutOfData> {
98 if n > 32 {
101 return Err(OutOfData);
102 }
103 if n == 0 {
104 return Ok(0);
105 }
106 if n <= 24 {
107 let v = self.peek_bits(n);
108 self.skip_bits(n)?;
109 return Ok(v);
110 }
111 let hi = self.read_bits(n - 16)?;
113 let lo = self.read_bits(16)?;
114 Ok((hi << 16) | lo)
115 }
116
117 #[inline]
123 pub fn peek_bits(&self, n: u32) -> u32 {
124 debug_assert!(n <= 24);
125 let byte = self.pos / 8;
126 let off = (self.pos % 8) as u32;
127 let acc = ((*self.data.get(byte).unwrap_or(&0) as u32) << 24)
129 | ((*self.data.get(byte + 1).unwrap_or(&0) as u32) << 16)
130 | ((*self.data.get(byte + 2).unwrap_or(&0) as u32) << 8)
131 | (*self.data.get(byte + 3).unwrap_or(&0) as u32);
132 (acc >> (32 - off - n)) & ((1u32 << n) - 1)
134 }
135
136 #[inline]
140 pub fn skip_bits(&mut self, n: u32) -> Result<(), OutOfData> {
141 if self.pos + n as usize > self.bit_len() {
142 return Err(OutOfData);
143 }
144 self.pos += n as usize;
145 Ok(())
146 }
147
148 pub fn read_ue(&mut self) -> Result<u32, OutOfData> {
150 let window = self.peek_bits(24);
154 let lz = window.leading_zeros() - 8; if lz <= 11 {
156 let total = 2 * lz + 1;
157 self.skip_bits(total)?;
158 if lz == 0 {
159 return Ok(0);
160 }
161 let info = (window >> (24 - total)) & ((1u32 << lz) - 1);
162 return Ok((1u32 << lz) - 1 + info);
163 }
164 let mut leading_zeros = 0u32;
166 while !self.read_bit()? {
167 leading_zeros += 1;
168 if leading_zeros >= 32 {
171 return Err(OutOfData);
172 }
173 }
174 if leading_zeros == 0 {
175 return Ok(0);
176 }
177 let info = self.read_bits(leading_zeros)?;
178 Ok((1u32 << leading_zeros) - 1 + info)
179 }
180
181 pub fn read_se(&mut self) -> Result<i32, OutOfData> {
183 let code_num = self.read_ue()?;
184 let magnitude = code_num.div_ceil(2) as i32;
186 Ok(if code_num % 2 == 1 { magnitude } else { -magnitude })
187 }
188}
189
190#[cfg(test)]
191mod tests {
192 use super::*;
193 use crate::BitWriter;
194
195 #[test]
196 fn roundtrip_ue() {
197 for v in [0u32, 1, 2, 3, 4, 7, 8, 255, 256, 65535, u32::MAX - 1] {
198 let mut w = BitWriter::new();
199 w.write_ue(v);
200 w.align_zero();
201 let bytes = w.into_bytes();
202 let mut r = BitReader::new(&bytes);
203 assert_eq!(r.read_ue().unwrap(), v, "ue roundtrip {v}");
204 }
205 }
206
207 #[test]
208 fn roundtrip_se() {
209 for v in [0i32, 1, -1, 2, -2, 100, -100, 32767, -32768] {
210 let mut w = BitWriter::new();
211 w.write_se(v);
212 w.align_zero();
213 let bytes = w.into_bytes();
214 let mut r = BitReader::new(&bytes);
215 assert_eq!(r.read_se().unwrap(), v, "se roundtrip {v}");
216 }
217 }
218
219 #[test]
220 fn roundtrip_mixed_stream() {
221 let mut w = BitWriter::new();
222 w.write_bits(0b1011, 4);
223 w.write_ue(42);
224 w.write_se(-17);
225 w.write_bits(1, 1);
226 w.align_zero();
227 let bytes = w.into_bytes();
228
229 let mut r = BitReader::new(&bytes);
230 assert_eq!(r.read_bits(4).unwrap(), 0b1011);
231 assert_eq!(r.read_ue().unwrap(), 42);
232 assert_eq!(r.read_se().unwrap(), -17);
233 assert_eq!(r.read_bits(1).unwrap(), 1);
234 }
235
236 #[test]
237 fn reports_out_of_data() {
238 let bytes = [0x80u8];
239 let mut r = BitReader::new(&bytes);
240 assert_eq!(r.read_bits(8).unwrap(), 0x80);
241 assert_eq!(r.read_bit(), Err(OutOfData));
242 }
243
244 #[test]
245 fn peek_then_skip_matches_read_bits() {
246 let bytes = [0xB5u8, 0x3C, 0xF0, 0x0A, 0x77];
247 for start in 0..16u32 {
250 for n in 1..=24u32 {
251 let mut a = BitReader::new(&bytes);
252 a.skip_bits(start).unwrap();
253 let peeked = a.peek_bits(n);
254 let pos_before = a.bit_pos();
255 a.skip_bits(n).unwrap();
256 assert_eq!(a.bit_pos(), pos_before + n as usize);
257
258 let mut b = BitReader::new(&bytes);
259 b.skip_bits(start).unwrap();
260 assert_eq!(peeked, b.read_bits(n).unwrap(), "start={start} n={n}");
261 }
262 }
263 }
264
265 #[test]
266 fn peek_zero_fills_past_end() {
267 let bytes = [0xFFu8];
268 let mut r = BitReader::new(&bytes);
269 r.skip_bits(4).unwrap();
270 assert_eq!(r.peek_bits(12), 0b1111_0000_0000);
272 assert_eq!(r.skip_bits(8), Err(OutOfData));
274 }
275}