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 _ => 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#[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 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}