mirror of
https://github.com/alfg/mp4-rust.git
synced 2025-01-23 01:58:07 +00:00
remove more calls to unwrap.
This commit is contained in:
parent
0fdd2d16b4
commit
12dac2e0ee
10 changed files with 98 additions and 82 deletions
|
@ -26,4 +26,6 @@ pub enum Error {
|
||||||
EntryInTrunNotFound(u32, BoxType, u32),
|
EntryInTrunNotFound(u32, BoxType, u32),
|
||||||
#[error("{0} version {1} is not supported")]
|
#[error("{0} version {1} is not supported")]
|
||||||
UnsupportedBoxVersion(BoxType, u8),
|
UnsupportedBoxVersion(BoxType, u8),
|
||||||
|
#[error("{0}")]
|
||||||
|
GenericError(String),
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,15 +64,9 @@ impl<R: Read + Seek> ReadBox<&mut R> for DinfBox {
|
||||||
current = reader.stream_position()?;
|
current = reader.stream_position()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if dref.is_none() {
|
let dref = dref.ok_or(Error::BoxNotFound(BoxType::DrefBox))?;
|
||||||
return Err(Error::BoxNotFound(BoxType::DrefBox));
|
|
||||||
}
|
|
||||||
|
|
||||||
skip_bytes_to(reader, start + size)?;
|
skip_bytes_to(reader, start + size)?;
|
||||||
|
Ok(DinfBox { dref })
|
||||||
Ok(DinfBox {
|
|
||||||
dref: dref.unwrap(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -127,13 +127,17 @@ impl<W: Write> WriteBox<&mut W> for EmsgBox {
|
||||||
write_null_terminated_str(writer, &self.scheme_id_uri)?;
|
write_null_terminated_str(writer, &self.scheme_id_uri)?;
|
||||||
write_null_terminated_str(writer, &self.value)?;
|
write_null_terminated_str(writer, &self.value)?;
|
||||||
writer.write_u32::<BigEndian>(self.timescale)?;
|
writer.write_u32::<BigEndian>(self.timescale)?;
|
||||||
writer.write_u32::<BigEndian>(self.presentation_time_delta.unwrap())?;
|
writer.write_u32::<BigEndian>(self.presentation_time_delta.ok_or(
|
||||||
|
crate::error::Error::InvalidData("presentation_time_delta not found"),
|
||||||
|
)?)?;
|
||||||
writer.write_u32::<BigEndian>(self.event_duration)?;
|
writer.write_u32::<BigEndian>(self.event_duration)?;
|
||||||
writer.write_u32::<BigEndian>(self.id)?;
|
writer.write_u32::<BigEndian>(self.id)?;
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
writer.write_u32::<BigEndian>(self.timescale)?;
|
writer.write_u32::<BigEndian>(self.timescale)?;
|
||||||
writer.write_u64::<BigEndian>(self.presentation_time.unwrap())?;
|
writer.write_u64::<BigEndian>(self.presentation_time.ok_or(
|
||||||
|
crate::error::Error::InvalidData("presentation_time not found"),
|
||||||
|
)?)?;
|
||||||
writer.write_u32::<BigEndian>(self.event_duration)?;
|
writer.write_u32::<BigEndian>(self.event_duration)?;
|
||||||
writer.write_u32::<BigEndian>(self.id)?;
|
writer.write_u32::<BigEndian>(self.id)?;
|
||||||
write_null_terminated_str(writer, &self.scheme_id_uri)?;
|
write_null_terminated_str(writer, &self.scheme_id_uri)?;
|
||||||
|
|
|
@ -149,15 +149,9 @@ impl<R: Read + Seek> ReadBox<&mut R> for IlstItemBox {
|
||||||
current = reader.stream_position()?;
|
current = reader.stream_position()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if data.is_none() {
|
let data = data.ok_or(Error::BoxNotFound(BoxType::DataBox))?;
|
||||||
return Err(Error::BoxNotFound(BoxType::DataBox));
|
|
||||||
}
|
|
||||||
|
|
||||||
skip_bytes_to(reader, start + size)?;
|
skip_bytes_to(reader, start + size)?;
|
||||||
|
Ok(IlstItemBox { data })
|
||||||
Ok(IlstItemBox {
|
|
||||||
data: data.unwrap(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,23 +75,13 @@ impl<R: Read + Seek> ReadBox<&mut R> for MdiaBox {
|
||||||
current = reader.stream_position()?;
|
current = reader.stream_position()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if mdhd.is_none() {
|
let mdhd = mdhd.ok_or(Error::BoxNotFound(BoxType::MdhdBox))?;
|
||||||
return Err(Error::BoxNotFound(BoxType::MdhdBox));
|
let hdlr = hdlr.ok_or(Error::BoxNotFound(BoxType::HdlrBox))?;
|
||||||
}
|
let minf = minf.ok_or(Error::BoxNotFound(BoxType::MinfBox))?;
|
||||||
if hdlr.is_none() {
|
|
||||||
return Err(Error::BoxNotFound(BoxType::HdlrBox));
|
|
||||||
}
|
|
||||||
if minf.is_none() {
|
|
||||||
return Err(Error::BoxNotFound(BoxType::MinfBox));
|
|
||||||
}
|
|
||||||
|
|
||||||
skip_bytes_to(reader, start + size)?;
|
skip_bytes_to(reader, start + size)?;
|
||||||
|
|
||||||
Ok(MdiaBox {
|
Ok(MdiaBox { mdhd, hdlr, minf })
|
||||||
mdhd: mdhd.unwrap(),
|
|
||||||
hdlr: hdlr.unwrap(),
|
|
||||||
minf: minf.unwrap(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,20 +93,16 @@ impl<R: Read + Seek> ReadBox<&mut R> for MinfBox {
|
||||||
current = reader.stream_position()?;
|
current = reader.stream_position()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if dinf.is_none() {
|
let dinf = dinf.ok_or(Error::BoxNotFound(BoxType::DinfBox))?;
|
||||||
return Err(Error::BoxNotFound(BoxType::DinfBox));
|
let stbl = stbl.ok_or(Error::BoxNotFound(BoxType::StblBox))?;
|
||||||
}
|
|
||||||
if stbl.is_none() {
|
|
||||||
return Err(Error::BoxNotFound(BoxType::StblBox));
|
|
||||||
}
|
|
||||||
|
|
||||||
skip_bytes_to(reader, start + size)?;
|
skip_bytes_to(reader, start + size)?;
|
||||||
|
|
||||||
Ok(MinfBox {
|
Ok(MinfBox {
|
||||||
vmhd,
|
vmhd,
|
||||||
smhd,
|
smhd,
|
||||||
dinf: dinf.unwrap(),
|
dinf,
|
||||||
stbl: stbl.unwrap(),
|
stbl,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -242,11 +242,15 @@ impl BoxHeader {
|
||||||
reader.read_exact(&mut buf)?;
|
reader.read_exact(&mut buf)?;
|
||||||
|
|
||||||
// Get size.
|
// Get size.
|
||||||
let s = buf[0..4].try_into().unwrap();
|
let s = buf[0..4]
|
||||||
|
.try_into()
|
||||||
|
.map_err(|_e| crate::error::Error::InvalidData("could not get slice"))?;
|
||||||
let size = u32::from_be_bytes(s);
|
let size = u32::from_be_bytes(s);
|
||||||
|
|
||||||
// Get box type string.
|
// Get box type string.
|
||||||
let t = buf[4..8].try_into().unwrap();
|
let t = buf[4..8]
|
||||||
|
.try_into()
|
||||||
|
.map_err(|_e| crate::error::Error::InvalidData("could not get slice"))?;
|
||||||
let typ = u32::from_be_bytes(t);
|
let typ = u32::from_be_bytes(t);
|
||||||
|
|
||||||
// Get largesize if size is 1
|
// Get largesize if size is 1
|
||||||
|
|
|
@ -76,16 +76,9 @@ impl<R: Read + Seek> ReadBox<&mut R> for MoofBox {
|
||||||
current = reader.stream_position()?;
|
current = reader.stream_position()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if mfhd.is_none() {
|
let mfhd = mfhd.ok_or(Error::BoxNotFound(BoxType::MfhdBox))?;
|
||||||
return Err(Error::BoxNotFound(BoxType::MfhdBox));
|
|
||||||
}
|
|
||||||
|
|
||||||
skip_bytes_to(reader, start + size)?;
|
skip_bytes_to(reader, start + size)?;
|
||||||
|
Ok(MoofBox { mfhd, trafs })
|
||||||
Ok(MoofBox {
|
|
||||||
mfhd: mfhd.unwrap(),
|
|
||||||
trafs,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -105,14 +105,10 @@ impl<R: Read + Seek> ReadBox<&mut R> for MoovBox {
|
||||||
current = reader.stream_position()?;
|
current = reader.stream_position()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if mvhd.is_none() {
|
let mvhd = mvhd.ok_or(Error::BoxNotFound(BoxType::MvhdBox))?;
|
||||||
return Err(Error::BoxNotFound(BoxType::MvhdBox));
|
|
||||||
}
|
|
||||||
|
|
||||||
skip_bytes_to(reader, start + size)?;
|
skip_bytes_to(reader, start + size)?;
|
||||||
|
|
||||||
Ok(MoovBox {
|
Ok(MoovBox {
|
||||||
mvhd: mvhd.unwrap(),
|
mvhd,
|
||||||
meta,
|
meta,
|
||||||
udta,
|
udta,
|
||||||
mvex,
|
mvex,
|
||||||
|
|
93
src/track.rs
93
src/track.rs
|
@ -343,7 +343,10 @@ impl Mp4Track {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ctts_index(&self, sample_id: u32) -> Result<(usize, u32)> {
|
fn ctts_index(&self, sample_id: u32) -> Result<(usize, u32)> {
|
||||||
let ctts = self.trak.mdia.minf.stbl.ctts.as_ref().unwrap();
|
let ctts = self.trak.mdia.minf.stbl.ctts.as_ref().ok_or(
|
||||||
|
// todo: is this the correct error to return here?
|
||||||
|
crate::error::Error::BoxNotFound(BoxType::CttsBox),
|
||||||
|
)?;
|
||||||
let mut sample_count: u32 = 1;
|
let mut sample_count: u32 = 1;
|
||||||
for (i, entry) in ctts.entries.iter().enumerate() {
|
for (i, entry) in ctts.entries.iter().enumerate() {
|
||||||
let next_sample_count =
|
let next_sample_count =
|
||||||
|
@ -366,30 +369,36 @@ impl Mp4Track {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// return `(traf_idx, sample_idx_in_trun)`
|
/// return `(traf_idx, sample_idx_in_trun)`
|
||||||
fn find_traf_idx_and_sample_idx(&self, sample_id: u32) -> Option<(usize, usize)> {
|
fn find_traf_idx_and_sample_idx(&self, sample_id: u32) -> Result<Option<(usize, usize)>> {
|
||||||
let global_idx = sample_id - 1;
|
let global_idx = sample_id - 1;
|
||||||
let mut offset = 0;
|
let mut offset = 0;
|
||||||
for traf_idx in 0..self.trafs.len() {
|
for traf_idx in 0..self.trafs.len() {
|
||||||
if let Some(trun) = &self.trafs[traf_idx].trun {
|
if let Some(trun) = &self.trafs[traf_idx].trun {
|
||||||
let sample_count = trun.sample_count;
|
let sample_count = trun.sample_count;
|
||||||
if sample_count > (global_idx - offset) {
|
if sample_count > (global_idx - offset) {
|
||||||
return Some((traf_idx, (global_idx - offset) as _));
|
return Ok(Some((traf_idx, (global_idx - offset) as _)));
|
||||||
}
|
}
|
||||||
offset = offset
|
offset =
|
||||||
.checked_add(sample_count)
|
offset
|
||||||
.expect("attempt to sum trun sample_count with overflow");
|
.checked_add(sample_count)
|
||||||
|
.ok_or(crate::error::Error::InvalidData(
|
||||||
|
"attempt to sum trun sample_count with overflow",
|
||||||
|
))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sample_size(&self, sample_id: u32) -> Result<u32> {
|
fn sample_size(&self, sample_id: u32) -> Result<u32> {
|
||||||
if !self.trafs.is_empty() {
|
if !self.trafs.is_empty() {
|
||||||
if let Some((traf_idx, sample_idx)) = self.find_traf_idx_and_sample_idx(sample_id) {
|
if let Some((traf_idx, sample_idx)) = self.find_traf_idx_and_sample_idx(sample_id)? {
|
||||||
if let Some(size) = self.trafs[traf_idx]
|
if let Some(size) = self.trafs[traf_idx]
|
||||||
.trun
|
.trun
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.ok_or(crate::error::Error::BoxInTrafNotFound(
|
||||||
|
traf_idx as u32,
|
||||||
|
BoxType::TrunBox,
|
||||||
|
))?
|
||||||
.sample_sizes
|
.sample_sizes
|
||||||
.get(sample_idx)
|
.get(sample_idx)
|
||||||
{
|
{
|
||||||
|
@ -436,7 +445,7 @@ impl Mp4Track {
|
||||||
|
|
||||||
fn sample_offset(&self, sample_id: u32) -> Result<u64> {
|
fn sample_offset(&self, sample_id: u32) -> Result<u64> {
|
||||||
if !self.trafs.is_empty() {
|
if !self.trafs.is_empty() {
|
||||||
if let Some((traf_idx, _sample_idx)) = self.find_traf_idx_and_sample_idx(sample_id) {
|
if let Some((traf_idx, _sample_idx)) = self.find_traf_idx_and_sample_idx(sample_id)? {
|
||||||
Ok(self.trafs[traf_idx].tfhd.base_data_offset.unwrap_or(0))
|
Ok(self.trafs[traf_idx].tfhd.base_data_offset.unwrap_or(0))
|
||||||
} else {
|
} else {
|
||||||
Err(Error::BoxInTrafNotFound(self.track_id(), BoxType::TrafBox))
|
Err(Error::BoxInTrafNotFound(self.track_id(), BoxType::TrafBox))
|
||||||
|
@ -445,7 +454,13 @@ impl Mp4Track {
|
||||||
let stsc_index = self.stsc_index(sample_id)?;
|
let stsc_index = self.stsc_index(sample_id)?;
|
||||||
|
|
||||||
let stsc = &self.trak.mdia.minf.stbl.stsc;
|
let stsc = &self.trak.mdia.minf.stbl.stsc;
|
||||||
let stsc_entry = stsc.entries.get(stsc_index).unwrap();
|
let stsc_entry =
|
||||||
|
stsc.entries
|
||||||
|
.get(stsc_index)
|
||||||
|
.ok_or(crate::error::Error::GenericError(format!(
|
||||||
|
"stsc entry not found for sample_id: {}, stsc_idx: {}",
|
||||||
|
sample_id, stsc_index
|
||||||
|
)))?;
|
||||||
|
|
||||||
let first_chunk = stsc_entry.first_chunk;
|
let first_chunk = stsc_entry.first_chunk;
|
||||||
let first_sample = stsc_entry.first_sample;
|
let first_sample = stsc_entry.first_sample;
|
||||||
|
@ -507,14 +522,19 @@ impl Mp4Track {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sample_rendering_offset(&self, sample_id: u32) -> i32 {
|
fn sample_rendering_offset(&self, sample_id: u32) -> Result<i32> {
|
||||||
if let Some(ref ctts) = self.trak.mdia.minf.stbl.ctts {
|
if let Some(ref ctts) = self.trak.mdia.minf.stbl.ctts {
|
||||||
if let Ok((ctts_index, _)) = self.ctts_index(sample_id) {
|
if let Ok((ctts_index, _)) = self.ctts_index(sample_id) {
|
||||||
let ctts_entry = ctts.entries.get(ctts_index).unwrap();
|
let ctts_entry =
|
||||||
return ctts_entry.sample_offset;
|
ctts.entries
|
||||||
|
.get(ctts_index)
|
||||||
|
.ok_or(crate::error::Error::InvalidData(
|
||||||
|
"ctts not found after ctts_index was returned",
|
||||||
|
))?;
|
||||||
|
return Ok(ctts_entry.sample_offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
0
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_sync_sample(&self, sample_id: u32) -> bool {
|
fn is_sync_sample(&self, sample_id: u32) -> bool {
|
||||||
|
@ -550,8 +570,8 @@ impl Mp4Track {
|
||||||
reader.seek(SeekFrom::Start(sample_offset))?;
|
reader.seek(SeekFrom::Start(sample_offset))?;
|
||||||
reader.read_exact(&mut buffer)?;
|
reader.read_exact(&mut buffer)?;
|
||||||
|
|
||||||
let (start_time, duration) = self.sample_time(sample_id).unwrap(); // XXX
|
let (start_time, duration) = self.sample_time(sample_id)?; // XXX
|
||||||
let rendering_offset = self.sample_rendering_offset(sample_id);
|
let rendering_offset = self.sample_rendering_offset(sample_id)?;
|
||||||
let is_sync = self.is_sync_sample(sample_id);
|
let is_sync = self.is_sync_sample(sample_id);
|
||||||
|
|
||||||
Ok(Some(Mp4Sample {
|
Ok(Some(Mp4Sample {
|
||||||
|
@ -780,9 +800,16 @@ impl Mp4TrackWriter {
|
||||||
Ok(self.trak.tkhd.duration)
|
Ok(self.trak.tkhd.duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn chunk_count(&self) -> u32 {
|
fn chunk_count(&self) -> Result<u32> {
|
||||||
let co64 = self.trak.mdia.minf.stbl.co64.as_ref().unwrap();
|
let co64 = self
|
||||||
co64.entries.len() as u32
|
.trak
|
||||||
|
.mdia
|
||||||
|
.minf
|
||||||
|
.stbl
|
||||||
|
.co64
|
||||||
|
.as_ref()
|
||||||
|
.ok_or(crate::error::Error::BoxNotFound(BoxType::Co64Box))?;
|
||||||
|
Ok(co64.entries.len() as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_sample_to_chunk(&mut self, chunk_id: u32) {
|
fn update_sample_to_chunk(&mut self, chunk_id: u32) {
|
||||||
|
@ -801,9 +828,17 @@ impl Mp4TrackWriter {
|
||||||
self.trak.mdia.minf.stbl.stsc.entries.push(entry);
|
self.trak.mdia.minf.stbl.stsc.entries.push(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_chunk_offsets(&mut self, offset: u64) {
|
fn update_chunk_offsets(&mut self, offset: u64) -> Result<()> {
|
||||||
let co64 = self.trak.mdia.minf.stbl.co64.as_mut().unwrap();
|
let co64 = self
|
||||||
|
.trak
|
||||||
|
.mdia
|
||||||
|
.minf
|
||||||
|
.stbl
|
||||||
|
.co64
|
||||||
|
.as_mut()
|
||||||
|
.ok_or(crate::error::Error::BoxNotFound(BoxType::Co64Box))?;
|
||||||
co64.entries.push(offset);
|
co64.entries.push(offset);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_chunk<W: Write + Seek>(&mut self, writer: &mut W) -> Result<()> {
|
fn write_chunk<W: Write + Seek>(&mut self, writer: &mut W) -> Result<()> {
|
||||||
|
@ -814,8 +849,8 @@ impl Mp4TrackWriter {
|
||||||
|
|
||||||
writer.write_all(&self.chunk_buffer)?;
|
writer.write_all(&self.chunk_buffer)?;
|
||||||
|
|
||||||
self.update_sample_to_chunk(self.chunk_count() + 1);
|
self.update_sample_to_chunk(self.chunk_count()? + 1);
|
||||||
self.update_chunk_offsets(chunk_offset);
|
self.update_chunk_offsets(chunk_offset)?;
|
||||||
|
|
||||||
self.chunk_buffer.clear();
|
self.chunk_buffer.clear();
|
||||||
self.chunk_samples = 0;
|
self.chunk_samples = 0;
|
||||||
|
@ -848,7 +883,15 @@ impl Mp4TrackWriter {
|
||||||
// mp4a.esds.es_desc.dec_config.max_bitrate
|
// mp4a.esds.es_desc.dec_config.max_bitrate
|
||||||
// mp4a.esds.es_desc.dec_config.avg_bitrate
|
// mp4a.esds.es_desc.dec_config.avg_bitrate
|
||||||
}
|
}
|
||||||
if let Ok(stco) = StcoBox::try_from(self.trak.mdia.minf.stbl.co64.as_ref().unwrap()) {
|
if let Ok(stco) = StcoBox::try_from(
|
||||||
|
self.trak
|
||||||
|
.mdia
|
||||||
|
.minf
|
||||||
|
.stbl
|
||||||
|
.co64
|
||||||
|
.as_ref()
|
||||||
|
.ok_or(crate::error::Error::BoxNotFound(BoxType::Co64Box))?,
|
||||||
|
) {
|
||||||
self.trak.mdia.minf.stbl.stco = Some(stco);
|
self.trak.mdia.minf.stbl.stco = Some(stco);
|
||||||
self.trak.mdia.minf.stbl.co64 = None;
|
self.trak.mdia.minf.stbl.co64 = None;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue