use crate::rbsp::BitRead;
use std::fmt;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum PrimaryPicType {
I = 0,
IP = 1,
IPB = 2,
SI = 3,
SISP = 4,
ISI = 5,
ISIPSP = 6,
ISIPSPB = 7,
}
#[derive(Debug)]
pub struct PrimaryPicTypeError(pub u8);
impl fmt::Display for PrimaryPicTypeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "invalid primary_pic_type value: {}", self.0)
}
}
impl PrimaryPicType {
pub fn from_id(id: u8) -> Result<PrimaryPicType, PrimaryPicTypeError> {
match id {
0 => Ok(PrimaryPicType::I),
1 => Ok(PrimaryPicType::IP),
2 => Ok(PrimaryPicType::IPB),
3 => Ok(PrimaryPicType::SI),
4 => Ok(PrimaryPicType::SISP),
5 => Ok(PrimaryPicType::ISI),
6 => Ok(PrimaryPicType::ISIPSP),
7 => Ok(PrimaryPicType::ISIPSPB),
_ => Err(PrimaryPicTypeError(id)),
}
}
pub fn id(self) -> u8 {
self as u8
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct AccessUnitDelimiter {
pub primary_pic_type: PrimaryPicType,
}
impl AccessUnitDelimiter {
pub fn from_bits<R: BitRead>(mut r: R) -> Result<AccessUnitDelimiter, AudError> {
let val: u8 = r.read::<3, _>("primary_pic_type")?;
let primary_pic_type =
PrimaryPicType::from_id(val).map_err(AudError::InvalidPrimaryPicType)?;
r.finish_rbsp()?;
Ok(AccessUnitDelimiter { primary_pic_type })
}
}
#[derive(Debug)]
pub enum AudError {
InvalidPrimaryPicType(PrimaryPicTypeError),
RbspError(crate::rbsp::BitReaderError),
}
impl From<crate::rbsp::BitReaderError> for AudError {
fn from(e: crate::rbsp::BitReaderError) -> Self {
AudError::RbspError(e)
}
}
impl fmt::Display for AudError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AudError::InvalidPrimaryPicType(e) => write!(f, "{}", e),
AudError::RbspError(e) => write!(f, "{:?}", e),
}
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::rbsp::BitReader;
#[test]
fn parse_all_pic_types() {
for id in 0u8..=7 {
let byte = (id << 5) | 0x10;
let data = [byte];
let aud = AccessUnitDelimiter::from_bits(BitReader::new(&data[..])).unwrap();
assert_eq!(aud.primary_pic_type.id(), id);
}
}
#[test]
fn parse_ipb() {
let data = [0x50u8];
let aud = AccessUnitDelimiter::from_bits(BitReader::new(&data[..])).unwrap();
assert_eq!(aud.primary_pic_type, PrimaryPicType::IPB);
}
}