gstreamer-rs/tutorials/src/bin/basic-tutorial-3.rs

121 lines
3.9 KiB
Rust

use gst::prelude::*;
#[path = "../tutorials-common.rs"]
mod tutorials_common;
fn tutorial_main() {
// Initialize GStreamer
gst::init().unwrap();
let uri =
"https://www.freedesktop.org/software/gstreamer-sdk/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 resample = gst::ElementFactory::make("audioresample")
.name("resample")
.build()
.expect("Could not create resample element.");
// Create the empty pipeline
let pipeline = gst::Pipeline::builder().name("test-pipeline").build();
// 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])
.unwrap();
gst::Element::link_many(&[&convert, &resample, &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());
let sink_pad = convert
.static_pad("sink")
.expect("Failed to get static sink pad from convert");
if 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");
if !is_audio {
println!("It has type {new_pad_type} which is not raw audio. Ignoring.");
return;
}
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}).");
}
});
// 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");
}
fn main() {
// tutorials_common::run is only required to set up the application environment on macOS
// (but not necessary in normal Cocoa applications where this is set up automatically)
tutorials_common::run(tutorial_main);
}