1use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
2use serde::Serialize;
3use std::io::{Read, Seek, Write};
4
5use crate::mp4box::*;
6
7#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
8pub struct Mp4aBox {
9 pub data_reference_index: u16,
10 pub channelcount: u16,
11 pub samplesize: u16,
12
13 #[serde(with = "value_u32")]
14 pub samplerate: FixedPointU16,
15 pub esds: Option<EsdsBox>,
16}
17
18impl Default for Mp4aBox {
19 fn default() -> Self {
20 Self {
21 data_reference_index: 0,
22 channelcount: 2,
23 samplesize: 16,
24 samplerate: FixedPointU16::new(48000),
25 esds: Some(EsdsBox::default()),
26 }
27 }
28}
29
30impl Mp4aBox {
31 pub fn new(config: &AacConfig) -> Self {
32 Self {
33 data_reference_index: 1,
34 channelcount: config.chan_conf as u16,
35 samplesize: 16,
36 samplerate: FixedPointU16::new(config.freq_index.freq() as u16),
37 esds: Some(EsdsBox::new(config)),
38 }
39 }
40
41 pub fn get_type(&self) -> BoxType {
42 BoxType::Mp4aBox
43 }
44
45 pub fn get_size(&self) -> u64 {
46 let mut size = HEADER_SIZE + 8 + 20;
47 if let Some(ref esds) = self.esds {
48 size += esds.box_size();
49 }
50 size
51 }
52}
53
54impl Mp4Box for Mp4aBox {
55 fn box_type(&self) -> BoxType {
56 self.get_type()
57 }
58
59 fn box_size(&self) -> u64 {
60 self.get_size()
61 }
62
63 fn to_json(&self) -> Result<String> {
64 Ok(serde_json::to_string(&self).unwrap())
65 }
66
67 fn summary(&self) -> Result<String> {
68 let s = format!(
69 "channel_count={} sample_size={} sample_rate={}",
70 self.channelcount,
71 self.samplesize,
72 self.samplerate.value()
73 );
74 Ok(s)
75 }
76}
77
78impl<R: Read + Seek> ReadBox<&mut R> for Mp4aBox {
79 fn read_box(reader: &mut R, size: u64) -> Result<Self> {
80 let start = box_start(reader)?;
81
82 reader.read_u32::<BigEndian>()?; reader.read_u16::<BigEndian>()?; let data_reference_index = reader.read_u16::<BigEndian>()?;
85 let version = reader.read_u16::<BigEndian>()?;
86 reader.read_u16::<BigEndian>()?; reader.read_u32::<BigEndian>()?; let channelcount = reader.read_u16::<BigEndian>()?;
89 let samplesize = reader.read_u16::<BigEndian>()?;
90 reader.read_u32::<BigEndian>()?; let samplerate = FixedPointU16::new_raw(reader.read_u32::<BigEndian>()?);
92
93 if version == 1 {
94 reader.read_u64::<BigEndian>()?;
96 reader.read_u64::<BigEndian>()?;
97 }
98
99 let mut esds = None;
101 let end = start + size;
102 loop {
103 let current = reader.stream_position()?;
104 if current >= end {
105 break;
106 }
107 let header = BoxHeader::read(reader)?;
108 let BoxHeader { name, size: s } = header;
109 if s > size {
110 return Err(Error::InvalidData(
111 "mp4a box contains a box with a larger size than it",
112 ));
113 }
114 if name == BoxType::EsdsBox {
115 esds = Some(EsdsBox::read_box(reader, s)?);
116 break;
117 } else if name == BoxType::WaveBox {
118 } else {
120 let skip_to = current + s;
122 skip_bytes_to(reader, skip_to)?;
123 }
124 }
125
126 skip_bytes_to(reader, end)?;
127
128 Ok(Mp4aBox {
129 data_reference_index,
130 channelcount,
131 samplesize,
132 samplerate,
133 esds,
134 })
135 }
136}
137
138impl<W: Write> WriteBox<&mut W> for Mp4aBox {
139 fn write_box(&self, writer: &mut W) -> Result<u64> {
140 let size = self.box_size();
141 BoxHeader::new(self.box_type(), size).write(writer)?;
142
143 writer.write_u32::<BigEndian>(0)?; writer.write_u16::<BigEndian>(0)?; writer.write_u16::<BigEndian>(self.data_reference_index)?;
146
147 writer.write_u64::<BigEndian>(0)?; writer.write_u16::<BigEndian>(self.channelcount)?;
149 writer.write_u16::<BigEndian>(self.samplesize)?;
150 writer.write_u32::<BigEndian>(0)?; writer.write_u32::<BigEndian>(self.samplerate.raw_value())?;
152
153 if let Some(ref esds) = self.esds {
154 esds.write_box(writer)?;
155 }
156
157 Ok(size)
158 }
159}
160
161#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize)]
162pub struct EsdsBox {
163 pub version: u8,
164 pub flags: u32,
165 pub es_desc: ESDescriptor,
166}
167
168impl EsdsBox {
169 pub fn new(config: &AacConfig) -> Self {
170 Self {
171 version: 0,
172 flags: 0,
173 es_desc: ESDescriptor::new(config),
174 }
175 }
176}
177
178impl Mp4Box for EsdsBox {
179 fn box_type(&self) -> BoxType {
180 BoxType::EsdsBox
181 }
182
183 fn box_size(&self) -> u64 {
184 HEADER_SIZE
185 + HEADER_EXT_SIZE
186 + 1
187 + size_of_length(ESDescriptor::desc_size()) as u64
188 + ESDescriptor::desc_size() as u64
189 }
190
191 fn to_json(&self) -> Result<String> {
192 Ok(serde_json::to_string(&self).unwrap())
193 }
194
195 fn summary(&self) -> Result<String> {
196 Ok(String::new())
197 }
198}
199
200impl<R: Read + Seek> ReadBox<&mut R> for EsdsBox {
201 fn read_box(reader: &mut R, size: u64) -> Result<Self> {
202 let start = box_start(reader)?;
203
204 let (version, flags) = read_box_header_ext(reader)?;
205
206 let mut es_desc = None;
207
208 let mut current = reader.stream_position()?;
209 let end = start + size;
210 while current < end {
211 let (desc_tag, desc_size) = read_desc(reader)?;
212 match desc_tag {
213 0x03 => {
214 es_desc = Some(ESDescriptor::read_desc(reader, desc_size)?);
215 }
216 _ => break,
217 }
218 current = reader.stream_position()?;
219 }
220
221 if es_desc.is_none() {
222 return Err(Error::InvalidData("ESDescriptor not found"));
223 }
224
225 skip_bytes_to(reader, start + size)?;
226
227 Ok(EsdsBox {
228 version,
229 flags,
230 es_desc: es_desc.unwrap(),
231 })
232 }
233}
234
235impl<W: Write> WriteBox<&mut W> for EsdsBox {
236 fn write_box(&self, writer: &mut W) -> Result<u64> {
237 let size = self.box_size();
238 BoxHeader::new(self.box_type(), size).write(writer)?;
239
240 write_box_header_ext(writer, self.version, self.flags)?;
241
242 self.es_desc.write_desc(writer)?;
243
244 Ok(size)
245 }
246}
247
248trait Descriptor: Sized {
249 fn desc_tag() -> u8;
250 fn desc_size() -> u32;
251}
252
253trait ReadDesc<T>: Sized {
254 fn read_desc(_: T, size: u32) -> Result<Self>;
255}
256
257trait WriteDesc<T>: Sized {
258 fn write_desc(&self, _: T) -> Result<u32>;
259}
260
261fn read_desc<R: Read>(reader: &mut R) -> Result<(u8, u32)> {
262 let tag = reader.read_u8()?;
263
264 let mut size: u32 = 0;
265 for _ in 0..4 {
266 let b = reader.read_u8()?;
267 size = (size << 7) | (b & 0x7F) as u32;
268 if b & 0x80 == 0 {
269 break;
270 }
271 }
272
273 Ok((tag, size))
274}
275
276fn size_of_length(size: u32) -> u32 {
277 match size {
278 0x0..=0x7F => 1,
279 0x80..=0x3FFF => 2,
280 0x4000..=0x1FFFFF => 3,
281 _ => 4,
282 }
283}
284
285fn write_desc<W: Write>(writer: &mut W, tag: u8, size: u32) -> Result<u64> {
286 writer.write_u8(tag)?;
287
288 if size as u64 > std::u32::MAX as u64 {
289 return Err(Error::InvalidData("invalid descriptor length range"));
290 }
291
292 let nbytes = size_of_length(size);
293
294 for i in 0..nbytes {
295 let mut b = (size >> ((nbytes - i - 1) * 7)) as u8 & 0x7F;
296 if i < nbytes - 1 {
297 b |= 0x80;
298 }
299 writer.write_u8(b)?;
300 }
301
302 Ok(1 + nbytes as u64)
303}
304
305#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize)]
306pub struct ESDescriptor {
307 pub es_id: u16,
308
309 pub dec_config: DecoderConfigDescriptor,
310 pub sl_config: SLConfigDescriptor,
311}
312
313impl ESDescriptor {
314 pub fn new(config: &AacConfig) -> Self {
315 Self {
316 es_id: 1,
317 dec_config: DecoderConfigDescriptor::new(config),
318 sl_config: SLConfigDescriptor::new(),
319 }
320 }
321}
322
323impl Descriptor for ESDescriptor {
324 fn desc_tag() -> u8 {
325 0x03
326 }
327
328 fn desc_size() -> u32 {
329 3 + 1
330 + size_of_length(DecoderConfigDescriptor::desc_size())
331 + DecoderConfigDescriptor::desc_size()
332 + 1
333 + size_of_length(SLConfigDescriptor::desc_size())
334 + SLConfigDescriptor::desc_size()
335 }
336}
337
338impl<R: Read + Seek> ReadDesc<&mut R> for ESDescriptor {
339 fn read_desc(reader: &mut R, size: u32) -> Result<Self> {
340 let start = reader.stream_position()?;
341
342 let es_id = reader.read_u16::<BigEndian>()?;
343 reader.read_u8()?; let mut dec_config = None;
346 let mut sl_config = None;
347
348 let mut current = reader.stream_position()?;
349 let end = start + size as u64;
350 while current < end {
351 let (desc_tag, desc_size) = read_desc(reader)?;
352 match desc_tag {
353 0x04 => {
354 dec_config = Some(DecoderConfigDescriptor::read_desc(reader, desc_size)?);
355 }
356 0x06 => {
357 sl_config = Some(SLConfigDescriptor::read_desc(reader, desc_size)?);
358 }
359 _ => {
360 skip_bytes(reader, desc_size as u64)?;
361 }
362 }
363 current = reader.stream_position()?;
364 }
365
366 Ok(ESDescriptor {
367 es_id,
368 dec_config: dec_config.unwrap_or_default(),
369 sl_config: sl_config.unwrap_or_default(),
370 })
371 }
372}
373
374impl<W: Write> WriteDesc<&mut W> for ESDescriptor {
375 fn write_desc(&self, writer: &mut W) -> Result<u32> {
376 let size = Self::desc_size();
377 write_desc(writer, Self::desc_tag(), size)?;
378
379 writer.write_u16::<BigEndian>(self.es_id)?;
380 writer.write_u8(0)?;
381
382 self.dec_config.write_desc(writer)?;
383 self.sl_config.write_desc(writer)?;
384
385 Ok(size)
386 }
387}
388
389#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize)]
390pub struct DecoderConfigDescriptor {
391 pub object_type_indication: u8,
392 pub stream_type: u8,
393 pub up_stream: u8,
394 pub buffer_size_db: u32,
395 pub max_bitrate: u32,
396 pub avg_bitrate: u32,
397
398 pub dec_specific: DecoderSpecificDescriptor,
399}
400
401impl DecoderConfigDescriptor {
402 pub fn new(config: &AacConfig) -> Self {
403 Self {
404 object_type_indication: 0x40, stream_type: 0x05, up_stream: 0,
407 buffer_size_db: 0,
408 max_bitrate: config.bitrate, avg_bitrate: config.bitrate,
410 dec_specific: DecoderSpecificDescriptor::new(config),
411 }
412 }
413}
414
415impl Descriptor for DecoderConfigDescriptor {
416 fn desc_tag() -> u8 {
417 0x04
418 }
419
420 fn desc_size() -> u32 {
421 13 + 1
422 + size_of_length(DecoderSpecificDescriptor::desc_size())
423 + DecoderSpecificDescriptor::desc_size()
424 }
425}
426
427impl<R: Read + Seek> ReadDesc<&mut R> for DecoderConfigDescriptor {
428 fn read_desc(reader: &mut R, size: u32) -> Result<Self> {
429 let start = reader.stream_position()?;
430
431 let object_type_indication = reader.read_u8()?;
432 let byte_a = reader.read_u8()?;
433 let stream_type = (byte_a & 0xFC) >> 2;
434 let up_stream = byte_a & 0x02;
435 let buffer_size_db = reader.read_u24::<BigEndian>()?;
436 let max_bitrate = reader.read_u32::<BigEndian>()?;
437 let avg_bitrate = reader.read_u32::<BigEndian>()?;
438
439 let mut dec_specific = None;
440
441 let mut current = reader.stream_position()?;
442 let end = start + size as u64;
443 while current < end {
444 let (desc_tag, desc_size) = read_desc(reader)?;
445 match desc_tag {
446 0x05 => {
447 dec_specific = Some(DecoderSpecificDescriptor::read_desc(reader, desc_size)?);
448 }
449 _ => {
450 skip_bytes(reader, desc_size as u64)?;
451 }
452 }
453 current = reader.stream_position()?;
454 }
455
456 Ok(DecoderConfigDescriptor {
457 object_type_indication,
458 stream_type,
459 up_stream,
460 buffer_size_db,
461 max_bitrate,
462 avg_bitrate,
463 dec_specific: dec_specific.unwrap_or_default(),
464 })
465 }
466}
467
468impl<W: Write> WriteDesc<&mut W> for DecoderConfigDescriptor {
469 fn write_desc(&self, writer: &mut W) -> Result<u32> {
470 let size = Self::desc_size();
471 write_desc(writer, Self::desc_tag(), size)?;
472
473 writer.write_u8(self.object_type_indication)?;
474 writer.write_u8((self.stream_type << 2) + (self.up_stream & 0x02) + 1)?; writer.write_u24::<BigEndian>(self.buffer_size_db)?;
476 writer.write_u32::<BigEndian>(self.max_bitrate)?;
477 writer.write_u32::<BigEndian>(self.avg_bitrate)?;
478
479 self.dec_specific.write_desc(writer)?;
480
481 Ok(size)
482 }
483}
484
485#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize)]
486pub struct DecoderSpecificDescriptor {
487 pub profile: u8,
488 pub freq_index: u8,
489 pub chan_conf: u8,
490}
491
492impl DecoderSpecificDescriptor {
493 pub fn new(config: &AacConfig) -> Self {
494 Self {
495 profile: config.profile as u8,
496 freq_index: config.freq_index as u8,
497 chan_conf: config.chan_conf as u8,
498 }
499 }
500}
501
502impl Descriptor for DecoderSpecificDescriptor {
503 fn desc_tag() -> u8 {
504 0x05
505 }
506
507 fn desc_size() -> u32 {
508 2
509 }
510}
511
512fn get_audio_object_type(byte_a: u8, byte_b: u8) -> u8 {
513 let mut profile = byte_a >> 3;
514 if profile == 31 {
515 profile = 32 + ((byte_a & 7) | (byte_b >> 5));
516 }
517
518 profile
519}
520
521fn get_chan_conf<R: Read + Seek>(
522 reader: &mut R,
523 byte_b: u8,
524 freq_index: u8,
525 extended_profile: bool,
526) -> Result<u8> {
527 let chan_conf;
528 if freq_index == 15 {
529 let sample_rate = reader.read_u24::<BigEndian>()?;
531 chan_conf = ((sample_rate >> 4) & 0x0F) as u8;
532 } else if extended_profile {
533 let byte_c = reader.read_u8()?;
534 chan_conf = (byte_b & 1) | (byte_c & 0xE0);
535 } else {
536 chan_conf = (byte_b >> 3) & 0x0F;
537 }
538
539 Ok(chan_conf)
540}
541
542impl<R: Read + Seek> ReadDesc<&mut R> for DecoderSpecificDescriptor {
543 fn read_desc(reader: &mut R, _size: u32) -> Result<Self> {
544 let byte_a = reader.read_u8()?;
545 let byte_b = reader.read_u8()?;
546 let profile = get_audio_object_type(byte_a, byte_b);
547 let freq_index;
548 let chan_conf;
549 if profile > 31 {
550 freq_index = (byte_b >> 1) & 0x0F;
551 chan_conf = get_chan_conf(reader, byte_b, freq_index, true)?;
552 } else {
553 freq_index = ((byte_a & 0x07) << 1) + (byte_b >> 7);
554 chan_conf = get_chan_conf(reader, byte_b, freq_index, false)?;
555 }
556
557 Ok(DecoderSpecificDescriptor {
558 profile,
559 freq_index,
560 chan_conf,
561 })
562 }
563}
564
565impl<W: Write> WriteDesc<&mut W> for DecoderSpecificDescriptor {
566 fn write_desc(&self, writer: &mut W) -> Result<u32> {
567 let size = Self::desc_size();
568 write_desc(writer, Self::desc_tag(), size)?;
569
570 writer.write_u8((self.profile << 3) + (self.freq_index >> 1))?;
571 writer.write_u8((self.freq_index << 7) + (self.chan_conf << 3))?;
572
573 Ok(size)
574 }
575}
576
577#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize)]
578pub struct SLConfigDescriptor {}
579
580impl SLConfigDescriptor {
581 pub fn new() -> Self {
582 SLConfigDescriptor {}
583 }
584}
585
586impl Descriptor for SLConfigDescriptor {
587 fn desc_tag() -> u8 {
588 0x06
589 }
590
591 fn desc_size() -> u32 {
592 1
593 }
594}
595
596impl<R: Read + Seek> ReadDesc<&mut R> for SLConfigDescriptor {
597 fn read_desc(reader: &mut R, _size: u32) -> Result<Self> {
598 reader.read_u8()?; Ok(SLConfigDescriptor {})
601 }
602}
603
604impl<W: Write> WriteDesc<&mut W> for SLConfigDescriptor {
605 fn write_desc(&self, writer: &mut W) -> Result<u32> {
606 let size = Self::desc_size();
607 write_desc(writer, Self::desc_tag(), size)?;
608
609 writer.write_u8(2)?; Ok(size)
611 }
612}
613
614#[cfg(test)]
615mod tests {
616 use super::*;
617 use crate::mp4box::BoxHeader;
618 use std::io::Cursor;
619
620 #[test]
621 fn test_mp4a() {
622 let src_box = Mp4aBox {
623 data_reference_index: 1,
624 channelcount: 2,
625 samplesize: 16,
626 samplerate: FixedPointU16::new(48000),
627 esds: Some(EsdsBox {
628 version: 0,
629 flags: 0,
630 es_desc: ESDescriptor {
631 es_id: 2,
632 dec_config: DecoderConfigDescriptor {
633 object_type_indication: 0x40,
634 stream_type: 0x05,
635 up_stream: 0,
636 buffer_size_db: 0,
637 max_bitrate: 67695,
638 avg_bitrate: 67695,
639 dec_specific: DecoderSpecificDescriptor {
640 profile: 2,
641 freq_index: 3,
642 chan_conf: 1,
643 },
644 },
645 sl_config: SLConfigDescriptor::default(),
646 },
647 }),
648 };
649 let mut buf = Vec::new();
650 src_box.write_box(&mut buf).unwrap();
651 assert_eq!(buf.len(), src_box.box_size() as usize);
652
653 let mut reader = Cursor::new(&buf);
654 let header = BoxHeader::read(&mut reader).unwrap();
655 assert_eq!(header.name, BoxType::Mp4aBox);
656 assert_eq!(src_box.box_size(), header.size);
657
658 let dst_box = Mp4aBox::read_box(&mut reader, header.size).unwrap();
659 assert_eq!(src_box, dst_box);
660 }
661
662 #[test]
663 fn test_mp4a_no_esds() {
664 let src_box = Mp4aBox {
665 data_reference_index: 1,
666 channelcount: 2,
667 samplesize: 16,
668 samplerate: FixedPointU16::new(48000),
669 esds: None,
670 };
671 let mut buf = Vec::new();
672 src_box.write_box(&mut buf).unwrap();
673 assert_eq!(buf.len(), src_box.box_size() as usize);
674
675 let mut reader = Cursor::new(&buf);
676 let header = BoxHeader::read(&mut reader).unwrap();
677 assert_eq!(header.name, BoxType::Mp4aBox);
678 assert_eq!(src_box.box_size(), header.size);
679
680 let dst_box = Mp4aBox::read_box(&mut reader, header.size).unwrap();
681 assert_eq!(src_box, dst_box);
682 }
683}