Skip to content

Commit b61315a

Browse files
author
Rain Liu
committed
refactoring peer_connection::sdp
1 parent ff10241 commit b61315a

File tree

1 file changed

+63
-27
lines changed

1 file changed

+63
-27
lines changed

src/peer_connection/sdp/mod.rs

Lines changed: 63 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub mod sdp_type;
1919
pub mod session_description;
2020

2121
use crate::peer_connection::MEDIA_SECTION_APPLICATION;
22+
use crate::SDP_ATTRIBUTE_RID;
2223
use ice::candidate::candidate_base::unmarshal_candidate;
2324
use ice::candidate::Candidate;
2425
use sdp::description::common::{Address, ConnectionInformation};
@@ -40,27 +41,37 @@ pub(crate) struct TrackDetails {
4041
pub(crate) kind: RTPCodecType,
4142
pub(crate) stream_id: String,
4243
pub(crate) id: String,
43-
pub(crate) ssrc: SSRC,
44+
pub(crate) ssrcs: Vec<SSRC>,
45+
pub(crate) repair_ssrc: SSRC,
4446
pub(crate) rids: Vec<String>,
4547
}
4648

4749
pub(crate) fn track_details_for_ssrc(
4850
track_details: &[TrackDetails],
4951
ssrc: SSRC,
5052
) -> Option<&TrackDetails> {
51-
track_details.iter().find(|x| x.ssrc == ssrc)
53+
track_details.iter().find(|x| x.ssrcs.contains(&ssrc))
54+
}
55+
56+
pub(crate) fn track_details_for_rid<'a>(
57+
track_details: &'a [TrackDetails],
58+
rid: &'a String,
59+
) -> Option<&'a TrackDetails> {
60+
track_details.iter().find(|x| x.rids.contains(rid))
5261
}
5362

5463
pub(crate) fn filter_track_with_ssrc(incoming_tracks: &mut Vec<TrackDetails>, ssrc: SSRC) {
55-
incoming_tracks.retain(|x| x.ssrc != ssrc);
64+
incoming_tracks.retain(|x| !x.ssrcs.contains(&ssrc));
5665
}
5766

5867
/// extract all TrackDetails from an SDP.
5968
pub(crate) fn track_details_from_sdp(s: &SessionDescription) -> Vec<TrackDetails> {
6069
let mut incoming_tracks = vec![];
61-
let mut rtx_repair_flows = HashMap::new();
6270

6371
for media in &s.media_descriptions {
72+
let mut tracks_in_media_section = vec![];
73+
let mut rtx_repair_flows = HashMap::new();
74+
6475
// Plan B can have multiple tracks in a signle media section
6576
let mut stream_id = "";
6677
let mut track_id = "";
@@ -93,21 +104,24 @@ pub(crate) fn track_details_from_sdp(s: &SessionDescription) -> Vec<TrackDetails
93104
// as this declares that the second SSRC (632943048) is a rtx repair flow (RFC4588) for the first
94105
// (2231627014) as specified in RFC5576
95106
if split.len() == 3 {
96-
if let Err(err) = split[1].parse::<u32>() {
97-
log::warn!("Failed to parse SSRC: {}", err);
98-
continue;
99-
}
107+
let base_ssrc = match split[1].parse::<u32>() {
108+
Ok(ssrc) => ssrc,
109+
Err(err) => {
110+
log::warn!("Failed to parse SSRC: {}", err);
111+
continue;
112+
}
113+
};
100114
let rtx_repair_flow = match split[2].parse::<u32>() {
101115
Ok(n) => n,
102116
Err(err) => {
103117
log::warn!("Failed to parse SSRC: {}", err);
104118
continue;
105119
}
106120
};
107-
rtx_repair_flows.insert(rtx_repair_flow, true);
121+
rtx_repair_flows.insert(rtx_repair_flow, base_ssrc);
108122
// Remove if rtx was added as track before
109123
filter_track_with_ssrc(
110-
&mut incoming_tracks,
124+
&mut tracks_in_media_section,
111125
rtx_repair_flow as SSRC,
112126
);
113127
}
@@ -148,31 +162,41 @@ pub(crate) fn track_details_from_sdp(s: &SessionDescription) -> Vec<TrackDetails
148162
track_id = split[2];
149163
}
150164

151-
let mut track_idx = incoming_tracks.len();
165+
let mut track_idx = tracks_in_media_section.len();
152166

153-
for (i, t) in incoming_tracks.iter().enumerate() {
154-
if t.ssrc == ssrc {
167+
for (i, t) in tracks_in_media_section.iter().enumerate() {
168+
if t.ssrcs.contains(&ssrc) {
155169
track_idx = i;
156170
//TODO: no break?
157171
}
158172
}
159173

160-
if track_idx < incoming_tracks.len() {
161-
incoming_tracks[track_idx].mid = mid_value.to_owned();
162-
incoming_tracks[track_idx].kind = codec_type;
163-
incoming_tracks[track_idx].stream_id = stream_id.to_owned();
164-
incoming_tracks[track_idx].id = track_id.to_owned();
165-
incoming_tracks[track_idx].ssrc = ssrc;
174+
let mut repair_ssrc = 0;
175+
for (repair, base) in &rtx_repair_flows {
176+
if *base == ssrc {
177+
repair_ssrc = *repair;
178+
//TODO: no break?
179+
}
180+
}
181+
182+
if track_idx < tracks_in_media_section.len() {
183+
tracks_in_media_section[track_idx].mid = mid_value.to_owned();
184+
tracks_in_media_section[track_idx].kind = codec_type;
185+
tracks_in_media_section[track_idx].stream_id = stream_id.to_owned();
186+
tracks_in_media_section[track_idx].id = track_id.to_owned();
187+
tracks_in_media_section[track_idx].ssrcs = vec![ssrc];
188+
tracks_in_media_section[track_idx].repair_ssrc = repair_ssrc;
166189
} else {
167190
let track_details = TrackDetails {
168191
mid: mid_value.to_owned(),
169192
kind: codec_type,
170193
stream_id: stream_id.to_owned(),
171194
id: track_id.to_owned(),
172-
ssrc,
195+
ssrcs: vec![ssrc],
196+
repair_ssrc,
173197
..Default::default()
174198
};
175-
incoming_tracks.push(track_details);
199+
tracks_in_media_section.push(track_details);
176200
}
177201
}
178202
}
@@ -182,7 +206,7 @@ pub(crate) fn track_details_from_sdp(s: &SessionDescription) -> Vec<TrackDetails
182206

183207
let rids = get_rids(media);
184208
if !rids.is_empty() && !track_id.is_empty() && !stream_id.is_empty() {
185-
let mut new_track = TrackDetails {
209+
let mut simulcast_track = TrackDetails {
186210
mid: mid_value.to_owned(),
187211
kind: codec_type,
188212
stream_id: stream_id.to_owned(),
@@ -191,11 +215,18 @@ pub(crate) fn track_details_from_sdp(s: &SessionDescription) -> Vec<TrackDetails
191215
..Default::default()
192216
};
193217
for rid in rids.keys() {
194-
new_track.rids.push(rid.to_owned());
218+
simulcast_track.rids.push(rid.to_owned());
219+
}
220+
if simulcast_track.rids.len() == tracks_in_media_section.len() {
221+
for track in &tracks_in_media_section {
222+
simulcast_track.ssrcs.extend(&track.ssrcs)
223+
}
195224
}
196225

197-
incoming_tracks.push(new_track);
226+
tracks_in_media_section = vec![simulcast_track];
198227
}
228+
229+
incoming_tracks.extend(tracks_in_media_section);
199230
}
200231

201232
incoming_tracks
@@ -204,7 +235,7 @@ pub(crate) fn track_details_from_sdp(s: &SessionDescription) -> Vec<TrackDetails
204235
pub(crate) fn get_rids(media: &MediaDescription) -> HashMap<String, String> {
205236
let mut rids = HashMap::new();
206237
for attr in &media.attributes {
207-
if attr.key.as_str() == "rid" {
238+
if attr.key.as_str() == SDP_ATTRIBUTE_RID {
208239
if let Some(value) = &attr.value {
209240
let split: Vec<&str> = value.split(' ').collect();
210241
rids.insert(split[0].to_owned(), value.to_owned());
@@ -425,6 +456,11 @@ pub(crate) async fn add_transceiver_sdp(
425456
}
426457
}
427458
if codecs.is_empty() {
459+
// If we are sender and we have no codecs throw an error early
460+
if t.sender().await.is_some() {
461+
return Err(Error::ErrSenderWithNoCodecs);
462+
}
463+
428464
// Explicitly reject track if we don't have the codec
429465
d = d.with_media(MediaDescription {
430466
media_name: sdp::description::media::MediaName {
@@ -474,7 +510,8 @@ pub(crate) async fn add_transceiver_sdp(
474510
let mut recv_rids: Vec<String> = vec![];
475511

476512
for rid in media_section.rid_map.keys() {
477-
media = media.with_value_attribute("rid".to_owned(), rid.to_owned() + " recv");
513+
media =
514+
media.with_value_attribute(SDP_ATTRIBUTE_RID.to_owned(), rid.to_owned() + " recv");
478515
recv_rids.push(rid.to_owned());
479516
}
480517
// Simulcast
@@ -869,7 +906,6 @@ pub(crate) fn rtp_extensions_from_media_description(
869906
/// for subsequent calling, it updates Origin for SessionDescription from saved one
870907
/// and increments session version by one.
871908
/// https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-25#section-5.2.2
872-
/// https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-25#section-5.3.2
873909
pub(crate) fn update_sdp_origin(origin: &mut Origin, d: &mut SessionDescription) {
874910
//TODO: if atomic.CompareAndSwapUint64(&origin.SessionVersion, 0, d.Origin.SessionVersion)
875911
if origin.session_version == 0 {

0 commit comments

Comments
 (0)