mp4_atom/moov/trak/mdia/minf/stbl/stsd/h264/
avcc.rs

1use crate::*;
2
3#[derive(Debug, Clone, PartialEq, Eq, Default)]
4#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
5pub struct Avcc {
6    pub configuration_version: u8,
7    pub avc_profile_indication: u8,
8    pub profile_compatibility: u8,
9    pub avc_level_indication: u8,
10    pub length_size: u8,
11    pub sequence_parameter_sets: Vec<Vec<u8>>,
12    pub picture_parameter_sets: Vec<Vec<u8>>,
13    pub ext: Option<AvccExt>,
14}
15
16// Only valid for certain profiles
17#[derive(Debug, Clone, PartialEq, Eq)]
18#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
19pub struct AvccExt {
20    pub chroma_format: u8,
21    pub bit_depth_luma: u8,
22    pub bit_depth_chroma: u8,
23    pub sequence_parameter_sets_ext: Vec<Vec<u8>>,
24}
25
26impl Default for AvccExt {
27    fn default() -> Self {
28        AvccExt {
29            chroma_format: 1,
30            bit_depth_luma: 8,
31            bit_depth_chroma: 8,
32            sequence_parameter_sets_ext: Vec::new(),
33        }
34    }
35}
36
37impl Avcc {
38    pub fn new(sps: &[u8], pps: &[u8]) -> Result<Self> {
39        if sps.len() < 4 {
40            return Err(Error::OutOfBounds);
41        }
42
43        Ok(Self {
44            configuration_version: 1,
45            avc_profile_indication: sps[1],
46            profile_compatibility: sps[2],
47            avc_level_indication: sps[3],
48            length_size: 4,
49            sequence_parameter_sets: vec![sps.into()],
50            picture_parameter_sets: vec![pps.into()],
51
52            // TODO This information could be parsed out of the SPS
53            ext: None,
54        })
55    }
56}
57
58impl Atom for Avcc {
59    const KIND: FourCC = FourCC::new(b"avcC");
60
61    fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
62        let configuration_version = u8::decode(buf)?;
63        if configuration_version != 1 {
64            return Err(Error::UnknownVersion(configuration_version));
65        }
66        let avc_profile_indication = u8::decode(buf)?;
67        let profile_compatibility = u8::decode(buf)?;
68        let avc_level_indication = u8::decode(buf)?;
69
70        // The first 5 bits are reserved as 0b11111 and the value is encoded -1
71        let mut length_size = u8::decode(buf)?;
72        length_size = match length_size {
73            0xfc..=0xff => (length_size & 0x03) + 1,
74            _ => return Err(Error::InvalidSize),
75        };
76
77        let num_of_spss = u8::decode(buf)? & 0x1F;
78        let mut sequence_parameter_sets = Vec::with_capacity(num_of_spss as usize);
79        for _ in 0..num_of_spss {
80            let size = u16::decode(buf)? as usize;
81            let nal = Vec::decode_exact(buf, size)?;
82            sequence_parameter_sets.push(nal);
83        }
84
85        let num_of_ppss = u8::decode(buf)?;
86        let mut picture_parameter_sets = Vec::with_capacity(num_of_ppss as usize);
87        for _ in 0..num_of_ppss {
88            let size = u16::decode(buf)? as usize;
89            let nal = Vec::decode_exact(buf, size)?;
90            picture_parameter_sets.push(nal);
91        }
92
93        let ext = match avc_profile_indication {
94            // NOTE: Many encoders/decoders skip this part, so it's not always present
95            100 | 110 | 122 | 144 if buf.remaining() > 0 => {
96                let chroma_format = u8::decode(buf)? & 0x3;
97                let bit_depth_luma_minus8 = u8::decode(buf)? & 0x7;
98                let bit_depth_chroma_minus8 = u8::decode(buf)? & 0x7;
99                let num_of_sequence_parameter_set_exts = u8::decode(buf)? as usize;
100                let mut sequence_parameter_sets_ext =
101                    Vec::with_capacity(num_of_sequence_parameter_set_exts);
102
103                for _ in 0..num_of_sequence_parameter_set_exts {
104                    let size = u16::decode(buf)? as usize;
105                    let nal = Vec::decode_exact(buf, size)?;
106                    sequence_parameter_sets_ext.push(nal);
107                }
108
109                Some(AvccExt {
110                    chroma_format,
111                    bit_depth_luma: bit_depth_luma_minus8 + 8,
112                    bit_depth_chroma: bit_depth_chroma_minus8 + 8,
113                    sequence_parameter_sets_ext,
114                })
115            }
116            _ => None,
117        };
118
119        Ok(Avcc {
120            configuration_version,
121            avc_profile_indication,
122            profile_compatibility,
123            avc_level_indication,
124            length_size,
125            sequence_parameter_sets,
126            picture_parameter_sets,
127            ext,
128        })
129    }
130
131    fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
132        self.configuration_version.encode(buf)?;
133        self.avc_profile_indication.encode(buf)?;
134        self.profile_compatibility.encode(buf)?;
135        self.avc_level_indication.encode(buf)?;
136        let length_size = match self.length_size {
137            0 => return Err(Error::InvalidSize),
138            1..=4 => self.length_size - 1,
139            _ => return Err(Error::InvalidSize),
140        };
141        (length_size | 0xFC).encode(buf)?;
142
143        (self.sequence_parameter_sets.len() as u8 | 0xE0).encode(buf)?;
144        for sps in &self.sequence_parameter_sets {
145            (sps.len() as u16).encode(buf)?;
146            sps.encode(buf)?;
147        }
148
149        (self.picture_parameter_sets.len() as u8).encode(buf)?;
150        for pps in &self.picture_parameter_sets {
151            (pps.len() as u16).encode(buf)?;
152            pps.encode(buf)?;
153        }
154
155        if let Some(ext) = &self.ext {
156            ext.chroma_format.encode(buf)?;
157            ext.bit_depth_luma.encode(buf)?;
158            ext.bit_depth_chroma.encode(buf)?;
159            (ext.sequence_parameter_sets_ext.len() as u8).encode(buf)?;
160            for sps in &ext.sequence_parameter_sets_ext {
161                (sps.len() as u16).encode(buf)?;
162                sps.encode(buf)?;
163            }
164        }
165
166        Ok(())
167    }
168}