Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix has_more_rbsp_data, PicParameterSetExtra::read #29

Merged
merged 1 commit into from
Jun 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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]
bitstream-io = "1.0"
bitstream-io = "1.1"
memchr = "2.1.1"
rfc6381-codec = "0.1"
log = "0.4"
Expand Down
6 changes: 3 additions & 3 deletions src/nal/pps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ pub struct PicParameterSetExtra {
}
impl PicParameterSetExtra {
fn read(r: &mut RbspBitReader<'_>, sps: &sps::SeqParameterSet) -> Result<Option<PicParameterSetExtra>,PpsError> {
Ok(if r.has_more_rbsp_data() {
Ok(if r.has_more_rbsp_data("pic_parameter_set_extra")? {
let transform_8x8_mode_flag = r.read_bool()?;
Some(PicParameterSetExtra {
transform_8x8_mode_flag,
Expand Down Expand Up @@ -231,7 +231,7 @@ impl PicParameterSet {
.map_err(PpsError::BadPicParamSetId)?;
let seq_parameter_set_id = ParamSetId::from_u32(r.read_ue_named("seq_parameter_set_id")?)
.map_err(PpsError::BadSeqParamSetId)?;
let _seq_parameter_set = ctx.sps_by_id(seq_parameter_set_id)
let seq_parameter_set = ctx.sps_by_id(seq_parameter_set_id)
.ok_or_else(|| PpsError::UnknownSeqParamSetId(seq_parameter_set_id))?;
Ok(PicParameterSet {
pic_parameter_set_id,
Expand All @@ -249,7 +249,7 @@ impl PicParameterSet {
deblocking_filter_control_present_flag: r.read_bool()?,
constrained_intra_pred_flag: r.read_bool()?,
redundant_pic_cnt_present_flag: r.read_bool()?,
extension: None, // TODO: buggy?: PicParameterSetExtra::read(&mut r, seq_parameter_set)?,
extension: PicParameterSetExtra::read(&mut r, seq_parameter_set)?,
})
}

Expand Down
4 changes: 0 additions & 4 deletions src/nal/sei/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,10 +366,6 @@ impl<R: SeiIncrementalPayloadReader> NalHandler for SeiHeaderReader<R> {
match self.state {
SeiHeaderState::Begin => (),
SeiHeaderState::End => panic!("SeiHeaderReader already ended and end() called again"),
SeiHeaderState::PayloadSize { payload_type: HeaderType::ReservedSeiMessage(0x80), payload_size: 0 } => {
// TODO: this is a bit of a hack to ignore rbsp_trailing_bits (which will always
// be 0b10000000 in an SEI payload since SEI messages are byte-aligned).
},
SeiHeaderState::PayloadType { .. } => {
error!("End of SEI data encountered while reading SEI payloadType");
self.reader.reset(ctx);
Expand Down
42 changes: 31 additions & 11 deletions src/rbsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,9 +248,24 @@ impl<'buf> RbspBitReader<'buf> {
self.reader.read(u32::from(bit_count)).map_err( |e| RbspBitReaderError::ReaderError(e) )
}

pub fn has_more_rbsp_data(&mut self) -> bool {
/// Returns true if positioned before the RBSP trailing bits.
///
/// This matches the definition of `more_rbsp_data()` in Rec. ITU-T H.264
/// (03/2010) section 7.2.
pub fn has_more_rbsp_data(&mut self, name: &'static str) -> Result<bool, RbspBitReaderError> {
// BitReader returns its reader iff at an aligned position.
self.reader.reader().map(|r| (r.position() as usize) < r.get_ref().len()).unwrap_or(true)
//self.reader.reader().map(|r| (r.position() as usize) < r.get_ref().len()).unwrap_or(true)
let mut throwaway = self.reader.clone();
let r = (move || {
throwaway.skip(1)?;
throwaway.read_unary1()?;
Ok::<_, std::io::Error>(())
})();
match r {
Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => Ok(false),
Err(e) => Err(RbspBitReaderError::ReaderErrorFor(name, e)),
Ok(_) => Ok(true),
}
}

fn golomb_to_signed(val: u32) -> i32 {
Expand Down Expand Up @@ -365,15 +380,20 @@ mod tests {

#[test]
fn bitreader_has_more_data() {
let mut reader = RbspBitReader::new(&[0x12, 0x34]);
assert!(reader.has_more_rbsp_data());
// Should work when the end bit is byte-aligned.
let mut reader = RbspBitReader::new(&[0x12, 0x80]);
assert!(reader.has_more_rbsp_data("call 1").unwrap());
assert_eq!(reader.read_u8(8).unwrap(), 0x12);
assert!(!reader.has_more_rbsp_data("call 2").unwrap());

// and when it's not.
let mut reader = RbspBitReader::new(&[0x18]);
assert!(reader.has_more_rbsp_data("call 3").unwrap());
assert_eq!(reader.read_u8(4).unwrap(), 0x1);
assert!(reader.has_more_rbsp_data()); // unaligned, backing reader not at EOF
assert_eq!(reader.read_u8(4).unwrap(), 0x2);
assert!(reader.has_more_rbsp_data()); // aligned, backing reader not at EOF
assert_eq!(reader.read_u8(4).unwrap(), 0x3);
assert!(reader.has_more_rbsp_data()); // unaligned, backing reader at EOF
assert_eq!(reader.read_u8(4).unwrap(), 0x4);
assert!(!reader.has_more_rbsp_data()); // aligned, backing reader at EOF
assert!(!reader.has_more_rbsp_data("call 4").unwrap());

// should also work when there are cabac-zero-words.
let mut reader = RbspBitReader::new(&[0x80, 0x00, 0x00]);
assert!(!reader.has_more_rbsp_data("at end with cabac-zero-words").unwrap());
}
}