diff options
author | metamuffin <metamuffin@disroot.org> | 2025-04-16 17:24:08 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2025-04-16 17:24:08 +0200 |
commit | cdf95d7b80bd2b78895671da8f462145bb5db522 (patch) | |
tree | f7f8377ee6352b313a45cb13362bbd7143fddccd /remuxer/src/matroska_to_webm.rs | |
parent | ad8016d8014af1e8dfb267fcdb51da63ab8ca4a9 (diff) | |
download | jellything-rewrite-stream.tar jellything-rewrite-stream.tar.bz2 jellything-rewrite-stream.tar.zst |
webm and mpeg4 fragments semi fixedrewrite-stream
Diffstat (limited to 'remuxer/src/matroska_to_webm.rs')
-rw-r--r-- | remuxer/src/matroska_to_webm.rs | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/remuxer/src/matroska_to_webm.rs b/remuxer/src/matroska_to_webm.rs new file mode 100644 index 0000000..b9a1819 --- /dev/null +++ b/remuxer/src/matroska_to_webm.rs @@ -0,0 +1,84 @@ +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(()) +} |