|
| 1 | +//! Parser for `seq_parameter_set_extension_rbsp()` (NAL type 13, spec 7.3.2.1.2). |
| 2 | +
|
| 3 | +use crate::nal::sps::{SeqParamSetId, SpsError}; |
| 4 | +use crate::rbsp::BitRead; |
| 5 | + |
| 6 | +/// Auxiliary format information, present when `aux_format_idc != 0`. |
| 7 | +#[derive(Clone, Debug, PartialEq, Eq)] |
| 8 | +pub struct AuxFormatInfo { |
| 9 | + pub bit_depth_aux_minus8: u8, |
| 10 | + pub alpha_incr_flag: bool, |
| 11 | + pub alpha_opaque_value: u32, |
| 12 | + pub alpha_transparent_value: u32, |
| 13 | +} |
| 14 | + |
| 15 | +/// Parsed `seq_parameter_set_extension_rbsp()` (NAL unit type 13). |
| 16 | +#[derive(Clone, Debug, PartialEq, Eq)] |
| 17 | +pub struct SeqParameterSetExtension { |
| 18 | + pub seq_parameter_set_id: SeqParamSetId, |
| 19 | + pub aux_format_idc: u32, |
| 20 | + pub aux_format_info: Option<AuxFormatInfo>, |
| 21 | + pub additional_extension_flag: bool, |
| 22 | +} |
| 23 | + |
| 24 | +impl SeqParameterSetExtension { |
| 25 | + pub fn from_bits<R: BitRead>(mut r: R) -> Result<SeqParameterSetExtension, SpsError> { |
| 26 | + let seq_parameter_set_id = |
| 27 | + SeqParamSetId::from_u32(r.read_ue("seq_parameter_set_id")?) |
| 28 | + .map_err(SpsError::BadSeqParamSetId)?; |
| 29 | + let aux_format_idc = r.read_ue("aux_format_idc")?; |
| 30 | + let aux_format_info = if aux_format_idc != 0 { |
| 31 | + let bit_depth_aux_minus8 = r.read_ue("bit_depth_aux_minus8")?; |
| 32 | + if bit_depth_aux_minus8 > 4 { |
| 33 | + return Err(SpsError::BitDepthOutOfRange(bit_depth_aux_minus8)); |
| 34 | + } |
| 35 | + let bit_depth_aux_minus8 = bit_depth_aux_minus8 as u8; |
| 36 | + let alpha_incr_flag = r.read_bool("alpha_incr_flag")?; |
| 37 | + let v = bit_depth_aux_minus8 as u32 + 9; |
| 38 | + let alpha_opaque_value = r.read(v, "alpha_opaque_value")?; |
| 39 | + let alpha_transparent_value = r.read(v, "alpha_transparent_value")?; |
| 40 | + Some(AuxFormatInfo { |
| 41 | + bit_depth_aux_minus8, |
| 42 | + alpha_incr_flag, |
| 43 | + alpha_opaque_value, |
| 44 | + alpha_transparent_value, |
| 45 | + }) |
| 46 | + } else { |
| 47 | + None |
| 48 | + }; |
| 49 | + let additional_extension_flag = r.read_bool("additional_extension_flag")?; |
| 50 | + r.finish_rbsp()?; |
| 51 | + Ok(SeqParameterSetExtension { |
| 52 | + seq_parameter_set_id, |
| 53 | + aux_format_idc, |
| 54 | + aux_format_info, |
| 55 | + additional_extension_flag, |
| 56 | + }) |
| 57 | + } |
| 58 | +} |
| 59 | + |
| 60 | +#[cfg(test)] |
| 61 | +mod test { |
| 62 | + use super::*; |
| 63 | + use crate::rbsp::BitReader; |
| 64 | + |
| 65 | + #[test] |
| 66 | + fn parse_minimal() { |
| 67 | + // seq_parameter_set_id=0 (ue: 1 bit '1') |
| 68 | + // aux_format_idc=0 (ue: 1 bit '1') |
| 69 | + // additional_extension_flag=0 (1 bit) |
| 70 | + // rbsp_stop_one_bit=1 + alignment padding |
| 71 | + // bits: 1 1 0 1 0000 = 0xD0 |
| 72 | + let data = [0xD0u8]; |
| 73 | + let ext = SeqParameterSetExtension::from_bits(BitReader::new(&data[..])).unwrap(); |
| 74 | + assert_eq!(ext.seq_parameter_set_id, SeqParamSetId::from_u32(0).unwrap()); |
| 75 | + assert_eq!(ext.aux_format_idc, 0); |
| 76 | + assert!(ext.aux_format_info.is_none()); |
| 77 | + assert!(!ext.additional_extension_flag); |
| 78 | + } |
| 79 | + |
| 80 | + #[test] |
| 81 | + fn parse_with_aux_format() { |
| 82 | + // seq_parameter_set_id=0 (ue: '1') 1 bit |
| 83 | + // aux_format_idc=1 (ue: '010') 3 bits |
| 84 | + // bit_depth_aux_minus8=0 (ue: '1') 1 bit |
| 85 | + // alpha_incr_flag=0 1 bit |
| 86 | + // alpha_opaque_value: u(9) = 0x1FF 9 bits |
| 87 | + // alpha_transparent_value: u(9) = 0x000 9 bits |
| 88 | + // additional_extension_flag=0 1 bit |
| 89 | + // rbsp_stop_one_bit=1 + padding 1 bit + 6 pad |
| 90 | + // |
| 91 | + // bits: 1 010 1 0 111111111 000000000 0 1 000000 |
| 92 | + // byte 0: 1010_1011 = 0xAB |
| 93 | + // byte 1: 1111_1110 = 0xFE |
| 94 | + // byte 2: 0000_0000 = 0x00 |
| 95 | + // byte 3: 0100_0000 = 0x40 |
| 96 | + let data = [0xABu8, 0xFE, 0x00, 0x40]; |
| 97 | + let ext = SeqParameterSetExtension::from_bits(BitReader::new(&data[..])).unwrap(); |
| 98 | + assert_eq!(ext.seq_parameter_set_id, SeqParamSetId::from_u32(0).unwrap()); |
| 99 | + assert_eq!(ext.aux_format_idc, 1); |
| 100 | + let info = ext.aux_format_info.as_ref().unwrap(); |
| 101 | + assert_eq!(info.bit_depth_aux_minus8, 0); |
| 102 | + assert!(!info.alpha_incr_flag); |
| 103 | + assert_eq!(info.alpha_opaque_value, 0x1FF); |
| 104 | + assert_eq!(info.alpha_transparent_value, 0x000); |
| 105 | + assert!(!ext.additional_extension_flag); |
| 106 | + } |
| 107 | +} |
0 commit comments