diff --git a/Cargo.lock b/Cargo.lock index 0ac12fa..72166cc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -250,7 +250,7 @@ checksum = "531b97fb4cd3dfdce92c35dedbfdc1f0b9d8091c8ca943d6dae340ef5012d514" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn", ] [[package]] @@ -417,7 +417,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.43", + "syn", ] [[package]] @@ -658,7 +658,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn", ] [[package]] @@ -711,7 +711,7 @@ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "gio-sys" version = "0.19.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#5613c9d139aa8ad7f142be782c6c75f21f1880f2" +source = "git+https://github.com/gtk-rs/gtk-rs-core#56a5549a7d5a28a20edd6ea1fcbd2f47a750cdd4" dependencies = [ "glib-sys", "gobject-sys", @@ -723,7 +723,7 @@ dependencies = [ [[package]] name = "glib" version = "0.19.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#5613c9d139aa8ad7f142be782c6c75f21f1880f2" +source = "git+https://github.com/gtk-rs/gtk-rs-core#56a5549a7d5a28a20edd6ea1fcbd2f47a750cdd4" dependencies = [ "bitflags 2.4.1", "futures-channel", @@ -745,20 +745,19 @@ dependencies = [ [[package]] name = "glib-macros" version = "0.19.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#5613c9d139aa8ad7f142be782c6c75f21f1880f2" +source = "git+https://github.com/gtk-rs/gtk-rs-core#56a5549a7d5a28a20edd6ea1fcbd2f47a750cdd4" dependencies = [ "heck", "proc-macro-crate", - "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.43", + "syn", ] [[package]] name = "glib-sys" version = "0.19.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#5613c9d139aa8ad7f142be782c6c75f21f1880f2" +source = "git+https://github.com/gtk-rs/gtk-rs-core#56a5549a7d5a28a20edd6ea1fcbd2f47a750cdd4" dependencies = [ "libc", "system-deps", @@ -779,7 +778,7 @@ dependencies = [ [[package]] name = "gobject-sys" version = "0.19.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#5613c9d139aa8ad7f142be782c6c75f21f1880f2" +source = "git+https://github.com/gtk-rs/gtk-rs-core#56a5549a7d5a28a20edd6ea1fcbd2f47a750cdd4" dependencies = [ "glib-sys", "libc", @@ -789,7 +788,7 @@ dependencies = [ [[package]] name = "gst-plugin-fmp4" version = "0.12.0-alpha.1" -source = "git+https://github.com/sdroege/gst-plugin-rs#80b58f3b45d2c3adee5684888937a3aa30e30cd7" +source = "git+https://github.com/sdroege/gst-plugin-rs#fcd57e9ac5e440056ed5b765d277570d2b617df6" dependencies = [ "anyhow", "gst-plugin-version-helper", @@ -803,7 +802,7 @@ dependencies = [ [[package]] name = "gst-plugin-mp4" version = "0.12.0-alpha.1" -source = "git+https://github.com/sdroege/gst-plugin-rs#80b58f3b45d2c3adee5684888937a3aa30e30cd7" +source = "git+https://github.com/sdroege/gst-plugin-rs#fcd57e9ac5e440056ed5b765d277570d2b617df6" dependencies = [ "anyhow", "gst-plugin-version-helper", @@ -817,7 +816,7 @@ dependencies = [ [[package]] name = "gst-plugin-version-helper" version = "0.8.0" -source = "git+https://github.com/sdroege/gst-plugin-rs#80b58f3b45d2c3adee5684888937a3aa30e30cd7" +source = "git+https://github.com/sdroege/gst-plugin-rs#fcd57e9ac5e440056ed5b765d277570d2b617df6" dependencies = [ "chrono", "toml_edit 0.21.0", @@ -1465,30 +1464,6 @@ dependencies = [ "toml_edit 0.21.0", ] -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - [[package]] name = "proc-macro2" version = "1.0.72" @@ -1822,7 +1797,7 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn", ] [[package]] @@ -1916,16 +1891,6 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "unicode-ident", -] - [[package]] name = "syn" version = "2.0.43" @@ -1982,7 +1947,7 @@ checksum = "3dcf4a824cce0aeacd6f38ae6f24234c8e80d68632338ebaa1443b5df9e29e19" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn", ] [[package]] @@ -2037,7 +2002,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn", ] [[package]] @@ -2105,7 +2070,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn", ] [[package]] @@ -2211,12 +2176,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - [[package]] name = "waker-fn" version = "1.1.1" @@ -2282,7 +2241,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.43", + "syn", "wasm-bindgen-shared", ] @@ -2316,7 +2275,7 @@ checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] diff --git a/Cargo.toml b/Cargo.toml index a86bf0e..75c7ac8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,6 @@ edition = "2021" [dependencies] gst = { package = "gstreamer", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs", features = ["v1_18"] } gst-app = { package = "gstreamer-app", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs", features = ["v1_18"] } -gst-plugin-fmp4 = { git = "https://github.com/sdroege/gst-plugin-rs", version = "0.12.0-alpha.1" } gst-video = { package = "gstreamer-video", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs", features = ["v1_18"] } gst-pbutils = { package = "gstreamer-pbutils", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs", features = ["v1_20"] } gst-sys = { package = "gstreamer-sys", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" } @@ -32,6 +31,7 @@ serde_json = "1" rfc6381-codec = "0.1" clap = { version = "4", features = ["derive"] } gst-plugin-mp4 = { git = "https://github.com/sdroege/gst-plugin-rs", version = "0.12.0-alpha.1" } +gst-plugin-fmp4 = { git = "https://github.com/sdroege/gst-plugin-rs", version = "0.12.0-alpha.1" } [build-dependencies] clap = { version = "4", features = ["derive"] } diff --git a/output.mp4 b/output.mp4 new file mode 100644 index 0000000..48357b4 Binary files /dev/null and b/output.mp4 differ diff --git a/src/media.rs b/src/media.rs index ff2cb57..f66d140 100644 --- a/src/media.rs +++ b/src/media.rs @@ -8,6 +8,7 @@ use gst::prelude::*; use gst::ClockTime; use gst_app::glib; use std::sync::{Arc, Mutex}; +use tokio::io::AsyncReadExt; use moq_transport::cache::{broadcast, fragment, segment, track}; use moq_transport::VarInt; @@ -69,9 +70,6 @@ impl Mp4Parser { let mut atom_bytes = Vec::with_capacity(atom_size); // TODO: Swap vectors? atom_bytes.extend_from_slice(&self.buf[0..atom_size]); - - println!("self.buffer length in Mp4 parser {:?}", self.buf.len()); - println!("atom size {:?}", atom_size); // assert_eq!(self.buf.len(), atom_size); self.buf.clear(); Some(Mp4Atom { @@ -124,12 +122,8 @@ pub struct GST {} impl GST { pub async fn run(mut broadcast: broadcast::Publisher) -> anyhow::Result<()> { - println!("starting up GST.run"); - gst::init()?; - //FIXME: add audio pipeline - gstfmp4::plugin_register_static()?; gstmp4::plugin_register_static().unwrap(); @@ -248,8 +242,8 @@ impl GST { // let pipeline = gst::parse::launch("videotestsrc num-buffers=2500 ! timecodestamper ! video/x-raw,format=I420,width=1280,height=720,framerate=30/1 ! timeoverlay ! x264enc bframes=0 bitrate=2048 ! video/x-h264,profile=main ! cmafmux fragment-duration=1 header-update-mode=update write-mehd=true ! appsink name=sink").unwrap().downcast::().unwrap(); // let pipeline = gst::parse::launch("videotestsrc num-buffers=2500 ! x264enc ! isomp4mux ! appsink name=sink").unwrap().downcast::().unwrap(); let pipeline = gst::parse::launch( - "videotestsrc num-buffers=99 ! x264enc ! mux. \ - audiotestsrc num-buffers=140 ! avenc_aac ! mux. \ + "videotestsrc num-buffers=60 ! video/x-raw,framerate=30/1 ! x264enc ! queue ! mux. \ + audiotestsrc num-buffers=60 ! audio/x-raw,rate=48000 ! avenc_aac ! queue ! mux. \ isomp4mux name=mux ! appsink name=sink \ ", ) @@ -270,6 +264,10 @@ impl GST { // Set the `emit-signals` property to `true` to receive signals appsink.set_property("emit-signals", &true); + //Get the buffers as soon as they are available + appsink.set_property("max-buffers", &1u32); + appsink.set_property("sync", &false); + // Set up a pad probe on the sink pad to intercept queries let sink_pad = appsink.static_pad("sink").unwrap(); @@ -280,7 +278,6 @@ impl GST { }; match query.view_mut() { gst::QueryViewMut::Seeking(q) => { - println!("Handling query {:?}", q); let format = q.format(); use gst::Format::Bytes; //https://github.com/Kurento/gstreamer/blob/f2553fb153edeeecc2f4f74fca996c74dc8210df/plugins/elements/gstfilesink.c#L494 @@ -320,19 +317,120 @@ impl GST { let sample = sink .pull_sample() .with_context(|| "Error pulling sample") - .map_err(|e| { - eprintln!("{:?}", e); - gst::FlowError::Eos - })?; + .map_err(|e| gst::FlowError::Eos)?; + // The muxer only outputs non-empty buffer lists let mut buffer_list = sample.buffer_list_owned().expect("no buffer list"); + assert!(!buffer_list.is_empty()); + + let mut data = Vec::new(); + let mut mp4_parser = Mp4Parser::new(); + for buffer in &*buffer_list { - println!("Found buffer {:?}", buffer); + let map = buffer + .map_readable() + .with_context(|| "Error mapping buffer to readable") + .map_err(|e| { + eprintln!("{:?}", e); + + gst::FlowError::Error + })?; + + data.extend_from_slice(map.as_slice()); + // mp4_parser.add(map.as_slice()) } + // loop { + // match mp4_parser.pop_atom() { + // Some(atom) => match atom.atom_type { + // ATOM_TYPE_FTYPE => { + // println!("Atom Ftyp") + // } + // ATOM_TYPE_MOOV => { + // println!("Atom Moov") + // } + // ATOM_TYPE_MOOF => { + // println!("Atom Moof") + // } + // ATOM_TYPE_MDAT => { + // println!("Atom Mdat") + // } + // _ => { + // println!("Unknown atom type {:?}", atom.atom_type) + // } + // }, + // None => break, + // } + // } + + let cursor = Cursor::new(data.to_vec()); + // let mut reader = mp4::BoxHeader::read(&mut cursor.clone()); + + while let Ok(header) = mp4::BoxHeader::read(&mut cursor.clone()) { + match header.name { + mp4::BoxType::MoofBox => { + println!("Found 'moof' box"); + // Process 'moof' box + } + mp4::BoxType::MdatBox => { + println!("Found 'mdat' box"); + // Process 'mdat' box + } + mp4::BoxType::EmsgBox => { + println!("Found 'emsg' box"); + // Process 'mdat' box + } + mp4::BoxType::FreeBox => { + println!("Found 'free' box"); + // Process 'mdat' box + } + mp4::BoxType::FtypBox => { + println!("Found 'ftyp' box"); + // Process 'mdat' box + } + mp4::BoxType::MoovBox => { + println!("Found 'moov' box"); + // Process 'mdat' box + } + // Handle other boxes if needed + _ => {} + } + } + // // Create a a Vec object from the data slice + // let bytes = map.as_slice().to_vec(); + + // // // We're going to parse the moov box. + // // We have to read the moov box header to correctly advance the cursor for the mp4 crate. + // let mut moov_reader = Cursor::new(bytes.clone()); + // let header = mp4::BoxHeader::read(&mut moov_reader) + // .map_err(|_| gst::FlowError::Error)?; + + // match header.name { + // mp4::BoxType::MoofBox => { + // println!("Moof body") + // } + // mp4::BoxType::MdatBox => { + // println!("Mdat body") + // } + // mp4::BoxType::MoovBox => { + // println!("Moov body") + // } + // mp4::BoxType::FtypBox => { + // println!("Ftyp body") + // } + // _ => { + // // Skip unknown atoms + // } + // } + Ok(gst::FlowSuccess::Ok) }) + .eos(move |_sink| { + println!("End-of-stream reached."); + + unreachable!() + }) .build(), );