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