mp4_atom/moov/trak/mdia/minf/stbl/stsd/h264/
avc1.rs1use crate::*;
2
3#[derive(Debug, Clone, PartialEq, Eq, Default)]
4#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
5pub struct Avc1 {
6 pub visual: Visual,
7 pub avcc: Avcc,
8 pub btrt: Option<Btrt>,
9 pub colr: Option<Colr>,
10 pub pasp: Option<Pasp>,
11 pub taic: Option<Taic>,
12}
13
14impl Atom for Avc1 {
15 const KIND: FourCC = FourCC::new(b"avc1");
16
17 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
18 let visual = Visual::decode(buf)?;
19
20 let mut avcc = None;
21 let mut btrt = None;
22 let mut colr = None;
23 let mut pasp = None;
24 let mut taic = None;
25 while let Some(atom) = Any::decode_maybe(buf)? {
26 match atom {
27 Any::Avcc(atom) => avcc = atom.into(),
28 Any::Btrt(atom) => btrt = atom.into(),
29 Any::Colr(atom) => colr = atom.into(),
30 Any::Pasp(atom) => pasp = atom.into(),
31 Any::Taic(atom) => taic = atom.into(),
32 _ => tracing::warn!("unknown atom: {:?}", atom),
33 }
34 }
35
36 Ok(Avc1 {
37 visual,
38 avcc: avcc.ok_or(Error::MissingBox(Avcc::KIND))?,
39 btrt,
40 colr,
41 pasp,
42 taic,
43 })
44 }
45
46 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
47 self.visual.encode(buf)?;
48 self.avcc.encode(buf)?;
49 if self.btrt.is_some() {
50 self.btrt.encode(buf)?;
51 }
52 if self.colr.is_some() {
53 self.colr.encode(buf)?;
54 }
55 if self.pasp.is_some() {
56 self.pasp.encode(buf)?;
57 }
58 if self.taic.is_some() {
59 self.taic.encode(buf)?
60 }
61 Ok(())
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68
69 #[test]
70 fn test_avc1() {
71 let expected = Avc1 {
72 visual: Visual {
73 data_reference_index: 1,
74 width: 320,
75 height: 240,
76 horizresolution: 0x48.into(),
77 vertresolution: 0x48.into(),
78 frame_count: 1,
79 compressor: "ya boy".into(),
80 depth: 24,
81 },
82 avcc: Avcc {
83 configuration_version: 1,
84 avc_profile_indication: 100,
85 profile_compatibility: 0,
86 avc_level_indication: 13,
87 length_size: 4,
88 sequence_parameter_sets: vec![vec![
89 0x67, 0x64, 0x00, 0x0D, 0xAC, 0xD9, 0x41, 0x41, 0xFA, 0x10, 0x00, 0x00, 0x03,
90 0x00, 0x10, 0x00, 0x00, 0x03, 0x03, 0x20, 0xF1, 0x42, 0x99, 0x60,
91 ]],
92 picture_parameter_sets: vec![vec![0x68, 0xEB, 0xE3, 0xCB, 0x22, 0xC0]],
93 ..Default::default()
94 },
95 btrt: None,
96 colr: None,
97 pasp: None,
98 taic: None,
99 };
100 let mut buf = Vec::new();
101 expected.encode(&mut buf).unwrap();
102
103 let mut buf = buf.as_ref();
104 let decoded = Avc1::decode(&mut buf).unwrap();
105 assert_eq!(decoded, expected);
106 }
107
108 #[test]
109 fn test_avc1_with_extras() {
110 let expected = Avc1 {
111 visual: Visual {
112 data_reference_index: 1,
113 width: 320,
114 height: 240,
115 horizresolution: 0x48.into(),
116 vertresolution: 0x48.into(),
117 frame_count: 1,
118 compressor: "they".into(),
119 depth: 24,
120 },
121 avcc: Avcc {
122 configuration_version: 1,
123 avc_profile_indication: 100,
124 profile_compatibility: 0,
125 avc_level_indication: 13,
126 length_size: 4,
127 sequence_parameter_sets: vec![vec![
128 0x67, 0x64, 0x00, 0x0D, 0xAC, 0xD9, 0x41, 0x41, 0xFA, 0x10, 0x00, 0x00, 0x03,
129 0x00, 0x10, 0x00, 0x00, 0x03, 0x03, 0x20, 0xF1, 0x42, 0x99, 0x60,
130 ]],
131 picture_parameter_sets: vec![vec![0x68, 0xEB, 0xE3, 0xCB, 0x22, 0xC0]],
132 ..Default::default()
133 },
134 btrt: Some(Btrt {
135 buffer_size_db: 14075,
136 max_bitrate: 374288,
137 avg_bitrate: 240976,
138 }),
139 colr: Some(Colr::default()),
140 pasp: Some(Pasp {
141 h_spacing: 4,
142 v_spacing: 3,
143 }),
144 taic: Some(Taic {
145 time_uncertainty: u64::MAX,
146 clock_resolution: 1000,
147 clock_drift_rate: i32::MAX,
148 clock_type: ClockType::CanSync,
149 }),
150 };
151 let mut buf = Vec::new();
152 expected.encode(&mut buf).unwrap();
153
154 let mut buf = buf.as_ref();
155 let decoded = Avc1::decode(&mut buf).unwrap();
156 assert_eq!(decoded, expected);
157 }
158}