diff options
| author | metamuffin <metamuffin@disroot.org> | 2025-10-09 15:16:34 +0200 |
|---|---|---|
| committer | metamuffin <metamuffin@disroot.org> | 2025-10-09 15:16:34 +0200 |
| commit | ea06e23a7fd3160f41da9aadec2229dc4dc47e37 (patch) | |
| tree | b485f8baeab5b6bf90321fdf60140f4ac362ade9 /remuxer | |
| parent | d9aa1005b589ae5eae93f00b25852166226bb9fd (diff) | |
| download | jellything-ea06e23a7fd3160f41da9aadec2229dc4dc47e37.tar jellything-ea06e23a7fd3160f41da9aadec2229dc4dc47e37.tar.bz2 jellything-ea06e23a7fd3160f41da9aadec2229dc4dc47e37.tar.zst | |
Fix bug seeking to clusters without seekhead
Diffstat (limited to 'remuxer')
| -rw-r--r-- | remuxer/src/bin/analyze_kf_placement.rs | 49 | ||||
| -rw-r--r-- | remuxer/src/bin/average_cluster_duration.rs | 13 | ||||
| -rw-r--r-- | remuxer/src/demuxers/matroska.rs | 21 | ||||
| -rw-r--r-- | remuxer/src/muxers/matroska.rs | 2 |
4 files changed, 70 insertions, 15 deletions
diff --git a/remuxer/src/bin/analyze_kf_placement.rs b/remuxer/src/bin/analyze_kf_placement.rs new file mode 100644 index 0000000..7a5a01d --- /dev/null +++ b/remuxer/src/bin/analyze_kf_placement.rs @@ -0,0 +1,49 @@ +/* + This file is part of jellything (https://codeberg.org/metamuffin/jellything) + which is licensed under the GNU Affero General Public License (version 3); see /COPYING. + Copyright (C) 2025 metamuffin <metamuffin.org> +*/ + +use anyhow::{Result, anyhow}; +use jellyremuxer::demuxers::{Demuxer, DemuxerNew, matroska::MatroskaDemuxer}; +use std::{env::args, fs::File}; +use winter_matroska::TrackType; + +fn main() -> Result<()> { + env_logger::init_from_env("LOG"); + let path = args().nth(1).ok_or(anyhow!("first arg is input path"))?; + let file = File::open(path)?; + let mut reader = MatroskaDemuxer::new(Box::new(file)); + + let tracks = reader.tracks()?.unwrap(); + let video_track = tracks + .entries + .iter() + .find(|t| matches!(t.track_type, TrackType::Video)) + .map(|t| t.track_number) + .unwrap(); + + reader.seek_cluster(None)?; + let mut num_kf_first = 0; + let mut num_kf_later = 0; + while let Some((_, cluster)) = reader.read_cluster()? { + let mut first = true; + for block in cluster.simple_blocks { + if block.track != video_track { + continue; + } + if block.flags.keyframe() { + if first { + num_kf_first += 1 + } else { + num_kf_later += 1; + } + } + first = false + } + } + + println!("{num_kf_first:>4} kf first"); + println!("{num_kf_later:>4} kf later"); + Ok(()) +} diff --git a/remuxer/src/bin/average_cluster_duration.rs b/remuxer/src/bin/average_cluster_duration.rs index 69bb79c..41effb4 100644 --- a/remuxer/src/bin/average_cluster_duration.rs +++ b/remuxer/src/bin/average_cluster_duration.rs @@ -6,7 +6,7 @@ use anyhow::{Result, anyhow}; use jellyremuxer::demuxers::{Demuxer, DemuxerNew, matroska::MatroskaDemuxer}; -use std::{env::args, fs::File}; +use std::{collections::BTreeMap, env::args, fs::File}; fn main() -> Result<()> { env_logger::init_from_env("LOG"); @@ -18,21 +18,22 @@ fn main() -> Result<()> { reader.seek_cluster(None)?; let mut num_clusters = 0; + let mut num_blocks = BTreeMap::<u64, usize>::new(); let mut last_ts = 0; let mut total_size = 0; while let Some((_, cluster)) = reader.read_cluster()? { last_ts = cluster.timestamp * info.timestamp_scale; num_clusters += 1; - total_size += cluster - .simple_blocks - .iter() - .map(|b| b.data.len()) - .sum::<usize>() as u64 + for block in &cluster.simple_blocks { + total_size += block.data.len() as u64; + *num_blocks.entry(block.track).or_default() += 1; + } } let average_duration = (last_ts / num_clusters) as f64 / 1_000_000_000.; let average_size = (total_size / num_clusters) as f64 / 1_000_000.; println!("{average_duration:>6.02}s {average_size:>6.02}MB"); + println!("{num_blocks:?}"); Ok(()) } diff --git a/remuxer/src/demuxers/matroska.rs b/remuxer/src/demuxers/matroska.rs index 21e8b2e..923db81 100644 --- a/remuxer/src/demuxers/matroska.rs +++ b/remuxer/src/demuxers/matroska.rs @@ -99,8 +99,9 @@ impl MatroskaDemuxer { Ok(self.seek_head.as_ref()) } - /// Seeks to the content of child tag of Segment possibly optimized via SeekHead. Returns the size of the content. - pub fn seek_to_segment_tag(&mut self, search_tag: u64) -> Result<Option<u64>> { + /// Seeks to the content of child tag of Segment possibly optimized via SeekHead. + /// Returns the absolute offset of the element start and size of the content. + pub fn seek_to_segment_tag(&mut self, search_tag: u64) -> Result<Option<(u64, u64)>> { if let Some(seek_head) = self.seek_head()? { let Some(segment_position) = seek_head .seeks @@ -111,22 +112,23 @@ impl MatroskaDemuxer { return Ok(None); }; let segment_offset = self.segment_offset()?; - self.reader - .seek(SeekFrom::Start(segment_offset + segment_position))?; + let absolute_offset = segment_offset + segment_position; + self.reader.seek(SeekFrom::Start(absolute_offset))?; let tag = self.reader.read_vint()?; let size = self.reader.read_vint()?; if tag != search_tag { bail!("SeekHead was lying (expected {search_tag:?}, got {tag:x})"); } - Ok(Some(size)) + Ok(Some((absolute_offset, size))) } else { self.seek_segment_start()?; loop { + let pos = self.reader.stream_position()?; let tag = self.reader.read_vint()?; let size = self.reader.read_vint()?; if tag == search_tag { - break Ok(Some(size)); + break Ok(Some((pos, size))); } if tag == Segment::TAG_CLUSTERS { break Ok(None); @@ -147,7 +149,7 @@ impl MatroskaDemuxer { tag: u64, ) -> Result<Option<Tag>> { debug!("reading {name:?}"); - let Some(size) = self.seek_to_segment_tag(tag)? else { + let Some((_, size)) = self.seek_to_segment_tag(tag)? else { return Ok(None); }; self.read_tag(size) @@ -181,7 +183,10 @@ impl Demuxer for MatroskaDemuxer { if let Some(pos) = position { self.reader.seek(SeekFrom::Start(pos))?; } else { - self.seek_to_segment_tag(Segment::TAG_CLUSTERS)?; + let Some((pos, _)) = self.seek_to_segment_tag(Segment::TAG_CLUSTERS)? else { + bail!("no clusters found"); + }; + self.reader.seek(SeekFrom::Start(pos))?; } Ok(()) } diff --git a/remuxer/src/muxers/matroska.rs b/remuxer/src/muxers/matroska.rs index c2f22e7..228f420 100644 --- a/remuxer/src/muxers/matroska.rs +++ b/remuxer/src/muxers/matroska.rs @@ -12,7 +12,7 @@ use winter_matroska::{MatroskaFile, Segment}; fn write_fragment_shared(out: &mut dyn Write, mut segment: Segment, webm: bool) -> Result<()> { segment.info.muxing_app = - concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION")).to_string(); + concat!(env!("CARGO_PKG_NAME"), "-", env!("CARGO_PKG_VERSION")).to_string(); if webm { if let Some(tracks) = &mut segment.tracks { for track in &mut tracks.entries { |