mirror of
https://github.com/alfg/mp4-rust.git
synced 2025-01-03 17:08:40 +00:00
feat(opus): add opus to StsdBox and implement read/write
This commit is contained in:
parent
09343a20ee
commit
c84183a942
2 changed files with 83 additions and 6 deletions
|
@ -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> {
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue