@@ -19,6 +19,7 @@ pub mod sdp_type;
19
19
pub mod session_description;
20
20
21
21
use crate :: peer_connection:: MEDIA_SECTION_APPLICATION ;
22
+ use crate :: SDP_ATTRIBUTE_RID ;
22
23
use ice:: candidate:: candidate_base:: unmarshal_candidate;
23
24
use ice:: candidate:: Candidate ;
24
25
use sdp:: description:: common:: { Address , ConnectionInformation } ;
@@ -40,27 +41,37 @@ pub(crate) struct TrackDetails {
40
41
pub ( crate ) kind : RTPCodecType ,
41
42
pub ( crate ) stream_id : String ,
42
43
pub ( crate ) id : String ,
43
- pub ( crate ) ssrc : SSRC ,
44
+ pub ( crate ) ssrcs : Vec < SSRC > ,
45
+ pub ( crate ) repair_ssrc : SSRC ,
44
46
pub ( crate ) rids : Vec < String > ,
45
47
}
46
48
47
49
pub ( crate ) fn track_details_for_ssrc (
48
50
track_details : & [ TrackDetails ] ,
49
51
ssrc : SSRC ,
50
52
) -> 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) )
52
61
}
53
62
54
63
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) ) ;
56
65
}
57
66
58
67
/// extract all TrackDetails from an SDP.
59
68
pub ( crate ) fn track_details_from_sdp ( s : & SessionDescription ) -> Vec < TrackDetails > {
60
69
let mut incoming_tracks = vec ! [ ] ;
61
- let mut rtx_repair_flows = HashMap :: new ( ) ;
62
70
63
71
for media in & s. media_descriptions {
72
+ let mut tracks_in_media_section = vec ! [ ] ;
73
+ let mut rtx_repair_flows = HashMap :: new ( ) ;
74
+
64
75
// Plan B can have multiple tracks in a signle media section
65
76
let mut stream_id = "" ;
66
77
let mut track_id = "" ;
@@ -93,21 +104,24 @@ pub(crate) fn track_details_from_sdp(s: &SessionDescription) -> Vec<TrackDetails
93
104
// as this declares that the second SSRC (632943048) is a rtx repair flow (RFC4588) for the first
94
105
// (2231627014) as specified in RFC5576
95
106
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
+ } ;
100
114
let rtx_repair_flow = match split[ 2 ] . parse :: < u32 > ( ) {
101
115
Ok ( n) => n,
102
116
Err ( err) => {
103
117
log:: warn!( "Failed to parse SSRC: {}" , err) ;
104
118
continue ;
105
119
}
106
120
} ;
107
- rtx_repair_flows. insert ( rtx_repair_flow, true ) ;
121
+ rtx_repair_flows. insert ( rtx_repair_flow, base_ssrc ) ;
108
122
// Remove if rtx was added as track before
109
123
filter_track_with_ssrc (
110
- & mut incoming_tracks ,
124
+ & mut tracks_in_media_section ,
111
125
rtx_repair_flow as SSRC ,
112
126
) ;
113
127
}
@@ -148,31 +162,41 @@ pub(crate) fn track_details_from_sdp(s: &SessionDescription) -> Vec<TrackDetails
148
162
track_id = split[ 2 ] ;
149
163
}
150
164
151
- let mut track_idx = incoming_tracks . len ( ) ;
165
+ let mut track_idx = tracks_in_media_section . len ( ) ;
152
166
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) {
155
169
track_idx = i;
156
170
//TODO: no break?
157
171
}
158
172
}
159
173
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;
166
189
} else {
167
190
let track_details = TrackDetails {
168
191
mid : mid_value. to_owned ( ) ,
169
192
kind : codec_type,
170
193
stream_id : stream_id. to_owned ( ) ,
171
194
id : track_id. to_owned ( ) ,
172
- ssrc,
195
+ ssrcs : vec ! [ ssrc] ,
196
+ repair_ssrc,
173
197
..Default :: default ( )
174
198
} ;
175
- incoming_tracks . push ( track_details) ;
199
+ tracks_in_media_section . push ( track_details) ;
176
200
}
177
201
}
178
202
}
@@ -182,7 +206,7 @@ pub(crate) fn track_details_from_sdp(s: &SessionDescription) -> Vec<TrackDetails
182
206
183
207
let rids = get_rids ( media) ;
184
208
if !rids. is_empty ( ) && !track_id. is_empty ( ) && !stream_id. is_empty ( ) {
185
- let mut new_track = TrackDetails {
209
+ let mut simulcast_track = TrackDetails {
186
210
mid : mid_value. to_owned ( ) ,
187
211
kind : codec_type,
188
212
stream_id : stream_id. to_owned ( ) ,
@@ -191,11 +215,18 @@ pub(crate) fn track_details_from_sdp(s: &SessionDescription) -> Vec<TrackDetails
191
215
..Default :: default ( )
192
216
} ;
193
217
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
+ }
195
224
}
196
225
197
- incoming_tracks . push ( new_track ) ;
226
+ tracks_in_media_section = vec ! [ simulcast_track ] ;
198
227
}
228
+
229
+ incoming_tracks. extend ( tracks_in_media_section) ;
199
230
}
200
231
201
232
incoming_tracks
@@ -204,7 +235,7 @@ pub(crate) fn track_details_from_sdp(s: &SessionDescription) -> Vec<TrackDetails
204
235
pub ( crate ) fn get_rids ( media : & MediaDescription ) -> HashMap < String , String > {
205
236
let mut rids = HashMap :: new ( ) ;
206
237
for attr in & media. attributes {
207
- if attr. key . as_str ( ) == "rid" {
238
+ if attr. key . as_str ( ) == SDP_ATTRIBUTE_RID {
208
239
if let Some ( value) = & attr. value {
209
240
let split: Vec < & str > = value. split ( ' ' ) . collect ( ) ;
210
241
rids. insert ( split[ 0 ] . to_owned ( ) , value. to_owned ( ) ) ;
@@ -425,6 +456,11 @@ pub(crate) async fn add_transceiver_sdp(
425
456
}
426
457
}
427
458
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
+
428
464
// Explicitly reject track if we don't have the codec
429
465
d = d. with_media ( MediaDescription {
430
466
media_name : sdp:: description:: media:: MediaName {
@@ -474,7 +510,8 @@ pub(crate) async fn add_transceiver_sdp(
474
510
let mut recv_rids: Vec < String > = vec ! [ ] ;
475
511
476
512
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" ) ;
478
515
recv_rids. push ( rid. to_owned ( ) ) ;
479
516
}
480
517
// Simulcast
@@ -869,7 +906,6 @@ pub(crate) fn rtp_extensions_from_media_description(
869
906
/// for subsequent calling, it updates Origin for SessionDescription from saved one
870
907
/// and increments session version by one.
871
908
/// 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
873
909
pub ( crate ) fn update_sdp_origin ( origin : & mut Origin , d : & mut SessionDescription ) {
874
910
//TODO: if atomic.CompareAndSwapUint64(&origin.SessionVersion, 0, d.Origin.SessionVersion)
875
911
if origin. session_version == 0 {
0 commit comments