Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Match header extensions to all media sections in offer #2444

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 20 additions & 4 deletions mediaengine.go
Expand Up @@ -489,14 +489,30 @@ func (m *MediaEngine) updateFromRemoteDescription(desc sdp.SessionDescription) e

for _, media := range desc.MediaDescriptions {
var typ RTPCodecType

// Determine the type
switch {
case !m.negotiatedAudio && strings.EqualFold(media.MediaName.Media, "audio"):
m.negotiatedAudio = true
case strings.EqualFold(media.MediaName.Media, "audio"):
typ = RTPCodecTypeAudio
case !m.negotiatedVideo && strings.EqualFold(media.MediaName.Media, "video"):
m.negotiatedVideo = true
case strings.EqualFold(media.MediaName.Media, "video"):
typ = RTPCodecTypeVideo
}

switch {
case !m.negotiatedAudio && typ == RTPCodecTypeAudio:
m.negotiatedAudio = true
case !m.negotiatedVideo && typ == RTPCodecTypeVideo:
m.negotiatedVideo = true
default:
extensions, err := rtpExtensionsFromMediaDescription(media)
if err != nil {
return err
}
for extension, id := range extensions {
if err = m.updateHeaderExtension(id, extension, typ); err != nil {
return err
}
}
continue
}

Expand Down
66 changes: 66 additions & 0 deletions mediaengine_test.go
Expand Up @@ -212,6 +212,38 @@
assert.False(t, midVideoEnabled)
})

t.Run("Different Header Extensions on same codec", func(t *testing.T) {
const headerExtensions = `v=0
o=- 4596489990601351948 2 IN IP4 127.0.0.1
s=-
t=0 0
m=audio 9 UDP/TLS/RTP/SAVPF 111
a=rtpmap:111 opus/48000/2
m=audio 9 UDP/TLS/RTP/SAVPF 111
a=extmap:7 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=rtpmap:111 opus/48000/2
`

m := MediaEngine{}
assert.NoError(t, m.RegisterDefaultCodecs())
registerSimulcastHeaderExtensions(&m, RTPCodecTypeAudio)

Check failure on line 230 in mediaengine_test.go

View workflow job for this annotation

GitHub Actions / test (1.19) / Go 1.19

undefined: registerSimulcastHeaderExtensions

Check failure on line 230 in mediaengine_test.go

View workflow job for this annotation

GitHub Actions / test (1.20) / Go 1.20

undefined: registerSimulcastHeaderExtensions
assert.NoError(t, m.updateFromRemoteDescription(mustParse(headerExtensions)))

assert.False(t, m.negotiatedVideo)
assert.True(t, m.negotiatedAudio)

absID, absAudioEnabled, absVideoEnabled := m.getHeaderExtensionID(RTPHeaderExtensionCapability{sdp.ABSSendTimeURI})
assert.Equal(t, absID, 0)
assert.False(t, absAudioEnabled)
assert.False(t, absVideoEnabled)

midID, midAudioEnabled, midVideoEnabled := m.getHeaderExtensionID(RTPHeaderExtensionCapability{sdp.SDESMidURI})
assert.Equal(t, midID, 7)
assert.True(t, midAudioEnabled)
assert.False(t, midVideoEnabled)
})

t.Run("Prefers exact codec matches", func(t *testing.T) {
const profileLevels = `v=0
o=- 4596489990601351948 2 IN IP4 127.0.0.1
Expand Down Expand Up @@ -368,6 +400,40 @@
_, _, err := m.getCodecByPayload(97)
assert.ErrorIs(t, err, ErrCodecNotFound)
})

t.Run("Multiple codecs same kind", func(t *testing.T) {
const mixedCodecs = `v=0
o=- 4596489990601351948 2 IN IP4 127.0.0.1
s=-
t=0 0
m=video 60323 UDP/TLS/RTP/SAVPF 96
a=rtpmap:96 VP9/90000
m=video 60323 UDP/TLS/RTP/SAVPF 94
a=rtpmap:94 VP8/90000
`
m := MediaEngine{}
assert.NoError(t, m.RegisterCodec(RTPCodecParameters{
RTPCodecCapability: RTPCodecCapability{MimeTypeVP8, 90000, 0, "", nil},
PayloadType: 94,
}, RTPCodecTypeVideo))
assert.NoError(t, m.RegisterCodec(RTPCodecParameters{
RTPCodecCapability: RTPCodecCapability{MimeTypeVP9, 90000, 0, "", nil},
PayloadType: 96,
}, RTPCodecTypeVideo))

assert.NoError(t, m.updateFromRemoteDescription(mustParse(mixedCodecs)))
assert.True(t, m.negotiatedVideo)

vp8Codec, _, err := m.getCodecByPayload(94)
assert.NoError(t, err)
assert.Equal(t, vp8Codec.MimeType, MimeTypeVP8)

vp9Codec, _, err := m.getCodecByPayload(96)
assert.NoError(t, err)
assert.Equal(t, vp9Codec.MimeType, MimeTypeVP9)

})

}

func TestMediaEngineHeaderExtensionDirection(t *testing.T) {
Expand Down
4 changes: 3 additions & 1 deletion peerconnection.go
Expand Up @@ -2475,7 +2475,9 @@ func (pc *PeerConnection) generateMatchedSDP(transceivers []*RTPTransceiver, use
sender.setNegotiated()
}
mediaTransceivers := []*RTPTransceiver{t}
mediaSections = append(mediaSections, mediaSection{id: midValue, transceivers: mediaTransceivers, ridMap: getRids(media)})

extensions, _ := rtpExtensionsFromMediaDescription(media)
mediaSections = append(mediaSections, mediaSection{id: midValue, transceivers: mediaTransceivers, extensions: extensions, ridMap: getRids(media)})
}
}

Expand Down
13 changes: 9 additions & 4 deletions sdp.go
Expand Up @@ -463,11 +463,15 @@ func addTransceiverSDP(

parameters := mediaEngine.getRTPParametersByKind(t.kind, directions)
for _, rtpExtension := range parameters.HeaderExtensions {
extURL, err := url.Parse(rtpExtension.URI)
if err != nil {
return false, err
if mediaSection.extensions != nil {
if _, enabled := mediaSection.extensions[rtpExtension.URI]; enabled {
extURL, err := url.Parse(rtpExtension.URI)
if err != nil {
return false, err
}
media.WithExtMap(sdp.ExtMap{Value: rtpExtension.ID, URI: extURL})
}
}
media.WithExtMap(sdp.ExtMap{Value: rtpExtension.ID, URI: extURL})
}

if len(mediaSection.ridMap) > 0 {
Expand Down Expand Up @@ -505,6 +509,7 @@ type mediaSection struct {
transceivers []*RTPTransceiver
data bool
ridMap map[string]string
extensions map[string]int
}

func bundleMatchFromRemote(matchBundleGroup *string) func(mid string) bool {
Expand Down