// Copyright 2024 The ChromiumOS Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. use std::borrow::Cow; use std::fmt; use std::io::Cursor; use std::io::Read; use std::io::Seek; use std::io::SeekFrom; use std::io::Write; use std::marker::PhantomData; use crate::codec::h264::parser::Nalu as H264Nalu; use crate::codec::h265::parser::Nalu as H265Nalu; /// A bit reader for codec bitstreams. It properly handles emulation-prevention /// bytes and stop bits for H264. #[derive(Clone)] pub(crate) struct BitReader<'a> { /// A reference into the next unread byte in the stream. data: Cursor<&'a [u8]>, /// Contents of the current byte. First unread bit starting at position 8 - /// num_remaining_bits_in_curr_bytes. curr_byte: u8, /// Number of bits remaining in `curr_byte` num_remaining_bits_in_curr_byte: usize, /// Used in emulation prevention byte detection. prev_two_bytes: u16, /// Number of emulation prevention bytes (i.e. 0x000003) we found. num_epb: usize, /// Whether or not we need emulation prevention logic. needs_epb: bool, /// How many bits have been read so far. position: u64, } #[derive(Debug)] pub(crate) enum GetByteError { OutOfBits, } impl fmt::Display for GetByteError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "reader ran out of bits") } } #[derive(Debug)] pub(crate) enum ReadBitsError { TooManyBitsRequested(usize), GetByte(GetByteError), ConversionFailed, } impl fmt::Display for ReadBitsError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ReadBitsError::TooManyBitsRequested(bits) => { write!(f, "more than 31 ({}) bits were requested", bits) } ReadBitsError::GetByte(_) => write!(f, "failed to advance the current byte"), ReadBitsError::ConversionFailed => { write!(f, "failed to convert read input to target type") } } } } impl From for ReadBitsError { fn from(err: GetByteError) -> Self { ReadBitsError::GetByte(err) } } impl<'a> BitReader<'a> { pub fn new(data: &'a [u8], needs_epb: bool) -> Self { Self { data: Cursor::new(data), curr_byte: Default::default(), num_remaining_bits_in_curr_byte: Default::default(), prev_two_bytes: 0xffff, num_epb: Default::default(), needs_epb: needs_epb, position: 0, } } /// Read a single bit from the stream. pub fn read_bit(&mut self) -> Result { let bit = self.read_bits::(1)?; match bit { 1 => Ok(true), 0 => Ok(false), _ => panic!("Unexpected value {}", bit), } } /// Read up to 31 bits from the stream. Note that we don't want to read 32 /// bits even though we're returning a u32 because that would break the /// read_bits_signed() function. 31 bits should be overkill for compressed /// header parsing anyway. pub fn read_bits>(&mut self, num_bits: usize) -> Result { if num_bits > 31 { return Err(ReadBitsError::TooManyBitsRequested(num_bits).to_string()); } let mut bits_left = num_bits; let mut out = 0u32; while self.num_remaining_bits_in_curr_byte < bits_left { out |= (self.curr_byte as u32) << (bits_left - self.num_remaining_bits_in_curr_byte); bits_left -= self.num_remaining_bits_in_curr_byte; self.move_to_next_byte().map_err(|err| err.to_string())?; } out |= (self.curr_byte >> (self.num_remaining_bits_in_curr_byte - bits_left)) as u32; out &= (1 << num_bits) - 1; self.num_remaining_bits_in_curr_byte -= bits_left; self.position += num_bits as u64; U::try_from(out).map_err(|_| ReadBitsError::ConversionFailed.to_string()) } /// Reads a two's complement signed integer of length |num_bits|. pub fn read_bits_signed>(&mut self, num_bits: usize) -> Result { let mut out: i32 = self .read_bits::(num_bits)? .try_into() .map_err(|_| ReadBitsError::ConversionFailed.to_string())?; if out >> (num_bits - 1) != 0 { out |= -1i32 ^ ((1 << num_bits) - 1); } U::try_from(out).map_err(|_| ReadBitsError::ConversionFailed.to_string()) } /// Reads an unsigned integer from the stream and checks if the stream is byte aligned. pub fn read_bits_aligned>(&mut self, num_bits: usize) -> Result { if self.num_remaining_bits_in_curr_byte % 8 != 0 { return Err("Attempted unaligned read_le()".into()); } Ok(self.read_bits(num_bits).map_err(|err| err.to_string())?) } /// Skip `num_bits` bits from the stream. pub fn skip_bits(&mut self, mut num_bits: usize) -> Result<(), String> { while num_bits > 0 { let n = std::cmp::min(num_bits, 31); self.read_bits::(n)?; num_bits -= n; } Ok(()) } /// Returns the amount of bits left in the stream pub fn num_bits_left(&mut self) -> usize { let cur_pos = self.data.position(); // This should always be safe to unwrap. let end_pos = self.data.seek(SeekFrom::End(0)).unwrap(); let _ = self.data.seek(SeekFrom::Start(cur_pos)); ((end_pos - cur_pos) as usize) * 8 + self.num_remaining_bits_in_curr_byte } /// Returns the number of emulation-prevention bytes read so far. pub fn num_epb(&self) -> usize { self.num_epb } /// Whether the stream still has RBSP data. Implements more_rbsp_data(). See /// the spec for more details. pub fn has_more_rsbp_data(&mut self) -> bool { if self.num_remaining_bits_in_curr_byte == 0 && self.move_to_next_byte().is_err() { // no more data at all in the rbsp return false; } // If the next bit is the stop bit, then we should only see unset bits // until the end of the data. if (self.curr_byte & ((1 << (self.num_remaining_bits_in_curr_byte - 1)) - 1)) != 0 { return true; } let mut buf = [0u8; 1]; let orig_pos = self.data.position(); while let Ok(_) = self.data.read_exact(&mut buf) { if buf[0] != 0 { self.data.set_position(orig_pos); return true; } } false } /// Reads an Unsigned Exponential golomb coding number from the next bytes in the /// bitstream. This may advance the state of position within the bitstream even if the /// read operation is unsuccessful. See H264 Annex B specification 9.1 for details. pub fn read_ue>(&mut self) -> Result { let mut num_bits = 0; while self.read_bits::(1)? == 0 { num_bits += 1; if num_bits > 31 { return Err("invalid stream".into()); } } let value = ((1u32 << num_bits) - 1) .checked_add(self.read_bits::(num_bits)?) .ok_or::("read number cannot fit in 32 bits".into())?; U::try_from(value).map_err(|_| "conversion error".into()) } pub fn read_ue_bounded>(&mut self, min: u32, max: u32) -> Result { let ue = self.read_ue()?; if ue > max || ue < min { Err(format!("Value out of bounds: expected {} - {}, got {}", min, max, ue)) } else { Ok(U::try_from(ue).map_err(|_| String::from("Conversion error"))?) } } pub fn read_ue_max>(&mut self, max: u32) -> Result { self.read_ue_bounded(0, max) } /// Reads a signed exponential golomb coding number. Instead of using two's /// complement, this scheme maps even integers to positive numbers and odd /// integers to negative numbers. The least significant bit indicates the /// sign. See H264 Annex B specification 9.1.1 for details. pub fn read_se>(&mut self) -> Result { let ue = self.read_ue::()? as i32; if ue % 2 == 0 { Ok(U::try_from(-(ue / 2)).map_err(|_| String::from("Conversion error"))?) } else { Ok(U::try_from(ue / 2 + 1).map_err(|_| String::from("Conversion error"))?) } } pub fn read_se_bounded>(&mut self, min: i32, max: i32) -> Result { let se = self.read_se()?; if se < min || se > max { Err(format!("Value out of bounds, expected between {}-{}, got {}", min, max, se)) } else { Ok(U::try_from(se).map_err(|_| String::from("Conversion error"))?) } } /// Read little endian multi-byte integer. pub fn read_le>(&mut self, num_bits: u8) -> Result { let mut t = 0; for i in 0..num_bits { let byte = self.read_bits_aligned::(8)?; t += byte << (i * 8) } Ok(U::try_from(t).map_err(|_| String::from("Conversion error"))?) } /// Return the position of this bitstream in bits. pub fn position(&self) -> u64 { self.position } fn get_byte(&mut self) -> Result { let mut buf = [0u8; 1]; self.data.read_exact(&mut buf).map_err(|_| GetByteError::OutOfBits)?; Ok(buf[0]) } fn move_to_next_byte(&mut self) -> Result<(), GetByteError> { let mut byte = self.get_byte()?; if self.needs_epb { if self.prev_two_bytes == 0 && byte == 0x03 { // We found an epb self.num_epb += 1; // Read another byte byte = self.get_byte()?; // We need another 3 bytes before another epb can happen. self.prev_two_bytes = 0xffff; } self.prev_two_bytes = (self.prev_two_bytes << 8) | u16::from(byte); } self.num_remaining_bits_in_curr_byte = 8; self.curr_byte = byte; Ok(()) } } /// Iterator over IVF packets. pub struct IvfIterator<'a> { cursor: Cursor<&'a [u8]>, } impl<'a> IvfIterator<'a> { pub fn new(data: &'a [u8]) -> Self { let mut cursor = Cursor::new(data); // Skip the IVH header entirely. cursor.seek(std::io::SeekFrom::Start(32)).unwrap(); Self { cursor } } } impl<'a> Iterator for IvfIterator<'a> { type Item = &'a [u8]; fn next(&mut self) -> Option { // Make sure we have a header. let mut len_buf = [0u8; 4]; self.cursor.read_exact(&mut len_buf).ok()?; let len = ((len_buf[3] as usize) << 24) | ((len_buf[2] as usize) << 16) | ((len_buf[1] as usize) << 8) | (len_buf[0] as usize); // Skip PTS. self.cursor.seek(std::io::SeekFrom::Current(8)).ok()?; let start = self.cursor.position() as usize; let _ = self.cursor.seek(std::io::SeekFrom::Current(len as i64)).ok()?; let end = self.cursor.position() as usize; Some(&self.cursor.get_ref()[start..end]) } } /// Helper struct for synthesizing IVF file header pub struct IvfFileHeader { pub magic: [u8; 4], pub version: u16, pub header_size: u16, pub codec: [u8; 4], pub width: u16, pub height: u16, pub framerate: u32, pub timescale: u32, pub frame_count: u32, pub unused: u32, } impl Default for IvfFileHeader { fn default() -> Self { Self { magic: Self::MAGIC, version: 0, header_size: 32, codec: Self::CODEC_VP9, width: 320, height: 240, framerate: 1, timescale: 1000, frame_count: 1, unused: Default::default(), } } } impl IvfFileHeader { pub const MAGIC: [u8; 4] = *b"DKIF"; pub const CODEC_VP8: [u8; 4] = *b"VP80"; pub const CODEC_VP9: [u8; 4] = *b"VP90"; pub const CODEC_AV1: [u8; 4] = *b"AV01"; pub fn new(codec: [u8; 4], width: u16, height: u16, framerate: u32, frame_count: u32) -> Self { let default = Self::default(); Self { codec, width, height, framerate: framerate * default.timescale, frame_count, ..default } } } impl IvfFileHeader { /// Writes header into writer pub fn writo_into(&self, writer: &mut impl std::io::Write) -> std::io::Result<()> { writer.write_all(&self.magic)?; writer.write_all(&self.version.to_le_bytes())?; writer.write_all(&self.header_size.to_le_bytes())?; writer.write_all(&self.codec)?; writer.write_all(&self.width.to_le_bytes())?; writer.write_all(&self.height.to_le_bytes())?; writer.write_all(&self.framerate.to_le_bytes())?; writer.write_all(&self.timescale.to_le_bytes())?; writer.write_all(&self.frame_count.to_le_bytes())?; writer.write_all(&self.unused.to_le_bytes())?; Ok(()) } } /// Helper struct for synthesizing IVF frame header pub struct IvfFrameHeader { pub frame_size: u32, pub timestamp: u64, } impl IvfFrameHeader { /// Writes header into writer pub fn writo_into(&self, writer: &mut impl std::io::Write) -> std::io::Result<()> { writer.write_all(&self.frame_size.to_le_bytes())?; writer.write_all(&self.timestamp.to_le_bytes())?; Ok(()) } } /// Iterator NALUs in a bitstream. pub struct NalIterator<'a, Nalu>(Cursor<&'a [u8]>, PhantomData); impl<'a, Nalu> NalIterator<'a, Nalu> { pub fn new(stream: &'a [u8]) -> Self { Self(Cursor::new(stream), PhantomData) } } impl<'a> Iterator for NalIterator<'a, H264Nalu<'a>> { type Item = Cow<'a, [u8]>; fn next(&mut self) -> Option { H264Nalu::next(&mut self.0).map(|n| n.data).ok() } } impl<'a> Iterator for NalIterator<'a, H265Nalu<'a>> { type Item = Cow<'a, [u8]>; fn next(&mut self) -> Option { H265Nalu::next(&mut self.0).map(|n| n.data).ok() } } #[derive(Debug)] pub enum BitWriterError { InvalidBitCount, Io(std::io::Error), } impl fmt::Display for BitWriterError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { BitWriterError::InvalidBitCount => write!(f, "invalid bit count"), BitWriterError::Io(x) => write!(f, "{}", x.to_string()), } } } impl From for BitWriterError { fn from(err: std::io::Error) -> Self { BitWriterError::Io(err) } } pub type BitWriterResult = std::result::Result; pub struct BitWriter { out: W, nth_bit: u8, curr_byte: u8, } impl BitWriter { pub fn new(writer: W) -> Self { Self { out: writer, curr_byte: 0, nth_bit: 0 } } /// Writes fixed bit size integer (up to 32 bit) pub fn write_f>(&mut self, bits: usize, value: T) -> BitWriterResult { let value = value.into(); if bits > 32 { return Err(BitWriterError::InvalidBitCount); } let mut written = 0; for bit in (0..bits).rev() { let bit = (1 << bit) as u32; self.write_bit((value & bit) == bit)?; written += 1; } Ok(written) } /// Takes a single bit that will be outputed to [`std::io::Write`] pub fn write_bit(&mut self, bit: bool) -> BitWriterResult<()> { self.curr_byte |= (bit as u8) << (7u8 - self.nth_bit); self.nth_bit += 1; if self.nth_bit == 8 { self.out.write_all(&[self.curr_byte])?; self.nth_bit = 0; self.curr_byte = 0; } Ok(()) } /// Immediately outputs any cached bits to [`std::io::Write`] pub fn flush(&mut self) -> BitWriterResult<()> { if self.nth_bit != 0 { self.out.write_all(&[self.curr_byte])?; self.nth_bit = 0; self.curr_byte = 0; } self.out.flush()?; Ok(()) } /// Returns `true` if ['Self`] hold data that wasn't written to [`std::io::Write`] pub fn has_data_pending(&self) -> bool { self.nth_bit != 0 } pub(crate) fn inner(&self) -> &W { &self.out } pub(crate) fn inner_mut(&mut self) -> &mut W { &mut self.out } } impl Drop for BitWriter { fn drop(&mut self) { if let Err(e) = self.flush() { log::error!("Unable to flush bits {e:?}"); } } } #[cfg(test)] mod tests { use super::*; #[test] fn test_ivf_file_header() { let mut hdr = IvfFileHeader { version: 0, codec: IvfFileHeader::CODEC_VP9, width: 256, height: 256, framerate: 30_000, timescale: 1_000, frame_count: 1, ..Default::default() }; let mut buf = Vec::new(); hdr.writo_into(&mut buf).unwrap(); const EXPECTED: [u8; 32] = [ 0x44, 0x4b, 0x49, 0x46, 0x00, 0x00, 0x20, 0x00, 0x56, 0x50, 0x39, 0x30, 0x00, 0x01, 0x00, 0x01, 0x30, 0x75, 0x00, 0x00, 0xe8, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]; assert_eq!(&buf, &EXPECTED); hdr.width = 1920; hdr.height = 800; hdr.framerate = 24; hdr.timescale = 1; hdr.frame_count = 100; buf.clear(); hdr.writo_into(&mut buf).unwrap(); const EXPECTED2: [u8; 32] = [ 0x44, 0x4b, 0x49, 0x46, 0x00, 0x00, 0x20, 0x00, 0x56, 0x50, 0x39, 0x30, 0x80, 0x07, 0x20, 0x03, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]; assert_eq!(&buf, &EXPECTED2); } #[test] fn test_ivf_frame_header() { let mut hdr = IvfFrameHeader { frame_size: 199249, timestamp: 0 }; let mut buf = Vec::new(); hdr.writo_into(&mut buf).unwrap(); const EXPECTED: [u8; 12] = [0x51, 0x0a, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; assert_eq!(&buf, &EXPECTED); hdr.timestamp = 1; hdr.frame_size = 52; buf.clear(); hdr.writo_into(&mut buf).unwrap(); const EXPECTED2: [u8; 12] = [0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; assert_eq!(&buf, &EXPECTED2); } #[test] fn test_bitwriter_f1() { let mut buf = Vec::::new(); { let mut writer = BitWriter::new(&mut buf); writer.write_f(1, true).unwrap(); writer.write_f(1, false).unwrap(); writer.write_f(1, false).unwrap(); writer.write_f(1, false).unwrap(); writer.write_f(1, true).unwrap(); writer.write_f(1, true).unwrap(); writer.write_f(1, true).unwrap(); writer.write_f(1, true).unwrap(); } assert_eq!(buf, vec![0b10001111u8]); } #[test] fn test_bitwriter_f3() { let mut buf = Vec::::new(); { let mut writer = BitWriter::new(&mut buf); writer.write_f(3, 0b100u8).unwrap(); writer.write_f(3, 0b101u8).unwrap(); writer.write_f(3, 0b011u8).unwrap(); } assert_eq!(buf, vec![0b10010101u8, 0b10000000u8]); } #[test] fn test_bitwriter_f4() { let mut buf = Vec::::new(); { let mut writer = BitWriter::new(&mut buf); writer.write_f(4, 0b1000u8).unwrap(); writer.write_f(4, 0b1011u8).unwrap(); } assert_eq!(buf, vec![0b10001011u8]); } // These tests are adapted from the chromium tests at media/video/h264_bit_reader_unitttest.cc #[test] fn read_stream_without_escape_and_trailing_zero_bytes() { const RBSP: [u8; 6] = [0x01, 0x23, 0x45, 0x67, 0x89, 0xa0]; let mut reader = BitReader::new(&RBSP, true); assert_eq!(reader.read_bits::(1).unwrap(), 0); assert_eq!(reader.num_bits_left(), 47); assert!(reader.has_more_rsbp_data()); assert_eq!(reader.read_bits::(8).unwrap(), 0x02); assert_eq!(reader.num_bits_left(), 39); assert!(reader.has_more_rsbp_data()); assert_eq!(reader.read_bits::(31).unwrap(), 0x23456789); assert_eq!(reader.num_bits_left(), 8); assert!(reader.has_more_rsbp_data()); assert_eq!(reader.read_bits::(1).unwrap(), 1); assert_eq!(reader.num_bits_left(), 7); assert!(reader.has_more_rsbp_data()); assert_eq!(reader.read_bits::(1).unwrap(), 0); assert_eq!(reader.num_bits_left(), 6); assert!(!reader.has_more_rsbp_data()); } #[test] fn single_byte_stream() { const RBSP: [u8; 1] = [0x18]; let mut reader = BitReader::new(&RBSP, true); assert_eq!(reader.num_bits_left(), 8); assert!(reader.has_more_rsbp_data()); assert_eq!(reader.read_bits::(4).unwrap(), 1); assert!(!reader.has_more_rsbp_data()); } #[test] fn stop_bit_occupy_full_byte() { const RBSP: [u8; 2] = [0xab, 0x80]; let mut reader = BitReader::new(&RBSP, true); assert_eq!(reader.num_bits_left(), 16); assert!(reader.has_more_rsbp_data()); assert_eq!(reader.read_bits::(8).unwrap(), 0xab); assert_eq!(reader.num_bits_left(), 8); assert!(!reader.has_more_rsbp_data()); } // Check that read_ue behaves properly with input at the limits. #[test] fn read_ue() { // Regular value. let mut reader = BitReader::new(&[0b0001_1010], true); assert_eq!(reader.read_ue::().unwrap(), 12); assert_eq!(reader.data.position(), 1); assert_eq!(reader.num_remaining_bits_in_curr_byte, 1); // 0 value. let mut reader = BitReader::new(&[0b1000_0000], true); assert_eq!(reader.read_ue::().unwrap(), 0); assert_eq!(reader.data.position(), 1); assert_eq!(reader.num_remaining_bits_in_curr_byte, 7); // No prefix stop bit. let mut reader = BitReader::new(&[0b0000_0000], true); reader.read_ue::().unwrap_err(); // u32 max value: 31 0-bits, 1 bit marker, 31 bits 1-bits. let mut reader = BitReader::new( &[ 0b0000_0000, 0b0000_0000, 0b0000_0000, 0b0000_0001, 0b1111_1111, 0b1111_1111, 0b1111_1111, 0b1111_1110, ], true, ); assert_eq!(reader.read_ue::().unwrap(), 0xffff_fffe); assert_eq!(reader.data.position(), 8); assert_eq!(reader.num_remaining_bits_in_curr_byte, 1); } // Check that emulation prevention is being handled correctly. #[test] fn skip_epb_when_enabled() { let mut reader = BitReader::new(&[0x00, 0x00, 0x03, 0x01], false); assert_eq!(reader.read_bits::(8).unwrap(), 0x00); assert_eq!(reader.read_bits::(8).unwrap(), 0x00); assert_eq!(reader.read_bits::(8).unwrap(), 0x03); assert_eq!(reader.read_bits::(8).unwrap(), 0x01); let mut reader = BitReader::new(&[0x00, 0x00, 0x03, 0x01], true); assert_eq!(reader.read_bits::(8).unwrap(), 0x00); assert_eq!(reader.read_bits::(8).unwrap(), 0x00); assert_eq!(reader.read_bits::(8).unwrap(), 0x01); } #[test] fn read_signed_bits() { let mut reader = BitReader::new(&[0b1111_0000], false); assert_eq!(reader.read_bits_signed::(4).unwrap(), -1); } }