1use byteorder::{BigEndian, WriteBytesExt};
2use serde::Serialize;
3use std::io::Write;
4
5use crate::mp4box::*;
6
7#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
8pub struct Avc1Box {
9 pub data_reference_index: u16,
10 pub width: u16,
11 pub height: u16,
12
13 #[serde(with = "value_u32")]
14 pub horizresolution: FixedPointU16,
15
16 #[serde(with = "value_u32")]
17 pub vertresolution: FixedPointU16,
18 pub frame_count: u16,
19 pub depth: u16,
20 pub avcc: AvcCBox,
21}
22
23impl Default for Avc1Box {
24 fn default() -> Self {
25 Avc1Box {
26 data_reference_index: 0,
27 width: 0,
28 height: 0,
29 horizresolution: FixedPointU16::new(0x48),
30 vertresolution: FixedPointU16::new(0x48),
31 frame_count: 1,
32 depth: 0x0018,
33 avcc: AvcCBox::default(),
34 }
35 }
36}
37
38impl Avc1Box {
39 pub fn new(config: &AvcConfig) -> Self {
40 Avc1Box {
41 data_reference_index: 1,
42 width: config.width,
43 height: config.height,
44 horizresolution: FixedPointU16::new(0x48),
45 vertresolution: FixedPointU16::new(0x48),
46 frame_count: 1,
47 depth: 0x0018,
48 avcc: AvcCBox::new(&config.seq_param_set, &config.pic_param_set),
49 }
50 }
51
52 pub fn get_size(&self) -> u64 {
53 HEADER_SIZE + 8 + 70 + self.avcc.box_size()
54 }
55
56 fn box_type(&self) -> BoxType {
57 BoxType::Avc1Box
58 }
59}
60
61impl Mp4Box for Avc1Box {
62 const TYPE: BoxType = BoxType::Avc1Box;
63
64 fn box_size(&self) -> u64 {
65 self.get_size()
66 }
67
68 fn to_json(&self) -> Result<String, Error> {
69 Ok(serde_json::to_string(&self).unwrap())
70 }
71
72 fn summary(&self) -> Result<String, Error> {
73 let s = format!(
74 "data_reference_index={} width={} height={} frame_count={}",
75 self.data_reference_index, self.width, self.height, self.frame_count
76 );
77 Ok(s)
78 }
79}
80
81impl BlockReader for Avc1Box {
82 fn read_block<'a>(reader: &mut impl Reader<'a>) -> Result<Self, Error> {
83 reader.get_u32(); reader.get_u16(); let data_reference_index = reader.get_u16();
87
88 reader.get_u32(); reader.get_u64(); reader.get_u32(); let width = reader.get_u16();
93 let height = reader.get_u16();
94
95 let horizresolution = FixedPointU16::new_raw(reader.get_u32());
96 let vertresolution = FixedPointU16::new_raw(reader.get_u32());
97
98 reader.get_u32(); let frame_count = reader.get_u16();
101
102 reader.skip(32); let depth = reader.get_u16();
105
106 reader.get_i16(); Ok(Avc1Box {
109 data_reference_index,
110 width,
111 height,
112 horizresolution,
113 vertresolution,
114 frame_count,
115 depth,
116 avcc: reader.find_box::<AvcCBox>()?,
117 })
118 }
119
120 fn size_hint() -> usize {
121 78
122 }
123}
124
125impl<W: Write> WriteBox<&mut W> for Avc1Box {
126 fn write_box(&self, writer: &mut W) -> Result<u64, Error> {
127 let size = self.box_size();
128 BoxHeader::new(self.box_type(), size).write(writer)?;
129
130 writer.write_u32::<BigEndian>(0)?; writer.write_u16::<BigEndian>(0)?; writer.write_u16::<BigEndian>(self.data_reference_index)?;
133
134 writer.write_u32::<BigEndian>(0)?; writer.write_u64::<BigEndian>(0)?; writer.write_u32::<BigEndian>(0)?; writer.write_u16::<BigEndian>(self.width)?;
138 writer.write_u16::<BigEndian>(self.height)?;
139 writer.write_u32::<BigEndian>(self.horizresolution.raw_value())?;
140 writer.write_u32::<BigEndian>(self.vertresolution.raw_value())?;
141 writer.write_u32::<BigEndian>(0)?; writer.write_u16::<BigEndian>(self.frame_count)?;
143 write_zeros(writer, 32)?;
145 writer.write_u16::<BigEndian>(self.depth)?;
146 writer.write_i16::<BigEndian>(-1)?; self.avcc.write_box(writer)?;
149
150 Ok(size)
151 }
152}
153
154#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize)]
155pub struct AvcCBox {
156 pub configuration_version: u8,
157 pub avc_profile_indication: u8,
158 pub profile_compatibility: u8,
159 pub avc_level_indication: u8,
160 pub length_size_minus_one: u8,
161 pub sequence_parameter_sets: Vec<NalUnit>,
162 pub picture_parameter_sets: Vec<NalUnit>,
163}
164
165impl AvcCBox {
166 pub fn new(sps: &[u8], pps: &[u8]) -> Self {
167 Self {
168 configuration_version: 1,
169 avc_profile_indication: sps[1],
170 profile_compatibility: sps[2],
171 avc_level_indication: sps[3],
172 length_size_minus_one: 0xff, sequence_parameter_sets: vec![NalUnit::from(sps)],
174 picture_parameter_sets: vec![NalUnit::from(pps)],
175 }
176 }
177}
178
179impl Mp4Box for AvcCBox {
180 const TYPE: BoxType = BoxType::AvcCBox;
181
182 fn box_size(&self) -> u64 {
183 let mut size = HEADER_SIZE + 7;
184 for sps in self.sequence_parameter_sets.iter() {
185 size += sps.size() as u64;
186 }
187 for pps in self.picture_parameter_sets.iter() {
188 size += pps.size() as u64;
189 }
190 size
191 }
192
193 fn to_json(&self) -> Result<String, Error> {
194 Ok(serde_json::to_string(&self).unwrap())
195 }
196
197 fn summary(&self) -> Result<String, Error> {
198 let s = format!("avc_profile_indication={}", self.avc_profile_indication);
199 Ok(s)
200 }
201}
202
203impl BlockReader for AvcCBox {
204 fn read_block<'a>(reader: &mut impl Reader<'a>) -> Result<Self, Error> {
205 let configuration_version = reader.get_u8();
206 let avc_profile_indication = reader.get_u8();
207 let profile_compatibility = reader.get_u8();
208 let avc_level_indication = reader.get_u8();
209 let length_size_minus_one = reader.get_u8() & 0x3;
210 let num_of_spss = reader.get_u8() & 0x1F;
211
212 let mut sequence_parameter_sets = Vec::with_capacity(num_of_spss as usize);
213 for _ in 0..num_of_spss {
214 let nal_unit = NalUnit::read(reader)?;
215 sequence_parameter_sets.push(nal_unit);
216 }
217
218 let num_of_ppss = reader.get_u8();
219
220 let mut picture_parameter_sets = Vec::with_capacity(num_of_ppss as usize);
221 for _ in 0..num_of_ppss {
222 let nal_unit = NalUnit::read(reader)?;
223 picture_parameter_sets.push(nal_unit);
224 }
225
226 Ok(AvcCBox {
227 configuration_version,
228 avc_profile_indication,
229 profile_compatibility,
230 avc_level_indication,
231 length_size_minus_one,
232 sequence_parameter_sets,
233 picture_parameter_sets,
234 })
235 }
236
237 fn size_hint() -> usize {
238 7
239 }
240}
241
242impl<W: Write> WriteBox<&mut W> for AvcCBox {
243 fn write_box(&self, writer: &mut W) -> Result<u64, Error> {
244 let size = self.box_size();
245 BoxHeader::new(Self::TYPE, size).write(writer)?;
246
247 writer.write_u8(self.configuration_version)?;
248 writer.write_u8(self.avc_profile_indication)?;
249 writer.write_u8(self.profile_compatibility)?;
250 writer.write_u8(self.avc_level_indication)?;
251 writer.write_u8(self.length_size_minus_one | 0xFC)?;
252 writer.write_u8(self.sequence_parameter_sets.len() as u8 | 0xE0)?;
253 for sps in self.sequence_parameter_sets.iter() {
254 sps.write(writer)?;
255 }
256 writer.write_u8(self.picture_parameter_sets.len() as u8)?;
257 for pps in self.picture_parameter_sets.iter() {
258 pps.write(writer)?;
259 }
260 Ok(size)
261 }
262}
263
264#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize)]
265pub struct NalUnit {
266 pub bytes: Vec<u8>,
267}
268
269impl From<&[u8]> for NalUnit {
270 fn from(bytes: &[u8]) -> Self {
271 Self {
272 bytes: bytes.to_vec(),
273 }
274 }
275}
276
277impl NalUnit {
278 fn size(&self) -> usize {
279 2 + self.bytes.len()
280 }
281
282 fn read<'a>(reader: &mut impl Reader<'a>) -> Result<Self, Error> {
283 let length = reader.try_get_u16()? as usize;
284
285 Ok(NalUnit {
286 bytes: reader.collect(length)?,
287 })
288 }
289
290 fn write<W: Write>(&self, writer: &mut W) -> Result<u64, Error> {
291 writer.write_u16::<BigEndian>(self.bytes.len() as u16)?;
292 writer.write_all(&self.bytes)?;
293 Ok(self.size() as u64)
294 }
295}
296
297#[cfg(test)]
298mod tests {
299 use super::*;
300 use crate::mp4box::BoxHeader;
301
302 #[tokio::test]
303 async fn test_avc1() {
304 let src_box = Avc1Box {
305 data_reference_index: 1,
306 width: 320,
307 height: 240,
308 horizresolution: FixedPointU16::new(0x48),
309 vertresolution: FixedPointU16::new(0x48),
310 frame_count: 1,
311 depth: 24,
312 avcc: AvcCBox {
313 configuration_version: 1,
314 avc_profile_indication: 100,
315 profile_compatibility: 0,
316 avc_level_indication: 13,
317 length_size_minus_one: 3,
318 sequence_parameter_sets: vec![NalUnit {
319 bytes: vec![
320 0x67, 0x64, 0x00, 0x0D, 0xAC, 0xD9, 0x41, 0x41, 0xFA, 0x10, 0x00, 0x00,
321 0x03, 0x00, 0x10, 0x00, 0x00, 0x03, 0x03, 0x20, 0xF1, 0x42, 0x99, 0x60,
322 ],
323 }],
324 picture_parameter_sets: vec![NalUnit {
325 bytes: vec![0x68, 0xEB, 0xE3, 0xCB, 0x22, 0xC0],
326 }],
327 },
328 };
329 let mut buf = Vec::new();
330 src_box.write_box(&mut buf).unwrap();
331 assert_eq!(buf.len(), src_box.box_size() as usize);
332
333 let header = BoxHeader::read(&mut buf.as_slice(), &mut 0)
334 .await
335 .unwrap()
336 .unwrap();
337 assert_eq!(header.kind, BoxType::Avc1Box);
338 assert_eq!(src_box.box_size(), header.size);
339
340 let dst_box = Avc1Box::read_block(&mut &buf[8..]).unwrap();
341 assert_eq!(src_box, dst_box);
342 }
343}