Skip to content

Commit 9e3b03a

Browse files
authored
Fix native RTP capabilities not being normalized (#341)
## Details - Fixes #340 - We need to normalize locally generated native RTP capabilities to be able to compare them properly with Router's RTP capabilities. - This was a regression introduced in PR #336. - Thanks @gnauhtt for reporting it and including the solution in the report.
1 parent 51c7d98 commit 9e3b03a

10 files changed

Lines changed: 55 additions & 26 deletions

File tree

src/Device.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ export class Device {
276276
);
277277

278278
// This may throw.
279-
ortc.validateRtpCapabilities(clonedRouterRtpCapabilities);
279+
ortc.validateAndNormalizeRtpCapabilities(clonedRouterRtpCapabilities);
280280

281281
const { getNativeRtpCapabilities, getNativeSctpCapabilities } =
282282
this._handlerFactory;
@@ -286,7 +286,7 @@ export class Device {
286286
);
287287

288288
// This may throw.
289-
ortc.validateRtpCapabilities(clonedNativeRtpCapabilities);
289+
ortc.validateAndNormalizeRtpCapabilities(clonedNativeRtpCapabilities);
290290

291291
logger.debug(
292292
'load() | got native RTP capabilities:%o',
@@ -317,7 +317,7 @@ export class Device {
317317
);
318318

319319
// This may throw.
320-
ortc.validateRtpCapabilities(this._recvRtpCapabilities);
320+
ortc.validateAndNormalizeRtpCapabilities(this._recvRtpCapabilities);
321321

322322
logger.debug(
323323
'load() | got receiving RTP capabilities:%o',

src/Transport.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,7 @@ export class Transport<
594594

595595
try {
596596
// This will fill rtpParameters's missing fields with default values.
597-
ortc.validateRtpParameters(rtpParameters);
597+
ortc.validateAndNormalizeRtpParameters(rtpParameters);
598598

599599
const { id } = await new Promise<{ id: string }>(
600600
(resolve, reject) => {
@@ -771,7 +771,7 @@ export class Transport<
771771
});
772772

773773
// This will fill sctpStreamParameters's missing fields with default values.
774-
ortc.validateSctpStreamParameters(sctpStreamParameters);
774+
ortc.validateAndNormalizeSctpStreamParameters(sctpStreamParameters);
775775

776776
const { id } = await new Promise<{ id: string }>((resolve, reject) => {
777777
this.safeEmit(
@@ -842,7 +842,7 @@ export class Transport<
842842
const clonedSctpStreamParameters = utils.clone(sctpStreamParameters);
843843

844844
// This may throw.
845-
ortc.validateSctpStreamParameters(clonedSctpStreamParameters);
845+
ortc.validateAndNormalizeSctpStreamParameters(clonedSctpStreamParameters);
846846

847847
// Enqueue command.
848848
return this._awaitQueue.push(async () => {

src/handlers/Chrome111.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,9 @@ export class Chrome111
132132
sdpObject: localSdpObject,
133133
});
134134

135+
// Need to validate and normalize native RTP capabilities.
136+
ortc.validateAndNormalizeRtpCapabilities(nativeRtpCapabilities);
137+
135138
// libwebrtc supports NACK for OPUS but doesn't announce it.
136139
ortcUtils.addNackSupportForOpus(nativeRtpCapabilities);
137140

src/handlers/Chrome74.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,9 @@ export class Chrome74
129129
sdpObject: localSdpObject,
130130
});
131131

132+
// Need to validate and normalize native RTP capabilities.
133+
ortc.validateAndNormalizeRtpCapabilities(nativeRtpCapabilities);
134+
132135
// libwebrtc supports NACK for OPUS but doesn't announce it.
133136
ortcUtils.addNackSupportForOpus(nativeRtpCapabilities);
134137

src/handlers/FakeHandler.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@ export class FakeHandler
101101
const nativeRtpCapabilities =
102102
fakeParameters.generateNativeRtpCapabilities();
103103

104+
// Need to validate and normalize native RTP capabilities.
105+
ortc.validateAndNormalizeRtpCapabilities(nativeRtpCapabilities);
106+
104107
return nativeRtpCapabilities;
105108
}
106109

src/handlers/Firefox120.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,9 @@ export class Firefox120
158158
sdpObject: localSdpObject,
159159
});
160160

161+
// Need to validate and normalize native RTP capabilities.
162+
ortc.validateAndNormalizeRtpCapabilities(nativeRtpCapabilities);
163+
161164
return nativeRtpCapabilities;
162165
}
163166

src/handlers/ReactNative106.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ export class ReactNative106
130130
sdpObject: localSdpObject,
131131
});
132132

