Skip to content

Commit

Permalink
Set up simulcast send SSRC
Browse files Browse the repository at this point in the history
  • Loading branch information
algesten committed Jan 10, 2025
1 parent 587988a commit 0be617c
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 13 deletions.
90 changes: 77 additions & 13 deletions src/change/sdp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,17 +269,10 @@ impl<'a> SdpApi<'a> {

let mut ssrcs = Vec::new();

let ssrc_group_count = if let Some(simulcast) = &simulcast {
if simulcast.force_ssrc_groups && dir.is_sending() {
simulcast.send.len()
} else {
0usize
}
} else {
1usize
};
// Main SSRC, not counting RTX.
let main_ssrc_count = simulcast.as_ref().map(|s| s.send.len()).unwrap_or(1);

for _ in 0..ssrc_group_count {
for _ in 0..main_ssrc_count {
let rtx = kind.is_video().then(|| self.rtc.session.streams.new_ssrc());
ssrcs.push((self.rtc.session.streams.new_ssrc(), rtx));
}
Expand Down Expand Up @@ -1309,9 +1302,8 @@ impl AsSdpMediaLine for Media {
}

let count = ssrcs_tx.len();
#[allow(clippy::comparison_chain)]
for _ in 0..count {
let (ssrc, ssrc_rtx) = &ssrcs_tx[0];
for i in 0..count {

Check failure on line 1305 in src/change/sdp.rs

View workflow job for this annotation

GitHub Actions / lint

the loop variable `i` is only used to index `ssrcs_tx`
let (ssrc, ssrc_rtx) = &ssrcs_tx[i];
if let Some(ssrc_rtx) = ssrc_rtx {
attrs.push(MediaAttribute::SsrcGroup {
semantics: "FID".to_string(),
Expand Down Expand Up @@ -1564,7 +1556,10 @@ impl Change {

#[cfg(test)]
mod test {
use sdp::RestrictionId;

use crate::format::Codec;
use crate::media::Simulcast;
use crate::sdp::RtpMap;

use super::*;
Expand Down Expand Up @@ -1667,4 +1662,73 @@ mod test {
"VP9 was not offered, so it should not be present in the answer"
);
}

#[test]
fn simulcast_ssrc_allocation() {
crate::init_crypto_default();

let mut rtc1 = Rtc::new();

let mut change = rtc1.sdp_api();
change.add_media(
MediaKind::Video,
Direction::SendOnly,
None,
None,
Some(Simulcast {
send: vec!["m".into(), "h".into(), "l".into()],
recv: vec![],
}),
);

let Change::AddMedia(am) = &change.changes[0] else {
panic!("Not AddMedia?!");
};

// these should be organized in order: m, h, l
let pending_ssrcs = am.ssrcs.clone();
assert_eq!(pending_ssrcs.len(), 3);

for p in &pending_ssrcs {
assert!(p.1.is_some()); // all should have rtx
}

let (offer, _) = change.apply().unwrap();
let sdp = offer.into_inner();
let line = &sdp.media_lines[0];

assert_eq!(
line.simulcast().unwrap().send,
SimulcastGroups(vec![
RestrictionId("m".into(), true),
RestrictionId("h".into(), true),
RestrictionId("l".into(), true),
])
);

// Each SSRC, both regular and RTX get their own a=ssrc line.
assert_eq!(line.ssrc_info().len(), pending_ssrcs.len() * 2);

let fids: Vec<_> = line
.attrs
.iter()
.filter_map(|a| {
if let MediaAttribute::SsrcGroup { semantics, ssrcs } = a {
// We don't have any other semantics right now.
assert_eq!(semantics, "FID");
assert_eq!(ssrcs.len(), 2);
Some((ssrcs[0], ssrcs[1]))
} else {
None
}
})
.collect();

assert_eq!(fids.len(), pending_ssrcs.len());

for (a, b) in fids.iter().zip(pending_ssrcs.iter()) {
assert_eq!(a.0, b.0);
assert_eq!(Some(a.1), b.1);
}
}
}
5 changes: 5 additions & 0 deletions src/sdp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ impl SdpOffer {
pub fn to_sdp_string(&self) -> String {
self.0.to_string()
}

#[cfg(test)]
pub(crate) fn into_inner(self) -> Sdp {
self.0
}
}

#[derive(Debug, PartialEq, Eq)]
Expand Down

0 comments on commit 0be617c

Please sign in to comment.