mp4_atom/moov/trak/mdia/minf/stbl/stsd/
ac3.rs1use crate::*;
2
3#[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#[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 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}