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 = match self.data.get(byte..byte + 4) {
141 Some(c) => u32::from_be_bytes([c[0], c[1], c[2], c[3]]),
142 None => {
143 ((*self.data.get(byte).unwrap_or(&0) as u32) << 24)
144 | ((*self.data.get(byte + 1).unwrap_or(&0) as u32) << 16)
145 | ((*self.data.get(byte + 2).unwrap_or(&0) as u32) << 8)
146 | (*self.data.get(byte + 3).unwrap_or(&0) as u32)
147 }
148 };
149 (acc >> (32 - off - n)) & ((1u32 << n) - 1)
151 }
152
153 #[inline]
157 pub fn skip_bits(&mut self, n: u32) -> Result<(), OutOfData> {
158 if self.pos + n as usize > self.bit_len() {
159 return Err(OutOfData);
160 }
161 self.pos += n as usize;
162 Ok(())
163 }
164
165 pub fn read_ue(&mut self) -> Result<u32, OutOfData> {
167 let window = self.peek_bits(24);
171 let lz = window.leading_zeros() - 8; if lz <= 11 {
173 let total = 2 * lz + 1;
174 self.skip_bits(total)?;
175 if lz == 0 {
176 return Ok(0);
177 }
178 let info = (window >> (24 - total)) & ((1u32 << lz) - 1);
179 return Ok((1u32 << lz) - 1 + info);
180 }
181 let mut leading_zeros = 0u32;
183 while !self.read_bit()? {
184 leading_zeros += 1;
185 if leading_zeros >= 32 {
188 return Err(OutOfData);
189 }
190 }
191 if leading_zeros == 0 {
192 return Ok(0);
193 }
194 let info = self.read_bits(leading_zeros)?;
195 Ok((1u32 << leading_zeros) - 1 + info)
196 }
197
198 pub fn read_se(&mut self) -> Result<i32, OutOfData> {
200 let code_num = self.read_ue()?;
201 let magnitude = code_num.div_ceil(2) as i32;
203 Ok(if code_num % 2 == 1 { magnitude } else { -magnitude })
204 }
205}
206
207#[cfg(test)]
208mod tests {
209 use super::*;
210 use crate::BitWriter;
211
212#[test]
218 fn peek_bits_matches_zero_fill_reference() {
219 fn reference(data: &[u8], pos: usize, n: u32) -> u32 {
220 let byte = pos / 8;
221 let off = (pos % 8) as u32;
222 let acc = ((*data.get(byte).unwrap_or(&0) as u32) << 24)
223 | ((*data.get(byte + 1).unwrap_or(&0) as u32) << 16)
224 | ((*data.get(byte + 2).unwrap_or(&0) as u32) << 8)
225 | (*data.get(byte + 3).unwrap_or(&0) as u32);
226 (acc >> (32 - off - n)) & ((1u32 << n) - 1)
227 }
228 let mut st = 0x1234_5678u32;
229 let mut rnd = || {
230 st ^= st << 13;
231 st ^= st >> 17;
232 st ^= st << 5;
233 st
234 };
235 for len in 1..24usize {
236 let data: Vec<u8> = (0..len).map(|_| (rnd() >> 7) as u8).collect();
237 let r = BitReader::new(&data);
238 for pos in 0..len * 8 {
239 for n in 1..=24u32 {
240 let mut br = BitReader::new(&data);
241 br.skip_bits(pos as u32).ok();
242 let mut probe = BitReader::new(&data);
244 while probe.bit_pos() < pos {
245 if probe.read_bit().is_err() {
246 break;
247 }
248 }
249 if probe.bit_pos() != pos {
250 continue;
251 }
252 assert_eq!(
253 probe.peek_bits(n),
254 reference(&data, pos, n),
255 "len={len} pos={pos} n={n}"
256 );
257 }
258 }
259 let _ = r;
260 }
261 }
262
263 #[test]
264 fn roundtrip_ue() {
265 for v in [0u32, 1, 2, 3, 4, 7, 8, 255, 256, 65535, u32::MAX - 1] {
266 let mut w = BitWriter::new();
267 w.write_ue(v);
268 w.align_zero();
269 let bytes = w.into_bytes();
270 let mut r = BitReader::new(&bytes);
271 assert_eq!(r.read_ue().unwrap(), v, "ue roundtrip {v}");
272 }
273 }
274
275 #[test]
276 fn roundtrip_se() {
277 for v in [0i32, 1, -1, 2, -2, 100, -100, 32767, -32768] {
278 let mut w = BitWriter::new();
279 w.write_se(v);
280 w.align_zero();
281 let bytes = w.into_bytes();
282 let mut r = BitReader::new(&bytes);
283 assert_eq!(r.read_se().unwrap(), v, "se roundtrip {v}");
284 }
285 }
286
287 #[test]
288 fn roundtrip_mixed_stream() {
289 let mut w = BitWriter::new();
290 w.write_bits(0b1011, 4);
291 w.write_ue(42);
292 w.write_se(-17);
293 w.write_bits(1, 1);
294 w.align_zero();
295 let bytes = w.into_bytes();
296
297 let mut r = BitReader::new(&bytes);
298 assert_eq!(r.read_bits(4).unwrap(), 0b1011);
299 assert_eq!(r.read_ue().unwrap(), 42);
300 assert_eq!(r.read_se().unwrap(), -17);
301 assert_eq!(r.read_bits(1).unwrap(), 1);
302 }
303
304 #[test]
305 fn reports_out_of_data() {
306 let bytes = [0x80u8];
307 let mut r = BitReader::new(&bytes);
308 assert_eq!(r.read_bits(8).unwrap(), 0x80);
309 assert_eq!(r.read_bit(), Err(OutOfData));
310 }
311
312 #[test]
313 fn peek_then_skip_matches_read_bits() {
314 let bytes = [0xB5u8, 0x3C, 0xF0, 0x0A, 0x77];
315 for start in 0..16u32 {
318 for n in 1..=24u32 {
319 let mut a = BitReader::new(&bytes);
320 a.skip_bits(start).unwrap();
321 let peeked = a.peek_bits(n);
322 let pos_before = a.bit_pos();
323 a.skip_bits(n).unwrap();
324 assert_eq!(a.bit_pos(), pos_before + n as usize);
325
326 let mut b = BitReader::new(&bytes);
327 b.skip_bits(start).unwrap();
328 assert_eq!(peeked, b.read_bits(n).unwrap(), "start={start} n={n}");
329 }
330 }
331 }
332
333 #[test]
334 fn peek_zero_fills_past_end() {
335 let bytes = [0xFFu8];
336 let mut r = BitReader::new(&bytes);
337 r.skip_bits(4).unwrap();
338 assert_eq!(r.peek_bits(12), 0b1111_0000_0000);
340 assert_eq!(r.skip_bits(8), Err(OutOfData));
342 }
343}