From 541c6379103b40ee0cc5f736c7461db055e6f974 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 19 Jan 2023 20:56:44 +0200 Subject: [PATCH] examples: webrtc: sendrecv: rust: Implement TWCC support in both directions Part-of: --- .../webrtc/sendrecv/gst-rust/Cargo.lock | 41 +++++++++++++++++++ .../webrtc/sendrecv/gst-rust/Cargo.toml | 1 + .../webrtc/sendrecv/gst-rust/src/main.rs | 39 ++++++++++++++++-- 3 files changed, 78 insertions(+), 3 deletions(-) diff --git a/subprojects/gst-examples/webrtc/sendrecv/gst-rust/Cargo.lock b/subprojects/gst-examples/webrtc/sendrecv/gst-rust/Cargo.lock index 58e2e9554e..7a67bbab4d 100644 --- a/subprojects/gst-examples/webrtc/sendrecv/gst-rust/Cargo.lock +++ b/subprojects/gst-examples/webrtc/sendrecv/gst-rust/Cargo.lock @@ -693,6 +693,46 @@ dependencies = [ "thiserror", ] +[[package]] +name = "gstreamer-base-sys" +version = "0.19.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc3c4476e1503ae245c89fbe20060c30ec6ade5f44620bcc402cbc70a3911a1" +dependencies = [ + "glib-sys", + "gobject-sys", + "gstreamer-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gstreamer-rtp" +version = "0.19.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2e464957d09a9abb8c3cbf818635f38113b327d9ba23b89ef11b10afb25cdfe" +dependencies = [ + "bitflags", + "glib", + "gstreamer", + "gstreamer-rtp-sys", + "libc", + "once_cell", +] + +[[package]] +name = "gstreamer-rtp-sys" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e65dbc4429a8cb494907c654caa74c1630111116f9ac2d1d9bf585c144e4821d" +dependencies = [ + "glib-sys", + "gstreamer-base-sys", + "gstreamer-sys", + "libc", + "system-deps", +] + [[package]] name = "gstreamer-sdp" version = "0.19.4" @@ -1590,6 +1630,7 @@ dependencies = [ "cocoa", "futures", "gstreamer", + "gstreamer-rtp", "gstreamer-sdp", "gstreamer-webrtc", "rand", diff --git a/subprojects/gst-examples/webrtc/sendrecv/gst-rust/Cargo.toml b/subprojects/gst-examples/webrtc/sendrecv/gst-rust/Cargo.toml index 16a4698c8e..11f3ca9bfc 100644 --- a/subprojects/gst-examples/webrtc/sendrecv/gst-rust/Cargo.toml +++ b/subprojects/gst-examples/webrtc/sendrecv/gst-rust/Cargo.toml @@ -12,6 +12,7 @@ anyhow = "1" rand = "0.8" async-tungstenite = { version = "0.19", features = ["async-std-runtime", "async-native-tls"] } gst = { package = "gstreamer", version = "0.19" } +gst-rtp = { package = "gstreamer-rtp", version = "0.19", features = ["v1_20"] } gst-webrtc = { package = "gstreamer-webrtc", version = "0.19" } gst-sdp = { package = "gstreamer-sdp", version = "0.19" } serde = "1" diff --git a/subprojects/gst-examples/webrtc/sendrecv/gst-rust/src/main.rs b/subprojects/gst-examples/webrtc/sendrecv/gst-rust/src/main.rs index 7a53608959..888f920ba8 100644 --- a/subprojects/gst-examples/webrtc/sendrecv/gst-rust/src/main.rs +++ b/subprojects/gst-examples/webrtc/sendrecv/gst-rust/src/main.rs @@ -18,6 +18,7 @@ use tungstenite::Message as WsMessage; use gst::glib; use gst::prelude::*; +use gst_rtp::prelude::*; use serde_derive::{Deserialize, Serialize}; @@ -26,6 +27,8 @@ use anyhow::{anyhow, bail, Context}; const STUN_SERVER: &str = "stun://stun.l.google.com:19302"; const TURN_SERVER: &str = "turn://foo:bar@webrtc.nirbheek.in:3478"; +const TWCC_URI: &str = "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01"; + // upgrade weak reference or return #[macro_export] macro_rules! upgrade_weak { @@ -149,6 +152,15 @@ impl App { // Connect to on-negotiation-needed to handle sending an Offer if app.args.peer_id.is_some() { + let vpay = app.pipeline.by_name("vpay").unwrap(); + let apay = app.pipeline.by_name("apay").unwrap(); + + for pay in [vpay, apay] { + let twcc = gst_rtp::RTPHeaderExtension::create_from_uri(TWCC_URI).unwrap(); + twcc.set_id(1); + pay.emit_by_name::<()>("add-extension", &[&twcc]); + } + let app_clone = app.downgrade(); app.webrtcbin.connect_closure( "on-negotiation-needed", @@ -403,10 +415,25 @@ impl App { Err(_) => continue, }; + let twcc_id = media.attributes().find_map(|attr| { + let key = attr.key(); + let value = attr.value(); + if key != "extmap" || !value.map_or(false, |value| value.ends_with(TWCC_URI)) { + return None; + } + let value = value.unwrap(); + + let id = value + .strip_suffix(TWCC_URI) + .and_then(|id| id.trim().parse::().ok()); + + id + }); + if encoding_name == "VP8" && vp8_id.is_none() { - vp8_id = Some(pt); + vp8_id = Some((pt, twcc_id)); } else if encoding_name == "OPUS" && opus_id.is_none() { - opus_id = Some(pt); + opus_id = Some((pt, twcc_id)); } } } @@ -415,8 +442,14 @@ impl App { let apay = self.pipeline.by_name("apay").unwrap(); let vpay = self.pipeline.by_name("vpay").unwrap(); - for (pay, pt) in [(apay, opus_id), (vpay, vp8_id)] { + for (pay, (pt, twcc_id)) in [(apay, opus_id), (vpay, vp8_id)] { pay.set_property("pt", pt as u32); + + if let Some(twcc_id) = twcc_id { + let twcc = gst_rtp::RTPHeaderExtension::create_from_uri(TWCC_URI).unwrap(); + twcc.set_id(twcc_id as u32); + pay.emit_by_name::<()>("add-extension", &[&twcc]); + } } } else { gst::element_error!(