Skip to content

Commit

Permalink
switch from bitreader to bitstream-io
Browse files Browse the repository at this point in the history
Why?
*   performance improvement to RbspBitReader as shown below (although
    this is likely a small percentage of any useful program's time)
*   switch from a less popular crate to a more popular crate
*   be more consistent with adts-reader
*   step toward the lazy RbspBufDecoder interface I described in #4

```
parse_nal/sps           time:   [511.27 ns 512.15 ns 513.01 ns]
                        change: [-17.150% -17.002% -16.853%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 4 outliers among 100 measurements (4.00%)
  3 (3.00%) high mild
  1 (1.00%) high severe
```
  • Loading branch information
scottlamb committed Jun 9, 2021
1 parent 7e61ce1 commit 7a02a3b
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 27 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ repository = "https://github.com/dholroyd/h264-reader"
edition = "2018"

[dependencies]
bitreader = "0.3.1"
bitstream-io = "1.0"
memchr = "2.1.1"
rfc6381-codec = "0.1"

Expand Down
8 changes: 4 additions & 4 deletions src/nal/sps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::nal::pps::ParamSetId;
use crate::nal::pps::ParamSetIdError;
use std::fmt::Debug;

#[derive(Debug, PartialEq)]
#[derive(Debug)]
pub enum SpsError {
/// Signals that bit_depth_luma_minus8 was greater than the max value, 6
BitDepthOutOfRange(u32),
Expand Down Expand Up @@ -301,7 +301,7 @@ impl ScalingList {
}
}

#[derive(Debug, PartialEq)]
#[derive(Debug)]
pub enum ScalingMatrixError {
ReaderError(RbspBitReaderError),
/// The `delta_scale` field must be between -128 and 127 inclusive.
Expand Down Expand Up @@ -393,7 +393,7 @@ impl ChromaInfo {
}
}

#[derive(Debug, PartialEq)]
#[derive(Debug)]
pub enum PicOrderCntError {
InvalidPicOrderCountType(u32),
ReaderError(RbspBitReaderError),
Expand Down Expand Up @@ -990,7 +990,7 @@ mod test {
assert!(!format!("{:?}", sps).is_empty());
assert_eq!(100, sps.profile_idc.0);
assert_eq!(0, sps.constraint_flags.reserved_zero_two_bits());
assert_eq!(Ok((64, 64)), sps.pixel_dimensions());
assert_eq!((64, 64), sps.pixel_dimensions().unwrap());
assert!(!sps.rfc6381().to_string().is_empty())
}

Expand Down
46 changes: 24 additions & 22 deletions src/rbsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
//! yield byte sequences where the encoding is removed (i.e. the decoder will replace instances of
//! the sequence `0x00 0x00 0x03` with `0x00 0x00`).
use bitstream_io::read::BitRead;
use std::borrow::Cow;
use bitreader;
use crate::nal::{NalHandler, NalHeader};
use crate::Context;

Expand Down Expand Up @@ -233,30 +233,30 @@ pub fn decode_nal<'a>(nal_unit: &'a [u8]) -> Cow<'a, [u8]> {
decoder.into_handler().data
}

