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_attr(docsrs, doc(cfg(feature = "family255")))]
136 #[cfg(feature = "family255")]
137 Family255 {
143 channels: u8,
145 table: ChannelMappingTable<255>,
147 },
148 #[cfg_attr(docsrs, doc(cfg(feature = "family255")))]
149 #[cfg(feature = "family255")]
150 Reserved {
156 channels: u8,
158 table: ChannelMappingTable<255>,
160 },
161}
162
163impl ChannelMapping {
164 pub fn get_channel_count(&self) -> u8 {
166 use ChannelMapping::*;
167 match self {
168 Family0 { channels } => *channels,
169 Family1 { channels, .. } => *channels,
170 #[cfg(feature = "family255")]
171 Family255 { channels, .. } => *channels,
172 #[cfg(feature = "family255")]
173 Reserved { channels, .. } => *channels,
174 }
175 }
176
177 pub fn get_stream_count(&self) -> u8 {
179 use ChannelMapping::*;
180 match self {
181 Family0 { .. } => 1,
182 Family1 { table, .. } => table.stream_count,
183 #[cfg(feature = "family255")]
184 Family255 { table, .. } => table.stream_count,
185 #[cfg(feature = "family255")]
186 Reserved { table, .. } => table.stream_count,
187 }
188 }
189
190 pub fn get_coupled_stream_count(&self) -> u8 {
192 use ChannelMapping::*;
193 match self {
194 Family0 { channels } => *channels - 1,
195 Family1 { table, .. } => table.coupled_count,
196 #[cfg(feature = "family255")]
197 Family255 { table, .. } => table.coupled_count,
198 #[cfg(feature = "family255")]
199 Reserved { table, .. } => table.coupled_count,
200 }
201 }
202
203 pub fn get_mapping(&self, channel: u8) -> Option<Mapping> {
209 use ChannelMapping::*;
210 let (speaker_location, index, coupled_count) = match self {
211 Family0 { channels } => {
212 let speaker_location = match (*channels, channel) {
213 (1, 0) => SpeakerLocation::Mono,
214 (2, 0) => SpeakerLocation::Left,
215 (2, 1) => SpeakerLocation::Right,
216 _ => return None,
217 };
218 Some((Some(speaker_location), channel, *channels - 1))
219 }
220 Family1 { channels, table } => {
221 let speaker_location = match (*channels, channel) {
222 (1, 0) => SpeakerLocation::Mono,
223 (2..=8, 0) => SpeakerLocation::Left,
224 (2, 1) | (3, 2) | (4, 1) | (5..=8, 2) => SpeakerLocation::Right,
225 (3, 1) | (5..=8, 1) => SpeakerLocation::Center,
226 (4, 2) | (5..=6, 3) | (8, 5) => SpeakerLocation::RearLeft,
227 (4, 3) | (5..=6, 4) | (8, 6) => SpeakerLocation::RearRight,
228 (6, 5) | (7, 6) | (8, 7) => SpeakerLocation::LFE,
229 (7..=8, 3) => SpeakerLocation::SideLeft,
230 (7..=8, 4) => SpeakerLocation::SideRight,
231 (7, 5) => SpeakerLocation::RearCenter,
232 _ => return None,
233 };
234 let ChannelMappingTable {
235 coupled_count,
236 mapping,
237 ..
238 } = &table;
239 let index = mapping[usize::from(channel)];
240 Some((Some(speaker_location), index, *coupled_count))
241 }
242 #[cfg(feature = "family255")]
243 Family255 { channels, table } | Reserved { channels, table } => {
244 if channel >= *channels {
245 None
246 } else {
247 let ChannelMappingTable {
248 coupled_count,
249 mapping,
250 ..
251 } = &table;
252 let index = mapping[usize::from(channel)];
253 Some((None, index, *coupled_count))
254 }
255 }
256 }?;
257 if index == 255 {
258 Some(Mapping {
259 stream: None,
260 speaker_location,
261 })
262 } else {
263 let stream = if index < 2 * coupled_count {
264 if index % 2 == 0 {
265 (index / 2, DecodedChannel::Left)
266 } else {
267 (index / 2, DecodedChannel::Right)
268 }
269 } else {
270 (index - coupled_count, DecodedChannel::Mono)
271 };
272 let stream = Some(stream);
273 Some(Mapping {
274 stream,
275 speaker_location,
276 })
277 }
278 }
279}
280
281#[derive(Clone, Copy, Debug, PartialEq)]
283#[non_exhaustive]
284pub enum SpeakerLocation {
285 Mono,
287 Left,
289 Right,
291 Center,
293 RearLeft,
295 RearRight,
297 RearCenter,
299 SideLeft,
301 SideRight,
303 LFE,
305}
306
307#[derive(Clone, Copy, Debug, PartialEq)]
309pub enum DecodedChannel {
310 Mono,
312 Left,
314 Right,
316}
317
318#[derive(Debug, PartialEq)]
320pub struct Mapping {
321 pub stream: Option<(u8, DecodedChannel)>,
323 pub speaker_location: Option<SpeakerLocation>,
325}
326
327#[derive(Debug, PartialEq)]
329pub struct ChannelMappingTable<const MAX_CHANNELS: usize> {
330 stream_count: u8,
332 coupled_count: u8,
334 mapping: [u8; MAX_CHANNELS],
336}
337
338impl<const MAX_CHANNELS: usize> ChannelMappingTable<MAX_CHANNELS> {
339 fn parse(input: &[u8], channels: u8) -> Result<ChannelMappingTable<MAX_CHANNELS>> {
340 use OpusError::*;
341 let (input, stream_count) = number::u8().parse(input)?;
342 let (input, coupled_count) = number::u8().parse(input)?;
343 let total_stream_count = stream_count.checked_add(coupled_count).ok_or_else(|| {
344 let total = stream_count as u16 + coupled_count as u16;
345 InvalidStream(ErrorValues::TotalStreamCountExceeds(total))
346 })?;
347 if stream_count == 0 {
348 Err(InvalidStream(ErrorValues::ZeroStreamCount))
349 } else if coupled_count > stream_count {
350 Err(InvalidStream(ErrorValues::StreamCountsMismatch(
351 coupled_count,
352 stream_count,
353 )))
354 } else if input.len() != channels.into() {
355 Err(InvalidStream(ErrorValues::BadTableLength(
356 input.len(),
357 channels,
358 )))
359 } else if input.len() > MAX_CHANNELS {
360 Err(InvalidStream(ErrorValues::TableTooBig(
361 input.len(),
362 MAX_CHANNELS as u8, )))
364 } else {
365 let mut mapping = [0; MAX_CHANNELS];
366 for (i, &v) in input.iter().enumerate() {
367 if v >= total_stream_count && v != 255 {
368 return Err(InvalidStream(ErrorValues::InvalidChannelIndex(v)));
369 }
370 mapping[i] = v;
371 }
372 Ok(ChannelMappingTable {
373 stream_count,
374 coupled_count,
375 mapping,
376 })
377 }
378 }
379}
380
381#[derive(Debug, PartialEq)]
383pub struct OpusHeader {
384 pub version: u8,
386 pub channels: ChannelMapping,
388 pub pre_skip: u16,
390 pub sample_rate: u32,
392 pub output_gain: u16,
394}
395
396impl OpusHeader {
397 pub fn parse(input: &[u8]) -> Result<Self> {
404 use OpusError::*;
405 let (input, _) = tag(b"OpusHead".as_slice())(input)
406 .map_err(|_: nom::Err<(&[u8], ErrorKind)>| NotOpusStream)?;
407 let (input, version) = number::u8().parse(input)?;
408 let (input, channels) = number::u8().parse(input)?;
409 let (input, pre_skip) = number::le_u16().parse(input)?;
410 let (input, sample_rate) = number::le_u32().parse(input)?;
411 let (input, output_gain) = number::le_u16().parse(input)?;
412 let (channel_mapping_table, channel_mapping_family) = number::u8().parse(input)?;
413 let channels = match channel_mapping_family {
414 0 => match channels {
415 1..=2 => ChannelMapping::Family0 { channels },
416 _ => return Err(InvalidStream(ErrorValues::BadNumberOfChannels(0, channels))),
417 },
418 1 => match channels {
419 1..=8 => ChannelMapping::Family1 {
420 channels,
421 table: ChannelMappingTable::parse(channel_mapping_table, channels)?,
422 },
423 _ => return Err(InvalidStream(ErrorValues::BadNumberOfChannels(1, channels))),
424 },
425 #[cfg(feature = "family255")]
426 255 => ChannelMapping::Family255 {
427 channels,
428 table: ChannelMappingTable::parse(channel_mapping_table, channels)?,
429 },
430 #[cfg(feature = "family255")]
431 _ => ChannelMapping::Reserved {
432 channels,
433 table: ChannelMappingTable::parse(channel_mapping_table, channels)?,
434 },
435 #[cfg(not(feature = "family255"))]
436 _ => {
437 return Err(UnsupportedStream(
438 "family 255 channel mapping is not supported",
439 ))
440 }
441 };
442 Ok(Self {
443 version,
444 channels,
445 pre_skip,
446 sample_rate,
447 output_gain,
448 })
449 }
450}
451
452#[cfg(test)]
453mod test {
454 use super::*;
455 use core::error::Error;
456
457 #[test]
458 fn parse_header() {
459 let data = include_bytes!("test/opus.data");
460 let header = OpusHeader::parse(data).unwrap();
461 assert_eq!(header.version, 1);
462 if let ChannelMapping::Family0 { channels } = header.channels {
463 assert_eq!(channels, 1);
464 } else {
465 panic!("Channel mapping family must be 0");
466 }
467 assert_eq!(header.pre_skip, 312);
468 assert_eq!(header.sample_rate, 8_000);
469 assert_eq!(header.output_gain, 0);
470 }
471
472 #[test]
473 fn family_0_mono() {
474 let channels = ChannelMapping::Family0 { channels: 1 };
475 assert_eq!(channels.get_channel_count(), 1);
476 assert_eq!(channels.get_stream_count(), 1);
477 assert_eq!(channels.get_coupled_stream_count(), 0);
478 let mapping = channels.get_mapping(0).unwrap();
479 assert_eq!(mapping.stream, Some((0, DecodedChannel::Mono)));
480 assert_eq!(mapping.speaker_location, Some(SpeakerLocation::Mono));
481 for index in 1..=255 {
482 assert_eq!(channels.get_mapping(index), None);
483 }
484 }
485
486 #[test]
487 fn family_0_stereo() {
488 let channels = ChannelMapping::Family0 { channels: 2 };
489 assert_eq!(channels.get_channel_count(), 2);
490 assert_eq!(channels.get_stream_count(), 1);
491 assert_eq!(channels.get_coupled_stream_count(), 1);
492 let mapping = channels.get_mapping(0).unwrap();
493 assert_eq!(mapping.stream, Some((0, DecodedChannel::Left)));
494 assert_eq!(mapping.speaker_location, Some(SpeakerLocation::Left));
495 let mapping = channels.get_mapping(1).unwrap();
496 assert_eq!(mapping.stream, Some((0, DecodedChannel::Right)));
497 assert_eq!(mapping.speaker_location, Some(SpeakerLocation::Right));
498 for index in 2..=255 {
499 assert_eq!(channels.get_mapping(index), None);
500 }
501 }
502
503 #[test]
504 fn family_1_stereo() {
505 let channels = ChannelMapping::Family1 {
506 channels: 2,
507 table: ChannelMappingTable::parse(&[1, 1, 0, 1], 2).unwrap(),
508 };
509 assert_eq!(channels.get_channel_count(), 2);
510 assert_eq!(channels.get_stream_count(), 1);
511 assert_eq!(channels.get_coupled_stream_count(), 1);
512 let mapping = channels.get_mapping(0).unwrap();
513 assert_eq!(mapping.stream, Some((0, DecodedChannel::Left)));
514 assert_eq!(mapping.speaker_location, Some(SpeakerLocation::Left));
515 let mapping = channels.get_mapping(1).unwrap();
516 assert_eq!(mapping.stream, Some((0, DecodedChannel::Right)));
517 assert_eq!(mapping.speaker_location, Some(SpeakerLocation::Right));
518 for index in 2..=255 {
519 assert_eq!(channels.get_mapping(index), None);
520 }
521 }
522
523 #[test]
524 fn family_1_surround_5_1() {
525 let data: [u8; 0x08] = [0x04, 0x02, 0x00, 0x04, 0x01, 0x02, 0x03, 0x05];
526 let channels = ChannelMapping::Family1 {
527 channels: 6,
528 table: ChannelMappingTable::parse(&data, 6).unwrap(),
529 };
530 assert_eq!(channels.get_channel_count(), 6);
531 assert_eq!(channels.get_stream_count(), 4);
532 assert_eq!(channels.get_coupled_stream_count(), 2);
533 let mappings = [
534 (0, DecodedChannel::Left, SpeakerLocation::Left),
535 (2, DecodedChannel::Mono, SpeakerLocation::Center),
536 (0, DecodedChannel::Right, SpeakerLocation::Right),
537 (1, DecodedChannel::Left, SpeakerLocation::RearLeft),
538 (1, DecodedChannel::Right, SpeakerLocation::RearRight),
539 (3, DecodedChannel::Mono, SpeakerLocation::LFE),
540 ];
541 for (index, (stream, channel, location)) in mappings.iter().enumerate() {
542 let mapping = channels.get_mapping(index as u8).unwrap();
543 assert_eq!(mapping.stream, Some((*stream, *channel)));
544 assert_eq!(mapping.speaker_location, Some(*location));
545 }
546 for index in 6..=255 {
547 assert_eq!(channels.get_mapping(index), None);
548 }
549 }
550
551 #[test]
552 #[cfg(feature = "family255")]
553 fn family_255() {
554 let data: [u8; 0x08] = [0x04, 0x02, 0x00, 0x04, 0x01, 0x02, 0x03, 0x05];
555 let channels = ChannelMapping::Family255 {
556 channels: 6,
557 table: ChannelMappingTable::parse(&data, 6).unwrap(),
558 };
559 assert_eq!(channels.get_channel_count(), 6);
560 assert_eq!(channels.get_stream_count(), 4);
561 assert_eq!(channels.get_coupled_stream_count(), 2);
562 let mappings = [
563 (0, DecodedChannel::Left),
564 (2, DecodedChannel::Mono),
565 (0, DecodedChannel::Right),
566 (1, DecodedChannel::Left),
567 (1, DecodedChannel::Right),
568 (3, DecodedChannel::Mono),
569 ];
570 for (index, (stream, channel)) in mappings.iter().enumerate() {
571 let mapping = channels.get_mapping(index as u8).unwrap();
572 assert_eq!(mapping.stream, Some((*stream, *channel)));
573 assert_eq!(mapping.speaker_location, None);
574 }
575 for index in 6..=255 {
576 assert_eq!(channels.get_mapping(index), None);
577 }
578 }
579
580 #[test]
581 #[cfg(feature = "family255")]
582 fn family_reserved() {
583 let data: [u8; 0x06] = [0x02, 0x01, 0x01, 0x00, 0x02, 0xFF];
584 let channels = ChannelMapping::Reserved {
585 channels: 4,
586 table: ChannelMappingTable::parse(&data, 4).unwrap(),
587 };
588 assert_eq!(channels.get_channel_count(), 4);
589 assert_eq!(channels.get_stream_count(), 2);
590 assert_eq!(channels.get_coupled_stream_count(), 1);
591 let mappings = [
592 Some((0, DecodedChannel::Right)),
593 Some((0, DecodedChannel::Left)),
594 Some((1, DecodedChannel::Mono)),
595 None,
596 ];
597 for (index, stream) in mappings.iter().enumerate() {
598 let mapping = channels.get_mapping(index as u8).unwrap();
599 assert_eq!(mapping.stream, *stream);
600 assert_eq!(mapping.speaker_location, None);
601 }
602 for index in 4..=255 {
603 assert_eq!(channels.get_mapping(index), None);
604 }
605 }
606
607 #[test]
608 fn invalid_stream_count() {
609 let data: [u8; 0x08] = [0x04, 0x05, 0x00, 0x04, 0x01, 0x02, 0x03, 0x05];
610 let result = ChannelMappingTable::<255>::parse(&data, 6);
611 assert_eq!(
612 result,
613 Err(OpusError::InvalidStream(ErrorValues::StreamCountsMismatch(
614 5, 4
615 )))
616 );
617 assert_eq!(
618 result.unwrap_err().to_string(),
619 "coupled stream count (5) cannot be larger than stream count (4)"
620 );
621 }
622
623 #[test]
624 fn zero_stream_count() {
625 let data: [u8; 0x08] = [0x00, 0x01, 0x00, 0x04, 0x01, 0x02, 0x03, 0x05];
626 let result = ChannelMappingTable::<255>::parse(&data, 6);
627 assert_eq!(
628 result,
629 Err(OpusError::InvalidStream(ErrorValues::ZeroStreamCount))
630 );
631 assert_eq!(result.unwrap_err().to_string(), "stream count cannot be 0");
632 }
633
634 #[test]
635 fn invalid_table_length() {
636 let data: [u8; 0x08] = [0x04, 0x02, 0x00, 0x04, 0x01, 0x02, 0x03, 0x05];
637 let result = ChannelMappingTable::<255>::parse(&data, 2);
638 assert_eq!(
639 result,
640 Err(OpusError::InvalidStream(ErrorValues::BadTableLength(6, 2)))
641 );
642 assert_eq!(
643 result.unwrap_err().to_string(),
644 "channel mapping table length does not match the number of channels (2): 6"
645 );
646 }
647
648 #[test]
649 fn too_long_table() {
650 let data: [u8; 0x08] = [0x04, 0x02, 0x00, 0x04, 0x01, 0x02, 0x03, 0x05];
651 let result = ChannelMappingTable::<5>::parse(&data, 6);
652 assert_eq!(
653 result,
654 Err(OpusError::InvalidStream(ErrorValues::TableTooBig(6, 5)))
655 );
656 assert_eq!(
657 result.unwrap_err().to_string(),
658 "channel mapping table does not fit to reserved space (5), it is 6 bytes long"
659 );
660 }
661
662 #[test]
663 fn invalid_channel_index() {
664 let data: [u8; 0x08] = [0x04, 0x02, 0x00, 0xFF, 0x0A, 0x02, 0x03, 0x05];
665 let result = ChannelMappingTable::<255>::parse(&data, 6);
666 assert_eq!(
667 result,
668 Err(OpusError::InvalidStream(ErrorValues::InvalidChannelIndex(
669 0x0A
670 )))
671 );
672 assert_eq!(
673 result.unwrap_err().to_string(),
674 "invalid channel index in channel mapping table: 10"
675 );
676 }
677
678 #[test]
679 fn too_many_streams() {
680 let data: [u8; 0x02] = [0x90, 0x90];
681 let result = ChannelMappingTable::<5>::parse(&data, 6);
682 assert_eq!(
683 result,
684 Err(OpusError::InvalidStream(
685 ErrorValues::TotalStreamCountExceeds(0x90 * 2)
686 ))
687 );
688 assert_eq!(
689 result.unwrap_err().to_string(),
690 "total stream count cannot be more than 255: 288"
691 );
692 }
693
694 #[test]
695 fn corrupted_stream() {
696 let mut data = Vec::from(include_bytes!("test/opus.data"));
697 data[2] = 10;
698 let result = OpusHeader::parse(&data);
699 assert_eq!(result, Err(OpusError::NotOpusStream));
700 assert!(result.unwrap_err().source().is_none());
701 }
702
703 #[test]
704 fn incomplete_header() {
705 let data = include_bytes!("test/opus.data");
706 let result = OpusHeader::parse(&data[..10]);
707 assert_eq!(
708 result,
709 Err(OpusError::EndOfStreamError(Some(2.try_into().unwrap())))
710 );
711 assert!(result.unwrap_err().source().is_none());
712 }
713
714 #[test]
715 fn invalid_channels() {
716 let mut data = Vec::from(include_bytes!("test/opus.data"));
717 data[9] = 0;
718 let result = OpusHeader::parse(&data);
719 assert_eq!(
720 result,
721 Err(OpusError::InvalidStream(ErrorValues::BadNumberOfChannels(
722 0, 0
723 )))
724 );
725 assert!(result.unwrap_err().source().is_none());
726 data[0x12] = 1;
727 let result = OpusHeader::parse(&data);
728 assert_eq!(
729 result,
730 Err(OpusError::InvalidStream(ErrorValues::BadNumberOfChannels(
731 1, 0
732 )))
733 );
734 assert!(result.unwrap_err().source().is_none());
735 }
736}