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