aboutsummaryrefslogtreecommitdiff
path: root/remuxer
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2024-01-28 03:21:03 +0100
committermetamuffin <metamuffin@disroot.org>2024-01-28 03:21:03 +0100
commitce9eb140ab9243d1c87ace4727a82b7fa50f964b (patch)
treeb64da94ba58f72a2371cdd8644dc48a178b7d260 /remuxer
parentb514ec8cea2c2143e0bd7a0eb377c96a6f091d0d (diff)
downloadjellything-ce9eb140ab9243d1c87ace4727a82b7fa50f964b.tar
jellything-ce9eb140ab9243d1c87ace4727a82b7fa50f964b.tar.bz2
jellything-ce9eb140ab9243d1c87ace4727a82b7fa50f964b.tar.zst
fix yet another fundamental issue in the ebml reader and seekindex.
Diffstat (limited to 'remuxer')
-rw-r--r--remuxer/src/extract.rs24
-rw-r--r--remuxer/src/import/mod.rs4
-rw-r--r--remuxer/src/remux.rs6
-rw-r--r--remuxer/src/seek_index.rs44
-rw-r--r--remuxer/src/segment_extractor.rs4
5 files changed, 53 insertions, 29 deletions
diff --git a/remuxer/src/extract.rs b/remuxer/src/extract.rs
index 108b76c..1b2b50c 100644
--- a/remuxer/src/extract.rs
+++ b/remuxer/src/extract.rs
@@ -6,8 +6,8 @@
use crate::seek_index::get_seek_index;
use anyhow::{anyhow, bail};
use jellycommon::LocalTrack;
-use jellymatroska::{block::Block, read::EbmlReader, unflatten::IterWithPos, Master, MatroskaTag};
-use log::{debug, info};
+use jellymatroska::{block::Block, read::EbmlReader, Master, MatroskaTag};
+use log::debug;
use std::{fs::File, io::BufReader, path::PathBuf};
pub fn extract_track(
@@ -20,12 +20,16 @@ pub fn extract_track(
let index = get_seek_index(&source_path)?;
let index = index
.get(&(track_info.track as u64))
- .ok_or(anyhow!("track missing 4"))?;
+ .ok_or(anyhow!("track missing"))?;
let mut out = Vec::new();
for b in &index.blocks {
- reader.seek(b.source_off, MatroskaTag::Cluster(Master::Start))?;
+ reader.seek(b.source_off, MatroskaTag::BlockGroup(Master::Start))?;
let (duration, block) = read_group(&mut reader)?;
+ assert_eq!(
+ track_info.track, block.track as usize,
+ "seek index is wrong"
+ );
out.push((b.pts, duration, block.data))
}
Ok(out)
@@ -33,23 +37,25 @@ pub fn extract_track(
pub fn read_group(segment: &mut EbmlReader) -> anyhow::Result<(u64, Block)> {
let (mut dur, mut block) = (None, None);
- loop {
- let item = segment.next().ok_or(anyhow!("eof"))??;
+ for _ in 0..10 {
+ let (_, item) = segment.next().ok_or(anyhow!("eof"))??;
match item {
MatroskaTag::Void(_) => (),
MatroskaTag::Crc32(_) => (),
- MatroskaTag::Cluster(_) => (),
+ MatroskaTag::Cluster(_) => bail!("unexpected cluster"),
MatroskaTag::Timestamp(_) => (),
MatroskaTag::SimpleBlock(_buf) => {
- // bail!("unexpected simpleblock, where a group was expected")
+ let block = Block::parse(&_buf)?;
+ return Ok((1000, block)); // HDMV/PGS does not use duration?!
}
MatroskaTag::BlockGroup(Master::Start) => (),
MatroskaTag::BlockGroup(Master::End) => return Ok((dur.unwrap(), block.unwrap())),
MatroskaTag::BlockDuration(duration) => dur = Some(duration),
MatroskaTag::Block(buf) => block = Some(Block::parse(&buf)?),
MatroskaTag::Cues(_) => bail!("reached cues, this is the end"),
- MatroskaTag::Segment(Master::End) => info!("extractor reached segment end"),
+ MatroskaTag::Segment(Master::End) => bail!("extractor reached segment end"),
_ => debug!("(rs) tag ignored: {item:?}"),
}
}
+ bail!(".")
}
diff --git a/remuxer/src/import/mod.rs b/remuxer/src/import/mod.rs
index 2981cea..d6fa2d0 100644
--- a/remuxer/src/import/mod.rs
+++ b/remuxer/src/import/mod.rs
@@ -9,7 +9,7 @@ use jellycommon::{Chapter, LocalTrack, SourceTrack, SourceTrackKind};
use jellymatroska::{
matroska::MatroskaTag,
read::EbmlReader,
- unflatten::{IterWithPos, Unflat, Unflatten},
+ unflatten::{Unflat, Unflatten},
};
use log::{debug, error, info, warn};
use std::{path::PathBuf, time::Instant};
@@ -30,7 +30,7 @@ pub struct MatroskaMetadata {
pub fn import_metadata(input: &mut EbmlReader) -> Result<MatroskaMetadata> {
while let Some(item) = input.next() {
let item = match item {
- Ok(item) => item,
+ Ok((_, item)) => item,
Err(e) => {
if !matches!(e, jellymatroska::error::Error::Io(_)) {
warn!("{e}");
diff --git a/remuxer/src/remux.rs b/remuxer/src/remux.rs
index 8273c9e..851b43d 100644
--- a/remuxer/src/remux.rs
+++ b/remuxer/src/remux.rs
@@ -31,7 +31,7 @@ use std::{
struct ClusterLayout {
position: usize,
timestamp: u64,
- source_offsets: Vec<Option<usize>>,
+ source_offsets: Vec<Option<u64>>,
blocks: Vec<(usize, BlockIndex)>,
}
@@ -277,7 +277,7 @@ pub fn remux_stream_into(
// 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),
+ MatroskaTag::Cluster(Master::Start), // TODO shouldn't this be a child of cluster?
)
.context("seeking in input")?;
let mut stream =
@@ -333,7 +333,7 @@ fn find_first_cluster_with_off(
segment_layout: &[ClusterLayout],
skip: usize,
track: usize,
-) -> Option<usize> {
+) -> Option<u64> {
for skip in skip..segment_layout.len() {
if let Some(off) = segment_layout[skip].source_offsets[track] {
return Some(off);
diff --git a/remuxer/src/seek_index.rs b/remuxer/src/seek_index.rs
index eba7344..7e9cee1 100644
--- a/remuxer/src/seek_index.rs
+++ b/remuxer/src/seek_index.rs
@@ -9,7 +9,7 @@ use jellycommon::seek_index::{BlockIndex, SeekIndex};
use jellymatroska::{
block::Block,
read::EbmlReader,
- unflatten::{IterWithPos, Unflat, Unflatten},
+ unflatten::{Unflat, Unflatten},
MatroskaTag,
};
use log::{debug, info, trace, warn};
@@ -30,7 +30,7 @@ pub fn import_seek_index(input: &mut EbmlReader) -> Result<BTreeMap<u64, SeekInd
let mut seek_index = BTreeMap::new();
while let Some(item) = input.next() {
let item = match item {
- Ok(item) => item,
+ Ok((_, item)) => item,
Err(e) => {
if !matches!(e, jellymatroska::error::Error::Io(_)) {
warn!("{e}");
@@ -67,20 +67,20 @@ fn import_seek_index_segment(
MatroskaTag::Cluster(_) => {
let mut children = children.unwrap();
let mut pts = 0;
- let mut position = children.position();
-
loop {
- if let Some(Ok(Unflat { children, item, .. })) = children.n() {
+ if let Some(Ok(Unflat {
+ children,
+ item,
+ position,
+ })) = children.n()
+ {
match item {
MatroskaTag::Timestamp(ts) => pts = ts,
MatroskaTag::BlockGroup(_) => {
trace!("group");
let mut children = children.unwrap();
- // let position = children.position(); //? TODO where should this point to? cluster or block? // probably block
while let Some(Ok(Unflat {
- children: _,
- item,
- position: _block_position,
+ children: _, item, ..
})) = children.n()
{
match item {
@@ -90,7 +90,12 @@ fn import_seek_index_segment(
"block: track={} tso={}",
block.track, block.timestamp_off
);
- seek_index_add(seek_index, &block, position, pts);
+ seek_index_add(
+ seek_index,
+ &block,
+ position.unwrap(),
+ pts,
+ );
}
_ => trace!("{item:?}"),
}
@@ -104,14 +109,13 @@ fn import_seek_index_segment(
block.timestamp_off
);
trace!("{pts} {}", block.timestamp_off);
- seek_index_add(seek_index, &block, position, pts);
+ seek_index_add(seek_index, &block, position.unwrap(), pts);
}
_ => trace!("(rsc) tag ignored: {item:?}"),
}
} else {
break;
}
- position = children.position();
}
}
_ => debug!("(rs) tag ignored: {item:?}"),
@@ -123,9 +127,23 @@ fn import_seek_index_segment(
fn seek_index_add(
seek_index: &mut BTreeMap<u64, SeekIndex>,
block: &Block,
- position: usize,
+ position: u64,
pts_base: u64,
) {
+ //* I heard this helped debugging once.
+ // {
+ // let mut f = File::open("/home/muffin/videos/itte-yorushika.mkv").unwrap();
+ // f.seek(std::io::SeekFrom::Start(position.try_into().unwrap()))
+ // .unwrap();
+ // let mut buf = [0u8];
+ // f.read_exact(&mut buf).unwrap();
+
+ // eprintln!("{}", buf[0]);
+ // if buf[0] != 0xa0 && buf[0] != 0xa3 {
+ // warn!("invalid position {position}")
+ // }
+ // }
+
let trs = seek_index
.entry(block.track)
.or_insert(SeekIndex::default());
diff --git a/remuxer/src/segment_extractor.rs b/remuxer/src/segment_extractor.rs
index 89d5784..ec645c3 100644
--- a/remuxer/src/segment_extractor.rs
+++ b/remuxer/src/segment_extractor.rs
@@ -4,7 +4,7 @@
Copyright (C) 2024 metamuffin <metamuffin.org>
*/
use anyhow::{anyhow, bail, Result};
-use jellymatroska::{block::Block, read::EbmlReader, unflatten::IterWithPos, Master, MatroskaTag};
+use jellymatroska::{block::Block, read::EbmlReader, Master, MatroskaTag};
use log::{debug, info, trace};
pub struct SegmentExtractIter<'a> {
@@ -23,7 +23,7 @@ impl<'a> SegmentExtractIter<'a> {
let mut group = false;
let mut saved_block = None;
loop {
- let item = self.segment.next().ok_or(anyhow!("eof"))??;
+ let (_, item) = self.segment.next().ok_or(anyhow!("eof"))??;
match item {
MatroskaTag::Void(_) => (),
MatroskaTag::Crc32(_) => (),