mp4_atom/moov/trak/mdia/minf/stbl/stsd/
chnl.rs

1use crate::*;
2
3/// ISO/IEC 23091-3 Audio Channel Position
4///
5/// Consistent with ISO/IEC 23091-3:2018/Amd. 1:2022(E) Table 2 changes.
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8#[repr(u8)]
9pub enum AudioChannelPosition {
10    /// Front left (L).
11    FrontLeft = 0,
12
13    /// Front right (R).
14    FrontRight = 1,
15
16    /// Centre front (C).
17    FrontCenter = 2,
18
19    /// Low frequency enhancement (LFE).
20    Lfe1 = 3,
21
22    /// Left surround (Ls).
23    LeftSurround = 4,
24
25    /// Right surround (Rs).
26    RightSurround = 5,
27
28    /// Left front centre (Lc).
29    FrontLeftOfCenter = 6,
30
31    /// Right front centre (Rc).
32    FrontRightOfCenter = 7,
33
34    /// Rear surround left (Lsr).
35    RearLeft = 8,
36
37    /// Rear surround right (Rsr).
38    RearRight = 9,
39
40    /// Rear centre (Cs).
41    RearCenter = 10,
42
43    /// Left surround direct (Lsd).
44    SurroundLeft = 11,
45
46    /// Right surround direct (Rsd).
47    SurroundRight = 12,
48
49    /// Left side surround (Lss).
50    SideLeft = 13,
51
52    /// Right side surround (Rss).
53    SideRight = 14,
54
55    /// Left wide front (Lw).
56    FrontLeftWide = 15,
57
58    /// Right wide front (Rw).
59    FrontRightWide = 16,
60
61    /// Left front vertical height (Lv).
62    TopFrontLeft = 17,
63
64    /// Right front vertical height (Rv).
65    TopFrontRight = 18,
66
67    /// Centre front vertical height (Cv).
68    TopFrontCenter = 19,
69
70    /// Left surround vertical height rear (Lvr).
71    TopRearLeft = 20,
72
73    /// Right surround vertical height rear (Rvr).
74    TopRearRight = 21,
75
76    /// Centre vertical height rear (Cvr).
77    TopRearCenter = 22,
78
79    /// Left vertical height side surround (Lvss).
80    TopSideLeft = 23,
81
82    /// Right vertical height side surround (Rvss).
83    TopSideRight = 24,
84
85    /// Top centre surround (Ts).
86    TopCenter = 25,
87
88    /// Low frequency enhancement 2 (LFE2).
89    Lfe2 = 26,
90
91    /// Left front vertical bottom (Lb).
92    BottomFrontLeft = 27,
93
94    /// Right front vertical bottom (Rb).
95    BottomFrontRight = 28,
96
97    /// Centre front vertical bottom (Cb).
98    BottomFrontCenter = 29,
99
100    /// Left vertical height surround (Lvs).
101    TopSurroundLeft = 30,
102
103    /// Right vertical height surround (Rvs).
104    TopSurroundRight = 31,
105
106    // 32-35: reserved
107    /// Low frequency enhancement 3 (LFE3).
108    Lfe3 = 36,
109
110    /// Left edge of screen (Leos).
111    Leos = 37,
112
113    /// Right edge of screen (Reos).
114    Reos = 38,
115
116    /// Half-way between centre of screen and left edge of screen (Hwbcal).
117    Hwbcal = 39,
118
119    /// Half-way between centre of screen and right edge of screen (Hwbcar).
120    Hwbcar = 40,
121
122    /// Left back surround (Lbs).
123    Lbs = 41,
124
125    /// Right back surround (Rbs).
126    Rbs = 42,
127
128    /// Left ear (Lear).
129    ///
130    /// Audio signals associated with this loudspeaker position are intended for
131    /// stereo headphone playback only. They can be unsuitable for loudspeaker
132    /// playback. This loudspeaker position is applicable for binaural signals
133    /// but it shall not be applied for traditional stereo signals.
134    LeftEar = 43,
135
136    /// Right ear (Rear).
137    ///
138    /// Audio signals associated with this loudspeaker position are intended for
139    /// stereo headphone playback only. They can be unsuitable for loudspeaker
140    /// playback. This loudspeaker position is applicable for binaural signals
141    /// but it shall not be applied for traditional stereo signals.
142    RightEar = 44,
143
144    // 45-125: reserved
145    // ExplicitPosition is handled separately with SpeakerPosition::Standard.
146    // ExplicitPosition = 126, // Followed by azimuth (i16) and elevation (i8)
147    /// Unknown/undefined position (unpositioned).
148    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
201/// Pre-defined channel layouts.
202///
203/// Consistent with ISO/IEC 23091-3:2018/Amd. 1:2022(E) Table 3 changes
204const CHANNEL_LAYOUTS: &[&[AudioChannelPosition]] = &[
205    // 0
206    &[],
207    // 1
208    &[AudioChannelPosition::FrontCenter],
209    // 2
210    &[
211        AudioChannelPosition::FrontLeft,
212        AudioChannelPosition::FrontRight,
213    ],
214    // 3
215    &[
216        AudioChannelPosition::FrontCenter,
217        AudioChannelPosition::FrontLeft,
218        AudioChannelPosition::FrontRight,
219    ],
220    // 4
221    &[
222        AudioChannelPosition::FrontCenter,
223        AudioChannelPosition::FrontLeft,
224        AudioChannelPosition::FrontRight,
225        AudioChannelPosition::RearCenter,
226    ],
227    // 5
228    &[
229        AudioChannelPosition::FrontCenter,
230        AudioChannelPosition::FrontLeft,
231        AudioChannelPosition::FrontRight,
232        AudioChannelPosition::LeftSurround,
233        AudioChannelPosition::RightSurround,
234    ],
235    // 6
236    &[
237        AudioChannelPosition::FrontCenter,
238        AudioChannelPosition::FrontLeft,
239        AudioChannelPosition::FrontRight,
240        AudioChannelPosition::LeftSurround,
241        AudioChannelPosition::RightSurround,
242        AudioChannelPosition::Lfe1,
243    ],
244    // 7
245    &[
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    // 8
256    &[],
257    // 9
258    &[
259        AudioChannelPosition::FrontLeft,
260        AudioChannelPosition::FrontRight,
261        AudioChannelPosition::RearCenter,
262    ],
263    // 10
264    &[
265        AudioChannelPosition::FrontLeft,
266        AudioChannelPosition::FrontRight,
267        AudioChannelPosition::LeftSurround,
268        AudioChannelPosition::RightSurround,
269    ],
270    // 11
271    &[
272        AudioChannelPosition::FrontCenter,
273        AudioChannelPosition::FrontLeft,
274        AudioChannelPosition::FrontRight,
275        AudioChannelPosition::LeftSurround,
276        AudioChannelPosition::RightSurround,
277        AudioChannelPosition::RearCenter,
278        AudioChannelPosition::Lfe1,
279    ],
280    // 12
281    &[
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    // 13
292    &[
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    // 14
319    &[
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    // 15
330    &[
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    // 16
345    &[
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    // 17
358    &[
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    // 18
373    &[
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    // 19
390    &[
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    // 20
405    &[
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    // 21
422    &[
423        AudioChannelPosition::LeftEar,
424        AudioChannelPosition::RightEar,
425    ],
426    // 22 to 63 reserved
427];
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            // Explicit position
495            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            // Explicit positions
545            let mut positions = Vec::new();
546
547            match channel_count {
548                // When channel count is known, read exactly that many positions
549                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                // Ideally the channel layout box will be decoded along
556                // with the audio sample entry which should call the
557                // decode_body_with_channel_count variant. So we should
558                // not be here except for the synthetic test cases below.
559                None => {
560                    // Workaround: When channel count is unknown, read until
561                    // end of buffer.
562                    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            // Pre-defined layout with omitted channels map
572            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            // Explicit positions with explicit channel count
586            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            // Pre-defined layout
596            let byte = u8::decode(buf)?;
597            let channel_order_definition = (byte >> 1) & 0x07;
598            let omitted_channels_present = (byte & 0x01) != 0;
599
600            // ISO/IEC 14496-12:2022 Section 12.2.4.3
601            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        // ISO/IEC 14496-12:2022 Section 12.2.4.3
624        // objectCount = baseChannelCount - channel count of channel structure.
625        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            // ISO/IEC 14496-12:2022 Section 12.2.4.3
637            // objectCount = baseChannelCount - channel count of channel structure.
638            .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)?; // defined_layout = 0
654
655                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)?; // defined_layout = 0
693                (positions.len() as u8).encode(buf)?; // layout_channel_count
694
695                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        // ISO/IEC 14496-12:2022 Section 12.2.4.3
768        // objectCount = baseChannelCount - channel count of channel structure.
769        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    // Allow Pcm box to decode the channel layout by using the channel
795    // count information from audio sample entry when available.
796    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
813// ISO/IEC 14496-12:2022 Section 12.2.4
814impl 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        // Determine version based on presence of v1-specific fields
828        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                // ISO/IEC 14496-12:2022 Section 12.2.4.3
859                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        // Skip the atom header (4 bytes: size + 4 bytes: fourcc)
960        // but keep the FullBox header (4 bytes: version + flags) and body
961        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), // Omit bit 5
996                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}