Skip to content

Commit 7407903

Browse files
committed
Match header extensions to remote media sections
Firefox would send updated header extension in renegotiation, e.g. publish a track without simucalst then renegotiate second track with simucalst, the two media secontions will have different rtp header extensions in offer. Need to match remote header extentions for each media sections to avoid second track publish failed.
1 parent 49ccf87 commit 7407903

File tree

5 files changed

+93
-19
lines changed

5 files changed

+93
-19
lines changed

mediaengine.go

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,30 @@ func (m *MediaEngine) matchRemoteCodec(remoteCodec RTPCodecParameters, typ RTPCo
456456
return matchType, nil
457457
}
458458

459+
// Update header extensions from a remote media section
460+
func (m *MediaEngine) updateHeaderExtensionFromMediaSection(media *sdp.MediaDescription) error {
461+
var typ RTPCodecType
462+
switch {
463+
case strings.EqualFold(media.MediaName.Media, "audio"):
464+
typ = RTPCodecTypeAudio
465+
case strings.EqualFold(media.MediaName.Media, "video"):
466+
typ = RTPCodecTypeVideo
467+
default:
468+
return nil
469+
}
470+
extensions, err := rtpExtensionsFromMediaDescription(media)
471+
if err != nil {
472+
return err
473+
}
474+
475+
for extension, id := range extensions {
476+
if err = m.updateHeaderExtension(id, extension, typ); err != nil {
477+
return err
478+
}
479+
}
480+
return nil
481+
}
482+
459483
// Look up a header extension and enable if it exists
460484
func (m *MediaEngine) updateHeaderExtension(id int, extension string, typ RTPCodecType) error {
461485
if m.negotiatedHeaderExtensions == nil {
@@ -499,14 +523,27 @@ func (m *MediaEngine) updateFromRemoteDescription(desc sdp.SessionDescription) e
499523

500524
for _, media := range desc.MediaDescriptions {
501525
var typ RTPCodecType
526+
502527
switch {
503-
case !m.negotiatedAudio && strings.EqualFold(media.MediaName.Media, "audio"):
504-
m.negotiatedAudio = true
528+
case strings.EqualFold(media.MediaName.Media, "audio"):
505529
typ = RTPCodecTypeAudio
506-
case !m.negotiatedVideo && strings.EqualFold(media.MediaName.Media, "video"):
507-
m.negotiatedVideo = true
530+
case strings.EqualFold(media.MediaName.Media, "video"):
508531
typ = RTPCodecTypeVideo
532+
}
533+
534+
switch {
535+
case !m.negotiatedAudio && typ == RTPCodecTypeAudio:
536+
m.negotiatedAudio = true
537+
case !m.negotiatedVideo && typ == RTPCodecTypeVideo:
538+
m.negotiatedVideo = true
509539
default:
540+
// update header extesions from remote sdp if codec is negotiated, Firefox
541+
// would send updated header extension in renegotiation.
542+
// e.g. publish first track without simucalst ->negotiated-> publish second track with simucalst
543+
// then the two media secontions have different rtp header extensions in offer
544+
if err := m.updateHeaderExtensionFromMediaSection(media); err != nil {
545+
return err
546+
}
510547
continue
511548
}
512549

@@ -542,16 +579,9 @@ func (m *MediaEngine) updateFromRemoteDescription(desc sdp.SessionDescription) e
542579
continue
543580
}
544581

545-
extensions, err := rtpExtensionsFromMediaDescription(media)
546-
if err != nil {
582+
if err := m.updateHeaderExtensionFromMediaSection(media); err != nil {
547583
return err
548584
}
549-
550-
for extension, id := range extensions {
551-
if err = m.updateHeaderExtension(id, extension, typ); err != nil {
552-
return err
553-
}
554-
}
555585
}
556586
return nil
557587
}

mediaengine_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,39 @@ a=rtpmap:111 opus/48000/2
212212
assert.False(t, midVideoEnabled)
213213
})
214214

