pito_codecs/ac3/
header.rs1use super::bits::Bits;
2use super::tables::FRAME_WORDS;
3use crate::media::{Error, Result};
4
5pub const NFCHANS: [usize; 8] = [2, 1, 2, 3, 3, 4, 4, 5];
6
7#[derive(Clone, Copy, Debug, PartialEq, Eq)]
8pub enum Kind {
9 Independent,
10 Dependent,
11 Convert,
12}
13
14#[derive(Clone, Copy, Debug)]
15pub struct Header {
16 pub eac3: bool,
17 pub kind: Kind,
18 pub substream: u8,
19 pub bytes: usize,
20 pub fscod: u8,
21 pub rate: u32,
22 pub blocks: usize,
23 pub acmod: u8,
24 pub nfchans: usize,
25 pub lfeon: bool,
26 pub chanmap: Option<u16>,
27 pub bits: usize,
28}
29
30impl Header {
31 pub fn nchans(&self) -> usize {
32 self.nfchans + self.lfeon as usize
33 }
34}
35
36fn invalid(what: &str) -> Error {
37 Error::Invalid(format!("AC-3 {what}"))
38}
39
40pub fn frame_len(data: &[u8]) -> Option<usize> {
41 if data.len() < 6 || data[0] != 0x0B || data[1] != 0x77 {
42 return None;
43 }
44 let bsid = data[5] >> 3;
45 if bsid <= 10 {
46 let fscod = (data[4] >> 6) as usize;
47 let code = (data[4] & 0x3F) as usize;
48 let words = FRAME_WORDS.get(code)?.get(fscod)?;
49 Some(*words as usize * 2)
50 } else {
51 let frmsiz = (((data[2] & 7) as usize) << 8) | data[3] as usize;
52 Some((frmsiz + 1) * 2)
53 }
54}
55
56pub fn parse(data: &[u8]) -> Result<Header> {
57 if data.len() < 6 {
58 return Err(invalid("frame shorter than its header"));
59 }
60 if data[0] != 0x0B || data[1] != 0x77 {
61 return Err(invalid("frame without a sync word"));
62 }
63 if data[5] >> 3 <= 10 {
64 ac3(data)
65 } else {
66 eac3(data)
67 }
68}
69
70fn ac3(data: &[u8]) -> Result<Header> {
71 let fscod = data[4] >> 6;
72 let code = (data[4] & 0x3F) as usize;
73 let rate = match fscod {
74 0 => 48_000,
75 1 => 44_100,
76 2 => 32_000,
77 _ => return Err(invalid("frame with a reserved sample rate")),
78 };
79 let words = FRAME_WORDS
80 .get(code)
81 .ok_or_else(|| invalid("frame with a reserved frame size"))?[fscod as usize];
82 let mut b = Bits::new(&data[5..]);
83 b.skip(8)?;
84 let acmod = b.read(3)? as u8;
85 if acmod & 1 != 0 && acmod != 1 {
86 b.skip(2)?;
87 }
88 if acmod & 4 != 0 {
89 b.skip(2)?;
90 }
91 if acmod == 2 {
92 b.skip(2)?;
93 }
94 let lfeon = b.flag()?;
95 for _ in 0..if acmod == 0 { 2 } else { 1 } {
96 b.skip(5)?;
97 if b.flag()? {
98 b.skip(8)?;
99 }
100 if b.flag()? {
101 b.skip(8)?;
102 }
103 if b.flag()? {
104 b.skip(7)?;
105 }
106 }
107 b.skip(2)?;
108 if b.flag()? {
109 b.skip(14)?;
110 }
111 if b.flag()? {
112 b.skip(14)?;
113 }
114 if b.flag()? {
115 let n = b.read(6)? as usize + 1;
116 b.skip(n * 8)?;
117 }
118 Ok(Header {
119 eac3: false,
120 kind: Kind::Independent,
121 substream: 0,
122 bytes: words as usize * 2,
123 fscod,
124 rate,
125 blocks: 6,
126 acmod,
127 nfchans: NFCHANS[acmod as usize],
128 lfeon,
129 chanmap: None,
130 bits: 40 + b.pos(),
131 })
132}
133
134fn eac3(data: &[u8]) -> Result<Header> {
135 let mut b = Bits::new(&data[2..]);
136 let kind = match b.read(2)? {
137 0 => Kind::Independent,
138 1 => Kind::Dependent,
139 2 => Kind::Convert,
140 _ => return Err(invalid("E-AC-3 frame with a reserved stream type")),
141 };
142 let substream = b.read(3)? as u8;
143 let bytes = (b.read(11)? as usize + 1) * 2;
144 if bytes < 8 {
145 return Err(invalid("E-AC-3 frame too small"));
146 }
147 let fscod = b.read(2)? as u8;
148 let numblkscod = if fscod == 3 {
149 return Err(Error::Unsupported(
150 "E-AC-3 at a reduced sample rate (16 to 24 kHz)".into(),
151 ));
152 } else {
153 b.read(2)? as u8
154 };
155 let rate = [48_000, 44_100, 32_000][fscod as usize];
156 let blocks = [1, 2, 3, 6][numblkscod as usize];
157 let acmod = b.read(3)? as u8;
158 let lfeon = b.flag()?;
159 let bsid = b.read(5)? as u8;
160 if !(11..=16).contains(&bsid) {
161 return Err(Error::Unsupported(format!("E-AC-3 bitstream id {bsid}")));
162 }
163 for _ in 0..if acmod == 0 { 2 } else { 1 } {
164 b.skip(5)?;
165 if b.flag()? {
166 b.skip(8)?;
167 }
168 }
169 let mut chanmap = None;
170 if kind == Kind::Dependent && b.flag()? {
171 chanmap = Some(b.read(16)? as u16);
172 }
173 if b.flag()? {
174 mixing(&mut b, acmod, lfeon, kind, numblkscod)?;
175 }
176 if b.flag()? {
177 b.skip(5)?;
178 if acmod == 2 {
179 b.skip(4)?;
180 }
181 if acmod >= 6 {
182 b.skip(2)?;
183 }
184 for _ in 0..if acmod == 0 { 2 } else { 1 } {
185 if b.flag()? {
186 b.skip(8)?;
187 }
188 }
189 if fscod < 3 {
190 b.skip(1)?;
191 }
192 }
193 if kind == Kind::Independent && numblkscod != 3 {
194 b.skip(1)?;
195 }
196 if kind == Kind::Convert && (numblkscod == 3 || b.flag()?) {
197 b.skip(6)?;
198 }
199 if b.flag()? {
200 let n = b.read(6)? as usize + 1;
201 b.skip(n * 8)?;
202 }
203 Ok(Header {
204 eac3: true,
205 kind,
206 substream,
207 bytes,
208 fscod,
209 rate,
210 blocks,
211 acmod,
212 nfchans: NFCHANS[acmod as usize],
213 lfeon,
214 chanmap,
215 bits: 16 + b.pos(),
216 })
217}
218
219fn mixing(b: &mut Bits, acmod: u8, lfeon: bool, kind: Kind, numblkscod: u8) -> Result<()> {
220 if acmod > 2 {
221 b.skip(2)?;
222 }
223 if acmod & 1 != 0 && acmod > 2 {
224 b.skip(6)?;
225 }
226 if acmod & 4 != 0 {
227 b.skip(6)?;
228 }
229 if lfeon && b.flag()? {
230 b.skip(5)?;
231 }
232 if kind != Kind::Independent {
233 return Ok(());
234 }
235 if b.flag()? {
236 b.skip(6)?;
237 }
238 if acmod == 0 && b.flag()? {
239 b.skip(6)?;
240 }
241 if b.flag()? {
242 b.skip(6)?;
243 }
244 match b.read(2)? {
245 1 => b.skip(5)?,
246 2 => b.skip(12)?,
247 3 => {
248 let len = b.read(5)? as usize;
249 b.skip(8 * (len + 2) - 5)?;
250 }
251 _ => {}
252 }
253 if acmod < 2 {
254 if b.flag()? {
255 b.skip(14)?;
256 }
257 if acmod == 0 && b.flag()? {
258 b.skip(14)?;
259 }
260 }
261 if b.flag()? {
262 if numblkscod == 0 {
263 b.skip(5)?;
264 } else {
265 for _ in 0..[1, 2, 3, 6][numblkscod as usize] {
266 if b.flag()? {
267 b.skip(5)?;
268 }
269 }
270 }
271 }
272 Ok(())
273}