RTX and TWCC working correctly
This commit is contained in:
parent
d5842ee79f
commit
f414c9db66
|
@ -387,9 +387,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gio"
|
||||
version = "0.14.0"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86c6823b39d46d22cac2466de261f28d7f049ebc18f7b35296a42c7ed8a88325"
|
||||
checksum = "402a7057cd21d64bfa7ac027b344a7f50f677fb3308693df0e8c70fb55d29f0d"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"futures-channel",
|
||||
|
@ -417,9 +417,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "glib"
|
||||
version = "0.14.2"
|
||||
version = "0.14.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbecad7a3a898ee749d491ce2ae0decb0bce9e736f9747bc49159b1cea5d37f4"
|
||||
checksum = "a8fb802e3798d75b415bea8f016eed88d50106ce82f1274e80f31d80cfd4b056"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"futures-channel",
|
||||
|
@ -489,9 +489,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gstreamer"
|
||||
version = "0.17.2"
|
||||
version = "0.17.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4aa71d1b3f562645e2d3b96c8d5cf1f26174696e37781ef34193311da733f98c"
|
||||
checksum = "810e68483c27518ec8491d71ee163f9fc03dcc4ebacee98caa348e8a064898ef"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
|
@ -512,9 +512,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gstreamer-sys"
|
||||
version = "0.17.0"
|
||||
version = "0.17.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8188ba998999a4a16005c3984812807ff882a87f5f3457c3d5bbbfcbdf631ebd"
|
||||
checksum = "a81704feeb3e8599913bdd1e738455c2991a01ff4a1780cb62200993e454cc3e"
|
||||
dependencies = [
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
|
@ -559,9 +559,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "httparse"
|
||||
version = "1.5.0"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ba8d84e9efea6aedae6fed9b6d9cfcaac6c53992b437d79a87a549d5537fea9"
|
||||
checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503"
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
|
@ -603,9 +603,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.7"
|
||||
version = "0.4.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
|
||||
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
|
||||
|
||||
[[package]]
|
||||
name = "jid"
|
||||
|
@ -618,9 +618,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.52"
|
||||
version = "0.3.53"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce791b7ca6638aae45be056e068fc756d871eb3b3b10b8efa62d1c9cec616752"
|
||||
checksum = "e4bf49d50e2961077d9c99f4b7997d770a1114f087c3c2e0069b36c13fc2979d"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
@ -683,9 +683,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.99"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7f823d141fe0a24df1e23b4af4e3c7ba9e5966ec514ea068c93024aa7deb765"
|
||||
checksum = "a1fa8cddc8fbbee11227ef194b5317ed014b8acbf15139bd716a18ad3fe99ec5"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
|
@ -744,8 +744,6 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "minidom"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "332592c2149fc7dd40a64fc9ef6f0d65607284b474cef9817d1fc8c7e7b3608e"
|
||||
dependencies = [
|
||||
"quick-xml",
|
||||
]
|
||||
|
@ -1085,9 +1083,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rcgen"
|
||||
version = "0.8.11"
|
||||
version = "0.8.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48b4fc1b81d685fcd442a86da2e2c829d9e353142633a8159f42bf28e7e94428"
|
||||
checksum = "2351cbef4bf91837f5ff7face6091cb277ba960d1638d2c5ae2327859912fbba"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"ring",
|
||||
|
@ -1179,18 +1177,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.127"
|
||||
version = "1.0.129"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f03b9878abf6d14e6779d3f24f07b2cfa90352cfec4acc5aab8f1ac7f146fae8"
|
||||
checksum = "d1f72836d2aa753853178eda473a3b9d8e4eefdaf20523b919677e6de489f8f1"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.127"
|
||||
version = "1.0.129"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a024926d3432516606328597e0f224a51355a493b49fdd67e9209187cbe55ecc"
|
||||
checksum = "e57ae87ad533d9a56427558b516d0adac283614e347abf85b0dc0cbbf0a249f3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1338,9 +1336,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.74"
|
||||
version = "1.0.75"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c"
|
||||
checksum = "b7f58f7e8eaa0009c5fec437aabf511bd9933e4b2d7407bd05273c01a8906ea7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1683,9 +1681,9 @@ checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.75"
|
||||
version = "0.2.76"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b608ecc8f4198fe8680e2ed18eccab5f0cd4caaf3d83516fa5fb2e927fda2586"
|
||||
checksum = "8ce9b1b516211d33767048e5d47fa2a381ed8b76fc48d2ce4aa39877f9f183e0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
|
@ -1693,9 +1691,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.75"
|
||||
version = "0.2.76"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "580aa3a91a63d23aac5b6b267e2d13cb4f363e31dce6c352fca4752ae12e479f"
|
||||
checksum = "cfe8dc78e2326ba5f845f4b5bf548401604fa20b1dd1d365fb73b6c1d6364041"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"lazy_static",
|
||||
|
@ -1708,9 +1706,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.75"
|
||||
version = "0.2.76"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "171ebf0ed9e1458810dfcb31f2e766ad6b3a89dbda42d8901f2b268277e5f09c"
|
||||
checksum = "44468aa53335841d9d6b6c023eaab07c0cd4bddbcfdee3e2bb1e8d2cb8069fef"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
|
@ -1718,9 +1716,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.75"
|
||||
version = "0.2.76"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c2657dd393f03aa2a659c25c6ae18a13a4048cebd220e147933ea837efc589f"
|
||||
checksum = "0195807922713af1e67dc66132c7328206ed9766af3858164fb583eedc25fbad"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1731,15 +1729,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.75"
|
||||
version = "0.2.76"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e0c4a743a309662d45f4ede961d7afa4ba4131a59a639f29b0069c3798bbcc2"
|
||||
checksum = "acdb075a845574a1fa5f09fd77e43f7747599301ea3417a9fbffdeedfc1f4a29"
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.52"
|
||||
version = "0.3.53"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01c70a82d842c9979078c772d4a1344685045f1a5628f677c2b2eab4dd7d2696"
|
||||
checksum = "224b2f6b67919060055ef1a67807367c2066ed520c3862cc013d26cf893a783c"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
|
|
|
@ -6,3 +6,6 @@ members = [
|
|||
"nice-gst-meet",
|
||||
"nice-gst-meet-sys",
|
||||
]
|
||||
|
||||
[patch.crates-io]
|
||||
minidom = { path = "../xmpp-rs/minidom" }
|
|
@ -22,7 +22,7 @@ use xmpp_parsers::{
|
|||
jingle::{Action, Content, Creator, Description, Jingle, Senders, Transport},
|
||||
jingle_dtls_srtp::{Fingerprint, Setup},
|
||||
jingle_ice_udp::{self, Transport as IceUdpTransport},
|
||||
jingle_rtp::{Description as RtpDescription, PayloadType, RtcpMux},
|
||||
jingle_rtp::{self, Description as RtpDescription, PayloadType, RtcpMux},
|
||||
jingle_rtp_hdrext::RtpHdrext,
|
||||
jingle_ssma::{self, Parameter},
|
||||
Jid,
|
||||
|
@ -39,10 +39,6 @@ const RTP_HDREXT_SSRC_AUDIO_LEVEL: &str = "urn:ietf:params:rtp-hdrext:ssrc-audio
|
|||
const RTP_HDREXT_ABS_SEND_TIME: &str = "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time";
|
||||
const RTP_HDREXT_TRANSPORT_CC: &str = "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01";
|
||||
|
||||
const RTX_PAYLOAD_TYPE_VP8: u8 = 96;
|
||||
const RTX_PAYLOAD_TYPE_VP9: u8 = 97;
|
||||
const RTX_PAYLOAD_TYPE_H264: u8 = 99;
|
||||
|
||||
const DEFAULT_STUN_PORT: u16 = 3478;
|
||||
const DEFAULT_TURNS_PORT: u16 = 5349;
|
||||
|
||||
|
@ -111,9 +107,16 @@ impl JingleSession {
|
|||
let mut ice_remote_pwd = None;
|
||||
let mut dtls_fingerprint = None;
|
||||
let mut opus_payload_type = None;
|
||||
let mut opus_rtcp_fbs = None;
|
||||
let mut h264_payload_type = None;
|
||||
let mut h264_rtx_payload_type = None;
|
||||
let mut h264_rtcp_fbs = None;
|
||||
let mut vp8_payload_type = None;
|
||||
let mut vp8_rtx_payload_type = None;
|
||||
let mut vp8_rtcp_fbs = None;
|
||||
let mut vp9_payload_type = None;
|
||||
let mut vp9_rtx_payload_type = None;
|
||||
let mut vp9_rtcp_fbs = None;
|
||||
let mut audio_hdrext_ssrc_audio_level = None;
|
||||
let mut audio_hdrext_transport_cc = None;
|
||||
let mut video_hdrext_abs_send_time = None;
|
||||
|
@ -130,6 +133,11 @@ impl JingleSession {
|
|||
.iter()
|
||||
.find(|pt| pt.name.as_deref() == Some("opus"))
|
||||
.map(|pt| pt.id);
|
||||
opus_rtcp_fbs = description
|
||||
.payload_types
|
||||
.iter()
|
||||
.find(|pt| pt.name.as_deref() == Some("opus"))
|
||||
.map(|pt| pt.rtcp_fbs.clone());
|
||||
audio_hdrext_ssrc_audio_level = description
|
||||
.hdrexts
|
||||
.iter()
|
||||
|
@ -149,16 +157,79 @@ impl JingleSession {
|
|||
.iter()
|
||||
.find(|pt| pt.name.as_deref() == Some("H264"))
|
||||
.map(|pt| pt.id);
|
||||
h264_rtx_payload_type = description
|
||||
.payload_types
|
||||
.iter()
|
||||
.find(|pt| {
|
||||
pt.name.as_deref() == Some("rtx")
|
||||
&&
|
||||
pt
|
||||
.parameters
|
||||
.iter()
|
||||
.any(|param| {
|
||||
param.name == "apt"
|
||||
&&
|
||||
param.value == h264_payload_type.map(|pt| pt.to_string()).unwrap_or_default()
|
||||
})
|
||||
})
|
||||
.map(|pt| pt.id);
|
||||
h264_rtcp_fbs = description
|
||||
.payload_types
|
||||
.iter()
|
||||
.find(|pt| pt.name.as_deref() == Some("H264"))
|
||||
.map(|pt| pt.rtcp_fbs.clone());
|
||||
vp8_payload_type = description
|
||||
.payload_types
|
||||
.iter()
|
||||
.find(|pt| pt.name.as_deref() == Some("VP8"))
|
||||
.map(|pt| pt.id);
|
||||
vp8_rtx_payload_type = description
|
||||
.payload_types
|
||||
.iter()
|
||||
.find(|pt| {
|
||||
pt.name.as_deref() == Some("rtx")
|
||||
&&
|
||||
pt
|
||||
.parameters
|
||||
.iter()
|
||||
.any(|param| {
|
||||
param.name == "apt"
|
||||
&&
|
||||
param.value == vp8_payload_type.map(|pt| pt.to_string()).unwrap_or_default()
|
||||
})
|
||||
})
|
||||
.map(|pt| pt.id);
|
||||
vp8_rtcp_fbs = description
|
||||
.payload_types
|
||||
.iter()
|
||||
.find(|pt| pt.name.as_deref() == Some("VP8"))
|
||||
.map(|pt| pt.rtcp_fbs.clone());
|
||||
vp9_payload_type = description
|
||||
.payload_types
|
||||
.iter()
|
||||
.find(|pt| pt.name.as_deref() == Some("VP9"))
|
||||
.map(|pt| pt.id);
|
||||
vp9_rtx_payload_type = description
|
||||
.payload_types
|
||||
.iter()
|
||||
.find(|pt| {
|
||||
pt.name.as_deref() == Some("rtx")
|
||||
&&
|
||||
pt
|
||||
.parameters
|
||||
.iter()
|
||||
.any(|param| {
|
||||
param.name == "apt"
|
||||
&&
|
||||
param.value == vp9_payload_type.map(|pt| pt.to_string()).unwrap_or_default()
|
||||
})
|
||||
})
|
||||
.map(|pt| pt.id);
|
||||
vp9_rtcp_fbs = description
|
||||
.payload_types
|
||||
.iter()
|
||||
.find(|pt| pt.name.as_deref() == Some("VP9"))
|
||||
.map(|pt| pt.rtcp_fbs.clone());
|
||||
video_hdrext_abs_send_time = description
|
||||
.hdrexts
|
||||
.iter()
|
||||
|
@ -257,9 +328,11 @@ impl JingleSession {
|
|||
|
||||
let audio_ssrc: u32 = random();
|
||||
let video_ssrc: u32 = random();
|
||||
let video_rtx_ssrc: u32 = random();
|
||||
|
||||
debug!("audio SSRC: {}", audio_ssrc);
|
||||
debug!("video SSRC: {}", video_ssrc);
|
||||
debug!("video RTX SSRC: {}", video_rtx_ssrc);
|
||||
|
||||
let ice_agent = nice::Agent::new(&conference.glib_main_context, nice::Compatibility::Rfc5245);
|
||||
ice_agent.set_ice_tcp(false);
|
||||
|
@ -389,7 +462,6 @@ impl JingleSession {
|
|||
|
||||
let rtpbin = gstreamer::ElementFactory::make("rtpbin", Some("rtpbin"))?;
|
||||
rtpbin.set_property_from_str("rtp-profile", "savpf");
|
||||
rtpbin.set_property("do-retransmission", true)?;
|
||||
rtpbin.set_property("autoremove", true)?;
|
||||
pipeline.add(&rtpbin)?;
|
||||
|
||||
|
@ -407,6 +479,11 @@ impl JingleSession {
|
|||
|
||||
let dtls_srtp_connection_id = "gst-meet";
|
||||
|
||||
let dtlssrtpenc = gstreamer::ElementFactory::make("dtlssrtpenc", None)?;
|
||||
dtlssrtpenc.set_property("connection-id", dtls_srtp_connection_id)?;
|
||||
dtlssrtpenc.set_property("is-client", true)?;
|
||||
pipeline.add(&dtlssrtpenc)?;
|
||||
|
||||
let dtlssrtpdec = gstreamer::ElementFactory::make("dtlssrtpdec", None)?;
|
||||
dtlssrtpdec.set_property("connection-id", dtls_srtp_connection_id)?;
|
||||
dtlssrtpdec.set_property(
|
||||
|
@ -415,11 +492,6 @@ impl JingleSession {
|
|||
)?;
|
||||
pipeline.add(&dtlssrtpdec)?;
|
||||
|
||||
let dtlssrtpenc = gstreamer::ElementFactory::make("dtlssrtpenc", None)?;
|
||||
dtlssrtpenc.set_property("connection-id", dtls_srtp_connection_id)?;
|
||||
dtlssrtpenc.set_property("is-client", true)?;
|
||||
pipeline.add(&dtlssrtpenc)?;
|
||||
|
||||
rtpbin.connect("request-pt-map", false, move |values| {
|
||||
let f = || {
|
||||
debug!("rtpbin request-pt-map {:?}", values);
|
||||
|
@ -462,20 +534,20 @@ impl JingleSession {
|
|||
}
|
||||
Ok(Some(caps.build()))
|
||||
}
|
||||
else if pt == RTX_PAYLOAD_TYPE_VP8 || pt == RTX_PAYLOAD_TYPE_VP9 || pt == RTX_PAYLOAD_TYPE_H264 {
|
||||
else if Some(pt) == vp8_rtx_payload_type || Some(pt) == vp9_rtx_payload_type || Some(pt) == h264_rtx_payload_type {
|
||||
caps = caps
|
||||
.field("media", "video")
|
||||
.field("clock-rate", 90000)
|
||||
.field("encoding-name", "RTX")
|
||||
.field("apt", if pt == RTX_PAYLOAD_TYPE_VP8 {
|
||||
.field("apt", if Some(pt) == vp8_rtx_payload_type {
|
||||
vp8_payload_type
|
||||
.context("missing VP8 payload type")?
|
||||
}
|
||||
else if pt == RTX_PAYLOAD_TYPE_VP9 {
|
||||
else if Some(pt) == vp9_rtx_payload_type {
|
||||
vp9_payload_type
|
||||
.context("missing VP9 payload type")?
|
||||
}
|
||||
else if pt == RTX_PAYLOAD_TYPE_H264 {
|
||||
else if Some(pt) == h264_rtx_payload_type {
|
||||
h264_payload_type
|
||||
.context("missing H264 payload type")?
|
||||
}
|
||||
|
@ -502,23 +574,64 @@ impl JingleSession {
|
|||
}
|
||||
})?;
|
||||
|
||||
let handle = Handle::current();
|
||||
let inner_ = conference.inner.clone();
|
||||
rtpbin.connect("new-jitterbuffer", false, move |values| {
|
||||
let handle = handle.clone();
|
||||
let inner_ = inner_.clone();
|
||||
let f = move || {
|
||||
let rtpjitterbuffer: gstreamer::Element = values[1].get()?;
|
||||
let session: u32 = values[2].get()?;
|
||||
let ssrc: u32 = values[3].get()?;
|
||||
debug!("new jitterbuffer created for session {} ssrc {}", session, ssrc);
|
||||
|
||||
let source = handle.block_on(async move {
|
||||
let locked_inner = inner_.lock().await;
|
||||
let jingle_session = locked_inner
|
||||
.jingle_session
|
||||
.as_ref()
|
||||
.context("not connected (no jingle session)")?;
|
||||
Ok::<_, anyhow::Error>(
|
||||
jingle_session
|
||||
.remote_ssrc_map
|
||||
.get(&ssrc)
|
||||
.context(format!("unknown ssrc: {}", ssrc))?
|
||||
.clone(),
|
||||
)
|
||||
})?;
|
||||
debug!("jitterbuffer is for remote source: {:?}", source);
|
||||
if source.media_type == MediaType::Video {
|
||||
debug!("enabling RTX for ssrc {}", ssrc);
|
||||
rtpjitterbuffer.set_property("do-retransmission", true)?;
|
||||
}
|
||||
Ok::<_, anyhow::Error>(())
|
||||
};
|
||||
if let Err(e) = f() {
|
||||
warn!("new-jitterbuffer: {:?}", e);
|
||||
}
|
||||
None
|
||||
})?;
|
||||
|
||||
rtpbin.connect("request-aux-sender", false, move |values| {
|
||||
let f = move || {
|
||||
let session: u32 = values[1].get()?;
|
||||
debug!("creating RTX sender for session {}", session);
|
||||
let mut pt_map = gstreamer::Structure::builder("application/x-rtp-pt-map");
|
||||
if let Some(pt) = vp8_payload_type {
|
||||
pt_map = pt_map.field(&pt.to_string(), &(RTX_PAYLOAD_TYPE_VP8 as u32));
|
||||
let mut ssrc_map = gstreamer::Structure::builder("application/x-rtp-ssrc-map");
|
||||
if let (Some(pt), Some(rtx_pt)) = (vp8_payload_type, vp8_rtx_payload_type) {
|
||||
pt_map = pt_map.field(&pt.to_string(), &(rtx_pt as u32));
|
||||
}
|
||||
if let Some(pt) = vp9_payload_type {
|
||||
pt_map = pt_map.field(&pt.to_string(), &(RTX_PAYLOAD_TYPE_VP9 as u32));
|
||||
if let (Some(pt), Some(rtx_pt)) = (vp9_payload_type, vp9_rtx_payload_type) {
|
||||
pt_map = pt_map.field(&pt.to_string(), &(rtx_pt as u32));
|
||||
}
|
||||
if let Some(pt) = h264_payload_type {
|
||||
pt_map = pt_map.field(&pt.to_string(), &(RTX_PAYLOAD_TYPE_H264 as u32));
|
||||
if let (Some(pt), Some(rtx_pt)) = (h264_payload_type, h264_rtx_payload_type) {
|
||||
pt_map = pt_map.field(&pt.to_string(), &(rtx_pt as u32));
|
||||
}
|
||||
ssrc_map = ssrc_map.field(&video_ssrc.to_string(), &(video_rtx_ssrc as u32));
|
||||
let bin = gstreamer::Bin::new(None);
|
||||
let rtx_sender = gstreamer::ElementFactory::make("rtprtxsend", None)?;
|
||||
rtx_sender.set_property("payload-type-map", pt_map.build())?;
|
||||
rtx_sender.set_property("ssrc-map", ssrc_map.build())?;
|
||||
bin.add(&rtx_sender)?;
|
||||
bin.add_pad(
|
||||
&gstreamer::GhostPad::with_target(
|
||||
|
@ -552,14 +665,14 @@ impl JingleSession {
|
|||
let session: u32 = values[1].get()?;
|
||||
debug!("creating RTX receiver for session {}", session);
|
||||
let mut pt_map = gstreamer::Structure::builder("application/x-rtp-pt-map");
|
||||
if let Some(pt) = vp8_payload_type {
|
||||
pt_map = pt_map.field(&pt.to_string(), RTX_PAYLOAD_TYPE_VP8 as u32);
|
||||
if let (Some(pt), Some(rtx_pt)) = (vp8_payload_type, vp8_rtx_payload_type) {
|
||||
pt_map = pt_map.field(&pt.to_string(), &(rtx_pt as u32));
|
||||
}
|
||||
if let Some(pt) = vp9_payload_type {
|
||||
pt_map = pt_map.field(&pt.to_string(), RTX_PAYLOAD_TYPE_VP9 as u32);
|
||||
if let (Some(pt), Some(rtx_pt)) = (vp9_payload_type, vp9_rtx_payload_type) {
|
||||
pt_map = pt_map.field(&pt.to_string(), &(rtx_pt as u32));
|
||||
}
|
||||
if let Some(pt) = h264_payload_type {
|
||||
pt_map = pt_map.field(&pt.to_string(), RTX_PAYLOAD_TYPE_H264 as u32);
|
||||
if let (Some(pt), Some(rtx_pt)) = (h264_payload_type, h264_rtx_payload_type) {
|
||||
pt_map = pt_map.field(&pt.to_string(), &(rtx_pt as u32));
|
||||
}
|
||||
let bin = gstreamer::Bin::new(None);
|
||||
let rtx_receiver = gstreamer::ElementFactory::make("rtprtxreceive", None)?;
|
||||
|
@ -800,28 +913,34 @@ impl JingleSession {
|
|||
video_capsfilter.set_property("caps", video_caps.build())?;
|
||||
pipeline.add(&video_capsfilter)?;
|
||||
|
||||
debug!("linking audio payloader -> rtpbin");
|
||||
let rtpfunnel = gstreamer::ElementFactory::make("funnel", None)?;
|
||||
pipeline.add(&rtpfunnel)?;
|
||||
|
||||
debug!("linking audio payloader -> rtp funnel");
|
||||
audio_sink_element.link(&audio_capsfilter)?;
|
||||
audio_capsfilter.link_pads(None, &rtpbin, Some("send_rtp_sink_0"))?;
|
||||
audio_capsfilter.link_pads(None, &rtpfunnel, Some("sink_0"))?;
|
||||
|
||||
debug!("linking video payloader -> rtpbin");
|
||||
debug!("linking video payloader -> rtp funnel");
|
||||
video_sink_element.link(&video_capsfilter)?;
|
||||
video_capsfilter.link_pads(None, &rtpbin, Some("send_rtp_sink_1"))?;
|
||||
video_capsfilter.link_pads(None, &rtpfunnel, Some("sink_1"))?;
|
||||
|
||||
debug!("linking ICE <-> DTLS-SRTP");
|
||||
nicesrc.link(&dtlssrtpdec)?;
|
||||
dtlssrtpenc.link(&nicesink)?;
|
||||
debug!("linking rtp funnel -> rtpbin");
|
||||
rtpfunnel.link_pads(None, &rtpbin, Some("send_rtp_sink_0"))?;
|
||||
|
||||
debug!("linking rtpbin -> DTLS-SRTP encoder");
|
||||
rtpbin.link_pads(Some("send_rtp_src_0"), &dtlssrtpenc, Some("rtp_sink_0"))?;
|
||||
rtpbin.link_pads(Some("send_rtcp_src_0"), &dtlssrtpenc, Some("rtcp_sink_0"))?;
|
||||
rtpbin.link_pads(Some("send_rtp_src_1"), &dtlssrtpenc, Some("rtp_sink_1"))?;
|
||||
rtpbin.link_pads(Some("send_rtcp_src_1"), &dtlssrtpenc, Some("rtcp_sink_1"))?;
|
||||
|
||||
debug!("linking DTLS-SRTP decoder -> rtpbin");
|
||||
debug!("link dtlssrtpdec -> rtpbin");
|
||||
dtlssrtpdec.link_pads(Some("rtp_src"), &rtpbin, Some("recv_rtp_sink_0"))?;
|
||||
dtlssrtpdec.link_pads(Some("rtcp_src"), &rtpbin, Some("recv_rtcp_sink_0"))?;
|
||||
|
||||
debug!("linking rtpbin -> dtlssrtpenc");
|
||||
rtpbin.link_pads(Some("send_rtp_src_0"), &dtlssrtpenc, Some("rtp_sink_0"))?;
|
||||
rtpbin.link_pads(Some("send_rtcp_src_0"), &dtlssrtpenc, Some("rtcp_sink_0"))?;
|
||||
|
||||
debug!("linking ice src -> dtlssrtpdec");
|
||||
nicesrc.link(&dtlssrtpdec)?;
|
||||
|
||||
debug!("linking dtlssrtpenc -> ice sink");
|
||||
dtlssrtpenc.link_pads(Some("src"), &nicesink, Some("sink"))?;
|
||||
|
||||
let bus = pipeline.bus().context("failed to get pipeline bus")?;
|
||||
|
||||
let (pipeline_state_null_tx, pipeline_state_null_rx) = oneshot::channel();
|
||||
|
@ -875,35 +994,76 @@ impl JingleSession {
|
|||
let mut description = RtpDescription::new(initiate_content.name.0.clone());
|
||||
|
||||
description.payload_types = if initiate_content.name.0 == "audio" {
|
||||
vec![PayloadType::new(
|
||||
let mut pt = PayloadType::new(
|
||||
opus_payload_type.context("no opus payload type in jingle session-initiate")?,
|
||||
"opus".to_owned(),
|
||||
48000,
|
||||
2,
|
||||
)]
|
||||
);
|
||||
pt.rtcp_fbs = opus_rtcp_fbs.clone().unwrap_or_default();
|
||||
vec![pt]
|
||||
}
|
||||
else {
|
||||
let mut pts = vec![];
|
||||
match conference.config.video_codec.as_str() {
|
||||
"h264" => vec![PayloadType::new(
|
||||
h264_payload_type.context("no h264 payload type in jingle session-initiate")?,
|
||||
"H264".to_owned(),
|
||||
90000,
|
||||
1,
|
||||
)],
|
||||
"vp8" => vec![PayloadType::new(
|
||||
vp8_payload_type.context("no vp8 payload type in jingle session-initiate")?,
|
||||
"VP8".to_owned(),
|
||||
90000,
|
||||
1,
|
||||
)],
|
||||
"vp9" => vec![PayloadType::new(
|
||||
vp9_payload_type.context("no vp9 payload type in jingle session-initiate")?,
|
||||
"VP9".to_owned(),
|
||||
90000,
|
||||
1,
|
||||
)],
|
||||
"h264" => {
|
||||
if let Some(h264_pt) = h264_payload_type {
|
||||
let mut pt = PayloadType::new(h264_pt, "H264".to_owned(), 90000, 1);
|
||||
pt.rtcp_fbs = h264_rtcp_fbs.clone().unwrap_or_default();
|
||||
pts.push(pt);
|
||||
if let Some(rtx_pt) = h264_rtx_payload_type {
|
||||
let mut rtx_pt = PayloadType::new(rtx_pt, "rtx".to_owned(), 90000, 1);
|
||||
rtx_pt.parameters = vec![jingle_rtp::Parameter {
|
||||
name: "apt".to_owned(),
|
||||
value: h264_pt.to_string(),
|
||||
}];
|
||||
pts.push(rtx_pt);
|
||||
}
|
||||
}
|
||||
else {
|
||||
bail!("no h264 payload type in jingle session-initiate");
|
||||
}
|
||||
},
|
||||
"vp8" => {
|
||||
if let Some(vp8_pt) = vp8_payload_type {
|
||||
let mut pt = PayloadType::new(vp8_pt, "VP8".to_owned(), 90000, 1);
|
||||
pt.rtcp_fbs = vp8_rtcp_fbs.clone().unwrap_or_default();
|
||||
pts.push(pt);
|
||||
if let Some(rtx_pt) = vp8_rtx_payload_type {
|
||||
let mut rtx_pt = PayloadType::new(rtx_pt, "rtx".to_owned(), 90000, 1);
|
||||
rtx_pt.parameters = vec![jingle_rtp::Parameter {
|
||||
name: "apt".to_owned(),
|
||||
value: vp8_pt.to_string(),
|
||||
}];
|
||||
pts.push(rtx_pt);
|
||||
}
|
||||
}
|
||||
else {
|
||||
bail!("no vp8 payload type in jingle session-initiate");
|
||||
}
|
||||
},
|
||||
"vp9" => {
|
||||
if let Some(vp9_pt) = vp9_payload_type {
|
||||
let mut pt = PayloadType::new(vp9_pt, "VP9".to_owned(), 90000, 1);
|
||||
pt.rtcp_fbs = vp9_rtcp_fbs.clone().unwrap_or_default();
|
||||
pts.push(pt);
|
||||
if let Some(rtx_pt) = vp9_rtx_payload_type {
|
||||
let mut rtx_pt = PayloadType::new(rtx_pt, "rtx".to_owned(), 90000, 1);
|
||||
rtx_pt.parameters = vec![jingle_rtp::Parameter {
|
||||
name: "apt".to_owned(),
|
||||
value: vp9_pt.to_string(),
|
||||
}];
|
||||
pts.push(rtx_pt);
|
||||
}
|
||||
}
|
||||
else {
|
||||
bail!("no vp9 payload type in jingle session-initiate");
|
||||
}
|
||||
|
||||
},
|
||||
other => bail!("unsupported video codec: {}", other),
|
||||
}
|
||||
pts
|
||||
};
|
||||
|
||||
description.rtcp_mux = Some(RtcpMux);
|
||||
|
@ -912,11 +1072,21 @@ impl JingleSession {
|
|||
let label = Uuid::new_v4().to_string();
|
||||
let cname = Uuid::new_v4().to_string();
|
||||
|
||||
description.ssrc = Some(if initiate_content.name.0 == "audio" {
|
||||
audio_ssrc.to_string()
|
||||
}
|
||||
else {
|
||||
video_ssrc.to_string()
|
||||
});
|
||||
|
||||
description.ssrcs = if initiate_content.name.0 == "audio" {
|
||||
vec![jingle_ssma::Source::new(audio_ssrc.to_string())]
|
||||
}
|
||||
else {
|
||||
vec![jingle_ssma::Source::new(video_ssrc.to_string())]
|
||||
vec![
|
||||
jingle_ssma::Source::new(video_ssrc.to_string()),
|
||||
jingle_ssma::Source::new(video_rtx_ssrc.to_string()),
|
||||
]
|
||||
};
|
||||
|
||||
for ssrc in description.ssrcs.iter_mut() {
|
||||
|
@ -928,16 +1098,21 @@ impl JingleSession {
|
|||
name: "msid".to_owned(),
|
||||
value: Some(format!("{} {}", mslabel, label)),
|
||||
});
|
||||
ssrc.parameters.push(Parameter {
|
||||
name: "mslabel".to_owned(),
|
||||
value: Some(mslabel.clone()),
|
||||
});
|
||||
ssrc.parameters.push(Parameter {
|
||||
name: "label".to_owned(),
|
||||
value: Some(label.clone()),
|
||||
});
|
||||
}
|
||||
|
||||
description.ssrc_groups = if initiate_content.name.0 == "audio" {
|
||||
vec![]
|
||||
}
|
||||
else {
|
||||
vec![jingle_ssma::Group {
|
||||
semantics: "FID".to_owned(),
|
||||
sources: vec![
|
||||
jingle_ssma::Source::new(video_ssrc.to_string()),
|
||||
jingle_ssma::Source::new(video_rtx_ssrc.to_string()),
|
||||
],
|
||||
}]
|
||||
};
|
||||
|
||||
if initiate_content.name.0 == "audio" {
|
||||
// TODO: fails to negotiate
|
||||
// if let Some(hdrext) = audio_hdrext_ssrc_audio_level {
|
||||
|
|
Loading…
Reference in New Issue