215+
t.Run("Different Header Extensions on same codec", func(t *testing.T) {
216+
const headerExtensions = `v=0
217+
o=- 4596489990601351948 2 IN IP4 127.0.0.1
218+
s=-
219+
t=0 0
220+
m=audio 9 UDP/TLS/RTP/SAVPF 111
221+
a=rtpmap:111 opus/48000/2
222+
m=audio 9 UDP/TLS/RTP/SAVPF 111
223+
a=extmap:7 urn:ietf:params:rtp-hdrext:sdes:mid
224+
a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
225+
a=rtpmap:111 opus/48000/2
226+
`
227+
228+
m := MediaEngine{}
229+
assert.NoError(t, m.RegisterDefaultCodecs())
230+
assert.NoError(t, m.RegisterHeaderExtension(RTPHeaderExtensionCapability{URI: "urn:ietf:params:rtp-hdrext:sdes:mid"}, RTPCodecTypeAudio))
231+
assert.NoError(t, m.RegisterHeaderExtension(RTPHeaderExtensionCapability{URI: "urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id"}, RTPCodecTypeAudio))
232+
assert.NoError(t, m.updateFromRemoteDescription(mustParse(headerExtensions)))
233+
234+
assert.False(t, m.negotiatedVideo)
235+
assert.True(t, m.negotiatedAudio)
236+
237+
absID, absAudioEnabled, absVideoEnabled := m.getHeaderExtensionID(RTPHeaderExtensionCapability{sdp.ABSSendTimeURI})
238+
assert.Equal(t, absID, 0)
239+
assert.False(t, absAudioEnabled)
240+
assert.False(t, absVideoEnabled)
241+
242+
midID, midAudioEnabled, midVideoEnabled := m.getHeaderExtensionID(RTPHeaderExtensionCapability{sdp.SDESMidURI})
243+
assert.Equal(t, midID, 7)
244+
assert.True(t, midAudioEnabled)
245+
assert.False(t, midVideoEnabled)
246+
})
247+
215248
t.Run("Prefers exact codec matches", func(t *testing.T) {
216249
const profileLevels = `v=0
217250
o=- 4596489990601351948 2 IN IP4 127.0.0.1

peerconnection.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2445,7 +2445,9 @@ func (pc *PeerConnection) generateMatchedSDP(transceivers []*RTPTransceiver, use
24452445
sender.setNegotiated()
24462446
}
24472447
mediaTransceivers := []*RTPTransceiver{t}
2448-
mediaSections = append(mediaSections, mediaSection{id: midValue, transceivers: mediaTransceivers, ridMap: getRids(media)})
2448+
2449+
extensions, _ := rtpExtensionsFromMediaDescription(media)
2450+
mediaSections = append(mediaSections, mediaSection{id: midValue, transceivers: mediaTransceivers, matchExtensions: extensions, ridMap: getRids(media)})
24492451
}
24502452
}
24512453

peerconnection_media_test.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,6 +1090,9 @@ func TestPeerConnection_Simulcast_Probe(t *testing.T) {
10901090
return
10911091
}))
10921092

1093+
peerConnectionConnected := untilConnectionState(PeerConnectionStateConnected, pcOffer, pcAnswer)
1094+
peerConnectionConnected.Wait()
1095+
10931096
sequenceNumber := uint16(0)
10941097
sendRTPPacket := func() {
10951098
sequenceNumber++
@@ -1107,13 +1110,13 @@ func TestPeerConnection_Simulcast_Probe(t *testing.T) {
11071110
sendRTPPacket()
11081111
}
11091112

1110-
assert.NoError(t, signalPair(pcOffer, pcAnswer))
1111-
11121113
trackRemoteChan := make(chan *TrackRemote, 1)
11131114
pcAnswer.OnTrack(func(trackRemote *TrackRemote, _ *RTPReceiver) {
11141115
trackRemoteChan <- trackRemote
11151116
})
11161117

1118+
assert.NoError(t, signalPair(pcOffer, pcAnswer))
1119+
11171120
trackRemote := func() *TrackRemote {
11181121
for {
11191122
select {

sdp.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,11 @@ func addTransceiverSDP(
487487

488488
parameters := mediaEngine.getRTPParametersByKind(t.kind, directions)
489489
for _, rtpExtension := range parameters.HeaderExtensions {
490+
if mediaSection.matchExtensions != nil {
491+
if _, enabled := mediaSection.matchExtensions[rtpExtension.URI]; !enabled {
492+
continue
493+
}
494+
}
490495
extURL, err := url.Parse(rtpExtension.URI)
491496
if err != nil {
492497
return false, err
@@ -533,10 +538,11 @@ type simulcastRid struct {
533538
}
534539

535540
type mediaSection struct {
536-
id string
537-
transceivers []*RTPTransceiver
538-
data bool
539-
ridMap map[string]*simulcastRid
541+
id string
542+
transceivers []*RTPTransceiver
543+
data bool
544+
matchExtensions map[string]int
545+
ridMap map[string]*simulcastRid
540546
}
541547

542548
func bundleMatchFromRemote(matchBundleGroup *string) func(mid string) bool {

0 commit comments

Comments
 (0)