// Copyright © SixtyFPS GmbH // SPDX-License-Identifier: MIT slint::include_modules!(); use anyhow::{bail, Result}; use gst::prelude::*; fn try_gstreamer_video_frame_to_pixel_buffer( frame: &gst_video::VideoFrame, ) -> Result> { match frame.format() { gst_video::VideoFormat::Rgb => { let mut slint_pixel_buffer = slint::SharedPixelBuffer::::new(frame.width(), frame.height()); frame .buffer() .copy_to_slice(0, slint_pixel_buffer.make_mut_bytes()) .expect("Unable to copy to slice!"); // Copies! Ok(slint_pixel_buffer) } _ => { bail!( "Cannot convert frame to a slint RGB frame because it is format {}", frame.format().to_str() ) } } } fn main() { let app = App::new().unwrap(); let app_weak = app.as_weak(); gst::init().unwrap(); let source = gst::ElementFactory::make("videotestsrc") .name("source") .property_from_str("pattern", "smpte") .build() .expect("Could not create source element."); let width: u32 = 1024; let height: u32 = 1024; let appsink = gst_app::AppSink::builder() .caps( &gst_video::VideoCapsBuilder::new() .format(gst_video::VideoFormat::Rgb) .width(width as i32) .height(height as i32) .build(), ) .build(); let pipeline = gst::Pipeline::with_name("test-pipeline"); pipeline.add_many([&source, &appsink.upcast_ref()]).unwrap(); source.link(&appsink).expect("Elements could not be linked."); appsink.set_callbacks( gst_app::AppSinkCallbacks::builder() .new_sample(move |appsink| { let sample = appsink.pull_sample().map_err(|_| gst::FlowError::Eos)?; let buffer = sample.buffer_owned().unwrap(); // Probably copies! let video_info = gst_video::VideoInfo::builder(gst_video::VideoFormat::Rgb, width, height) .build() .expect("couldn't build video info!"); let video_frame = gst_video::VideoFrame::from_buffer_readable(buffer, &video_info).unwrap(); let slint_frame = try_gstreamer_video_frame_to_pixel_buffer(&video_frame) .expect("Unable to convert the video frame to a slint video frame!"); app_weak .upgrade_in_event_loop(|app| { app.set_video_frame(slint::Image::from_rgb8(slint_frame)) }) .unwrap(); Ok(gst::FlowSuccess::Ok) }) .build(), ); pipeline .set_state(gst::State::Playing) .expect("Unable to set the pipeline to the `Playing` state"); app.run().unwrap(); }