我如何在 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 得到任何东西。我什至不确定这是否是正确的方法,如果有任何指示可以找到有关如何将 rtpbinudpsrc.

一起使用的示例或指示,我将不胜感激。

您没有指定要将 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 序列并让您将它与其他元素一起使用。