1
0
Fork 0
mirror of https://github.com/alfg/mp4-rust.git synced 2024-06-11 09:29:21 +00:00

feat(opus): add opus to StsdBox and implement read/write

This commit is contained in:
Stuart Woodbury 2023-07-13 11:04:43 -04:00
parent 09343a20ee
commit c84183a942
2 changed files with 83 additions and 6 deletions

View file

@ -38,6 +38,38 @@ impl Mp4Box for OpusBox {
}
}
impl<R: Read + Seek> ReadBox<&mut R> for OpusBox {
fn read_box(reader: &mut R, size: u64) -> Result<Self> {
box_start(reader)?;
reader.read_u32::<BigEndian>()?; // reserved
reader.read_u16::<BigEndian>()?; // reserved
let data_reference_index = reader.read_u16::<BigEndian>()?;
reader.read_u64::<BigEndian>()?; // reserved
let channelcount = reader.read_u16::<BigEndian>()?;
let samplesize = reader.read_u16::<BigEndian>()?;
reader.read_u32::<BigEndian>()?; // reserved
let samplerate = reader.read_u32::<BigEndian>()?;
let num_read = 36;
if num_read > size {
return Err(Error::InvalidData("opus box is too small"));
}
let remaining = num_read.saturating_sub(size);
// todo: if the size of DopsBox becomes variable, then the size of
// OpusBox will be needed to determine what size to pass to DopsBox::read_box()
let dops = DopsBox::read_box(reader, remaining)?;
Ok(Self {
data_reference_index,
channelcount,
samplesize,
samplerate: FixedPointU16::new_raw(samplerate),
dops,
})
}
}
impl<W: Write> WriteBox<&mut W> for OpusBox {
fn write_box(&self, writer: &mut W) -> Result<u64> {
let mut written = 0;
@ -50,12 +82,8 @@ impl<W: Write> WriteBox<&mut W> for OpusBox {
writer.write_u16::<BigEndian>(self.data_reference_index)?;
written += 2;
writer.write_u16::<BigEndian>(0)?; // reserved
written += 2;
writer.write_u16::<BigEndian>(0)?; // reserved
written += 2;
writer.write_u32::<BigEndian>(0)?; // reserved
written += 4;
writer.write_u64::<BigEndian>(0)?; // reserved
written += 8;
writer.write_u16::<BigEndian>(self.channelcount)?;
written += 2;
writer.write_u16::<BigEndian>(self.samplesize)?;
@ -102,6 +130,33 @@ impl Mp4Box for DopsBox {
}
}
impl<R: Read + Seek> ReadBox<&mut R> for DopsBox {
fn read_box(reader: &mut R, size: u64) -> Result<Self> {
if size < 19 {
return Err(Error::InvalidData("Dops box size too small"));
}
box_start(reader)?;
let version = reader.read_u8()?;
let num_channels = reader.read_u8()?;
let pre_skip = reader.read_u16::<BigEndian>()?;
let input_sample_rate = reader.read_u32::<BigEndian>()?;
let output_gain = reader.read_i16::<BigEndian>()?;
// todo: should this be used?
let _channel_mapping_family = reader.read_u8()?;
Ok(DopsBox {
version,
pre_skip,
input_sample_rate,
output_gain,
channel_mapping_family: ChannelMappingFamily::Family0 {
stereo: num_channels == 2,
},
})
}
}
// https://github.com/Wicpar/async-mp4/blob/master/src/mp4box/dops.rs
impl<W: Write> WriteBox<&mut W> for DopsBox {
fn write_box(&self, writer: &mut W) -> Result<u64> {

View file

@ -25,8 +25,21 @@ pub struct StsdBox {
#[serde(skip_serializing_if = "Option::is_none")]
pub tx3g: Option<Tx3gBox>,
#[serde(skip_serializing_if = "Option::is_none")]
pub opus: Option<OpusBox>,
}
// todo: all the Options in StsdBox may be better as an enumeration
// pub enum StsdChildBox {
// Avc1(Avc1Box),
// Hev1(Hev1Box),
// Vp09(Vp09Box),
// Mp4a(Mp4aBox),
// Tx3g(Tx3gBox),
// Opus(OpusBox),
// }
impl StsdBox {
pub fn get_type(&self) -> BoxType {
BoxType::StsdBox
@ -44,6 +57,8 @@ impl StsdBox {
size += mp4a.box_size();
} else if let Some(ref tx3g) = self.tx3g {
size += tx3g.box_size();
} else if let Some(ref opus) = self.opus {
size += opus.box_size();
}
size
}
@ -81,6 +96,7 @@ impl<R: Read + Seek> ReadBox<&mut R> for StsdBox {
let mut vp09 = None;
let mut mp4a = None;
let mut tx3g = None;
let mut opus = None;
// Get box header.
let header = BoxHeader::read(reader)?;
@ -107,6 +123,9 @@ impl<R: Read + Seek> ReadBox<&mut R> for StsdBox {
BoxType::Tx3gBox => {
tx3g = Some(Tx3gBox::read_box(reader, s)?);
}
BoxType::OpusBox => {
opus = Some(OpusBox::read_box(reader, s)?);
}
_ => {}
}
@ -120,6 +139,7 @@ impl<R: Read + Seek> ReadBox<&mut R> for StsdBox {
vp09,
mp4a,
tx3g,
opus,
})
}
}
@ -143,6 +163,8 @@ impl<W: Write> WriteBox<&mut W> for StsdBox {
mp4a.write_box(writer)?;
} else if let Some(ref tx3g) = self.tx3g {
tx3g.write_box(writer)?;
} else if let Some(ref opus) = self.opus {
opus.write_box(writer)?;
}
Ok(size)