flowly_mp4/mp4box/
mp4a.rs

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