Skip to content

Commit 1385481

Browse files
Fix missing RTX codec using SetCodecPreferences
1 parent e4ff415 commit 1385481

File tree

4 files changed

+162
-1
lines changed

4 files changed

+162
-1
lines changed

rtpcodec.go

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ func codecParametersFuzzySearch(
143143
return RTPCodecParameters{}, codecMatchNone
144144
}
145145

146-
// Given a CodecParameters find the RTX CodecParameters if one exists.
146+
// Given a CodecParameters find the RTX Payload if one exists.
147147
func findRTXPayloadType(needle PayloadType, haystack []RTPCodecParameters) PayloadType {
148148
aptStr := fmt.Sprintf("apt=%d", needle)
149149
for _, c := range haystack {
@@ -155,6 +155,46 @@ func findRTXPayloadType(needle PayloadType, haystack []RTPCodecParameters) Paylo
155155
return PayloadType(0)
156156
}
157157

158+
// Given a RTPCodecParameters check if it exists in a list of other RTPCodecParameters.
159+
func doesCodecExistInList(
160+
needle RTPCodecParameters,
161+
haystack []RTPCodecParameters,
162+
) bool {
163+
needleFmtp := fmtp.Parse(
164+
needle.RTPCodecCapability.MimeType,
165+
needle.RTPCodecCapability.ClockRate,
166+
needle.RTPCodecCapability.Channels,
167+
needle.RTPCodecCapability.SDPFmtpLine,
168+
)
169+
170+
for _, c := range haystack {
171+
cfmtp := fmtp.Parse(
172+
c.RTPCodecCapability.MimeType,
173+
c.RTPCodecCapability.ClockRate,
174+
c.RTPCodecCapability.Channels,
175+
c.RTPCodecCapability.SDPFmtpLine,
176+
)
177+
178+
if needleFmtp.Match(cfmtp) {
179+
return true
180+
}
181+
}
182+
183+
return false
184+
}
185+
186+
// Given a CodecParameters find the RTX CodecParameters if one exists.
187+
func findRTXPCodec(needle PayloadType, haystack []RTPCodecParameters) *RTPCodecParameters {
188+
aptStr := fmt.Sprintf("apt=%d", needle)
189+
for _, c := range haystack {
190+
if aptStr == c.SDPFmtpLine {
191+
return &c
192+
}
193+
}
194+
195+
return nil
196+
}
197+
158198
func rtcpFeedbackIntersection(a, b []RTCPFeedback) (out []RTCPFeedback) {
159199
for _, aFeedback := range a {
160200
for _, bFeeback := range b {

rtpcodec_test.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
2+
// SPDX-License-Identifier: MIT
3+
4+
//go:build !js
5+
// +build !js
6+
7+
package webrtc
8+
9+
import (
10+
"testing"
11+
12+
"github.com/stretchr/testify/assert"
13+
)
14+
15+
func Test_DoesCodecExistInList(t *testing.T) {
16+
mediaEngine := &MediaEngine{}
17+
NewAPI(WithMediaEngine(mediaEngine))
18+
assert.NoError(t, mediaEngine.RegisterDefaultCodecs())
19+
20+
codecs := mediaEngine.getCodecsByKind(RTPCodecTypeVideo)
21+
22+
tests := []struct {
23+
Label string
24+
Result bool
25+
Codec RTPCodecParameters
26+
}{
27+
{
28+
Label: "Codec does not exist in list",
29+
Result: false,
30+
Codec: RTPCodecParameters{
31+
RTPCodecCapability: RTPCodecCapability{
32+
"I am bad mimetype",
33+
90000,
34+
0,
35+
"",
36+
[]RTCPFeedback{
37+
{"goog-remb", ""},
38+
{"ccm", "fir"},
39+
{"nack", ""},
40+
{"nack", "pli"},
41+
},
42+
},
43+
PayloadType: 96,
44+
},
45+
},
46+
{
47+
Label: "Codec does exist in list",
48+
Result: true,
49+
Codec: codecs[0],
50+
},
51+
}
52+
53+
for _, test := range tests {
54+
t.Run(test.Label, func(t *testing.T) {
55+
assert.Equal(t, test.Result, doesCodecExistInList(test.Codec, codecs))
56+
})
57+
}
58+
}

rtptransceiver.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,17 @@ func (t *RTPTransceiver) getCodecs() []RTPCodecParameters {
8686
}
8787
}
8888

89+
// check if direction is specified
90+
if t.direction.Load() != nil {
91+
for _, c := range filteredCodecs {
92+
if rtxCodec := findRTXPCodec(c.PayloadType, mediaEngineCodecs); rtxCodec != nil {
93+
if !doesCodecExistInList(*rtxCodec, filteredCodecs) {
94+
filteredCodecs = append(filteredCodecs, *rtxCodec)
95+
}
96+
}
97+
}
98+
}
99+
89100
return filteredCodecs
90101
}
91102

rtptransceiver_test.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,55 @@ func Test_RTPTransceiver_SetCodecPreferences_PayloadType(t *testing.T) {
135135

136136
closePairNow(t, offerPC, answerPC)
137137
}
138+
139+
func Test_RTPTransceiver_SDP_Codec(t *testing.T) {
140+
tests := []struct {
141+
Label string
142+
setPreferences bool
143+
}{
144+
{
145+
Label: "NoSetCodecPreferences",
146+
setPreferences: false,
147+
},
148+
{
149+
Label: "SetCodecPreferences",
150+
setPreferences: true,
151+
},
152+
}
153+
154+
for _, test := range tests {
155+
t.Run(test.Label, func(t *testing.T) {
156+
pc, err := NewPeerConnection(Configuration{})
157+
assert.NoError(t, err)
158+
159+
transceiver, err := pc.AddTransceiverFromKind(
160+
RTPCodecTypeVideo,
161+
RTPTransceiverInit{
162+
Direction: RTPTransceiverDirectionRecvonly,
163+
},
164+
)
165+
assert.NoError(t, err)
166+
167+
if test.setPreferences {
168+
codec := RTPCodecCapability{
169+
"video/vp8", 90000, 0, "", nil,
170+
}
171+
172+
err = transceiver.SetCodecPreferences(
173+
[]RTPCodecParameters{
174+
{
175+
RTPCodecCapability: codec,
176+
},
177+
},
178+
)
179+
assert.NoError(t, err)
180+
}
181+
182+
offer, err := pc.CreateOffer(nil)
183+
assert.NoError(t, err)
184+
185+
assert.Equal(t, true, strings.Contains(offer.SDP, "apt=96"))
186+
assert.NoError(t, pc.Close())
187+
})
188+
}
189+
}

0 commit comments

Comments
 (0)