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

1use crate::*;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
4#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
5pub struct Opus {
6    pub audio: Audio,
7    pub dops: Dops,
8}
9
10impl Atom for Opus {
11    const KIND: FourCC = FourCC::new(b"Opus");
12
13    fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
14        let audio = Audio::decode(buf)?;
15
16        let mut dops = None;
17
18        // Find esds in mp4a or wave
19        while let Some(atom) = Any::decode_maybe(buf)? {
20            match atom {
21                Any::Dops(atom) => dops = atom.into(),
22                _ => tracing::warn!("unknown atom: {:?}", atom),
23            }
24        }
25
26        Ok(Self {
27            audio,
28            dops: dops.ok_or(Error::MissingBox(Dops::KIND))?,
29        })
30    }
31
32    fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
33        self.audio.encode(buf)?;
34        self.dops.encode(buf)?;
35        Ok(())
36    }
37}
38
39/*
40    class ChannelMappingTable (unsigned int(8) OutputChannelCount){
41        unsigned int(8) StreamCount;
42        unsigned int(8) CoupledCount;
43        unsigned int(8 * OutputChannelCount) ChannelMapping;
44    }
45
46    aligned(8) class OpusSpecificBox extends Box('dOps'){
47        unsigned int(8) Version;
48        unsigned int(8) OutputChannelCount;
49        unsigned int(16) PreSkip;
50        unsigned int(32) InputSampleRate;
51        signed int(16) OutputGain;
52        unsigned int(8) ChannelMappingFamily;
53        if (ChannelMappingFamily != 0) {
54            ChannelMappingTable(OutputChannelCount);
55        }
56    }
57*/
58
59// Opus specific data
60#[derive(Debug, Clone, PartialEq, Eq)]
61#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
62pub struct Dops {
63    pub output_channel_count: u8,
64    pub pre_skip: u16,
65    pub input_sample_rate: u32,
66    pub output_gain: i16,
67}
68
69impl Atom for Dops {
70    const KIND: FourCC = FourCC::new(b"dOps");
71
72    fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
73        let version = u8::decode(buf)?;
74        if version != 0 {
75            return Err(Error::UnknownVersion(version));
76        }
77
78        let output_channel_count = u8::decode(buf)?;
79        let pre_skip = u16::decode(buf)?;
80        let input_sample_rate = u32::decode(buf)?;
81        let output_gain = i16::decode(buf)?;
82
83        let channel_mapping_family = u8::decode(buf)?;
84        if channel_mapping_family != 0 {
85            return Err(Error::Unsupported("OPUS channel mapping"));
86        }
87
88        Ok(Self {
89            output_channel_count,
90            pre_skip,
91            input_sample_rate,
92            output_gain,
93        })
94    }
95
96    fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
97        (0u8).encode(buf)?;
98        self.output_channel_count.encode(buf)?;
99        self.pre_skip.encode(buf)?;
100        self.input_sample_rate.encode(buf)?;
101        self.output_gain.encode(buf)?;
102        (0u8).encode(buf)?;
103
104        Ok(())
105    }
106}