vcs-controller/src/ui/gstreamer_pipeline.rs

115 lines
3.6 KiB
Rust
Raw Normal View History

2024-04-24 21:29:59 -07:00
use gstreamer::prelude::{ElementExt, ElementExtManual, GstBinExtManual, PadExt};
use gstreamer::{Element, ElementFactory, Pipeline, State};
2024-04-24 21:30:32 -07:00
#[derive(Clone)]
2024-04-24 21:29:59 -07:00
pub struct WebcamPipeline {
pub pipeline: Pipeline,
pub src: Element,
pub converter: Element,
pub tee: Element,
pub sink_paintable: Element,
pub resize: Element,
pub decode: Element,
pub sink_frame: Element,
}
impl WebcamPipeline {
pub fn new() -> WebcamPipeline {
let pipeline = Pipeline::with_name("webcam_pipeline");
let source = ElementFactory::make("mfvideosrc")
.build()
.expect("Could not build video source for GStreamer");
let convert = ElementFactory::make("videoconvert")
.build()
.expect("Could not build video convert for GStreamer");
let tee = ElementFactory::make("tee")
.build()
.expect("Could not create tee element");
let sink_paintable = ElementFactory::make("gtk4paintablesink")
.build()
.expect("Could not build gtk sink for GStreamer");
let resize = ElementFactory::make("videoscale")
.build()
.expect("Could not build videoscale for GStreamer");
todo!("Video XRaw is not actually working yet");
let decode = ElementFactory::make("video/x-raw,width=650,height=480")
.build()
.expect("Could not create decoder");
let sink_frame = ElementFactory::make("appsink name=frame_sink")
.build()
.expect("Could not build appsrc for GStreamer");
pipeline.add_many(&[
&source,
&convert,
&tee,
&sink_paintable,
&resize,
&sink_frame,
]).expect("Could not link the elements to the pipeline");
source
.link(&convert)
.expect("Could not link video source to converter");
convert.link(&tee).expect("Could not link converter to tee");
let tee_pad_template = tee
.pad_template("src_%u")
.expect("Could not get pad templates");
let tee_src_1 = tee
.request_pad(&tee_pad_template, Some("paintable_src_pad"), None)
.expect("Could not create src pad 1");
let sink_paintable_sinkpad = sink_paintable
.static_pad("sink")
.expect("Could not get sink pad for paintablesink");
tee_src_1
.link(&sink_paintable_sinkpad)
.expect("Could not link tee srcpad 1 to paintablesink pad");
let tee_src_2 = tee
.request_pad(&tee_pad_template, Some("output_src_pad"), None)
.expect("Could not create src pad 2");
let sink_frameoutput_sinkpad = sink_frame
.static_pad("sink")
.expect("Could not get sink pad for frameoutput sink");
tee_src_2
.link(&sink_frameoutput_sinkpad)
.expect("Could not link tee srcpad 2 to frame output sink pad");
resize
.link(&decode)
.expect("Could not bind resize to decoder");
decode
.link(&sink_frame)
.expect("Could not bind decoder to webcam frame output");
WebcamPipeline {
pipeline,
src: source,
converter: convert,
tee,
sink_paintable,
resize,
decode,
sink_frame,
}
}
}
impl Drop for WebcamPipeline {
fn drop(&mut self) {
self.pipeline
.set_state(State::Null)
.expect("Could not close pipeline during window deconstruction");
}
}