use crate::ebml_track_entry; use anyhow::Context; use ebml_struct::{ ids::*, matroska::{Cluster, Ebml, Info, Tracks}, read::{EbmlReadExt, TagRead}, write::TagWrite, }; use jellymatroska::{read::EbmlReader, write::EbmlWriter, Master, MatroskaTag}; use log::warn; use std::io::{BufReader, BufWriter, ErrorKind, Read, Seek, Write}; pub fn matroska_to_webm( input: impl Read + Seek + 'static, output: impl Write, ) -> anyhow::Result<()> { let mut output = EbmlWriter::new(BufWriter::new(output), 0); let mut input = EbmlReader::new(BufReader::new(input)); Ebml { ebml_version: 1, ebml_read_version: 1, ebml_max_id_length: 4, ebml_max_size_length: 8, doc_type: "webm".to_string(), doc_type_version: 4, doc_type_read_version: 2, doc_type_extensions: vec![], } .write(&mut output)?; output.write_tag(&MatroskaTag::Segment(Master::Start))?; let (x, mut ebml) = input.read_tag()?; assert_eq!(x, EL_EBML); let ebml = Ebml::read(&mut ebml).unwrap(); assert!(ebml.doc_type == "matroska" || ebml.doc_type == "webm"); let (x, mut segment) = input.read_tag()?; assert_eq!(x, EL_SEGMENT); loop { let (x, mut seg) = match segment.read_tag() { Ok(o) => o, Err(e) if e.kind() == ErrorKind::UnexpectedEof => break, Err(e) => return Err(e.into()), }; match x { EL_INFO => { let info = Info::read(&mut seg).context("info")?; output.write_tag(&{ MatroskaTag::Info(Master::Collected(vec![ MatroskaTag::TimestampScale(info.timestamp_scale), MatroskaTag::Duration(info.duration.unwrap_or_default()), MatroskaTag::Title(info.title.unwrap_or_default()), MatroskaTag::MuxingApp("jellyremux".to_string()), MatroskaTag::WritingApp("jellything".to_string()), ])) })?; } EL_TRACKS => { let tracks = Tracks::read(&mut seg).context("tracks")?; output.write_tag(&MatroskaTag::Tracks(Master::Collected( tracks .entries .into_iter() .map(|t| ebml_track_entry(t.track_number, &t)) .collect(), )))?; } EL_VOID | EL_CRC32 | EL_CUES | EL_SEEKHEAD | EL_ATTACHMENTS | EL_TAGS => { seg.consume()?; } EL_CLUSTER => { let cluster = Cluster::read(&mut seg).context("cluster")?; // TODO mixing both ebml libraries :))) cluster.write(&mut output)?; } id => { warn!("unknown top-level element {id:x}"); seg.consume()?; } } } Ok(()) }