1use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
2use serde::Serialize;
3use std::io::{Read, Seek, 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_type(&self) -> BoxType {
53 BoxType::Avc1Box
54 }
55
56 pub fn get_size(&self) -> u64 {
57 HEADER_SIZE + 8 + 70 + self.avcc.box_size()
58 }
59}
60
61impl Mp4Box for Avc1Box {
62 fn box_type(&self) -> BoxType {
63 self.get_type()
64 }
65
66 fn box_size(&self) -> u64 {
67 self.get_size()
68 }
69
70 fn to_json(&self) -> Result<String> {
71 Ok(serde_json::to_string(&self).unwrap())
72 }
73
74 fn summary(&self) -> Result<String> {
75 let s = format!(
76 "data_reference_index={} width={} height={} frame_count={}",
77 self.data_reference_index, self.width, self.height, self.frame_count
78 );
79 Ok(s)
80 }
81}
82
83impl<R: Read + Seek> ReadBox<&mut R> for Avc1Box {
84 fn read_box(reader: &mut R, size: u64) -> Result<Self> {
85 let start = box_start(reader)?;
86
87 reader.read_u32::<BigEndian>()?; reader.read_u16::<BigEndian>()?; let data_reference_index = reader.read_u16::<BigEndian>()?;
90
91 reader.read_u32::<BigEndian>()?; reader.read_u64::<BigEndian>()?; reader.read_u32::<BigEndian>()?; let width = reader.read_u16::<BigEndian>()?;
95 let height = reader.read_u16::<BigEndian>()?;
96 let horizresolution = FixedPointU16::new_raw(reader.read_u32::<BigEndian>()?);
97 let vertresolution = FixedPointU16::new_raw(reader.read_u32::<BigEndian>()?);
98 reader.read_u32::<BigEndian>()?; let frame_count = reader.read_u16::<BigEndian>()?;
100 skip_bytes(reader, 32)?; let depth = reader.read_u16::<BigEndian>()?;
102 reader.read_i16::<BigEndian>()?; let end = start + size;
105 loop {
106 let current = reader.stream_position()?;
107 if current >= end {
108 return Err(Error::InvalidData("avcc not found"));
109 }
110 let header = BoxHeader::read(reader)?;
111 let BoxHeader { name, size: s } = header;
112 if s > size {
113 return Err(Error::InvalidData(
114 "avc1 box contains a box with a larger size than it",
115 ));
116 }
117 if name == BoxType::AvcCBox {
118 let avcc = AvcCBox::read_box(reader, s)?;
119
120 skip_bytes_to(reader, start + size)?;
121
122 return Ok(Avc1Box {
123 data_reference_index,
124 width,
125 height,
126 horizresolution,
127 vertresolution,
128 frame_count,
129 depth,
130 avcc,
131 });
132 } else {
133 skip_bytes_to(reader, current + s)?;
134 }
135 }
136 }
137}
138
139impl<W: Write> WriteBox<&mut W> for Avc1Box {
140 fn write_box(&self, writer: &mut W) -> Result<u64> {
141 let size = self.box_size();
142 BoxHeader::new(self.box_type(), size).write(writer)?;
143
144 writer.write_u32::<BigEndian>(0)?; writer.write_u16::<BigEndian>(0)?; writer.write_u16::<BigEndian>(self.data_reference_index)?;
147
148 writer.write_u32::<BigEndian>(0)?; writer.write_u64::<BigEndian>(0)?; writer.write_u32::<BigEndian>(0)?; writer.write_u16::<BigEndian>(self.width)?;
152 writer.write_u16::<BigEndian>(self.height)?;
153 writer.write_u32::<BigEndian>(self.horizresolution.raw_value())?;
154 writer.write_u32::<BigEndian>(self.vertresolution.raw_value())?;
155 writer.write_u32::<BigEndian>(0)?; writer.write_u16::<BigEndian>(self.frame_count)?;
157 write_zeros(writer, 32)?;
159 writer.write_u16::<BigEndian>(self.depth)?;
160 writer.write_i16::<BigEndian>(-1)?; self.avcc.write_box(writer)?;
163
164 Ok(size)
165 }
166}
167
168#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize)]
169pub struct AvcCBox {
170 pub configuration_version: u8,
171 pub avc_profile_indication: u8,
172 pub profile_compatibility: u8,
173 pub avc_level_indication: u8,
174 pub length_size_minus_one: u8,
175 pub sequence_parameter_sets: Vec<NalUnit>,
176 pub picture_parameter_sets: Vec<NalUnit>,
177}
178
179impl AvcCBox {
180 pub fn new(sps: &[u8], pps: &[u8]) -> Self {
181 Self {
182 configuration_version: 1,
183 avc_profile_indication: sps[1],
184 profile_compatibility: sps[2],
185 avc_level_indication: sps[3],
186 length_size_minus_one: 0xff, sequence_parameter_sets: vec![NalUnit::from(sps)],
188 picture_parameter_sets: vec![NalUnit::from(pps)],
189 }
190 }
191}
192
193impl Mp4Box for AvcCBox {
194 fn box_type(&self) -> BoxType {
195 BoxType::AvcCBox
196 }
197
198 fn box_size(&self) -> u64 {
199 let mut size = HEADER_SIZE + 7;
200 for sps in self.sequence_parameter_sets.iter() {
201 size += sps.size() as u64;
202 }
203 for pps in self.picture_parameter_sets.iter() {
204 size += pps.size() as u64;
205 }
206 size
207 }
208
209 fn to_json(&self) -> Result<String> {
210 Ok(serde_json::to_string(&self).unwrap())
211 }
212
213 fn summary(&self) -> Result<String> {
214 let s = format!("avc_profile_indication={}", self.avc_profile_indication);
215 Ok(s)
216 }
217}
218
219impl<R: Read + Seek> ReadBox<&mut R> for AvcCBox {
220 fn read_box(reader: &mut R, size: u64) -> Result<Self> {
221 let start = box_start(reader)?;
222
223 let configuration_version = reader.read_u8()?;
224 let avc_profile_indication = reader.read_u8()?;
225 let profile_compatibility = reader.read_u8()?;
226 let avc_level_indication = reader.read_u8()?;
227 let length_size_minus_one = reader.read_u8()? & 0x3;
228 let num_of_spss = reader.read_u8()? & 0x1F;
229 let mut sequence_parameter_sets = Vec::with_capacity(num_of_spss as usize);
230 for _ in 0..num_of_spss {
231 let nal_unit = NalUnit::read(reader)?;
232 sequence_parameter_sets.push(nal_unit);
233 }
234 let num_of_ppss = reader.read_u8()?;
235 let mut picture_parameter_sets = Vec::with_capacity(num_of_ppss as usize);
236 for _ in 0..num_of_ppss {
237 let nal_unit = NalUnit::read(reader)?;
238 picture_parameter_sets.push(nal_unit);
239 }
240
241 skip_bytes_to(reader, start + size)?;
242
243 Ok(AvcCBox {
244 configuration_version,
245 avc_profile_indication,
246 profile_compatibility,
247 avc_level_indication,
248 length_size_minus_one,
249 sequence_parameter_sets,
250 picture_parameter_sets,
251 })
252 }
253}
254
255impl<W: Write> WriteBox<&mut W> for AvcCBox {
256 fn write_box(&self, writer: &mut W) -> Result<u64> {
257 let size = self.box_size();
258 BoxHeader::new(self.box_type(), size).write(writer)?;
259
260 writer.write_u8(self.configuration_version)?;
261 writer.write_u8(self.avc_profile_indication)?;
262 writer.write_u8(self.profile_compatibility)?;
263 writer.write_u8(self.avc_level_indication)?;
264 writer.write_u8(self.length_size_minus_one | 0xFC)?;
265 writer.write_u8(self.sequence_parameter_sets.len() as u8 | 0xE0)?;
266 for sps in self.sequence_parameter_sets.iter() {
267 sps.write(writer)?;
268 }
269 writer.write_u8(self.picture_parameter_sets.len() as u8)?;
270 for pps in self.picture_parameter_sets.iter() {
271 pps.write(writer)?;
272 }
273 Ok(size)
274 }
275}
276
277#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize)]
278pub struct NalUnit {
279 pub bytes: Vec<u8>,
280}
281
282impl From<&[u8]> for NalUnit {
283 fn from(bytes: &[u8]) -> Self {
284 Self {
285 bytes: bytes.to_vec(),
286 }
287 }
288}
289
290impl NalUnit {
291 fn size(&self) -> usize {
292 2 + self.bytes.len()
293 }
294
295 fn read<R: Read + Seek>(reader: &mut R) -> Result<Self> {
296 let length = reader.read_u16::<BigEndian>()? as usize;
297 let mut bytes = vec![0u8; length];
298 reader.read_exact(&mut bytes)?;
299 Ok(NalUnit { bytes })
300 }
301
302 fn write<W: Write>(&self, writer: &mut W) -> Result<u64> {
303 writer.write_u16::<BigEndian>(self.bytes.len() as u16)?;
304 writer.write_all(&self.bytes)?;
305 Ok(self.size() as u64)
306 }
307}
308
309#[cfg(test)]
310mod tests {
311 use super::*;
312 use crate::mp4box::BoxHeader;
313 use std::io::Cursor;
314
315 #[test]
316 fn test_avc1() {
317 let src_box = Avc1Box {
318 data_reference_index: 1,
319 width: 320,
320 height: 240,
321 horizresolution: FixedPointU16::new(0x48),
322 vertresolution: FixedPointU16::new(0x48),
323 frame_count: 1,
324 depth: 24,
325 avcc: AvcCBox {
326 configuration_version: 1,
327 avc_profile_indication: 100,
328 profile_compatibility: 0,
329 avc_level_indication: 13,
330 length_size_minus_one: 3,
331 sequence_parameter_sets: vec![NalUnit {
332 bytes: vec![
333 0x67, 0x64, 0x00, 0x0D, 0xAC, 0xD9, 0x41, 0x41, 0xFA, 0x10, 0x00, 0x00,
334 0x03, 0x00, 0x10, 0x00, 0x00, 0x03, 0x03, 0x20, 0xF1, 0x42, 0x99, 0x60,
335 ],
336 }],
337 picture_parameter_sets: vec![NalUnit {
338 bytes: vec![0x68, 0xEB, 0xE3, 0xCB, 0x22, 0xC0],
339 }],
340 },
341 };
342 let mut buf = Vec::new();
343 src_box.write_box(&mut buf).unwrap();
344 assert_eq!(buf.len(), src_box.box_size() as usize);
345
346 let mut reader = Cursor::new(&buf);
347 let header = BoxHeader::read(&mut reader).unwrap();
348 assert_eq!(header.name, BoxType::Avc1Box);
349 assert_eq!(src_box.box_size(), header.size);
350
351 let dst_box = Avc1Box::read_box(&mut reader, header.size).unwrap();
352 assert_eq!(src_box, dst_box);
353 }
354}