Skip to content

Commit 635bfd9

Browse files
committed
Set prefer codec created by remote sdp
If a transceiver is created by remote sdp, then set prefer codec same as offer peer. For pion's codec match, it will use exact match first, and then partial match. If patial match only, the partial match codecs will become negotiated codes. So it will be set prefer codec when only exist partial match. And has same payload. Add test cast for this. refer to https://www.w3.org/TR/webrtc/#bib-rfc8829
1 parent 5f6baf7 commit 635bfd9

File tree

3 files changed

+138
-0
lines changed

3 files changed

+138
-0
lines changed

peerconnection.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,6 +1064,20 @@ func (pc *PeerConnection) SetRemoteDescription(desc SessionDescription) error {
10641064
pc.mu.Lock()
10651065
pc.addRTPTransceiver(t)
10661066
pc.mu.Unlock()
1067+
1068+
// if transceiver is create by remote sdp, set prefer codec same as remote peer
1069+
if codecs, err := codecsFromMediaDescription(media); err == nil {
1070+
filteredCodecs := []RTPCodecParameters{}
1071+
for _, codec := range codecs {
1072+
if c, matchType := codecParametersFuzzySearch(codec, pc.api.mediaEngine.getCodecsByKind(kind)); matchType == codecMatchExact {
1073+
// if codec match exact, use payloadtype register to mediaengine
1074+
codec.PayloadType = c.PayloadType
1075+
filteredCodecs = append(filteredCodecs, codec)
1076+
}
1077+
}
1078+
_ = t.SetCodecPreferences(filteredCodecs)
1079+
}
1080+
10671081
case direction == RTPTransceiverDirectionRecvonly:
10681082
if t.Direction() == RTPTransceiverDirectionSendrecv {
10691083
t.setDirection(RTPTransceiverDirectionSendonly)

peerconnection_go_test.go

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1433,3 +1433,124 @@ func TestPeerConnectionNilCallback(t *testing.T) {
14331433

14341434
assert.NoError(t, pc.Close())
14351435
}
1436+
1437+
func TestTransceiverCreatedByRemoteSdpHasSameCodecOrderAsRemote(t *testing.T) {
1438+
t.Run("Codec MatchExact", func(t *testing.T) { //nolint:dupl
1439+
const remoteSdp = `v=0
1440+
o=- 4596489990601351948 2 IN IP4 127.0.0.1
1441+
s=-
1442+
t=0 0
1443+
m=video 60323 UDP/TLS/RTP/SAVPF 98 94 106
1444+
a=ice-ufrag:1/MvHwjAyVf27aLu
1445+
a=ice-pwd:3dBU7cFOBl120v33cynDvN1E
1446+
a=ice-options:google-ice
1447+
a=fingerprint:sha-256 75:74:5A:A6:A4:E5:52:F4:A7:67:4C:01:C7:EE:91:3F:21:3D:A2:E3:53:7B:6F:30:86:F2:30:AA:65:FB:04:24
1448+
a=mid:0
1449+
a=rtpmap:98 H264/90000
1450+
a=fmtp:98 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
1451+
a=rtpmap:94 VP8/90000
1452+
a=rtpmap:106 H264/90000
1453+
a=fmtp:106 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f
1454+
a=sendonly
1455+
m=video 60323 UDP/TLS/RTP/SAVPF 108 98 125
1456+
a=ice-ufrag:1/MvHwjAyVf27aLu
1457+
a=ice-pwd:3dBU7cFOBl120v33cynDvN1E
1458+
a=ice-options:google-ice
1459+
a=fingerprint:sha-256 75:74:5A:A6:A4:E5:52:F4:A7:67:4C:01:C7:EE:91:3F:21:3D:A2:E3:53:7B:6F:30:86:F2:30:AA:65:FB:04:24
1460+
a=mid:1
1461+
a=rtpmap:98 H264/90000
1462+
a=fmtp:98 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
1463+
a=rtpmap:108 VP8/90000
1464+
a=sendonly
1465+
a=rtpmap:125 H264/90000
1466+
a=fmtp:125 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f
1467+
`
1468+
m := MediaEngine{}
1469+
assert.NoError(t, m.RegisterCodec(RTPCodecParameters{
1470+
RTPCodecCapability: RTPCodecCapability{MimeTypeVP8, 90000, 0, "", nil},
1471+
PayloadType: 94,
1472+
}, RTPCodecTypeVideo))
1473+
assert.NoError(t, m.RegisterCodec(RTPCodecParameters{
1474+
RTPCodecCapability: RTPCodecCapability{MimeTypeH264, 90000, 0, "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f", nil},
1475+
PayloadType: 98,
1476+
}, RTPCodecTypeVideo))
1477+
1478+
api := NewAPI(WithMediaEngine(&m))
1479+
pc, err := api.NewPeerConnection(Configuration{})
1480+
assert.NoError(t, err)
1481+
assert.NoError(t, pc.SetRemoteDescription(SessionDescription{
1482+
Type: SDPTypeOffer,
1483+
SDP: remoteSdp,
1484+
}))
1485+
ans, _ := pc.CreateAnswer(nil)
1486+
assert.NoError(t, pc.SetLocalDescription(ans))
1487+
codecOfTr1 := pc.GetTransceivers()[0].getCodecs()[0]
1488+
codecs := pc.api.mediaEngine.getCodecsByKind(RTPCodecTypeVideo)
1489+
_, matchType := codecParametersFuzzySearch(codecOfTr1, codecs)
1490+
assert.Equal(t, codecMatchExact, matchType)
1491+
codecOfTr2 := pc.GetTransceivers()[1].getCodecs()[0]
1492+
_, matchType = codecParametersFuzzySearch(codecOfTr2, codecs)
1493+
assert.Equal(t, codecMatchExact, matchType)
1494+
assert.EqualValues(t, 94, codecOfTr2.PayloadType)
1495+
assert.NoError(t, pc.Close())
1496+
})
1497+
1498+
t.Run("Codec PartialExact Only", func(t *testing.T) { //nolint:dupl
1499+
const remoteSdp = `v=0
1500+
o=- 4596489990601351948 2 IN IP4 127.0.0.1
1501+
s=-
1502+
t=0 0
1503+
m=video 60323 UDP/TLS/RTP/SAVPF 98 106
1504+
a=ice-ufrag:1/MvHwjAyVf27aLu
1505+
a=ice-pwd:3dBU7cFOBl120v33cynDvN1E
1506+
a=ice-options:google-ice
1507+
a=fingerprint:sha-256 75:74:5A:A6:A4:E5:52:F4:A7:67:4C:01:C7:EE:91:3F:21:3D:A2:E3:53:7B:6F:30:86:F2:30:AA:65:FB:04:24
1508+
a=mid:0
1509+
a=rtpmap:98 H264/90000
1510+
a=fmtp:98 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f
1511+
a=rtpmap:106 H264/90000
1512+
a=fmtp:106 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=640032
1513+
a=sendonly
1514+
m=video 60323 UDP/TLS/RTP/SAVPF 125 98
1515+
a=ice-ufrag:1/MvHwjAyVf27aLu
1516+
a=ice-pwd:3dBU7cFOBl120v33cynDvN1E
1517+
a=ice-options:google-ice
1518+
a=fingerprint:sha-256 75:74:5A:A6:A4:E5:52:F4:A7:67:4C:01:C7:EE:91:3F:21:3D:A2:E3:53:7B:6F:30:86:F2:30:AA:65:FB:04:24
1519+
a=mid:1
1520+
a=rtpmap:125 H264/90000
1521+
a=fmtp:125 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=640032
1522+
a=rtpmap:98 H264/90000
1523+
a=fmtp:98 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f
1524+
a=sendonly
1525+
`
1526+
m := MediaEngine{}
1527+
assert.NoError(t, m.RegisterCodec(RTPCodecParameters{
1528+
RTPCodecCapability: RTPCodecCapability{MimeTypeVP8, 90000, 0, "", nil},
1529+
PayloadType: 94,
1530+
}, RTPCodecTypeVideo))
1531+
assert.NoError(t, m.RegisterCodec(RTPCodecParameters{
1532+
RTPCodecCapability: RTPCodecCapability{MimeTypeH264, 90000, 0, "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f", nil},
1533+
PayloadType: 98,
1534+
}, RTPCodecTypeVideo))
1535+
1536+
api := NewAPI(WithMediaEngine(&m))
1537+
pc, err := api.NewPeerConnection(Configuration{})
1538+
assert.NoError(t, err)
1539+
assert.NoError(t, pc.SetRemoteDescription(SessionDescription{
1540+
Type: SDPTypeOffer,
1541+
SDP: remoteSdp,
1542+
}))
1543+
ans, _ := pc.CreateAnswer(nil)
1544+
assert.NoError(t, pc.SetLocalDescription(ans))
1545+
codecOfTr1 := pc.GetTransceivers()[0].getCodecs()[0]
1546+
codecs := pc.api.mediaEngine.getCodecsByKind(RTPCodecTypeVideo)
1547+
_, matchType := codecParametersFuzzySearch(codecOfTr1, codecs)
1548+
assert.Equal(t, codecMatchExact, matchType)
1549+
codecOfTr2 := pc.GetTransceivers()[1].getCodecs()[0]
1550+
_, matchType = codecParametersFuzzySearch(codecOfTr2, codecs)
1551+
assert.Equal(t, codecMatchExact, matchType)
1552+
// h.264/profile-id=640032 should be remap to 106 as same as transceiver 1
1553+
assert.EqualValues(t, 106, codecOfTr2.PayloadType)
1554+
assert.NoError(t, pc.Close())
1555+
})
1556+
}

peerconnection_media_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,9 @@ func TestPeerConnection_Media_Sample(t *testing.T) {
129129
go func() {
130130
for {
131131
time.Sleep(time.Millisecond * 100)
132+
if pcOffer.ICEConnectionState() != ICEConnectionStateConnected {
133+
continue
134+
}
132135
if routineErr := vp8Track.WriteSample(media.Sample{Data: []byte{0x00}, Duration: time.Second}); routineErr != nil {
133136
fmt.Println(routineErr)
134137
}

0 commit comments

Comments
 (0)