2023-06-21 17:55:27 +00:00
|
|
|
use anyhow::Error;
|
|
|
|
use futures::prelude::*;
|
|
|
|
use futures::stream::select_all;
|
|
|
|
use gst::prelude::*;
|
|
|
|
|
|
|
|
fn toplevel(obj: &gst::Object) -> gst::Object {
|
|
|
|
if let Some(parent) = obj.parent() {
|
|
|
|
toplevel(&parent)
|
|
|
|
} else {
|
|
|
|
obj.clone()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[tokio::main]
|
|
|
|
async fn main() -> Result<(), Error> {
|
|
|
|
gst::init()?;
|
|
|
|
|
2023-12-04 14:54:00 +00:00
|
|
|
let src_pipeline = gst::parse::launch("videotestsrc is-live=true ! intersink")?;
|
|
|
|
let sink_pipeline = gst::parse::launch("intersrc ! videoconvert ! autovideosink")?;
|
2023-06-21 17:55:27 +00:00
|
|
|
|
|
|
|
let mut stream = select_all([
|
|
|
|
src_pipeline.bus().unwrap().stream(),
|
|
|
|
sink_pipeline.bus().unwrap().stream(),
|
|
|
|
]);
|
|
|
|
|
|
|
|
let base_time = gst::SystemClock::obtain().time().unwrap();
|
|
|
|
|
|
|
|
src_pipeline.set_clock(Some(&gst::SystemClock::obtain()))?;
|
|
|
|
src_pipeline.set_start_time(gst::ClockTime::NONE);
|
|
|
|
src_pipeline.set_base_time(base_time);
|
|
|
|
|
|
|
|
sink_pipeline.set_clock(Some(&gst::SystemClock::obtain()))?;
|
|
|
|
sink_pipeline.set_start_time(gst::ClockTime::NONE);
|
|
|
|
sink_pipeline.set_base_time(base_time);
|
|
|
|
|
|
|
|
src_pipeline.set_state(gst::State::Playing)?;
|
|
|
|
sink_pipeline.set_state(gst::State::Playing)?;
|
|
|
|
|
|
|
|
while let Some(msg) = stream.next().await {
|
|
|
|
use gst::MessageView;
|
|
|
|
|
|
|
|
match msg.view() {
|
|
|
|
MessageView::Latency(..) => {
|
|
|
|
if let Some(o) = msg.src() {
|
|
|
|
if let Ok(pipeline) = toplevel(o).downcast::<gst::Pipeline>() {
|
|
|
|
eprintln!("Recalculating latency {:?}", pipeline);
|
|
|
|
let _ = pipeline.recalculate_latency();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
MessageView::Eos(..) => {
|
|
|
|
eprintln!("Unexpected EOS");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
MessageView::Error(err) => {
|
|
|
|
eprintln!(
|
|
|
|
"Got error from {}: {} ({})",
|
|
|
|
msg.src()
|
|
|
|
.map(|s| String::from(s.path_string()))
|
|
|
|
.unwrap_or_else(|| "None".into()),
|
|
|
|
err.error(),
|
|
|
|
err.debug().unwrap_or_else(|| "".into()),
|
|
|
|
);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
_ => (),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
src_pipeline.set_state(gst::State::Null)?;
|
|
|
|
sink_pipeline.set_state(gst::State::Null)?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|