aboutsummaryrefslogtreecommitdiff
path: root/remuxer/src
diff options
context:
space:
mode:
Diffstat (limited to 'remuxer/src')
-rw-r--r--remuxer/src/remux.rs32
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
+}