1use crate::aac::bits::{BitReader, BitWriter};
2
3use crate::aac::tables::{SAMPLE_RATES, table_index_for_rate};
4use crate::media::{Error, Result};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum ElementType {
8 Sce,
9 Cpe,
10 Lfe,
11}
12
13impl ElementType {
14 pub fn channels(self) -> usize {
15 if self == ElementType::Cpe { 2 } else { 1 }
16 }
17}
18
19#[derive(Debug, Clone, PartialEq, Eq, Default)]
20pub struct ProgramConfig {
21 pub element_instance_tag: u8,
22 pub object_type: u8,
23 pub sf_index: u8,
24 pub front: Vec<(bool, u8)>,
25 pub side: Vec<(bool, u8)>,
26 pub back: Vec<(bool, u8)>,
27 pub lfe: Vec<u8>,
28 pub assoc_data: Vec<u8>,
29 pub cc: Vec<(bool, u8)>,
30 pub comment: Vec<u8>,
31}
32
33impl ProgramConfig {
34 pub fn parse(br: &mut BitReader) -> Result<ProgramConfig> {
35 let mut p = ProgramConfig {
36 element_instance_tag: br.read_bits(4)? as u8,
37 object_type: br.read_bits(2)? as u8,
38 sf_index: br.read_bits(4)? as u8,
39 ..Default::default()
40 };
41 let nf = br.read_bits(4)?;
42 let ns = br.read_bits(4)?;
43 let nb = br.read_bits(4)?;
44 let nl = br.read_bits(2)?;
45 let na = br.read_bits(3)?;
46 let nc = br.read_bits(4)?;
47 if br.read_bits(1)? == 1 {
48 br.skip(4)?;
49 }
50 if br.read_bits(1)? == 1 {
51 br.skip(4)?;
52 }
53 if br.read_bits(1)? == 1 {
54 br.skip(3)?;
55 }
56 for (n, v) in [(nf, &mut p.front), (ns, &mut p.side), (nb, &mut p.back)] {
57 for _ in 0..n {
58 let cpe = br.read_bits(1)? == 1;
59 v.push((cpe, br.read_bits(4)? as u8));
60 }
61 }
62 for _ in 0..nl {
63 p.lfe.push(br.read_bits(4)? as u8);
64 }
65 for _ in 0..na {
66 p.assoc_data.push(br.read_bits(4)? as u8);
67 }
68 for _ in 0..nc {
69 let ind = br.read_bits(1)? == 1;
70 p.cc.push((ind, br.read_bits(4)? as u8));
71 }
72 br.byte_align();
73 let len = br.read_bits(8)?;
74 for _ in 0..len {
75 p.comment.push(br.read_bits(8)? as u8);
76 }
77 Ok(p)
78 }
79
80 pub fn write(&self, bw: &mut BitWriter) {
81 bw.write_bits(self.element_instance_tag as u32, 4);
82 bw.write_bits(self.object_type as u32, 2);
83 bw.write_bits(self.sf_index as u32, 4);
84 bw.write_bits(self.front.len() as u32, 4);
85 bw.write_bits(self.side.len() as u32, 4);
86 bw.write_bits(self.back.len() as u32, 4);
87 bw.write_bits(self.lfe.len() as u32, 2);
88 bw.write_bits(self.assoc_data.len() as u32, 3);
89 bw.write_bits(self.cc.len() as u32, 4);
90 bw.write_bits(0, 3);
91 for v in [&self.front, &self.side, &self.back] {
92 for &(cpe, tag) in v {
93 bw.write_bits(cpe as u32, 1);
94 bw.write_bits(tag as u32, 4);
95 }
96 }
97 for &t in &self.lfe {
98 bw.write_bits(t as u32, 4);
99 }
100 for &t in &self.assoc_data {
101 bw.write_bits(t as u32, 4);
102 }
103 for &(ind, t) in &self.cc {
104 bw.write_bits(ind as u32, 1);
105 bw.write_bits(t as u32, 4);
106 }
107 bw.align_zero();
108 bw.write_bits(self.comment.len().min(255) as u32, 8);
109 for &b in self.comment.iter().take(255) {
110 bw.write_bits(b as u32, 8);
111 }
112 }
113
114 pub fn layout(&self) -> Vec<(ElementType, u8)> {
115 let mut out = Vec::new();
116 for v in [&self.front, &self.side, &self.back] {
117 for &(cpe, tag) in v {
118 out.push((
119 if cpe {
120 ElementType::Cpe
121 } else {
122 ElementType::Sce
123 },
124 tag,
125 ));
126 }
127 }
128 for &t in &self.lfe {
129 out.push((ElementType::Lfe, t));
130 }
131 out
132 }
133}
134
135pub fn config_layout(channel_config: u8) -> Option<Vec<(ElementType, u8)>> {
136 use ElementType::*;
137 Some(match channel_config {
138 1 => vec![(Sce, 0)],
139 2 => vec![(Cpe, 0)],
140 3 => vec![(Sce, 0), (Cpe, 0)],
141 4 => vec![(Sce, 0), (Cpe, 0), (Sce, 1)],
142 5 => vec![(Sce, 0), (Cpe, 0), (Cpe, 1)],
143 6 => vec![(Sce, 0), (Cpe, 0), (Cpe, 1), (Lfe, 0)],
144 7 => vec![(Sce, 0), (Cpe, 0), (Cpe, 1), (Cpe, 2), (Lfe, 0)],
145 _ => return None,
146 })
147}
148
149#[derive(Debug, Clone, PartialEq, Eq)]
150pub struct AudioSpecificConfig {
151 pub object_type: u8,
152 pub sample_rate: u32,
153 pub sf_index: u8,
154 pub channel_config: u8,
155 pub frame_length_flag: bool,
156 pub sbr: bool,
157 pub ps: bool,
158 pub extension_sample_rate: Option<u32>,
159 pub pce: Option<ProgramConfig>,
160}
161
162fn read_aot(br: &mut BitReader) -> Result<u8> {
163 let a = br.read_bits(5)? as u8;
164 Ok(if a == 31 {
165 32 + br.read_bits(6)? as u8
166 } else {
167 a
168 })
169}
170
171fn read_rate(br: &mut BitReader) -> Result<(u8, u32)> {
172 let i = br.read_bits(4)? as u8;
173 if i == 15 {
174 let r = br.read_bits(24)?;
175 return Ok((table_index_for_rate(r), r));
176 }
177 let r = *SAMPLE_RATES
178 .get(i as usize)
179 .ok_or(Error::Invalid("reserved sampling frequency index".into()))?;
180 Ok((i, r))
181}
182
183impl AudioSpecificConfig {
184 pub fn lc(sf_index: u8, channel_config: u8) -> AudioSpecificConfig {
185 AudioSpecificConfig {
186 object_type: 2,
187 sample_rate: SAMPLE_RATES.get(sf_index as usize).copied().unwrap_or(0),
188 sf_index,
189 channel_config,
190 frame_length_flag: false,
191 sbr: false,
192 ps: false,
193 extension_sample_rate: None,
194 pce: None,
195 }
196 }
197
198 pub fn parse(data: &[u8]) -> Result<AudioSpecificConfig> {
199 let mut br = BitReader::new(data);
200 let mut aot = read_aot(&mut br)?;
201 let (sf_index, sample_rate) = read_rate(&mut br)?;
202 let channel_config = br.read_bits(4)? as u8;
203 let (mut sbr, mut ps, mut extension_sample_rate) = (false, false, None);
204 if aot == 5 || aot == 29 {
205 sbr = true;
206 ps = aot == 29;
207 let (_, ext) = read_rate(&mut br)?;
208 extension_sample_rate = Some(ext);
209 aot = read_aot(&mut br)?;
210 }
211 if aot != 2 {
212 return Err(Error::Unsupported(
213 match aot {
214 1 => "AAC Main profile",
215 3 => "AAC SSR profile",
216 4 => "AAC LTP profile",
217 23 => "AAC-LD",
218 39 => "AAC-ELD",
219 _ => "audio object type other than AAC LC",
220 }
221 .into(),
222 ));
223 }
224 let frame_length_flag = br.read_bits(1)? == 1;
225 if br.read_bits(1)? == 1 {
226 br.skip(14)?;
227 }
228 let _extension_flag = br.read_bits(1)?;
229 let pce = if channel_config == 0 {
230 Some(ProgramConfig::parse(&mut br)?)
231 } else {
232 None
233 };
234 if frame_length_flag {
235 return Err(Error::Unsupported("960-sample frames".into()));
236 }
237 let cfg = AudioSpecificConfig {
238 object_type: aot,
239 sample_rate,
240 sf_index,
241 channel_config,
242 frame_length_flag,
243 sbr,
244 ps,
245 extension_sample_rate,
246 pce,
247 };
248 if cfg.channels() == 0 {
249 return Err(Error::Invalid("no channels".into()));
250 }
251 Ok(cfg)
252 }
253
254 pub fn to_bytes(&self) -> Vec<u8> {
255 let mut bw = BitWriter::new();
256 bw.write_bits(self.object_type as u32, 5);
257 match crate::aac::tables::sample_rate_index(self.sample_rate) {
258 Some(i) => bw.write_bits(i as u32, 4),
259 None => {
260 bw.write_bits(15, 4);
261 bw.write_bits(self.sample_rate, 24);
262 }
263 }
264 bw.write_bits(self.channel_config as u32, 4);
265 bw.write_bits(0, 3);
266 if self.channel_config == 0
267 && let Some(p) = &self.pce
268 {
269 p.write(&mut bw);
270 }
271 bw.finish()
272 }
273
274 pub fn layout(&self) -> Vec<(ElementType, u8)> {
275 match &self.pce {
276 Some(p) if self.channel_config == 0 => p.layout(),
277 _ => config_layout(self.channel_config).unwrap_or_default(),
278 }
279 }
280
281 pub fn channels(&self) -> usize {
282 self.layout().iter().map(|e| e.0.channels()).sum()
283 }
284}
285
286#[derive(Debug, Clone, Copy, PartialEq, Eq)]
287pub struct AdtsHeader {
288 pub object_type: u8,
289 pub sf_index: u8,
290 pub channel_config: u8,
291 pub frame_length: usize,
292 pub buffer_fullness: u16,
293 pub header_length: usize,
294 pub raw_data_blocks: u8,
295}
296
297impl AdtsHeader {
298 pub fn parse(data: &[u8]) -> Result<AdtsHeader> {
299 let mut br = BitReader::new(data);
300 if br.read_bits(12)? != 0xFFF {
301 return Err(Error::Invalid("missing ADTS syncword".into()));
302 }
303 br.skip(1)?;
304 if br.read_bits(2)? != 0 {
305 return Err(Error::Invalid("ADTS layer must be 0".into()));
306 }
307 let protection_absent = br.read_bits(1)? == 1;
308 let object_type = br.read_bits(2)? as u8 + 1;
309 let sf_index = br.read_bits(4)? as u8;
310 if sf_index as usize >= SAMPLE_RATES.len() {
311 return Err(Error::Invalid(
312 "invalid ADTS sampling frequency index".into(),
313 ));
314 }
315 br.skip(1)?;
316 let channel_config = br.read_bits(3)? as u8;
317 br.skip(4)?;
318 let frame_length = br.read_bits(13)? as usize;
319 let buffer_fullness = br.read_bits(11)? as u16;
320 let raw_data_blocks = br.read_bits(2)? as u8 + 1;
321 let header_length = if protection_absent { 7 } else { 9 };
322 if frame_length < header_length {
323 return Err(Error::Invalid("ADTS frame shorter than its header".into()));
324 }
325 Ok(AdtsHeader {
326 object_type,
327 sf_index,
328 channel_config,
329 frame_length,
330 buffer_fullness,
331 header_length,
332 raw_data_blocks,
333 })
334 }
335
336 pub fn to_asc(&self) -> AudioSpecificConfig {
337 AudioSpecificConfig {
338 object_type: self.object_type,
339 ..AudioSpecificConfig::lc(self.sf_index, self.channel_config)
340 }
341 }
342
343 pub fn write(
344 object_type: u8,
345 sf_index: u8,
346 channel_config: u8,
347 payload_len: usize,
348 buffer_fullness: u16,
349 ) -> [u8; 7] {
350 let len = (payload_len + 7) as u32;
351 let mut bw = BitWriter::new();
352 bw.write_bits(0xFFF, 12);
353 bw.write_bits(0, 1);
354 bw.write_bits(0, 2);
355 bw.write_bits(1, 1);
356 bw.write_bits((object_type.max(1) - 1) as u32 & 3, 2);
357 bw.write_bits(sf_index as u32, 4);
358 bw.write_bits(0, 1);
359 bw.write_bits(channel_config as u32 & 7, 3);
360 bw.write_bits(0, 4);
361 bw.write_bits(len & 0x1FFF, 13);
362 bw.write_bits(buffer_fullness as u32 & 0x7FF, 11);
363 bw.write_bits(0, 2);
364 let v = bw.finish();
365 let mut out = [0u8; 7];
366 out.copy_from_slice(&v);
367 out
368 }
369}
370
371pub fn split_adts(mut data: &[u8]) -> Result<Vec<(AdtsHeader, &[u8])>> {
372 let mut out = Vec::new();
373 while data.len() >= 7 {
374 let h = match AdtsHeader::parse(data) {
375 Ok(h) => h,
376 Err(e) => {
377 if out.is_empty() {
378 return Err(e);
379 }
380 break;
381 }
382 };
383 if h.frame_length > data.len() {
384 break;
385 }
386 out.push((h, &data[h.header_length..h.frame_length]));
387 data = &data[h.frame_length..];
388 }
389 if out.is_empty() {
390 return Err(Error::Invalid("no ADTS frames".into()));
391 }
392 Ok(out)
393}