diff options
Diffstat (limited to 'remuxer/src/muxers')
-rw-r--r-- | remuxer/src/muxers/matroska.rs | 51 | ||||
-rw-r--r-- | remuxer/src/muxers/mod.rs | 26 | ||||
-rw-r--r-- | remuxer/src/muxers/mpeg4.rs | 37 |
3 files changed, 71 insertions, 43 deletions
diff --git a/remuxer/src/muxers/matroska.rs b/remuxer/src/muxers/matroska.rs index 47210c9..c2f22e7 100644 --- a/remuxer/src/muxers/matroska.rs +++ b/remuxer/src/muxers/matroska.rs @@ -8,15 +8,25 @@ use crate::muxers::FragmentMuxer; use anyhow::Result; use std::io::Write; use winter_ebml::{EbmlHeader, EbmlToVec}; -use winter_matroska::{Cluster, Info, MatroskaFile, Segment, Tracks}; +use winter_matroska::{MatroskaFile, Segment}; + +fn write_fragment_shared(out: &mut dyn Write, mut segment: Segment, webm: bool) -> Result<()> { + segment.info.muxing_app = + concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION")).to_string(); + if webm { + if let Some(tracks) = &mut segment.tracks { + for track in &mut tracks.entries { + if let Some(video) = &mut track.video { + video.colour = None; + video.projection = None; + video.display_unit = 0; // pixels + video.display_width = Some(video.pixel_width); + video.display_height = Some(video.pixel_height); + } + } + } + } -fn write_fragment_shared( - out: &mut dyn Write, - info: Info, - tracks: Tracks, - cluster: Cluster, - webm: bool, -) -> Result<()> { let file = MatroskaFile { ebml_header: EbmlHeader { ebml_version: 1, @@ -28,12 +38,7 @@ fn write_fragment_shared( doc_type_read_version: 2, ..Default::default() }, - segment: Segment { - info, - tracks: Some(tracks), - clusters: vec![cluster], - ..Default::default() - }, + segment, }; out.write_all(&file.to_vec())?; Ok(()) @@ -41,23 +46,13 @@ fn write_fragment_shared( pub struct MatroskaFragmentMuxer; impl FragmentMuxer for MatroskaFragmentMuxer { - fn write_fragment( - out: &mut dyn Write, - info: Info, - tracks: Tracks, - cluster: Cluster, - ) -> Result<()> { - write_fragment_shared(out, info, tracks, cluster, false) + fn write_fragment(out: &mut dyn Write, segment: Segment) -> Result<()> { + write_fragment_shared(out, segment, false) } } pub struct WebmFragmentMuxer; impl FragmentMuxer for WebmFragmentMuxer { - fn write_fragment( - out: &mut dyn Write, - info: Info, - tracks: Tracks, - cluster: Cluster, - ) -> Result<()> { - write_fragment_shared(out, info, tracks, cluster, true) + fn write_fragment(out: &mut dyn Write, segment: Segment) -> Result<()> { + write_fragment_shared(out, segment, true) } } diff --git a/remuxer/src/muxers/mod.rs b/remuxer/src/muxers/mod.rs index 8752373..ae544eb 100644 --- a/remuxer/src/muxers/mod.rs +++ b/remuxer/src/muxers/mod.rs @@ -5,36 +5,32 @@ */ pub mod matroska; +pub mod mpeg4; use crate::{ ContainerFormat, - muxers::matroska::{MatroskaFragmentMuxer, WebmFragmentMuxer}, + muxers::{ + matroska::{MatroskaFragmentMuxer, WebmFragmentMuxer}, + mpeg4::Mpeg4FragmentMuxer, + }, }; use anyhow::Result; use std::io::Write; -use winter_matroska::{Cluster, Info, Tracks}; +use winter_matroska::Segment; pub trait FragmentMuxer { - fn write_fragment( - out: &mut dyn Write, - info: Info, - tracks: Tracks, - cluster: Cluster, - ) -> Result<()>; + fn write_fragment(out: &mut dyn Write, segment: Segment) -> Result<()>; } pub fn write_fragment( container: ContainerFormat, out: &mut dyn Write, - info: Info, - tracks: Tracks, - cluster: Cluster, + segment: Segment, ) -> Result<()> { match container { - ContainerFormat::Matroska => { - MatroskaFragmentMuxer::write_fragment(out, info, tracks, cluster) - } - ContainerFormat::Webm => WebmFragmentMuxer::write_fragment(out, info, tracks, cluster), + ContainerFormat::Matroska => MatroskaFragmentMuxer::write_fragment(out, segment), + ContainerFormat::Webm => WebmFragmentMuxer::write_fragment(out, segment), + ContainerFormat::Mpeg4 => Mpeg4FragmentMuxer::write_fragment(out, segment), _ => unimplemented!(), } } diff --git a/remuxer/src/muxers/mpeg4.rs b/remuxer/src/muxers/mpeg4.rs new file mode 100644 index 0000000..437f117 --- /dev/null +++ b/remuxer/src/muxers/mpeg4.rs @@ -0,0 +1,37 @@ +/* + 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) 2025 metamuffin <metamuffin.org> +*/ + +use crate::muxers::{FragmentMuxer, matroska::MatroskaFragmentMuxer}; +use anyhow::Result; +use std::{ + io::{Cursor, Write, copy}, + process::{Command, Stdio}, + thread::spawn, +}; +use winter_matroska::Segment; + +pub struct Mpeg4FragmentMuxer; +impl FragmentMuxer for Mpeg4FragmentMuxer { + fn write_fragment(out: &mut dyn Write, segment: Segment) -> Result<()> { + let mut mk_frag = Vec::new(); + MatroskaFragmentMuxer::write_fragment(&mut mk_frag, segment)?; + + let mut child = Command::new("ffmpeg") + .args( + "-hide_banner -f matroska -i pipe:0 -c copy -f mp4 -movflags frag_keyframe+empty_moov pipe:1" + .split(" "), + ) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn()?; + + let mut stdin = child.stdin.take().unwrap(); + let mut stdout = child.stdout.take().unwrap(); + spawn(move || copy(&mut Cursor::new(mk_frag), &mut stdin)); + copy(&mut stdout, out)?; + Ok(()) + } +} |