flowly_mp4/mp4box/
avc1.rs

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(); // reserved
84        reader.get_u16(); // reserved
85
86        let data_reference_index = reader.get_u16();
87
88        reader.get_u32(); // pre-defined, reserved
89        reader.get_u64(); // pre-defined
90        reader.get_u32(); // pre-defined
91
92        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(); // reserved
99
100        let frame_count = reader.get_u16();
101
102        reader.skip(32); // compressorname
103
104        let depth = reader.get_u16();
105
106        reader.get_i16(); // pre-defined
107
108        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)?; // reserved
131        writer.write_u16::<BigEndian>(0)?; // reserved
132        writer.write_u16::<BigEndian>(self.data_reference_index)?;
133
134        writer.write_u32::<BigEndian>(0)?; // pre-defined, reserved
135        writer.write_u64::<BigEndian>(0)?; // pre-defined
136        writer.write_u32::<BigEndian>(0)?; // pre-defined
137        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)?; // reserved
142        writer.write_u16::<BigEndian>(self.frame_count)?;
143        // skip compressorname
144        write_zeros(writer, 32)?;
145        writer.write_u16::<BigEndian>(self.depth)?;
146        writer.write_i16::<BigEndian>(-1)?; // pre-defined
147
148        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, // length_size = 4
173            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}