zvidlib_vorbis_syntax/
lib.rs1#[allow(unused_imports)]
16use zvidlib_core::*;
17
18use crate::{EncodedAudioSample, Error, ErrorKind, Result, SampleRange};
19
20pub const VORBIS_PREROLL_PACKETS: usize = 1;
25
26#[derive(Clone, Debug, Eq, PartialEq)]
28pub struct VorbisConfig {
29 pub channels: u8,
30 pub sample_rate: u32,
31 pub bitrate_maximum: i32,
34 pub bitrate_nominal: i32,
35 pub bitrate_minimum: i32,
36 pub block_sizes: (u16, u16),
38 pub identification_header: Vec<u8>,
39 pub comment_header: Vec<u8>,
40 pub setup_header: Vec<u8>,
41 mode_block_flags: Vec<bool>,
43}
44
45impl VorbisConfig {
46 pub fn from_headers(
48 identification_header: Vec<u8>,
49 comment_header: Vec<u8>,
50 setup_header: Vec<u8>,
51 ) -> Result<Self> {
52 let ident = &identification_header;
53 if ident.len() != 30 || ident[0] != 1 || &ident[1..7] != b"vorbis" {
54 return Err(malformed(
55 "Vorbis identification header is not a 30-byte type 1 packet",
56 ));
57 }
58 if u32::from_le_bytes(ident[7..11].try_into().expect("fixed")) != 0 {
59 return Err(unsupported("only Vorbis I streams are supported"));
60 }
61 let channels = ident[11];
62 let sample_rate = u32::from_le_bytes(ident[12..16].try_into().expect("fixed"));
63 let bitrate = |at: usize| i32::from_le_bytes(ident[at..at + 4].try_into().expect("fixed"));
64 let short_exponent = ident[28] & 0x0f;
65 let long_exponent = ident[28] >> 4;
66 if channels == 0 || sample_rate == 0 {
67 return Err(malformed(
68 "Vorbis identification header has no channels or sample rate",
69 ));
70 }
71 if !(6..=13).contains(&short_exponent)
72 || !(6..=13).contains(&long_exponent)
73 || short_exponent > long_exponent
74 {
75 return Err(malformed(
76 "Vorbis identification header has invalid block sizes",
77 ));
78 }
79 if ident[29] & 1 == 0 {
80 return Err(malformed(
81 "Vorbis identification header framing bit is unset",
82 ));
83 }
84 if comment_header.len() < 7 || comment_header[0] != 3 || &comment_header[1..7] != b"vorbis"
85 {
86 return Err(malformed("Vorbis comment header is not a type 3 packet"));
87 }
88 let mode_block_flags = parse_setup_modes(&setup_header, channels)?;
89 Ok(Self {
90 channels,
91 sample_rate,
92 bitrate_maximum: bitrate(16),
93 bitrate_nominal: bitrate(20),
94 bitrate_minimum: bitrate(24),
95 block_sizes: (1 << short_exponent, 1 << long_exponent),
96 identification_header,
97 comment_header,
98 setup_header,
99 mode_block_flags,
100 })
101 }
102
103 pub fn from_codec_private(codec_private: &[u8]) -> Result<Self> {
108 let (&count, mut rest) = codec_private
109 .split_first()
110 .ok_or_else(|| malformed("Vorbis CodecPrivate is empty"))?;
111 if count != 2 {
112 return Err(malformed(
113 "Vorbis CodecPrivate must lace three header packets",
114 ));
115 }
116 let mut sizes = [0_usize; 2];
117 for size in &mut sizes {
118 loop {
119 let (&byte, tail) = rest
120 .split_first()
121 .ok_or_else(|| malformed("Vorbis CodecPrivate lacing is truncated"))?;
122 rest = tail;
123 *size += usize::from(byte);
124 if byte != 255 {
125 break;
126 }
127 }
128 }
129 if sizes[0] + sizes[1] > rest.len() {
130 return Err(malformed("Vorbis CodecPrivate is shorter than its lacing"));
131 }
132 let (identification, rest) = rest.split_at(sizes[0]);
133 let (comment, setup) = rest.split_at(sizes[1]);
134 Self::from_headers(identification.to_vec(), comment.to_vec(), setup.to_vec())
135 }
136
137 pub fn to_codec_private(&self) -> Vec<u8> {
140 let mut out = vec![2];
141 for size in [self.identification_header.len(), self.comment_header.len()] {
142 out.extend(std::iter::repeat_n(255, size / 255));
143 out.push((size % 255) as u8);
144 }
145 out.extend_from_slice(&self.identification_header);
146 out.extend_from_slice(&self.comment_header);
147 out.extend_from_slice(&self.setup_header);
148 out
149 }
150
151 pub fn packet_block_size(&self, packet: &[u8]) -> Result<u16> {
153 let mut bits = BitReader::new(packet);
154 if bits.read(1)? != 0 {
155 return Err(malformed("Vorbis audio packet has a header packet type"));
156 }
157 let mode_bits = ilog(self.mode_block_flags.len() as u32 - 1);
158 let mode = usize::try_from(bits.read(mode_bits)?).expect("at most eight bits");
159 let long = *self
160 .mode_block_flags
161 .get(mode)
162 .ok_or_else(|| malformed("Vorbis audio packet names an undefined mode"))?;
163 Ok(if long {
164 self.block_sizes.1
165 } else {
166 self.block_sizes.0
167 })
168 }
169
170 pub fn encoded_samples(&self, packets: Vec<Vec<u8>>) -> Result<Vec<EncodedAudioSample>> {
174 let mut previous = None;
175 let mut end = 0_u64;
176 packets
177 .into_iter()
178 .map(|data| {
179 let block = self.packet_block_size(&data)?;
180 let length = previous.map_or(0, |previous: u16| {
181 (u64::from(previous) + u64::from(block)) / 4
182 });
183 previous = Some(block);
184 let start = end;
185 end += length;
186 Ok(EncodedAudioSample {
187 decoded_range: SampleRange::new(start, end)?,
188 data,
189 })
190 })
191 .collect()
192 }
193}
194
195fn parse_setup_modes(setup: &[u8], channels: u8) -> Result<Vec<bool>> {
198 if setup.len() < 7 || setup[0] != 5 || &setup[1..7] != b"vorbis" {
199 return Err(malformed("Vorbis setup header is not a type 5 packet"));
200 }
201 let mut bits = BitReader::new(&setup[7..]);
202 let codebooks = bits.read(8)? + 1;
203 for _ in 0..codebooks {
204 skip_codebook(&mut bits)?;
205 }
206 let time_domain_transforms = bits.read(6)? + 1;
207 for _ in 0..time_domain_transforms {
208 if bits.read(16)? != 0 {
209 return Err(malformed(
210 "Vorbis setup header has a nonzero time domain type",
211 ));
212 }
213 }
214 let floors = bits.read(6)? + 1;
215 for _ in 0..floors {
216 skip_floor(&mut bits)?;
217 }
218 let residues = bits.read(6)? + 1;
219 for _ in 0..residues {
220 skip_residue(&mut bits)?;
221 }
222 let mappings = bits.read(6)? + 1;
223 for _ in 0..mappings {
224 skip_mapping(&mut bits, channels)?;
225 }
226 let modes = bits.read(6)? + 1;
227 let mut block_flags = Vec::with_capacity(modes as usize);
228 for _ in 0..modes {
229 block_flags.push(bits.read(1)? == 1);
230 if bits.read(16)? != 0 || bits.read(16)? != 0 {
231 return Err(malformed(
232 "Vorbis setup header mode has a nonzero window or transform type",
233 ));
234 }
235 if bits.read(8)? >= mappings {
236 return Err(malformed(
237 "Vorbis setup header mode names an undefined mapping",
238 ));
239 }
240 }
241 if bits.read(1)? != 1 {
242 return Err(malformed("Vorbis setup header framing bit is unset"));
243 }
244 Ok(block_flags)
245}
246
247fn skip_codebook(bits: &mut BitReader<'_>) -> Result<()> {
248 if bits.read(24)? != 0x56_4342 {
249 return Err(malformed("Vorbis codebook has an invalid sync pattern"));
250 }
251 let dimensions = bits.read(16)?;
252 let entries = bits.read(24)?;
253 if bits.read(1)? == 1 {
254 let mut current = 0;
256 bits.read(5)?;
257 while current < entries {
258 current += bits.read(ilog(entries - current))?;
259 }
260 if current > entries {
261 return Err(malformed(
262 "Vorbis codebook length runs overflow its entries",
263 ));
264 }
265 } else {
266 let sparse = bits.read(1)? == 1;
267 for _ in 0..entries {
268 if !sparse || bits.read(1)? == 1 {
269 bits.read(5)?;
270 }
271 }
272 }
273 match bits.read(4)? {
274 0 => {}
275 lookup_type @ (1 | 2) => {
276 bits.read(32)?;
277 bits.read(32)?;
278 let value_bits = bits.read(4)? + 1;
279 bits.read(1)?;
280 let values = if lookup_type == 1 {
281 lookup1_values(entries, dimensions)
282 } else {
283 u64::from(entries) * u64::from(dimensions)
284 };
285 bits.skip(values * u64::from(value_bits))?;
286 }
287 _ => return Err(malformed("Vorbis codebook has an invalid lookup type")),
288 }
289 Ok(())
290}
291
292fn skip_floor(bits: &mut BitReader<'_>) -> Result<()> {
293 match bits.read(16)? {
294 0 => {
295 bits.read(8 + 16 + 16 + 6 + 8)?;
296 let books = bits.read(4)? + 1;
297 bits.skip(u64::from(books) * 8)?;
298 }
299 1 => {
300 let partitions = bits.read(5)?;
301 let mut classes = Vec::with_capacity(partitions as usize);
302 for _ in 0..partitions {
303 classes.push(bits.read(4)?);
304 }
305 let class_count = classes.iter().max().map_or(0, |&max| max + 1);
306 let mut dimensions = Vec::with_capacity(class_count as usize);
307 for _ in 0..class_count {
308 dimensions.push(bits.read(3)? + 1);
309 let subclasses = bits.read(2)?;
310 if subclasses != 0 {
311 bits.read(8)?;
312 }
313 bits.skip((1_u64 << subclasses) * 8)?;
314 }
315 bits.read(2)?;
316 let range_bits = bits.read(4)?;
317 for class in classes {
318 bits.skip(u64::from(dimensions[class as usize]) * u64::from(range_bits))?;
319 }
320 }
321 _ => return Err(malformed("Vorbis setup header has an invalid floor type")),
322 }
323 Ok(())
324}
325
326fn skip_residue(bits: &mut BitReader<'_>) -> Result<()> {
327 if bits.read(16)? > 2 {
328 return Err(malformed("Vorbis setup header has an invalid residue type"));
329 }
330 bits.read(24)?;
331 bits.read(24)?;
332 bits.read(24)?;
333 let classifications = bits.read(6)? + 1;
334 bits.read(8)?;
335 let mut books = 0;
336 for _ in 0..classifications {
337 let low = bits.read(3)?;
338 let high = if bits.read(1)? == 1 { bits.read(5)? } else { 0 };
339 books += (high << 3 | low).count_ones();
340 }
341 bits.skip(u64::from(books) * 8)
342}
343
344fn skip_mapping(bits: &mut BitReader<'_>, channels: u8) -> Result<()> {
345 if bits.read(16)? != 0 {
346 return Err(malformed("Vorbis setup header has an invalid mapping type"));
347 }
348 let submaps = if bits.read(1)? == 1 {
349 bits.read(4)? + 1
350 } else {
351 1
352 };
353 let channel_bits = ilog(u32::from(channels) - 1);
354 if bits.read(1)? == 1 {
355 let steps = bits.read(8)? + 1;
356 bits.skip(u64::from(steps) * 2 * u64::from(channel_bits))?;
357 }
358 if bits.read(2)? != 0 {
359 return Err(malformed(
360 "Vorbis setup header mapping reserved bits are set",
361 ));
362 }
363 if submaps > 1 {
364 bits.skip(u64::from(channels) * 4)?;
365 }
366 bits.skip(u64::from(submaps) * 24)
367}
368
369fn ilog(value: u32) -> u32 {
371 u32::BITS - value.leading_zeros()
372}
373
374fn lookup1_values(entries: u32, dimensions: u32) -> u64 {
377 if dimensions == 0 {
378 return 0;
379 }
380 let mut value = (f64::from(entries))
381 .powf(1.0 / f64::from(dimensions))
382 .floor() as u64;
383 while (value + 1)
384 .checked_pow(dimensions)
385 .is_some_and(|power| power <= u64::from(entries))
386 {
387 value += 1;
388 }
389 while value > 0
390 && value
391 .checked_pow(dimensions)
392 .is_none_or(|power| power > u64::from(entries))
393 {
394 value -= 1;
395 }
396 value
397}
398
399struct BitReader<'a> {
401 bytes: &'a [u8],
402 position: u64,
403}
404
405impl<'a> BitReader<'a> {
406 fn new(bytes: &'a [u8]) -> Self {
407 Self { bytes, position: 0 }
408 }
409
410 fn read(&mut self, count: u32) -> Result<u32> {
411 debug_assert!(count <= 32);
412 let end = self.position + u64::from(count);
413 if end > self.bytes.len() as u64 * 8 {
414 return Err(malformed("Vorbis packet is truncated"));
415 }
416 let mut value = 0_u64;
417 for bit in 0..u64::from(count) {
418 let at = self.position + bit;
419 let byte = self.bytes[(at / 8) as usize];
420 value |= u64::from((byte >> (at % 8)) & 1) << bit;
421 }
422 self.position = end;
423 Ok(value as u32)
424 }
425
426 fn skip(&mut self, count: u64) -> Result<()> {
427 let end = self
428 .position
429 .checked_add(count)
430 .filter(|&end| end <= self.bytes.len() as u64 * 8)
431 .ok_or_else(|| malformed("Vorbis packet is truncated"))?;
432 self.position = end;
433 Ok(())
434 }
435}
436
437fn malformed(message: impl Into<String>) -> Error {
438 Error::new(ErrorKind::MalformedMedia, message)
439}
440
441fn unsupported(message: impl Into<String>) -> Error {
442 Error::new(ErrorKind::Unsupported, message)
443}