1use crate::*;
2
3#[derive(Debug, Clone, PartialEq, Eq, Default)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8pub struct Avc3 {
9 pub visual: Visual,
10 pub avcc: Avcc,
11 pub btrt: Option<Btrt>,
12 pub colr: Option<Colr>,
13 pub pasp: Option<Pasp>,
14 pub taic: Option<Taic>,
15 pub fiel: Option<Fiel>,
16 pub spatial: Option<Box<Spatial>>,
17}
18
19impl Atom for Avc3 {
20 const KIND: FourCC = FourCC::new(b"avc3");
21
22 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
23 let visual = Visual::decode(buf)?;
24
25 let mut avcc = None;
26 let mut btrt = None;
27 let mut colr = None;
28 let mut pasp = None;
29 let mut taic = None;
30 let mut fiel = None;
31 let mut spatial = None;
32 while let Some(atom) = Any::decode_maybe(buf)? {
33 match atom {
34 Any::Avcc(atom) => avcc = atom.into(),
35 Any::Btrt(atom) => btrt = atom.into(),
36 Any::Colr(atom) => colr = atom.into(),
37 Any::Pasp(atom) => pasp = atom.into(),
38 Any::Taic(atom) => taic = atom.into(),
39 Any::Fiel(atom) => fiel = atom.into(),
40 atom => Spatial::decode_child::<Self>(&mut spatial, atom)?,
41 }
42 }
43 skip_trailing_padding(buf);
44
45 Ok(Avc3 {
46 visual,
47 avcc: avcc.ok_or(Error::MissingBox(Avcc::KIND))?,
48 btrt,
49 colr,
50 pasp,
51 taic,
52 fiel,
53 spatial,
54 })
55 }
56
57 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
58 self.visual.encode(buf)?;
59 self.avcc.encode(buf)?;
60 self.btrt.encode(buf)?;
61 self.colr.encode(buf)?;
62 if let Some(spatial) = &self.spatial {
63 spatial.encode(buf)?;
64 }
65 self.pasp.encode(buf)?;
66 self.taic.encode(buf)?;
67 self.fiel.encode(buf)?;
68 Ok(())
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75
76 fn roundtrip(expected: &Avc3) {
77 let mut buf = Vec::new();
78 expected.encode(&mut buf).unwrap();
79
80 let decoded = Avc3::decode(&mut buf.as_slice()).unwrap();
81 assert_eq!(&decoded, expected);
82
83 let codec = Codec::from(expected.clone());
85 let mut buf = Vec::new();
86 codec.encode(&mut buf).unwrap();
87 assert_eq!(Codec::decode(&mut buf.as_slice()).unwrap(), codec);
88 }
89
90 const BBC: &[u8] = &[
94 0x00, 0x00, 0x00, 0x88, 0x61, 0x76, 0x63, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96 0x00, 0x00, 0x00, 0xC0, 0x00, 0x6C, 0x00, 0x48, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
97 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x68, 0x32, 0x36, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00,
98 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
99 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0F,
100 0x61, 0x76, 0x63, 0x43, 0x01, 0x42, 0xC0, 0x15, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x10,
101 0x70, 0x61, 0x73, 0x70, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
102 0x13, 0x63, 0x6F, 0x6C, 0x72, 0x6E, 0x63, 0x6C, 0x78, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
103 0x00,
104 ];
105
106 #[test]
107 fn test_avc3_bbc() {
108 let expected = Avc3 {
109 visual: Visual {
110 data_reference_index: 1,
111 width: 192,
112 height: 108,
113 horizresolution: 0x48.into(),
114 vertresolution: 0x48.into(),
115 frame_count: 1,
116 compressor: "h264".into(),
117 depth: 24,
118 },
119 avcc: Avcc {
120 configuration_version: 1,
121 avc_profile_indication: 0x42,
122 profile_compatibility: 0xC0,
123 avc_level_indication: 0x15,
124 length_size: 4,
125 sequence_parameter_sets: Vec::new(),
126 picture_parameter_sets: Vec::new(),
127 ext: None,
128 },
129 colr: Some(Colr::Nclx {
130 colour_primaries: 1,
131 transfer_characteristics: 1,
132 matrix_coefficients: 1,
133 full_range_flag: false,
134 }),
135 pasp: Some(Pasp {
136 h_spacing: 1,
137 v_spacing: 1,
138 }),
139 ..Default::default()
140 };
141
142 let decoded = Avc3::decode(&mut &BBC[..]).unwrap();
143 assert_eq!(decoded, expected);
144 roundtrip(&expected);
145 }
146
147 #[test]
148 fn test_avc3_with_extras() {
149 roundtrip(&Avc3 {
150 visual: Visual {
151 data_reference_index: 1,
152 width: 320,
153 height: 240,
154 horizresolution: 0x48.into(),
155 vertresolution: 0x48.into(),
156 frame_count: 1,
157 compressor: "they".into(),
158 depth: 24,
159 },
160 avcc: Avcc {
161 configuration_version: 1,
162 avc_profile_indication: 100,
163 profile_compatibility: 0,
164 avc_level_indication: 13,
165 length_size: 4,
166 sequence_parameter_sets: vec![vec![
167 0x67, 0x64, 0x00, 0x0D, 0xAC, 0xD9, 0x41, 0x41, 0xFA, 0x10, 0x00, 0x00, 0x03,
168 0x00, 0x10, 0x00, 0x00, 0x03, 0x03, 0x20, 0xF1, 0x42, 0x99, 0x60,
169 ]],
170 picture_parameter_sets: vec![vec![0x68, 0xEB, 0xE3, 0xCB, 0x22, 0xC0]],
171 ..Default::default()
172 },
173 btrt: Some(Btrt {
174 buffer_size_db: 14075,
175 max_bitrate: 374288,
176 avg_bitrate: 240976,
177 }),
178 colr: Some(Colr::default()),
179 pasp: Some(Pasp {
180 h_spacing: 4,
181 v_spacing: 3,
182 }),
183 taic: Some(Taic {
184 time_uncertainty: u64::MAX,
185 clock_resolution: 1000,
186 clock_drift_rate: i32::MAX,
187 clock_type: ClockType::CanSync,
188 }),
189 fiel: Some(Fiel {
190 field_count: 2,
191 field_order: 0,
192 }),
193 spatial: Default::default(),
194 });
195 }
196}