use jellycommon::ItemInfo; use log::{debug, info}; use std::{fs::File, io::Write, path::PathBuf, sync::Arc}; use tokio::sync::mpsc::Sender; use webm_iterable::{ matroska_spec::{Master, MatroskaSpec, Block}, WebmIterator, WebmWriter, }; pub struct RemuxerContext {} impl RemuxerContext { pub fn new() -> Arc { Arc::new(Self {}) } pub fn generate_into( &self, writer: impl Write, path_base: PathBuf, item: ItemInfo, selection: Vec, ) -> anyhow::Result<()> { let source_path = path_base.join(item.source.path); info!("remuxing {source_path:?} to have tracks {selection:?}"); let mut input = File::open(source_path)?; let tags = WebmIterator::new(&mut input, &[MatroskaSpec::TrackEntry(Master::Start)]); let mut output = WebmWriter::new(writer); for tag in tags { let tag = tag.unwrap(); match tag { MatroskaSpec::TrackEntry(master) => { let children = master.get_children(); let mut number = None; for c in &children { if let MatroskaSpec::TrackNumber(n) = c { number = Some(*n) } } let number = number.unwrap(); if selection.contains(&number) { output.write(&MatroskaSpec::TrackEntry(Master::Full(children)))?; } } MatroskaSpec::Block(ref data) => { let data: &[u8] = &data; let block: Block = data.try_into()?; if selection.contains(&block.track) { output.write(&tag)?; } }, MatroskaSpec::SimpleBlock(ref data) => { let data: &[u8] = &data; let block: Block = data.try_into()?; if selection.contains(&block.track) { output.write(&tag)?; } }, x => { // debug!("tag"); output.write(&x)?; } } } Ok(()) } } pub struct SendWriter(pub Sender>); impl Write for SendWriter { fn write(&mut self, buf: &[u8]) -> std::io::Result { debug!("write {buf:?}"); self.0.blocking_send(buf.to_owned()).unwrap(); Ok(buf.len()) } fn flush(&mut self) -> std::io::Result<()> { Ok(()) // TODO should we actually do something here? } }