diff --git a/src/error.rs b/src/error.rs index 11690f0..a09b982 100644 --- a/src/error.rs +++ b/src/error.rs @@ -26,4 +26,6 @@ pub enum Error { EntryInTrunNotFound(u32, BoxType, u32), #[error("{0} version {1} is not supported")] UnsupportedBoxVersion(BoxType, u8), + #[error("{0}")] + GenericError(String), } diff --git a/src/mp4box/dinf.rs b/src/mp4box/dinf.rs index a6943c7..af6fbc2 100644 --- a/src/mp4box/dinf.rs +++ b/src/mp4box/dinf.rs @@ -64,15 +64,9 @@ impl ReadBox<&mut R> for DinfBox { current = reader.stream_position()?; } - if dref.is_none() { - return Err(Error::BoxNotFound(BoxType::DrefBox)); - } - + let dref = dref.ok_or(Error::BoxNotFound(BoxType::DrefBox))?; skip_bytes_to(reader, start + size)?; - - Ok(DinfBox { - dref: dref.unwrap(), - }) + Ok(DinfBox { dref }) } } diff --git a/src/mp4box/emsg.rs b/src/mp4box/emsg.rs index 921dd4d..1028ed0 100644 --- a/src/mp4box/emsg.rs +++ b/src/mp4box/emsg.rs @@ -127,13 +127,17 @@ impl WriteBox<&mut W> for EmsgBox { write_null_terminated_str(writer, &self.scheme_id_uri)?; write_null_terminated_str(writer, &self.value)?; writer.write_u32::(self.timescale)?; - writer.write_u32::(self.presentation_time_delta.unwrap())?; + writer.write_u32::(self.presentation_time_delta.ok_or( + crate::error::Error::InvalidData("presentation_time_delta not found"), + )?)?; writer.write_u32::(self.event_duration)?; writer.write_u32::(self.id)?; } 1 => { writer.write_u32::(self.timescale)?; - writer.write_u64::(self.presentation_time.unwrap())?; + writer.write_u64::(self.presentation_time.ok_or( + crate::error::Error::InvalidData("presentation_time not found"), + )?)?; writer.write_u32::(self.event_duration)?; writer.write_u32::(self.id)?; write_null_terminated_str(writer, &self.scheme_id_uri)?; diff --git a/src/mp4box/ilst.rs b/src/mp4box/ilst.rs index 9336b90..9be0343 100644 --- a/src/mp4box/ilst.rs +++ b/src/mp4box/ilst.rs @@ -149,15 +149,9 @@ impl ReadBox<&mut R> for IlstItemBox { current = reader.stream_position()?; } - if data.is_none() { - return Err(Error::BoxNotFound(BoxType::DataBox)); - } - + let data = data.ok_or(Error::BoxNotFound(BoxType::DataBox))?; skip_bytes_to(reader, start + size)?; - - Ok(IlstItemBox { - data: data.unwrap(), - }) + Ok(IlstItemBox { data }) } } diff --git a/src/mp4box/mdia.rs b/src/mp4box/mdia.rs index ea4d647..1900916 100644 --- a/src/mp4box/mdia.rs +++ b/src/mp4box/mdia.rs @@ -75,23 +75,13 @@ impl ReadBox<&mut R> for MdiaBox { current = reader.stream_position()?; } - if mdhd.is_none() { - return Err(Error::BoxNotFound(BoxType::MdhdBox)); - } - if hdlr.is_none() { - return Err(Error::BoxNotFound(BoxType::HdlrBox)); - } - if minf.is_none() { - return Err(Error::BoxNotFound(BoxType::MinfBox)); - } + let mdhd = mdhd.ok_or(Error::BoxNotFound(BoxType::MdhdBox))?; + let hdlr = hdlr.ok_or(Error::BoxNotFound(BoxType::HdlrBox))?; + let minf = minf.ok_or(Error::BoxNotFound(BoxType::MinfBox))?; skip_bytes_to(reader, start + size)?; - Ok(MdiaBox { - mdhd: mdhd.unwrap(), - hdlr: hdlr.unwrap(), - minf: minf.unwrap(), - }) + Ok(MdiaBox { mdhd, hdlr, minf }) } } diff --git a/src/mp4box/minf.rs b/src/mp4box/minf.rs index 6eb561f..20d22a0 100644 --- a/src/mp4box/minf.rs +++ b/src/mp4box/minf.rs @@ -93,20 +93,16 @@ impl ReadBox<&mut R> for MinfBox { current = reader.stream_position()?; } - if dinf.is_none() { - return Err(Error::BoxNotFound(BoxType::DinfBox)); - } - if stbl.is_none() { - return Err(Error::BoxNotFound(BoxType::StblBox)); - } + let dinf = dinf.ok_or(Error::BoxNotFound(BoxType::DinfBox))?; + let stbl = stbl.ok_or(Error::BoxNotFound(BoxType::StblBox))?; skip_bytes_to(reader, start + size)?; Ok(MinfBox { vmhd, smhd, - dinf: dinf.unwrap(), - stbl: stbl.unwrap(), + dinf, + stbl, }) } } diff --git a/src/mp4box/mod.rs b/src/mp4box/mod.rs index 19578b1..068f11e 100644 --- a/src/mp4box/mod.rs +++ b/src/mp4box/mod.rs @@ -242,11 +242,15 @@ impl BoxHeader { reader.read_exact(&mut buf)?; // 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); // 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); // Get largesize if size is 1 diff --git a/src/mp4box/moof.rs b/src/mp4box/moof.rs index e90c1f5..c4839a2 100644 --- a/src/mp4box/moof.rs +++ b/src/mp4box/moof.rs @@ -76,16 +76,9 @@ impl ReadBox<&mut R> for MoofBox { current = reader.stream_position()?; } - if mfhd.is_none() { - return Err(Error::BoxNotFound(BoxType::MfhdBox)); - } - + let mfhd = mfhd.ok_or(Error::BoxNotFound(BoxType::MfhdBox))?; skip_bytes_to(reader, start + size)?; - - Ok(MoofBox { - mfhd: mfhd.unwrap(), - trafs, - }) + Ok(MoofBox { mfhd, trafs }) } } diff --git a/src/mp4box/moov.rs b/src/mp4box/moov.rs index 70578d9..00ef2f9 100644 --- a/src/mp4box/moov.rs +++ b/src/mp4box/moov.rs @@ -105,14 +105,10 @@ impl ReadBox<&mut R> for MoovBox { current = reader.stream_position()?; } - if mvhd.is_none() { - return Err(Error::BoxNotFound(BoxType::MvhdBox)); - } - + let mvhd = mvhd.ok_or(Error::BoxNotFound(BoxType::MvhdBox))?; skip_bytes_to(reader, start + size)?; - Ok(MoovBox { - mvhd: mvhd.unwrap(), + mvhd, meta, udta, mvex, diff --git a/src/track.rs b/src/track.rs index 472ca1d..946eba4 100644 --- a/src/track.rs +++ b/src/track.rs @@ -343,7 +343,10 @@ impl Mp4Track { } 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; for (i, entry) in ctts.entries.iter().enumerate() { let next_sample_count = @@ -366,30 +369,36 @@ impl Mp4Track { } /// 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> { let global_idx = sample_id - 1; let mut offset = 0; for traf_idx in 0..self.trafs.len() { if let Some(trun) = &self.trafs[traf_idx].trun { let sample_count = trun.sample_count; 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 - .checked_add(sample_count) - .expect("attempt to sum trun sample_count with overflow"); + offset = + offset + .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 { 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] .trun .as_ref() - .unwrap() + .ok_or(crate::error::Error::BoxInTrafNotFound( + traf_idx as u32, + BoxType::TrunBox, + ))? .sample_sizes .get(sample_idx) { @@ -436,7 +445,7 @@ impl Mp4Track { fn sample_offset(&self, sample_id: u32) -> Result { 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)) } else { Err(Error::BoxInTrafNotFound(self.track_id(), BoxType::TrafBox)) @@ -445,7 +454,13 @@ impl Mp4Track { let stsc_index = self.stsc_index(sample_id)?; 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_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 { if let Some(ref ctts) = self.trak.mdia.minf.stbl.ctts { if let Ok((ctts_index, _)) = self.ctts_index(sample_id) { - let ctts_entry = ctts.entries.get(ctts_index).unwrap(); - return ctts_entry.sample_offset; + let ctts_entry = + 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 { @@ -550,8 +570,8 @@ impl Mp4Track { reader.seek(SeekFrom::Start(sample_offset))?; reader.read_exact(&mut buffer)?; - let (start_time, duration) = self.sample_time(sample_id).unwrap(); // XXX - let rendering_offset = self.sample_rendering_offset(sample_id); + let (start_time, duration) = self.sample_time(sample_id)?; // XXX + let rendering_offset = self.sample_rendering_offset(sample_id)?; let is_sync = self.is_sync_sample(sample_id); Ok(Some(Mp4Sample { @@ -780,9 +800,16 @@ impl Mp4TrackWriter { Ok(self.trak.tkhd.duration) } - fn chunk_count(&self) -> u32 { - let co64 = self.trak.mdia.minf.stbl.co64.as_ref().unwrap(); - co64.entries.len() as u32 + fn chunk_count(&self) -> Result { + let co64 = self + .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) { @@ -801,9 +828,17 @@ impl Mp4TrackWriter { self.trak.mdia.minf.stbl.stsc.entries.push(entry); } - fn update_chunk_offsets(&mut self, offset: u64) { - let co64 = self.trak.mdia.minf.stbl.co64.as_mut().unwrap(); + fn update_chunk_offsets(&mut self, offset: u64) -> Result<()> { + let co64 = self + .trak + .mdia + .minf + .stbl + .co64 + .as_mut() + .ok_or(crate::error::Error::BoxNotFound(BoxType::Co64Box))?; co64.entries.push(offset); + Ok(()) } fn write_chunk(&mut self, writer: &mut W) -> Result<()> { @@ -814,8 +849,8 @@ impl Mp4TrackWriter { writer.write_all(&self.chunk_buffer)?; - self.update_sample_to_chunk(self.chunk_count() + 1); - self.update_chunk_offsets(chunk_offset); + self.update_sample_to_chunk(self.chunk_count()? + 1); + self.update_chunk_offsets(chunk_offset)?; self.chunk_buffer.clear(); self.chunk_samples = 0; @@ -848,7 +883,15 @@ impl Mp4TrackWriter { // mp4a.esds.es_desc.dec_config.max_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.co64 = None; }