use crate::DecodeError;
use mediaway_sw::h264::BitReader;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(super) struct Sps {
pub(super) profile_idc: u8,
pub(super) log2_max_frame_num_minus4: u32,
pub(super) pic_order_cnt_type: u32,
pub(super) log2_max_pic_order_cnt_lsb_minus4: u32,
pub(super) gaps_in_frame_num_value_allowed_flag: bool,
pub(super) pic_width_in_mbs_minus1: u32,
pub(super) pic_height_in_map_units_minus1: u32,
pub(super) direct_8x8_inference_flag: bool,
}
impl Sps {
pub(super) fn parse(rbsp: &[u8]) -> Result<Self, DecodeError> {
let profile_idc = *rbsp.first().ok_or(DecodeError::InvalidInput)?;
if !matches!(profile_idc, 66 | 77) {
return Err(DecodeError::Unsupported);
}
let mut r = BitReader::new(rbsp.get(3..).ok_or(DecodeError::InvalidInput)?);
let map_err = |_| DecodeError::InvalidInput;
let _seq_parameter_set_id = r.read_ue().map_err(map_err)?;
let log2_max_frame_num_minus4 = r.read_ue().map_err(map_err)?;
let pic_order_cnt_type = r.read_ue().map_err(map_err)?;
if pic_order_cnt_type != 0 {
return Err(DecodeError::Unsupported);
}
let log2_max_pic_order_cnt_lsb_minus4 = r.read_ue().map_err(map_err)?;
let _max_num_ref_frames = r.read_ue().map_err(map_err)?;
let gaps_in_frame_num_value_allowed_flag = r.read_bit().map_err(map_err)? != 0;
let pic_width_in_mbs_minus1 = r.read_ue().map_err(map_err)?;
let pic_height_in_map_units_minus1 = r.read_ue().map_err(map_err)?;
let frame_mbs_only_flag = r.read_bit().map_err(map_err)? != 0;
if !frame_mbs_only_flag {
return Err(DecodeError::Unsupported);
}
let direct_8x8_inference_flag = r.read_bit().map_err(map_err)? != 0;
Ok(Self {
profile_idc,
log2_max_frame_num_minus4,
pic_order_cnt_type,
log2_max_pic_order_cnt_lsb_minus4,
gaps_in_frame_num_value_allowed_flag,
pic_width_in_mbs_minus1,
pic_height_in_map_units_minus1,
direct_8x8_inference_flag,
})
}
pub(super) const fn width(&self) -> u32 {
(self.pic_width_in_mbs_minus1 + 1).saturating_mul(16)
}
pub(super) const fn height(&self) -> u32 {
(self.pic_height_in_map_units_minus1 + 1).saturating_mul(16)
}
}
#[cfg(test)]
#[path = "sps_tests.rs"]
mod tests;