1use core::num::NonZeroUsize;
8use nom::{bytes::complete::tag, error::ErrorKind, number, Parser};
9
10#[derive(Debug, PartialEq)]
12#[doc(hidden)]
13#[non_exhaustive]
14pub enum ErrorValues {
15 ZeroStreamCount,
16 BadNumberOfChannels(u8, u8),
17 InvalidChannelIndex(u8),
18 TotalStreamCountExceeds(u16),
19 StreamCountsMismatch(u8, u8),
20 BadTableLength(usize, u8),
21 TableTooBig(usize, u8),
22}
23
24#[derive(Debug, PartialEq)]
26pub enum OpusError {
27 ParsingError(ErrorKind),
29 EndOfStreamError(Option<NonZeroUsize>),
31 InvalidStream(ErrorValues),
33 UnsupportedStream(&'static str),
35 NotOpusStream,
37}
38
39impl core::fmt::Display for OpusError {
40 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
41 use OpusError::*;
42 match self {
43 ParsingError(kind) => f.write_fmt(format_args!(
44 "parsing error with Opus: {}",
45 kind.description()
46 ))?,
47 EndOfStreamError(Some(size)) => f.write_fmt(format_args!(
48 "Opus stream ended abruptly with {} more bytes needed",
49 size
50 ))?,
51 EndOfStreamError(None) => f.write_fmt(format_args!("Opus stream ended abruptly"))?,
52 InvalidStream(issue) => match issue {
53 ErrorValues::ZeroStreamCount => {
54 f.write_str("stream count cannot be 0")?
55 }
56 ErrorValues::BadNumberOfChannels(family, channels) => f.write_fmt(format_args!(
57 "bad number of channels for family {}: {}",
58 family, channels
59 ))?,
60 ErrorValues::InvalidChannelIndex(index) => f.write_fmt(format_args!(
61 "invalid channel index in channel mapping table: {}",
62 index
63 ))?,
64 ErrorValues::TotalStreamCountExceeds(total) => f.write_fmt(format_args!(
65 "total stream count cannot be more than 255: {}",
66 total
67 ))?,
68 ErrorValues::StreamCountsMismatch(coupled_count, stream_count) => f.write_fmt(format_args!(
69 "coupled stream count ({}) cannot be larger than stream count ({})",
70 coupled_count, stream_count
71 ))?,
72 ErrorValues::BadTableLength(length, channels) => f.write_fmt(format_args!(
73 "channel mapping table length does not match the number of channels ({}): {}",
74 channels, length
75 ))?,
76 ErrorValues::TableTooBig(length, max_size) => f.write_fmt(format_args!(
77 "channel mapping table does not fit to reserved space ({}), it is {} bytes long",
78 max_size, length,
79 ))?,
80 },
81 UnsupportedStream(issue) => {
82 f.write_fmt(format_args!("unsupported stream: {}", issue))?
83 }
84 NotOpusStream => f.write_str("this is not an Opus stream")?,
85 };
86 Ok(())
87 }
88}
89
90impl core::error::Error for OpusError {
91 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
92 None
93 }
94}
95
96impl<'data> From<nom::Err<(&'data [u8], ErrorKind)>> for OpusError {
97 fn from(error: nom::Err<(&'data [u8], ErrorKind)>) -> OpusError {
98 use OpusError::*;
99 match error {
100 nom::Err::Failure((_, kind)) => ParsingError(kind),
101 nom::Err::Error((_, kind)) => ParsingError(kind),
102 nom::Err::Incomplete(nom::Needed::Size(size)) => EndOfStreamError(Some(size)),
103 nom::Err::Incomplete(nom::Needed::Unknown) => EndOfStreamError(None),
104 }
105 }
106}
107
108pub type Result<'data, O> = core::result::Result<O, OpusError>;
110
111#[derive(Debug, PartialEq)]
113#[non_exhaustive]
114pub enum ChannelMapping {
115 Family0 {
121 channels: u8,
123 },
124 Family1 {
130 channels: u8,
132 table: ChannelMappingTable<8>,
134 },
135 #[cfg(feature = "family255")]
136 Family255 {
144 channels: u8,
146 table: ChannelMappingTable<255>,
148 },
149 #[cfg(feature = "family255")]
150 Reserved {
158 channels: u8,
160 table: ChannelMappingTable<255>,
162 },
163}
164
165impl ChannelMapping {
166 pub fn get_channel_count(&self) -> u8 {
168 use ChannelMapping::*;
169 match self {
170 Family0 { channels } => *channels,
171 Family1 { channels, .. } => *channels,
172 #[cfg(feature = "family255")]
173 Family255 { channels, .. } => *channels,
174 #[cfg(feature = "family255")]
175 Reserved { channels, .. } => *channels,
176 }
177 }
178
179 pub fn get_stream_count(&self) -> u8 {
181 use ChannelMapping::*;
182 match self {
183 Family0 { .. } => 1,
184 Family1 { table, .. } => table.stream_count,
185 #[cfg(feature = "family255")]
186 Family255 { table, .. } => table.stream_count,
187 #[cfg(feature = "family255")]
188 Reserved { table, .. } => table.stream_count,
189 }
190 }
191
192 pub fn get_coupled_stream_count(&self) -> u8 {
194 use ChannelMapping::*;
195 match self {
196 Family0 { channels } => *channels - 1,
197 Family1 { table, .. } => table.coupled_count,
198 #[cfg(feature = "family255")]
199 Family255 { table, .. } => table.coupled_count,
200 #[cfg(feature = "family255")]
201 Reserved { table, .. } => table.coupled_count,
202 }
203 }
204
205 pub fn get_mapping(&self, channel: u8) -> Option<Mapping> {
211 use ChannelMapping::*;
212 let (speaker_location, index, coupled_count) = match self {
213 Family0 { channels } => {
214 let speaker_location = match (*channels, channel) {
215 (1, 0) => SpeakerLocation::Mono,
216 (2, 0) => SpeakerLocation::Left,
217 (2, 1) => SpeakerLocation::Right,
218 _ => return None,
219 };
220 Some((Some(speaker_location), channel, *channels - 1))
221 }
222 Family1 { channels, table } => {
223 let speaker_location = match (*channels, channel) {
224 (1, 0) => SpeakerLocation::Mono,
225 (2..=8, 0) => SpeakerLocation::Left,
226 (2, 1) | (3, 2) | (4, 1) | (5..=8, 2) => SpeakerLocation::Right,
227 (3, 1) | (5..=8, 1) => SpeakerLocation::Center,
228 (4, 2) | (5..=6, 3) | (8, 5) => SpeakerLocation::RearLeft,
229 (4, 3) | (5..=6, 4) | (8, 6) => SpeakerLocation::RearRight,
230 (6, 5) | (7, 6) | (8, 7) => SpeakerLocation::LFE,
231 (7..=8, 3) => SpeakerLocation::SideLeft,
232 (7..=8, 4) => SpeakerLocation::SideRight,
233 (7, 5) => SpeakerLocation::RearCenter,
234 _ => return None,
235 };
236 let ChannelMappingTable {
237 coupled_count,
238 mapping,
239 ..
240 } = &table;
241 let index = mapping[usize::from(channel)];
242 Some((Some(speaker_location), index, *coupled_count))
243 }
244 #[cfg(feature = "family255")]
245 Family255 { channels, table } | Reserved { channels, table } => {
246 if channel >= *channels {
247 None
248 } else {
249 let ChannelMappingTable {
250 coupled_count,
251 mapping,
252 ..
253 } = &table;
254 let index = mapping[usize::from(channel)];
255 Some((None, index, *coupled_count))
256 }
257 }
258 }?;
259 if index == 255 {
260 Some(Mapping {
261 stream: None,
262 speaker_location,
263 })
264 } else {
265 let stream = if index < 2 * coupled_count {
266 if index % 2 == 0 {
267 (index / 2, DecodedChannel::Left)
268 } else {
269 (index / 2, DecodedChannel::Right)
270 }
271 } else {
272 (index - coupled_count, DecodedChannel::Mono)
273 };
274 let stream = Some(stream);
275 Some(Mapping {
276 stream,
277 speaker_location,
278 })
279 }
280 }
281}
282
283#[derive(Clone, Copy, Debug, PartialEq)]
285#[non_exhaustive]
286pub enum SpeakerLocation {
287 Mono,
289 Left,
291 Right,
293 Center,
295 RearLeft,
297 RearRight,
299 RearCenter,
301 SideLeft,
303 SideRight,
305 LFE,
307}
308
309#[derive(Clone, Copy, Debug, PartialEq)]
311pub enum DecodedChannel {
312 Mono,
314 Left,
316 Right,
318}
319
320#[derive(Debug, PartialEq)]
322pub struct Mapping {
323 pub stream: Option<(u8, DecodedChannel)>,
325 pub speaker_location: Option<SpeakerLocation>,
327}
328
329#[derive(Debug, PartialEq)]
331pub struct ChannelMappingTable<const MAX_CHANNELS: usize> {
332 stream_count: u8,
334 coupled_count: u8,
336 mapping: [u8; MAX_CHANNELS],
338}
339
340impl<const MAX_CHANNELS: usize> ChannelMappingTable<MAX_CHANNELS> {
341 fn parse(input: &[u8], channels: u8) -> Result<ChannelMappingTable<MAX_CHANNELS>> {
342 use OpusError::*;
343 let (input, stream_count) = number::u8().parse(input)?;
344 let (input, coupled_count) = number::u8().parse(input)?;
345 let total_stream_count = stream_count.checked_add(coupled_count).ok_or_else(|| {
346 let total = stream_count as u16 + coupled_count as u16;
347 InvalidStream(ErrorValues::TotalStreamCountExceeds(total))
348 })?;
349 if stream_count == 0 {
350 Err(InvalidStream(ErrorValues::ZeroStreamCount))
351 } else if coupled_count > stream_count {
352 Err(InvalidStream(ErrorValues::StreamCountsMismatch(
353 coupled_count,
354 stream_count,
355 )))
356 } else if input.len() != channels.into() {
357 Err(InvalidStream(ErrorValues::BadTableLength(
358 input.len(),
359 channels,
360 )))
361 } else if input.len() > MAX_CHANNELS {
362 Err(InvalidStream(ErrorValues::TableTooBig(
363 input.len(),
364 MAX_CHANNELS as u8, )))
366 } else {
367 let mut mapping = [0; MAX_CHANNELS];
368 for (i, &v) in input.iter().enumerate() {
369 if v >= total_stream_count && v != 255 {
370 return Err(InvalidStream(ErrorValues::InvalidChannelIndex(v)));
371 }
372 mapping[i] = v;
373 }
374 Ok(ChannelMappingTable {
375 stream_count,
376 coupled_count,
377 mapping,
378 })
379 }
380 }
381}
382
383#[derive(Debug, PartialEq)]
385pub struct OpusHeader {
386 pub version: u8,
388 pub channels: ChannelMapping,
390 pub pre_skip: u16,
392 pub sample_rate: u32,
394 pub output_gain: u16,
396}
397
398impl OpusHeader {
399 pub fn parse(input: &[u8]) -> Result<Self> {
406 use OpusError::*;
407 let (input, _) = tag(b"OpusHead".as_slice())(input)
408 .map_err(|_: nom::Err<(&[u8], ErrorKind)>| NotOpusStream)?;
409 let (input, version) = number::u8().parse(input)?;
410 let (input, channels) = number::u8().parse(input)?;
411 let (input, pre_skip) = number::le_u16().parse(input)?;
412 let (input, sample_rate) = number::le_u32().parse(input)?;
413 let (input, output_gain) = number::le_u16().parse(input)?;
414 let (channel_mapping_table, channel_mapping_family) = number::u8().parse(input)?;
415 let channels = match channel_mapping_family {
416 0 => match channels {
417 1..=2 => ChannelMapping::Family0 { channels },
418 _ => return Err(InvalidStream(ErrorValues::BadNumberOfChannels(0, channels))),
419 },
420 1 => match channels {
421 1..=8 => ChannelMapping::Family1 {
422 channels,
423 table: ChannelMappingTable::parse(channel_mapping_table, channels)?,
424 },
425 _ => return Err(InvalidStream(ErrorValues::BadNumberOfChannels(1, channels))),
426 },
427 #[cfg(feature = "family255")]
428 255 => ChannelMapping::Family255 {
429 channels,
430 table: ChannelMappingTable::parse(channel_mapping_table, channels)?,
431 },
432 #[cfg(feature = "family255")]
433 _ => ChannelMapping::Reserved {
434 channels,
435 table: ChannelMappingTable::parse(channel_mapping_table, channels)?,
436 },
437 #[cfg(not(feature = "family255"))]
438 _ => {
439 return Err(UnsupportedStream(
440 "family 255 channel mapping is not supported",
441 ))
442 }
443 };
444 Ok(Self {
445 version,
446 channels,
447 pre_skip,
448 sample_rate,
449 output_gain,
450 })
451 }
452}
453
454#[cfg(test)]
455mod test {
456 use super::*;
457 use core::error::Error;
458
459 #[test]
460 fn parse_header() {
461 let data = include_bytes!("test/opus.data");
462 let header = OpusHeader::parse(data).unwrap();
463 assert_eq!(header.version, 1);
464 if let ChannelMapping::Family0 { channels } = header.channels {
465 assert_eq!(channels, 1);
466 } else {
467 panic!("Channel mapping family must be 0");
468 }
469 assert_eq!(header.pre_skip, 312);
470 assert_eq!(header.sample_rate, 8_000);
471 assert_eq!(header.output_gain, 0);
472 }
473
474 #[test]
475 fn family_0_mono() {
476 let channels = ChannelMapping::Family0 { channels: 1 };
477 assert_eq!(channels.get_channel_count(), 1);
478 assert_eq!(channels.get_stream_count(), 1);
479 assert_eq!(channels.get_coupled_stream_count(), 0);
480 let mapping = channels.get_mapping(0).unwrap();
481 assert_eq!(mapping.stream, Some((0, DecodedChannel::Mono)));
482 assert_eq!(mapping.speaker_location, Some(SpeakerLocation::Mono));
483 for index in 1..=255 {
484 assert_eq!(channels.get_mapping(index), None);
485 }
486 }
487
488 #[test]
489 fn family_0_stereo() {
490 let channels = ChannelMapping::Family0 { channels: 2 };
491 assert_eq!(channels.get_channel_count(), 2);
492 assert_eq!(channels.get_stream_count(), 1);
493 assert_eq!(channels.get_coupled_stream_count(), 1);
494 let mapping = channels.get_mapping(0).unwrap();
495 assert_eq!(mapping.stream, Some((0, DecodedChannel::Left)));
496 assert_eq!(mapping.speaker_location, Some(SpeakerLocation::Left));
497 let mapping = channels.get_mapping(1).unwrap();
498 assert_eq!(mapping.stream, Some((0, DecodedChannel::Right)));
499 assert_eq!(mapping.speaker_location, Some(SpeakerLocation::Right));
500 for index in 2..=255 {
501 assert_eq!(channels.get_mapping(index), None);
502 }
503 }
504
505 #[test]
506 fn family_1_stereo() {
507 let channels = ChannelMapping::Family1 {
508 channels: 2,
509 table: ChannelMappingTable::parse(&[1, 1, 0, 1], 2).unwrap(),
510 };
511 assert_eq!(channels.get_channel_count(), 2);
512 assert_eq!(channels.get_stream_count(), 1);
513 assert_eq!(channels.get_coupled_stream_count(), 1);
514 let mapping = channels.get_mapping(0).unwrap();
515 assert_eq!(mapping.stream, Some((0, DecodedChannel::Left)));
516 assert_eq!(mapping.speaker_location, Some(SpeakerLocation::Left));
517 let mapping = channels.get_mapping(1).unwrap();
518 assert_eq!(mapping.stream, Some((0, DecodedChannel::Right)));
519 assert_eq!(mapping.speaker_location, Some(SpeakerLocation::Right));
520 for index in 2..=255 {
521 assert_eq!(channels.get_mapping(index), None);
522 }
523 }
524
525 #[test]
526 fn family_1_surround_5_1() {
527 let data: [u8; 0x08] = [0x04, 0x02, 0x00, 0x04, 0x01, 0x02, 0x03, 0x05];
528 let channels = ChannelMapping::Family1 {
529 channels: 6,
530 table: ChannelMappingTable::parse(&data, 6).unwrap(),
531 };
532 assert_eq!(channels.get_channel_count(), 6);
533 assert_eq!(channels.get_stream_count(), 4);
534 assert_eq!(channels.get_coupled_stream_count(), 2);
535 let mappings = [
536 (0, DecodedChannel::Left, SpeakerLocation::Left),
537 (2, DecodedChannel::Mono, SpeakerLocation::Center),
538 (0, DecodedChannel::Right, SpeakerLocation::Right),
539 (1, DecodedChannel::Left, SpeakerLocation::RearLeft),
540 (1, DecodedChannel::Right, SpeakerLocation::RearRight),
541 (3, DecodedChannel::Mono, SpeakerLocation::LFE),
542 ];
543 for (index, (stream, channel, location)) in mappings.iter().enumerate() {
544 let mapping = channels.get_mapping(index as u8).unwrap();
545 assert_eq!(mapping.stream, Some((*stream, *channel)));
546 assert_eq!(mapping.speaker_location, Some(*location));
547 }
548 for index in 6..=255 {
549 assert_eq!(channels.get_mapping(index), None);
550 }
551 }
552
553 #[test]
554 #[cfg(feature = "family255")]
555 fn family_255() {
556 let data: [u8; 0x08] = [0x04, 0x02, 0x00, 0x04, 0x01, 0x02, 0x03, 0x05];
557 let channels = ChannelMapping::Family255 {
558 channels: 6,
559 table: ChannelMappingTable::parse(&data, 6).unwrap(),
560 };
561 assert_eq!(channels.get_channel_count(), 6);
562 assert_eq!(channels.get_stream_count(), 4);
563 assert_eq!(channels.get_coupled_stream_count(), 2);
564 let mappings = [
565 (0, DecodedChannel::Left),
566 (2, DecodedChannel::Mono),
567 (0, DecodedChannel::Right),
568 (1, DecodedChannel::Left),
569 (1, DecodedChannel::Right),
570 (3, DecodedChannel::Mono),
571 ];
572 for (index, (stream, channel)) in mappings.iter().enumerate() {
573 let mapping = channels.get_mapping(index as u8).unwrap();
574 assert_eq!(mapping.stream, Some((*stream, *channel)));
575 assert_eq!(mapping.speaker_location, None);
576 }
577 for index in 6..=255 {
578 assert_eq!(channels.get_mapping(index), None);
579 }
580 }
581
582 #[test]
583 #[cfg(feature = "family255")]
584 fn family_reserved() {
585 let data: [u8; 0x06] = [0x02, 0x01, 0x01, 0x00, 0x02, 0xFF];
586 let channels = ChannelMapping::Reserved {
587 channels: 4,
588 table: ChannelMappingTable::parse(&data, 4).unwrap(),
589 };
590 assert_eq!(channels.get_channel_count(), 4);
591 assert_eq!(channels.get_stream_count(), 2);
592 assert_eq!(channels.get_coupled_stream_count(), 1);
593 let mappings = [
594 Some((0, DecodedChannel::Right)),
595 Some((0, DecodedChannel::Left)),
596 Some((1, DecodedChannel::Mono)),
597 None,
598 ];
599 for (index, stream) in mappings.iter().enumerate() {
600 let mapping = channels.get_mapping(index as u8).unwrap();
601 assert_eq!(mapping.stream, *stream);
602 assert_eq!(mapping.speaker_location, None);
603 }
604 for index in 4..=255 {
605 assert_eq!(channels.get_mapping(index), None);
606 }
607 }
608
609 #[test]
610 fn invalid_stream_count() {
611 let data: [u8; 0x08] = [0x04, 0x05, 0x00, 0x04, 0x01, 0x02, 0x03, 0x05];
612 let result = ChannelMappingTable::<255>::parse(&data, 6);
613 assert_eq!(
614 result,
615 Err(OpusError::InvalidStream(ErrorValues::StreamCountsMismatch(
616 5, 4
617 )))
618 );
619 assert_eq!(
620 result.unwrap_err().to_string(),
621 "coupled stream count (5) cannot be larger than stream count (4)"
622 );
623 }
624
625 #[test]
626 fn zero_stream_count() {
627 let data: [u8; 0x08] = [0x00, 0x01, 0x00, 0x04, 0x01, 0x02, 0x03, 0x05];
628 let result = ChannelMappingTable::<255>::parse(&data, 6);
629 assert_eq!(
630 result,
631 Err(OpusError::InvalidStream(ErrorValues::ZeroStreamCount))
632 );
633 assert_eq!(result.unwrap_err().to_string(), "stream count cannot be 0");
634 }
635
636 #[test]
637 fn invalid_table_length() {
638 let data: [u8; 0x08] = [0x04, 0x02, 0x00, 0x04, 0x01, 0x02, 0x03, 0x05];
639 let result = ChannelMappingTable::<255>::parse(&data, 2);
640 assert_eq!(
641 result,
642 Err(OpusError::InvalidStream(ErrorValues::BadTableLength(6, 2)))
643 );
644 assert_eq!(
645 result.unwrap_err().to_string(),
646 "channel mapping table length does not match the number of channels (2): 6"
647 );
648 }
649
650 #[test]
651 fn too_long_table() {
652 let data: [u8; 0x08] = [0x04, 0x02, 0x00, 0x04, 0x01, 0x02, 0x03, 0x05];
653 let result = ChannelMappingTable::<5>::parse(&data, 6);
654 assert_eq!(
655 result,
656 Err(OpusError::InvalidStream(ErrorValues::TableTooBig(6, 5)))
657 );
658 assert_eq!(
659 result.unwrap_err().to_string(),
660 "channel mapping table does not fit to reserved space (5), it is 6 bytes long"
661 );
662 }
663
664 #[test]
665 fn invalid_channel_index() {
666 let data: [u8; 0x08] = [0x04, 0x02, 0x00, 0xFF, 0x0A, 0x02, 0x03, 0x05];
667 let result = ChannelMappingTable::<255>::parse(&data, 6);
668 assert_eq!(
669 result,
670 Err(OpusError::InvalidStream(ErrorValues::InvalidChannelIndex(
671 0x0A
672 )))
673 );
674 assert_eq!(
675 result.unwrap_err().to_string(),
676 "invalid channel index in channel mapping table: 10"
677 );
678 }
679
680 #[test]
681 fn too_many_streams() {
682 let data: [u8; 0x02] = [0x90, 0x90];
683 let result = ChannelMappingTable::<5>::parse(&data, 6);
684 assert_eq!(
685 result,
686 Err(OpusError::InvalidStream(
687 ErrorValues::TotalStreamCountExceeds(0x90 * 2)
688 ))
689 );
690 assert_eq!(
691 result.unwrap_err().to_string(),
692 "total stream count cannot be more than 255: 288"
693 );
694 }
695
696 #[test]
697 fn corrupted_stream() {
698 let mut data = Vec::from(include_bytes!("test/opus.data"));
699 data[2] = 10;
700 let result = OpusHeader::parse(&data);
701 assert_eq!(result, Err(OpusError::NotOpusStream));
702 assert!(result.unwrap_err().source().is_none());
703 }
704
705 #[test]
706 fn incomplete_header() {
707 let data = include_bytes!("test/opus.data");
708 let result = OpusHeader::parse(&data[..10]);
709 assert_eq!(
710 result,
711 Err(OpusError::EndOfStreamError(Some(2.try_into().unwrap())))
712 );
713 assert!(result.unwrap_err().source().is_none());
714 }
715
716 #[test]
717 fn invalid_channels() {
718 let mut data = Vec::from(include_bytes!("test/opus.data"));
719 data[9] = 0;
720 let result = OpusHeader::parse(&data);
721 assert_eq!(
722 result,
723 Err(OpusError::InvalidStream(ErrorValues::BadNumberOfChannels(
724 0, 0
725 )))
726 );
727 assert!(result.unwrap_err().source().is_none());
728 data[0x12] = 1;
729 let result = OpusHeader::parse(&data);
730 assert_eq!(
731 result,
732 Err(OpusError::InvalidStream(ErrorValues::BadNumberOfChannels(
733 1, 0
734 )))
735 );
736 assert!(result.unwrap_err().source().is_none());
737 }
738}