webvtt-playground/src/main.rs

137 lines
4.3 KiB
Rust
Raw Normal View History

2021-12-29 16:00:06 +00:00
use anyhow::Error;
2022-01-11 21:21:20 +00:00
use gst::prelude::*;
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Duration;
2021-12-29 16:00:06 +00:00
2022-01-11 21:21:20 +00:00
fn main() -> Result<(), Error> {
2021-12-29 16:00:06 +00:00
gst::init().unwrap();
gstrsclosedcaption::plugin_register_static().expect("Failed to register closed caption plugin");
2021-12-29 18:55:21 +00:00
// Create a video source with X buffers and burn the captions in the video feed using the captions tooling
2021-12-29 16:00:06 +00:00
let pipeline = gst::parse_launch(
2021-12-29 17:10:51 +00:00
"cccombiner name=ccc ! cea608overlay ! autovideosink \
2022-01-11 21:21:20 +00:00
videotestsrc num-buffers=3600 ! video/x-raw,width=1280,height=720,framerate=30/1 ! queue ! ccc.sink \
tttocea608 name=converter mode=0 ! queue ! ccc.caption",
2021-12-29 16:00:06 +00:00
)?
.downcast::<gst::Pipeline>()
.expect("Expected a gst::Pipeline");
2022-01-11 21:21:20 +00:00
let text_src = gst::ElementFactory::make("appsrc", Some("text-src"))
.unwrap()
.downcast::<gst_app::AppSrc>()
.unwrap();
2021-12-29 17:19:29 +00:00
text_src.set_is_live(true);
text_src.set_format(gst::Format::Time);
text_src.set_caps(Some(
2021-12-29 17:10:51 +00:00
&gst::Caps::builder("text/x-raw")
2022-01-11 21:21:20 +00:00
.field("format", "utf8")
.build(),
2021-12-29 17:19:29 +00:00
));
2022-01-11 21:21:20 +00:00
pipeline
.add(&text_src)
.expect("Failed to add elements to pipeline");
2021-12-29 17:10:51 +00:00
let converter = pipeline.by_name("converter").unwrap();
2022-01-11 21:21:20 +00:00
text_src
.link_pads(Some("src"), &converter, Some("sink"))
.expect("Failed to link elements");
2021-12-29 16:00:06 +00:00
println!("Starting pipeline..");
main_loop(pipeline)
}
2021-12-29 17:10:51 +00:00
fn main_loop(pipeline: gst::Pipeline) -> Result<(), Error> {
2021-12-29 18:55:21 +00:00
let context = glib::MainContext::default();
let main_loop = glib::MainLoop::new(Some(&context), false);
2021-12-29 17:10:51 +00:00
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)
}
})
2022-01-11 21:21:20 +00:00
.expect("Failed to add bus watch");
static RUNNING: AtomicBool = AtomicBool::new(true);
let subtitles_src_thread = std::thread::spawn({
let pipeline_weak = pipeline.downgrade();
move || {
std::thread::sleep(Duration::from_secs(2));
let subtitles = [
"Hello people!",
"This is just an example of \nsubtitle",
"We will learn more about \nGStreamer and buffers today",
];
2022-01-11 21:22:16 +00:00
let mut sub_idx = (0..subtitles.len()).cycle();
2022-01-11 21:21:20 +00:00
while RUNNING.load(Ordering::Relaxed) {
if let Some(pipeline) = pipeline_weak.upgrade() {
push_buffer(&pipeline, subtitles[sub_idx.next().unwrap_or(0)]);
2022-02-02 14:00:43 +00:00
} else {
break;
2022-01-11 21:21:20 +00:00
}
println!("pushed the buffer.. now waiting.");
std::thread::sleep(Duration::from_secs(5));
}
println!("Stopping subtitles source thread!");
}
2021-12-29 17:10:51 +00:00
});
main_loop.run();
pipeline.set_state(gst::State::Null)?;
2022-01-11 21:21:20 +00:00
RUNNING.store(false, Ordering::Relaxed);
subtitles_src_thread.join().unwrap();
2021-12-29 17:10:51 +00:00
bus.remove_watch().unwrap();
Ok(())
}
2022-01-11 21:21:20 +00:00
fn push_buffer(pipeline: &gst::Pipeline, text: impl AsRef<str>) {
2021-12-29 16:00:06 +00:00
let src = pipeline
.by_name("text-src")
.unwrap()
.downcast::<gst_app::AppSrc>()
.unwrap();
2022-01-11 21:21:20 +00:00
let present_caption_at =
pipeline.query_position::<gst::ClockTime>().unwrap() + gst::ClockTime::from_seconds(1);
2021-12-29 17:10:51 +00:00
2022-01-11 21:21:20 +00:00
println!(
"Trying to publish text buffer NOW! - {} > {}",
present_caption_at.display(),
text.as_ref()
);
2021-12-29 16:00:06 +00:00
2022-01-11 21:21:20 +00:00
let mut buffer = gst::Buffer::from_mut_slice(text.as_ref().to_string().into_bytes());
2021-12-29 16:00:06 +00:00
{
let buffer = buffer.get_mut().unwrap();
2022-01-11 21:21:20 +00:00
buffer.set_pts(present_caption_at);
2021-12-29 18:55:21 +00:00
buffer.set_duration(gst::ClockTime::from_seconds(1));
2021-12-29 16:00:06 +00:00
}
src.push_buffer(buffer).unwrap();
2022-01-11 21:21:20 +00:00
}