aboutsummaryrefslogtreecommitdiff
path: root/remuxer/src
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2023-01-26 21:45:29 +0100
committermetamuffin <metamuffin@disroot.org>2023-01-26 21:45:29 +0100
commit04e3ebfdda613be0e58290a49536116cc57ad147 (patch)
treef694064c74e35ddb49fd900a83885e5874a78448 /remuxer/src
parentc715d411f465ef742ba76866dfb177f71598b69c (diff)
downloadjellything-04e3ebfdda613be0e58290a49536116cc57ad147.tar
jellything-04e3ebfdda613be0e58290a49536116cc57ad147.tar.bz2
jellything-04e3ebfdda613be0e58290a49536116cc57ad147.tar.zst
mhh
Diffstat (limited to 'remuxer/src')
-rw-r--r--remuxer/src/lib.rs83
1 files changed, 58 insertions, 25 deletions
diff --git a/remuxer/src/lib.rs b/remuxer/src/lib.rs
index 91c913a..1dfbacd 100644
--- a/remuxer/src/lib.rs
+++ b/remuxer/src/lib.rs
@@ -114,11 +114,18 @@ impl RemuxerContext {
.collect();
output.write_tag(&MatroskaTag::Tracks(Master::Collected(tracks_header)))?;
+ struct ClusterLayout {
+ position: usize,
+ timestamp: u64,
+ blocks: Vec<(usize, BlockIndex)>,
+ }
+
let segment_layout = {
- let mut pts = 0;
- let mut cluster_pts = pts + 2_000;
+ let mut cluster_pts = 0;
let mut clusters = vec![];
let mut cluster = vec![];
+ 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,
@@ -135,14 +142,32 @@ impl RemuxerContext {
};
}
inputs[best_index].temp_index += 1;
- pts = best_block.pts;
- if pts > cluster_pts + 2_000 {
- clusters.push(std::mem::replace(&mut cluster, vec![]));
- cluster_pts = pts;
+ if best_block.pts > cluster_pts + 2_000 {
+ let cluster_content_size = 1 // timestamp tag
+ + 1 // timestamp tag size
+ + EbmlWriter::vint_length(cluster_pts as u64) // timestamp tag value
+ + p;
+ let cluster_header_size = 4 // tag length
+ + EbmlWriter::vint_length(cluster_content_size as u64)// size varint
+ + cluster_content_size;
+ clusters.push(ClusterLayout {
+ position: gp,
+ timestamp: cluster_pts,
+ blocks: std::mem::replace(&mut cluster, vec![]),
+ });
+
+ cluster_pts = best_block.pts;
+ gp += p + cluster_header_size;
+ p = 0;
}
- if pts == u64::MAX {
+ if best_block.pts == u64::MAX {
break;
}
+ p += 1; // simpleblock tag
+ p += EbmlWriter::vint_length(1 + 2 + 1 + best_block.size as u64); // simpleblock size vint
+ p += 1 + 2 + 1; // block {tracknum, pts_off, flags}
+ // TODO does not work, if more than 127 tracks are present
+ p += best_block.size; // block payload
cluster.push((best_index, best_block))
}
info!("segment layout computed ({} clusters)", clusters.len());
@@ -183,28 +208,32 @@ impl RemuxerContext {
for (cluster_index, cluster) in segment_layout.into_iter().enumerate() {
info!(
- "writing cluster {cluster_index} with {} blocks",
- cluster.len()
+ "writing cluster {cluster_index} (pts_base={}) with {} blocks",
+ cluster.timestamp,
+ cluster.blocks.len()
+ );
+ debug!(
+ "calculation was {} bytes off",
+ cluster.position as i64 - output.position() as i64
);
- for (block_index, iblock) in cluster {
+ let mut cluster_blocks = vec![MatroskaTag::Timestamp(cluster.timestamp as u64)];
+ for (block_index, iblock) in cluster.blocks {
let kn = &mut ks[block_index];
let mut block = kn
.peek
.replace(kn.stream.next()?)
.expect("source file too short");
- assert_eq!(iblock.size, block.block.data.len(), "seek index is wrong");
+ assert_eq!(iblock.size, block.inner.data.len(), "seek index is wrong");
assert_eq!(iblock.pts, block.pts(), "seek index is wrong");
- let pts = block.pts();
- block.block.track = kn.mapped;
- block.block.timestamp_off = 0;
- let buf = block.block.dump();
- output.write_tag(&MatroskaTag::Cluster(Master::Collected(vec![
- MatroskaTag::Timestamp(pts),
- MatroskaTag::SimpleBlock(buf),
- ])))?;
+ block.inner.track = kn.mapped;
+ block.inner.timestamp_off = (iblock.pts - cluster.timestamp).try_into().unwrap();
+ debug!("n={} tso={}", block.inner.track, block.inner.timestamp_off);
+ let buf = block.inner.dump();
+ cluster_blocks.push(MatroskaTag::SimpleBlock(buf))
}
+ output.write_tag(&MatroskaTag::Cluster(Master::Collected(cluster_blocks)))?;
}
output.write_tag(&MatroskaTag::Segment(Master::End))?;
Ok(())
@@ -213,7 +242,7 @@ impl RemuxerContext {
struct AbsoluteBlock {
pts_base: u64,
- block: Block,
+ inner: Block,
}
struct SegmentExtractIter<'a> {
@@ -224,7 +253,7 @@ struct SegmentExtractIter<'a> {
impl AbsoluteBlock {
pub fn pts(&self) -> u64 {
- self.block.timestamp_off as u64 + self.pts_base
+ self.inner.timestamp_off as u64 + self.pts_base
}
}
@@ -272,16 +301,20 @@ impl SegmentExtractIter<'_> {
let block = Block::parse(&block.unwrap())?;
if block.track == self.extract {
trace!("block: track={} tso={}", block.track, block.timestamp_off);
- self.emission_queue
- .push_back(AbsoluteBlock { pts_base, block });
+ self.emission_queue.push_back(AbsoluteBlock {
+ pts_base,
+ inner: block,
+ });
}
}
MatroskaTag::SimpleBlock(buf) => {
let block = Block::parse(&buf)?;
if block.track == self.extract {
trace!("block: track={} tso={}", block.track, block.timestamp_off);
- self.emission_queue
- .push_back(AbsoluteBlock { pts_base, block });
+ self.emission_queue.push_back(AbsoluteBlock {
+ pts_base,
+ inner: block,
+ });
}
}
_ => warn!("(rsc) tag ignored: {item:?}"),