1use crate::*;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8#[repr(u8)]
9pub enum AudioChannelPosition {
10 FrontLeft = 0,
12
13 FrontRight = 1,
15
16 FrontCenter = 2,
18
19 Lfe1 = 3,
21
22 LeftSurround = 4,
24
25 RightSurround = 5,
27
28 FrontLeftOfCenter = 6,
30
31 FrontRightOfCenter = 7,
33
34 RearLeft = 8,
36
37 RearRight = 9,
39
40 RearCenter = 10,
42
43 SurroundLeft = 11,
45
46 SurroundRight = 12,
48
49 SideLeft = 13,
51
52 SideRight = 14,
54
55 FrontLeftWide = 15,
57
58 FrontRightWide = 16,
60
61 TopFrontLeft = 17,
63
64 TopFrontRight = 18,
66
67 TopFrontCenter = 19,
69
70 TopRearLeft = 20,
72
73 TopRearRight = 21,
75
76 TopRearCenter = 22,
78
79 TopSideLeft = 23,
81
82 TopSideRight = 24,
84
85 TopCenter = 25,
87
88 Lfe2 = 26,
90
91 BottomFrontLeft = 27,
93
94 BottomFrontRight = 28,
96
97 BottomFrontCenter = 29,
99
100 TopSurroundLeft = 30,
102
103 TopSurroundRight = 31,
105
106 Lfe3 = 36,
109
110 Leos = 37,
112
113 Reos = 38,
115
116 Hwbcal = 39,
118
119 Hwbcar = 40,
121
122 Lbs = 41,
124
125 Rbs = 42,
127
128 LeftEar = 43,
135
136 RightEar = 44,
143
144 Unknown = 127,
149}
150
151impl AudioChannelPosition {
152 pub fn from_u8(value: u8) -> Option<Self> {
153 match value {
154 0 => Some(Self::FrontLeft),
155 1 => Some(Self::FrontRight),
156 2 => Some(Self::FrontCenter),
157 3 => Some(Self::Lfe1),
158 4 => Some(Self::LeftSurround),
159 5 => Some(Self::RightSurround),
160 6 => Some(Self::FrontLeftOfCenter),
161 7 => Some(Self::FrontRightOfCenter),
162 8 => Some(Self::RearLeft),
163 9 => Some(Self::RearRight),
164 10 => Some(Self::RearCenter),
165 11 => Some(Self::SurroundLeft),
166 12 => Some(Self::SurroundRight),
167 13 => Some(Self::SideLeft),
168 14 => Some(Self::SideRight),
169 15 => Some(Self::FrontLeftWide),
170 16 => Some(Self::FrontRightWide),
171 17 => Some(Self::TopFrontLeft),
172 18 => Some(Self::TopFrontRight),
173 19 => Some(Self::TopFrontCenter),
174 20 => Some(Self::TopRearLeft),
175 21 => Some(Self::TopRearRight),
176 22 => Some(Self::TopRearCenter),
177 23 => Some(Self::TopSideLeft),
178 24 => Some(Self::TopSideRight),
179 25 => Some(Self::TopCenter),
180 26 => Some(Self::Lfe2),
181 27 => Some(Self::BottomFrontLeft),
182 28 => Some(Self::BottomFrontRight),
183 29 => Some(Self::BottomFrontCenter),
184 30 => Some(Self::TopSurroundLeft),
185 31 => Some(Self::TopSurroundRight),
186 36 => Some(Self::Lfe3),
187 37 => Some(Self::Leos),
188 38 => Some(Self::Reos),
189 39 => Some(Self::Hwbcal),
190 40 => Some(Self::Hwbcar),
191 41 => Some(Self::Lbs),
192 42 => Some(Self::Rbs),
193 43 => Some(Self::LeftEar),
194 44 => Some(Self::RightEar),
195 127 => Some(Self::Unknown),
196 _ => None,
197 }
198 }
199}
200
201const CHANNEL_LAYOUTS: &[&[AudioChannelPosition]] = &[
205 &[],
207 &[AudioChannelPosition::FrontCenter],
209 &[
211 AudioChannelPosition::FrontLeft,
212 AudioChannelPosition::FrontRight,
213 ],
214 &[
216 AudioChannelPosition::FrontCenter,
217 AudioChannelPosition::FrontLeft,
218 AudioChannelPosition::FrontRight,
219 ],
220 &[
222 AudioChannelPosition::FrontCenter,
223 AudioChannelPosition::FrontLeft,
224 AudioChannelPosition::FrontRight,
225 AudioChannelPosition::RearCenter,
226 ],
227 &[
229 AudioChannelPosition::FrontCenter,
230 AudioChannelPosition::FrontLeft,
231 AudioChannelPosition::FrontRight,
232 AudioChannelPosition::LeftSurround,
233 AudioChannelPosition::RightSurround,
234 ],
235 &[
237 AudioChannelPosition::FrontCenter,
238 AudioChannelPosition::FrontLeft,
239 AudioChannelPosition::FrontRight,
240 AudioChannelPosition::LeftSurround,
241 AudioChannelPosition::RightSurround,
242 AudioChannelPosition::Lfe1,
243 ],
244 &[
246 AudioChannelPosition::FrontCenter,
247 AudioChannelPosition::FrontLeftOfCenter,
248 AudioChannelPosition::FrontRightOfCenter,
249 AudioChannelPosition::FrontLeft,
250 AudioChannelPosition::FrontRight,
251 AudioChannelPosition::LeftSurround,
252 AudioChannelPosition::RightSurround,
253 AudioChannelPosition::Lfe1,
254 ],
255 &[],
257 &[
259 AudioChannelPosition::FrontLeft,
260 AudioChannelPosition::FrontRight,
261 AudioChannelPosition::RearCenter,
262 ],
263 &[
265 AudioChannelPosition::FrontLeft,
266 AudioChannelPosition::FrontRight,
267 AudioChannelPosition::LeftSurround,
268 AudioChannelPosition::RightSurround,
269 ],
270 &[
272 AudioChannelPosition::FrontCenter,
273 AudioChannelPosition::FrontLeft,
274 AudioChannelPosition::FrontRight,
275 AudioChannelPosition::LeftSurround,
276 AudioChannelPosition::RightSurround,
277 AudioChannelPosition::RearCenter,
278 AudioChannelPosition::Lfe1,
279 ],
280 &[
282 AudioChannelPosition::FrontCenter,
283 AudioChannelPosition::FrontLeft,
284 AudioChannelPosition::FrontRight,
285 AudioChannelPosition::LeftSurround,
286 AudioChannelPosition::RightSurround,
287 AudioChannelPosition::RearLeft,
288 AudioChannelPosition::RearRight,
289 AudioChannelPosition::Lfe1,
290 ],
291 &[
293 AudioChannelPosition::FrontCenter,
294 AudioChannelPosition::FrontLeftOfCenter,
295 AudioChannelPosition::FrontRightOfCenter,
296 AudioChannelPosition::FrontLeft,
297 AudioChannelPosition::FrontRight,
298 AudioChannelPosition::SideLeft,
299 AudioChannelPosition::SideRight,
300 AudioChannelPosition::RearLeft,
301 AudioChannelPosition::RearRight,
302 AudioChannelPosition::RearCenter,
303 AudioChannelPosition::Lfe1,
304 AudioChannelPosition::Lfe2,
305 AudioChannelPosition::TopFrontCenter,
306 AudioChannelPosition::TopFrontLeft,
307 AudioChannelPosition::TopFrontRight,
308 AudioChannelPosition::TopSideLeft,
309 AudioChannelPosition::TopSideRight,
310 AudioChannelPosition::TopCenter,
311 AudioChannelPosition::TopRearLeft,
312 AudioChannelPosition::TopRearRight,
313 AudioChannelPosition::TopRearCenter,
314 AudioChannelPosition::BottomFrontCenter,
315 AudioChannelPosition::BottomFrontLeft,
316 AudioChannelPosition::BottomFrontRight,
317 ],
318 &[
320 AudioChannelPosition::FrontCenter,
321 AudioChannelPosition::FrontLeft,
322 AudioChannelPosition::FrontRight,
323 AudioChannelPosition::LeftSurround,
324 AudioChannelPosition::RightSurround,
325 AudioChannelPosition::Lfe1,
326 AudioChannelPosition::TopFrontLeft,
327 AudioChannelPosition::TopFrontRight,
328 ],
329 &[
331 AudioChannelPosition::FrontCenter,
332 AudioChannelPosition::FrontLeft,
333 AudioChannelPosition::FrontRight,
334 AudioChannelPosition::SideLeft,
335 AudioChannelPosition::SideRight,
336 AudioChannelPosition::LeftSurround,
337 AudioChannelPosition::RightSurround,
338 AudioChannelPosition::TopFrontLeft,
339 AudioChannelPosition::TopFrontRight,
340 AudioChannelPosition::TopRearCenter,
341 AudioChannelPosition::Lfe1,
342 AudioChannelPosition::Lfe2,
343 ],
344 &[
346 AudioChannelPosition::FrontCenter,
347 AudioChannelPosition::FrontLeft,
348 AudioChannelPosition::FrontRight,
349 AudioChannelPosition::LeftSurround,
350 AudioChannelPosition::RightSurround,
351 AudioChannelPosition::Lfe1,
352 AudioChannelPosition::TopFrontLeft,
353 AudioChannelPosition::TopFrontRight,
354 AudioChannelPosition::TopSurroundLeft,
355 AudioChannelPosition::TopSurroundRight,
356 ],
357 &[
359 AudioChannelPosition::FrontCenter,
360 AudioChannelPosition::FrontLeft,
361 AudioChannelPosition::FrontRight,
362 AudioChannelPosition::LeftSurround,
363 AudioChannelPosition::RightSurround,
364 AudioChannelPosition::Lfe1,
365 AudioChannelPosition::TopFrontLeft,
366 AudioChannelPosition::TopFrontRight,
367 AudioChannelPosition::TopFrontCenter,
368 AudioChannelPosition::TopSurroundLeft,
369 AudioChannelPosition::TopSurroundRight,
370 AudioChannelPosition::TopCenter,
371 ],
372 &[
374 AudioChannelPosition::FrontCenter,
375 AudioChannelPosition::FrontLeft,
376 AudioChannelPosition::FrontRight,
377 AudioChannelPosition::LeftSurround,
378 AudioChannelPosition::RightSurround,
379 AudioChannelPosition::Lbs,
380 AudioChannelPosition::Rbs,
381 AudioChannelPosition::Lfe1,
382 AudioChannelPosition::TopFrontLeft,
383 AudioChannelPosition::TopFrontRight,
384 AudioChannelPosition::TopFrontCenter,
385 AudioChannelPosition::TopSurroundLeft,
386 AudioChannelPosition::TopSurroundRight,
387 AudioChannelPosition::TopCenter,
388 ],
389 &[
391 AudioChannelPosition::FrontCenter,
392 AudioChannelPosition::FrontLeft,
393 AudioChannelPosition::FrontRight,
394 AudioChannelPosition::SideLeft,
395 AudioChannelPosition::SideRight,
396 AudioChannelPosition::RearLeft,
397 AudioChannelPosition::RearRight,
398 AudioChannelPosition::Lfe1,
399 AudioChannelPosition::TopFrontLeft,
400 AudioChannelPosition::TopFrontRight,
401 AudioChannelPosition::TopRearLeft,
402 AudioChannelPosition::TopRearRight,
403 ],
404 &[
406 AudioChannelPosition::FrontCenter,
407 AudioChannelPosition::Leos,
408 AudioChannelPosition::Reos,
409 AudioChannelPosition::FrontLeft,
410 AudioChannelPosition::FrontRight,
411 AudioChannelPosition::SideLeft,
412 AudioChannelPosition::SideRight,
413 AudioChannelPosition::RearLeft,
414 AudioChannelPosition::RearRight,
415 AudioChannelPosition::Lfe1,
416 AudioChannelPosition::TopFrontLeft,
417 AudioChannelPosition::TopFrontRight,
418 AudioChannelPosition::TopSurroundLeft,
419 AudioChannelPosition::TopSurroundRight,
420 ],
421 &[
423 AudioChannelPosition::LeftEar,
424 AudioChannelPosition::RightEar,
425 ],
426 ];
428
429#[derive(Debug, Clone, PartialEq, Eq)]
430#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
431pub struct ExplicitSpeakerPosition {
432 pub azimuth: i16,
433 pub elevation: i8,
434}
435
436#[derive(Debug, Clone, PartialEq, Eq)]
437#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
438pub enum SpeakerPosition {
439 Standard(AudioChannelPosition),
440 Explicit(ExplicitSpeakerPosition),
441}
442
443#[derive(Debug, Clone, PartialEq, Eq)]
444#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
445pub enum ChannelStructure {
446 ExplicitPositions {
447 positions: Vec<SpeakerPosition>,
448 },
449 DefinedLayout {
450 layout: u8,
451 omitted_channels_map: Option<u64>,
452 channel_order_definition: Option<u8>,
453 },
454}
455
456impl ChannelStructure {
457 fn channel_count(&self) -> u8 {
458 match self {
459 Self::ExplicitPositions { positions } => positions.len() as u8,
460 Self::DefinedLayout { layout, .. } => CHANNEL_LAYOUTS
461 .get(*layout as usize)
462 .map(|l| l.len())
463 .unwrap_or(0) as u8,
464 }
465 }
466}
467
468ext! {
469 name: Chnl,
470 versions: [0, 1],
471 flags: {}
472}
473
474#[derive(Debug, Clone, PartialEq, Eq)]
475#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
476pub struct Chnl {
477 pub channel_structure: Option<ChannelStructure>,
478 pub object_count: Option<u8>,
479 pub format_ordering: Option<u8>,
480 pub base_channel_count: Option<u8>,
481}
482
483#[derive(Debug)]
484struct StreamStructure {
485 channel_structured: bool,
486 object_structured: bool,
487}
488
489impl Chnl {
490 fn decode_speaker_position<B: Buf>(buf: &mut B) -> Result<SpeakerPosition> {
491 let speaker_position = u8::decode(buf)?;
492
493 if speaker_position == 126 {
494 let azimuth = i16::decode(buf)?;
496 let elevation = i8::decode(buf)?;
497 Ok(SpeakerPosition::Explicit(ExplicitSpeakerPosition {
498 azimuth,
499 elevation,
500 }))
501 } else if let Some(pos) = AudioChannelPosition::from_u8(speaker_position) {
502 Ok(SpeakerPosition::Standard(pos))
503 } else {
504 Err(Error::Unsupported("invalid speaker position"))
505 }
506 }
507
508 fn decode_stream_structure_v0<B: Buf>(buf: &mut B) -> Result<StreamStructure> {
509 let stream_structure = u8::decode(buf)?;
510 let channel_structured = (stream_structure & 0x01) != 0;
511 let object_structured = (stream_structure & 0x02) != 0;
512
513 Ok(StreamStructure {
514 channel_structured,
515 object_structured,
516 })
517 }
518
519 fn decode_stream_structure_v1<B: Buf>(buf: &mut B) -> Result<(StreamStructure, u8)> {
520 let byte = u8::decode(buf)?;
521 let stream_structure = (byte >> 4) & 0x0F;
522 let format_ordering = byte & 0x0F;
523
524 let channel_structured = (stream_structure & 0x01) != 0;
525 let object_structured = (stream_structure & 0x02) != 0;
526
527 Ok((
528 StreamStructure {
529 channel_structured,
530 object_structured,
531 },
532 format_ordering,
533 ))
534 }
535
536 fn decode_channel_structure_v0<B: Buf>(
537 buf: &mut B,
538 channel_count: Option<u16>,
539 object_structured: bool,
540 ) -> Result<Option<ChannelStructure>> {
541 let defined_layout = u8::decode(buf)?;
542
543 if defined_layout == 0 {
544 let mut positions = Vec::new();
546
547 match channel_count {
548 Some(chnl_count) => {
550 positions.reserve(chnl_count as usize);
551 for _ in 0..chnl_count {
552 positions.push(Self::decode_speaker_position(buf)?);
553 }
554 }
555 None => {
560 let reserved_bytes = if object_structured { 1 } else { 0 };
563 while buf.remaining() > reserved_bytes {
564 positions.push(Self::decode_speaker_position(buf)?);
565 }
566 }
567 }
568
569 Ok(Some(ChannelStructure::ExplicitPositions { positions }))
570 } else {
571 let omitted_channels_map = u64::decode(buf)?;
573 Ok(Some(ChannelStructure::DefinedLayout {
574 layout: defined_layout,
575 omitted_channels_map: Some(omitted_channels_map),
576 channel_order_definition: None,
577 }))
578 }
579 }
580
581 fn decode_channel_structure_v1<B: Buf>(buf: &mut B) -> Result<Option<ChannelStructure>> {
582 let defined_layout = u8::decode(buf)?;
583
584 if defined_layout == 0 {
585 let layout_channel_count = u8::decode(buf)?;
587 let mut positions = Vec::with_capacity(layout_channel_count as usize);
588
589 for _ in 0..layout_channel_count {
590 positions.push(Self::decode_speaker_position(buf)?);
591 }
592
593 Ok(Some(ChannelStructure::ExplicitPositions { positions }))
594 } else {
595 let byte = u8::decode(buf)?;
597 let channel_order_definition = (byte >> 1) & 0x07;
598 let omitted_channels_present = (byte & 0x01) != 0;
599
600 if channel_order_definition > 4 {
602 return Err(Error::Unsupported("invalid channel order definition"));
603 }
604
605 let omitted_channels_map = if omitted_channels_present {
606 Some(u64::decode(buf)?)
607 } else {
608 None
609 };
610
611 Ok(Some(ChannelStructure::DefinedLayout {
612 layout: defined_layout,
613 omitted_channels_map,
614 channel_order_definition: Some(channel_order_definition),
615 }))
616 }
617 }
618
619 fn get_object_count_v1(
620 channel_structure: Option<&ChannelStructure>,
621 base_channel_count: u8,
622 ) -> Option<u8> {
623 channel_structure
626 .map(|cs| base_channel_count.saturating_sub(cs.channel_count()))
627 .filter(|&count| count != 0)
628 }
629
630 fn encode_object_structure_v1<B: BufMut>(
631 buf: &mut B,
632 channel_structure: Option<&ChannelStructure>,
633 base_channel_count: u8,
634 ) -> Result<()> {
635 channel_structure
636 .map(|cs| base_channel_count.saturating_sub(cs.channel_count()))
639 .filter(|&count| count > 0)
640 .map(|count| count.encode(buf))
641 .transpose()?;
642
643 Ok(())
644 }
645
646 fn encode_channel_structure_v0<B: BufMut>(&self, buf: &mut B) -> Result<()> {
647 let Some(ref structure) = self.channel_structure else {
648 return Ok(());
649 };
650
651 match structure {
652 ChannelStructure::ExplicitPositions { positions } => {
653 (0u8).encode(buf)?; for position in positions {
656 match position {
657 SpeakerPosition::Standard(pos) => {
658 (*pos as u8).encode(buf)?;
659 }
660 SpeakerPosition::Explicit(explicit) => {
661 (126u8).encode(buf)?;
662 explicit.azimuth.encode(buf)?;
663 explicit.elevation.encode(buf)?;
664 }
665 }
666 }
667 }
668 ChannelStructure::DefinedLayout {
669 layout,
670 omitted_channels_map,
671 ..
672 } => {
673 layout.encode(buf)?;
674
675 let map = omitted_channels_map.ok_or_else(|| {
676 Error::Unsupported("omitted_channels_map required for version 0 defined layout")
677 })?;
678 map.encode(buf)?;
679 }
680 }
681
682 Ok(())
683 }
684
685 fn encode_channel_structure_v1<B: BufMut>(&self, buf: &mut B) -> Result<()> {
686 let Some(ref structure) = self.channel_structure else {
687 return Ok(());
688 };
689
690 match structure {
691 ChannelStructure::ExplicitPositions { positions } => {
692 (0u8).encode(buf)?; (positions.len() as u8).encode(buf)?; for position in positions {
696 match position {
697 SpeakerPosition::Standard(pos) => {
698 (*pos as u8).encode(buf)?;
699 }
700 SpeakerPosition::Explicit(explicit) => {
701 (126u8).encode(buf)?;
702 explicit.azimuth.encode(buf)?;
703 explicit.elevation.encode(buf)?;
704 }
705 }
706 }
707 }
708 ChannelStructure::DefinedLayout {
709 layout,
710 omitted_channels_map,
711 channel_order_definition,
712 } => {
713 layout.encode(buf)?;
714
715 let channel_order_def = channel_order_definition.unwrap_or(0);
716 let omitted_present = omitted_channels_map.is_some();
717
718 let combined = (channel_order_def << 1) | (if omitted_present { 1 } else { 0 });
719 combined.encode(buf)?;
720
721 if let Some(map) = omitted_channels_map {
722 map.encode(buf)?;
723 }
724 }
725 }
726
727 Ok(())
728 }
729
730 fn decode_body_v0<B: Buf>(buf: &mut B, channel_count: Option<u16>) -> Result<Self> {
731 let stream_structure = Self::decode_stream_structure_v0(buf)?;
732
733 let channel_structure = if stream_structure.channel_structured {
734 Self::decode_channel_structure_v0(
735 buf,
736 channel_count,
737 stream_structure.object_structured,
738 )?
739 } else {
740 None
741 };
742
743 let object_count = if stream_structure.object_structured {
744 Some(u8::decode(buf)?)
745 } else {
746 None
747 };
748
749 Ok(Self {
750 channel_structure,
751 object_count,
752 format_ordering: None,
753 base_channel_count: None,
754 })
755 }
756
757 fn decode_body_v1<B: Buf>(buf: &mut B) -> Result<Self> {
758 let (stream_structure, format_ordering) = Self::decode_stream_structure_v1(buf)?;
759 let base_channel_count = u8::decode(buf)?;
760
761 let channel_structure = if stream_structure.channel_structured {
762 Self::decode_channel_structure_v1(buf)?
763 } else {
764 None
765 };
766
767 let computed_object_count = stream_structure
770 .object_structured
771 .then(|| Self::get_object_count_v1(channel_structure.as_ref(), base_channel_count))
772 .flatten();
773
774 let decoded_object_count = if stream_structure.object_structured {
775 Some(u8::decode(buf)?)
776 } else {
777 None
778 };
779
780 if stream_structure.object_structured && computed_object_count != decoded_object_count {
781 return Err(Error::Unsupported(
782 "computed object count != decoded object count",
783 ));
784 }
785
786 Ok(Self {
787 channel_structure,
788 object_count: decoded_object_count,
789 format_ordering: Some(format_ordering),
790 base_channel_count: Some(base_channel_count),
791 })
792 }
793
794 pub fn decode_body_with_channel_count<B: Buf>(buf: &mut B, channel_count: u16) -> Result<Self> {
797 let version_and_flags = u32::decode(buf)?;
798 let version = (version_and_flags >> 24) as u8;
799 let flags = version_and_flags & 0xFFFFFF;
800
801 if flags != 0 {
802 return Err(Error::Unsupported("chnl box with non-zero flags"));
803 }
804
805 match version {
806 0 => Self::decode_body_v0(buf, Some(channel_count)),
807 1 => Self::decode_body_v1(buf),
808 _ => Err(Error::Unsupported("invalid version")),
809 }
810 }
811}
812
813impl AtomExt for Chnl {
815 const KIND_EXT: FourCC = FourCC::new(b"chnl");
816
817 type Ext = ChnlExt;
818
819 fn decode_body_ext<B: Buf>(buf: &mut B, ext: ChnlExt) -> Result<Self> {
820 match ext.version {
821 ChnlVersion::V0 => Self::decode_body_v0(buf, None),
822 ChnlVersion::V1 => Self::decode_body_v1(buf),
823 }
824 }
825
826 fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<ChnlExt> {
827 let version = if self.format_ordering.is_some() && self.base_channel_count.is_some() {
829 ChnlVersion::V1
830 } else {
831 ChnlVersion::V0
832 };
833
834 match version {
835 ChnlVersion::V0 => {
836 let mut stream_structure = 0u8;
837
838 if self.channel_structure.is_some() {
839 stream_structure |= 0x01;
840 }
841
842 if self.object_count.is_some() {
843 stream_structure |= 0x02;
844 }
845
846 stream_structure.encode(buf)?;
847
848 self.encode_channel_structure_v0(buf)?;
849
850 if let Some(object_count) = self.object_count {
851 object_count.encode(buf)?;
852 }
853 }
854 ChnlVersion::V1 => {
855 let base_channel_count = self.base_channel_count.unwrap();
856 let format_ordering = self.format_ordering.unwrap_or(1);
857
858 if !(0..=2).contains(&format_ordering) {
860 return Err(Error::Unsupported("format ordering must be 0, 1 or 2"));
861 }
862
863 let object_count =
864 Self::get_object_count_v1(self.channel_structure.as_ref(), base_channel_count);
865 let object_structured = object_count.is_some();
866 let channel_structured = self.channel_structure.is_some();
867
868 let mut stream_structure = 0u8;
869 if channel_structured {
870 stream_structure |= 0x01;
871 }
872 if object_structured {
873 stream_structure |= 0x02;
874 }
875
876 let combined = (stream_structure << 4) | (format_ordering & 0x0F);
877 combined.encode(buf)?;
878
879 base_channel_count.encode(buf)?;
880
881 self.encode_channel_structure_v1(buf)?;
882
883 if object_structured {
884 Self::encode_object_structure_v1(
885 buf,
886 self.channel_structure.as_ref(),
887 base_channel_count,
888 )?;
889 }
890 }
891 }
892
893 Ok(ChnlExt { version })
894 }
895}
896
897#[cfg(test)]
898mod tests {
899 use super::*;
900
901 #[test]
902 fn test_chnl_v0_explicit_positions() {
903 let chnl = Chnl {
904 channel_structure: Some(ChannelStructure::ExplicitPositions {
905 positions: vec![
906 SpeakerPosition::Standard(AudioChannelPosition::FrontLeft),
907 SpeakerPosition::Standard(AudioChannelPosition::FrontRight),
908 ],
909 }),
910 object_count: None,
911 format_ordering: None,
912 base_channel_count: None,
913 };
914
915 let mut buf = Vec::new();
916 chnl.encode(&mut buf).unwrap();
917
918 let decoded = Chnl::decode(&mut &buf[..]).unwrap();
919 assert_eq!(chnl, decoded);
920 }
921
922 #[test]
923 fn test_chnl_v0_defined_layout() {
924 let chnl = Chnl {
925 channel_structure: Some(ChannelStructure::DefinedLayout {
926 layout: 2,
927 omitted_channels_map: Some(0),
928 channel_order_definition: None,
929 }),
930 object_count: None,
931 format_ordering: None,
932 base_channel_count: None,
933 };
934
935 let mut buf = Vec::new();
936 chnl.encode(&mut buf).unwrap();
937
938 let decoded = Chnl::decode(&mut &buf[..]).unwrap();
939 assert_eq!(chnl, decoded);
940 }
941
942 #[test]
943 fn test_chnl_decode_with_channel_count() {
944 let chnl = Chnl {
945 channel_structure: Some(ChannelStructure::ExplicitPositions {
946 positions: vec![
947 SpeakerPosition::Standard(AudioChannelPosition::FrontLeft),
948 SpeakerPosition::Standard(AudioChannelPosition::FrontRight),
949 ],
950 }),
951 object_count: Some(2),
952 format_ordering: None,
953 base_channel_count: None,
954 };
955
956 let mut buf = Vec::new();
957 chnl.encode(&mut buf).unwrap();
958
959 let body_start = 8;
962 let mut body_buf = &buf[body_start..];
963
964 let decoded = Chnl::decode_body_with_channel_count(&mut body_buf, 2).unwrap();
965 assert_eq!(chnl, decoded);
966 }
967
968 #[test]
969 fn test_chnl_v1_explicit_positions() {
970 let chnl = Chnl {
971 channel_structure: Some(ChannelStructure::ExplicitPositions {
972 positions: vec![
973 SpeakerPosition::Standard(AudioChannelPosition::FrontLeft),
974 SpeakerPosition::Standard(AudioChannelPosition::FrontRight),
975 SpeakerPosition::Standard(AudioChannelPosition::FrontCenter),
976 ],
977 }),
978 object_count: None,
979 format_ordering: Some(1),
980 base_channel_count: Some(3),
981 };
982
983 let mut buf = Vec::new();
984 chnl.encode(&mut buf).unwrap();
985
986 let decoded = Chnl::decode(&mut &buf[..]).unwrap();
987 assert_eq!(chnl, decoded);
988 }
989
990 #[test]
991 fn test_chnl_v1_defined_layout_with_omitted() {
992 let chnl = Chnl {
993 channel_structure: Some(ChannelStructure::DefinedLayout {
994 layout: 6,
995 omitted_channels_map: Some(0x20), channel_order_definition: Some(0),
997 }),
998 object_count: None,
999 format_ordering: Some(1),
1000 base_channel_count: Some(6),
1001 };
1002
1003 let mut buf = Vec::new();
1004 chnl.encode(&mut buf).unwrap();
1005
1006 let decoded = Chnl::decode(&mut &buf[..]).unwrap();
1007 assert_eq!(chnl, decoded);
1008 }
1009
1010 #[test]
1011 fn test_chnl_v1_defined_layout_without_omitted() {
1012 let chnl = Chnl {
1013 channel_structure: Some(ChannelStructure::DefinedLayout {
1014 layout: 2,
1015 omitted_channels_map: None,
1016 channel_order_definition: Some(0),
1017 }),
1018 object_count: None,
1019 format_ordering: Some(1),
1020 base_channel_count: Some(2),
1021 };
1022
1023 let mut buf = Vec::new();
1024 chnl.encode(&mut buf).unwrap();
1025
1026 let decoded = Chnl::decode(&mut &buf[..]).unwrap();
1027 assert_eq!(chnl, decoded);
1028 }
1029
1030 #[test]
1031 fn test_chnl_unpositioned_audio() {
1032 let chnl = Chnl {
1033 channel_structure: Some(ChannelStructure::ExplicitPositions {
1034 positions: vec![
1035 SpeakerPosition::Standard(AudioChannelPosition::Unknown),
1036 SpeakerPosition::Standard(AudioChannelPosition::Unknown),
1037 ],
1038 }),
1039 object_count: None,
1040 format_ordering: None,
1041 base_channel_count: None,
1042 };
1043
1044 let mut buf = Vec::new();
1045 chnl.encode(&mut buf).unwrap();
1046
1047 let decoded = Chnl::decode(&mut &buf[..]).unwrap();
1048 assert_eq!(chnl, decoded);
1049 }
1050
1051 #[test]
1052 fn test_chnl_v1_with_objects() {
1053 let chnl = Chnl {
1054 channel_structure: Some(ChannelStructure::ExplicitPositions {
1055 positions: vec![
1056 SpeakerPosition::Standard(AudioChannelPosition::FrontLeft),
1057 SpeakerPosition::Standard(AudioChannelPosition::FrontRight),
1058 ],
1059 }),
1060 object_count: None,
1061 format_ordering: Some(1),
1062 base_channel_count: Some(5),
1063 };
1064
1065 let mut buf = Vec::new();
1066 chnl.encode(&mut buf).unwrap();
1067
1068 let decoded = Chnl::decode(&mut &buf[..]).unwrap();
1069 assert_eq!(decoded.object_count, Some(3));
1070 }
1071
1072 #[test]
1073 fn test_chnl_explicit_speaker_positions() {
1074 let chnl = Chnl {
1075 channel_structure: Some(ChannelStructure::ExplicitPositions {
1076 positions: vec![
1077 SpeakerPosition::Standard(AudioChannelPosition::FrontLeft),
1078 SpeakerPosition::Explicit(ExplicitSpeakerPosition {
1079 azimuth: 30,
1080 elevation: 0,
1081 }),
1082 SpeakerPosition::Standard(AudioChannelPosition::FrontRight),
1083 ],
1084 }),
1085 object_count: None,
1086 format_ordering: None,
1087 base_channel_count: None,
1088 };
1089
1090 let mut buf = Vec::new();
1091 chnl.encode(&mut buf).unwrap();
1092
1093 let decoded = Chnl::decode(&mut &buf[..]).unwrap();
1094 assert_eq!(chnl, decoded);
1095 }
1096}