133+
// Need to validate and normalize native RTP capabilities.
134+
ortc.validateAndNormalizeRtpCapabilities(nativeRtpCapabilities);
135+
133136
// libwebrtc supports NACK for OPUS but doesn't announce it.
134137
ortcUtils.addNackSupportForOpus(nativeRtpCapabilities);
135138

src/handlers/Safari12.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,9 @@ export class Safari12
128128
sdpObject: localSdpObject,
129129
});
130130

131+
// Need to validate and normalize native RTP capabilities.
132+
ortc.validateAndNormalizeRtpCapabilities(nativeRtpCapabilities);
133+
131134
// libwebrtc supports NACK for OPUS but doesn't announce it.
132135
ortcUtils.addNackSupportForOpus(nativeRtpCapabilities);
133136

src/ortc.ts

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ const RTP_PROBATOR_CODEC_PAYLOAD_TYPE = 127;
3030
* fields with default values.
3131
* It throws if invalid.
3232
*/
33-
export function validateRtpCapabilities(caps: RtpCapabilities): void {
33+
export function validateAndNormalizeRtpCapabilities(
34+
caps: RtpCapabilities
35+
): void {
3436
if (typeof caps !== 'object') {
3537
throw new TypeError('caps is not an object');
3638
}
@@ -43,7 +45,7 @@ export function validateRtpCapabilities(caps: RtpCapabilities): void {
4345
}
4446

4547
for (const codec of caps.codecs) {
46-
validateRtpCodecCapability(codec);
48+
validateAndNormalizeRtpCodecCapability(codec);
4749
}
4850

4951
// headerExtensions is optional. If unset, fill with an empty array.
@@ -54,7 +56,7 @@ export function validateRtpCapabilities(caps: RtpCapabilities): void {
5456
}
5557

5658
for (const ext of caps.headerExtensions) {
57-
validateRtpHeaderExtension(ext);
59+
validateAndNormalizeRtpHeaderExtension(ext);
5860
}
5961
}
6062

@@ -63,7 +65,7 @@ export function validateRtpCapabilities(caps: RtpCapabilities): void {
6365
* fields with default values.
6466
* It throws if invalid.
6567
*/
66-
export function validateRtpParameters(params: RtpParameters): void {
68+
export function validateAndNormalizeRtpParameters(params: RtpParameters): void {
6769
if (typeof params !== 'object') {
6870
throw new TypeError('params is not an object');
6971
}
@@ -79,7 +81,7 @@ export function validateRtpParameters(params: RtpParameters): void {
7981
}
8082

8183
for (const codec of params.codecs) {
82-
validateRtpCodecParameters(codec);
84+
validateAndNormalizeRtpCodecParameters(codec);
8385
}
8486

8587
// headerExtensions is optional. If unset, fill with an empty array.
@@ -101,7 +103,7 @@ export function validateRtpParameters(params: RtpParameters): void {
101103
}
102104

103105
for (const encoding of params.encodings) {
104-
validateRtpEncodingParameters(encoding);
106+
validateAndNormalizeRtpEncodingParameters(encoding);
105107
}
106108

107109
// rtcp is optional. If unset, fill with an empty object.
@@ -111,15 +113,15 @@ export function validateRtpParameters(params: RtpParameters): void {
111113
params.rtcp = {};
112114
}
113115

114-
validateRtcpParameters(params.rtcp);
116+
validateAndNormalizeRtcpParameters(params.rtcp);
115117
}
116118

117119
/**
118120
* Validates SctpStreamParameters. It may modify given data by adding missing
119121
* fields with default values.
120122
* It throws if invalid.
121123
*/
122-
export function validateSctpStreamParameters(
124+
export function validateAndNormalizeSctpStreamParameters(
123125
params: SctpStreamParameters
124126
): void {
125127
if (typeof params !== 'object') {
@@ -658,7 +660,7 @@ export function generateProbatorRtpParameters(
658660
videoRtpParameters = utils.clone<RtpParameters>(videoRtpParameters);
659661

660662
// This may throw.
661-
validateRtpParameters(videoRtpParameters);
663+
validateAndNormalizeRtpParameters(videoRtpParameters);
662664

663665
const rtpParameters: RtpParameters = {
664666
mid: RTP_PROBATOR_MID,
@@ -694,7 +696,7 @@ export function canReceive(
694696
rtpCapabilities: RtpCapabilities
695697
): boolean {
696698
// This may throw.
697-
validateRtpParameters(rtpParameters);
699+
validateAndNormalizeRtpParameters(rtpParameters);
698700

699701
if (rtpParameters.codecs.length === 0) {
700702
return false;
@@ -712,7 +714,9 @@ export function canReceive(
712714
* fields with default values.
713715
* It throws if invalid.
714716
*/
715-
function validateRtpCodecCapability(codec: RtpCodecCapability): void {
717+
function validateAndNormalizeRtpCodecCapability(
718+
codec: RtpCodecCapability
719+
): void {
716720
const MimeTypeRegex = new RegExp('^(audio|video)/(.+)', 'i');
717721

718722
if (typeof codec !== 'object') {
@@ -785,7 +789,7 @@ function validateRtpCodecCapability(codec: RtpCodecCapability): void {
785789
}
786790

787791
for (const fb of codec.rtcpFeedback) {
788-
validateRtcpFeedback(fb);
792+
validateAndNormalizeRtcpFeedback(fb);
789793
}
790794
}
791795

@@ -794,7 +798,7 @@ function validateRtpCodecCapability(codec: RtpCodecCapability): void {
794798
* fields with default values.
795799
* It throws if invalid.
796800
*/
797-
function validateRtcpFeedback(fb: RtcpFeedback): void {
801+
function validateAndNormalizeRtcpFeedback(fb: RtcpFeedback): void {
798802
if (typeof fb !== 'object') {
799803
throw new TypeError('fb is not an object');
800804
}
@@ -815,7 +819,7 @@ function validateRtcpFeedback(fb: RtcpFeedback): void {
815819
* fields with default values.
816820
* It throws if invalid.
817821
*/
818-
function validateRtpHeaderExtension(ext: RtpHeaderExtension): void {
822+
function validateAndNormalizeRtpHeaderExtension(ext: RtpHeaderExtension): void {
819823
if (typeof ext !== 'object') {
820824
throw new TypeError('ext is not an object');
821825
}
@@ -855,7 +859,9 @@ function validateRtpHeaderExtension(ext: RtpHeaderExtension): void {
855859
* fields with default values.
856860
* It throws if invalid.
857861
*/
858-
function validateRtpCodecParameters(codec: RtpCodecParameters): void {
862+
function validateAndNormalizeRtpCodecParameters(
863+
codec: RtpCodecParameters
864+
): void {
859865
const MimeTypeRegex = new RegExp('^(audio|video)/(.+)', 'i');
860866

861867
if (typeof codec !== 'object') {
@@ -927,7 +933,7 @@ function validateRtpCodecParameters(codec: RtpCodecParameters): void {
927933
}
928934

929935
for (const fb of codec.rtcpFeedback) {
930-
validateRtcpFeedback(fb);
936+
validateAndNormalizeRtcpFeedback(fb);
931937
}
932938
}
933939

@@ -984,7 +990,9 @@ function validateRtpHeaderExtensionParameters(
984990
* fields with default values.
985991
* It throws if invalid.
986992
*/
987-
function validateRtpEncodingParameters(encoding: RtpEncodingParameters): void {
993+
function validateAndNormalizeRtpEncodingParameters(
994+
encoding: RtpEncodingParameters
995+
): void {
988996
if (typeof encoding !== 'object') {
989997
throw new TypeError('encoding is not an object');
990998
}
@@ -1028,7 +1036,7 @@ function validateRtpEncodingParameters(encoding: RtpEncodingParameters): void {
10281036
* fields with default values.
10291037
* It throws if invalid.
10301038
*/
1031-
function validateRtcpParameters(rtcp: RtcpParameters): void {
1039+
function validateAndNormalizeRtcpParameters(rtcp: RtcpParameters): void {
10321040
if (typeof rtcp !== 'object') {
10331041
throw new TypeError('rtcp is not an object');
10341042
}

src/test/fakeParameters.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,11 @@ export function generateRouterRtpCapabilities(): mediasoupClient.types.RtpCapabi
184184
});
185185
}
186186

187+
// NOTE: We don't freeze these RTP capabilities because we do need to normalize
188+
// them as we do in real browser handlers (this is an object supposed to be
189+
// generated internally so it's ok).
187190
export function generateNativeRtpCapabilities(): mediasoupClient.types.RtpCapabilities {
188-
return utils.deepFreeze<mediasoupClient.types.RtpCapabilities>({
191+
return {
189192
codecs: [
190193
{
191194
mimeType: 'audio/opus',
@@ -361,7 +364,7 @@ export function generateNativeRtpCapabilities(): mediasoupClient.types.RtpCapabi
361364
preferredId: 10,
362365
},
363366
],
364-
});
367+
};
365368
}
366369

367370
export function generateNativeSctpCapabilities(): mediasoupClient.types.SctpCapabilities {

0 commit comments

Comments
 (0)