diff options
author | metamuffin <metamuffin@disroot.org> | 2023-12-09 11:36:54 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2023-12-09 11:36:54 +0100 |
commit | 9b1310a6e1a6065c541ad35bdf274f7941a26ef4 (patch) | |
tree | 7c22b53757f39249ab1ea70fddbd5185c269b88d /remuxer/src/remux.rs | |
parent | 2b5cbd8eba60785be55a8ed2b7558feef683e503 (diff) | |
download | jellything-9b1310a6e1a6065c541ad35bdf274f7941a26ef4.tar jellything-9b1310a6e1a6065c541ad35bdf274f7941a26ef4.tar.bz2 jellything-9b1310a6e1a6065c541ad35bdf274f7941a26ef4.tar.zst |
fix panic when seeking into holes
Diffstat (limited to 'remuxer/src/remux.rs')
-rw-r--r-- | remuxer/src/remux.rs | 32 |
1 files changed, 24 insertions, 8 deletions
diff --git a/remuxer/src/remux.rs b/remuxer/src/remux.rs index df4f67d..0e7877d 100644 --- a/remuxer/src/remux.rs +++ b/remuxer/src/remux.rs @@ -28,6 +28,13 @@ use std::{ time::Instant, }; +struct ClusterLayout { + position: usize, + timestamp: u64, + source_offsets: Vec<Option<usize>>, + blocks: Vec<(usize, BlockIndex)>, +} + pub fn remux_stream_into( writer: impl Write, range: Range<usize>, @@ -113,13 +120,6 @@ pub fn remux_stream_into( .collect(); output.write_tag(&MatroskaTag::Tracks(Master::Collected(tracks_header)))?; - struct ClusterLayout { - position: usize, - timestamp: u64, - source_offsets: Vec<Option<usize>>, - blocks: Vec<(usize, BlockIndex)>, - } - let mut segment_layout: Vec<ClusterLayout> = { let mut cluster_pts = 0; let mut clusters = vec![]; @@ -273,7 +273,10 @@ pub fn remux_stream_into( .map(|(i, inp)| { inp.reader .seek( - segment_layout[skip].source_offsets[i].unwrap(), // TODO will crash if there is a "hole" + // the seek target might be a hole; we continue until the next clust of that track. + // this should be fine since tracks are only read according to segment_layout + find_first_cluster_with_off(&segment_layout, skip, i) + .ok_or(anyhow!("cluster hole at eof"))?, MatroskaTag::Cluster(Master::Start), ) .context("seeking in input")?; @@ -325,3 +328,16 @@ pub fn remux_stream_into( output.write_tag(&MatroskaTag::Segment(Master::End))?; Ok(()) } + +fn find_first_cluster_with_off( + segment_layout: &[ClusterLayout], + skip: usize, + track: usize, +) -> Option<usize> { + for skip in skip..segment_layout.len() { + if let Some(off) = segment_layout[skip].source_offsets[track] { + return Some(off); + } + } + None +} |