Skip to main content

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