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 dec_config: esds::DecoderConfig {
105 object_type_indication: 0x40,
106 stream_type: 0x05,
107 up_stream: 0,
108 buffer_size_db: Default::default(),
109 max_bitrate: 67695,
110 avg_bitrate: 67695,
111 dec_specific: Some(esds::DecoderSpecific {
112 profile: 2,
113 freq_index: 4,
114 chan_conf: 2,
115 raw: vec![0x12, 0x10],
116 }),
117 },
118 sl_config: esds::SLConfig::default(),
119 },
120 },
121 btrt: Some(Btrt {
122 buffer_size_db: 1,
123 max_bitrate: 2,
124 avg_bitrate: 3,
125 }),
126 taic: None,
127 };
128 let mut buf = Vec::new();
129 expected.encode(&mut buf).unwrap();
130
131 let mut buf = buf.as_ref();
132 let decoded = Mp4a::decode(&mut buf).unwrap();
133 assert_eq!(decoded, expected);
134 }
135
136 fn atom_box(fourcc: &[u8; 4], body: &[u8]) -> Vec<u8> {
138 let mut v = Vec::with_capacity(8 + body.len());
139 v.extend_from_slice(&((8 + body.len()) as u32).to_be_bytes());
140 v.extend_from_slice(fourcc);
141 v.extend_from_slice(body);
142 v
143 }
144
145 #[test]
149 fn test_mp4a_quicktime_wave() {
150 let audio = Audio {
151 data_reference_index: 1,
152 channel_count: 2,
153 sample_size: 16,
154 sample_rate: 48000.into(),
155 };
156 let esds = Esds {
157 es_desc: esds::EsDescriptor {
158 es_id: 2,
159 dec_config: esds::DecoderConfig {
160 object_type_indication: 0x40,
161 stream_type: 0x05,
162 up_stream: 0,
163 buffer_size_db: Default::default(),
164 max_bitrate: 67695,
165 avg_bitrate: 67695,
166 dec_specific: Some(esds::DecoderSpecific {
167 profile: 2,
168 freq_index: 4,
169 chan_conf: 2,
170 raw: vec![0x12, 0x10],
171 }),
172 },
173 sl_config: esds::SLConfig::default(),
174 },
175 };
176
177 let btrt = Btrt {
178 buffer_size_db: 1,
179 max_bitrate: 2,
180 avg_bitrate: 3,
181 };
182
183 let mut audio_bytes = Vec::new();
185 audio.encode(&mut audio_bytes).unwrap();
186 let mut esds_box = Vec::new();
187 esds.encode(&mut esds_box).unwrap();
188 let mut btrt_box = Vec::new();
189 btrt.encode(&mut btrt_box).unwrap();
190
191 let mut wave_body = Vec::new();
194 wave_body.extend_from_slice(&atom_box(b"frma", b"mp4a"));
195 wave_body.extend_from_slice(&atom_box(b"mp4a", &[0, 0, 0, 0]));
196 wave_body.extend_from_slice(&esds_box);
197 wave_body.extend_from_slice(&btrt_box);
198 wave_body.extend_from_slice(&[0, 0, 0, 8, 0, 0, 0, 0]);
199
200 let mut mp4a_body = audio_bytes;
202 mp4a_body.extend_from_slice(&atom_box(b"wave", &wave_body));
203 let mp4a = atom_box(b"mp4a", &mp4a_body);
204
205 let mut buf = mp4a.as_slice();
206 let decoded = Mp4a::decode(&mut buf).unwrap();
207 assert_eq!(decoded.audio, audio);
208 assert_eq!(decoded.esds, esds);
209 assert_eq!(decoded.btrt, Some(btrt));
211 }
212
213 #[test]
214 fn test_mp4a_with_taic() {
215 let expected = Mp4a {
216 audio: Audio {
217 data_reference_index: 1,
218 channel_count: 2,
219 sample_size: 16,
220 sample_rate: 48000.into(),
221 },
222 esds: Esds {
223 es_desc: esds::EsDescriptor {
224 es_id: 2,
225 dec_config: esds::DecoderConfig {
226 object_type_indication: 0x40,
227 stream_type: 0x05,
228 up_stream: 0,
229 buffer_size_db: Default::default(),
230 max_bitrate: 67695,
231 avg_bitrate: 67695,
232 dec_specific: Some(esds::DecoderSpecific {
233 profile: 2,
234 freq_index: 4,
235 chan_conf: 2,
236 raw: vec![0x12, 0x10],
237 }),
238 },
239 sl_config: esds::SLConfig::default(),
240 },
241 },
242 btrt: None,
243 taic: Some(Taic {
244 time_uncertainty: 1,
245 clock_resolution: 2,
246 clock_drift_rate: 4,
247 clock_type: ClockType::CanSync,
248 }),
249 };
250 let mut buf = Vec::new();
251 expected.encode(&mut buf).unwrap();
252
253 let mut buf = buf.as_ref();
254 let decoded = Mp4a::decode(&mut buf).unwrap();
255 assert_eq!(decoded, expected);
256 }
257}