scuffle_mp4/boxes/types/
opus.rs1use 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)]
13pub 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}