diff options
Diffstat (limited to 'matroska')
-rw-r--r-- | matroska/src/bin/experiment.rs | 33 | ||||
-rw-r--r-- | matroska/src/bin/mkvdump.rs | 8 | ||||
-rw-r--r-- | matroska/src/read.rs | 62 | ||||
-rw-r--r-- | matroska/src/unflatten.rs | 24 |
4 files changed, 38 insertions, 89 deletions
diff --git a/matroska/src/bin/experiment.rs b/matroska/src/bin/experiment.rs deleted file mode 100644 index e185787..0000000 --- a/matroska/src/bin/experiment.rs +++ /dev/null @@ -1,33 +0,0 @@ -/* - 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) 2024 metamuffin <metamuffin.org> -*/ -use jellymatroska::{ - matroska::MatroskaTag, read::EbmlReader, unflatten::IterWithPos, write::EbmlWriter, -}; -use std::{ - fs::File, - io::{stdout, BufReader, BufWriter}, -}; - -fn main() { - env_logger::init_from_env("LOG"); - let path = std::env::args().nth(1).unwrap(); - let mut r = EbmlReader::new(BufReader::new(File::open(path).unwrap())); - let mut w = EbmlWriter::new(BufWriter::new(stdout()), 0); - - // r.seek( - // 631147167 + 52, - // ebml::matroska::MatroskaTag::Cues(Master::Start), - // ) - // .unwrap(); - - while let Some(tag) = r.next() { - let tag = tag.unwrap(); - if MatroskaTag::is_master(tag.id()).unwrap() { - eprintln!("{tag:?}"); - } - w.write_tag(&tag).unwrap(); - } -} diff --git a/matroska/src/bin/mkvdump.rs b/matroska/src/bin/mkvdump.rs index 9e35716..27b4849 100644 --- a/matroska/src/bin/mkvdump.rs +++ b/matroska/src/bin/mkvdump.rs @@ -3,9 +3,7 @@ which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2024 metamuffin <metamuffin.org> */ -use jellymatroska::{ - block::Block, matroska::MatroskaTag, read::EbmlReader, unflatten::IterWithPos, -}; +use jellymatroska::{block::Block, matroska::MatroskaTag, read::EbmlReader}; use std::{fs::File, io::BufReader}; fn main() { @@ -14,13 +12,13 @@ fn main() { let mut r = EbmlReader::new(BufReader::new(File::open(path).unwrap())); while let Some(tag) = r.next() { - let tag = tag.unwrap(); + let (position, tag) = tag.unwrap(); match tag { MatroskaTag::SimpleBlock(b) | MatroskaTag::Block(b) => { let b = Block::parse(&b).unwrap(); println!("block kf={} ts_off={}", b.keyframe, b.timestamp_off) } - _ => println!("{} {tag:?}", r.position), + _ => println!("{} {tag:?}", position.unwrap_or(0)), } } } diff --git a/matroska/src/read.rs b/matroska/src/read.rs index 3e858f7..68a8efa 100644 --- a/matroska/src/read.rs +++ b/matroska/src/read.rs @@ -5,7 +5,7 @@ */ use crate::error::Error; use crate::Result; -use crate::{matroska::MatroskaTag, size::EbmlSize, unflatten::IterWithPos, Master}; +use crate::{matroska::MatroskaTag, size::EbmlSize, Master}; use log::{debug, warn}; use std::{ collections::VecDeque, @@ -17,21 +17,21 @@ impl<T: Read + Seek> ReadAndSeek for T {} #[derive(Debug, Clone, Copy)] pub struct StackTag { - end: Option<usize>, + end: Option<u64>, id: u64, } pub struct EbmlReader { inner: Box<dyn ReadAndSeek>, stack: Vec<StackTag>, - queue: VecDeque<MatroskaTag>, - pub position: usize, + queue: VecDeque<(Option<u64>, MatroskaTag)>, + position: u64, } impl Read for EbmlReader { fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> { let r = self.inner.read(buf)?; - self.position += r; + self.position += r as u64; Ok(r) } } @@ -53,15 +53,15 @@ impl EbmlReader { self.position += 1; Ok(b[0]) } - + pub fn read_buf(&mut self, size: impl Into<usize>) -> Result<Vec<u8>> { let size = size.into(); let mut b = vec![0u8; size]; self.inner.read_exact(&mut b).map_err(Error::Io)?; - self.position += size; + self.position += size as u64; Ok(b) } - + pub fn read_vint_len(&mut self) -> Result<(u64, usize)> { let s = self.read_byte()?; let len = s.leading_zeros() + 1; @@ -76,24 +76,24 @@ impl EbmlReader { } Ok((value, len as usize)) } - + #[inline] pub fn read_vint(&mut self) -> Result<u64> { Ok(self.read_vint_len()?.0) } - + #[inline] pub fn read_utf8(&mut self, size: impl Into<usize>) -> Result<String> { let b = self.read_buf(size)?; Ok(String::from_utf8(b).map_err(|_| Error::InvalidUTF8)?) } - + #[inline] pub fn read_tag_id(&mut self) -> Result<u64> { let (value, len) = self.read_vint_len()?; Ok(value + (1 << (7 * len))) } - + #[inline] pub fn read_tag_size(&mut self) -> Result<EbmlSize> { Ok(EbmlSize::from_vint(self.read_vint_len()?)) @@ -109,7 +109,7 @@ impl EbmlReader { } self.stack.pop(); self.queue - .push_back(MatroskaTag::construct_master(e.id, Master::End)?); + .push_back((None, MatroskaTag::construct_master(e.id, Master::End)?)); } else { break; } @@ -118,6 +118,7 @@ impl EbmlReader { } } + let start_position = self.position; let id = self.read_tag_id()?; let size = self.read_tag_size()?; let is_master = MatroskaTag::is_master(id)?; @@ -131,30 +132,29 @@ impl EbmlReader { if let Some(path) = tag.path() { // we have slightly different rules for closing tags implicitly // this closes as many tags as needed to make the next tag a valid child - while let Some(tag @ StackTag { end: None, .. }) = self.stack.last() { - if path.last() == Some(&tag.id) { + while let Some(stag @ StackTag { end: None, .. }) = self.stack.last() { + if path.last() == Some(&stag.id) { break; } else { - self.queue.push_back(MatroskaTag::construct_master( - self.stack.pop().unwrap().id, - Master::End, - )?); + let end = + MatroskaTag::construct_master(self.stack.pop().unwrap().id, Master::End)?; + self.queue.push_back((None, end)); } } } if is_master { self.stack.push(StackTag { - end: size.some().map(|s| s + self.position), + end: size.some().map(|s| s as u64 + self.position), id, }); } - self.queue.push_back(tag); + self.queue.push_back((Some(start_position), tag)); Ok(()) } /// context should be the next expected tag, such that the stack can be derived from its path. - pub fn seek(&mut self, position: usize, context: MatroskaTag) -> Result<()> { + pub fn seek(&mut self, position: u64, context: MatroskaTag) -> Result<()> { let path = context.path().ok_or(Error::GlobalTagsAsContext)?; debug!( "seeking to {position} with a context restored from path {:x?}", @@ -162,9 +162,7 @@ impl EbmlReader { ); self.queue.clear(); self.position = position; - self.inner - .seek(SeekFrom::Start(position as u64)) - .map_err(Error::Io)?; + self.inner.seek(SeekFrom::Start(position as u64))?; self.stack = path .iter() .map(|id| StackTag { id: *id, end: None }) @@ -173,13 +171,8 @@ impl EbmlReader { } } -impl IterWithPos for EbmlReader { - type Item = Result<MatroskaTag>; - - fn position(&self) -> usize { - self.position - } - +impl Iterator for EbmlReader { + type Item = Result<(Option<u64>, MatroskaTag)>; fn next(&mut self) -> Option<Self::Item> { if let Some(t) = self.queue.pop_front() { // match t { @@ -198,7 +191,10 @@ impl IterWithPos for EbmlReader { match self.queue.pop_front() { Some(q) => Some(Ok(q)), None => match self.stack.pop() { - Some(q) => Some(MatroskaTag::construct_master(q.id, Master::End)), + Some(q) => Some(Ok(( + None, + MatroskaTag::construct_master(q.id, Master::End).unwrap(), + ))), None => Some(Err(e)), }, } diff --git a/matroska/src/unflatten.rs b/matroska/src/unflatten.rs index 71089f4..944d2c7 100644 --- a/matroska/src/unflatten.rs +++ b/matroska/src/unflatten.rs @@ -3,30 +3,23 @@ which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2024 metamuffin <metamuffin.org> */ -use crate::{matroska::MatroskaTag, Master}; use crate::Result; - - -pub trait IterWithPos { - type Item; - fn next(&mut self) -> Option<Self::Item>; - fn position(&self) -> usize; -} +use crate::{matroska::MatroskaTag, Master}; pub struct Unflat<'a> { pub item: MatroskaTag, pub children: Option<Unflatten<'a>>, - pub position: usize, + pub position: Option<u64>, } pub struct Unflatten<'a> { - inner: &'a mut dyn IterWithPos<Item = Result<MatroskaTag>>, + inner: &'a mut dyn Iterator<Item = Result<(Option<u64>, MatroskaTag)>>, stop: bool, end: Option<MatroskaTag>, } impl<'a> Unflatten<'a> { - pub fn new(inner: &'a mut dyn IterWithPos<Item = Result<MatroskaTag>>) -> Self { + pub fn new(inner: &'a mut dyn Iterator<Item = Result<(Option<u64>, MatroskaTag)>>) -> Self { Self { inner, stop: false, @@ -34,7 +27,7 @@ impl<'a> Unflatten<'a> { } } pub fn new_with_end( - inner: &'a mut dyn IterWithPos<Item = Result<MatroskaTag>>, + inner: &'a mut dyn Iterator<Item = Result<(Option<u64>, MatroskaTag)>>, start: MatroskaTag, ) -> Self { Self { @@ -47,19 +40,14 @@ impl<'a> Unflatten<'a> { self.stop = true; } - pub fn position(&self) -> usize { - self.inner.position() - } - pub fn n(&mut self) -> Option<Result<Unflat>> { if self.stop { return None; } - let position = self.inner.position(); match self.inner.next() { None => None, Some(Err(e)) => Some(Err(e)), - Some(Ok(item)) => { + Some(Ok((position, item))) => { let master = MatroskaTag::is_master(item.id()).unwrap(); if Some(&item) == self.end.as_ref() { self.stop = true; |