我如何在 Gstreamer Rust 中 link 一个 udpsrc 到 rtpbin?
How do I link a udpsrc to rtpbin in Gstreamer Rust?
我尝试使用 gstreamer-rs crate 通过 Gstreamer 创建一个接收 RTP video/audio 流的管道,但我运气不佳。这是我的方法的快速提炼:
let udp_src = ElementFactory::make("udpsrc", Some("udp_src"))?;
udp_src.set_property("port", &5004);
udp_src.set_property("caps", &"application/x-rtp".to_string());
let rtpbin = ElementFactory::make("rtpbin", Some("rtp_bin"))?;
let pipeline = Pipeline::new(Some("RTP Pipeline"));
pipeline.add_many(&[&udp_src, &rtpbin]);
udp_src.link(&rtpbin)?;
rtpbin.connect_pad_added(move |src, src_pad| {
println!("Received new pad {} from {}", src_pad.get_name(), src.get_name());
let new_pad_caps = src_pad.get_current_caps().expect("Failed to get caps of new pad");
let new_pad_struct = new_pad_caps.get_structure(0).expect("Failed to get first structure of caps");
let new_pad_type = new_pad_struct.get_name();
println!("{}", new_pad_type);
});
但是当我 运行 代码并将 UDP 信号发送到指定端口时,我没有从 connect_pad_added
得到任何东西。我什至不确定这是否是正确的方法,如果有任何指示可以找到有关如何将 rtpbin
与 udpsrc
.
一起使用的示例或指示,我将不胜感激。
您没有指定要将 udpsrc
链接到 rtpbin
的哪个垫,所以它可能在这里选择了错误的垫(可能是发件人的那个垫-rtpbin
).
试试 udp_src.link_pads(Some("src"), &rtpbin, Some("recv_rtp_sink_%u"))
。然后你应该得到一个 pad-added
和 "recv_rtp_src_%u_%u_%u"
名字。第一个数字是 0,另外两个是 payload type 和 ssrc.
您可以通过以下方式将 udp 源 link 发送到 rtpbin:
fn get_static_pad(element: &Element, pad_name: &'static str) -> Result<Pad, Error> {
let pad = element.get_static_pad(pad_name);
pad.ok_or(Error::msg(format!("Failed to get pad: {}", pad_name)))
}
fn get_request_pad(element: &Element, pad_name: &'static str) -> Result<Pad, Error> {
match element.get_request_pad(pad_name) {
Some(pad) => Ok(pad),
None => {
let element_name = element.get_name();
Err(Error::msg(pad_name))
}
}
}
let rtp_udp_src = ElementFactory::make("udpsrc", Some("rtp_udp_src"))?;
let caps = Caps::new_simple("application/x-rtp", &[("clock-rate", &90000i32)]);
rtp_udp_src.set_property("port", &5006);
rtp_udp_src.set_property("caps", &caps);
let rtpbin = ElementFactory::make("rtpbin", Some("rtp_bin"))?;
rtpbin.connect("request-pt-map", false, |values| {
let pt = values[2].get::<u32>().expect("Invalid argument");
match pt {
Some(100) => Some(
Caps::new_simple(
"application/x-rtp",
&[
("media", &"video"),
("clock-rate", &90000i32),
],
)
.to_value(),
),
Some(96) => Some(
Caps::new_simple(
"application/x-rtp",
&[
("media", &"video"),
("clock-rate", &90000i32),
("encoding-name", &"VP8"),
],
)
.to_value(),
),
_ => None,
}
})?;
let rtp_udp_src_pad = get_static_pad(&rtp_udp_src, "src")?;
let rtp_recv_sink_pad = get_request_pad(&rtpbin, "recv_rtp_sink_0")?;
rtp_udp_src_pad.link(&rtp_recv_sink_pad).expect("Failed to link rtp_udp_src_pad and rtpbin");
这将正确触发 connect_pad_added
序列并让您将它与其他元素一起使用。
我尝试使用 gstreamer-rs crate 通过 Gstreamer 创建一个接收 RTP video/audio 流的管道,但我运气不佳。这是我的方法的快速提炼:
let udp_src = ElementFactory::make("udpsrc", Some("udp_src"))?;
udp_src.set_property("port", &5004);
udp_src.set_property("caps", &"application/x-rtp".to_string());
let rtpbin = ElementFactory::make("rtpbin", Some("rtp_bin"))?;
let pipeline = Pipeline::new(Some("RTP Pipeline"));
pipeline.add_many(&[&udp_src, &rtpbin]);
udp_src.link(&rtpbin)?;
rtpbin.connect_pad_added(move |src, src_pad| {
println!("Received new pad {} from {}", src_pad.get_name(), src.get_name());
let new_pad_caps = src_pad.get_current_caps().expect("Failed to get caps of new pad");
let new_pad_struct = new_pad_caps.get_structure(0).expect("Failed to get first structure of caps");
let new_pad_type = new_pad_struct.get_name();
println!("{}", new_pad_type);
});
但是当我 运行 代码并将 UDP 信号发送到指定端口时,我没有从 connect_pad_added
得到任何东西。我什至不确定这是否是正确的方法,如果有任何指示可以找到有关如何将 rtpbin
与 udpsrc
.
您没有指定要将 udpsrc
链接到 rtpbin
的哪个垫,所以它可能在这里选择了错误的垫(可能是发件人的那个垫-rtpbin
).
试试 udp_src.link_pads(Some("src"), &rtpbin, Some("recv_rtp_sink_%u"))
。然后你应该得到一个 pad-added
和 "recv_rtp_src_%u_%u_%u"
名字。第一个数字是 0,另外两个是 payload type 和 ssrc.
您可以通过以下方式将 udp 源 link 发送到 rtpbin:
fn get_static_pad(element: &Element, pad_name: &'static str) -> Result<Pad, Error> {
let pad = element.get_static_pad(pad_name);
pad.ok_or(Error::msg(format!("Failed to get pad: {}", pad_name)))
}
fn get_request_pad(element: &Element, pad_name: &'static str) -> Result<Pad, Error> {
match element.get_request_pad(pad_name) {
Some(pad) => Ok(pad),
None => {
let element_name = element.get_name();
Err(Error::msg(pad_name))
}
}
}
let rtp_udp_src = ElementFactory::make("udpsrc", Some("rtp_udp_src"))?;
let caps = Caps::new_simple("application/x-rtp", &[("clock-rate", &90000i32)]);
rtp_udp_src.set_property("port", &5006);
rtp_udp_src.set_property("caps", &caps);
let rtpbin = ElementFactory::make("rtpbin", Some("rtp_bin"))?;
rtpbin.connect("request-pt-map", false, |values| {
let pt = values[2].get::<u32>().expect("Invalid argument");
match pt {
Some(100) => Some(
Caps::new_simple(
"application/x-rtp",
&[
("media", &"video"),
("clock-rate", &90000i32),
],
)
.to_value(),
),
Some(96) => Some(
Caps::new_simple(
"application/x-rtp",
&[
("media", &"video"),
("clock-rate", &90000i32),
("encoding-name", &"VP8"),
],
)
.to_value(),
),
_ => None,
}
})?;
let rtp_udp_src_pad = get_static_pad(&rtp_udp_src, "src")?;
let rtp_recv_sink_pad = get_request_pad(&rtpbin, "recv_rtp_sink_0")?;
rtp_udp_src_pad.link(&rtp_recv_sink_pad).expect("Failed to link rtp_udp_src_pad and rtpbin");
这将正确触发 connect_pad_added
序列并让您将它与其他元素一起使用。