Created
October 31, 2024 15:20
-
-
Save dvtkrlbs/c649efb52a039c73f5f1ad98f00169b0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| use glib::object::Cast; | |
| use gstreamer as gst; | |
| use gstreamer::prelude::{ElementExt, ElementExtManual, GstBinExtManual, GstObjectExt, PadExt}; | |
| fn main() { | |
| // Initialize GStreamer | |
| gst::init().unwrap(); | |
| let uri = "https://gstreamer.freedesktop.org/data/media/sintel_trailer-480p.webm"; | |
| // Create the elements | |
| let source = gst::ElementFactory::make("uridecodebin") | |
| .name("source") | |
| // Set the URI to play | |
| .property("uri", uri) | |
| .build() | |
| .expect("Could not create uridecodebin element."); | |
| let convert = gst::ElementFactory::make("audioconvert") | |
| .name("convert") | |
| .build() | |
| .expect("Could not create convert element."); | |
| let sink = gst::ElementFactory::make("autoaudiosink") | |
| .name("sink") | |
| .build() | |
| .expect("Could not create sink element."); | |
| let video_convert = gst::ElementFactory::make("videoconvert") | |
| .name("video_convert") | |
| .build() | |
| .expect("Could not create video_convert element."); | |
| let video_sink = gst::ElementFactory::make("autovideosink") | |
| .name("video_sink") | |
| .build() | |
| .expect("Could not create video_sink element."); | |
| let resample = gst::ElementFactory::make("audioresample") | |
| .name("resample") | |
| .build() | |
| .expect("Could not create resample element."); | |
| // Create the empty pipeline | |
| let pipeline = gst::Pipeline::with_name("test-pipeline"); | |
| // Build the pipeline Note that we are NOT linking the source at this | |
| // point. We will do it later. | |
| pipeline | |
| .add_many([&source, &convert, &resample, &sink, &video_convert, &video_sink]) | |
| .unwrap(); | |
| gst::Element::link_many([&convert, &resample, &sink]).expect("Elements could not be linked."); | |
| gst::Element::link_many([&video_convert, &video_sink]).expect("Elements could not be linked"); | |
| // Connect the pad-added signal | |
| source.connect_pad_added(move |src, src_pad| { | |
| println!("Received new pad {} from {}", src_pad.name(), src.name()); | |
| src.downcast_ref::<gst::Bin>() | |
| .unwrap() | |
| .debug_to_dot_file_with_ts(gst::DebugGraphDetails::all(), "pad-added"); | |
| let sink_pad = convert | |
| .static_pad("sink") | |
| .expect("Failed to get static sink pad from convert"); | |
| let video_sink_pad = video_convert | |
| .static_pad("video_sink") | |
| .expect("Failed to get static video sink pad from video_convert"); | |
| if sink_pad.is_linked() && video_sink_pad.is_linked() { | |
| println!("We are already linked. Ignoring."); | |
| return; | |
| } | |
| let new_pad_caps = src_pad | |
| .current_caps() | |
| .expect("Failed to get caps of new pad."); | |
| let new_pad_struct = new_pad_caps | |
| .structure(0) | |
| .expect("Failed to get first structure of caps."); | |
| let new_pad_type = new_pad_struct.name(); | |
| let is_audio = new_pad_type.starts_with("audio/x-raw"); | |
| let is_video = new_pad_type.starts_with("video/x-raw"); | |
| if !is_audio && !is_video { | |
| println!("It has type {new_pad_type} which is not raw audio or video. Ignoring."); | |
| return; | |
| } | |
| if is_audio { | |
| let res = src_pad.link(&sink_pad); | |
| if res.is_err() { | |
| println!("Type is {new_pad_type} but link failed."); | |
| } else { | |
| println!("Link succeeded (type {new_pad_type})."); | |
| } | |
| } | |
| if is_video { | |
| let res = src_pad.link(&video_sink_pad); | |
| if res.is_err() { | |
| println!("Type is {new_pad_type} but link failed."); | |
| } else { | |
| println!("Link succeeded (type {new_pad_type})."); | |
| } | |
| } | |
| }); | |
| // Start playing | |
| pipeline | |
| .set_state(gst::State::Playing) | |
| .expect("Unable to set the pipeline to the `Playing` state"); | |
| // Wait until error or EOS | |
| let bus = pipeline.bus().unwrap(); | |
| for msg in bus.iter_timed(gst::ClockTime::NONE) { | |
| use gst::MessageView; | |
| match msg.view() { | |
| MessageView::Error(err) => { | |
| eprintln!( | |
| "Error received from element {:?} {}", | |
| err.src().map(|s| s.path_string()), | |
| err.error() | |
| ); | |
| eprintln!("Debugging information: {:?}", err.debug()); | |
| break; | |
| } | |
| MessageView::StateChanged(state_changed) => { | |
| if state_changed.src().map(|s| s == &pipeline).unwrap_or(false) { | |
| println!( | |
| "Pipeline state changed from {:?} to {:?}", | |
| state_changed.old(), | |
| state_changed.current() | |
| ); | |
| } | |
| } | |
| MessageView::Eos(..) => break, | |
| _ => (), | |
| } | |
| } | |
| pipeline | |
| .set_state(gst::State::Null) | |
| .expect("Unable to set the pipeline to the `Null` state"); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment