Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix simulcast for firefox #534

Merged
merged 3 commits into from
Apr 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions sdp/src/extmap/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ pub const TRANSPORT_CC_URI: &str =
"http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01";
pub const SDES_MID_URI: &str = "urn:ietf:params:rtp-hdrext:sdes:mid";
pub const SDES_RTP_STREAM_ID_URI: &str = "urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id";
pub const SDES_REPAIR_RTP_STREAM_ID_URI: &str =
"urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id";

pub const AUDIO_LEVEL_URI: &str = "urn:ietf:params:rtp-hdrext:ssrc-audio-level";
pub const VIDEO_ORIENTATION_URI: &str = "urn:3gpp:video-orientation";

Expand Down
2 changes: 0 additions & 2 deletions webrtc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,3 @@ pub(crate) const RECEIVE_MTU: usize = 1460;
pub(crate) const SDP_ATTRIBUTE_RID: &str = "rid";
pub(crate) const SDP_ATTRIBUTE_SIMULCAST: &str = "simulcast";
pub(crate) const GENERATED_CERTIFICATE_ORIGIN: &str = "WebRTC";
pub(crate) const SDES_REPAIR_RTP_STREAM_ID_URI: &str =
"urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id";
40 changes: 19 additions & 21 deletions webrtc/src/peer_connection/peer_connection_internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::stats::{
StatsReportType,
};
use crate::track::TrackStream;
use crate::{SDES_REPAIR_RTP_STREAM_ID_URI, SDP_ATTRIBUTE_RID};
use crate::SDP_ATTRIBUTE_RID;

