Update everything for element factory builder API changes

And set properties as part of object construction wherever it makes
sense.
This commit is contained in:
Sebastian Dröge 2022-10-19 19:18:43 +03:00
parent 9ce8e93c63
commit 12400b6b87
41 changed files with 937 additions and 684 deletions

View file

@ -37,7 +37,7 @@ fn test_rnnoise_silence_small_buffers() {
} }
fn test_rnnoise(audio_info: &gst_audio::AudioInfo, buffer_size: usize) { fn test_rnnoise(audio_info: &gst_audio::AudioInfo, buffer_size: usize) {
let filter = gst::ElementFactory::make("audiornnoise", None).unwrap(); let filter = gst::ElementFactory::make("audiornnoise").build().unwrap();
let mut h = gst_check::Harness::with_element(&filter, Some("sink"), Some("src")); let mut h = gst_check::Harness::with_element(&filter, Some("sink"), Some("src"));
let sink_caps = audio_info.to_caps().unwrap(); let sink_caps = audio_info.to_caps().unwrap();
let src_caps = sink_caps.clone(); let src_caps = sink_caps.clone();

View file

@ -27,8 +27,10 @@ fn init() {
} }
fn build_harness(src_caps: gst::Caps, sink_caps: gst::Caps) -> (gst_check::Harness, gst::Element) { fn build_harness(src_caps: gst::Caps, sink_caps: gst::Caps) -> (gst_check::Harness, gst::Element) {
let hrtf = gst::ElementFactory::make("hrtfrender", None).unwrap(); let hrtf = gst::ElementFactory::make("hrtfrender")
hrtf.set_property("hrir-raw", &*CONFIG); .property("hrir-raw", &*CONFIG)
.build()
.unwrap();
let mut h = gst_check::Harness::with_element(&hrtf, Some("sink"), Some("src")); let mut h = gst_check::Harness::with_element(&hrtf, Some("sink"), Some("src"));
h.set_caps(src_caps, sink_caps); h.set_caps(src_caps, sink_caps);

View file

@ -79,8 +79,10 @@ fn create_pipeline() -> Result<gst::Pipeline, Box<dyn Error>> {
let audio_sink = gst::parse_bin_from_description(AUDIO_SINK, true)?.upcast(); let audio_sink = gst::parse_bin_from_description(AUDIO_SINK, true)?.upcast();
let csoundfilter = gst::ElementFactory::make("csoundfilter", None)?; let csoundfilter = gst::ElementFactory::make("csoundfilter")
csoundfilter.set_property("csd-text", &CSD); .property("csd-text", &CSD)
.build()
.unwrap();
pipeline.add_many(&[&audio_src, &csoundfilter, &audio_sink])?; pipeline.add_many(&[&audio_src, &csoundfilter, &audio_sink])?;

View file

@ -56,8 +56,10 @@ fn init() {
} }
fn build_harness(src_caps: gst::Caps, sink_caps: gst::Caps, csd: &str) -> gst_check::Harness { fn build_harness(src_caps: gst::Caps, sink_caps: gst::Caps, csd: &str) -> gst_check::Harness {
let filter = gst::ElementFactory::make("csoundfilter", None).unwrap(); let filter = gst::ElementFactory::make("csoundfilter")
filter.set_property("csd-text", &csd); .property("csd-text", &csd)
.build()
.unwrap();
let mut h = gst_check::Harness::with_element(&filter, Some("sink"), Some("src")); let mut h = gst_check::Harness::with_element(&filter, Some("sink"), Some("src"));

View file

@ -15,7 +15,7 @@ use std::collections::VecDeque;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use anyhow::{anyhow, Error}; use anyhow::Error;
use chrono::{DateTime, Duration, Utc}; use chrono::{DateTime, Duration, Utc};
use m3u8_rs::{ use m3u8_rs::{
AlternativeMedia, AlternativeMediaType, MasterPlaylist, MediaPlaylist, MediaSegment, AlternativeMedia, AlternativeMediaType, MasterPlaylist, MediaPlaylist, MediaSegment,
@ -139,11 +139,6 @@ struct AudioStream {
wave: String, wave: String,
} }
pub fn make_element(element: &str, name: Option<&str>) -> Result<gst::Element, Error> {
gst::ElementFactory::make(element, name)
.map_err(|_| anyhow!("Failed to make element {}", element))
}
fn trim_segments(state: &mut StreamState) { fn trim_segments(state: &mut StreamState) {
// Arbitrary 5 segments window // Arbitrary 5 segments window
while state.segments.len() > 5 { while state.segments.len() > 5 {
@ -396,13 +391,24 @@ impl VideoStream {
pipeline: &gst::Pipeline, pipeline: &gst::Pipeline,
path: &Path, path: &Path,
) -> Result<(), Error> { ) -> Result<(), Error> {
let src = make_element("videotestsrc", None)?; let src = gst::ElementFactory::make("videotestsrc")
let raw_capsfilter = make_element("capsfilter", None)?; .property("is-live", true)
let timeoverlay = make_element("timeoverlay", None)?; .build()?;
let enc = make_element("x264enc", None)?;
let h264_capsfilter = make_element("capsfilter", None)?; let raw_capsfilter = gst::ElementFactory::make("capsfilter").build()?;
let mux = make_element("cmafmux", None)?; let timeoverlay = gst::ElementFactory::make("timeoverlay").build()?;
let appsink = make_element("appsink", None)?; let enc = gst::ElementFactory::make("x264enc")
.property("bframes", 0u32)
.property("bitrate", self.bitrate as u32 / 1000u32)
.property_from_str("tune", "zerolatency")
.build()?;
let h264_capsfilter = gst::ElementFactory::make("capsfilter").build()?;
let mux = gst::ElementFactory::make("cmafmux")
.property("fragment-duration", 2500.mseconds())
.property_from_str("header-update-mode", "update")
.property("write-mehd", true)
.build()?;
let appsink = gst::ElementFactory::make("appsink").build()?;
pipeline.add_many(&[ pipeline.add_many(&[
&src, &src,
@ -414,16 +420,6 @@ impl VideoStream {
&appsink, &appsink,
])?; ])?;
gst::Element::link_many(&[
&src,
&raw_capsfilter,
&timeoverlay,
&enc,
&h264_capsfilter,
&mux,
&appsink,
])?;
raw_capsfilter.set_property( raw_capsfilter.set_property(
"caps", "caps",
gst_video::VideoCapsBuilder::new() gst_video::VideoCapsBuilder::new()
@ -441,13 +437,15 @@ impl VideoStream {
.build(), .build(),
); );
src.set_property("is-live", true); gst::Element::link_many(&[
enc.set_property("bframes", 0u32); &src,
enc.set_property("bitrate", self.bitrate as u32 / 1000u32); &raw_capsfilter,
enc.set_property_from_str("tune", "zerolatency"); &timeoverlay,
mux.set_property("fragment-duration", 2500.mseconds()); &enc,
mux.set_property_from_str("header-update-mode", "update"); &h264_capsfilter,
mux.set_property("write-mehd", true); &mux,
&appsink,
])?;
probe_encoder(state, enc); probe_encoder(state, enc);
@ -466,21 +464,22 @@ impl AudioStream {
pipeline: &gst::Pipeline, pipeline: &gst::Pipeline,
path: &Path, path: &Path,
) -> Result<(), Error> { ) -> Result<(), Error> {
let src = make_element("audiotestsrc", None)?; let src = gst::ElementFactory::make("audiotestsrc")
let enc = make_element("avenc_aac", None)?; .property("is-live", true)
let mux = make_element("cmafmux", None)?; .property_from_str("wave", &self.wave)
let appsink = make_element("appsink", None)?; .property("fragment-duration", 2500.mseconds())
.build()?;
let enc = gst::ElementFactory::make("avenc_aac").build()?;
let mux = gst::ElementFactory::make("cmafmux")
.property_from_str("header-update-mode", "update")
.property("write-mehd", true)
.build()?;
let appsink = gst::ElementFactory::make("appsink").build()?;
pipeline.add_many(&[&src, &enc, &mux, &appsink])?; pipeline.add_many(&[&src, &enc, &mux, &appsink])?;
gst::Element::link_many(&[&src, &enc, &mux, &appsink])?; gst::Element::link_many(&[&src, &enc, &mux, &appsink])?;
src.set_property("is-live", true);
src.set_property_from_str("wave", &self.wave);
mux.set_property("fragment-duration", 2500.mseconds());
mux.set_property_from_str("header-update-mode", "update");
mux.set_property("write-mehd", true);
probe_encoder(state, enc); probe_encoder(state, enc);
let appsink = appsink.downcast::<gst_app::AppSink>().unwrap(); let appsink = appsink.downcast::<gst_app::AppSink>().unwrap();

View file

@ -14,7 +14,7 @@ use gst::prelude::*;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use anyhow::{anyhow, Error}; use anyhow::Error;
use m3u8_rs::{ use m3u8_rs::{
AlternativeMedia, AlternativeMediaType, MasterPlaylist, MediaPlaylist, MediaPlaylistType, AlternativeMedia, AlternativeMediaType, MasterPlaylist, MediaPlaylist, MediaPlaylistType,
@ -127,11 +127,6 @@ impl State {
} }
} }
pub fn make_element(element: &str, name: Option<&str>) -> Result<gst::Element, Error> {
gst::ElementFactory::make(element, name)
.map_err(|_| anyhow!("Failed to make element {}", element))
}
fn setup_appsink(appsink: &gst_app::AppSink, name: &str, path: &Path, is_video: bool) { fn setup_appsink(appsink: &gst_app::AppSink, name: &str, path: &Path, is_video: bool) {
let mut path: PathBuf = path.into(); let mut path: PathBuf = path.into();
path.push(name); path.push(name);
@ -291,13 +286,22 @@ impl VideoStream {
pipeline: &gst::Pipeline, pipeline: &gst::Pipeline,
path: &Path, path: &Path,
) -> Result<(), Error> { ) -> Result<(), Error> {
let src = make_element("videotestsrc", None)?; let src = gst::ElementFactory::make("videotestsrc")
let raw_capsfilter = make_element("capsfilter", None)?; .property("num-buffers", 300)
let timeoverlay = make_element("timeoverlay", None)?; .build()?;
let enc = make_element("x264enc", None)?; let raw_capsfilter = gst::ElementFactory::make("capsfilter").build()?;
let h264_capsfilter = make_element("capsfilter", None)?; let timeoverlay = gst::ElementFactory::make("timeoverlay").build()?;
let mux = make_element("cmafmux", None)?; let enc = gst::ElementFactory::make("x264enc")
let appsink = make_element("appsink", None)?; .property("bframes", 0u32)
.property("bitrate", self.bitrate as u32 / 1000u32)
.build()?;
let h264_capsfilter = gst::ElementFactory::make("capsfilter").build()?;
let mux = gst::ElementFactory::make("cmafmux")
.property("fragment-duration", 2500.mseconds())
.property_from_str("header-update-mode", "update")
.property("write-mehd", true)
.build()?;
let appsink = gst::ElementFactory::make("appsink").build()?;
pipeline.add_many(&[ pipeline.add_many(&[
&src, &src,
@ -336,13 +340,6 @@ impl VideoStream {
.build(), .build(),
); );
src.set_property("num-buffers", 300);
enc.set_property("bframes", 0u32);
enc.set_property("bitrate", self.bitrate as u32 / 1000u32);
mux.set_property("fragment-duration", 2500.mseconds());
mux.set_property_from_str("header-update-mode", "update");
mux.set_property("write-mehd", true);
probe_encoder(state, enc); probe_encoder(state, enc);
let appsink = appsink.downcast::<gst_app::AppSink>().unwrap(); let appsink = appsink.downcast::<gst_app::AppSink>().unwrap();
@ -360,28 +357,29 @@ impl AudioStream {
pipeline: &gst::Pipeline, pipeline: &gst::Pipeline,
path: &Path, path: &Path,
) -> Result<(), Error> { ) -> Result<(), Error> {
let src = make_element("audiotestsrc", None)?; let src = gst::ElementFactory::make("audiotestsrc")
let raw_capsfilter = make_element("capsfilter", None)?; .property("num-buffers", 100)
let enc = make_element("avenc_aac", None)?; .property("samplesperbuffer", 4410)
let mux = make_element("cmafmux", None)?; .property_from_str("wave", &self.wave)
let appsink = make_element("appsink", None)?; .build()?;
let raw_capsfilter = gst::ElementFactory::make("capsfilter").build()?;
let enc = gst::ElementFactory::make("avenc_aac").build()?;
let mux = gst::ElementFactory::make("cmafmux")
.property("fragment-duration", 2500.mseconds())
.property_from_str("header-update-mode", "update")
.property("write-mehd", true)
.build()?;
let appsink = gst::ElementFactory::make("appsink").build()?;
pipeline.add_many(&[&src, &raw_capsfilter, &enc, &mux, &appsink])?; pipeline.add_many(&[&src, &raw_capsfilter, &enc, &mux, &appsink])?;
gst::Element::link_many(&[&src, &raw_capsfilter, &enc, &mux, &appsink])?; gst::Element::link_many(&[&src, &raw_capsfilter, &enc, &mux, &appsink])?;
src.set_property("num-buffers", 100);
src.set_property("samplesperbuffer", 4410);
src.set_property_from_str("wave", &self.wave);
raw_capsfilter.set_property( raw_capsfilter.set_property(
"caps", "caps",
gst_audio::AudioCapsBuilder::new().rate(44100).build(), gst_audio::AudioCapsBuilder::new().rate(44100).build(),
); );
mux.set_property("fragment-duration", 2500.mseconds());
mux.set_property_from_str("header-update-mode", "update");
mux.set_property("write-mehd", true);
probe_encoder(state, enc); probe_encoder(state, enc);
let appsink = appsink.downcast::<gst_app::AppSink>().unwrap(); let appsink = appsink.downcast::<gst_app::AppSink>().unwrap();

View file

@ -85,16 +85,20 @@ fn main() -> Result<(), Box<dyn Error>> {
let receiver = &Keys::from_file(&receiver_keys)?; let receiver = &Keys::from_file(&receiver_keys)?;
let sender = &Keys::from_file(&sender_keys)?; let sender = &Keys::from_file(&sender_keys)?;
let filesrc = gst::ElementFactory::make("filesrc", None).unwrap(); let filesrc = gst::ElementFactory::make("filesrc")
let decrypter = gst::ElementFactory::make("sodiumdecrypter", None).unwrap(); .property("location", &args.input)
let typefind = gst::ElementFactory::make("typefind", None).unwrap(); .build()
let filesink = gst::ElementFactory::make("filesink", None).unwrap(); .unwrap();
let decrypter = gst::ElementFactory::make("sodiumdecrypter")
filesrc.set_property("location", &args.input); .property("receiver-key", glib::Bytes::from_owned(receiver.private.0))
filesink.set_property("location", &args.output); .property("sender-key", glib::Bytes::from_owned(sender.public))
.build()
decrypter.set_property("receiver-key", glib::Bytes::from_owned(receiver.private.0)); .unwrap();
decrypter.set_property("sender-key", glib::Bytes::from_owned(sender.public)); let typefind = gst::ElementFactory::make("typefind").build().unwrap();
let filesink = gst::ElementFactory::make("filesink")
.property("location", &args.output)
.build()
.unwrap();
let pipeline = gst::Pipeline::new(Some("test-pipeline")); let pipeline = gst::Pipeline::new(Some("test-pipeline"));
pipeline pipeline

View file

@ -89,15 +89,19 @@ fn main() -> Result<(), Box<dyn Error>> {
let receiver = &Keys::from_file(&receiver_keys)?; let receiver = &Keys::from_file(&receiver_keys)?;
let sender = &Keys::from_file(&sender_keys)?; let sender = &Keys::from_file(&sender_keys)?;
let filesrc = gst::ElementFactory::make("filesrc", None).unwrap(); let filesrc = gst::ElementFactory::make("filesrc")
let encrypter = gst::ElementFactory::make("sodiumencrypter", None).unwrap(); .property("location", &args.input)
let filesink = gst::ElementFactory::make("filesink", None).unwrap(); .build()
.unwrap();
filesrc.set_property("location", &args.input); let encrypter = gst::ElementFactory::make("sodiumencrypter")
filesink.set_property("location", &args.output); .property("receiver-key", glib::Bytes::from_owned(receiver.public))
.property("sender-key", glib::Bytes::from_owned(sender.private.0))
encrypter.set_property("receiver-key", glib::Bytes::from_owned(receiver.public)); .build()
encrypter.set_property("sender-key", glib::Bytes::from_owned(sender.private.0)); .unwrap();
let filesink = gst::ElementFactory::make("filesink")
.property("location", &args.output)
.build()
.unwrap();
let pipeline = gst::Pipeline::new(Some("test-pipeline")); let pipeline = gst::Pipeline::new(Some("test-pipeline"));
pipeline pipeline

View file

@ -72,17 +72,21 @@ fn test_pipeline() {
r r
}; };
let filesrc = gst::ElementFactory::make("filesrc", None).unwrap(); let filesrc = gst::ElementFactory::make("filesrc")
filesrc.set_property("location", &input_path.to_str().unwrap()); .property("location", &input_path.to_str().unwrap())
.build()
.unwrap();
let dec = gst::ElementFactory::make("sodiumdecrypter", None).unwrap(); let dec = gst::ElementFactory::make("sodiumdecrypter")
dec.set_property("sender-key", &*SENDER_PUBLIC); .property("sender-key", &*SENDER_PUBLIC)
dec.set_property("receiver-key", &*RECEIVER_PRIVATE); .property("receiver-key", &*RECEIVER_PRIVATE)
.build()
.unwrap();
// the typefind element here is cause the decrypter only supports // the typefind element here is cause the decrypter only supports
// operating in pull mode bu the filesink wants push-mode. // operating in pull mode bu the filesink wants push-mode.
let typefind = gst::ElementFactory::make("typefind", None).unwrap(); let typefind = gst::ElementFactory::make("typefind").build().unwrap();
let sink = gst::ElementFactory::make("appsink", None).unwrap(); let sink = gst::ElementFactory::make("appsink").build().unwrap();
pipeline pipeline
.add_many(&[&filesrc, &dec, &typefind, &sink]) .add_many(&[&filesrc, &dec, &typefind, &sink])
@ -160,12 +164,16 @@ fn test_pull_range() {
r r
}; };
let filesrc = gst::ElementFactory::make("filesrc", None).unwrap(); let filesrc = gst::ElementFactory::make("filesrc")
filesrc.set_property("location", input_path.to_str().unwrap()); .property("location", input_path.to_str().unwrap())
.build()
.unwrap();
let dec = gst::ElementFactory::make("sodiumdecrypter", None).unwrap(); let dec = gst::ElementFactory::make("sodiumdecrypter")
dec.set_property("sender-key", &*SENDER_PUBLIC); .property("sender-key", &*SENDER_PUBLIC)
dec.set_property("receiver-key", &*RECEIVER_PRIVATE); .property("receiver-key", &*RECEIVER_PRIVATE)
.build()
.unwrap();
pipeline pipeline
.add_many(&[&filesrc, &dec]) .add_many(&[&filesrc, &dec])
@ -265,33 +273,43 @@ fn test_state_changes() {
// NullToReady without keys provided // NullToReady without keys provided
{ {
let dec = gst::ElementFactory::make("sodiumdecrypter", None).unwrap(); let dec = gst::ElementFactory::make("sodiumdecrypter")
.build()
.unwrap();
assert!(dec.change_state(gst::StateChange::NullToReady).is_err()); assert!(dec.change_state(gst::StateChange::NullToReady).is_err());
// Set only receiver key // Set only receiver key
let dec = gst::ElementFactory::make("sodiumdecrypter", None).unwrap(); let dec = gst::ElementFactory::make("sodiumdecrypter")
dec.set_property("receiver-key", &*RECEIVER_PRIVATE); .property("receiver-key", &*RECEIVER_PRIVATE)
.build()
.unwrap();
assert!(dec.change_state(gst::StateChange::NullToReady).is_err()); assert!(dec.change_state(gst::StateChange::NullToReady).is_err());
// Set only sender key // Set only sender key
let dec = gst::ElementFactory::make("sodiumdecrypter", None).unwrap(); let dec = gst::ElementFactory::make("sodiumdecrypter")
dec.set_property("sender-key", &*SENDER_PUBLIC); .property("sender-key", &*SENDER_PUBLIC)
.build()
.unwrap();
assert!(dec.change_state(gst::StateChange::NullToReady).is_err()); assert!(dec.change_state(gst::StateChange::NullToReady).is_err());
} }
// NullToReady, no nonce provided // NullToReady, no nonce provided
{ {
let dec = gst::ElementFactory::make("sodiumdecrypter", None).unwrap(); let dec = gst::ElementFactory::make("sodiumdecrypter")
dec.set_property("sender-key", &*SENDER_PUBLIC); .property("sender-key", &*SENDER_PUBLIC)
dec.set_property("receiver-key", &*RECEIVER_PRIVATE); .property("receiver-key", &*RECEIVER_PRIVATE)
.build()
.unwrap();
assert!(dec.change_state(gst::StateChange::NullToReady).is_ok()); assert!(dec.change_state(gst::StateChange::NullToReady).is_ok());
} }
// ReadyToNull // ReadyToNull
{ {
let dec = gst::ElementFactory::make("sodiumdecrypter", None).unwrap(); let dec = gst::ElementFactory::make("sodiumdecrypter")
dec.set_property("sender-key", &*SENDER_PUBLIC); .property("sender-key", &*SENDER_PUBLIC)
dec.set_property("receiver-key", &*RECEIVER_PRIVATE); .property("receiver-key", &*RECEIVER_PRIVATE)
.build()
.unwrap();
assert!(dec.change_state(gst::StateChange::NullToReady).is_ok()); assert!(dec.change_state(gst::StateChange::NullToReady).is_ok());
} }
} }

View file

@ -73,10 +73,12 @@ fn encrypt_file() {
let mut adapter = gst_base::UniqueAdapter::new(); let mut adapter = gst_base::UniqueAdapter::new();
let enc = gst::ElementFactory::make("sodiumencrypter", None).unwrap(); let enc = gst::ElementFactory::make("sodiumencrypter")
enc.set_property("sender-key", &*SENDER_PRIVATE); .property("sender-key", &*SENDER_PRIVATE)
enc.set_property("receiver-key", &*RECEIVER_PUBLIC); .property("receiver-key", &*RECEIVER_PUBLIC)
enc.set_property("block-size", 1024u32); .property("block-size", 1024u32)
.build()
.unwrap();
let mut h = gst_check::Harness::with_element(&enc, None, None); let mut h = gst_check::Harness::with_element(&enc, None, None);
h.add_element_src_pad(&enc.static_pad("src").expect("failed to get src pad")); h.add_element_src_pad(&enc.static_pad("src").expect("failed to get src pad"));
@ -109,33 +111,43 @@ fn test_state_changes() {
// NullToReady without keys provided // NullToReady without keys provided
{ {
let enc = gst::ElementFactory::make("sodiumencrypter", None).unwrap(); let enc = gst::ElementFactory::make("sodiumencrypter")
.build()
.unwrap();
assert!(enc.change_state(gst::StateChange::NullToReady).is_err()); assert!(enc.change_state(gst::StateChange::NullToReady).is_err());
// Set only receiver key // Set only receiver key
let enc = gst::ElementFactory::make("sodiumencrypter", None).unwrap(); let enc = gst::ElementFactory::make("sodiumencrypter")
enc.set_property("receiver-key", &*RECEIVER_PUBLIC); .property("receiver-key", &*RECEIVER_PUBLIC)
.build()
.unwrap();
assert!(enc.change_state(gst::StateChange::NullToReady).is_err()); assert!(enc.change_state(gst::StateChange::NullToReady).is_err());
// Set only sender key // Set only sender key
let enc = gst::ElementFactory::make("sodiumencrypter", None).unwrap(); let enc = gst::ElementFactory::make("sodiumencrypter")
enc.set_property("sender-key", &*SENDER_PRIVATE); .property("sender-key", &*SENDER_PRIVATE)
.build()
.unwrap();
assert!(enc.change_state(gst::StateChange::NullToReady).is_err()); assert!(enc.change_state(gst::StateChange::NullToReady).is_err());
} }
// NullToReady // NullToReady
{ {
let enc = gst::ElementFactory::make("sodiumencrypter", None).unwrap(); let enc = gst::ElementFactory::make("sodiumencrypter")
enc.set_property("sender-key", &*SENDER_PRIVATE); .property("sender-key", &*SENDER_PRIVATE)
enc.set_property("receiver-key", &*RECEIVER_PUBLIC); .property("receiver-key", &*RECEIVER_PUBLIC)
.build()
.unwrap();
assert!(enc.change_state(gst::StateChange::NullToReady).is_ok()); assert!(enc.change_state(gst::StateChange::NullToReady).is_ok());
} }
// ReadyToNull // ReadyToNull
{ {
let enc = gst::ElementFactory::make("sodiumencrypter", None).unwrap(); let enc = gst::ElementFactory::make("sodiumencrypter")
enc.set_property("sender-key", &*SENDER_PRIVATE); .property("sender-key", &*SENDER_PRIVATE)
enc.set_property("receiver-key", &*RECEIVER_PUBLIC); .property("receiver-key", &*RECEIVER_PUBLIC)
.build()
.unwrap();
assert!(enc.change_state(gst::StateChange::NullToReady).is_ok()); assert!(enc.change_state(gst::StateChange::NullToReady).is_ok());
} }
} }

View file

@ -77,11 +77,13 @@ fn main() {
for i in 0..n_streams { for i in 0..n_streams {
let build_context = || format!("context-{}", (i as u32) % n_groups); let build_context = || format!("context-{}", (i as u32) % n_groups);
let sink = let sink = gst::ElementFactory::make("fakesink")
gst::ElementFactory::make("fakesink", Some(format!("sink-{}", i).as_str())).unwrap(); .name(format!("sink-{}", i).as_str())
sink.set_property("sync", false); .property("sync", false)
sink.set_property("async", false); .property("async", false)
sink.set_property("signal-handoffs", true); .property("signal-handoffs", true)
.build()
.unwrap();
sink.connect( sink.connect(
"handoff", "handoff",
true, true,
@ -93,22 +95,24 @@ fn main() {
let (source, context) = match source.as_str() { let (source, context) = match source.as_str() {
"udpsrc" => { "udpsrc" => {
let source = let source = gst::ElementFactory::make("udpsrc")
gst::ElementFactory::make("udpsrc", Some(format!("source-{}", i).as_str())) .name(format!("source-{}", i).as_str())
.unwrap(); .property("port", 40000i32 + i as i32)
source.set_property("port", 40000i32 + i as i32); .property("retrieve-sender-address", false)
source.set_property("retrieve-sender-address", false); .build()
.unwrap();
(source, None) (source, None)
} }
"ts-udpsrc" => { "ts-udpsrc" => {
let context = build_context(); let context = build_context();
let source = let source = gst::ElementFactory::make("ts-udpsrc")
gst::ElementFactory::make("ts-udpsrc", Some(format!("source-{}", i).as_str())) .name(format!("source-{}", i).as_str())
.unwrap(); .property("port", 40000i32 + i as i32)
source.set_property("port", 40000i32 + i as i32); .property("context", &context)
source.set_property("context", &context); .property("context-wait", wait)
source.set_property("context-wait", wait); .build()
.unwrap();
if is_rtp { if is_rtp {
source.set_property("caps", &rtp_caps); source.set_property("caps", &rtp_caps);
@ -117,37 +121,34 @@ fn main() {
(source, Some(context)) (source, Some(context))
} }
"tcpclientsrc" => { "tcpclientsrc" => {
let source = gst::ElementFactory::make( let source = gst::ElementFactory::make("tcpclientsrc")
"tcpclientsrc", .name(format!("source-{}", i).as_str())
Some(format!("source-{}", i).as_str()), .property("host", "127.0.0.1")
) .property("port", 40000i32)
.unwrap(); .build()
source.set_property("host", "127.0.0.1"); .unwrap();
source.set_property("port", 40000i32);
(source, None) (source, None)
} }
"ts-tcpclientsrc" => { "ts-tcpclientsrc" => {
let context = build_context(); let context = build_context();
let source = gst::ElementFactory::make( let source = gst::ElementFactory::make("ts-tcpclientsrc")
"ts-tcpclientsrc", .name(format!("source-{}", i).as_str())
Some(format!("source-{}", i).as_str()), .property("host", "127.0.0.1")
) .property("port", 40000i32)
.unwrap(); .property("context", &context)
source.set_property("host", "127.0.0.1"); .property("context-wait", wait)
source.set_property("port", 40000i32); .build()
source.set_property("context", &context); .unwrap();
source.set_property("context-wait", wait);
(source, Some(context)) (source, Some(context))
} }
"tonegeneratesrc" => { "tonegeneratesrc" => {
let source = gst::ElementFactory::make( let source = gst::ElementFactory::make("tonegeneratesrc")
"tonegeneratesrc", .name(format!("source-{}", i).as_str())
Some(format!("source-{}", i).as_str()), .property("samplesperbuffer", (wait as i32) * 8000 / 1000)
) .build()
.unwrap(); .unwrap();
source.set_property("samplesperbuffer", (wait as i32) * 8000 / 1000);
sink.set_property("sync", true); sink.set_property("sync", true);
@ -155,12 +156,13 @@ fn main() {
} }
"ts-tonesrc" => { "ts-tonesrc" => {
let context = build_context(); let context = build_context();
let source = let source = gst::ElementFactory::make("ts-tonesrc")
gst::ElementFactory::make("ts-tonesrc", Some(format!("source-{}", i).as_str())) .name(format!("source-{}", i).as_str())
.unwrap(); .property("samples-per-buffer", (wait as u32) * 8000 / 1000)
source.set_property("samples-per-buffer", (wait as u32) * 8000 / 1000); .property("context", &context)
source.set_property("context", &context); .property("context-wait", wait)
source.set_property("context-wait", wait); .build()
.unwrap();
(source, Some(context)) (source, Some(context))
} }
@ -168,28 +170,33 @@ fn main() {
}; };
if is_rtp { if is_rtp {
let jb = let jb = gst::ElementFactory::make("ts-jitterbuffer")
gst::ElementFactory::make("ts-jitterbuffer", Some(format!("jb-{}", i).as_str())) .name(format!("jb-{}", i).as_str())
.unwrap(); .property("context-wait", wait)
.property("latency", wait)
.build()
.unwrap();
if let Some(context) = context { if let Some(context) = context {
jb.set_property("context", &context); jb.set_property("context", &context);
} }
jb.set_property("context-wait", wait);
jb.set_property("latency", wait);
let elements = &[&source, &jb, &sink]; let elements = &[&source, &jb, &sink];
pipeline.add_many(elements).unwrap(); pipeline.add_many(elements).unwrap();
gst::Element::link_many(elements).unwrap(); gst::Element::link_many(elements).unwrap();
} else { } else {
let queue = if let Some(context) = context { let queue = if let Some(context) = context {
let queue = let queue = gst::ElementFactory::make("ts-queue")
gst::ElementFactory::make("ts-queue", Some(format!("queue-{}", i).as_str())) .name(format!("queue-{}", i).as_str())
.unwrap(); .property("context", &context)
queue.set_property("context", &context); .property("context-wait", wait)
queue.set_property("context-wait", wait); .build()
.unwrap();
queue queue
} else { } else {
gst::ElementFactory::make("queue2", Some(format!("queue-{}", i).as_str())).unwrap() gst::ElementFactory::make("queue")
.name(format!("queue-{}", i).as_str())
.build()
.unwrap()
}; };
let elements = &[&source, &queue, &sink]; let elements = &[&source, &queue, &sink];

View file

@ -133,23 +133,21 @@ fn main() {
for i in 0..args.streams { for i in 0..args.streams {
let ctx_name = format!("standalone {}", i % args.groups); let ctx_name = format!("standalone {}", i % args.groups);
let src = gst::ElementFactory::make( let src = gst::ElementFactory::make("ts-standalone-test-src")
"ts-standalone-test-src", .name(format!("src-{}", i).as_str())
Some(format!("src-{}", i).as_str()), .property("context", &ctx_name)
) .property("context-wait", args.wait)
.unwrap(); .property("push-period", args.push_period)
src.set_property("context", &ctx_name); .property("num-buffers", args.num_buffers)
src.set_property("context-wait", args.wait); .build()
src.set_property("push-period", args.push_period); .unwrap();
src.set_property("num-buffers", args.num_buffers);
let sink = gst::ElementFactory::make( let sink = gst::ElementFactory::make("ts-standalone-test-sink")
"ts-standalone-test-sink", .name(format!("sink-{}", i).as_str())
Some(format!("sink-{}", i).as_str()), .property("context", &ctx_name)
) .property("context-wait", args.wait)
.unwrap(); .build()
sink.set_property("context", &ctx_name); .unwrap();
sink.set_property("context-wait", args.wait);
if i == 0 { if i == 0 {
src.set_property("raise-log-level", true); src.set_property("raise-log-level", true);

View file

@ -92,21 +92,27 @@ fn send_rtp_buffers(n_streams: u16) {
let l = glib::MainLoop::new(None, false); let l = glib::MainLoop::new(None, false);
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
for i in 0..n_streams { for i in 0..n_streams {
let src = let src = gst::ElementFactory::make("audiotestsrc")
gst::ElementFactory::make("audiotestsrc", Some(format!("audiotestsrc-{}", i).as_str())) .name(format!("audiotestsrc-{}", i).as_str())
.unwrap(); .build()
.unwrap();
src.set_property("is-live", true); src.set_property("is-live", true);
let enc = let enc = gst::ElementFactory::make("alawenc")
gst::ElementFactory::make("alawenc", Some(format!("alawenc-{}", i).as_str())).unwrap(); .name(format!("alawenc-{}", i).as_str())
let pay = .build()
gst::ElementFactory::make("rtppcmapay", Some(format!("rtppcmapay-{}", i).as_str())) .unwrap();
.unwrap(); let pay = gst::ElementFactory::make("rtppcmapay")
let sink = gst::ElementFactory::make("ts-udpsink", Some(format!("udpsink-{}", i).as_str())) .name(format!("rtppcmapay-{}", i).as_str())
.build()
.unwrap();
let sink = gst::ElementFactory::make("ts-udpsink")
.name(format!("udpsink-{}", i).as_str())
.property("clients", format!("127.0.0.1:{}", i + 40000))
.property("context", "context-udpsink")
.property("context-wait", 20u32)
.build()
.unwrap(); .unwrap();
sink.set_property("clients", format!("127.0.0.1:{}", i + 40000));
sink.set_property("context", "context-udpsink");
sink.set_property("context-wait", 20u32);
let elements = &[&src, &enc, &pay, &sink]; let elements = &[&src, &enc, &pay, &sink];
pipeline.add_many(elements).unwrap(); pipeline.add_many(elements).unwrap();

View file

@ -33,7 +33,9 @@ fn init() {
fn test_active_pad() { fn test_active_pad() {
init(); init();
let is = gst::ElementFactory::make("ts-input-selector", None).unwrap(); let is = gst::ElementFactory::make("ts-input-selector")
.build()
.unwrap();
let mut h1 = gst_check::Harness::with_element(&is, Some("sink_%u"), Some("src")); let mut h1 = gst_check::Harness::with_element(&is, Some("sink_%u"), Some("src"));
let mut h2 = gst_check::Harness::with_element(&is, Some("sink_%u"), None); let mut h2 = gst_check::Harness::with_element(&is, Some("sink_%u"), None);

View file

@ -51,25 +51,45 @@ fn jb_pipeline() {
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
let src = gst::ElementFactory::make("audiotestsrc", Some("audiotestsrc")).unwrap(); let src = gst::ElementFactory::make("audiotestsrc")
src.set_property("is-live", true); .name("audiotestsrc")
src.set_property("num-buffers", BUFFER_NB); .property("is-live", true)
.property("num-buffers", BUFFER_NB)
.build()
.unwrap();
let enc = gst::ElementFactory::make("alawenc", Some("alawenc")).unwrap(); let enc = gst::ElementFactory::make("alawenc")
let pay = gst::ElementFactory::make("rtppcmapay", Some("rtppcmapay")).unwrap(); .name("alawenc")
.build()
.unwrap();
let pay = gst::ElementFactory::make("rtppcmapay")
.name("rtppcmapay")
.build()
.unwrap();
let jb = gst::ElementFactory::make("ts-jitterbuffer", Some("ts-jitterbuffer")).unwrap(); let jb = gst::ElementFactory::make("ts-jitterbuffer")
jb.set_property("context", "jb_pipeline"); .name("ts-jitterbuffer")
jb.set_property("context-wait", CONTEXT_WAIT); .property("context", "jb_pipeline")
jb.set_property("latency", LATENCY); .property("context-wait", CONTEXT_WAIT)
.property("latency", LATENCY)
.build()
.unwrap();
let depay = gst::ElementFactory::make("rtppcmadepay", Some("rtppcmadepay")).unwrap(); let depay = gst::ElementFactory::make("rtppcmadepay")
let dec = gst::ElementFactory::make("alawdec", Some("alawdec")).unwrap(); .name("rtppcmadepay")
.build()
.unwrap();
let dec = gst::ElementFactory::make("alawdec")
.name("alawdec")
.build()
.unwrap();
let sink = gst::ElementFactory::make("appsink", Some("appsink")).unwrap(); let sink = gst::ElementFactory::make("appsink")
sink.set_property("sync", false); .name("appsink")
sink.set_property("async", false); .property("sync", false)
sink.set_property("emit-signals", true); .property("async", false)
.build()
.unwrap();
pipeline pipeline
.add_many(&[&src, &enc, &pay, &jb, &depay, &dec, &sink]) .add_many(&[&src, &enc, &pay, &jb, &depay, &dec, &sink])
@ -110,29 +130,52 @@ fn jb_ts_pipeline() {
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
let src = gst::ElementFactory::make("audiotestsrc", Some("audiotestsrc")).unwrap(); let src = gst::ElementFactory::make("audiotestsrc")
src.set_property("is-live", true); .name("audiotestsrc")
src.set_property("num-buffers", BUFFER_NB); .property("is-live", true)
.property("num-buffers", BUFFER_NB)
.build()
.unwrap();
let queue = gst::ElementFactory::make("ts-queue", Some("ts-queue")).unwrap(); let queue = gst::ElementFactory::make("ts-queue")
queue.set_property("context", "jb_ts_pipeline_queue"); .name("ts-queue")
queue.set_property("context-wait", CONTEXT_WAIT); .property("context", "jb_ts_pipeline_queue")
.property("context-wait", CONTEXT_WAIT)
.build()
.unwrap();
let enc = gst::ElementFactory::make("alawenc", Some("alawenc")).unwrap(); let enc = gst::ElementFactory::make("alawenc")
let pay = gst::ElementFactory::make("rtppcmapay", Some("rtppcmapay")).unwrap(); .name("alawenc")
.build()
.unwrap();
let pay = gst::ElementFactory::make("rtppcmapay")
.name("rtppcmapay")
.build()
.unwrap();
let jb = gst::ElementFactory::make("ts-jitterbuffer", Some("ts-jitterbuffer")).unwrap(); let jb = gst::ElementFactory::make("ts-jitterbuffer")
jb.set_property("context", "jb_ts_pipeline"); .name("ts-jitterbuffer")
jb.set_property("context-wait", CONTEXT_WAIT); .property("context", "jb_ts_pipeline")
jb.set_property("latency", LATENCY); .property("context-wait", CONTEXT_WAIT)
.property("latency", LATENCY)
.build()
.unwrap();
let depay = gst::ElementFactory::make("rtppcmadepay", Some("rtppcmadepay")).unwrap(); let depay = gst::ElementFactory::make("rtppcmadepay")
let dec = gst::ElementFactory::make("alawdec", Some("alawdec")).unwrap(); .name("rtppcmadepay")
.build()
.unwrap();
let dec = gst::ElementFactory::make("alawdec")
.name("alawdec")
.build()
.unwrap();
let sink = gst::ElementFactory::make("appsink", Some("appsink")).unwrap(); let sink = gst::ElementFactory::make("appsink")
sink.set_property("sync", false); .name("appsink")
sink.set_property("async", false); .property("sync", false)
sink.set_property("emit-signals", true); .property("async", false)
.build()
.unwrap();
pipeline pipeline
.add_many(&[&src, &queue, &enc, &pay, &jb, &depay, &dec, &sink]) .add_many(&[&src, &queue, &enc, &pay, &jb, &depay, &dec, &sink])

View file

@ -892,9 +892,12 @@ fn src_tsqueue_sink_nominal() {
let name = "src_tsqueue_sink"; let name = "src_tsqueue_sink";
let ts_queue = gst::ElementFactory::make("ts-queue", Some("ts-queue")).unwrap(); let ts_queue = gst::ElementFactory::make("ts-queue")
ts_queue.set_property("context", format!("{}_queue", name)); .name("ts-queue")
ts_queue.set_property("context-wait", THROTTLING_DURATION.as_millis() as u32); .property("context", format!("{}_queue", name))
.property("context-wait", THROTTLING_DURATION.as_millis() as u32)
.build()
.unwrap();
let (pipeline, src_element, _sink_element, receiver) = setup(name, Some(ts_queue), None); let (pipeline, src_element, _sink_element, receiver) = setup(name, Some(ts_queue), None);
@ -907,7 +910,10 @@ fn src_queue_sink_nominal() {
let name = "src_queue_sink"; let name = "src_queue_sink";
let queue = gst::ElementFactory::make("queue", Some("queue")).unwrap(); let queue = gst::ElementFactory::make("queue")
.name("queue")
.build()
.unwrap();
let (pipeline, src_element, _sink_element, receiver) = setup(name, Some(queue), None); let (pipeline, src_element, _sink_element, receiver) = setup(name, Some(queue), None);
nominal_scenario(name, pipeline, src_element, receiver); nominal_scenario(name, pipeline, src_element, receiver);
@ -919,13 +925,19 @@ fn src_tsproxy_sink_nominal() {
let name = "src_tsproxy_sink"; let name = "src_tsproxy_sink";
let ts_proxy_sink = gst::ElementFactory::make("ts-proxysink", Some("ts-proxysink")).unwrap(); let ts_proxy_sink = gst::ElementFactory::make("ts-proxysink")
ts_proxy_sink.set_property("proxy-context", format!("{}_proxy_context", name)); .name("ts-proxysink")
.property("proxy-context", format!("{}_proxy_context", name))
.build()
.unwrap();
let ts_proxy_src = gst::ElementFactory::make("ts-proxysrc", Some("ts-proxysrc")).unwrap(); let ts_proxy_src = gst::ElementFactory::make("ts-proxysrc")
ts_proxy_src.set_property("proxy-context", format!("{}_proxy_context", name)); .name("ts-proxysrc")
ts_proxy_src.set_property("context", format!("{}_context", name)); .property("proxy-context", format!("{}_proxy_context", name))
ts_proxy_src.set_property("context-wait", THROTTLING_DURATION.as_millis() as u32); .property("context", format!("{}_context", name))
.property("context-wait", THROTTLING_DURATION.as_millis() as u32)
.build()
.unwrap();
let (pipeline, src_element, _sink_element, receiver) = let (pipeline, src_element, _sink_element, receiver) =
setup(name, Some(ts_proxy_sink), Some(ts_proxy_src)); setup(name, Some(ts_proxy_sink), Some(ts_proxy_src));

View file

@ -63,22 +63,27 @@ fn multiple_contexts_queue() {
let (sender, receiver) = mpsc::channel(); let (sender, receiver) = mpsc::channel();
for i in 0..SRC_NB { for i in 0..SRC_NB {
let src = let src = gst::ElementFactory::make("ts-udpsrc")
gst::ElementFactory::make("ts-udpsrc", Some(format!("src-{}", i).as_str())).unwrap(); .name(format!("src-{}", i).as_str())
src.set_property("context", format!("context-{}", (i as u32) % CONTEXT_NB)); .property("context", format!("context-{}", (i as u32) % CONTEXT_NB))
src.set_property("context-wait", CONTEXT_WAIT); .property("context-wait", CONTEXT_WAIT)
src.set_property("port", (FIRST_PORT + i) as i32); .property("port", (FIRST_PORT + i) as i32)
.build()
.unwrap();
let queue = let queue = gst::ElementFactory::make("ts-queue")
gst::ElementFactory::make("ts-queue", Some(format!("queue-{}", i).as_str())).unwrap(); .name(format!("queue-{}", i).as_str())
queue.set_property("context", format!("context-{}", (i as u32) % CONTEXT_NB)); .property("context", format!("context-{}", (i as u32) % CONTEXT_NB))
queue.set_property("context-wait", CONTEXT_WAIT); .property("context-wait", CONTEXT_WAIT)
.build()
.unwrap();
let sink = let sink = gst::ElementFactory::make("appsink")
gst::ElementFactory::make("appsink", Some(format!("sink-{}", i).as_str())).unwrap(); .name(format!("sink-{}", i).as_str())
sink.set_property("sync", false); .property("sync", false)
sink.set_property("async", false); .property("async", false)
sink.set_property("emit-signals", true); .build()
.unwrap();
pipeline.add_many(&[&src, &queue, &sink]).unwrap(); pipeline.add_many(&[&src, &queue, &sink]).unwrap();
gst::Element::link_many(&[&src, &queue, &sink]).unwrap(); gst::Element::link_many(&[&src, &queue, &sink]).unwrap();
@ -194,38 +199,36 @@ fn multiple_contexts_proxy() {
for i in 0..SRC_NB { for i in 0..SRC_NB {
let pipeline_index = i + OFFSET; let pipeline_index = i + OFFSET;
let src = gst::ElementFactory::make( let src = gst::ElementFactory::make("ts-udpsrc")
"ts-udpsrc", .name(format!("src-{}", pipeline_index).as_str())
Some(format!("src-{}", pipeline_index).as_str()), .property("context", format!("context-{}", (i as u32) % CONTEXT_NB))
) .property("context-wait", CONTEXT_WAIT)
.unwrap(); .property("port", (FIRST_PORT + i) as i32)
src.set_property("context", format!("context-{}", (i as u32) % CONTEXT_NB)); .build()
src.set_property("context-wait", CONTEXT_WAIT); .unwrap();
src.set_property("port", (FIRST_PORT + i) as i32);
let proxysink = gst::ElementFactory::make( let proxysink = gst::ElementFactory::make("ts-proxysink")
"ts-proxysink", .name(format!("proxysink-{}", pipeline_index).as_str())
Some(format!("proxysink-{}", pipeline_index).as_str()), .property("proxy-context", format!("proxy-{}", pipeline_index))
) .build()
.unwrap(); .unwrap();
proxysink.set_property("proxy-context", format!("proxy-{}", pipeline_index));
let proxysrc = gst::ElementFactory::make(
"ts-proxysrc",
Some(format!("proxysrc-{}", pipeline_index).as_str()),
)
.unwrap();
proxysrc.set_property(
"context",
&format!("context-{}", (pipeline_index as u32) % CONTEXT_NB),
);
proxysrc.set_property("proxy-context", format!("proxy-{}", pipeline_index));
let sink = let proxysrc = gst::ElementFactory::make("ts-proxysrc")
gst::ElementFactory::make("appsink", Some(format!("sink-{}", pipeline_index).as_str())) .name(format!("proxysrc-{}", pipeline_index).as_str())
.unwrap(); .property(
sink.set_property("sync", false); "context",
sink.set_property("async", false); &format!("context-{}", (pipeline_index as u32) % CONTEXT_NB),
sink.set_property("emit-signals", true); )
.property("proxy-context", format!("proxy-{}", pipeline_index))
.build()
.unwrap();
let sink = gst::ElementFactory::make("appsink")
.name(format!("sink-{}", pipeline_index).as_str())
.property("sync", false)
.property("async", false)
.build()
.unwrap();
pipeline pipeline
.add_many(&[&src, &proxysink, &proxysrc, &sink]) .add_many(&[&src, &proxysink, &proxysrc, &sink])
@ -331,23 +334,30 @@ fn eos() {
let caps = gst::Caps::builder("foo/bar").build(); let caps = gst::Caps::builder("foo/bar").build();
let src = gst::ElementFactory::make("ts-appsrc", Some("src-eos")).unwrap(); let src = gst::ElementFactory::make("ts-appsrc")
src.set_property("caps", &caps); .name("src-eos")
src.set_property("do-timestamp", true); .property("caps", &caps)
src.set_property("context", &CONTEXT); .property("do-timestamp", true)
.property("context", &CONTEXT)
.build()
.unwrap();
let queue = gst::ElementFactory::make("ts-queue", Some("queue-eos")).unwrap(); let queue = gst::ElementFactory::make("ts-queue")
queue.set_property("context", &CONTEXT); .name("queue-eos")
.property("context", &CONTEXT)
.build()
.unwrap();
let appsink = gst::ElementFactory::make("appsink", Some("sink-eos")).unwrap(); let appsink = gst::ElementFactory::make("appsink")
.name("sink-eos")
.property("sync", false)
.property("async", false)
.build()
.unwrap();
pipeline.add_many(&[&src, &queue, &appsink]).unwrap(); pipeline.add_many(&[&src, &queue, &appsink]).unwrap();
gst::Element::link_many(&[&src, &queue, &appsink]).unwrap(); gst::Element::link_many(&[&src, &queue, &appsink]).unwrap();
appsink.set_property("sync", false);
appsink.set_property("async", false);
appsink.set_property("emit-signals", true);
let (sample_notifier, sample_notif_rcv) = mpsc::channel(); let (sample_notifier, sample_notif_rcv) = mpsc::channel();
let (eos_notifier, eos_notif_rcv) = mpsc::channel(); let (eos_notifier, eos_notif_rcv) = mpsc::channel();
let appsink = appsink.dynamic_cast::<gst_app::AppSink>().unwrap(); let appsink = appsink.dynamic_cast::<gst_app::AppSink>().unwrap();
@ -455,26 +465,33 @@ fn premature_shutdown() {
let caps = gst::Caps::builder("foo/bar").build(); let caps = gst::Caps::builder("foo/bar").build();
let src = gst::ElementFactory::make("ts-appsrc", Some("src-ps")).unwrap(); let src = gst::ElementFactory::make("ts-appsrc")
src.set_property("caps", &caps); .name("src-ps")
src.set_property("do-timestamp", true); .property("caps", &caps)
src.set_property("context", "appsrc-context"); .property("do-timestamp", true)
src.set_property("context-wait", APPSRC_CONTEXT_WAIT); .property("context", "appsrc-context")
.property("context-wait", APPSRC_CONTEXT_WAIT)
.build()
.unwrap();
let queue = gst::ElementFactory::make("ts-queue", Some("queue-ps")).unwrap(); let queue = gst::ElementFactory::make("ts-queue")
queue.set_property("context", "queue-context"); .name("queue-ps")
queue.set_property("context-wait", QUEUE_CONTEXT_WAIT); .property("context", "queue-context")
queue.set_property("max-size-buffers", QUEUE_ITEMS_CAPACITY); .property("context-wait", QUEUE_CONTEXT_WAIT)
.property("max-size-buffers", QUEUE_ITEMS_CAPACITY)
.build()
.unwrap();
let appsink = gst::ElementFactory::make("appsink", Some("sink-ps")).unwrap(); let appsink = gst::ElementFactory::make("appsink")
.name("sink-ps")
.property("sync", false)
.property("async", false)
.build()
.unwrap();
pipeline.add_many(&[&src, &queue, &appsink]).unwrap(); pipeline.add_many(&[&src, &queue, &appsink]).unwrap();
gst::Element::link_many(&[&src, &queue, &appsink]).unwrap(); gst::Element::link_many(&[&src, &queue, &appsink]).unwrap();
appsink.set_property("emit-signals", true);
appsink.set_property("sync", false);
appsink.set_property("async", false);
let (appsink_sender, appsink_receiver) = mpsc::channel(); let (appsink_sender, appsink_receiver) = mpsc::channel();
let appsink = appsink.dynamic_cast::<gst_app::AppSink>().unwrap(); let appsink = appsink.dynamic_cast::<gst_app::AppSink>().unwrap();
@ -605,9 +622,6 @@ fn socket_play_null_play() {
let l = glib::MainLoop::new(None, false); let l = glib::MainLoop::new(None, false);
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
let sink =
gst::ElementFactory::make("ts-udpsink", Some(format!("sink-{}", TEST).as_str())).unwrap();
let socket = gio::Socket::new( let socket = gio::Socket::new(
SocketFamily::Ipv4, SocketFamily::Ipv4,
SocketType::Datagram, SocketType::Datagram,
@ -621,9 +635,13 @@ fn socket_play_null_play() {
) )
.unwrap(); .unwrap();
sink.set_property("socket", &socket); let sink = gst::ElementFactory::make("ts-udpsink")
sink.set_property("context", &TEST); .name(format!("sink-{}", TEST).as_str())
sink.set_property("context-wait", 20u32); .property("socket", &socket)
.property("context", &TEST)
.property("context-wait", 20u32)
.build()
.unwrap();
pipeline.add(&sink).unwrap(); pipeline.add(&sink).unwrap();

View file

@ -36,10 +36,22 @@ fn test_push() {
init(); init();
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
let fakesrc = gst::ElementFactory::make("fakesrc", None).unwrap(); let fakesrc = gst::ElementFactory::make("fakesrc")
let proxysink = gst::ElementFactory::make("ts-proxysink", Some("proxysink::test1")).unwrap(); .property("num-buffers", 3i32)
let proxysrc = gst::ElementFactory::make("ts-proxysrc", Some("proxysrc::test1")).unwrap(); .build()
let appsink = gst::ElementFactory::make("appsink", None).unwrap(); .unwrap();
let proxysink = gst::ElementFactory::make("ts-proxysink")
.name("proxysink::test1")
.property("proxy-context", "proxy::test1_proxy")
.build()
.unwrap();
let proxysrc = gst::ElementFactory::make("ts-proxysrc")
.name("proxysrc::test1")
.property("proxy-context", "proxy::test1_proxy")
.property("context", "proxy::test")
.build()
.unwrap();
let appsink = gst::ElementFactory::make("appsink").build().unwrap();
pipeline pipeline
.add_many(&[&fakesrc, &proxysink, &proxysrc, &appsink]) .add_many(&[&fakesrc, &proxysink, &proxysrc, &appsink])
@ -47,13 +59,6 @@ fn test_push() {
fakesrc.link(&proxysink).unwrap(); fakesrc.link(&proxysink).unwrap();
proxysrc.link(&appsink).unwrap(); proxysrc.link(&appsink).unwrap();
fakesrc.set_property("num-buffers", 3i32);
proxysink.set_property("proxy-context", "proxy::test1_proxy");
proxysrc.set_property("proxy-context", "proxy::test1_proxy");
proxysrc.set_property("context", "proxy::test");
appsink.set_property("emit-signals", true);
let samples = Arc::new(Mutex::new(Vec::new())); let samples = Arc::new(Mutex::new(Vec::new()));
let appsink = appsink.dynamic_cast::<gst_app::AppSink>().unwrap(); let appsink = appsink.dynamic_cast::<gst_app::AppSink>().unwrap();
@ -102,12 +107,21 @@ fn test_from_pipeline_to_pipeline() {
init(); init();
let pipe_1 = gst::Pipeline::new(None); let pipe_1 = gst::Pipeline::new(None);
let fakesrc = gst::ElementFactory::make("fakesrc", None).unwrap(); let fakesrc = gst::ElementFactory::make("fakesrc").build().unwrap();
let pxsink = gst::ElementFactory::make("ts-proxysink", Some("proxysink::test2")).unwrap(); let pxsink = gst::ElementFactory::make("ts-proxysink")
.name("proxysink::test2")
.property("proxy-context", "proxy::test2_proxy")
.build()
.unwrap();
let pipe_2 = gst::Pipeline::new(None); let pipe_2 = gst::Pipeline::new(None);
let pxsrc = gst::ElementFactory::make("ts-proxysrc", Some("proxysrc::test2")).unwrap(); let pxsrc = gst::ElementFactory::make("ts-proxysrc")
let fakesink = gst::ElementFactory::make("fakesink", None).unwrap(); .name("proxysrc::test2")
.property("proxy-context", "proxy::test2_proxy")
.property("context", "proxy::test")
.build()
.unwrap();
let fakesink = gst::ElementFactory::make("fakesink").build().unwrap();
pipe_1.add_many(&[&fakesrc, &pxsink]).unwrap(); pipe_1.add_many(&[&fakesrc, &pxsink]).unwrap();
fakesrc.link(&pxsink).unwrap(); fakesrc.link(&pxsink).unwrap();
@ -115,10 +129,6 @@ fn test_from_pipeline_to_pipeline() {
pipe_2.add_many(&[&pxsrc, &fakesink]).unwrap(); pipe_2.add_many(&[&pxsrc, &fakesink]).unwrap();
pxsrc.link(&fakesink).unwrap(); pxsrc.link(&fakesink).unwrap();
pxsink.set_property("proxy-context", "proxy::test2_proxy");
pxsrc.set_property("proxy-context", "proxy::test2_proxy");
pxsrc.set_property("context", "proxy::test");
pipe_1.set_state(gst::State::Paused).unwrap(); pipe_1.set_state(gst::State::Paused).unwrap();
pipe_2.set_state(gst::State::Paused).unwrap(); pipe_2.set_state(gst::State::Paused).unwrap();
@ -135,12 +145,30 @@ fn test_from_pipeline_to_pipeline_and_back() {
init(); init();
let pipe_1 = gst::Pipeline::new(None); let pipe_1 = gst::Pipeline::new(None);
let pxsrc_1 = gst::ElementFactory::make("ts-proxysrc", Some("proxysrc1::test3")).unwrap(); let pxsrc_1 = gst::ElementFactory::make("ts-proxysrc")
let pxsink_1 = gst::ElementFactory::make("ts-proxysink", Some("proxysink1::test3")).unwrap(); .name("proxysrc1::test3")
.property("proxy-context", "proxy::test3_proxy1")
.property("context", "proxy::test")
.build()
.unwrap();
let pxsink_1 = gst::ElementFactory::make("ts-proxysink")
.name("proxysink1::test3")
.property("proxy-context", "proxy::test3_proxy2")
.build()
.unwrap();
let pipe_2 = gst::Pipeline::new(None); let pipe_2 = gst::Pipeline::new(None);
let pxsrc_2 = gst::ElementFactory::make("ts-proxysrc", Some("proxysrc2::test3")).unwrap(); let pxsrc_2 = gst::ElementFactory::make("ts-proxysrc")
let pxsink_2 = gst::ElementFactory::make("ts-proxysink", Some("proxysink2::test3")).unwrap(); .name("proxysrc2::test3")
.property("proxy-context", "proxy::test3_proxy2")
.property("context", "proxy::test")
.build()
.unwrap();
let pxsink_2 = gst::ElementFactory::make("ts-proxysink")
.name("proxysink2::test3")
.property("proxy-context", "proxy::test3_proxy1")
.build()
.unwrap();
pipe_1.add_many(&[&pxsrc_1, &pxsink_1]).unwrap(); pipe_1.add_many(&[&pxsrc_1, &pxsink_1]).unwrap();
pxsrc_1.link(&pxsink_1).unwrap(); pxsrc_1.link(&pxsink_1).unwrap();
@ -148,14 +176,6 @@ fn test_from_pipeline_to_pipeline_and_back() {
pipe_2.add_many(&[&pxsrc_2, &pxsink_2]).unwrap(); pipe_2.add_many(&[&pxsrc_2, &pxsink_2]).unwrap();
pxsrc_2.link(&pxsink_2).unwrap(); pxsrc_2.link(&pxsink_2).unwrap();
pxsrc_1.set_property("proxy-context", "proxy::test3_proxy1");
pxsrc_1.set_property("context", "proxy::test");
pxsink_2.set_property("proxy-context", "proxy::test3_proxy1");
pxsrc_2.set_property("proxy-context", "proxy::test3_proxy2");
pxsrc_2.set_property("context", "proxy::test");
pxsink_1.set_property("proxy-context", "proxy::test3_proxy2");
pipe_1.set_state(gst::State::Paused).unwrap(); pipe_1.set_state(gst::State::Paused).unwrap();
pipe_2.set_state(gst::State::Paused).unwrap(); pipe_2.set_state(gst::State::Paused).unwrap();

View file

@ -36,18 +36,17 @@ fn test_push() {
init(); init();
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
let fakesrc = gst::ElementFactory::make("fakesrc", None).unwrap(); let fakesrc = gst::ElementFactory::make("fakesrc")
let queue = gst::ElementFactory::make("ts-queue", None).unwrap(); .property("num-buffers", 3i32)
let appsink = gst::ElementFactory::make("appsink", None).unwrap(); .build()
.unwrap();
let queue = gst::ElementFactory::make("ts-queue").build().unwrap();
let appsink = gst::ElementFactory::make("appsink").build().unwrap();
pipeline.add_many(&[&fakesrc, &queue, &appsink]).unwrap(); pipeline.add_many(&[&fakesrc, &queue, &appsink]).unwrap();
fakesrc.link(&queue).unwrap(); fakesrc.link(&queue).unwrap();
queue.link(&appsink).unwrap(); queue.link(&appsink).unwrap();
fakesrc.set_property("num-buffers", 3i32);
appsink.set_property("emit-signals", true);
let samples = Arc::new(Mutex::new(Vec::new())); let samples = Arc::new(Mutex::new(Vec::new()));
let appsink = appsink.dynamic_cast::<gst_app::AppSink>().unwrap(); let appsink = appsink.dynamic_cast::<gst_app::AppSink>().unwrap();

View file

@ -56,20 +56,21 @@ fn test_push() {
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
let tcpclientsrc = gst::ElementFactory::make("ts-tcpclientsrc", None).unwrap(); let caps = gst::Caps::builder("foo/bar").build();
let appsink = gst::ElementFactory::make("appsink", None).unwrap(); let tcpclientsrc = gst::ElementFactory::make("ts-tcpclientsrc")
appsink.set_property("sync", false); .property("caps", &caps)
appsink.set_property("async", false); .property("port", 5000i32)
.build()
.unwrap();
let appsink = gst::ElementFactory::make("appsink")
.property("sync", false)
.property("async", false)
.build()
.unwrap();
pipeline.add_many(&[&tcpclientsrc, &appsink]).unwrap(); pipeline.add_many(&[&tcpclientsrc, &appsink]).unwrap();
tcpclientsrc.link(&appsink).unwrap(); tcpclientsrc.link(&appsink).unwrap();
let caps = gst::Caps::builder("foo/bar").build();
tcpclientsrc.set_property("caps", &caps);
tcpclientsrc.set_property("port", 5000i32);
appsink.set_property("emit-signals", true);
let samples = Arc::new(Mutex::new(Vec::new())); let samples = Arc::new(Mutex::new(Vec::new()));
let appsink = appsink.dynamic_cast::<gst_app::AppSink>().unwrap(); let appsink = appsink.dynamic_cast::<gst_app::AppSink>().unwrap();

View file

@ -410,9 +410,14 @@ impl ObjectSubclass for S3HlsSink {
fn with_class(_klass: &Self::Class) -> Self { fn with_class(_klass: &Self::Class) -> Self {
/* Prefer hlssink3 here due to it's support for media playlist types */ /* Prefer hlssink3 here due to it's support for media playlist types */
let hlssink = match gst::ElementFactory::make("hlssink3", Some("hlssink3")) { let hlssink = match gst::ElementFactory::make("hlssink3")
.name("hlssink3")
.build()
{
Ok(element) => element, Ok(element) => element,
Err(_) => gst::ElementFactory::make("hlssink2", Some("hlssink2")) Err(_) => gst::ElementFactory::make("hlssink2")
.name("hlssink2")
.build()
.expect("Could not find hlssink2. Need hlssink2 or hlssink3."), .expect("Could not find hlssink2. Need hlssink2 or hlssink3."),
}; };

View file

@ -76,9 +76,13 @@ struct Settings {
impl Default for Settings { impl Default for Settings {
fn default() -> Self { fn default() -> Self {
let splitmuxsink = gst::ElementFactory::make("splitmuxsink", Some("split_mux_sink")) let splitmuxsink = gst::ElementFactory::make("splitmuxsink")
.name("split_mux_sink")
.build()
.expect("Could not make element splitmuxsink"); .expect("Could not make element splitmuxsink");
let giostreamsink = gst::ElementFactory::make("giostreamsink", Some("giostream_sink")) let giostreamsink = gst::ElementFactory::make("giostreamsink")
.name("giostream_sink")
.build()
.expect("Could not make element giostreamsink"); .expect("Could not make element giostreamsink");
Self { Self {
location: String::from(DEFAULT_LOCATION), location: String::from(DEFAULT_LOCATION),
@ -619,7 +623,9 @@ impl ObjectImpl for HlsSink3 {
let settings = self.settings.lock().unwrap(); let settings = self.settings.lock().unwrap();
let mux = gst::ElementFactory::make("mpegtsmux", Some("mpeg-ts_mux")) let mux = gst::ElementFactory::make("mpegtsmux")
.name("mpeg-ts_mux")
.build()
.expect("Could not make element mpegtsmux"); .expect("Could not make element mpegtsmux");
let location: Option<String> = None; let location: Option<String> = None;

View file

@ -37,7 +37,7 @@ macro_rules! try_or_pause {
macro_rules! try_create_element { macro_rules! try_create_element {
($l:expr, $n:expr) => { ($l:expr, $n:expr) => {
match gst::ElementFactory::find($l) { match gst::ElementFactory::find($l) {
Some(factory) => factory.create(Some($n)).unwrap(), Some(factory) => factory.create().name($n).build().unwrap(),
None => { None => {
eprintln!("Could not find {} ({}) plugin, skipping test", $l, $n); eprintln!("Could not find {} ({}) plugin, skipping test", $l, $n);
return Ok(()); return Ok(());
@ -114,11 +114,13 @@ fn test_hlssink3_element_with_video_content() -> Result<(), ()> {
let x264enc = try_create_element!("x264enc"); let x264enc = try_create_element!("x264enc");
let h264parse = try_create_element!("h264parse"); let h264parse = try_create_element!("h264parse");
let hlssink3 = gst::ElementFactory::make("hlssink3", Some("test_hlssink3")) let hlssink3 = gst::ElementFactory::make("hlssink3")
.name("test_hlssink3")
.property("target-duration", 2u32)
.property("playlist-length", 2u32)
.property("max-files", 2u32)
.build()
.expect("Must be able to instantiate hlssink3"); .expect("Must be able to instantiate hlssink3");
hlssink3.set_property("target-duration", 2u32);
hlssink3.set_property("playlist-length", 2u32);
hlssink3.set_property("max-files", 2u32);
hlssink3.set_property("playlist-type", HlsSink3PlaylistType::Event); hlssink3.set_property("playlist-type", HlsSink3PlaylistType::Event);
let pl_type: HlsSink3PlaylistType = hlssink3.property("playlist-type"); let pl_type: HlsSink3PlaylistType = hlssink3.property("playlist-type");
@ -257,13 +259,14 @@ fn test_hlssink3_element_with_audio_content() -> Result<(), ()> {
audio_src.set_property("is-live", true); audio_src.set_property("is-live", true);
audio_src.set_property("num-buffers", BUFFER_NB); audio_src.set_property("num-buffers", BUFFER_NB);
let hls_avenc_aac = try_or_pause!(gst::ElementFactory::make( let hls_avenc_aac = try_or_pause!(gst::ElementFactory::make("avenc_aac")
"avenc_aac", .name("hls_avenc_aac")
Some("hls_avenc_aac") .build());
)); let hlssink3 = gst::ElementFactory::make("hlssink3")
let hlssink3 = gst::ElementFactory::make("hlssink3", Some("hlssink3")) .name("hlssink3")
.property("target-duration", 6u32)
.build()
.expect("Must be able to instantiate hlssink3"); .expect("Must be able to instantiate hlssink3");
hlssink3.set_property("target-duration", 6u32);
hlssink3.connect("get-playlist-stream", false, move |_args| { hlssink3.connect("get-playlist-stream", false, move |_args| {
let stream = gio::MemoryOutputStream::new_resizable(); let stream = gio::MemoryOutputStream::new_resizable();
@ -322,13 +325,13 @@ fn test_hlssink3_write_correct_playlist_content() -> Result<(), ()> {
let x264enc = try_create_element!("x264enc"); let x264enc = try_create_element!("x264enc");
let h264parse = try_create_element!("h264parse"); let h264parse = try_create_element!("h264parse");
let hlssink3 = gst::ElementFactory::make("hlssink3", Some("test_hlssink3")) let hlssink3 = gst::ElementFactory::make("hlssink3")
.name("test_hlssink3")
.property("location", "/www/media/segments/my-own-filename-%03d.ts")
.property("playlist-location", "/www/media/main.m3u8")
.property("playlist-root", "segments")
.build()
.expect("Must be able to instantiate hlssink3"); .expect("Must be able to instantiate hlssink3");
hlssink3.set_properties(&[
("location", &"/www/media/segments/my-own-filename-%03d.ts"),
("playlist-location", &"/www/media/main.m3u8"),
("playlist-root", &"segments"),
]);
let (hls_events_sender, hls_events_receiver) = mpsc::sync_channel(20); let (hls_events_sender, hls_events_receiver) = mpsc::sync_channel(20);
let playlist_content = Arc::new(Mutex::new(String::from(""))); let playlist_content = Arc::new(Mutex::new(String::from("")));

View file

@ -41,7 +41,7 @@ impl RaptorqTest {
fn new() -> Self { fn new() -> Self {
init(); init();
let enc = gst::ElementFactory::make("raptorqenc", None).unwrap(); let enc = gst::ElementFactory::make("raptorqenc").build().unwrap();
let protected_packets = enc.property::<u32>("protected-packets") as usize; let protected_packets = enc.property::<u32>("protected-packets") as usize;
let repair_packets = enc.property::<u32>("repair-packets") as usize; let repair_packets = enc.property::<u32>("repair-packets") as usize;
@ -117,13 +117,14 @@ impl RaptorqTest {
assert!(self.input_buffers >= self.protected_packets); assert!(self.input_buffers >= self.protected_packets);
// 1. Decoder Setup: // 1. Decoder Setup:
let enc = gst::ElementFactory::make("raptorqenc", None).unwrap(); let enc = gst::ElementFactory::make("raptorqenc")
.property("protected-packets", self.protected_packets as u32)
enc.set_property("protected-packets", self.protected_packets as u32); .property("repair-packets", self.repair_packets as u32)
enc.set_property("repair-packets", self.repair_packets as u32); .property("repair-window", self.repair_window as u32)
enc.set_property("repair-window", self.repair_window as u32); .property("symbol-size", self.symbol_size as u32)
enc.set_property("symbol-size", self.symbol_size as u32); .property("mtu", self.mtu as u32)
enc.set_property("mtu", self.mtu as u32); .build()
.unwrap();
let mut h_enc = gst_check::Harness::with_element(&enc, Some("sink"), Some("src")); let mut h_enc = gst_check::Harness::with_element(&enc, Some("sink"), Some("src"));
let mut h_enc_fec = gst_check::Harness::with_element(&enc, None, Some("fec_0")); let mut h_enc_fec = gst_check::Harness::with_element(&enc, None, Some("fec_0"));
@ -131,7 +132,7 @@ impl RaptorqTest {
h_enc.set_src_caps_str("application/x-rtp,clock-rate=8000"); h_enc.set_src_caps_str("application/x-rtp,clock-rate=8000");
// 2. Decoder Setup: // 2. Decoder Setup:
let dec = gst::ElementFactory::make("raptorqdec", None).unwrap(); let dec = gst::ElementFactory::make("raptorqdec").build().unwrap();
let mut h_dec = gst_check::Harness::with_element(&dec, Some("sink"), Some("src")); let mut h_dec = gst_check::Harness::with_element(&dec, Some("sink"), Some("src"));
let mut h_dec_fec = gst_check::Harness::with_element(&dec, Some("fec_0"), None); let mut h_dec_fec = gst_check::Harness::with_element(&dec, Some("fec_0"), None);
@ -438,12 +439,13 @@ fn test_raptorq_wrapping_sequence_number_3() {
fn test_raptorq_encoder_flush_cancels_pending_timers() { fn test_raptorq_encoder_flush_cancels_pending_timers() {
init(); init();
let enc = gst::ElementFactory::make("raptorqenc", None).unwrap(); let enc = gst::ElementFactory::make("raptorqenc")
// Set delay to 5s, this way each buffer should be delayed by 1s
// Set delay to 5s, this way each buffer should be delayed by 1s .property("repair-window", 5000u32)
enc.set_property("repair-window", 5000u32); .property("protected-packets", 5u32)
enc.set_property("protected-packets", 5u32); .property("repair-packets", 5u32)
enc.set_property("repair-packets", 5u32); .build()
.unwrap();
let mut h_enc = gst_check::Harness::with_element(&enc, Some("sink"), Some("src")); let mut h_enc = gst_check::Harness::with_element(&enc, Some("sink"), Some("src"));
let mut h_enc_fec = gst_check::Harness::with_element(&enc, None, Some("fec_0")); let mut h_enc_fec = gst_check::Harness::with_element(&enc, None, Some("fec_0"));
@ -504,12 +506,13 @@ fn test_raptorq_encoder_flush_cancels_pending_timers() {
fn test_raptorq_repair_window_tolerance() { fn test_raptorq_repair_window_tolerance() {
init(); init();
let enc = gst::ElementFactory::make("raptorqenc", None).unwrap(); let enc = gst::ElementFactory::make("raptorqenc")
// Set delay to 5s, this way each buffer should be delayed by 1s
// Set delay to 5s, this way each buffer should be delayed by 1s .property("repair-window", 1000u32)
enc.set_property("repair-window", 1000u32); .property("protected-packets", 5u32)
enc.set_property("protected-packets", 5u32); .property("repair-packets", 5u32)
enc.set_property("repair-packets", 5u32); .build()
.unwrap();
let mut h_enc = gst_check::Harness::with_element(&enc, Some("sink"), Some("src")); let mut h_enc = gst_check::Harness::with_element(&enc, Some("sink"), Some("src"));
let mut h_enc_fec = gst_check::Harness::with_element(&enc, None, Some("fec_0")); let mut h_enc_fec = gst_check::Harness::with_element(&enc, None, Some("fec_0"));
@ -531,9 +534,10 @@ fn test_raptorq_repair_window_tolerance() {
assert!(result.is_ok()); assert!(result.is_ok());
} }
let dec = gst::ElementFactory::make("raptorqdec", None).unwrap(); let dec = gst::ElementFactory::make("raptorqdec")
.property("repair-window-tolerance", 1000u32)
dec.set_property("repair-window-tolerance", 1000u32); .build()
.unwrap();
let mut h_dec = gst_check::Harness::with_element(&dec, Some("sink"), Some("src")); let mut h_dec = gst_check::Harness::with_element(&dec, Some("sink"), Some("src"));
let mut h_dec_fec = gst_check::Harness::with_element(&dec, Some("fec_0"), None); let mut h_dec_fec = gst_check::Harness::with_element(&dec, Some("fec_0"), None);

View file

@ -63,7 +63,7 @@ impl Harness {
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
// Create the HTTP source // Create the HTTP source
let src = gst::ElementFactory::make("reqwesthttpsrc", None).unwrap(); let src = gst::ElementFactory::make("reqwesthttpsrc").build().unwrap();
// Sender/receiver for the messages we generate from various places for the tests // Sender/receiver for the messages we generate from various places for the tests
// //
@ -1193,8 +1193,10 @@ fn test_proxy_prop_souphttpsrc_compatibility() {
fn assert_proxy_set(set_to: Option<&str>, expected: Option<&str>) { fn assert_proxy_set(set_to: Option<&str>, expected: Option<&str>) {
// The same assertions should hold for "souphttpsrc". // The same assertions should hold for "souphttpsrc".
let src = gst::ElementFactory::make("reqwesthttpsrc", None).unwrap(); let src = gst::ElementFactory::make("reqwesthttpsrc")
src.set_property("proxy", set_to); .property("proxy", set_to)
.build()
.unwrap();
assert_eq!(src.property::<Option<String>>("proxy").as_deref(), expected); assert_eq!(src.property::<Option<String>>("proxy").as_deref(), expected);
} }

View file

@ -80,7 +80,9 @@ pub struct WhipSink {
impl Default for WhipSink { impl Default for WhipSink {
fn default() -> Self { fn default() -> Self {
let webrtcbin = gst::ElementFactory::make("webrtcbin", Some("whip-webrtcbin")) let webrtcbin = gst::ElementFactory::make("webrtcbin")
.name("whip-webrtcbin")
.build()
.expect("Failed to create webrtcbin"); .expect("Failed to create webrtcbin");
Self { Self {
settings: Mutex::new(Settings::default()), settings: Mutex::new(Settings::default()),

View file

@ -63,9 +63,12 @@ impl ObjectSubclass for ProgressBin {
let srcpad = gst::GhostPad::from_template(&templ, Some("src")); let srcpad = gst::GhostPad::from_template(&templ, Some("src"));
// Create the progressreport element. // Create the progressreport element.
let progress = gst::ElementFactory::make("progressreport", Some("progress")).unwrap(); let progress = gst::ElementFactory::make("progressreport")
// Don't let progressreport print to stdout itself .name("progress")
progress.set_property("silent", true); // Don't let progressreport print to stdout itself
.property("silent", true)
.build()
.unwrap();
// Return an instance of our struct // Return an instance of our struct
Self { Self {

View file

@ -32,11 +32,13 @@ fn create_pipeline() -> (gst::Pipeline, gst::Pad, gst::Element) {
.unwrap() .unwrap()
.upcast(); .upcast();
let fallbackswitch = gst::ElementFactory::make("fallbackswitch", None).unwrap(); let fallbackswitch = gst::ElementFactory::make("fallbackswitch")
fallbackswitch.set_property("timeout", gst::ClockTime::SECOND); .property("timeout", gst::ClockTime::SECOND)
.build()
.unwrap();
let decodebin = gst::ElementFactory::make("decodebin", None).unwrap(); let decodebin = gst::ElementFactory::make("decodebin").build().unwrap();
let videoconvert = gst::ElementFactory::make("videoconvert", None).unwrap(); let videoconvert = gst::ElementFactory::make("videoconvert").build().unwrap();
let videoconvert_clone = videoconvert.clone(); let videoconvert_clone = videoconvert.clone();
decodebin.connect_pad_added(move |_, pad| { decodebin.connect_pad_added(move |_, pad| {
@ -50,7 +52,9 @@ fn create_pipeline() -> (gst::Pipeline, gst::Pad, gst::Element) {
} }
}); });
let video_sink = gst::ElementFactory::make("gtk4paintablesink", None).unwrap(); let video_sink = gst::ElementFactory::make("gtk4paintablesink")
.build()
.unwrap();
pipeline pipeline
.add_many(&[ .add_many(&[

View file

@ -896,30 +896,35 @@ impl FallbackSrc {
fn create_dummy_audio_source(filter_caps: &gst::Caps, min_latency: gst::ClockTime) -> gst::Bin { fn create_dummy_audio_source(filter_caps: &gst::Caps, min_latency: gst::ClockTime) -> gst::Bin {
let bin = gst::Bin::new(None); let bin = gst::Bin::new(None);
let audiotestsrc = gst::ElementFactory::make("audiotestsrc", Some("audiosrc")) let audiotestsrc = gst::ElementFactory::make("audiotestsrc")
.name("audiosrc")
.property_from_str("wave", "silence")
.property("is-live", true)
.build()
.expect("No audiotestsrc found"); .expect("No audiotestsrc found");
let audioconvert = gst::ElementFactory::make("audioconvert", Some("audio_audioconvert")) let audioconvert = gst::ElementFactory::make("audioconvert")
.name("audio_audioconvert")
.build()
.expect("No audioconvert found"); .expect("No audioconvert found");
let audioresample = gst::ElementFactory::make("audioresample", Some("audio_audioresample")) let audioresample = gst::ElementFactory::make("audioresample")
.name("audio_audioresample")
.build()
.expect("No audioresample found"); .expect("No audioresample found");
let capsfilter = gst::ElementFactory::make("capsfilter", Some("audio_capsfilter")) let capsfilter = gst::ElementFactory::make("capsfilter")
.name("audio_capsfilter")
.property("caps", filter_caps)
.build()
.expect("No capsfilter found"); .expect("No capsfilter found");
let queue = gst::ElementFactory::make("queue", None).expect("No queue found"); let queue = gst::ElementFactory::make("queue")
.property("max-size-bytes", 0u32)
audiotestsrc.set_property_from_str("wave", "silence"); .property("max-size-buffers", 0u32)
audiotestsrc.set_property("is-live", true); .property("max-size-time", cmp::max(min_latency, 1.seconds()))
.build()
capsfilter.set_property("caps", filter_caps); .expect("No queue found");
queue.set_properties(&[
("max-size-bytes", &0u32),
("max-size-buffers", &0u32),
("max-size-time", &(cmp::max(min_latency, 1.seconds()))),
]);
bin.add_many(&[ bin.add_many(&[
&audiotestsrc, &audiotestsrc,
@ -950,30 +955,35 @@ impl FallbackSrc {
fn create_dummy_video_source(filter_caps: &gst::Caps, min_latency: gst::ClockTime) -> gst::Bin { fn create_dummy_video_source(filter_caps: &gst::Caps, min_latency: gst::ClockTime) -> gst::Bin {
let bin = gst::Bin::new(None); let bin = gst::Bin::new(None);
let videotestsrc = gst::ElementFactory::make("videotestsrc", Some("videosrc")) let videotestsrc = gst::ElementFactory::make("videotestsrc")
.name("videosrc")
.property_from_str("pattern", "black")
.property("is-live", true)
.build()
.expect("No videotestsrc found"); .expect("No videotestsrc found");
let videoconvert = gst::ElementFactory::make("videoconvert", Some("video_videoconvert")) let videoconvert = gst::ElementFactory::make("videoconvert")
.name("video_videoconvert")
.build()
.expect("No videoconvert found"); .expect("No videoconvert found");
let videoscale = gst::ElementFactory::make("videoscale", Some("video_videoscale")) let videoscale = gst::ElementFactory::make("videoscale")
.name("video_videoscale")
.build()
.expect("No videoscale found"); .expect("No videoscale found");
let capsfilter = gst::ElementFactory::make("capsfilter", Some("video_capsfilter")) let capsfilter = gst::ElementFactory::make("capsfilter")
.name("video_capsfilter")
.property("caps", filter_caps)
.build()
.expect("No capsfilter found"); .expect("No capsfilter found");
let queue = gst::ElementFactory::make("queue", None).expect("No queue found"); let queue = gst::ElementFactory::make("queue")
.property("max-size-bytes", 0u32)
videotestsrc.set_property_from_str("pattern", "black"); .property("max-size-buffers", 0u32)
videotestsrc.set_property("is-live", true); .property("max-size-time", cmp::max(min_latency, 1.seconds()))
.build()
capsfilter.set_property("caps", filter_caps); .expect("No queue found");
queue.set_properties(&[
("max-size-bytes", &0u32),
("max-size-buffers", &0u32),
("max-size-time", &(cmp::max(min_latency, 1.seconds()))),
]);
bin.add_many(&[ bin.add_many(&[
&videotestsrc, &videotestsrc,
@ -1006,16 +1016,17 @@ impl FallbackSrc {
let source = match source { let source = match source {
Source::Uri(ref uri) => { Source::Uri(ref uri) => {
let source = gst::ElementFactory::make("uridecodebin3", Some("uridecodebin"))
.expect("No uridecodebin3 found");
let uri = self let uri = self
.instance() .instance()
.emit_by_name::<glib::GString>("update-uri", &[uri]); .emit_by_name::<glib::GString>("update-uri", &[uri]);
source.set_property("uri", uri); let source = gst::ElementFactory::make("uridecodebin3")
source.set_property("use-buffering", true); .name("uridecodebin")
source.set_property("buffer-duration", buffer_duration); .property("uri", uri)
.property("use-buffering", true)
.property("buffer-duration", buffer_duration)
.build()
.expect("No uridecodebin3 found");
source source
} }
@ -1081,11 +1092,13 @@ impl FallbackSrc {
) -> Option<SourceBin> { ) -> Option<SourceBin> {
let source: gst::Element = match fallback_uri { let source: gst::Element = match fallback_uri {
Some(uri) => { Some(uri) => {
let dbin = gst::ElementFactory::make("uridecodebin3", Some("uridecodebin")) let dbin = gst::ElementFactory::make("uridecodebin3")
.name("uridecodebin")
.property("uri", uri)
.property("use-buffering", true)
.property("buffer-duration", buffer_duration)
.build()
.expect("No uridecodebin3 found"); .expect("No uridecodebin3 found");
dbin.set_property("uri", uri);
dbin.set_property("use-buffering", true);
dbin.set_property("buffer-duration", buffer_duration);
dbin dbin
} }
@ -1156,15 +1169,15 @@ impl FallbackSrc {
dummy_source: &gst::Bin, dummy_source: &gst::Bin,
filter_caps: &gst::Caps, filter_caps: &gst::Caps,
) -> Stream { ) -> Stream {
let switch = let switch = gst::ElementFactory::make("fallbackswitch")
gst::ElementFactory::make("fallbackswitch", None).expect("No fallbackswitch found"); .property("timeout", timeout.nseconds())
.property("min-upstream-latency", min_latency.nseconds())
.property("immediate-fallback", immediate_fallback)
.build()
.expect("No fallbackswitch found");
self.instance().add(&switch).unwrap(); self.instance().add(&switch).unwrap();
switch.set_property("timeout", timeout.nseconds());
switch.set_property("min-upstream-latency", min_latency.nseconds());
switch.set_property("immediate-fallback", immediate_fallback);
let dummy_srcpad = dummy_source.static_pad("src").unwrap(); let dummy_srcpad = dummy_source.static_pad("src").unwrap();
let dummy_sinkpad = switch.request_pad_simple("sink_%u").unwrap(); let dummy_sinkpad = switch.request_pad_simple("sink_%u").unwrap();
dummy_srcpad.link(&dummy_sinkpad).unwrap(); dummy_srcpad.link(&dummy_sinkpad).unwrap();
@ -1686,14 +1699,19 @@ impl FallbackSrc {
let converters = if is_video { let converters = if is_video {
let bin = gst::Bin::new(None); let bin = gst::Bin::new(None);
let videoconvert = let videoconvert = gst::ElementFactory::make("videoconvert")
gst::ElementFactory::make("videoconvert", Some("video_videoconvert")) .name("video_videoconvert")
.expect("No videoconvert found"); .build()
.expect("No videoconvert found");
let videoscale = gst::ElementFactory::make("videoscale", Some("video_videoscale")) let videoscale = gst::ElementFactory::make("videoscale")
.name("video_videoscale")
.build()
.expect("No videoscale found"); .expect("No videoscale found");
let capsfilter = gst::ElementFactory::make("capsfilter", Some("video_capsfilter")) let capsfilter = gst::ElementFactory::make("capsfilter")
.name("video_capsfilter")
.build()
.expect("No capsfilter found"); .expect("No capsfilter found");
if fallback_source { if fallback_source {
@ -1721,15 +1739,19 @@ impl FallbackSrc {
} else { } else {
let bin = gst::Bin::new(None); let bin = gst::Bin::new(None);
let audioconvert = let audioconvert = gst::ElementFactory::make("audioconvert")
gst::ElementFactory::make("audioconvert", Some("audio_audioconvert")) .name("audio_audioconvert")
.expect("No audioconvert found"); .build()
.expect("No audioconvert found");
let audioresample = let audioresample = gst::ElementFactory::make("audioresample")
gst::ElementFactory::make("audioresample", Some("audio_audioresample")) .name("audio_audioresample")
.expect("No audioresample found"); .build()
.expect("No audioresample found");
let capsfilter = gst::ElementFactory::make("capsfilter", Some("audio_capsfilter")) let capsfilter = gst::ElementFactory::make("capsfilter")
.name("audio_capsfilter")
.build()
.expect("No capsfilter found"); .expect("No capsfilter found");
if fallback_source { if fallback_source {
@ -1756,20 +1778,24 @@ impl FallbackSrc {
bin.upcast() bin.upcast()
}; };
let queue = gst::ElementFactory::make("queue", None).unwrap(); let queue = gst::ElementFactory::make("queue")
queue.set_properties(&[ .property("max-size-bytes", 0u32)
("max-size-bytes", &0u32), .property("max-size-buffers", 0u32)
("max-size-buffers", &0u32), .property(
(
"max-size-time", "max-size-time",
&(cmp::max(state.settings.min_latency, 1.seconds())), cmp::max(state.settings.min_latency, 1.seconds()),
), )
]); .build()
let clocksync = gst::ElementFactory::make("clocksync", None).unwrap_or_else(|_| { .unwrap();
let identity = gst::ElementFactory::make("identity", None).unwrap(); let clocksync = gst::ElementFactory::make("clocksync")
identity.set_property("sync", true); .build()
identity .unwrap_or_else(|_| {
}); let identity = gst::ElementFactory::make("identity")
.property("sync", true)
.build()
.unwrap();
identity
});
source source
.source .source
@ -1790,10 +1816,11 @@ impl FallbackSrc {
let imagefreeze = if is_image { let imagefreeze = if is_image {
gst::debug!(CAT, imp: self, "Image stream, inserting imagefreeze"); gst::debug!(CAT, imp: self, "Image stream, inserting imagefreeze");
let imagefreeze = let imagefreeze = gst::ElementFactory::make("imagefreeze")
gst::ElementFactory::make("imagefreeze", None).expect("no imagefreeze found"); .property("is-live", true)
.build()
.expect("no imagefreeze found");
source.source.add(&imagefreeze).unwrap(); source.source.add(&imagefreeze).unwrap();
imagefreeze.set_property("is-live", true);
if imagefreeze.sync_state_with_parent().is_err() { if imagefreeze.sync_state_with_parent().is_err() {
gst::error!(CAT, imp: self, "imagefreeze failed to change state",); gst::error!(CAT, imp: self, "imagefreeze failed to change state",);

View file

@ -473,25 +473,30 @@ fn setup_pipeline(
pipeline.set_base_time(gst::ClockTime::SECOND); pipeline.set_base_time(gst::ClockTime::SECOND);
pipeline.set_start_time(gst::ClockTime::NONE); pipeline.set_start_time(gst::ClockTime::NONE);
let src = gst::ElementFactory::make("appsrc", Some("src")) let src = gst::ElementFactory::make("appsrc")
.name("src")
.build()
.unwrap() .unwrap()
.downcast::<gst_app::AppSrc>() .downcast::<gst_app::AppSrc>()
.unwrap(); .unwrap();
src.set_property("is-live", true); src.set_is_live(true);
src.set_property("format", gst::Format::Time); src.set_format(gst::Format::Time);
src.set_property("min-latency", LATENCY.nseconds() as i64); src.set_min_latency(LATENCY.nseconds() as i64);
src.set_property( src.set_caps(Some(
"caps", &gst_video::VideoCapsBuilder::new()
gst_video::VideoCapsBuilder::new()
.format(gst_video::VideoFormat::Argb) .format(gst_video::VideoFormat::Argb)
.width(320) .width(320)
.height(240) .height(240)
.framerate((0, 1).into()) .framerate((0, 1).into())
.build(), .build(),
); ));
let switch = gst::ElementFactory::make("fallbackswitch")
.name("switch")
.property("timeout", 3.seconds())
.build()
.unwrap();
let switch = gst::ElementFactory::make("fallbackswitch", Some("switch")).unwrap();
switch.set_property("timeout", 3.seconds());
if let Some(imm) = immediate_fallback { if let Some(imm) = immediate_fallback {
switch.set_property("immediate-fallback", imm); switch.set_property("immediate-fallback", imm);
} }
@ -499,13 +504,15 @@ fn setup_pipeline(
switch.set_property("auto-switch", auto_switch); switch.set_property("auto-switch", auto_switch);
} }
let sink = gst::ElementFactory::make("appsink", Some("sink")) let sink = gst::ElementFactory::make("appsink")
.name("sink")
.build()
.unwrap() .unwrap()
.downcast::<gst_app::AppSink>() .downcast::<gst_app::AppSink>()
.unwrap(); .unwrap();
sink.set_property("sync", false); sink.set_sync(false);
let queue = gst::ElementFactory::make("queue", None).unwrap(); let queue = gst::ElementFactory::make("queue").build().unwrap();
pipeline pipeline
.add_many(&[src.upcast_ref(), &switch, &queue, sink.upcast_ref()]) .add_many(&[src.upcast_ref(), &switch, &queue, sink.upcast_ref()])
@ -518,22 +525,23 @@ fn setup_pipeline(
sink_pad.set_property("priority", 0u32); sink_pad.set_property("priority", 0u32);
if let Some(live) = with_live_fallback { if let Some(live) = with_live_fallback {
let fallback_src = gst::ElementFactory::make("appsrc", Some("fallback-src")) let fallback_src = gst::ElementFactory::make("appsrc")
.name("fallback-src")
.build()
.unwrap() .unwrap()
.downcast::<gst_app::AppSrc>() .downcast::<gst_app::AppSrc>()
.unwrap(); .unwrap();
fallback_src.set_property("is-live", live); fallback_src.set_is_live(live);
fallback_src.set_property("format", gst::Format::Time); fallback_src.set_format(gst::Format::Time);
fallback_src.set_property("min-latency", LATENCY.nseconds() as i64); fallback_src.set_min_latency(LATENCY.nseconds() as i64);
fallback_src.set_property( fallback_src.set_caps(Some(
"caps", &gst_video::VideoCapsBuilder::new()
gst_video::VideoCapsBuilder::new()
.format(gst_video::VideoFormat::Argb) .format(gst_video::VideoFormat::Argb)
.width(160) .width(160)
.height(120) .height(120)
.framerate((0, 1).into()) .framerate((0, 1).into())
.build(), .build(),
); ));
pipeline.add(&fallback_src).unwrap(); pipeline.add(&fallback_src).unwrap();

View file

@ -23,54 +23,66 @@ fn create_pipeline() -> (
) { ) {
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
let video_src = gst::ElementFactory::make("videotestsrc", None).unwrap(); let video_src = gst::ElementFactory::make("videotestsrc")
video_src.set_property("is-live", true); .property("is-live", true)
video_src.set_property_from_str("pattern", "ball"); .property_from_str("pattern", "ball")
.build()
.unwrap();
let timeoverlay = gst::ElementFactory::make("timeoverlay", None).unwrap(); let timeoverlay = gst::ElementFactory::make("timeoverlay")
timeoverlay.set_property("font-desc", "Monospace 20"); .property("font-desc", "Monospace 20")
.build()
.unwrap();
let video_tee = gst::ElementFactory::make("tee", None).unwrap(); let video_tee = gst::ElementFactory::make("tee").build().unwrap();
let video_queue1 = gst::ElementFactory::make("queue", None).unwrap(); let video_queue1 = gst::ElementFactory::make("queue").build().unwrap();
let video_queue2 = gst::ElementFactory::make("queue", None).unwrap(); let video_queue2 = gst::ElementFactory::make("queue").build().unwrap();
let video_convert1 = gst::ElementFactory::make("videoconvert", None).unwrap(); let video_convert1 = gst::ElementFactory::make("videoconvert").build().unwrap();
let video_convert2 = gst::ElementFactory::make("videoconvert", None).unwrap(); let video_convert2 = gst::ElementFactory::make("videoconvert").build().unwrap();
let video_sink = gst::ElementFactory::make("gtk4paintablesink", None).unwrap(); let video_sink = gst::ElementFactory::make("gtk4paintablesink")
.build()
.unwrap();
let video_enc = gst::ElementFactory::make("x264enc", None).unwrap(); let video_enc = gst::ElementFactory::make("x264enc")
video_enc.set_property("rc-lookahead", 10i32); .property("rc-lookahead", 10i32)
video_enc.set_property("key-int-max", 30u32); .property("key-int-max", 30u32)
let video_parse = gst::ElementFactory::make("h264parse", None).unwrap(); .build()
.unwrap();
let video_parse = gst::ElementFactory::make("h264parse").build().unwrap();
let audio_src = gst::ElementFactory::make("audiotestsrc", None).unwrap(); let audio_src = gst::ElementFactory::make("audiotestsrc")
audio_src.set_property("is-live", true); .property("is-live", true)
audio_src.set_property_from_str("wave", "ticks"); .property_from_str("wave", "ticks")
.build()
.unwrap();
let audio_tee = gst::ElementFactory::make("tee", None).unwrap(); let audio_tee = gst::ElementFactory::make("tee").build().unwrap();
let audio_queue1 = gst::ElementFactory::make("queue", None).unwrap(); let audio_queue1 = gst::ElementFactory::make("queue").build().unwrap();
let audio_queue2 = gst::ElementFactory::make("queue", None).unwrap(); let audio_queue2 = gst::ElementFactory::make("queue").build().unwrap();
let audio_convert1 = gst::ElementFactory::make("audioconvert", None).unwrap(); let audio_convert1 = gst::ElementFactory::make("audioconvert").build().unwrap();
let audio_convert2 = gst::ElementFactory::make("audioconvert", None).unwrap(); let audio_convert2 = gst::ElementFactory::make("audioconvert").build().unwrap();
let audio_sink = gst::ElementFactory::make("autoaudiosink", None).unwrap(); let audio_sink = gst::ElementFactory::make("autoaudiosink").build().unwrap();
let audio_enc = gst::ElementFactory::make("lamemp3enc", None).unwrap(); let audio_enc = gst::ElementFactory::make("lamemp3enc").build().unwrap();
let audio_parse = gst::ElementFactory::make("mpegaudioparse", None).unwrap(); let audio_parse = gst::ElementFactory::make("mpegaudioparse").build().unwrap();
let togglerecord = gst::ElementFactory::make("togglerecord", None).unwrap(); let togglerecord = gst::ElementFactory::make("togglerecord").build().unwrap();
let mux_queue1 = gst::ElementFactory::make("queue", None).unwrap(); let mux_queue1 = gst::ElementFactory::make("queue").build().unwrap();
let mux_queue2 = gst::ElementFactory::make("queue", None).unwrap(); let mux_queue2 = gst::ElementFactory::make("queue").build().unwrap();
let mux = gst::ElementFactory::make("mp4mux", None).unwrap(); let mux = gst::ElementFactory::make("mp4mux").build().unwrap();
let file_sink = gst::ElementFactory::make("filesink", None).unwrap(); let file_sink = gst::ElementFactory::make("filesink")
file_sink.set_property("location", "recording.mp4"); .property("location", "recording.mp4")
file_sink.set_property("async", false); .property("async", false)
file_sink.set_property("sync", false); .property("sync", false)
.build()
.unwrap();
pipeline pipeline
.add_many(&[ .add_many(&[

View file

@ -43,8 +43,10 @@ fn setup_sender_receiver(
mpsc::Receiver<Either<gst::Buffer, gst::Event>>, mpsc::Receiver<Either<gst::Buffer, gst::Event>>,
thread::JoinHandle<()>, thread::JoinHandle<()>,
) { ) {
let fakesink = gst::ElementFactory::make("fakesink", None).unwrap(); let fakesink = gst::ElementFactory::make("fakesink")
fakesink.set_property("async", false); .property("async", false)
.build()
.unwrap();
pipeline.add(&fakesink).unwrap(); pipeline.add(&fakesink).unwrap();
let main_stream = pad == "src"; let main_stream = pad == "src";
@ -250,13 +252,13 @@ fn recv_buffers(
#[test] #[test]
fn test_create() { fn test_create() {
init(); init();
assert!(gst::ElementFactory::make("togglerecord", None).is_ok()); assert!(gst::ElementFactory::make("togglerecord").build().is_ok());
} }
#[test] #[test]
fn test_create_pads() { fn test_create_pads() {
init(); init();
let togglerecord = gst::ElementFactory::make("togglerecord", None).unwrap(); let togglerecord = gst::ElementFactory::make("togglerecord").build().unwrap();
let sinkpad = togglerecord.request_pad_simple("sink_%u").unwrap(); let sinkpad = togglerecord.request_pad_simple("sink_%u").unwrap();
let srcpad = sinkpad.iterate_internal_links().next().unwrap().unwrap(); let srcpad = sinkpad.iterate_internal_links().next().unwrap().unwrap();
@ -274,7 +276,7 @@ fn test_one_stream_open() {
init(); init();
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
let togglerecord = gst::ElementFactory::make("togglerecord", None).unwrap(); let togglerecord = gst::ElementFactory::make("togglerecord").build().unwrap();
pipeline.add(&togglerecord).unwrap(); pipeline.add(&togglerecord).unwrap();
let (sender_input, _, receiver_output, thread) = let (sender_input, _, receiver_output, thread) =
@ -306,7 +308,7 @@ fn test_one_stream_gaps_open() {
init(); init();
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
let togglerecord = gst::ElementFactory::make("togglerecord", None).unwrap(); let togglerecord = gst::ElementFactory::make("togglerecord").build().unwrap();
pipeline.add(&togglerecord).unwrap(); pipeline.add(&togglerecord).unwrap();
let (sender_input, _, receiver_output, thread) = let (sender_input, _, receiver_output, thread) =
@ -339,7 +341,7 @@ fn test_one_stream_close_open() {
init(); init();
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
let togglerecord = gst::ElementFactory::make("togglerecord", None).unwrap(); let togglerecord = gst::ElementFactory::make("togglerecord").build().unwrap();
pipeline.add(&togglerecord).unwrap(); pipeline.add(&togglerecord).unwrap();
let (sender_input, receiver_input_done, receiver_output, thread) = let (sender_input, receiver_input_done, receiver_output, thread) =
@ -373,7 +375,7 @@ fn test_one_stream_open_close() {
init(); init();
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
let togglerecord = gst::ElementFactory::make("togglerecord", None).unwrap(); let togglerecord = gst::ElementFactory::make("togglerecord").build().unwrap();
pipeline.add(&togglerecord).unwrap(); pipeline.add(&togglerecord).unwrap();
let (sender_input, receiver_input_done, receiver_output, thread) = let (sender_input, receiver_input_done, receiver_output, thread) =
@ -408,7 +410,7 @@ fn test_one_stream_open_close_open() {
init(); init();
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
let togglerecord = gst::ElementFactory::make("togglerecord", None).unwrap(); let togglerecord = gst::ElementFactory::make("togglerecord").build().unwrap();
pipeline.add(&togglerecord).unwrap(); pipeline.add(&togglerecord).unwrap();
let (sender_input, receiver_input_done, receiver_output, thread) = let (sender_input, receiver_input_done, receiver_output, thread) =
@ -452,7 +454,7 @@ fn test_two_stream_open() {
init(); init();
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
let togglerecord = gst::ElementFactory::make("togglerecord", None).unwrap(); let togglerecord = gst::ElementFactory::make("togglerecord").build().unwrap();
pipeline.add(&togglerecord).unwrap(); pipeline.add(&togglerecord).unwrap();
let (sender_input_1, receiver_input_done_1, receiver_output_1, thread_1) = let (sender_input_1, receiver_input_done_1, receiver_output_1, thread_1) =
@ -505,7 +507,7 @@ fn test_two_stream_open_shift() {
init(); init();
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
let togglerecord = gst::ElementFactory::make("togglerecord", None).unwrap(); let togglerecord = gst::ElementFactory::make("togglerecord").build().unwrap();
pipeline.add(&togglerecord).unwrap(); pipeline.add(&togglerecord).unwrap();
let (sender_input_1, receiver_input_done_1, receiver_output_1, thread_1) = let (sender_input_1, receiver_input_done_1, receiver_output_1, thread_1) =
@ -562,7 +564,7 @@ fn test_two_stream_open_shift_main() {
init(); init();
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
let togglerecord = gst::ElementFactory::make("togglerecord", None).unwrap(); let togglerecord = gst::ElementFactory::make("togglerecord").build().unwrap();
pipeline.add(&togglerecord).unwrap(); pipeline.add(&togglerecord).unwrap();
let (sender_input_1, receiver_input_done_1, receiver_output_1, thread_1) = let (sender_input_1, receiver_input_done_1, receiver_output_1, thread_1) =
@ -627,7 +629,7 @@ fn test_two_stream_open_close() {
init(); init();
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
let togglerecord = gst::ElementFactory::make("togglerecord", None).unwrap(); let togglerecord = gst::ElementFactory::make("togglerecord").build().unwrap();
pipeline.add(&togglerecord).unwrap(); pipeline.add(&togglerecord).unwrap();
let (sender_input_1, receiver_input_done_1, receiver_output_1, thread_1) = let (sender_input_1, receiver_input_done_1, receiver_output_1, thread_1) =
@ -696,7 +698,7 @@ fn test_two_stream_close_open() {
init(); init();
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
let togglerecord = gst::ElementFactory::make("togglerecord", None).unwrap(); let togglerecord = gst::ElementFactory::make("togglerecord").build().unwrap();
pipeline.add(&togglerecord).unwrap(); pipeline.add(&togglerecord).unwrap();
let (sender_input_1, receiver_input_done_1, receiver_output_1, thread_1) = let (sender_input_1, receiver_input_done_1, receiver_output_1, thread_1) =
@ -765,7 +767,7 @@ fn test_two_stream_open_close_open() {
init(); init();
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
let togglerecord = gst::ElementFactory::make("togglerecord", None).unwrap(); let togglerecord = gst::ElementFactory::make("togglerecord").build().unwrap();
pipeline.add(&togglerecord).unwrap(); pipeline.add(&togglerecord).unwrap();
let (sender_input_1, receiver_input_done_1, receiver_output_1, thread_1) = let (sender_input_1, receiver_input_done_1, receiver_output_1, thread_1) =
@ -859,7 +861,7 @@ fn test_two_stream_open_close_open_gaps() {
init(); init();
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
let togglerecord = gst::ElementFactory::make("togglerecord", None).unwrap(); let togglerecord = gst::ElementFactory::make("togglerecord").build().unwrap();
pipeline.add(&togglerecord).unwrap(); pipeline.add(&togglerecord).unwrap();
let (sender_input_1, receiver_input_done_1, receiver_output_1, thread_1) = let (sender_input_1, receiver_input_done_1, receiver_output_1, thread_1) =
@ -959,7 +961,7 @@ fn test_two_stream_close_open_close_delta() {
init(); init();
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
let togglerecord = gst::ElementFactory::make("togglerecord", None).unwrap(); let togglerecord = gst::ElementFactory::make("togglerecord").build().unwrap();
pipeline.add(&togglerecord).unwrap(); pipeline.add(&togglerecord).unwrap();
let (sender_input_1, receiver_input_done_1, receiver_output_1, thread_1) = let (sender_input_1, receiver_input_done_1, receiver_output_1, thread_1) =
@ -1048,7 +1050,7 @@ fn test_three_stream_open_close_open() {
init(); init();
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
let togglerecord = gst::ElementFactory::make("togglerecord", None).unwrap(); let togglerecord = gst::ElementFactory::make("togglerecord").build().unwrap();
pipeline.add(&togglerecord).unwrap(); pipeline.add(&togglerecord).unwrap();
let (sender_input_1, receiver_input_done_1, receiver_output_1, thread_1) = let (sender_input_1, receiver_input_done_1, receiver_output_1, thread_1) =
@ -1172,7 +1174,7 @@ fn test_two_stream_main_eos() {
init(); init();
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
let togglerecord = gst::ElementFactory::make("togglerecord", None).unwrap(); let togglerecord = gst::ElementFactory::make("togglerecord").build().unwrap();
pipeline.add(&togglerecord).unwrap(); pipeline.add(&togglerecord).unwrap();
let (sender_input_1, receiver_input_done_1, receiver_output_1, thread_1) = let (sender_input_1, receiver_input_done_1, receiver_output_1, thread_1) =
@ -1247,7 +1249,7 @@ fn test_two_stream_secondary_eos_first() {
init(); init();
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
let togglerecord = gst::ElementFactory::make("togglerecord", None).unwrap(); let togglerecord = gst::ElementFactory::make("togglerecord").build().unwrap();
pipeline.add(&togglerecord).unwrap(); pipeline.add(&togglerecord).unwrap();
let (sender_input_1, receiver_input_done_1, receiver_output_1, thread_1) = let (sender_input_1, receiver_input_done_1, receiver_output_1, thread_1) =
@ -1315,7 +1317,7 @@ fn test_three_stream_main_eos() {
init(); init();
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
let togglerecord = gst::ElementFactory::make("togglerecord", None).unwrap(); let togglerecord = gst::ElementFactory::make("togglerecord").build().unwrap();
pipeline.add(&togglerecord).unwrap(); pipeline.add(&togglerecord).unwrap();
let (sender_input_1, receiver_input_done_1, receiver_output_1, thread_1) = let (sender_input_1, receiver_input_done_1, receiver_output_1, thread_1) =
@ -1416,7 +1418,7 @@ fn test_three_stream_main_and_second_eos() {
init(); init();
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
let togglerecord = gst::ElementFactory::make("togglerecord", None).unwrap(); let togglerecord = gst::ElementFactory::make("togglerecord").build().unwrap();
pipeline.add(&togglerecord).unwrap(); pipeline.add(&togglerecord).unwrap();
let (sender_input_1, receiver_input_done_1, receiver_output_1, thread_1) = let (sender_input_1, receiver_input_done_1, receiver_output_1, thread_1) =
@ -1517,7 +1519,7 @@ fn test_three_stream_secondary_eos_first() {
init(); init();
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
let togglerecord = gst::ElementFactory::make("togglerecord", None).unwrap(); let togglerecord = gst::ElementFactory::make("togglerecord").build().unwrap();
pipeline.add(&togglerecord).unwrap(); pipeline.add(&togglerecord).unwrap();
let (sender_input_1, receiver_input_done_1, receiver_output_1, thread_1) = let (sender_input_1, receiver_input_done_1, receiver_output_1, thread_1) =

View file

@ -64,8 +64,8 @@ static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
}); });
static QUEUE_TYPE: Lazy<glib::Type> = Lazy::new(|| { static QUEUE_TYPE: Lazy<glib::Type> = Lazy::new(|| {
if let Ok(queue) = gst::ElementFactory::make("queue", None) { if let Some(queue) = gst::ElementFactory::find("queue").and_then(|f| f.load().ok()) {
queue.type_() queue.element_type()
} else { } else {
gst::warning!(CAT, "Can't instantiate queue element"); gst::warning!(CAT, "Can't instantiate queue element");
glib::Type::INVALID glib::Type::INVALID
@ -73,8 +73,8 @@ static QUEUE_TYPE: Lazy<glib::Type> = Lazy::new(|| {
}); });
static QUEUE2_TYPE: Lazy<glib::Type> = Lazy::new(|| { static QUEUE2_TYPE: Lazy<glib::Type> = Lazy::new(|| {
if let Ok(queue) = gst::ElementFactory::make("queue2", None) { if let Some(queue) = gst::ElementFactory::find("queue2").and_then(|f| f.load().ok()) {
queue.type_() queue.element_type()
} else { } else {
gst::warning!(CAT, "Can't instantiate queue2 element"); gst::warning!(CAT, "Can't instantiate queue2 element");
glib::Type::INVALID glib::Type::INVALID
@ -82,8 +82,8 @@ static QUEUE2_TYPE: Lazy<glib::Type> = Lazy::new(|| {
}); });
static MULTIQUEUE_TYPE: Lazy<glib::Type> = Lazy::new(|| { static MULTIQUEUE_TYPE: Lazy<glib::Type> = Lazy::new(|| {
if let Ok(queue) = gst::ElementFactory::make("multiqueue", None) { if let Some(queue) = gst::ElementFactory::find("multiqueue").and_then(|f| f.load().ok()) {
queue.type_() queue.element_type()
} else { } else {
gst::warning!(CAT, "Can't instantiate multiqueue element"); gst::warning!(CAT, "Can't instantiate multiqueue element");
glib::Type::INVALID glib::Type::INVALID

View file

@ -25,13 +25,13 @@ struct Opt {
fn create_pipeline(uris: Vec<String>, iterations: u32) -> anyhow::Result<gst::Pipeline> { fn create_pipeline(uris: Vec<String>, iterations: u32) -> anyhow::Result<gst::Pipeline> {
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
let playlist = gst::ElementFactory::make("uriplaylistbin", None)?; let playlist = gst::ElementFactory::make("uriplaylistbin")
.property("uris", &uris)
.property("iterations", &iterations)
.build()?;
pipeline.add(&playlist)?; pipeline.add(&playlist)?;
playlist.set_property("uris", &uris);
playlist.set_property("iterations", &iterations);
let sink_bins = Arc::new(Mutex::new(HashMap::new())); let sink_bins = Arc::new(Mutex::new(HashMap::new()));
let sink_bins_clone = sink_bins.clone(); let sink_bins_clone = sink_bins.clone();

View file

@ -441,12 +441,11 @@ impl Item {
fn set_waiting_for_stream_collection(&self) -> Result<(), PlaylistError> { fn set_waiting_for_stream_collection(&self) -> Result<(), PlaylistError> {
let mut inner = self.inner.lock().unwrap(); let mut inner = self.inner.lock().unwrap();
let uridecodebin = gst::ElementFactory::make( let uridecodebin = gst::ElementFactory::make("uridecodebin3")
"uridecodebin3", .name(&format!("playlist-decodebin-{}", inner.index))
Some(&format!("playlist-decodebin-{}", inner.index)), .property("uri", &inner.uri)
) .build()
.map_err(|e| PlaylistError::PluginMissing { error: e.into() })?; .map_err(|e| PlaylistError::PluginMissing { error: e.into() })?;
uridecodebin.set_property("uri", &inner.uri);
assert!(matches!(inner.state, ItemState::Pending)); assert!(matches!(inner.state, ItemState::Pending));
inner.state = ItemState::WaitingForStreamCollection { uridecodebin }; inner.state = ItemState::WaitingForStreamCollection { uridecodebin };
@ -974,9 +973,10 @@ impl UriPlaylistBin {
let mut state_guard = self.state.lock().unwrap(); let mut state_guard = self.state.lock().unwrap();
assert!(state_guard.is_none()); assert!(state_guard.is_none());
let streamsynchronizer = let streamsynchronizer = gst::ElementFactory::make("streamsynchronizer")
gst::ElementFactory::make("streamsynchronizer", Some("playlist-streamsync")) .name("playlist-streamsync")
.map_err(|e| PlaylistError::PluginMissing { error: e.into() })?; .build()
.map_err(|e| PlaylistError::PluginMissing { error: e.into() })?;
self.instance().add(&streamsynchronizer).unwrap(); self.instance().add(&streamsynchronizer).unwrap();
@ -1261,14 +1261,14 @@ impl UriPlaylistBin {
item.index() item.index()
); );
let concat = match gst::ElementFactory::make( let concat = match gst::ElementFactory::make("concat")
"concat", .name(&format!(
Some(&format!(
"playlist-concat-{}-{}", "playlist-concat-{}-{}",
stream_type.name(), stream_type.name(),
stream_index stream_index
)), ))
) { .build()
{
Ok(concat) => concat, Ok(concat) => concat,
Err(_) => { Err(_) => {
drop(state_guard); drop(state_guard);

View file

@ -81,18 +81,19 @@ fn test(
let playlist_len = medias.len() * (iterations as usize); let playlist_len = medias.len() * (iterations as usize);
let pipeline = gst::Pipeline::new(None);
let playlist = gst::ElementFactory::make("uriplaylistbin", None).unwrap();
let mq = gst::ElementFactory::make("multiqueue", None).unwrap();
pipeline.add_many(&[&playlist, &mq]).unwrap();
let total_len: gst::ClockTime = medias.iter().map(|t| t.len * (iterations as u64)).sum(); let total_len: gst::ClockTime = medias.iter().map(|t| t.len * (iterations as u64)).sum();
let uris: Vec<String> = medias.iter().map(|t| t.uri.clone()).collect(); let uris: Vec<String> = medias.iter().map(|t| t.uri.clone()).collect();
playlist.set_property("uris", &uris); let pipeline = gst::Pipeline::new(None);
playlist.set_property("iterations", &iterations); let playlist = gst::ElementFactory::make("uriplaylistbin")
.property("uris", &uris)
.property("iterations", &iterations)
.build()
.unwrap();
let mq = gst::ElementFactory::make("multiqueue").build().unwrap();
pipeline.add_many(&[&playlist, &mq]).unwrap();
assert_eq!(playlist.property::<u32>("current-iteration"), 0); assert_eq!(playlist.property::<u32>("current-iteration"), 0);
assert_eq!(playlist.property::<u64>("current-uri-index"), 0); assert_eq!(playlist.property::<u64>("current-uri-index"), 0);
@ -114,7 +115,7 @@ fn test(
None => return, None => return,
}; };
let sink = gst::ElementFactory::make("fakesink", None).unwrap(); let sink = gst::ElementFactory::make("fakesink").build().unwrap();
pipeline.add(&sink).unwrap(); pipeline.add(&sink).unwrap();
sink.sync_state_with_parent().unwrap(); sink.sync_state_with_parent().unwrap();

View file

@ -37,8 +37,10 @@ fn test_cdgdec() {
}; };
// Ensure we are in push mode so 'blocksize' prop is used // Ensure we are in push mode so 'blocksize' prop is used
let filesrc = gst::ElementFactory::make("pushfilesrc", None).unwrap(); let filesrc = gst::ElementFactory::make("pushfilesrc")
filesrc.set_property("location", input_path.to_str().unwrap()); .property("location", input_path.to_str().unwrap())
.build()
.unwrap();
{ {
let child_proxy = filesrc.dynamic_cast_ref::<gst::ChildProxy>().unwrap(); let child_proxy = filesrc.dynamic_cast_ref::<gst::ChildProxy>().unwrap();
child_proxy.set_child_property("real-filesrc::num-buffers", 1); child_proxy.set_child_property("real-filesrc::num-buffers", 1);
@ -46,9 +48,9 @@ fn test_cdgdec() {
child_proxy.set_child_property("real-filesrc::blocksize", blocksize); child_proxy.set_child_property("real-filesrc::blocksize", blocksize);
} }
let parse = gst::ElementFactory::make("cdgparse", None).unwrap(); let parse = gst::ElementFactory::make("cdgparse").build().unwrap();
let dec = gst::ElementFactory::make("cdgdec", None).unwrap(); let dec = gst::ElementFactory::make("cdgdec").build().unwrap();
let sink = gst::ElementFactory::make("appsink", None).unwrap(); let sink = gst::ElementFactory::make("appsink").build().unwrap();
pipeline pipeline
.add_many(&[&filesrc, &parse, &dec, &sink]) .add_many(&[&filesrc, &parse, &dec, &sink])

View file

@ -88,12 +88,14 @@ impl TranscriberBin {
fn construct_transcription_bin(&self, state: &mut State) -> Result<(), Error> { fn construct_transcription_bin(&self, state: &mut State) -> Result<(), Error> {
gst::debug!(CAT, imp: self, "Building transcription bin"); gst::debug!(CAT, imp: self, "Building transcription bin");
let aqueue_transcription = gst::ElementFactory::make("queue", Some("transqueue"))?; let aqueue_transcription = gst::ElementFactory::make("queue")
aqueue_transcription.set_property("max-size-buffers", 0u32); .name("transqueue")
aqueue_transcription.set_property("max-size-bytes", 0u32); .property("max-size-buffers", 0u32)
aqueue_transcription.set_property("max-size-time", 5_000_000_000u64); .property("max-size-bytes", 0u32)
aqueue_transcription.set_property_from_str("leaky", "downstream"); .property("max-size-time", 5_000_000_000u64)
let ccconverter = gst::ElementFactory::make("ccconverter", None)?; .property_from_str("leaky", "downstream")
.build()?;
let ccconverter = gst::ElementFactory::make("ccconverter").build()?;
state.transcription_bin.add_many(&[ state.transcription_bin.add_many(&[
&aqueue_transcription, &aqueue_transcription,
@ -150,9 +152,9 @@ impl TranscriberBin {
} }
fn construct_internal_bin(&self, state: &mut State) -> Result<(), Error> { fn construct_internal_bin(&self, state: &mut State) -> Result<(), Error> {
let aclocksync = gst::ElementFactory::make("clocksync", None)?; let aclocksync = gst::ElementFactory::make("clocksync").build()?;
let vclocksync = gst::ElementFactory::make("clocksync", None)?; let vclocksync = gst::ElementFactory::make("clocksync").build()?;
state.internal_bin.add_many(&[ state.internal_bin.add_many(&[
&aclocksync, &aclocksync,
@ -442,22 +444,31 @@ impl TranscriberBin {
fn build_state(&self) -> Result<State, Error> { fn build_state(&self) -> Result<State, Error> {
let internal_bin = gst::Bin::new(Some("internal")); let internal_bin = gst::Bin::new(Some("internal"));
let transcription_bin = gst::Bin::new(Some("transcription-bin")); let transcription_bin = gst::Bin::new(Some("transcription-bin"));
let audio_tee = gst::ElementFactory::make("tee", None)?; let audio_tee = gst::ElementFactory::make("tee")
let cccombiner = gst::ElementFactory::make("cccombiner", Some("cccombiner"))?; // Protect passthrough enable (and resulting dynamic reconfigure)
let textwrap = gst::ElementFactory::make("textwrap", Some("textwrap"))?; // from non-streaming thread
let tttocea608 = gst::ElementFactory::make("tttocea608", Some("tttocea608"))?; .property("allow-not-linked", true)
let transcriber_aconv = gst::ElementFactory::make("audioconvert", None)?; .build()?;
let transcriber = gst::ElementFactory::make("awstranscriber", Some("transcriber"))?; let cccombiner = gst::ElementFactory::make("cccombiner")
let transcriber_queue = gst::ElementFactory::make("queue", None)?; .name("cccombiner")
let audio_queue_passthrough = gst::ElementFactory::make("queue", None)?; .build()?;
let video_queue = gst::ElementFactory::make("queue", None)?; let textwrap = gst::ElementFactory::make("textwrap")
let cccapsfilter = gst::ElementFactory::make("capsfilter", None)?; .name("textwrap")
let transcription_valve = gst::ElementFactory::make("valve", None)?; .build()?;
let tttocea608 = gst::ElementFactory::make("tttocea608")
// Protect passthrough enable (and resulting dynamic reconfigure) .name("tttocea608")
// from non-streaming thread .build()?;
audio_tee.set_property("allow-not-linked", true); let transcriber_aconv = gst::ElementFactory::make("audioconvert").build()?;
transcription_valve.set_property_from_str("drop-mode", "transform-to-gap"); let transcriber = gst::ElementFactory::make("awstranscriber")
.name("transcriber")
.build()?;
let transcriber_queue = gst::ElementFactory::make("queue").build()?;
let audio_queue_passthrough = gst::ElementFactory::make("queue").build()?;
let video_queue = gst::ElementFactory::make("queue").build()?;
let cccapsfilter = gst::ElementFactory::make("capsfilter").build()?;
let transcription_valve = gst::ElementFactory::make("valve")
.property_from_str("drop-mode", "transform-to-gap")
.build()?;
Ok(State { Ok(State {
framerate: None, framerate: None,

View file

@ -7,12 +7,16 @@ use std::cell::RefCell;
fn create_ui(app: &gtk::Application) { fn create_ui(app: &gtk::Application) {
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
let src = gst::ElementFactory::make("videotestsrc", None).unwrap(); let src = gst::ElementFactory::make("videotestsrc").build().unwrap();
let overlay = gst::ElementFactory::make("clockoverlay", None).unwrap(); let overlay = gst::ElementFactory::make("clockoverlay")
overlay.set_property("font-desc", "Monospace 42"); .property("font-desc", "Monospace 42")
.build()
.unwrap();
let sink = gst::ElementFactory::make("gtk4paintablesink", None).unwrap(); let sink = gst::ElementFactory::make("gtk4paintablesink")
.build()
.unwrap();
let paintable = sink.property::<gdk::Paintable>("paintable"); let paintable = sink.property::<gdk::Paintable>("paintable");
pipeline.add_many(&[&src, &overlay, &sink]).unwrap(); pipeline.add_many(&[&src, &overlay, &sink]).unwrap();

View file

@ -23,12 +23,14 @@ fn test_red_color() {
init(); init();
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
let src = gst::ElementFactory::make("videotestsrc", None).unwrap(); let src = gst::ElementFactory::make("videotestsrc")
src.set_property_from_str("pattern", "red"); .property_from_str("pattern", "red")
src.set_property("num-buffers", &2i32); .property("num-buffers", &2i32)
.build()
.unwrap();
let filter = gst::ElementFactory::make("colordetect", None).unwrap(); let filter = gst::ElementFactory::make("colordetect").build().unwrap();
let sink = gst::ElementFactory::make("fakevideosink", None).unwrap(); let sink = gst::ElementFactory::make("fakevideosink").build().unwrap();
pipeline pipeline
.add_many(&[&src, &filter, &sink]) .add_many(&[&src, &filter, &sink])

View file

@ -26,18 +26,26 @@ fn setup_pipeline(
max_distance_threshold: f64, max_distance_threshold: f64,
hash_algo: HashAlgorithm, hash_algo: HashAlgorithm,
) { ) {
let videocompare = gst::ElementFactory::make("videocompare", None).unwrap(); let videocompare = gst::ElementFactory::make("videocompare")
videocompare.set_property("max-dist-threshold", max_distance_threshold); .property("max-dist-threshold", max_distance_threshold)
videocompare.set_property("hash-algo", hash_algo); .property("hash-algo", hash_algo)
.build()
.unwrap();
let reference_src = gst::ElementFactory::make("videotestsrc", Some("reference_src")).unwrap(); let reference_src = gst::ElementFactory::make("videotestsrc")
reference_src.set_property_from_str("pattern", pattern_a); .name("reference_src")
reference_src.set_property("num-buffers", 1i32); .property_from_str("pattern", pattern_a)
.property("num-buffers", 1i32)
.build()
.unwrap();
let secondary_src = gst::ElementFactory::make("videotestsrc", Some("secondary_src")).unwrap(); let secondary_src = gst::ElementFactory::make("videotestsrc")
reference_src.set_property_from_str("pattern", pattern_b); .name("secondary_src")
.property_from_str("pattern", pattern_b)
.build()
.unwrap();
let sink = gst::ElementFactory::make("fakesink", None).unwrap(); let sink = gst::ElementFactory::make("fakesink").build().unwrap();
pipeline pipeline
.add_many(&[&reference_src, &secondary_src, &videocompare, &sink]) .add_many(&[&reference_src, &secondary_src, &videocompare, &sink])
@ -50,9 +58,7 @@ fn setup_pipeline(
fn test_can_find_similar_frames() { fn test_can_find_similar_frames() {
init(); init();
// TODO: for some reason only in the tests, the distance is higher let max_distance = 0.0f64;
// than when running via gst-launch tool for the same pipeline. What is happening?
let max_distance = 32_f64;
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
setup_pipeline( setup_pipeline(
@ -101,7 +107,7 @@ fn test_do_not_send_message_when_image_not_found() {
init(); init();
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
setup_pipeline(&pipeline, "black", "red", 0f64, HashAlgorithm::Blockhash); setup_pipeline(&pipeline, "snow", "red", 0f64, HashAlgorithm::Blockhash);
pipeline.set_state(gst::State::Playing).unwrap(); pipeline.set_state(gst::State::Playing).unwrap();
@ -127,7 +133,9 @@ fn test_do_not_send_message_when_image_not_found() {
pipeline.set_state(gst::State::Null).unwrap(); pipeline.set_state(gst::State::Null).unwrap();
assert!(detection.is_none()); if let Some(detection) = detection {
panic!("Got unexpected detection message {:?}", detection);
}
} }
#[cfg(feature = "dssim")] #[cfg(feature = "dssim")]
@ -135,7 +143,7 @@ fn test_do_not_send_message_when_image_not_found() {
fn test_use_dssim_to_find_similar_frames() { fn test_use_dssim_to_find_similar_frames() {
init(); init();
let max_distance = 1_f64; let max_distance = 0.0f64;
let pipeline = gst::Pipeline::new(None); let pipeline = gst::Pipeline::new(None);
setup_pipeline(&pipeline, "red", "red", max_distance, HashAlgorithm::Dssim); setup_pipeline(&pipeline, "red", "red", max_distance, HashAlgorithm::Dssim);