Skip to main content

h264_reader/
rbsp.rs

1//! Decoder that will remove NAL header bytes and _Emulation Prevention_ byte
2//! values from encoded NAL Units, to produce the _Raw Byte Sequence Payload_
3//! (RBSP).
4//!
5//! The following byte sequences are not allowed to appear in a framed H264 bitstream,
6//!
7//!  - `0x00` `0x00` `0x00`
8//!  - `0x00` `0x00` `0x01`
9//!  - `0x00` `0x00` `0x02`
10//!  - `0x00` `0x00` `0x03`
11//!
12//! therefore if these byte sequences do appear in the raw bitstream, an 'escaping' mechanism
13//! (called 'emulation prevention' in the spec) is applied by adding a `0x03` byte between the
14//! second and third bytes in the above sequence, resulting in the following encoded versions,
15//!
16//!  - `0x00` `0x00` **`0x03`** `0x00`
17//!  - `0x00` `0x00` **`0x03`** `0x01`
18//!  - `0x00` `0x00` **`0x03`** `0x02`
19//!  - `0x00` `0x00` **`0x03`** `0x03`
20//!
21//! The [`ByteReader`] type will accept byte sequences that have had this encoding applied, and will
22//! yield byte sequences where the encoding is removed (i.e. the decoder will replace instances of
23//! the sequence `0x00 0x00 0x03` with `0x00 0x00`).
24
25use bitstream_io::read::BitRead as _;
26use bitstream_io::write::BitWrite as _;
27use std::borrow::Cow;
28use std::io::BufRead;
29use std::io::Read;
30use std::io::Write;
31use std::num::NonZeroUsize;
32
33#[derive(Copy, Clone, Debug)]
34enum ParseState {
35    /// Scanning for emulation prevention bytes; `zero_count` (0, 1, or 2)
36    /// tracks consecutive trailing `0x00` bytes.
37    Start(u8),
38    Skip(NonZeroUsize),
39    Three,
40    PostThree,
41}
42
43const H264_HEADER_LEN: NonZeroUsize = match NonZeroUsize::new(1) {
44    Some(one) => one,
45    None => panic!("1 should be non-zero"),
46};
47
48fn zero_pair_finder() -> &'static memchr::memmem::Finder<'static> {
49    static FINDER: std::sync::OnceLock<memchr::memmem::Finder<'static>> =
50        std::sync::OnceLock::new();
51    FINDER.get_or_init(|| memchr::memmem::Finder::new(b"\x00\x00"))
52}
53
54/// [`BufRead`] adapter which returns RBSP from NAL bytes.
55///
56/// This optionally skips a given number of leading bytes, then returns any bytes except the
57/// `emulation-prevention-three` bytes.
58///
59/// See also [module docs](self).
60///
61/// Typically used via a [`h264_reader::nal::Nal`]. Returns error on encountering
62/// invalid byte sequences.
63#[derive(Clone)]
64pub struct ByteReader<R: BufRead> {
65    // self.inner[0..self.i] hasn't yet been emitted and is RBSP (has no
66    // emulation_prevention_three_bytes).
67    //
68    // self.state describes the state before self.inner[self.i].
69    //
70    // self.inner[self.i..] has yet to be examined.
71    inner: R,
72    state: ParseState,
73    i: usize,
74
75    /// The maximum number of bytes in a fresh chunk. Surprisingly, it's
76    /// significantly faster to limit this, maybe due to CPU cache effects, or
77    /// maybe because it's common to examine at most the headers of large slice NALs.
78    max_fill: usize,
79}
80impl<R: BufRead> ByteReader<R> {
81    /// Constructs an adapter from the given [`BufRead`] which does not skip any initial bytes.
82    pub fn without_skip(inner: R) -> Self {
83        Self {
84            inner,
85            state: ParseState::Start(0),
86            i: 0,
87            max_fill: 128,
88        }
89    }
90
91    /// Constructs an adapter from the given [`BufRead`] which skips the 1-byte H.264 header.
92    pub fn skipping_h264_header(inner: R) -> Self {
93        Self {
94            inner,
95            state: ParseState::Skip(H264_HEADER_LEN),
96            i: 0,
97            max_fill: 128,
98        }
99    }
100
101    /// Constructs an adapter from the given [`BufRead`] which will skip over the first `skip` bytes.
102    ///
103    /// This can be useful for parsing H.265, which uses the same
104    /// `emulation-prevention-three-bytes` convention but two-byte NAL headers.
105    pub fn skipping_bytes(inner: R, skip: NonZeroUsize) -> Self {
106        Self {
107            inner,
108            state: ParseState::Skip(skip),
109            i: 0,
110            max_fill: 128,
111        }
112    }
113
114    /// Called when self.i == 0 only; returns false at EOF.
115    /// Doesn't return actual buffer contents due to borrow checker limitations;
116    /// caller will need to call fill_buf again.
117    fn try_fill_buf_slow(&mut self) -> std::io::Result<bool> {
118        debug_assert_eq!(self.i, 0);
119        let chunk = self.inner.fill_buf()?;
120        if chunk.is_empty() {
121            return Ok(false);
122        }
123
124        let limit = std::cmp::min(chunk.len(), self.max_fill);
125        while self.i < limit {
126            match self.state {
127                ParseState::Start(zero_count) => {
128                    // Find the index of the byte right after a 0x00 0x00 pair,
129                    // or None if no complete pair is available in this chunk.
130                    let after_pair = if zero_count >= 2 {
131                        // Two trailing zeros carried from previous buffer.
132                        Some(self.i)
133                    } else if zero_count == 1 && chunk[self.i] == 0x00 {
134                        // One trailing zero + current 0x00 = cross-buffer pair.
135                        if self.i + 1 < limit {
136                            Some(self.i + 1)
137                        } else {
138                            self.state = ParseState::Start(2);
139                            self.i += 1;
140                            None
141                        }
142                    } else {
143                        // Bulk scan for the next 0x00 0x00 pair.
144                        match zero_pair_finder().find(&chunk[self.i..limit]) {
145                            Some(offset) => {
146                                let ap = self.i + offset + 2;
147                                if ap < limit {
148                                    Some(ap)
149                                } else {
150                                    self.state = ParseState::Start(2);
151                                    self.i = ap;
152                                    None
153                                }
154                            }
155                            None => {
156                                let trailing = if limit > self.i && chunk[limit - 1] == 0x00 {
157                                    1
158                                } else {
159                                    0
160                                };
161                                self.state = ParseState::Start(trailing);
162                                self.i = limit;
163                                None
164                            }
165                        }
166                    };
167                    let Some(after_pair) = after_pair else { break };
168                    // Check the byte after the 0x00 0x00 pair.
169                    match chunk[after_pair] {
170                        0x03 => {
171                            self.i = after_pair;
172                            self.state = ParseState::Three;
173                            break;
174                        }
175
176                        // H.264 section 7.4.1:
177                        // > Within the NAL unit, the following three-byte sequences shall not occur at
178                        // > any byte-aligned position:
179                        // > *   0x000000
180                        // > *   0x000001
181                        // > *   0x000002
182                        b @ 0x00..=0x02 => {
183                            return Err(std::io::Error::new(
184                                std::io::ErrorKind::InvalidData,
185                                format!("invalid RBSP byte {:#x} in state {:?}", b, &self.state,),
186                            ));
187                        }
188                        _ => {
189                            self.i = after_pair + 1;
190                            self.state = ParseState::Start(0);
191                            continue;
192                        }
193                    }
194                }
195                ParseState::Skip(remaining) => {
196                    debug_assert_eq!(self.i, 0);
197                    let skip = std::cmp::min(chunk.len(), remaining.get());
198                    self.inner.consume(skip);
199                    self.state = NonZeroUsize::new(remaining.get() - skip)
200                        .map(ParseState::Skip)
201                        .unwrap_or(ParseState::Start(0));
202                    break;
203                }
204                ParseState::Three => {
205                    debug_assert_eq!(self.i, 0);
206                    self.inner.consume(1);
207                    self.state = ParseState::PostThree;
208                    break;
209                }
210                ParseState::PostThree => {
211                    match chunk[self.i] {
212                        0x00 => self.state = ParseState::Start(1),
213                        0x01 | 0x02 | 0x03 => self.state = ParseState::Start(0),
214                        o => {
215                            return Err(std::io::Error::new(
216                                std::io::ErrorKind::InvalidData,
217                                format!("invalid RBSP byte {:#x} in state {:?}", o, &self.state),
218                            ))
219                        }
220                    }
221                    self.i += 1;
222                }
223            }
224        }
225        Ok(true)
226    }
227
228    /// Borrows the underlying reader
229    pub fn reader(&mut self) -> &mut R {
230        &mut self.inner
231    }
232}
233impl<R: BufRead> Read for ByteReader<R> {
234    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
235        let chunk = self.fill_buf()?;
236        let amt = std::cmp::min(buf.len(), chunk.len());
237        if amt == 1 {
238            // Stolen from std::io::Read implementation for &[u8]:
239            // apparently this is faster to special-case. (And this is the
240            // common case for BitReader.)
241            buf[0] = chunk[0];
242        } else {
243            buf[..amt].copy_from_slice(&chunk[..amt]);
244        }
245        self.consume(amt);
246        Ok(amt)
247    }
248}
249impl<R: BufRead> BufRead for ByteReader<R> {
250    fn fill_buf(&mut self) -> std::io::Result<&[u8]> {
251        while self.i == 0 && self.try_fill_buf_slow()? {}
252        Ok(&self.inner.fill_buf()?[0..self.i])
253    }
254
255    fn consume(&mut self, amt: usize) {
256        self.i = self.i.checked_sub(amt).unwrap();
257        self.inner.consume(amt);
258    }
259}
260
261/// Returns RBSP from a NAL by removing the NAL header and `emulation-prevention-three` bytes.
262///
263/// See also [module docs](self).
264///
265/// Returns error on invalid byte sequences. Returns a borrowed pointer if possible.
266///
267/// ```
268/// # use h264_reader::rbsp::decode_nal;
269/// # use std::borrow::Cow;
270/// # use std::io::ErrorKind;
271/// let nal_with_escape = &b"\x68\x12\x34\x00\x00\x03\x00\x86"[..];
272/// assert!(matches!(
273///     decode_nal(nal_with_escape).unwrap(),
274///     Cow::Owned(s) if s == &b"\x12\x34\x00\x00\x00\x86"[..]));
275///
276/// let nal_without_escape = &b"\x68\xE8\x43\x8F\x13\x21\x30"[..];
277/// assert_eq!(decode_nal(nal_without_escape).unwrap(), Cow::Borrowed(&nal_without_escape[1..]));
278///
279/// let invalid_nal = &b"\x68\x12\x34\x00\x00\x00\x86"[..];
280/// assert_eq!(decode_nal(invalid_nal).unwrap_err().kind(), ErrorKind::InvalidData);
281/// ```
282pub fn decode_nal<'a>(nal_unit: &'a [u8]) -> Result<Cow<'a, [u8]>, std::io::Error> {
283    let mut reader = ByteReader {
284        inner: nal_unit,
285        state: ParseState::Skip(H264_HEADER_LEN),
286        i: 0,
287        max_fill: usize::MAX, // to borrow if at all possible.
288    };
289    let buf = reader.fill_buf()?;
290    if buf.len() + 1 == nal_unit.len() {
291        return Ok(Cow::Borrowed(&nal_unit[1..]));
292    }
293    // Upper bound estimate; skipping the NAL header and at least one emulation prevention byte.
294    let mut dst = Vec::with_capacity(nal_unit.len() - 2);
295    loop {
296        let buf = reader.fill_buf()?;
297        if buf.is_empty() {
298            break;
299        }
300        dst.extend_from_slice(buf);
301        let len = buf.len();
302        reader.consume(len);
303    }
304    Ok(Cow::Owned(dst))
305}
306
307#[derive(Debug)]
308pub enum BitReaderError {
309    /// An I/O error occurred reading the given field.
310    ReaderError(&'static str, std::io::Error),
311
312    /// An Exp-Golomb-coded syntax elements value has more than 32 bits.
313    ExpGolombTooLarge(&'static str),
314
315    /// The stream was positioned before the final one bit on [BitRead::finish_rbsp].
316    RemainingData,
317}
318
319pub trait Integer: bitstream_io::Integer + std::fmt::Debug {}
320impl<I: bitstream_io::Integer + std::fmt::Debug> Integer for I {}
321
322pub trait Primitive: bitstream_io::Primitive + std::fmt::Debug {}
323impl<P: bitstream_io::Primitive + std::fmt::Debug> Primitive for P {}
324
325/// Writes H.26x bitstream syntax elements.
326///
327/// This is the write counterpart to [`BitRead`].
328pub trait BitWrite {
329    /// Writes an unsigned Exp-Golomb-coded value, as defined in the H.264 spec.
330    fn write_ue(&mut self, value: u32) -> std::io::Result<()>;
331
332    /// Writes a signed Exp-Golomb-coded value, as defined in the H.264 spec.
333    fn write_se(&mut self, value: i32) -> std::io::Result<()>;
334
335    /// Writes a single bit.
336    fn write_bit(&mut self, bit: bool) -> std::io::Result<()>;
337
338    /// Writes `BITS` bits of `value`.
339    fn write<const BITS: u32, I: Integer>(&mut self, value: I) -> std::io::Result<()>;
340
341    /// Writes `bit_count` bits of `value`.
342    fn write_var<I: Integer>(&mut self, bit_count: u32, value: I) -> std::io::Result<()>;
343
344    /// Writes the RBSP trailing bits: a stop bit (1) and then zero-padding to byte boundary.
345    fn write_rbsp_trailing_bits(&mut self) -> std::io::Result<()>;
346}
347
348/// Reads H.26x bitstream elements as specified in H.264 section 7.2.
349pub trait BitRead {
350    /// Reads an unsigned Exp-Golomb-coded value, as defined in the H.264 spec.
351    fn read_ue(&mut self, name: &'static str) -> Result<u32, BitReaderError>;
352
353    /// Reads a signed Exp-Golomb-coded value, as defined in the H.264 spec.
354    fn read_se(&mut self, name: &'static str) -> Result<i32, BitReaderError>;
355
356    /// Reads a single bit, as in [`crate::bitstream_io::read::BitRead::read_bit`].
357    fn read_bit(&mut self, name: &'static str) -> Result<bool, BitReaderError>;
358
359    /// Reads a value from the bitstream with a statically-known number of bits, as in
360    /// [`crate::bitstream_io::read::BitRead::read`]. This matches the `u(BITS)`
361    /// and `i(BITS)` syntax elements.
362    fn read<const BITS: u32, I: Integer>(
363        &mut self,
364        name: &'static str,
365    ) -> Result<I, BitReaderError>;
366
367    /// Reads a value from the bitstream with a runtime-determined number of bits, as in
368    /// [`crate::bitstream_io::read::BitRead::read_var`]. This matches the
369    /// `u(bit_count)` and `i(bit_count)` syntax elements.
370    fn read_var<I: Integer>(
371        &mut self,
372        bit_count: u32,
373        name: &'static str,
374    ) -> Result<I, BitReaderError>;
375
376    /// Reads a whole value from the bitstream whose size is equal to its byte size, as in
377    /// [`crate::bitstream_io::read::BitRead::read_to`].
378    fn read_to<V: Primitive>(&mut self, name: &'static str) -> Result<V, BitReaderError>;
379
380    /// Skips the given number of bits in the bitstream, as in
381    /// [`crate::bitstream_io::read::BitRead::skip`].
382    fn skip(&mut self, bit_count: u32, name: &'static str) -> Result<(), BitReaderError>;
383
384    /// Returns true if the reader is at a byte boundary.
385    fn byte_aligned(&self) -> bool;
386
387    /// Returns true if positioned before the RBSP trailing bits.
388    ///
389    /// This matches the definition of `more_rbsp_data()` in Rec. ITU-T H.264
390    /// (03/2010) section 7.2.
391    fn has_more_rbsp_data(&mut self, name: &'static str) -> Result<bool, BitReaderError>;
392
393    /// Consumes the reader, returning error if it's not positioned at the RBSP trailing bits.
394    fn finish_rbsp(self) -> Result<(), BitReaderError>;
395
396    /// Consumes the reader, returning error if this `sei_payload` message is unfinished.
397    ///
398    /// This is similar to `finish_rbsp`, but SEI payloads have no trailing bits if
399    /// already byte-aligned.
400    fn finish_sei_payload(self) -> Result<(), BitReaderError>;
401}
402
403/// Reads H.264 bitstream syntax elements from an RBSP representation (no NAL
404/// header byte or emulation prevention three bytes).
405///
406/// Use `BitReader::new(ByteReader::skipping_h264_header(nal))` to read the bit stream
407/// from a complete NAL representation, including header and emulation prevention three bytes.
408pub struct BitReader<R: std::io::BufRead + Clone> {
409    reader: bitstream_io::read::BitReader<R, bitstream_io::BigEndian>,
410}
411impl<R: std::io::BufRead + Clone> BitReader<R> {
412    pub fn new(inner: R) -> Self {
413        Self {
414            reader: bitstream_io::read::BitReader::new(inner),
415        }
416    }
417
418    /// Borrows the underlying reader if byte-aligned.
419    pub fn reader(&mut self) -> Option<&mut R> {
420        self.reader.reader()
421    }
422
423    /// Unwraps internal reader and disposes of BitReader.
424    ///
425    /// # Warning
426    ///
427    /// Any unread partial bits are discarded.
428    pub fn into_reader(self) -> R {
429        self.reader.into_reader()
430    }
431}
432
433impl<R: std::io::BufRead + Clone> BitRead for BitReader<R> {
434    fn read_ue(&mut self, name: &'static str) -> Result<u32, BitReaderError> {
435        let count = self
436            .reader
437            .read_unary::<1>()
438            .map_err(|e| BitReaderError::ReaderError(name, e))?;
439        if count > 31 {
440            return Err(BitReaderError::ExpGolombTooLarge(name));
441        } else if count > 0 {
442            let val: u32 = self.read_var(count, name)?;
443            Ok((1 << count) - 1 + val)
444        } else {
445            Ok(0)
446        }
447    }
448
449    fn read_se(&mut self, name: &'static str) -> Result<i32, BitReaderError> {
450        Ok(golomb_to_signed(self.read_ue(name)?))
451    }
452
453    fn read_bit(&mut self, name: &'static str) -> Result<bool, BitReaderError> {
454        self.reader
455            .read_bit()
456            .map_err(|e| BitReaderError::ReaderError(name, e))
457    }
458
459    fn read<const BITS: u32, I: Integer>(
460        &mut self,
461        name: &'static str,
462    ) -> Result<I, BitReaderError> {
463        self.reader
464            .read::<BITS, I>()
465            .map_err(|e| BitReaderError::ReaderError(name, e))
466    }
467
468    fn read_var<I: Integer>(
469        &mut self,
470        bit_count: u32,
471        name: &'static str,
472    ) -> Result<I, BitReaderError> {
473        self.reader
474            .read_var(bit_count)
475            .map_err(|e| BitReaderError::ReaderError(name, e))
476    }
477
478    fn read_to<V: Primitive>(&mut self, name: &'static str) -> Result<V, BitReaderError> {
479        self.reader
480            .read_to()
481            .map_err(|e| BitReaderError::ReaderError(name, e))
482    }
483
484    fn skip(&mut self, bit_count: u32, name: &'static str) -> Result<(), BitReaderError> {
485        self.reader
486            .skip(bit_count)
487            .map_err(|e| BitReaderError::ReaderError(name, e))
488    }
489
490    fn byte_aligned(&self) -> bool {
491        self.reader.byte_aligned()
492    }
493
494    fn has_more_rbsp_data(&mut self, name: &'static str) -> Result<bool, BitReaderError> {
495        let mut throwaway = self.reader.clone();
496        let r = (move || {
497            throwaway.skip(1)?;
498            throwaway.read_unary::<1>()?;
499            Ok::<_, std::io::Error>(())
500        })();
501        match r {
502            Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => Ok(false),
503            Err(e) => Err(BitReaderError::ReaderError(name, e)),
504            Ok(_) => Ok(true),
505        }
506    }
507
508    fn finish_rbsp(mut self) -> Result<(), BitReaderError> {
509        // The next bit is expected to be the final one bit.
510        if !self
511            .reader
512            .read_bit()
513            .map_err(|e| BitReaderError::ReaderError("finish", e))?
514        {
515            // It was a zero! Determine if we're past the end or haven't reached it yet.
516            match self.reader.read_unary::<1>() {
517                Err(e) => return Err(BitReaderError::ReaderError("finish", e)),
518                Ok(_) => return Err(BitReaderError::RemainingData),
519            }
520        }
521        // All remaining bits in the stream must then be zeros.
522        match self.reader.read_unary::<1>() {
523            Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => Ok(()),
524            Err(e) => Err(BitReaderError::ReaderError("finish", e)),
525            Ok(_) => Err(BitReaderError::RemainingData),
526        }
527    }
528
529    fn finish_sei_payload(mut self) -> Result<(), BitReaderError> {
530        match self.reader.read_bit() {
531            Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => return Ok(()),
532            Err(e) => return Err(BitReaderError::ReaderError("finish", e)),
533            Ok(false) => return Err(BitReaderError::RemainingData),
534            Ok(true) => {}
535        }
536        match self.reader.read_unary::<1>() {
537            Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => Ok(()),
538            Err(e) => Err(BitReaderError::ReaderError("finish", e)),
539            Ok(_) => Err(BitReaderError::RemainingData),
540        }
541    }
542}
543fn golomb_to_signed(val: u32) -> i32 {
544    let sign = (((val & 0x1) as i32) << 1) - 1;
545    ((val >> 1) as i32 + (val & 0x1) as i32) * sign
546}
547
548/// Writes H.264 bitstream syntax elements to RBSP writer.
549pub struct BitWriter<W: std::io::Write> {
550    inner: bitstream_io::write::BitWriter<W, bitstream_io::BigEndian>,
551}
552
553impl<W: std::io::Write> BitWriter<W> {
554    /// Creates a new `BitWriter` writing to `writer`.
555    pub fn new(writer: W) -> Self {
556        Self {
557            inner: bitstream_io::write::BitWriter::new(writer),
558        }
559    }
560
561    /// Returns a mutable reference to the underlying writer, if the stream is byte-aligned.
562    pub fn writer(&mut self) -> Option<&mut W> {
563        self.inner.writer()
564    }
565
566    /// Returns the underlying writer.
567    ///
568    /// # Warning
569    ///
570    /// Any unwritten partial bits are discarded.
571    pub fn into_writer(self) -> W {
572        self.inner.into_writer()
573    }
574}
575
576impl<W: std::io::Write> BitWrite for BitWriter<W> {
577    fn write_ue(&mut self, value: u32) -> std::io::Result<()> {
578        // Exp-Golomb: write (count) zero bits, then 1 bit, then (count) data bits.
579        // code_num = value, M = floor(log2(value+1)), prefix is (M+1) bits = M zeros + 1 one,
580        // suffix is M bits = value+1 - 2^M.
581        if value == 0 {
582            self.inner.write_bit(true)
583        } else {
584            let code_num = value + 1;
585            let bits = 32 - code_num.leading_zeros(); // = floor(log2(code_num)) + 1
586            let zeros = bits - 1;
587            // write (zeros) zero bits
588            for _ in 0..zeros {
589                self.inner.write_bit(false)?;
590            }
591            // write (bits) bits of code_num
592            self.inner.write_var(bits, code_num)
593        }
594    }
595
596    fn write_se(&mut self, value: i32) -> std::io::Result<()> {
597        // Map signed -> unsigned: 0->0, 1->1, -1->2, 2->3, -2->4, ...
598        let code_num = if value > 0 {
599            (value as u32) * 2 - 1
600        } else {
601            (-value as u32) * 2
602        };
603        self.write_ue(code_num)
604    }
605
606    fn write_bit(&mut self, bit: bool) -> std::io::Result<()> {
607        self.inner.write_bit(bit)
608    }
609
610    fn write<const BITS: u32, I: Integer>(&mut self, value: I) -> std::io::Result<()> {
611        self.inner.write::<BITS, I>(value)
612    }
613
614    fn write_var<I: Integer>(&mut self, bit_count: u32, value: I) -> std::io::Result<()> {
615        self.inner.write_var::<I>(bit_count, value)
616    }
617
618    fn write_rbsp_trailing_bits(&mut self) -> std::io::Result<()> {
619        self.inner.write_bit(true)?; // stop bit
620        self.inner.byte_align()?; // zero-pad to byte boundary
621        Ok(())
622    }
623}
624
625/// [`Write`] adapter which inserts emulation-prevention-three bytes into RBSP.
626///
627/// The caller writes raw RBSP bytes; this inserts `0x03` bytes wherever the
628/// sequence `0x00 0x00` would be followed by `0x00`, `0x01`, `0x02`, or `0x03`.
629///
630/// See also [module docs](self).
631pub struct ByteWriter<W: Write> {
632    inner: W,
633    /// Number of consecutive `0x00` bytes at the tail of what has been written
634    /// so far. Always 0, 1, or 2.
635    zero_count: u8,
636}
637
638impl<W: Write> ByteWriter<W> {
639    /// Creates a new `ByteWriter` wrapping the given [`Write`].
640    pub fn new(inner: W) -> Self {
641        Self {
642            inner,
643            zero_count: 0,
644        }
645    }
646
647    /// Returns the underlying writer.
648    pub fn into_writer(self) -> W {
649        self.inner
650    }
651}
652
653impl<W: Write> Write for ByteWriter<W> {
654    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
655        let mut i = 0;
656        let mut chunk_start = 0;
657        while i < buf.len() {
658            // When two trailing zeros have been written, the current byte may
659            // require an emulation-prevention byte inserted before it.
660            if self.zero_count == 2 {
661                let b = buf[i];
662                if b <= 3 {
663                    self.inner.write_all(&buf[chunk_start..i])?;
664                    chunk_start = i;
665                    self.inner.write_all(&[0x03])?;
666                }
667                self.zero_count = 0;
668                // Fall through; the memchr scan below processes buf[i].
669            }
670            // zero_count is 0 or 1 here. Use memchr to skip non-zero bytes.
671            match memchr::memchr(0x00, &buf[i..]) {
672                None => {
673                    self.zero_count = 0;
674                    break;
675                }
676                Some(rel) => {
677                    // buf[i..i+rel] are non-zero (any of them resets zero_count),
678                    // buf[i+rel] is 0x00.
679                    self.zero_count = if rel > 0 { 1 } else { self.zero_count + 1 };
680                    i += rel + 1;
681                }
682            }
683        }
684        self.inner.write_all(&buf[chunk_start..])?;
685        Ok(buf.len())
686    }
687
688    fn flush(&mut self) -> std::io::Result<()> {
689        self.inner.flush()
690    }
691}
692
693#[cfg(test)]
694mod tests {
695    use super::*;
696    use hex_literal::*;
697    use hex_slice::AsHex;
698
699    #[test]
700    fn byte_reader() {
701        let data = hex!(
702            "67 64 00 0A AC 72 84 44 26 84 00 00 03
703            00 04 00 00 03 00 CA 3C 48 96 11 80"
704        );
705        for i in 1..data.len() - 1 {
706            let (head, tail) = data.split_at(i);
707            let r = head.chain(tail);
708            let mut r = ByteReader::skipping_h264_header(r);
709            let mut rbsp = Vec::new();
710            r.read_to_end(&mut rbsp).unwrap();
711            let expected = hex!(
712                "64 00 0A AC 72 84 44 26 84 00 00
713            00 04 00 00 00 CA 3C 48 96 11 80"
714            );
715            assert!(
716                rbsp == &expected[..],
717                "Mismatch with on split_at({}):\nrbsp     {:02x}\nexpected {:02x}",
718                i,
719                rbsp.as_hex(),
720                expected.as_hex()
721            );
722        }
723    }
724
725    #[test]
726    fn bitreader_has_more_data() {
727        // Should work when the end bit is byte-aligned.
728        let mut reader = BitReader::new(&[0x12, 0x80][..]);
729        assert!(reader.has_more_rbsp_data("call 1").unwrap());
730        assert_eq!(reader.read::<8, u8>("u8 1").unwrap(), 0x12);
731        assert!(!reader.has_more_rbsp_data("call 2").unwrap());
732
733        // and when it's not.
734        let mut reader = BitReader::new(&[0x18][..]);
735        assert!(reader.has_more_rbsp_data("call 3").unwrap());
736        assert_eq!(reader.read::<4, u8>("u8 2").unwrap(), 0x1);
737        assert!(!reader.has_more_rbsp_data("call 4").unwrap());
738
739        // should also work when there are cabac-zero-words.
740        let mut reader = BitReader::new(&[0x80, 0x00, 0x00][..]);
741        assert!(!reader
742            .has_more_rbsp_data("at end with cabac-zero-words")
743            .unwrap());
744    }
745
746    #[test]
747    fn byte_reader_emulation_prevention_beyond_max_fill() {
748        // Input: 129 non-zero bytes followed by an emulation prevention
749        // sequence (00 00 03 01). With max_fill=128, the initial memchr scan
750        // only covers the first 128 bytes. A bug caused bytes beyond max_fill
751        // to be returned as RBSP without being checked, so the 0x03 emulation
752        // prevention byte would not be stripped.
753        let mut input = vec![0xFF; 129];
754        input.extend_from_slice(&[0x00, 0x00, 0x03, 0x01]);
755        let mut r = ByteReader::without_skip(&input[..]);
756        let mut rbsp = Vec::new();
757        r.read_to_end(&mut rbsp).unwrap();
758        let mut expected = vec![0xFF; 129];
759        expected.extend_from_slice(&[0x00, 0x00, 0x01]);
760        assert_eq!(rbsp, expected, "emulation prevention byte was not stripped");
761    }
762
763    #[test]
764    fn read_ue_overflow() {
765        let mut reader = BitReader::new(&[0, 0, 0, 0, 255, 255, 255, 255, 255][..]);
766        assert!(matches!(
767            reader.read_ue("test"),
768            Err(BitReaderError::ExpGolombTooLarge("test"))
769        ));
770    }
771
772    /// Writes `rbsp` through a `ByteWriter` and returns the emulation-prevention-encoded bytes.
773    fn byte_writer_encode(rbsp: &[u8]) -> Vec<u8> {
774        let mut out = Vec::new();
775        ByteWriter::new(&mut out).write_all(rbsp).unwrap();
776        out
777    }
778
779    #[test]
780    fn byte_writer_no_escaping_needed() {
781        // Bytes that never trigger emulation prevention.
782        assert_eq!(byte_writer_encode(b"hello"), b"hello");
783        assert_eq!(
784            byte_writer_encode(&[0xFF, 0xFE, 0x01, 0x02]),
785            &[0xFF, 0xFE, 0x01, 0x02]
786        );
787        // Single zero: no escape.
788        assert_eq!(byte_writer_encode(&[0x00, 0x04]), &[0x00, 0x04]);
789        // Two zeros followed by non-trigger byte: no escape.
790        assert_eq!(byte_writer_encode(&[0x00, 0x00, 0x04]), &[0x00, 0x00, 0x04]);
791    }
792
793    #[test]
794    fn byte_writer_escaping() {
795        // The four trigger bytes after two zeros.
796        assert_eq!(
797            byte_writer_encode(&[0x00, 0x00, 0x00]),
798            &[0x00, 0x00, 0x03, 0x00]
799        );
800        assert_eq!(
801            byte_writer_encode(&[0x00, 0x00, 0x01]),
802            &[0x00, 0x00, 0x03, 0x01]
803        );
804        assert_eq!(
805            byte_writer_encode(&[0x00, 0x00, 0x02]),
806            &[0x00, 0x00, 0x03, 0x02]
807        );
808        assert_eq!(
809            byte_writer_encode(&[0x00, 0x00, 0x03]),
810            &[0x00, 0x00, 0x03, 0x03]
811        );
812    }
813
814    #[test]
815    fn byte_writer_multiple_escapes() {
816        // Five zeros then 0x01: the third zero triggers one escape (leaving one
817        // trailing zero), then the fifth zero makes two trailing zeros again so
818        // 0x01 triggers a second escape.
819        assert_eq!(
820            byte_writer_encode(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x01]),
821            &[0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x01],
822        );
823    }
824
825    #[test]
826    fn byte_writer_split_writes() {
827        // Verify state is maintained across separate write() calls.
828        let mut out = Vec::new();
829        let mut w = ByteWriter::new(&mut out);
830        w.write_all(&[0x00, 0x00]).unwrap();
831        w.write_all(&[0x03]).unwrap(); // should be escaped
832        drop(w);
833        assert_eq!(out, &[0x00, 0x00, 0x03, 0x03]);
834
835        let mut out2 = Vec::new();
836        let mut w2 = ByteWriter::new(&mut out2);
837        w2.write_all(&[0x00]).unwrap();
838        w2.write_all(&[0x00]).unwrap();
839        w2.write_all(&[0x01]).unwrap(); // should be escaped
840        drop(w2);
841        assert_eq!(out2, &[0x00, 0x00, 0x03, 0x01]);
842    }
843
844    /// Builds a complete NAL unit from `hdr` and `rbsp` using `ByteWriter`.
845    fn make_nal(hdr: u8, rbsp: &[u8]) -> Vec<u8> {
846        // Capacity: at most 1 escape per 3 RBSP bytes.
847        let mut out = Vec::with_capacity(1 + rbsp.len() + rbsp.len() / 3);
848        out.push(hdr);
849        ByteWriter::new(&mut out).write_all(rbsp).unwrap();
850        out
851    }
852
853    #[test]
854    fn byte_writer_roundtrip() {
855        // Roundtrip: decode(make_nal(hdr, rbsp)) == rbsp.
856        let rbsp = hex!(
857            "64 00 0A AC 72 84 44 26 84 00 00
858            00 04 00 00 00 CA 3C 48 96 11 80"
859        );
860        let nal = make_nal(0x67, &rbsp);
861        let decoded = decode_nal(&nal).unwrap();
862        assert_eq!(&*decoded, &rbsp[..]);
863    }
864
865    #[test]
866    fn byte_reader_rejects_forbidden_sequences() {
867        // H.264 section 7.4.1: within a NAL unit, the three-byte sequences
868        // 0x000000, 0x000001, and 0x000002 shall not occur at any byte-aligned
869        // position. ByteReader must return InvalidData for all three.
870        for forbidden in [0x00u8, 0x01, 0x02] {
871            let nal = [0x67, 0x12, 0x00, 0x00, forbidden, 0x34];
872            let mut r = ByteReader::skipping_h264_header(&nal[..]);
873            let mut buf = Vec::new();
874            let err = r.read_to_end(&mut buf).unwrap_err();
875            assert_eq!(
876                err.kind(),
877                std::io::ErrorKind::InvalidData,
878                "expected InvalidData for 0x00 0x00 {:#04x}, got {:?}",
879                forbidden,
880                err.kind(),
881            );
882        }
883    }
884
885    #[test]
886    fn byte_writer_escape_inserted_in_nal() {
887        // RBSP: 12 34 00 00 00 86 -> NAL: 68 12 34 00 00 03 00 86
888        assert_eq!(
889            make_nal(0x68, &hex!("12 34 00 00 00 86")),
890            hex!("68 12 34 00 00 03 00 86"),
891        );
892    }
893}