mp4_atom/moov/trak/mdia/minf/stbl/stsd/mp4a/
mod.rs1use crate::*;
2
3pub mod esds;
5pub use esds::Esds;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9pub struct Mp4a {
10 pub audio: Audio,
11 pub esds: Esds,
12 pub btrt: Option<Btrt>,
13 pub taic: Option<Taic>,
14}
15
16impl Atom for Mp4a {
17 const KIND: FourCC = FourCC::new(b"mp4a");
18
19 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
20 let audio = Audio::decode(buf)?;
21
22 let mut btrt = None;
23 let mut esds = None;
24 let mut taic = None;
25
26 while let Some(atom) = Any::decode_maybe(buf)? {
30 match atom {
31 Any::Btrt(atom) => btrt = atom.into(),
32 Any::Esds(atom) => esds = atom.into(),
33 Any::Taic(atom) => taic = atom.into(),
34 Any::Unknown(kind, body) if kind == WAVE => {
35 decode_wave(&body, &mut esds, &mut btrt)?;
36 }
37 unknown => Self::decode_unknown(&unknown)?,
38 }
39 }
40 skip_trailing_padding(buf);
41
42 Ok(Mp4a {
43 audio,
44 esds: esds.ok_or(Error::MissingBox(Esds::KIND))?,
45 btrt,
46 taic,
47 })
48 }
49
50 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
51 self.audio.encode(buf)?;
52 self.esds.encode(buf)?;
53 self.btrt.encode(buf)?;
54 self.taic.encode(buf)?;
55
56 Ok(())
57 }
58}
59
60const WAVE: FourCC = FourCC::new(b"wave");
62
63fn decode_wave(mut wave: &[u8], esds: &mut Option<Esds>, btrt: &mut Option<Btrt>) -> Result<()> {
70 while let Some(header) = Header::decode_maybe(&mut wave)? {
71 let size = match header.size {
74 Some(size) if size <= wave.remaining() => size,
75 _ => break,
76 };
77 let mut child = wave.slice(size);
78 if header.kind == Esds::KIND {
79 *esds = Some(Esds::decode_body(&mut child)?);
80 } else if header.kind == Btrt::KIND {
81 *btrt = Some(Btrt::decode_body(&mut child)?);
82 }
83 wave.advance(size);
84 }
85 Ok(())
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91
92 #[test]
93 fn test_mp4a() {
94 let expected = Mp4a {
95 audio: Audio {
96 data_reference_index: 1,
97 channel_count: 2,
98 sample_size: 16,
99 sample_rate: 48000.into(),
100 },
101 esds: Esds {
102 es_desc: esds::EsDescriptor {
103 es_id: 2,
104 depends_on_es_id: None,
105 url: None,
106 ocr_es_id: None,
107 stream_priority: 0,
108 dec_config: esds::DecoderConfig {
109 object_type_indication: 0x40,
110 stream_type: 0x05,
111 up_stream: 0,
112 buffer_size_db: Default::default(),
113 max_bitrate: 67695,
114 avg_bitrate: 67695,
115 dec_specific: Some(esds::DecoderSpecific {
116 profile: 2,
117 freq_index: 4,
118 chan_conf: 2,
119 raw: vec![0x12, 0x10],
120 }),
121 },
122 sl_config: esds::SLConfig::default(),
123 },
124 },
125 btrt: Some(Btrt {
126 buffer_size_db: 1,
127 max_bitrate: 2,
128 avg_bitrate: 3,
129 }),
130 taic: None,
131 };
132 let mut buf = Vec::new();
133 expected.encode(&mut buf).unwrap();
134
135 let mut buf = buf.as_ref();
136 let decoded = Mp4a::decode(&mut buf).unwrap();
137 assert_eq!(decoded, expected);
138 }
139
140 fn atom_box(fourcc: &[u8; 4], body: &[u8]) -> Vec<u8> {
142 let mut v = Vec::with_capacity(8 + body.len());
143 v.extend_from_slice(&((8 + body.len()) as u32).to_be_bytes());
144 v.extend_from_slice(fourcc);
145 v.extend_from_slice(body);
146 v
147 }
148
149 #[test]
153 fn test_mp4a_quicktime_wave() {
154 let audio = Audio {
155 data_reference_index: 1,
156 channel_count: 2,
157 sample_size: 16,
158 sample_rate: 48000.into(),
159 };
160 let esds = Esds {
161 es_desc: esds::EsDescriptor {
162 es_id: 2,
163 depends_on_es_id: None,
164 url: None,
165 ocr_es_id: None,
166 stream_priority: 0,
167 dec_config: esds::DecoderConfig {
168 object_type_indication: 0x40,
169 stream_type: 0x05,
170 up_stream: 0,
171 buffer_size_db: Default::default(),
172 max_bitrate: 67695,
173 avg_bitrate: 67695,
174 dec_specific: Some(esds::DecoderSpecific {
175 profile: 2,
176 freq_index: 4,
177 chan_conf: 2,
178 raw: vec![0x12, 0x10],
179 }),
180 },
181 sl_config: esds::SLConfig::default(),
182 },
183 };
184
185 let btrt = Btrt {
186 buffer_size_db: 1,
187 max_bitrate: 2,
188 avg_bitrate: 3,
189 };
190
191 let mut audio_bytes = Vec::new();
193 audio.encode(&mut audio_bytes).unwrap();
194 let mut esds_box = Vec::new();
195 esds.encode(&mut esds_box).unwrap();
196 let mut btrt_box = Vec::new();
197 btrt.encode(&mut btrt_box).unwrap();
198
199 let mut wave_body = Vec::new();
202 wave_body.extend_from_slice(&atom_box(b"frma", b"mp4a"));
203 wave_body.extend_from_slice(&atom_box(b"mp4a", &[0, 0, 0, 0]));
204 wave_body.extend_from_slice(&esds_box);
205 wave_body.extend_from_slice(&btrt_box);
206 wave_body.extend_from_slice(&[0, 0, 0, 8, 0, 0, 0, 0]);
207
208 let mut mp4a_body = audio_bytes;
210 mp4a_body.extend_from_slice(&atom_box(b"wave", &wave_body));
211 let mp4a = atom_box(b"mp4a", &mp4a_body);
212
213 let mut buf = mp4a.as_slice();
214 let decoded = Mp4a::decode(&mut buf).unwrap();
215 assert_eq!(decoded.audio, audio);
216 assert_eq!(decoded.esds, esds);
217 assert_eq!(decoded.btrt, Some(btrt));
219 }
220
221 #[test]
222 fn test_mp4a_with_taic() {
223 let expected = Mp4a {
224 audio: Audio {
225 data_reference_index: 1,
226 channel_count: 2,
227 sample_size: 16,
228 sample_rate: 48000.into(),
229 },
230 esds: Esds {
231 es_desc: esds::EsDescriptor {
232 es_id: 2,
233 depends_on_es_id: None,
234 url: None,
235 ocr_es_id: None,
236 stream_priority: 0,
237 dec_config: esds::DecoderConfig {
238 object_type_indication: 0x40,
239 stream_type: 0x05,
240 up_stream: 0,
241 buffer_size_db: Default::default(),
242 max_bitrate: 67695,
243 avg_bitrate: 67695,
244 dec_specific: Some(esds::DecoderSpecific {
245 profile: 2,
246 freq_index: 4,
247 chan_conf: 2,
248 raw: vec![0x12, 0x10],
249 }),
250 },
251 sl_config: esds::SLConfig::default(),
252 },
253 },
254 btrt: None,
255 taic: Some(Taic {
256 time_uncertainty: 1,
257 clock_resolution: 2,
258 clock_drift_rate: 4,
259 clock_type: ClockType::CanSync,
260 }),
261 };
262 let mut buf = Vec::new();
263 expected.encode(&mut buf).unwrap();
264
265 let mut buf = buf.as_ref();
266 let decoded = Mp4a::decode(&mut buf).unwrap();
267 assert_eq!(decoded, expected);
268 }
269}