use gstreamer::prelude::{ElementExt, ElementExtManual, GstBinExtManual, PadExt}; use gstreamer::{Element, ElementFactory, Pipeline, State}; 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"); } }