Skip to main content

pito_codecs/opus/
packet.rs

1use crate::media::Error;
2
3#[derive(Clone, Copy, Debug, PartialEq, Eq)]
4pub enum Mode {
5    SilkOnly,
6    Hybrid,
7    CeltOnly,
8}
9
10#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
11pub enum Bandwidth {
12    Narrowband,
13    Mediumband,
14    Wideband,
15    SuperWideband,
16    Fullband,
17}
18
19impl Bandwidth {
20    pub fn celt_end_band(self) -> usize {
21        match self {
22            Bandwidth::Narrowband => 13,
23            Bandwidth::Mediumband | Bandwidth::Wideband => 17,
24            Bandwidth::SuperWideband => 19,
25            Bandwidth::Fullband => 21,
26        }
27    }
28}
29
30#[derive(Clone, Copy, Debug, PartialEq, Eq)]
31pub struct Toc {
32    pub config: u8,
33    pub mode: Mode,
34    pub bandwidth: Bandwidth,
35    pub stereo: bool,
36    pub code: u8,
37}
38
39impl Toc {
40    pub fn parse(b: u8) -> Toc {
41        let config = b >> 3;
42        let (mode, bandwidth) = match config {
43            0..=3 => (Mode::SilkOnly, Bandwidth::Narrowband),
44            4..=7 => (Mode::SilkOnly, Bandwidth::Mediumband),
45            8..=11 => (Mode::SilkOnly, Bandwidth::Wideband),
46            12..=13 => (Mode::Hybrid, Bandwidth::SuperWideband),
47            14..=15 => (Mode::Hybrid, Bandwidth::Fullband),
48            16..=19 => (Mode::CeltOnly, Bandwidth::Narrowband),
49            20..=23 => (Mode::CeltOnly, Bandwidth::Wideband),
50            24..=27 => (Mode::CeltOnly, Bandwidth::SuperWideband),
51            _ => (Mode::CeltOnly, Bandwidth::Fullband),
52        };
53        Toc {
54            config,
55            mode,
56            bandwidth,
57            stereo: b & 4 != 0,
58            code: b & 3,
59        }
60    }
61
62    pub fn frame_samples_48k(&self) -> usize {
63        self.frame_samples(48000)
64    }
65
66    pub fn frame_samples(&self, rate: u32) -> usize {
67        let rate = rate as usize;
68        let c = self.config as usize;
69        match self.mode {
70            Mode::CeltOnly => (rate << (c & 3)) / 400,
71            Mode::Hybrid => {
72                if c & 1 != 0 {
73                    rate / 50
74                } else {
75                    rate / 100
76                }
77            }
78            Mode::SilkOnly => match c & 3 {
79                3 => rate * 60 / 1000,
80                s => (rate << s) / 100,
81            },
82        }
83    }
84
85    pub fn channels(&self) -> usize {
86        if self.stereo { 2 } else { 1 }
87    }
88}
89
90#[derive(Clone, Debug)]
91pub struct Packet<'a> {
92    pub toc: Toc,
93    pub frames: Vec<&'a [u8]>,
94    pub padding: usize,
95}
96
97fn parse_size(data: &[u8]) -> Option<(usize, usize)> {
98    match data.first() {
99        None => None,
100        Some(&b) if b < 252 => Some((b as usize, 1)),
101        Some(&b) => data.get(1).map(|&b1| (4 * b1 as usize + b as usize, 2)),
102    }
103}
104
105impl<'a> Packet<'a> {
106    pub fn parse(data: &'a [u8]) -> Result<Packet<'a>, Error> {
107        Self::parse_impl(data, false).map(|(p, _)| p)
108    }
109
110    pub fn parse_self_delimited(data: &'a [u8]) -> Result<(Packet<'a>, usize), Error> {
111        Self::parse_impl(data, true)
112    }
113
114    fn parse_impl(data: &'a [u8], self_delimited: bool) -> Result<(Packet<'a>, usize), Error> {
115        let bad = || Error::Invalid("malformed packet framing".into());
116        if data.is_empty() {
117            return Err(Error::Invalid("empty packet".into()));
118        }
119        let toc = Toc::parse(data[0]);
120        let fs = toc.frame_samples_48k();
121        let mut pos = 1usize;
122        let mut len = data.len() as isize - 1;
123        let mut sizes: Vec<isize> = Vec::new();
124        let mut padding = 0usize;
125        let mut cbr = false;
126        let count;
127        let mut last_size = len;
128        let read_size = |pos: &mut usize, len: &mut isize| -> Result<isize, Error> {
129            let avail = &data[*pos..(*pos + (*len).max(0) as usize).min(data.len())];
130            let (s, n) = parse_size(avail).ok_or_else(bad)?;
131            *pos += n;
132            *len -= n as isize;
133            Ok(s as isize)
134        };
135        match toc.code {
136            0 => count = 1,
137            1 => {
138                count = 2;
139                cbr = true;
140                if !self_delimited {
141                    if len & 1 != 0 {
142                        return Err(bad());
143                    }
144                    last_size = len / 2;
145                    sizes.push(last_size);
146                }
147            }
148            2 => {
149                count = 2;
150                let s0 = read_size(&mut pos, &mut len)?;
151                if s0 > len {
152                    return Err(bad());
153                }
154                sizes.push(s0);
155                last_size = len - s0;
156            }
157            _ => {
158                if len < 1 {
159                    return Err(bad());
160                }
161                let ch = data[pos];
162                pos += 1;
163                len -= 1;
164                count = (ch & 0x3F) as usize;
165                if count == 0 || fs * count > 5760 {
166                    return Err(bad());
167                }
168                if ch & 0x40 != 0 {
169                    loop {
170                        if len <= 0 {
171                            return Err(bad());
172                        }
173                        let b = data[pos];
174                        pos += 1;
175                        len -= 1;
176                        let tmp = if b == 255 { 254 } else { b as isize };
177                        len -= tmp;
178                        padding += tmp as usize;
179                        if b != 255 {
180                            break;
181                        }
182                    }
183                }
184                if len < 0 {
185                    return Err(bad());
186                }
187                cbr = ch & 0x80 == 0;
188                if !cbr {
189                    last_size = len;
190                    for _ in 0..count - 1 {
191                        let before = len;
192                        let s = read_size(&mut pos, &mut len)?;
193                        if s > len {
194                            return Err(bad());
195                        }
196                        sizes.push(s);
197                        last_size -= (before - len) + s;
198                    }
199                    if last_size < 0 {
200                        return Err(bad());
201                    }
202                } else if !self_delimited {
203                    last_size = len / count as isize;
204                    if last_size * count as isize != len {
205                        return Err(bad());
206                    }
207                    for _ in 0..count - 1 {
208                        sizes.push(last_size);
209                    }
210                }
211            }
212        }
213        if self_delimited {
214            let before = len;
215            let s = read_size(&mut pos, &mut len)?;
216            if s > len {
217                return Err(bad());
218            }
219            if cbr {
220                if s * count as isize > len {
221                    return Err(bad());
222                }
223                sizes = vec![s; count - 1];
224            } else if (before - len) + s > last_size {
225                return Err(bad());
226            }
227            last_size = s;
228        }
229        if last_size > 1275 || sizes.iter().any(|&s| s > 1275) {
230            return Err(bad());
231        }
232        sizes.push(last_size);
233        let mut frames = Vec::with_capacity(count);
234        for &s in &sizes {
235            let s = s as usize;
236            if pos + s > data.len() {
237                return Err(bad());
238            }
239            frames.push(&data[pos..pos + s]);
240            pos += s;
241        }
242        let total = if self_delimited {
243            pos + padding
244        } else {
245            data.len()
246        };
247        if total > data.len() {
248            return Err(bad());
249        }
250        Ok((
251            Packet {
252                toc,
253                frames,
254                padding,
255            },
256            total,
257        ))
258    }
259}
260
261pub fn packet_samples_48k(data: &[u8]) -> Result<usize, Error> {
262    let p = Packet::parse(data)?;
263    Ok(p.toc.frame_samples_48k() * p.frames.len())
264}
265
266#[cfg(test)]
267mod tests {
268    use super::*;
269
270    #[test]
271    fn toc_configs() {
272        for cfg in 0u8..32 {
273            let t = Toc::parse(cfg << 3);
274            let ms10 = t.frame_samples(48000) * 10 / 48;
275            let expect = match cfg {
276                0..=11 => [100, 200, 400, 600][cfg as usize & 3],
277                12..=15 => [100, 200][cfg as usize & 1],
278                _ => [25, 50, 100, 200][cfg as usize & 3],
279            };
280            assert_eq!(ms10, expect, "config {cfg}");
281        }
282        assert!(Toc::parse(0x04).stereo);
283    }
284
285    #[test]
286    fn frame_codes() {
287        let p = Packet::parse(&[0x00, 1, 2, 3]).unwrap();
288        assert_eq!(p.frames, vec![&[1u8, 2, 3][..]]);
289        assert!(Packet::parse(&[0x01, 1, 2, 3]).is_err());
290        let p = Packet::parse(&[0x01, 1, 2, 3, 4]).unwrap();
291        assert_eq!(p.frames.len(), 2);
292        let p = Packet::parse(&[0x02, 1, 9, 8, 7]).unwrap();
293        assert_eq!(p.frames, vec![&[9u8][..], &[8u8, 7][..]]);
294        assert!(Packet::parse(&[0x02, 5, 1]).is_err());
295        let p = Packet::parse(&[0x03, 0x42, 3, 1, 2, 3, 4, 0, 0, 0]).unwrap();
296        assert_eq!(p.frames, vec![&[1u8, 2][..], &[3u8, 4][..]]);
297        assert_eq!(p.padding, 3);
298        let p = Packet::parse(&[0x03, 0x83, 1, 2, 10, 20, 21, 30]).unwrap();
299        assert_eq!(p.frames, vec![&[10u8][..], &[20u8, 21][..], &[30u8][..]]);
300        assert!(Packet::parse(&[0x03 | (3 << 3), 0x03, 0]).is_err());
301        assert!(Packet::parse(&[0x03, 0x00]).is_err());
302        assert!(Packet::parse(&[]).is_err());
303    }
304
305    #[test]
306    fn two_byte_sizes() {
307        let mut pkt = vec![0x02u8, 252, 1];
308        pkt.extend(std::iter::repeat_n(7u8, 256));
309        pkt.extend([1, 2]);
310        let p = Packet::parse(&pkt).unwrap();
311        assert_eq!(p.frames[0].len(), 256);
312        assert_eq!(p.frames[1], &[1, 2]);
313    }
314
315    #[test]
316    fn self_delimited() {
317        let (p, used) = Packet::parse_self_delimited(&[0x00, 2, 5, 6, 0xAA, 0xBB]).unwrap();
318        assert_eq!(p.frames, vec![&[5u8, 6][..]]);
319        assert_eq!(used, 4);
320        let (p, used) = Packet::parse_self_delimited(&[0x01, 1, 5, 6, 9]).unwrap();
321        assert_eq!(p.frames, vec![&[5u8][..], &[6u8][..]]);
322        assert_eq!(used, 4);
323        let (p, used) = Packet::parse_self_delimited(&[0x03, 0x82, 1, 2, 7, 8, 9, 0xFF]).unwrap();
324        assert_eq!(p.frames, vec![&[7u8][..], &[8u8, 9][..]]);
325        assert_eq!(used, 7);
326    }
327}