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
41 Ok(Mp4a {
42 audio,
43 esds: esds.ok_or(Error::MissingBox(Esds::KIND))?,
44 btrt,
45 taic,
46 })
47 }
48
49 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
50 self.audio.encode(buf)?;
51 self.esds.encode(buf)?;
52 self.btrt.encode(buf)?;
53 self.taic.encode(buf)?;
54
55 Ok(())
56 }
57}
58
59const WAVE: FourCC = FourCC::new(b"wave");
61
62fn decode_wave(mut wave: &[u8], esds: &mut Option<Esds>, btrt: &mut Option<Btrt>) -> Result<()> {
69 while let Some(header) = Header::decode_maybe(&mut wave)? {
70 let size = match header.size {
73 Some(size) if size <= wave.remaining() => size,
74 _ => break,
75 };
76 let mut child = wave.slice(size);
77 if header.kind == Esds::KIND {
78 *esds = Some(Esds::decode_body(&mut child)?);
79 } else if header.kind == Btrt::KIND {
80 *btrt = Some(Btrt::decode_body(&mut child)?);
81 }
82 wave.advance(size);
83 }
84 Ok(())
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90
91 #[test]
92 fn test_mp4a() {
93 let expected = Mp4a {
94 audio: Audio {
95 data_reference_index: 1,
96 channel_count: 2,
97 sample_size: 16,
98 sample_rate: 48000.into(),
99 },
100 esds: Esds {
101 es_desc: esds::EsDescriptor {
102 es_id: 2,
103 dec_config: esds::DecoderConfig {
104 object_type_indication: 0x40,
105 stream_type: 0x05,
106 up_stream: 0,
107 buffer_size_db: Default::default(),
108 max_bitrate: 67695,
109 avg_bitrate: 67695,
110 dec_specific: esds::DecoderSpecific {
111 profile: 2,
112 freq_index: 4,
113 chan_conf: 2,
114 },
115 },
116 sl_config: esds::SLConfig::default(),
117 },
118 },
119 btrt: Some(Btrt {
120 buffer_size_db: 1,
121 max_bitrate: 2,
122 avg_bitrate: 3,
123 }),
124 taic: None,
125 };
126 let mut buf = Vec::new();
127 expected.encode(&mut buf).unwrap();
128
129 let mut buf = buf.as_ref();
130 let decoded = Mp4a::decode(&mut buf).unwrap();
131 assert_eq!(decoded, expected);
132 }
133
134 fn atom_box(fourcc: &[u8; 4], body: &[u8]) -> Vec<u8> {
136 let mut v = Vec::with_capacity(8 + body.len());
137 v.extend_from_slice(&((8 + body.len()) as u32).to_be_bytes());
138 v.extend_from_slice(fourcc);
139 v.extend_from_slice(body);
140 v
141 }
142
143 #[test]
147 fn test_mp4a_quicktime_wave() {
148 let audio = Audio {
149 data_reference_index: 1,
150 channel_count: 2,
151 sample_size: 16,
152 sample_rate: 48000.into(),
153 };
154 let esds = Esds {
155 es_desc: esds::EsDescriptor {
156 es_id: 2,
157 dec_config: esds::DecoderConfig {
158 object_type_indication: 0x40,
159 stream_type: 0x05,
160 up_stream: 0,
161 buffer_size_db: Default::default(),
162 max_bitrate: 67695,
163 avg_bitrate: 67695,
164 dec_specific: esds::DecoderSpecific {
165 profile: 2,
166 freq_index: 4,
167 chan_conf: 2,
168 },
169 },
170 sl_config: esds::SLConfig::default(),
171 },
172 };
173
174 let btrt = Btrt {
175 buffer_size_db: 1,
176 max_bitrate: 2,
177 avg_bitrate: 3,
178 };
179
180 let mut audio_bytes = Vec::new();
182 audio.encode(&mut audio_bytes).unwrap();
183 let mut esds_box = Vec::new();
184 esds.encode(&mut esds_box).unwrap();
185 let mut btrt_box = Vec::new();
186 btrt.encode(&mut btrt_box).unwrap();
187
188 let mut wave_body = Vec::new();
191 wave_body.extend_from_slice(&atom_box(b"frma", b"mp4a"));
192 wave_body.extend_from_slice(&atom_box(b"mp4a", &[0, 0, 0, 0]));
193 wave_body.extend_from_slice(&esds_box);
194 wave_body.extend_from_slice(&btrt_box);
195 wave_body.extend_from_slice(&[0, 0, 0, 8, 0, 0, 0, 0]);
196
197 let mut mp4a_body = audio_bytes;
199 mp4a_body.extend_from_slice(&atom_box(b"wave", &wave_body));
200 let mp4a = atom_box(b"mp4a", &mp4a_body);
201
202 let mut buf = mp4a.as_slice();
203 let decoded = Mp4a::decode(&mut buf).unwrap();
204 assert_eq!(decoded.audio, audio);
205 assert_eq!(decoded.esds, esds);
206 assert_eq!(decoded.btrt, Some(btrt));
208 }
209
210 #[test]
211 fn test_mp4a_with_taic() {
212 let expected = Mp4a {
213 audio: Audio {
214 data_reference_index: 1,
215 channel_count: 2,
216 sample_size: 16,
217 sample_rate: 48000.into(),
218 },
219 esds: Esds {
220 es_desc: esds::EsDescriptor {
221 es_id: 2,
222 dec_config: esds::DecoderConfig {
223 object_type_indication: 0x40,
224 stream_type: 0x05,
225 up_stream: 0,
226 buffer_size_db: Default::default(),
227 max_bitrate: 67695,
228 avg_bitrate: 67695,
229 dec_specific: esds::DecoderSpecific {
230 profile: 2,
231 freq_index: 4,
232 chan_conf: 2,
233 },
234 },
235 sl_config: esds::SLConfig::default(),
236 },
237 },
238 btrt: None,
239 taic: Some(Taic {
240 time_uncertainty: 1,
241 clock_resolution: 2,
242 clock_drift_rate: 4,
243 clock_type: ClockType::CanSync,
244 }),
245 };
246 let mut buf = Vec::new();
247 expected.encode(&mut buf).unwrap();
248
249 let mut buf = buf.as_ref();
250 let decoded = Mp4a::decode(&mut buf).unwrap();
251 assert_eq!(decoded, expected);
252 }
253}