gstreamer: bin: more generic {add,remove}_many() API

No longer enforces to pass an array of references.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1230>
This commit is contained in:
Guillaume Desmottes 2023-03-09 11:42:44 +01:00 committed by GStreamer Marge Bot
parent 0bd6e07346
commit c4a968a403
25 changed files with 49 additions and 33 deletions

View file

@ -46,7 +46,7 @@ fn create_pipeline() -> Result<gst::Pipeline, Error> {
) )
.build(); .build();
pipeline.add_many(&[&src, appsink.upcast_ref()])?; pipeline.add_many([&src, appsink.upcast_ref()])?;
src.link(&appsink)?; src.link(&appsink)?;
// Getting data out of the appsink is done by setting callbacks on it. // Getting data out of the appsink is done by setting callbacks on it.

View file

@ -49,7 +49,7 @@ fn create_pipeline() -> Result<gst::Pipeline, Error> {
let videoconvert = gst::ElementFactory::make("videoconvert").build()?; let videoconvert = gst::ElementFactory::make("videoconvert").build()?;
let sink = gst::ElementFactory::make("autovideosink").build()?; let sink = gst::ElementFactory::make("autovideosink").build()?;
pipeline.add_many(&[appsrc.upcast_ref(), &videoconvert, &sink])?; pipeline.add_many([appsrc.upcast_ref(), &videoconvert, &sink])?;
gst::Element::link_many(&[appsrc.upcast_ref(), &videoconvert, &sink])?; gst::Element::link_many(&[appsrc.upcast_ref(), &videoconvert, &sink])?;
// Our frame counter, that is stored in the mutable environment // Our frame counter, that is stored in the mutable environment

View file

@ -576,7 +576,7 @@ fn create_pipeline() -> Result<gst::Pipeline, Error> {
comp.set_property("background-color", 0xff_33_33_33u32); comp.set_property("background-color", 0xff_33_33_33u32);
pipeline.add_many(&[&src1, &src2, comp.upcast_ref(), &conv, &sink])?; pipeline.add_many([&src1, &src2, comp.upcast_ref(), &conv, &sink])?;
// Link everything together. // Link everything together.
src1.link_filtered( src1.link_filtered(

View file

@ -70,7 +70,7 @@ fn example_main() -> Result<(), Error> {
.build()?; .build()?;
let decodebin = gst::ElementFactory::make("decodebin").build()?; let decodebin = gst::ElementFactory::make("decodebin").build()?;
pipeline.add_many(&[&src, &decodebin])?; pipeline.add_many([&src, &decodebin])?;
gst::Element::link_many(&[&src, &decodebin])?; gst::Element::link_many(&[&src, &decodebin])?;
// Need to move a new reference into the closure. // Need to move a new reference into the closure.

View file

@ -97,7 +97,7 @@ fn example_main() -> Result<(), Error> {
configure_encodebin(&encodebin); configure_encodebin(&encodebin);
pipeline pipeline
.add_many(&[&src, &encodebin, &sink]) .add_many([&src, &encodebin, &sink])
.expect("failed to add elements to pipeline"); .expect("failed to add elements to pipeline");
// It is clear from the start, that encodebin has only one src pad, so we can // It is clear from the start, that encodebin has only one src pad, so we can
// directly link it to our filesink without problems. // directly link it to our filesink without problems.

View file

@ -45,7 +45,7 @@ fn create_receiver_pipeline(
let queue = gst::ElementFactory::make("queue").build()?; let queue = gst::ElementFactory::make("queue").build()?;
let sink = gst::ElementFactory::make("autovideosink").build()?; let sink = gst::ElementFactory::make("autovideosink").build()?;
pipeline.add_many(&[src.upcast_ref(), &filter, &convert, &queue, &sink])?; pipeline.add_many([src.upcast_ref(), &filter, &convert, &queue, &sink])?;
gst::Element::link_many(&[src.upcast_ref(), &filter, &convert, &queue, &sink])?; gst::Element::link_many(&[src.upcast_ref(), &filter, &convert, &queue, &sink])?;
let fd_allocator = gst_allocators::FdAllocator::new(); let fd_allocator = gst_allocators::FdAllocator::new();
@ -115,7 +115,7 @@ fn create_sender_pipeline(
.ok_or_else(|| anyhow::anyhow!("is not a appsink"))? .ok_or_else(|| anyhow::anyhow!("is not a appsink"))?
.set_caps(Some(&caps)); .set_caps(Some(&caps));
pipeline.add_many(&[&src, &sink])?; pipeline.add_many([&src, &sink])?;
gst::Element::link_many(&[&src, &sink])?; gst::Element::link_many(&[&src, &sink])?;
let appsink = sink let appsink = sink

View file

@ -49,7 +49,7 @@ fn create_ui(app: &gtk::Application) {
(sink, widget) (sink, widget)
}; };
pipeline.add_many(&[&src, &sink]).unwrap(); pipeline.add_many([&src, &sink]).unwrap();
src.link(&sink).unwrap(); src.link(&sink).unwrap();
// Create a simple gtk gui window to place our widget into. // Create a simple gtk gui window to place our widget into.

View file

@ -103,7 +103,7 @@ fn create_ui(app: &gtk::Application) {
// specific. This example supports Linux and Mac (using X11 and Quartz). // specific. This example supports Linux and Mac (using X11 and Quartz).
let sink = create_video_sink(); let sink = create_video_sink();
pipeline.add_many(&[&src, &sink]).unwrap(); pipeline.add_many([&src, &sink]).unwrap();
src.link(&sink).unwrap(); src.link(&sink).unwrap();
// First, we create our gtk window - which will contain a region where // First, we create our gtk window - which will contain a region where

View file

@ -77,7 +77,7 @@ fn create_pipeline() -> Result<gst::Pipeline, Error> {
let videoconvert = gst::ElementFactory::make("videoconvert").build()?; let videoconvert = gst::ElementFactory::make("videoconvert").build()?;
let sink = gst::ElementFactory::make("autovideosink").build()?; let sink = gst::ElementFactory::make("autovideosink").build()?;
pipeline.add_many(&[&src, &overlay, &capsfilter, &videoconvert, &sink])?; pipeline.add_many([&src, &overlay, &capsfilter, &videoconvert, &sink])?;
gst::Element::link_many(&[&src, &overlay, &capsfilter, &videoconvert, &sink])?; gst::Element::link_many(&[&src, &overlay, &capsfilter, &videoconvert, &sink])?;
// The PangoFontMap represents the set of fonts available for a particular rendering system. // The PangoFontMap represents the set of fonts available for a particular rendering system.

View file

@ -76,7 +76,7 @@ fn create_pipeline() -> Result<gst::Pipeline, Error> {
let videoconvert = gst::ElementFactory::make("videoconvert").build()?; let videoconvert = gst::ElementFactory::make("videoconvert").build()?;
let sink = gst::ElementFactory::make("autovideosink").build()?; let sink = gst::ElementFactory::make("autovideosink").build()?;
pipeline.add_many(&[&src, &overlay, &capsfilter, &videoconvert, &sink])?; pipeline.add_many([&src, &overlay, &capsfilter, &videoconvert, &sink])?;
gst::Element::link_many(&[&src, &overlay, &capsfilter, &videoconvert, &sink])?; gst::Element::link_many(&[&src, &overlay, &capsfilter, &videoconvert, &sink])?;
// The PangoFontMap represents the set of fonts available for a particular rendering system. // The PangoFontMap represents the set of fonts available for a particular rendering system.

View file

@ -114,7 +114,7 @@ fn example_main() -> Result<(), Error> {
.property("caps", &video_caps) .property("caps", &video_caps)
.build()?; .build()?;
pipeline.add_many(&[&src, &netsim, &rtpbin, &depay, &dec, &conv, &scale, &filter])?; pipeline.add_many([&src, &netsim, &rtpbin, &depay, &dec, &conv, &scale, &filter])?;
gst::Element::link_many(&[&depay, &dec, &conv, &scale, &filter])?; gst::Element::link_many(&[&depay, &dec, &conv, &scale, &filter])?;
match args[1].as_str() { match args[1].as_str() {
@ -132,7 +132,7 @@ fn example_main() -> Result<(), Error> {
.property("location", "out.mkv") .property("location", "out.mkv")
.build()?; .build()?;
pipeline.add_many(&[&enc, &mux, &sink])?; pipeline.add_many([&enc, &mux, &sink])?;
gst::Element::link_many(&[&filter, &enc, &mux, &sink])?; gst::Element::link_many(&[&filter, &enc, &mux, &sink])?;
eprintln!("Recording to out.mkv"); eprintln!("Recording to out.mkv");
} }

View file

@ -99,7 +99,7 @@ fn example_main() -> Result<(), Error> {
.property("sync", true) .property("sync", true)
.build()?; .build()?;
pipeline.add_many(&[&src, &conv, &q1, &enc, &q2, &pay, &rtpbin, &sink])?; pipeline.add_many([&src, &conv, &q1, &enc, &q2, &pay, &rtpbin, &sink])?;
conv.link(&q1)?; conv.link(&q1)?;
q1.link(&enc)?; q1.link(&enc)?;

View file

@ -137,7 +137,7 @@ mod media_factory {
.build() .build()
.unwrap(); .unwrap();
bin.add_many(&[&src, &enc, &pay]).unwrap(); bin.add_many([&src, &enc, &pay]).unwrap();
gst::Element::link_many(&[&src, &enc, &pay]).unwrap(); gst::Element::link_many(&[&src, &enc, &pay]).unwrap();
Some(bin.upcast()) Some(bin.upcast())

View file

@ -248,7 +248,7 @@ fn create_pipeline() -> Result<gst::Pipeline, Error> {
let conv = gst::ElementFactory::make("audioconvert").build()?; let conv = gst::ElementFactory::make("audioconvert").build()?;
let sink = gst::ElementFactory::make("autoaudiosink").build()?; let sink = gst::ElementFactory::make("autoaudiosink").build()?;
pipeline.add_many(&[&src, filter.upcast_ref(), &conv, &sink])?; pipeline.add_many([&src, filter.upcast_ref(), &conv, &sink])?;
src.link(&filter)?; src.link(&filter)?;
filter.link(&conv)?; filter.link(&conv)?;
conv.link(&sink)?; conv.link(&sink)?;

View file

@ -34,7 +34,7 @@ fn example_main() {
.unwrap(); .unwrap();
let decodebin = gst::ElementFactory::make("decodebin").build().unwrap(); let decodebin = gst::ElementFactory::make("decodebin").build().unwrap();
pipeline.add_many(&[&src, &decodebin]).unwrap(); pipeline.add_many([&src, &decodebin]).unwrap();
gst::Element::link_many(&[&src, &decodebin]).unwrap(); gst::Element::link_many(&[&src, &decodebin]).unwrap();
// Need to move a new reference into the closure. // Need to move a new reference into the closure.

View file

@ -66,7 +66,7 @@ fn example_main() -> Result<(), Error> {
// Increase the queue capacity to 100MB to avoid a stalling pipeline // Increase the queue capacity to 100MB to avoid a stalling pipeline
pipeline pipeline
.add_many(&[&src, &typefinder, &queue, &muxer, &sink]) .add_many([&src, &typefinder, &queue, &muxer, &sink])
.expect("failed to add elements to pipeline"); .expect("failed to add elements to pipeline");
src.link(&typefinder)?; src.link(&typefinder)?;

View file

@ -555,7 +555,7 @@ impl App {
if let Some(gl_element) = gl_element { if let Some(gl_element) = gl_element {
let glupload = gst::ElementFactory::make("glupload").build()?; let glupload = gst::ElementFactory::make("glupload").build()?;
pipeline.add_many(&[&src, &glupload])?; pipeline.add_many([&src, &glupload])?;
pipeline.add(gl_element)?; pipeline.add(gl_element)?;
pipeline.add(&appsink)?; pipeline.add(&appsink)?;
@ -569,7 +569,7 @@ impl App {
.property("sink", &appsink) .property("sink", &appsink)
.build()?; .build()?;
pipeline.add_many(&[&src, &sink])?; pipeline.add_many([&src, &sink])?;
src.link(&sink)?; src.link(&sink)?;
Ok((pipeline, appsink)) Ok((pipeline, appsink))

View file

@ -23,9 +23,16 @@ impl Bin {
pub trait GstBinExtManual: 'static { pub trait GstBinExtManual: 'static {
#[doc(alias = "gst_bin_add_many")] #[doc(alias = "gst_bin_add_many")]
fn add_many<E: IsA<Element>>(&self, elements: &[&E]) -> Result<(), glib::BoolError>; fn add_many(
&self,
elements: impl IntoIterator<Item = impl AsRef<Element>>,
) -> Result<(), glib::BoolError>;
#[doc(alias = "gst_bin_remove_many")] #[doc(alias = "gst_bin_remove_many")]
fn remove_many<E: IsA<Element>>(&self, elements: &[&E]) -> Result<(), glib::BoolError>; fn remove_many(
&self,
elements: impl IntoIterator<Item = impl AsRef<Element>>,
) -> Result<(), glib::BoolError>;
#[doc(alias = "do-latency")] #[doc(alias = "do-latency")]
fn connect_do_latency<F: Fn(&Self) -> Result<(), LoggableError> + Send + Sync + 'static>( fn connect_do_latency<F: Fn(&Self) -> Result<(), LoggableError> + Send + Sync + 'static>(
@ -78,7 +85,10 @@ pub trait GstBinExtManual: 'static {
} }
impl<O: IsA<Bin>> GstBinExtManual for O { impl<O: IsA<Bin>> GstBinExtManual for O {
fn add_many<E: IsA<Element>>(&self, elements: &[&E]) -> Result<(), glib::BoolError> { fn add_many(
&self,
elements: impl IntoIterator<Item = impl AsRef<Element>>,
) -> Result<(), glib::BoolError> {
for e in elements { for e in elements {
unsafe { unsafe {
glib::result_from_gboolean!( glib::result_from_gboolean!(
@ -91,7 +101,10 @@ impl<O: IsA<Bin>> GstBinExtManual for O {
Ok(()) Ok(())
} }
fn remove_many<E: IsA<Element>>(&self, elements: &[&E]) -> Result<(), glib::BoolError> { fn remove_many(
&self,
elements: impl IntoIterator<Item = impl AsRef<Element>>,
) -> Result<(), glib::BoolError> {
for e in elements { for e in elements {
unsafe { unsafe {
glib::result_from_gboolean!( glib::result_from_gboolean!(

View file

@ -733,7 +733,7 @@ mod tests {
let sink = ElementFactory::make("fakesink").build().unwrap(); let sink = ElementFactory::make("fakesink").build().unwrap();
pipeline pipeline
.add_many(&[&src, element.upcast_ref(), &sink]) .add_many([&src, element.upcast_ref(), &sink])
.unwrap(); .unwrap();
Element::link_many(&[&src, element.upcast_ref(), &sink]).unwrap(); Element::link_many(&[&src, element.upcast_ref(), &sink]).unwrap();

View file

@ -22,7 +22,7 @@ fn tutorial_main() {
let pipeline = gst::Pipeline::builder().name("test-pipeline").build(); let pipeline = gst::Pipeline::builder().name("test-pipeline").build();
// Build the pipeline // Build the pipeline
pipeline.add_many(&[&source, &sink]).unwrap(); pipeline.add_many([&source, &sink]).unwrap();
source.link(&sink).expect("Elements could not be linked."); source.link(&sink).expect("Elements could not be linked.");
// Start playing // Start playing

View file

@ -7,8 +7,7 @@ fn tutorial_main() {
// Initialize GStreamer // Initialize GStreamer
gst::init().unwrap(); gst::init().unwrap();
let uri = let uri = "http://desmottes.be/~cassidy/files/brol/test.mkv";
"https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm";
// Create the elements // Create the elements
let source = gst::ElementFactory::make("uridecodebin") let source = gst::ElementFactory::make("uridecodebin")
@ -36,7 +35,7 @@ fn tutorial_main() {
// Build the pipeline Note that we are NOT linking the source at this // Build the pipeline Note that we are NOT linking the source at this
// point. We will do it later. // point. We will do it later.
pipeline pipeline
.add_many(&[&source, &convert, &resample, &sink]) .add_many([&source, &convert, &resample, &sink])
.unwrap(); .unwrap();
gst::Element::link_many(&[&convert, &resample, &sink]).expect("Elements could not be linked."); gst::Element::link_many(&[&convert, &resample, &sink]).expect("Elements could not be linked.");
@ -44,6 +43,10 @@ fn tutorial_main() {
source.connect_pad_added(move |src, src_pad| { source.connect_pad_added(move |src, src_pad| {
println!("Received new pad {} from {}", src_pad.name(), src.name()); 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 let sink_pad = convert
.static_pad("sink") .static_pad("sink")
.expect("Failed to get static sink pad from convert"); .expect("Failed to get static sink pad from convert");

View file

@ -103,7 +103,7 @@ fn tutorial_main() {
// Create the empty pipeline // Create the empty pipeline
let pipeline = gst::Pipeline::builder().name("test-pipeline").build(); let pipeline = gst::Pipeline::builder().name("test-pipeline").build();
pipeline.add_many(&[&source, &sink]).unwrap(); pipeline.add_many([&source, &sink]).unwrap();
source.link(&sink).expect("Elements could not be linked."); source.link(&sink).expect("Elements could not be linked.");
// Print initial negotiated caps (in NULL state) // Print initial negotiated caps (in NULL state)

View file

@ -57,7 +57,7 @@ fn tutorial_main() {
let pipeline = gst::Pipeline::builder().name("test-pipeline").build(); let pipeline = gst::Pipeline::builder().name("test-pipeline").build();
pipeline pipeline
.add_many(&[ .add_many([
&audio_source, &audio_source,
&tee, &tee,
&audio_queue, &audio_queue,

View file

@ -110,7 +110,7 @@ fn main() {
let pipeline = gst::Pipeline::builder().name("test-pipeline").build(); let pipeline = gst::Pipeline::builder().name("test-pipeline").build();
pipeline pipeline
.add_many(&[ .add_many([
appsrc.upcast_ref(), appsrc.upcast_ref(),
&tee, &tee,
&audio_queue, &audio_queue,

View file

@ -28,7 +28,7 @@ fn tutorial_main() -> Result<(), Error> {
// Create the sink bin, add the elements and link them // Create the sink bin, add the elements and link them
let bin = gst::Bin::builder().name("audio_sink_bin").build(); let bin = gst::Bin::builder().name("audio_sink_bin").build();
bin.add_many(&[&equalizer, &convert, &sink]).unwrap(); bin.add_many([&equalizer, &convert, &sink]).unwrap();
gst::Element::link_many(&[&equalizer, &convert, &sink]).expect("Failed to link elements."); gst::Element::link_many(&[&equalizer, &convert, &sink]).expect("Failed to link elements.");
let pad = equalizer let pad = equalizer