mp4_atom/moov/trak/mdia/minf/stbl/stsd/h264/
avcc.rs1use 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#[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 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 let length_size = (u8::decode(buf)? & 0b00000011) + 1;
72
73 let num_of_spss = u8::decode(buf)? & 0x1F;
74 let mut sequence_parameter_sets = Vec::with_capacity(num_of_spss as usize);
75 for _ in 0..num_of_spss {
76 let size = u16::decode(buf)? as usize;
77 let nal = Vec::decode_exact(buf, size)?;
78 sequence_parameter_sets.push(nal);
79 }
80
81 let num_of_ppss = u8::decode(buf)?;
82 let mut picture_parameter_sets = Vec::with_capacity(num_of_ppss as usize);
83 for _ in 0..num_of_ppss {
84 let size = u16::decode(buf)? as usize;
85 let nal = Vec::decode_exact(buf, size)?;
86 picture_parameter_sets.push(nal);
87 }
88
89 let ext = if buf.has_remaining() {
92 let chroma_format = u8::decode(buf)? & 0x3;
93 let bit_depth_luma_minus8 = u8::decode(buf)? & 0x7;
94 let bit_depth_chroma_minus8 = u8::decode(buf)? & 0x7;
95 let num_of_sequence_parameter_set_exts = u8::decode(buf)? as usize;
96 let mut sequence_parameter_sets_ext =
97 Vec::with_capacity(num_of_sequence_parameter_set_exts);
98
99 for _ in 0..num_of_sequence_parameter_set_exts {
100 let size = u16::decode(buf)? as usize;
101 let nal = Vec::decode_exact(buf, size)?;
102 sequence_parameter_sets_ext.push(nal);
103 }
104
105 Some(AvccExt {
106 chroma_format,
107 bit_depth_luma: bit_depth_luma_minus8 + 8,
108 bit_depth_chroma: bit_depth_chroma_minus8 + 8,
109 sequence_parameter_sets_ext,
110 })
111 } else {
112 None
113 };
114
115 Ok(Avcc {
116 configuration_version,
117 avc_profile_indication,
118 profile_compatibility,
119 avc_level_indication,
120 length_size,
121 sequence_parameter_sets,
122 picture_parameter_sets,
123 ext,
124 })
125 }
126
127 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
128 self.configuration_version.encode(buf)?;
129 self.avc_profile_indication.encode(buf)?;
130 self.profile_compatibility.encode(buf)?;
131 self.avc_level_indication.encode(buf)?;
132 let length_size = match self.length_size {
133 0 => return Err(Error::InvalidSize),
134 1..=4 => self.length_size - 1,
135 _ => return Err(Error::InvalidSize),
136 };
137 (length_size | 0xFC).encode(buf)?;
138
139 (self.sequence_parameter_sets.len() as u8 | 0xE0).encode(buf)?;
140 for sps in &self.sequence_parameter_sets {
141 (sps.len() as u16).encode(buf)?;
142 sps.encode(buf)?;
143 }
144
145 (self.picture_parameter_sets.len() as u8).encode(buf)?;
146 for pps in &self.picture_parameter_sets {
147 (pps.len() as u16).encode(buf)?;
148 pps.encode(buf)?;
149 }
150
151 if let Some(ext) = &self.ext {
152 ok_in_range(ext.chroma_format, 0..4)
153 .map(|n| n | 0b11111100)?
154 .encode(buf)?;
155 ok_in_range(
156 ext.bit_depth_luma
157 .checked_sub(8)
158 .ok_or(Error::InvalidSize)?,
159 0..8,
160 )
161 .map(|n| n | 0b11111000)?
162 .encode(buf)?;
163 ok_in_range(
164 ext.bit_depth_chroma
165 .checked_sub(8)
166 .ok_or(Error::InvalidSize)?,
167 0..8,
168 )
169 .map(|n| n | 0b11111000)?
170 .encode(buf)?;
171 (ext.sequence_parameter_sets_ext.len() as u8).encode(buf)?;
172 for sps in &ext.sequence_parameter_sets_ext {
173 (sps.len() as u16).encode(buf)?;
174 sps.encode(buf)?;
175 }
176 }
177
178 Ok(())
179 }
180}
181
182fn ok_in_range(n: u8, range: std::ops::Range<u8>) -> Result<u8> {
185 if range.contains(&n) {
186 Ok(n)
187 } else {
188 Err(Error::InvalidSize)
189 }
190}
191
192#[cfg(test)]
193mod tests {
194 use super::*;
195 use std::io::Cursor;
196
197 #[test]
198 fn ok_in_range_is_ok_when_in_range() {
199 assert_eq!(1, ok_in_range(1, 0..8).expect("should be Ok"));
200 }
201
202 #[test]
203 fn ok_in_range_is_err_when_out_of_range() {
204 match ok_in_range(8, 0..8) {
205 Err(Error::InvalidSize) => (),
206 Ok(n) => panic!("unexpected Ok value Ok({n})"),
207 Err(e) => panic!("unexpected error case {e}"),
208 }
209 }
210
211 const ENCODED: &[u8] = &[
221 0x00, 0x00, 0x00, 0x41, 0x61, 0x76, 0x63, 0x43, 0x01, 0x64, 0x00, 0x2A, 0x03, 0x01, 0x00,
222 0x26, 0x27, 0x64, 0x00, 0x2A, 0xAC, 0x24, 0x8C, 0x07, 0x80, 0x22, 0x7E, 0x5C, 0x04, 0x40,
223 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x1E, 0x38, 0xA0, 0x00, 0x0B, 0x71, 0xB0, 0x00,
224 0x16, 0xE3, 0x7B, 0xDE, 0xE0, 0x3E, 0x11, 0x08, 0xA7, 0x01, 0x00, 0x04, 0x28, 0xDE, 0xBC,
225 0xB0, 0xFD, 0xF8, 0xF8, 0x00,
226 ];
227
228 #[test]
229 fn avcc_decodes_correctly() {
230 let mut buf = Cursor::new(ENCODED);
231 let avcc = Avcc {
232 configuration_version: 1,
233 avc_profile_indication: 100,
234 profile_compatibility: 0,
235 avc_level_indication: 42,
236 length_size: 4,
237 sequence_parameter_sets: vec![ENCODED[16..54].to_vec()],
238 picture_parameter_sets: vec![ENCODED[57..61].to_vec()],
239 ext: Some(AvccExt {
240 chroma_format: 1,
241 bit_depth_luma: 8,
242 bit_depth_chroma: 8,
243 sequence_parameter_sets_ext: Vec::new(),
244 }),
245 };
246 let decoded = Avcc::decode(&mut buf).expect("avcC should decode successfully");
247 assert_eq!(avcc, decoded);
248 let mut encoded = Vec::new();
249 avcc.encode(&mut encoded)
250 .expect("encode should be successful");
251 let mut fixed_encoded = ENCODED.to_vec();
254 if let Some(length_size_minus_one) = fixed_encoded.get_mut(12) {
255 *length_size_minus_one |= 0b11111100;
256 }
257 if let Some(num_of_sequence_parameter_sets) = fixed_encoded.get_mut(13) {
258 *num_of_sequence_parameter_sets |= 0b11100000;
259 }
260 assert_eq!(fixed_encoded, encoded);
261 }
262}