impl From<bitreader::BitReaderError> for RbspBitReaderError {
fn from(e: bitreader::BitReaderError) -> Self {
impl From<std::io::Error> for RbspBitReaderError {
fn from(e: std::io::Error) -> Self {
RbspBitReaderError::ReaderError(e)
}
}

#[derive(Debug, PartialEq)]
#[derive(Debug)]
pub enum RbspBitReaderError {
ReaderError(bitreader::BitReaderError),
ReaderErrorFor(&'static str, bitreader::BitReaderError),
ReaderError(std::io::Error),
ReaderErrorFor(&'static str, std::io::Error),

/// An Exp-Golomb-coded syntax elements value has more than 32 bits.
ExpGolombTooLarge(&'static str),
}

pub struct RbspBitReader<'a> {
pub struct RbspBitReader<'buf> {
total_size: usize,
reader: bitreader::BitReader<'a>,
reader: bitstream_io::read::BitReader<std::io::Cursor<&'buf [u8]>, bitstream_io::BigEndian>,
}
impl<'a> RbspBitReader<'a> {
pub fn new(buf: &'a[u8]) -> RbspBitReader<'a> {
impl<'buf> RbspBitReader<'buf> {
pub fn new(buf: &'buf [u8]) -> Self {
RbspBitReader {
total_size: buf.len() * 8,
reader: bitreader::BitReader::new(buf),
reader: bitstream_io::read::BitReader::new(std::io::Cursor::new(buf)),
}
}

Expand All @@ -275,41 +275,43 @@ impl<'a> RbspBitReader<'a> {
}

pub fn read_bool(&mut self) -> Result<bool, RbspBitReaderError> {
self.reader.read_bool().map_err( |e| RbspBitReaderError::ReaderError(e) )
self.reader.read_bit().map_err( |e| RbspBitReaderError::ReaderError(e) )
}

pub fn read_bool_named(&mut self, name: &'static str) -> Result<bool, RbspBitReaderError> {
self.reader.read_bool().map_err( |e| RbspBitReaderError::ReaderErrorFor(name, e) )
self.reader.read_bit().map_err( |e| RbspBitReaderError::ReaderErrorFor(name, e) )
}

pub fn read_u8(&mut self, bit_count: u8) -> Result<u8, RbspBitReaderError> {
self.reader.read_u8(bit_count).map_err( |e| RbspBitReaderError::ReaderError(e) )
pub fn read_u8(&mut self, bit_count: u32) -> Result<u8, RbspBitReaderError> {
self.reader.read(u32::from(bit_count)).map_err( |e| RbspBitReaderError::ReaderError(e) )
}

pub fn read_u16(&mut self, bit_count: u8) -> Result<u16, RbspBitReaderError> {
self.reader.read_u16(bit_count).map_err( |e| RbspBitReaderError::ReaderError(e) )
self.reader.read(u32::from(bit_count)).map_err( |e| RbspBitReaderError::ReaderError(e) )
}

pub fn read_u32(&mut self, bit_count: u8) -> Result<u32, RbspBitReaderError> {
self.reader.read_u32(bit_count).map_err( |e| RbspBitReaderError::ReaderError(e) )
self.reader.read(u32::from(bit_count)).map_err( |e| RbspBitReaderError::ReaderError(e) )
}

pub fn read_i32(&mut self, bit_count: u8) -> Result<i32, RbspBitReaderError> {
self.reader.read_i32(bit_count).map_err( |e| RbspBitReaderError::ReaderError(e) )
self.reader.read(u32::from(bit_count)).map_err( |e| RbspBitReaderError::ReaderError(e) )
}

pub fn has_more_rbsp_data(&self) -> bool {
self.reader.position() < self.total_size as u64
pub fn has_more_rbsp_data(&mut self) -> bool {
// BitReader returns its reader iff at an aligned position.
let total_size = self.total_size;
self.reader.reader().map(|r| r.position() < total_size as u64).unwrap_or(true)
}

fn golomb_to_signed(val: u32) -> i32 {
let sign = (((val & 0x1) as i32) << 1) - 1;
((val >> 1) as i32 + (val & 0x1) as i32) * sign
}
}
fn count_zero_bits(r: &mut bitreader::BitReader<'_>, name: &'static str) -> Result<u8, RbspBitReaderError> {
fn count_zero_bits<R: BitRead>(r: &mut R, name: &'static str) -> Result<u8, RbspBitReaderError> {
let mut count = 0;
while !r.read_bool()? {
while !r.read_bit()? {
count += 1;
if count > 31 {
return Err(RbspBitReaderError::ExpGolombTooLarge(name));
Expand Down

0 comments on commit 7a02a3b

Please sign in to comment.