scuffle_mp4/boxes/types/
opus.rs

1use std::io;
2
3use bytes::{Buf, Bytes};
4
5use super::btrt::Btrt;
6use super::stsd::{AudioSampleEntry, SampleEntry};
7use crate::boxes::DynBox;
8use crate::boxes::header::BoxHeader;
9use crate::boxes::traits::BoxType;
10use crate::codec::AudioCodec;
11
12#[derive(Debug, Clone, PartialEq)]
13/// Opus Audio Sample Entry
14/// Encapsulation of Opus in ISO Base Media File Format - Version 0.8.1
15pub struct Opus {
16    pub header: BoxHeader,
17    pub audio_sample_entry: SampleEntry<AudioSampleEntry>,
18    pub btrt: Option<Btrt>,
19    pub unknown: Vec<DynBox>,
20}
21
22impl Opus {
23    pub fn new(audio_sample_entry: SampleEntry<AudioSampleEntry>, btrt: Option<Btrt>) -> Self {
24        Self {
25            header: BoxHeader::new(Self::NAME),
26            audio_sample_entry,
27            btrt,
28            unknown: Vec::new(),
29        }
30    }
31
32    pub fn codec(&self) -> io::Result<AudioCodec> {
33        Ok(AudioCodec::Opus)
34    }
35}
36
37impl BoxType for Opus {
38    const NAME: [u8; 4] = *b"Opus";
39
40    fn demux(header: BoxHeader, data: Bytes) -> io::Result<Self> {
41        let mut reader = io::Cursor::new(data);
42
43        let audio_sample_entry = SampleEntry::<AudioSampleEntry>::demux(&mut reader)?;
44        let mut btrt = None;
45        let mut unknown = Vec::new();
46
47        while reader.has_remaining() {
48            let dyn_box = DynBox::demux(&mut reader)?;
49            match dyn_box {
50                DynBox::Btrt(btrt_box) => {
51                    btrt = Some(*btrt_box);
52                }
53                _ => {
54                    unknown.push(dyn_box);
55                }
56            }
57        }
58
59        Ok(Self {
60            header,
61            audio_sample_entry,
62            btrt,
63            unknown,
64        })
65    }
66
67    fn primitive_size(&self) -> u64 {
68        self.audio_sample_entry.size()
69            + self.btrt.as_ref().map(|b| b.size()).unwrap_or(0)
70            + self.unknown.iter().map(|b| b.size()).sum::<u64>()
71    }
72
73    fn primitive_mux<T: io::Write>(&self, writer: &mut T) -> io::Result<()> {
74        self.audio_sample_entry.mux(writer)?;
75        if let Some(btrt) = &self.btrt {
76            btrt.mux(writer)?;
77        }
78        for unknown in &self.unknown {
79            unknown.mux(writer)?;
80        }
81        Ok(())
82    }
83}