pub(crate) struct PeerConnectionInternal {
/// a value containing the last known greater mid value
Expand Down Expand Up @@ -940,7 +940,7 @@ impl PeerConnectionInternal {
let (rsid_extension_id, _, _) = self
.media_engine
.get_header_extension_id(RTCRtpHeaderExtensionCapability {
uri: SDES_REPAIR_RTP_STREAM_ID_URI.to_owned(),
uri: ::sdp::extmap::SDES_REPAIR_RTP_STREAM_ID_URI.to_owned(),
})
.await;

Expand Down Expand Up @@ -1068,40 +1068,38 @@ impl PeerConnectionInternal {
on_track_handler: Arc<ArcSwapOption<Mutex<OnTrackHdlrFn>>>,
) {
receiver.start(incoming).await;
for t in receiver.tracks().await {
if t.ssrc() == 0 {
for track in receiver.tracks().await {
if track.ssrc() == 0 {
return;
}

let receiver = Arc::clone(&receiver);
let transceiver = Arc::clone(&transceiver);
let on_track_handler = Arc::clone(&on_track_handler);
tokio::spawn(async move {
if let Some(track) = receiver.track().await {
let mut b = vec![0u8; receive_mtu];
let pkt = match track.peek(&mut b).await {
Ok((pkt, _)) => pkt,
Err(err) => {
log::warn!(
"Could not determine PayloadType for SSRC {} ({})",
track.ssrc(),
err
);
return;
}
};

if let Err(err) = track.check_and_update_track(&pkt).await {
let mut b = vec![0u8; receive_mtu];
let pkt = match track.peek(&mut b).await {
Ok((pkt, _)) => pkt,
Err(err) => {
log::warn!(
"Failed to set codec settings for track SSRC {} ({})",
"Could not determine PayloadType for SSRC {} ({})",
track.ssrc(),
err
);
return;
}
};

RTCPeerConnection::do_track(on_track_handler, track, receiver, transceiver);
if let Err(err) = track.check_and_update_track(&pkt).await {
log::warn!(
"Failed to set codec settings for track SSRC {} ({})",
track.ssrc(),
err
);
return;
}

RTCPeerConnection::do_track(on_track_handler, track, receiver, transceiver);
});
}
}
Expand Down
20 changes: 7 additions & 13 deletions webrtc/src/peer_connection/sdp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,26 +211,20 @@ pub(crate) fn track_details_from_sdp(
};
}

// If media line is using RTP Stream Identifier Source Description per RFC8851
// we will need to override tracks, and remove ssrcs.
// This is in particular important for Firefox, as it uses both 'rid', 'simulcast'
// and 'a=ssrc' lines.
let rids = get_rids(media);
if !rids.is_empty() && !track_id.is_empty() && !stream_id.is_empty() {
let mut simulcast_track = TrackDetails {
tracks_in_media_section = vec![TrackDetails {
mid: SmolStr::from(mid_value),
kind: codec_type,
stream_id: stream_id.to_owned(),
id: track_id.to_owned(),
rids: vec![],
rids: rids.iter().map(|r| SmolStr::from(&r.id)).collect(),
..Default::default()
};
for rid in &rids {
simulcast_track.rids.push(SmolStr::from(&rid.id));
}
if simulcast_track.rids.len() == tracks_in_media_section.len() {
for track in &tracks_in_media_section {
simulcast_track.ssrcs.extend(&track.ssrcs)
}
}

tracks_in_media_section = vec![simulcast_track];
}];
}

incoming_tracks.extend(tracks_in_media_section);
Expand Down
12 changes: 0 additions & 12 deletions webrtc/src/rtp_transceiver/rtp_receiver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -487,18 +487,6 @@ impl RTCRtpReceiver {
}
}

/// track returns the RtpTransceiver TrackRemote
pub async fn track(&self) -> Option<Arc<TrackRemote>> {
let tracks = self.internal.tracks.read().await;
if tracks.len() != 1 {
None
} else {
// Clippy bug (reported at https://github.com/rust-lang/rust-clippy/issues/12560) suggests .first().cloned()
#[allow(clippy::map_clone)]
tracks.first().map(|t| Arc::clone(&t.track))
}
}

/// tracks returns the RtpTransceiver traclockks
/// A RTPReceiver to support Simulcast may now have multiple tracks
pub async fn tracks(&self) -> Vec<Arc<TrackRemote>> {
Expand Down
62 changes: 32 additions & 30 deletions webrtc/src/rtp_transceiver/rtp_receiver/rtp_receiver_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,36 +92,38 @@ async fn test_set_rtp_parameters() -> Result<()> {
Box::pin(async move {
receiver.set_rtp_parameters(P.clone()).await;

if let Some(t) = receiver.track().await {
let incoming_track_codecs = t.codec();

assert_eq!(P.header_extensions, t.params().header_extensions);
assert_eq!(
P.codecs[0].capability.mime_type,
incoming_track_codecs.capability.mime_type
);
assert_eq!(
P.codecs[0].capability.clock_rate,
incoming_track_codecs.capability.clock_rate
);
assert_eq!(
P.codecs[0].capability.channels,
incoming_track_codecs.capability.channels
);
assert_eq!(
P.codecs[0].capability.sdp_fmtp_line,
incoming_track_codecs.capability.sdp_fmtp_line
);
assert_eq!(
P.codecs[0].capability.rtcp_feedback,
incoming_track_codecs.capability.rtcp_feedback
);
assert_eq!(P.codecs[0].payload_type, incoming_track_codecs.payload_type);

{
let mut done = seen_packet_tx2.lock().await;
done.take();
}
let tracks = receiver.tracks().await;
assert_eq!(tracks.len(), 1);
let t = tracks.first().unwrap();

let incoming_track_codecs = t.codec();

assert_eq!(P.header_extensions, t.params().header_extensions);
assert_eq!(
P.codecs[0].capability.mime_type,
incoming_track_codecs.capability.mime_type
);
assert_eq!(
P.codecs[0].capability.clock_rate,
incoming_track_codecs.capability.clock_rate
);
assert_eq!(
P.codecs[0].capability.channels,
incoming_track_codecs.capability.channels
);
assert_eq!(
P.codecs[0].capability.sdp_fmtp_line,
incoming_track_codecs.capability.sdp_fmtp_line
);
assert_eq!(
P.codecs[0].capability.rtcp_feedback,
incoming_track_codecs.capability.rtcp_feedback
);
assert_eq!(P.codecs[0].payload_type, incoming_track_codecs.payload_type);

{
let mut done = seen_packet_tx2.lock().await;
done.take();
}
})
}));
Expand Down
Loading