use gst::prelude::*; use anyhow::Error; fn main() -> Result<(), Error> { gst::init().unwrap(); gstrsclosedcaption::plugin_register_static().expect("Failed to register closed caption plugin"); // TODO: create a video source with X buffers and burn the captions in the video feed using the captions tooling let pipeline = gst::parse_launch( "cccombiner name=ccc ! cea608overlay ! autovideosink \ videotestsrc num-buffers=1800 ! video/x-raw,width=1280,height=720,framerate=30/1 ! queue ! ccc.sink \ tttocea608 name=converter ! queue ! ccc.caption", )? .downcast::() .expect("Expected a gst::Pipeline"); let text_src = gst::ElementFactory::make("appsrc", Some("text-src")).unwrap(); text_src.set_property("is-live", true); text_src.set_property("caps", &gst::Caps::builder("text/x-raw") .field("format", "utf8") .build(), ); pipeline.add(&text_src).expect("Failed to add elements to pipeline"); let converter = pipeline.by_name("converter").unwrap(); text_src.link_pads(Some("src"), &converter, Some("sink")).expect("Failed to link elements"); println!("Starting pipeline.."); main_loop(pipeline) } fn main_loop(pipeline: gst::Pipeline) -> Result<(), Error> { let main_loop = glib::MainLoop::new(None, false); pipeline.set_state(gst::State::Playing)?; let bus = pipeline.bus().unwrap(); bus.add_watch({ let main_loop = main_loop.clone(); move |_, msg| { use gst::MessageView; let main_loop = &main_loop; match msg.view() { MessageView::Eos(..) => main_loop.quit(), MessageView::Error(err) => { println!( "Error from {:?}: {} ({:?})", err.src().map(|s| s.path_string()), err.error(), err.debug() ); main_loop.quit(); } _ => (), }; glib::Continue(true) } }) .expect("Failed to add bus watch"); let pipeline_weak = pipeline.downgrade(); let timeout_id = glib::timeout_add_local(std::time::Duration::from_secs(10), move || { let pipeline = match pipeline_weak.upgrade() { Some(pipeline) => pipeline, None => return glib::Continue(true), }; push_buffer(&pipeline); glib::Continue(true) }); main_loop.run(); pipeline.set_state(gst::State::Null)?; timeout_id.remove(); bus.remove_watch().unwrap(); Ok(()) } fn push_buffer(pipeline: &gst::Pipeline) { let src = pipeline .by_name("text-src") .unwrap() .downcast::() .unwrap(); let timestamp = pipeline.query_position::().unwrap(); println!("Trying to publish text buffer NOW! - {}", timestamp.display()); let text = "Nice story, bro!1".to_string(); let mut buffer = gst::Buffer::from_mut_slice(text.into_bytes()); { let buffer = buffer.get_mut().unwrap(); buffer.set_pts(timestamp); buffer.set_duration(gst::ClockTime::from_seconds(10)); } src.push_buffer(buffer).unwrap(); }