Skip to content

Commit 7367daf

Browse files
committed
Increase requirements for Plan-B detection
Before a SessionDescription was assumed to be Plan-B if it contained a MediaName of `audio` or `video`. This PR Changes that behavior. If SDPSemantics is UnifiedPlan the SessionDescription must contain a MediaDescription with two SSRCes to be considered a Plan-B. Before if the MediaDescription had name of `audio` or `video` it was assumed to be Plan-B. If SDPSemantics is PlanB or UnifiedPlanWithFallback it maintains the existing behavior. Resolves #2193
1 parent 4983f08 commit 7367daf

File tree

4 files changed

+39
-7
lines changed

4 files changed

+39
-7
lines changed

peerconnection.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -635,8 +635,8 @@ func (pc *PeerConnection) CreateOffer(options *OfferOptions) (SessionDescription
635635
// in-parallel steps to create an offer
636636
// https://w3c.github.io/webrtc-pc/#dfn-in-parallel-steps-to-create-an-offer
637637
isPlanB := pc.configuration.SDPSemantics == SDPSemanticsPlanB
638-
if pc.currentRemoteDescription != nil {
639-
isPlanB = descriptionIsPlanB(pc.currentRemoteDescription)
638+
if pc.currentRemoteDescription != nil && isPlanB {
639+
isPlanB = descriptionPossiblyPlanB(pc.currentRemoteDescription)
640640
}
641641

642642
// include unmatched local transceivers
@@ -1032,7 +1032,11 @@ func (pc *PeerConnection) SetRemoteDescription(desc SessionDescription) error {
10321032

10331033
var t *RTPTransceiver
10341034
localTransceivers := append([]*RTPTransceiver{}, pc.GetTransceivers()...)
1035-
detectedPlanB := descriptionIsPlanB(pc.RemoteDescription())
1035+
detectedPlanB := descriptionIsPlanB(pc.RemoteDescription(), pc.log)
1036+
if pc.configuration.SDPSemantics != SDPSemanticsUnifiedPlan {
1037+
detectedPlanB = descriptionPossiblyPlanB(pc.RemoteDescription())
1038+
}
1039+
10361040
weOffer := desc.Type == SDPTypeAnswer
10371041

10381042
if !weOffer && !detectedPlanB {
@@ -1355,7 +1359,7 @@ func (pc *PeerConnection) startRTPReceivers(remoteDesc *SessionDescription, curr
13551359
case SDPSemanticsPlanB:
13561360
remoteIsPlanB = true
13571361
case SDPSemanticsUnifiedPlanWithFallback:
1358-
remoteIsPlanB = descriptionIsPlanB(pc.RemoteDescription())
1362+
remoteIsPlanB = descriptionPossiblyPlanB(pc.RemoteDescription())
13591363
default:
13601364
// none
13611365
}
@@ -2281,7 +2285,12 @@ func (pc *PeerConnection) generateMatchedSDP(transceivers []*RTPTransceiver, use
22812285
}
22822286
isExtmapAllowMixed := isExtMapAllowMixedSet(remoteDescription.parsed)
22832287
localTransceivers := append([]*RTPTransceiver{}, transceivers...)
2284-
detectedPlanB := descriptionIsPlanB(remoteDescription)
2288+
2289+
detectedPlanB := descriptionIsPlanB(remoteDescription, pc.log)
2290+
if pc.configuration.SDPSemantics != SDPSemanticsUnifiedPlan {
2291+
detectedPlanB = descriptionPossiblyPlanB(remoteDescription)
2292+
}
2293+
22852294
mediaSections := []mediaSection{}
22862295
alreadyHaveApplicationMediaSection := false
22872296
for _, media := range remoteDescription.parsed.MediaDescriptions {

peerconnection_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,7 @@ t=0 0
486486
a=group:BUNDLE audio
487487
a=msid-semantic: WMS 2867270241552712
488488
m=video 0 UDP/TLS/RTP/SAVPF 0
489+
a=mid:video
489490
c=IN IP4 192.168.84.254
490491
a=inactive
491492
m=audio 9 UDP/TLS/RTP/SAVPF 111

sdp.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -568,7 +568,29 @@ func getMidValue(media *sdp.MediaDescription) string {
568568
return ""
569569
}
570570

571-
func descriptionIsPlanB(desc *SessionDescription) bool {
571+
// SessionDescription contains a MediaSection with Multiple SSRCs, it is Plan-B
572+
func descriptionIsPlanB(desc *SessionDescription, log logging.LeveledLogger) bool {
573+
if desc == nil || desc.parsed == nil {
574+
return false
575+
}
576+
577+
// Store all MIDs that already contain a track
578+
midWithTrack := map[string]bool{}
579+
580+
for _, trackDetail := range trackDetailsFromSDP(log, desc.parsed) {
581+
if _, ok := midWithTrack[trackDetail.mid]; ok {
582+
return true
583+
}
584+
midWithTrack[trackDetail.mid] = true
585+
}
586+
587+
return false
588+
}
589+
590+
// SessionDescription contains a MediaSection with name `audio`, `video` or `data`
591+
// If only one SSRC is set we can't know if it is Plan-B or Unified. If users have
592+
// set fallback mode assume it is Plan-B
593+
func descriptionPossiblyPlanB(desc *SessionDescription) bool {
572594
if desc == nil || desc.parsed == nil {
573595
return false
574596
}

sdpsemantics_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ func TestSDPSemantics_UnifiedPlanWithFallback(t *testing.T) {
325325

326326
// Assert that we can catch Remote SessionDescription that don't match our Semantics
327327
func TestSDPSemantics_SetRemoteDescription_Mismatch(t *testing.T) {
328-
planBOffer := "v=0\r\no=- 4648475892259889561 3 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE video audio\r\na=ice-ufrag:1hhfzwf0ijpzm\r\na=ice-pwd:jm5puo2ab1op3vs59ca53bdk7s\r\na=fingerprint:sha-256 40:42:FB:47:87:52:BF:CB:EC:3A:DF:EB:06:DA:2D:B7:2F:59:42:10:23:7B:9D:4C:C9:58:DD:FF:A2:8F:17:67\r\nm=video 9 UDP/TLS/RTP/SAVPF 96\r\nc=IN IP4 0.0.0.0\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=setup:passive\r\na=mid:video\r\na=sendonly\r\na=rtcp-mux\r\na=rtpmap:96 H264/90000\r\na=rtcp-fb:96 nack\r\na=rtcp-fb:96 goog-remb\r\na=fmtp:96 packetization-mode=1;profile-level-id=42e01f\r\na=ssrc:1505338584 cname:10000000b5810aac\r\nm=audio 9 UDP/TLS/RTP/SAVPF 111\r\nc=IN IP4 0.0.0.0\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=setup:passive\r\na=mid:audio\r\na=sendonly\r\na=rtcp-mux\r\na=rtpmap:111 opus/48000/2\r\na=ssrc:697641945 cname:10000000b5810aac\r\n"
328+
planBOffer := "v=0\r\no=- 4648475892259889561 3 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE video audio\r\na=ice-ufrag:1hhfzwf0ijpzm\r\na=ice-pwd:jm5puo2ab1op3vs59ca53bdk7s\r\na=fingerprint:sha-256 40:42:FB:47:87:52:BF:CB:EC:3A:DF:EB:06:DA:2D:B7:2F:59:42:10:23:7B:9D:4C:C9:58:DD:FF:A2:8F:17:67\r\nm=video 9 UDP/TLS/RTP/SAVPF 96\r\nc=IN IP4 0.0.0.0\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=setup:passive\r\na=mid:video\r\na=sendonly\r\na=rtcp-mux\r\na=rtpmap:96 H264/90000\r\na=rtcp-fb:96 nack\r\na=rtcp-fb:96 goog-remb\r\na=fmtp:96 packetization-mode=1;profile-level-id=42e01f\r\na=ssrc:1505338584 cname:10000000b5810aac\r\na=ssrc:1 cname:trackB\r\nm=audio 9 UDP/TLS/RTP/SAVPF 111\r\nc=IN IP4 0.0.0.0\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=setup:passive\r\na=mid:audio\r\na=sendonly\r\na=rtcp-mux\r\na=rtpmap:111 opus/48000/2\r\na=ssrc:697641945 cname:10000000b5810aac\r\n"
329329
unifiedPlanOffer := "v=0\r\no=- 4648475892259889561 3 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0 1\r\na=ice-ufrag:1hhfzwf0ijpzm\r\na=ice-pwd:jm5puo2ab1op3vs59ca53bdk7s\r\na=fingerprint:sha-256 40:42:FB:47:87:52:BF:CB:EC:3A:DF:EB:06:DA:2D:B7:2F:59:42:10:23:7B:9D:4C:C9:58:DD:FF:A2:8F:17:67\r\nm=video 9 UDP/TLS/RTP/SAVPF 96\r\nc=IN IP4 0.0.0.0\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=setup:passive\r\na=mid:0\r\na=sendonly\r\na=rtcp-mux\r\na=rtpmap:96 H264/90000\r\na=rtcp-fb:96 nack\r\na=rtcp-fb:96 goog-remb\r\na=fmtp:96 packetization-mode=1;profile-level-id=42e01f\r\na=ssrc:1505338584 cname:10000000b5810aac\r\nm=audio 9 UDP/TLS/RTP/SAVPF 111\r\nc=IN IP4 0.0.0.0\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=setup:passive\r\na=mid:1\r\na=sendonly\r\na=rtcp-mux\r\na=rtpmap:111 opus/48000/2\r\na=ssrc:697641945 cname:10000000b5810aac\r\n"
330330

331331
report := test.CheckRoutines(t)

0 commit comments

Comments
 (0)