Skip to main content

mp4_atom/moov/trak/mdia/minf/stbl/stsd/
ac3.rs

1use crate::*;
2
3// See ETSI TS 102 366 V1.4.1 (2017-09) for details of AC-3 and EAC-3
4
5#[derive(Debug, Clone, PartialEq, Eq)]
6#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7pub struct Ac3 {
8    pub audio: Audio,
9    pub dac3: Ac3SpecificBox,
10}
11
12impl Atom for Ac3 {
13    const KIND: FourCC = FourCC::new(b"ac-3");
14
15    fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
16        let audio = Audio::decode(buf)?;
17
18        let mut dac3 = None;
19
20        while let Some(atom) = Any::decode_maybe(buf)? {
21            match atom {
22                Any::Ac3SpecificBox(atom) => dac3 = atom.into(),
23                unknown => Self::decode_unknown(&unknown)?,
24            }
25        }
26        skip_trailing_padding(buf);
27
28        Ok(Self {
29            audio,
30            dac3: dac3.ok_or(Error::MissingBox(Ac3SpecificBox::KIND))?,
31        })
32    }
33
34    fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
35        self.audio.encode(buf)?;
36        self.dac3.encode(buf)?;
37        Ok(())
38    }
39}
40
41// AC-3 specific data
42#[derive(Debug, Clone, PartialEq, Eq)]
43#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
44pub struct Ac3SpecificBox {
45    pub fscod: u8,
46    pub bsid: u8,
47    pub bsmod: u8,
48    pub acmod: u8,
49    pub lfeon: bool,
50    pub bit_rate_code: u8,
51}
52
53impl Atom for Ac3SpecificBox {
54    const KIND: FourCC = FourCC::new(b"dac3");
55
56    fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
57        let body_bytes = u24::decode(buf)?;
58        let body: u32 = body_bytes.into();
59        let fscod = ((body >> 22) & 0b11) as u8;
60        let bsid = ((body >> 17) & 0b11111) as u8;
61        let bsmod = ((body >> 14) & 0b111) as u8;
62        let acmod = ((body >> 11) & 0b111) as u8;
63        let lfeon = ((body >> 10) & 0b1) == 0b1;
64        let bit_rate_code = ((body >> 5) & 0b11111) as u8;
65        Ok(Self {
66            fscod,
67            bsid,
68            bsmod,
69            acmod,
70            lfeon,
71            bit_rate_code,
72        })
73    }
74
75    fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
76        let body: u32 = ((self.bit_rate_code as u32) << 5)
77            | ((self.acmod as u32) << 11)
78            | ((self.bsmod as u32) << 14)
79            | ((self.bsid as u32) << 17)
80            | ((self.fscod as u32) << 22)
81            | (if self.lfeon { 0x1u32 << 10 } else { 0u32 });
82        let body_bytes: u24 = body
83            .try_into()
84            .map_err(|_| Error::TooLarge(Ac3SpecificBox::KIND))?;
85        body_bytes.encode(buf)?;
86        Ok(())
87    }
88}
89
90#[cfg(test)]
91mod tests {
92    use super::*;
93
94    // Streaminfo metadata block only
95    const ENCODED_AC3: &[u8] = &[
96        0x00, 0x00, 0x00, 0x2f, 0x61, 0x63, 0x2d, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
97        0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x00,
98        0x00, 0x00, 0xac, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x64, 0x61, 0x63, 0x33, 0x50,
99        0x11, 0x40,
100    ];
101
102    #[test]
103    fn test_ac3_decode() {
104        let buf: &mut std::io::Cursor<&[u8]> = &mut std::io::Cursor::new(ENCODED_AC3);
105
106        let ac3 = Ac3::decode(buf).expect("failed to decode ac-3");
107
108        assert_eq!(
109            ac3,
110            Ac3 {
111                audio: Audio {
112                    data_reference_index: 1,
113                    channel_count: 2,
114                    sample_size: 16,
115                    sample_rate: 44100.into()
116                },
117                dac3: Ac3SpecificBox {
118                    fscod: 1,
119                    bsid: 8,
120                    bsmod: 0,
121                    acmod: 2,
122                    lfeon: false,
123                    bit_rate_code: 10
124                }
125            }
126        );
127    }
128
129    #[test]
130    fn test_ac3_encode() {
131        let ac3 = Ac3 {
132            audio: Audio {
133                data_reference_index: 1,
134                channel_count: 2,
135                sample_size: 16,
136                sample_rate: 44100.into(),
137            },
138            dac3: Ac3SpecificBox {
139                fscod: 1,
140                bsid: 8,
141                bsmod: 0,
142                acmod: 2,
143                lfeon: false,
144                bit_rate_code: 10,
145            },
146        };
147
148        let mut buf = Vec::new();
149        ac3.encode(&mut buf).unwrap();
150
151        assert_eq!(buf.as_slice(), ENCODED_AC3);
152    }
153}