Skip to content

Commit dd7b283

Browse files
authored
Configuration of outgoing RTX streams (#607)
* interceptor: Add AssociatedStreamInfo and populate for rtx streams * rtp_sender: Create outgoing rtx streams * sdp: Assign repair stream regardless of attribute order
1 parent b00ebe2 commit dd7b283

File tree

13 files changed

+569
-38
lines changed

13 files changed

+569
-38
lines changed

interceptor/src/stream_info.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@ pub struct StreamInfo {
2020
pub channels: u16,
2121
pub sdp_fmtp_line: String,
2222
pub rtcp_feedback: Vec<RTCPFeedback>,
23+
pub associated_stream: Option<AssociatedStreamInfo>,
24+
}
25+
26+
/// AssociatedStreamInfo provides a mapping from an auxiliary stream (RTX, FEC,
27+
/// etc.) back to the original stream.
28+
#[derive(Default, Debug, Clone)]
29+
pub struct AssociatedStreamInfo {
30+
pub ssrc: u32,
31+
pub payload_type: u8,
2332
}
2433

2534
/// RTCPFeedback signals the connection to use additional RTCP packet types.

webrtc/src/api/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,11 +159,11 @@ impl API {
159159
) -> RTCRtpSender {
160160
let kind = track.as_ref().map(|t| t.kind()).unwrap_or_default();
161161
RTCRtpSender::new(
162-
self.setting_engine.get_receive_mtu(),
163162
track,
164163
kind,
165164
transport,
166165
Arc::clone(&self.media_engine),
166+
Arc::clone(&self.setting_engine),
167167
interceptor,
168168
false,
169169
)

webrtc/src/api/setting_engine/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ pub struct SettingEngine {
7878
pub(crate) srtp_protection_profiles: Vec<SrtpProtectionProfile>,
7979
pub(crate) receive_mtu: usize,
8080
pub(crate) mid_generator: Option<Arc<dyn Fn(isize) -> String + Send + Sync>>,
81+
pub(crate) enable_sender_rtx: bool,
8182
}
8283

8384
impl SettingEngine {
@@ -334,4 +335,11 @@ impl SettingEngine {
334335
pub fn set_mid_generator(&mut self, f: impl Fn(isize) -> String + Send + Sync + 'static) {
335336
self.mid_generator = Some(Arc::new(f));
336337
}
338+
339+
/// enable_sender_rtx allows outgoing rtx streams to be created where applicable.
340+
/// RTPSender will create an RTP retransmission stream for each source stream where a retransmission
341+
/// codec is configured.
342+
pub fn enable_sender_rtx(&mut self, is_enabled: bool) {
343+
self.enable_sender_rtx = is_enabled;
344+
}
337345
}

webrtc/src/peer_connection/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1415,11 +1415,11 @@ impl RTCPeerConnection {
14151415

14161416
let sender = Arc::new(
14171417
RTCRtpSender::new(
1418-
receive_mtu,
14191418
None,
14201419
kind,
14211420
Arc::clone(&self.internal.dtls_transport),
14221421
Arc::clone(&self.internal.media_engine),
1422+
Arc::clone(&self.internal.setting_engine),
14231423
Arc::clone(&self.interceptor),
14241424
false,
14251425
)

webrtc/src/peer_connection/peer_connection_internal.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -528,11 +528,11 @@ impl PeerConnectionInternal {
528528

529529
let sender = Arc::new(
530530
RTCRtpSender::new(
531-
self.setting_engine.get_receive_mtu(),
532531
None,
533532
kind,
534533
Arc::clone(&self.dtls_transport),
535534
Arc::clone(&self.media_engine),
535+
Arc::clone(&self.setting_engine),
536536
interceptor,
537537
false,
538538
)
@@ -582,11 +582,11 @@ impl PeerConnectionInternal {
582582

583583
let s = Arc::new(
584584
RTCRtpSender::new(
585-
self.setting_engine.get_receive_mtu(),
586585
Some(Arc::clone(&track)),
587586
track.kind(),
588587
Arc::clone(&self.dtls_transport),
589588
Arc::clone(&self.media_engine),
589+
Arc::clone(&self.setting_engine),
590590
Arc::clone(&interceptor),
591591
false,
592592
)
@@ -1080,6 +1080,7 @@ impl PeerConnectionInternal {
10801080
params.codecs[0].payload_type,
10811081
params.codecs[0].capability.clone(),
10821082
&params.header_extensions,
1083+
None,
10831084
);
10841085
let (rtp_read_stream, rtp_interceptor, rtcp_read_stream, rtcp_interceptor) = self
10851086
.dtls_transport
@@ -1386,20 +1387,30 @@ impl PeerConnectionInternal {
13861387
let sender = transceiver.sender().await;
13871388
let track_encodings = sender.track_encodings.lock().await;
13881389
for encoding in track_encodings.iter() {
1389-
let track_id = encoding.track.id().to_string();
1390+
let track_id = encoding.track.id();
13901391
let kind = match encoding.track.kind() {
13911392
RTPCodecType::Unspecified => continue,
13921393
RTPCodecType::Audio => "audio",
13931394
RTPCodecType::Video => "video",
13941395
};
13951396

13961397
track_infos.push(TrackInfo {
1397-
track_id,
1398+
track_id: track_id.to_owned(),
13981399
ssrc: encoding.ssrc,
13991400
mid: mid.to_owned(),
14001401
rid: encoding.track.rid().map(Into::into),
14011402
kind,
14021403
});
1404+
1405+
if let Some(rtx) = &encoding.rtx {
1406+
track_infos.push(TrackInfo {
1407+
track_id: track_id.to_owned(),
1408+
ssrc: rtx.ssrc,
1409+
mid: mid.to_owned(),
1410+
rid: encoding.track.rid().map(Into::into),
1411+
kind,
1412+
});
1413+
}
14031414
}
14041415
}
14051416

webrtc/src/peer_connection/sdp/mod.rs

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -178,29 +178,19 @@ pub(crate) fn track_details_from_sdp(
178178
}
179179
}
180180

181-
let mut repair_ssrc = 0;
182-
for (repair, base) in &rtx_repair_flows {
183-
if *base == ssrc {
184-
repair_ssrc = *repair;
185-
//TODO: no break?
186-
}
187-
}
188-
189181
if track_idx < tracks_in_media_section.len() {
190182
tracks_in_media_section[track_idx].mid = SmolStr::from(mid_value);
191183
tracks_in_media_section[track_idx].kind = codec_type;
192184
stream_id.clone_into(&mut tracks_in_media_section[track_idx].stream_id);
193185
track_id.clone_into(&mut tracks_in_media_section[track_idx].id);
194186
tracks_in_media_section[track_idx].ssrcs = vec![ssrc];
195-
tracks_in_media_section[track_idx].repair_ssrc = repair_ssrc;
196187
} else {
197188
let track_details = TrackDetails {
198189
mid: SmolStr::from(mid_value),
199190
kind: codec_type,
200191
stream_id: stream_id.to_owned(),
201192
id: track_id.to_owned(),
202193
ssrcs: vec![ssrc],
203-
repair_ssrc,
204194
..Default::default()
205195
};
206196
tracks_in_media_section.push(track_details);
@@ -210,6 +200,13 @@ pub(crate) fn track_details_from_sdp(
210200
_ => {}
211201
};
212202
}
203+
for (repair, base) in &rtx_repair_flows {
204+
for track in &mut tracks_in_media_section {
205+
if track.ssrcs.contains(base) {
206+
track.repair_ssrc = *repair;
207+
}
208+
}
209+
}
213210

214211
// If media line is using RTP Stream Identifier Source Description per RFC8851
215212
// we will need to override tracks, and remove ssrcs.
@@ -595,6 +592,23 @@ pub(crate) async fn add_transceiver_sdp(
595592
track.stream_id().to_owned(), /* streamLabel */
596593
track.id().to_owned(),
597594
);
595+
596+
if encoding.rtx.ssrc != 0 {
597+
media = media.with_media_source(
598+
encoding.rtx.ssrc,
599+
track.stream_id().to_owned(),
600+
track.stream_id().to_owned(),
601+
track.id().to_owned(),
602+
);
603+
604+
media = media.with_value_attribute(
605+
ATTR_KEY_SSRCGROUP.to_owned(),
606+
format!(
607+
"{} {} {}",
608+
SEMANTIC_TOKEN_FLOW_IDENTIFICATION, encoding.ssrc, encoding.rtx.ssrc
609+
),
610+
);
611+
}
598612
}
599613

600614
if send_parameters.encodings.len() > 1 {

0 commit comments

Comments
 (0)