Skip to content

Commit e84fdbc

Browse files
committed
Remove RTX codec if no primary
While adding transceivers from SetRemoteDescription, the filtered codecs could filter out the primart codec and leave the RTX codec in. Generating an answer with that fails `SetRemoteDescription` on remote peer due to an unrecognisable codec. Fix it by filtering out RTX is primary is not there.
1 parent 8efd17e commit e84fdbc

File tree

4 files changed

+175
-0
lines changed

4 files changed

+175
-0
lines changed

peerconnection.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1170,6 +1170,7 @@ func (pc *PeerConnection) SetRemoteDescription(desc SessionDescription) error {
11701170
filteredCodecs = append(filteredCodecs, codec)
11711171
}
11721172
}
1173+
11731174
_ = transceiver.SetCodecPreferences(filteredCodecs)
11741175
}
11751176

rtpcodec.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package webrtc
55

66
import (
77
"fmt"
8+
"strconv"
89
"strings"
910

1011
"github.com/pion/webrtc/v4/internal/fmtp"
@@ -155,6 +156,27 @@ func findRTXPayloadType(needle PayloadType, haystack []RTPCodecParameters) Paylo
155156
return PayloadType(0)
156157
}
157158

159+
// Given RTX CodecParameters find the primary CodecParameters if one exists.
160+
func findPrimaryPayloadTypeForRTX(needle RTPCodecParameters, haystack []RTPCodecParameters) PayloadType {
161+
parts := strings.Split(needle.SDPFmtpLine, "=")
162+
if len(parts) != 2 || parts[0] != "apt" {
163+
return PayloadType(0)
164+
}
165+
166+
primaryPayloadType, err := strconv.Atoi(parts[1])
167+
if err != nil || primaryPayloadType < 0 || primaryPayloadType > 255 {
168+
return PayloadType(0)
169+
}
170+
171+
for _, c := range haystack {
172+
if c.PayloadType == PayloadType(primaryPayloadType) {
173+
return c.PayloadType
174+
}
175+
}
176+
177+
return PayloadType(0)
178+
}
179+
158180
// For now, only FlexFEC is supported.
159181
func findFECPayloadType(haystack []RTPCodecParameters) PayloadType {
160182
for _, c := range haystack {

rtpcodec_test.go

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,143 @@ import (
99
"github.com/stretchr/testify/assert"
1010
)
1111

12+
func TestFindPrimaryPayloadTypeForRTX(t *testing.T) {
13+
for _, test := range []struct {
14+
Needle RTPCodecParameters
15+
Haystack []RTPCodecParameters
16+
ResultPayloadType PayloadType
17+
}{
18+
// incorrect fmtp
19+
{
20+
Needle: RTPCodecParameters{
21+
PayloadType: 2,
22+
RTPCodecCapability: RTPCodecCapability{
23+
MimeType: MimeTypeRTX,
24+
ClockRate: 90000,
25+
SDPFmtpLine: "incorrect-fmtp",
26+
},
27+
},
28+
Haystack: []RTPCodecParameters{
29+
{
30+
PayloadType: 1,
31+
RTPCodecCapability: RTPCodecCapability{
32+
MimeType: MimeTypeH264,
33+
ClockRate: 90000,
34+
},
35+
},
36+
},
37+
ResultPayloadType: 0,
38+
},
39+
// incomplete fmtp
40+
{
41+
Needle: RTPCodecParameters{
42+
PayloadType: 2,
43+
RTPCodecCapability: RTPCodecCapability{
44+
MimeType: MimeTypeRTX,
45+
ClockRate: 90000,
46+
SDPFmtpLine: "apt=",
47+
},
48+
},
49+
Haystack: []RTPCodecParameters{
50+
{
51+
PayloadType: 1,
52+
RTPCodecCapability: RTPCodecCapability{
53+
MimeType: MimeTypeH264,
54+
ClockRate: 90000,
55+
},
56+
},
57+
},
58+
ResultPayloadType: 0,
59+
},
60+
// primary payload type outside range (negative)
61+
{
62+
Needle: RTPCodecParameters{
63+
PayloadType: 2,
64+
RTPCodecCapability: RTPCodecCapability{
65+
MimeType: MimeTypeRTX,
66+
ClockRate: 90000,
67+
SDPFmtpLine: "apt=-10",
68+
},
69+
},
70+
Haystack: []RTPCodecParameters{
71+
{
72+
PayloadType: 1,
73+
RTPCodecCapability: RTPCodecCapability{
74+
MimeType: MimeTypeH264,
75+
ClockRate: 90000,
76+
},
77+
},
78+
},
79+
ResultPayloadType: 0,
80+
},
81+
// primary payload type outside range (high positive)
82+
{
83+
Needle: RTPCodecParameters{
84+
PayloadType: 2,
85+
RTPCodecCapability: RTPCodecCapability{
86+
MimeType: MimeTypeRTX,
87+
ClockRate: 90000,
88+
SDPFmtpLine: "apt=1000",
89+
},
90+
},
91+
Haystack: []RTPCodecParameters{
92+
{
93+
PayloadType: 1,
94+
RTPCodecCapability: RTPCodecCapability{
95+
MimeType: MimeTypeH264,
96+
ClockRate: 90000,
97+
},
98+
},
99+
},
100+
ResultPayloadType: 0,
101+
},
102+
// non-matching needle
103+
{
104+
Needle: RTPCodecParameters{
105+
PayloadType: 2,
106+
RTPCodecCapability: RTPCodecCapability{
107+
MimeType: MimeTypeRTX,
108+
ClockRate: 90000,
109+
SDPFmtpLine: "apt=23",
110+
},
111+
},
112+
Haystack: []RTPCodecParameters{
113+
{
114+
PayloadType: 1,
115+
RTPCodecCapability: RTPCodecCapability{
116+
MimeType: MimeTypeH264,
117+
ClockRate: 90000,
118+
},
119+
},
120+
},
121+
ResultPayloadType: 0,
122+
},
123+
// matching needle
124+
{
125+
Needle: RTPCodecParameters{
126+
PayloadType: 2,
127+
RTPCodecCapability: RTPCodecCapability{
128+
MimeType: MimeTypeRTX,
129+
ClockRate: 90000,
130+
SDPFmtpLine: "apt=1",
131+
},
132+
},
133+
Haystack: []RTPCodecParameters{
134+
{
135+
PayloadType: 1,
136+
RTPCodecCapability: RTPCodecCapability{
137+
MimeType: MimeTypeH264,
138+
ClockRate: 90000,
139+
},
140+
},
141+
},
142+
ResultPayloadType: 1,
143+
},
144+
} {
145+
assert.Equal(t, test.ResultPayloadType, findPrimaryPayloadTypeForRTX(test.Needle, test.Haystack))
146+
}
147+
}
148+
12149
func TestFindFECPayloadType(t *testing.T) {
13150
for _, test := range []struct {
14151
Haystack []RTPCodecParameters

rtptransceiver.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package webrtc
88

99
import (
1010
"fmt"
11+
"strings"
1112
"sync"
1213
"sync/atomic"
1314

@@ -60,6 +61,20 @@ func (t *RTPTransceiver) SetCodecPreferences(codecs []RTPCodecParameters) error
6061
}
6162
}
6263

64+
// remove RTX codecs if there is no corresponding primary codec
65+
for i := len(codecs) - 1; i >= 0; i-- {
66+
c := codecs[i]
67+
if !strings.EqualFold(c.MimeType, MimeTypeRTX) {
68+
continue
69+
}
70+
71+
primaryPayload := findPrimaryPayloadTypeForRTX(c, codecs)
72+
if primaryPayload == PayloadType(0) {
73+
// no primary for RTX, remove the RTX
74+
codecs = append(codecs[:i], codecs[i+1:]...)
75+
}
76+
}
77+
6378
t.codecs = codecs
6479

6580
return nil

0 commit comments

Comments
 (0)