diff options
Diffstat (limited to 'remuxer')
-rw-r--r-- | remuxer/src/import/mod.rs | 1 | ||||
-rw-r--r-- | remuxer/src/lib.rs | 124 | ||||
-rw-r--r-- | remuxer/src/trim_writer.rs | 7 |
3 files changed, 74 insertions, 58 deletions
diff --git a/remuxer/src/import/mod.rs b/remuxer/src/import/mod.rs index 49a9aa5..2dc2e5a 100644 --- a/remuxer/src/import/mod.rs +++ b/remuxer/src/import/mod.rs @@ -182,6 +182,7 @@ fn import_read_segment( MatroskaTag::BlockGroup(_) => { debug!("group"); let mut children = children.unwrap(); + let mut position = children.position(); while let Some(Ok(Unflat { children: _, item })) = children.n() { match item { MatroskaTag::Block(ref buf) => { diff --git a/remuxer/src/lib.rs b/remuxer/src/lib.rs index 0034cf8..feb4c44 100644 --- a/remuxer/src/lib.rs +++ b/remuxer/src/lib.rs @@ -16,7 +16,7 @@ use jellymatroska::{ write::{vint_length, EbmlWriter}, Master, MatroskaTag, }; -use log::{debug, info, trace}; +use log::{debug, info, trace, warn}; use std::{ fs::File, io::{Seek, SeekFrom, Write}, @@ -52,7 +52,7 @@ impl RemuxerContext { reader: EbmlReader, mapped: u64, index: SeekIndex, - temp_index: usize, + layouting_progress_index: usize, } let timing_cp = Instant::now(); @@ -88,7 +88,7 @@ impl RemuxerContext { reader, info, mapped, - temp_index: 0, + layouting_progress_index: 0, }) }) .collect::<anyhow::Result<Vec<_>>>()?; @@ -145,23 +145,26 @@ impl RemuxerContext { let mut gp = 0usize; // cluster position (in the segment) let mut p = 0usize; // block position (in the cluster) loop { - let mut best_block = BlockIndex { - pts: u64::MAX, - size: 0, - source_off: 0, - }; - let mut best_index = 0; - for (i, r) in inputs.iter().enumerate() { - if let Some(v) = r.index.blocks.get(r.temp_index) { - if v.pts < best_block.pts { - best_block = v.to_owned(); - best_index = i; - } + let (track, block) = { + let mut best_block = BlockIndex { + pts: u64::MAX, + size: 0, + source_off: 0, }; - } - inputs[best_index].temp_index += 1; - source_offsets[best_index].get_or_insert(best_block.source_off); - if best_block.pts > cluster_pts + 2_000 { + let mut best_track = 0; + for (i, r) in inputs.iter().enumerate() { + if let Some(v) = r.index.blocks.get(r.layouting_progress_index) { + if v.pts < best_block.pts { + best_block = v.to_owned(); + best_track = i; + } + }; + } + (best_track, best_block) + }; + inputs[track].layouting_progress_index += 1; + source_offsets[track].get_or_insert(block.source_off); + if block.pts > cluster_pts + 2_000 { let cluster_content_size = 1 + 1 // timestamp {tag, size} + vint_length(cluster_pts) // timestamp tag value + p; @@ -175,21 +178,23 @@ impl RemuxerContext { blocks: std::mem::take(&mut cluster), }); - cluster_pts = best_block.pts; + cluster_pts = block.pts; source_offsets = vec![None; inputs.len()]; gp += cluster_header_size; p = 0; } - if best_block.pts == u64::MAX { + if block.pts == u64::MAX { break; } - p += 1; // simpleblock tag + let simpleblock_size = 1 + 2 + 1 // block {tracknum, pts_off, flags} - // TODO does not work, if more than 127 tracks are present - + best_block.size; // block payload + // TODO does not work, if more than 127 tracks are present + + block.size; // block payload + p += 1; // simpleblock tag p += vint_length(simpleblock_size as u64); // simpleblock size vint p += simpleblock_size; - cluster.push((best_index, best_block)) + + cluster.push((track, block)) } info!("segment layout computed ({} clusters)", clusters.len()); clusters @@ -223,12 +228,12 @@ impl RemuxerContext { let segment_start_position = output.position(); let mut skip = 0; for (i, cluster) in segment_layout.iter().enumerate() { - if (cluster.position + segment_start_position) < range.start { - skip += i; - } else { + if (cluster.position + segment_start_position) > range.start { break; } + skip = i; } + if skip != 0 { info!("skipping {skip} clusters"); output.seek(SeekFrom::Start(segment_layout[skip].position as u64))?; @@ -240,50 +245,57 @@ impl RemuxerContext { mapped: u64, } - // read until start of the segment - let mut ks = vec![]; - for (i, inp) in inputs.iter_mut().enumerate() { - inp.reader - .seek( - segment_layout[skip].source_offsets[i].unwrap(), // TODO will crash if there is a "hole" - MatroskaTag::Cluster(Master::Start), - ) - .context("seeking in input")?; - let mut stream = SegmentExtractIter::new(&mut inp.reader, inp.info.track_number); + let mut track_readers = inputs + .iter_mut() + .enumerate() + .map(|(i, inp)| { + inp.reader + .seek( + segment_layout[skip].source_offsets[i].unwrap(), // TODO will crash if there is a "hole" + MatroskaTag::Cluster(Master::Start), + ) + .context("seeking in input")?; + let mut stream = SegmentExtractIter::new(&mut inp.reader, inp.info.track_number); + + Ok(ReaderD { + mapped: inp.mapped, + peek: Some(stream.next()?), + stream, + }) + }) + .collect::<anyhow::Result<Vec<_>>>()?; - ks.push(ReaderD { - mapped: inp.mapped, - peek: Some(stream.next()?), - stream, - }); - } info!( "(perf) seek inputs: {}ms", (Instant::now() - timing_cp).as_millis() ); for (cluster_index, cluster) in segment_layout.into_iter().enumerate().skip(skip) { - info!( + debug!( "writing cluster {cluster_index} (pts_base={}) with {} blocks", cluster.timestamp, cluster.blocks.len() ); - debug!( - "calculation was {} bytes off", - cluster.position as i64 - (output.position() - segment_start_position) as i64 - ); + { + let cue_error = + cluster.position as i64 - (output.position() - segment_start_position) as i64; + if cue_error != 0 { + warn!("calculation was {} bytes off", cue_error); + } + } + let mut cluster_blocks = vec![MatroskaTag::Timestamp(cluster.timestamp)]; - for (block_index, iblock) in cluster.blocks { - let kn = &mut ks[block_index]; - let mut block = kn + for (block_track, index_block) in cluster.blocks { + let track_reader = &mut track_readers[block_track]; + let mut block = track_reader .peek - .replace(kn.stream.next()?) + .replace(track_reader.stream.next()?) .expect("source file too short"); - assert_eq!(iblock.size, block.data.len(), "seek index is wrong"); + assert_eq!(index_block.size, block.data.len(), "seek index is wrong"); - block.track = kn.mapped; - block.timestamp_off = (iblock.pts - cluster.timestamp).try_into().unwrap(); + block.track = track_reader.mapped; + block.timestamp_off = (index_block.pts - cluster.timestamp).try_into().unwrap(); trace!("n={} tso={}", block.track, block.timestamp_off); let buf = block.dump(); cluster_blocks.push(MatroskaTag::SimpleBlock(buf)) diff --git a/remuxer/src/trim_writer.rs b/remuxer/src/trim_writer.rs index bed90e7..d278894 100644 --- a/remuxer/src/trim_writer.rs +++ b/remuxer/src/trim_writer.rs @@ -60,8 +60,11 @@ impl<W> Seek for TrimWriter<W> { std::io::SeekFrom::End(_) => unimplemented!(), std::io::SeekFrom::Current(s) => self.position += s as usize, } - if self.position < self.range.end { - warn!("seeked beyond end") + if self.position > self.range.end { + warn!( + "seeked beyond end: pos={} end={}", + self.position, self.range.end + ) } Ok(self.position as u64) } |