mediasoup-client 3.6.90 → 3.6.91

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/lib/Consumer.d.ts +115 -0
  2. package/lib/Consumer.d.ts.map +1 -0
  3. package/lib/Consumer.js +190 -0
  4. package/lib/DataConsumer.d.ts +93 -0
  5. package/lib/DataConsumer.d.ts.map +1 -0
  6. package/lib/DataConsumer.js +162 -0
  7. package/lib/DataProducer.d.ts +97 -0
  8. package/lib/DataProducer.d.ts.map +1 -0
  9. package/lib/DataProducer.js +180 -0
  10. package/lib/Device.d.ts +92 -0
  11. package/lib/Device.d.ts.map +1 -0
  12. package/lib/Device.js +463 -0
  13. package/lib/EnhancedEventEmitter.d.ts +24 -0
  14. package/lib/EnhancedEventEmitter.d.ts.map +1 -0
  15. package/lib/EnhancedEventEmitter.js +70 -0
  16. package/lib/Logger.d.ts +11 -0
  17. package/lib/Logger.d.ts.map +1 -0
  18. package/lib/Logger.js +37 -0
  19. package/lib/Producer.d.ts +169 -0
  20. package/lib/Producer.d.ts.map +1 -0
  21. package/lib/Producer.js +287 -0
  22. package/lib/RtpParameters.d.ts +306 -0
  23. package/lib/RtpParameters.d.ts.map +1 -0
  24. package/lib/RtpParameters.js +6 -0
  25. package/lib/SctpParameters.d.ts +68 -0
  26. package/lib/SctpParameters.d.ts.map +1 -0
  27. package/lib/SctpParameters.js +2 -0
  28. package/lib/Transport.d.ts +243 -0
  29. package/lib/Transport.d.ts.map +1 -0
  30. package/lib/Transport.js +824 -0
  31. package/lib/errors.d.ts +13 -0
  32. package/lib/errors.d.ts.map +1 -0
  33. package/lib/errors.js +39 -0
  34. package/lib/handlers/Chrome111.d.ts +49 -0
  35. package/lib/handlers/Chrome111.d.ts.map +1 -0
  36. package/lib/handlers/Chrome111.js +654 -0
  37. package/lib/handlers/Chrome55.d.ts +51 -0
  38. package/lib/handlers/Chrome55.d.ts.map +1 -0
  39. package/lib/handlers/Chrome55.js +538 -0
  40. package/lib/handlers/Chrome67.d.ts +51 -0
  41. package/lib/handlers/Chrome67.d.ts.map +1 -0
  42. package/lib/handlers/Chrome67.js +594 -0
  43. package/lib/handlers/Chrome70.d.ts +49 -0
  44. package/lib/handlers/Chrome70.d.ts.map +1 -0
  45. package/lib/handlers/Chrome70.js +623 -0
  46. package/lib/handlers/Chrome74.d.ts +49 -0
  47. package/lib/handlers/Chrome74.d.ts.map +1 -0
  48. package/lib/handlers/Chrome74.js +671 -0
  49. package/lib/handlers/Edge11.d.ts +55 -0
  50. package/lib/handlers/Edge11.d.ts.map +1 -0
  51. package/lib/handlers/Edge11.js +447 -0
  52. package/lib/handlers/FakeHandler.d.ts +49 -0
  53. package/lib/handlers/FakeHandler.d.ts.map +1 -0
  54. package/lib/handlers/FakeHandler.js +276 -0
  55. package/lib/handlers/Firefox60.d.ts +48 -0
  56. package/lib/handlers/Firefox60.d.ts.map +1 -0
  57. package/lib/handlers/Firefox60.js +681 -0
  58. package/lib/handlers/HandlerInterface.d.ts +97 -0
  59. package/lib/handlers/HandlerInterface.d.ts.map +1 -0
  60. package/lib/handlers/HandlerInterface.js +10 -0
  61. package/lib/handlers/ReactNative.d.ts +51 -0
  62. package/lib/handlers/ReactNative.d.ts.map +1 -0
  63. package/lib/handlers/ReactNative.js +554 -0
  64. package/lib/handlers/ReactNativeUnifiedPlan.d.ts +49 -0
  65. package/lib/handlers/ReactNativeUnifiedPlan.d.ts.map +1 -0
  66. package/lib/handlers/ReactNativeUnifiedPlan.js +690 -0
  67. package/lib/handlers/Safari11.d.ts +51 -0
  68. package/lib/handlers/Safari11.d.ts.map +1 -0
  69. package/lib/handlers/Safari11.js +588 -0
  70. package/lib/handlers/Safari12.d.ts +49 -0
  71. package/lib/handlers/Safari12.d.ts.map +1 -0
  72. package/lib/handlers/Safari12.js +644 -0
  73. package/lib/handlers/ortc/edgeUtils.d.ts +11 -0
  74. package/lib/handlers/ortc/edgeUtils.d.ts.map +1 -0
  75. package/lib/handlers/ortc/edgeUtils.js +86 -0
  76. package/lib/handlers/ortc/utils.d.ts +6 -0
  77. package/lib/handlers/ortc/utils.d.ts.map +1 -0
  78. package/lib/handlers/ortc/utils.js +19 -0
  79. package/lib/handlers/sdp/MediaSection.d.ts +68 -0
  80. package/lib/handlers/sdp/MediaSection.d.ts.map +1 -0
  81. package/lib/handlers/sdp/MediaSection.js +588 -0
  82. package/lib/handlers/sdp/RemoteSdp.d.ts +75 -0
  83. package/lib/handlers/sdp/RemoteSdp.d.ts.map +1 -0
  84. package/lib/handlers/sdp/RemoteSdp.js +303 -0
  85. package/lib/handlers/sdp/commonUtils.d.ts +24 -0
  86. package/lib/handlers/sdp/commonUtils.d.ts.map +1 -0
  87. package/lib/handlers/sdp/commonUtils.js +224 -0
  88. package/lib/handlers/sdp/plainRtpUtils.d.ts +14 -0
  89. package/lib/handlers/sdp/plainRtpUtils.d.ts.map +1 -0
  90. package/lib/handlers/sdp/plainRtpUtils.js +33 -0
  91. package/lib/handlers/sdp/planBUtils.d.ts +14 -0
  92. package/lib/handlers/sdp/planBUtils.d.ts.map +1 -0
  93. package/lib/handlers/sdp/planBUtils.js +155 -0
  94. package/lib/handlers/sdp/unifiedPlanUtils.d.ts +12 -0
  95. package/lib/handlers/sdp/unifiedPlanUtils.d.ts.map +1 -0
  96. package/lib/handlers/sdp/unifiedPlanUtils.js +131 -0
  97. package/lib/index.d.ts +14 -1435
  98. package/lib/index.d.ts.map +1 -0
  99. package/lib/index.js +43 -11884
  100. package/lib/ortc.d.ts +123 -0
  101. package/lib/ortc.d.ts.map +1 -0
  102. package/lib/ortc.js +943 -0
  103. package/lib/scalabilityModes.d.ts +6 -0
  104. package/lib/scalabilityModes.d.ts.map +1 -0
  105. package/lib/scalabilityModes.js +20 -0
  106. package/lib/tests/fakeParameters.d.ts +20 -0
  107. package/lib/tests/fakeParameters.d.ts.map +1 -0
  108. package/lib/tests/fakeParameters.js +659 -0
  109. package/lib/tests/test.d.ts +6 -0
  110. package/lib/tests/test.d.ts.map +1 -0
  111. package/lib/tests/test.js +1287 -0
  112. package/lib/tests/uaTestCases.d.ts +9 -0
  113. package/lib/tests/uaTestCases.d.ts.map +1 -0
  114. package/lib/tests/uaTestCases.js +85 -0
  115. package/lib/types.d.ts +15 -0
  116. package/lib/types.d.ts.map +1 -0
  117. package/lib/types.js +26 -0
  118. package/lib/utils.d.ts +9 -0
  119. package/lib/utils.d.ts.map +1 -0
  120. package/lib/utils.js +20 -0
  121. package/npm-scripts.mjs +2 -3
  122. package/package.json +1 -6
  123. package/lib/index.js.map +0 -1
  124. package/lib/index.mjs +0 -11860
  125. package/lib/index.mjs.map +0 -1
@@ -0,0 +1,654 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.Chrome111 = void 0;
27
+ const sdpTransform = __importStar(require("sdp-transform"));
28
+ const Logger_1 = require("../Logger");
29
+ const utils = __importStar(require("../utils"));
30
+ const ortc = __importStar(require("../ortc"));
31
+ const sdpCommonUtils = __importStar(require("./sdp/commonUtils"));
32
+ const sdpUnifiedPlanUtils = __importStar(require("./sdp/unifiedPlanUtils"));
33
+ const ortcUtils = __importStar(require("./ortc/utils"));
34
+ const HandlerInterface_1 = require("./HandlerInterface");
35
+ const RemoteSdp_1 = require("./sdp/RemoteSdp");
36
+ const scalabilityModes_1 = require("../scalabilityModes");
37
+ const logger = new Logger_1.Logger('Chrome111');
38
+ const SCTP_NUM_STREAMS = { OS: 1024, MIS: 1024 };
39
+ class Chrome111 extends HandlerInterface_1.HandlerInterface {
40
+ /**
41
+ * Creates a factory function.
42
+ */
43
+ static createFactory() {
44
+ return () => new Chrome111();
45
+ }
46
+ constructor() {
47
+ super();
48
+ // Map of RTCTransceivers indexed by MID.
49
+ this._mapMidTransceiver = new Map();
50
+ // Local stream for sending.
51
+ this._sendStream = new MediaStream();
52
+ // Whether a DataChannel m=application section has been created.
53
+ this._hasDataChannelMediaSection = false;
54
+ // Sending DataChannel id value counter. Incremented for each new DataChannel.
55
+ this._nextSendSctpStreamId = 0;
56
+ // Got transport local and remote parameters.
57
+ this._transportReady = false;
58
+ }
59
+ get name() {
60
+ return 'Chrome111';
61
+ }
62
+ close() {
63
+ logger.debug('close()');
64
+ // Close RTCPeerConnection.
65
+ if (this._pc) {
66
+ try {
67
+ this._pc.close();
68
+ }
69
+ catch (error) { }
70
+ }
71
+ this.emit('@close');
72
+ }
73
+ async getNativeRtpCapabilities() {
74
+ logger.debug('getNativeRtpCapabilities()');
75
+ const pc = new RTCPeerConnection({
76
+ iceServers: [],
77
+ iceTransportPolicy: 'all',
78
+ bundlePolicy: 'max-bundle',
79
+ rtcpMuxPolicy: 'require',
80
+ sdpSemantics: 'unified-plan'
81
+ });
82
+ try {
83
+ pc.addTransceiver('audio');
84
+ pc.addTransceiver('video');
85
+ const offer = await pc.createOffer();
86
+ try {
87
+ pc.close();
88
+ }
89
+ catch (error) { }
90
+ const sdpObject = sdpTransform.parse(offer.sdp);
91
+ const nativeRtpCapabilities = sdpCommonUtils.extractRtpCapabilities({ sdpObject });
92
+ // libwebrtc supports NACK for OPUS but doesn't announce it.
93
+ ortcUtils.addNackSuppportForOpus(nativeRtpCapabilities);
94
+ return nativeRtpCapabilities;
95
+ }
96
+ catch (error) {
97
+ try {
98
+ pc.close();
99
+ }
100
+ catch (error2) { }
101
+ throw error;
102
+ }
103
+ }
104
+ async getNativeSctpCapabilities() {
105
+ logger.debug('getNativeSctpCapabilities()');
106
+ return {
107
+ numStreams: SCTP_NUM_STREAMS
108
+ };
109
+ }
110
+ run({ direction, iceParameters, iceCandidates, dtlsParameters, sctpParameters, iceServers, iceTransportPolicy, additionalSettings, proprietaryConstraints, extendedRtpCapabilities }) {
111
+ logger.debug('run()');
112
+ this._direction = direction;
113
+ this._remoteSdp = new RemoteSdp_1.RemoteSdp({
114
+ iceParameters,
115
+ iceCandidates,
116
+ dtlsParameters,
117
+ sctpParameters
118
+ });
119
+ this._sendingRtpParametersByKind =
120
+ {
121
+ audio: ortc.getSendingRtpParameters('audio', extendedRtpCapabilities),
122
+ video: ortc.getSendingRtpParameters('video', extendedRtpCapabilities)
123
+ };
124
+ this._sendingRemoteRtpParametersByKind =
125
+ {
126
+ audio: ortc.getSendingRemoteRtpParameters('audio', extendedRtpCapabilities),
127
+ video: ortc.getSendingRemoteRtpParameters('video', extendedRtpCapabilities)
128
+ };
129
+ if (dtlsParameters.role && dtlsParameters.role !== 'auto') {
130
+ this._forcedLocalDtlsRole = dtlsParameters.role === 'server'
131
+ ? 'client'
132
+ : 'server';
133
+ }
134
+ this._pc = new RTCPeerConnection({
135
+ iceServers: iceServers || [],
136
+ iceTransportPolicy: iceTransportPolicy || 'all',
137
+ bundlePolicy: 'max-bundle',
138
+ rtcpMuxPolicy: 'require',
139
+ sdpSemantics: 'unified-plan',
140
+ ...additionalSettings
141
+ }, proprietaryConstraints);
142
+ if (this._pc.connectionState) {
143
+ this._pc.addEventListener('connectionstatechange', () => {
144
+ this.emit('@connectionstatechange', this._pc.connectionState);
145
+ });
146
+ }
147
+ else {
148
+ logger.warn('run() | pc.connectionState not supported, using pc.iceConnectionState');
149
+ this._pc.addEventListener('iceconnectionstatechange', () => {
150
+ switch (this._pc.iceConnectionState) {
151
+ case 'checking':
152
+ this.emit('@connectionstatechange', 'connecting');
153
+ break;
154
+ case 'connected':
155
+ case 'completed':
156
+ this.emit('@connectionstatechange', 'connected');
157
+ break;
158
+ case 'failed':
159
+ this.emit('@connectionstatechange', 'failed');
160
+ break;
161
+ case 'disconnected':
162
+ this.emit('@connectionstatechange', 'disconnected');
163
+ break;
164
+ case 'closed':
165
+ this.emit('@connectionstatechange', 'closed');
166
+ break;
167
+ }
168
+ });
169
+ }
170
+ }
171
+ async updateIceServers(iceServers) {
172
+ logger.debug('updateIceServers()');
173
+ const configuration = this._pc.getConfiguration();
174
+ configuration.iceServers = iceServers;
175
+ this._pc.setConfiguration(configuration);
176
+ }
177
+ async restartIce(iceParameters) {
178
+ logger.debug('restartIce()');
179
+ // Provide the remote SDP handler with new remote ICE parameters.
180
+ this._remoteSdp.updateIceParameters(iceParameters);
181
+ if (!this._transportReady) {
182
+ return;
183
+ }
184
+ if (this._direction === 'send') {
185
+ const offer = await this._pc.createOffer({ iceRestart: true });
186
+ logger.debug('restartIce() | calling pc.setLocalDescription() [offer:%o]', offer);
187
+ await this._pc.setLocalDescription(offer);
188
+ const answer = { type: 'answer', sdp: this._remoteSdp.getSdp() };
189
+ logger.debug('restartIce() | calling pc.setRemoteDescription() [answer:%o]', answer);
190
+ await this._pc.setRemoteDescription(answer);
191
+ }
192
+ else {
193
+ const offer = { type: 'offer', sdp: this._remoteSdp.getSdp() };
194
+ logger.debug('restartIce() | calling pc.setRemoteDescription() [offer:%o]', offer);
195
+ await this._pc.setRemoteDescription(offer);
196
+ const answer = await this._pc.createAnswer();
197
+ logger.debug('restartIce() | calling pc.setLocalDescription() [answer:%o]', answer);
198
+ await this._pc.setLocalDescription(answer);
199
+ }
200
+ }
201
+ async getTransportStats() {
202
+ return this._pc.getStats();
203
+ }
204
+ async send({ track, encodings, codecOptions, codec }) {
205
+ this.assertSendDirection();
206
+ logger.debug('send() [kind:%s, track.id:%s]', track.kind, track.id);
207
+ if (encodings && encodings.length > 1) {
208
+ encodings.forEach((encoding, idx) => {
209
+ encoding.rid = `r${idx}`;
210
+ });
211
+ // Set rid and verify scalabilityMode in each encoding.
212
+ // NOTE: Even if WebRTC allows different scalabilityMode (different number
213
+ // of temporal layers) per simulcast stream, we need that those are the
214
+ // same in all them, so let's pick up the highest value.
215
+ // NOTE: If scalabilityMode is not given, Chrome will use L1T3.
216
+ let nextRid = 1;
217
+ let maxTemporalLayers = 1;
218
+ for (const encoding of encodings) {
219
+ const temporalLayers = encoding.scalabilityMode
220
+ ? (0, scalabilityModes_1.parse)(encoding.scalabilityMode).temporalLayers
221
+ : 3;
222
+ if (temporalLayers > maxTemporalLayers) {
223
+ maxTemporalLayers = temporalLayers;
224
+ }
225
+ }
226
+ for (const encoding of encodings) {
227
+ encoding.rid = `r${nextRid++}`;
228
+ encoding.scalabilityMode = `L1T${maxTemporalLayers}`;
229
+ }
230
+ }
231
+ const sendingRtpParameters = utils.clone(this._sendingRtpParametersByKind[track.kind], {});
232
+ // This may throw.
233
+ sendingRtpParameters.codecs =
234
+ ortc.reduceCodecs(sendingRtpParameters.codecs, codec);
235
+ const sendingRemoteRtpParameters = utils.clone(this._sendingRemoteRtpParametersByKind[track.kind], {});
236
+ // This may throw.
237
+ sendingRemoteRtpParameters.codecs =
238
+ ortc.reduceCodecs(sendingRemoteRtpParameters.codecs, codec);
239
+ const mediaSectionIdx = this._remoteSdp.getNextMediaSectionIdx();
240
+ const transceiver = this._pc.addTransceiver(track, {
241
+ direction: 'sendonly',
242
+ streams: [this._sendStream],
243
+ sendEncodings: encodings
244
+ });
245
+ const offer = await this._pc.createOffer();
246
+ let localSdpObject = sdpTransform.parse(offer.sdp);
247
+ if (!this._transportReady) {
248
+ await this.setupTransport({
249
+ localDtlsRole: this._forcedLocalDtlsRole ?? 'client',
250
+ localSdpObject
251
+ });
252
+ }
253
+ logger.debug('send() | calling pc.setLocalDescription() [offer:%o]', offer);
254
+ await this._pc.setLocalDescription(offer);
255
+ // We can now get the transceiver.mid.
256
+ const localId = transceiver.mid;
257
+ // Set MID.
258
+ sendingRtpParameters.mid = localId;
259
+ localSdpObject = sdpTransform.parse(this._pc.localDescription.sdp);
260
+ const offerMediaObject = localSdpObject.media[mediaSectionIdx.idx];
261
+ // Set RTCP CNAME.
262
+ sendingRtpParameters.rtcp.cname =
263
+ sdpCommonUtils.getCname({ offerMediaObject });
264
+ // Set RTP encodings by parsing the SDP offer if no encodings are given.
265
+ if (!encodings) {
266
+ sendingRtpParameters.encodings =
267
+ sdpUnifiedPlanUtils.getRtpEncodings({ offerMediaObject });
268
+ }
269
+ // Set RTP encodings by parsing the SDP offer and complete them with given
270
+ // one if just a single encoding has been given.
271
+ else if (encodings.length === 1) {
272
+ const newEncodings = sdpUnifiedPlanUtils.getRtpEncodings({ offerMediaObject });
273
+ Object.assign(newEncodings[0], encodings[0]);
274
+ sendingRtpParameters.encodings = newEncodings;
275
+ }
276
+ // Otherwise if more than 1 encoding are given use them verbatim.
277
+ else {
278
+ sendingRtpParameters.encodings = encodings;
279
+ }
280
+ this._remoteSdp.send({
281
+ offerMediaObject,
282
+ reuseMid: mediaSectionIdx.reuseMid,
283
+ offerRtpParameters: sendingRtpParameters,
284
+ answerRtpParameters: sendingRemoteRtpParameters,
285
+ codecOptions,
286
+ extmapAllowMixed: true
287
+ });
288
+ const answer = { type: 'answer', sdp: this._remoteSdp.getSdp() };
289
+ logger.debug('send() | calling pc.setRemoteDescription() [answer:%o]', answer);
290
+ await this._pc.setRemoteDescription(answer);
291
+ // Store in the map.
292
+ this._mapMidTransceiver.set(localId, transceiver);
293
+ return {
294
+ localId,
295
+ rtpParameters: sendingRtpParameters,
296
+ rtpSender: transceiver.sender
297
+ };
298
+ }
299
+ async stopSending(localId) {
300
+ this.assertSendDirection();
301
+ logger.debug('stopSending() [localId:%s]', localId);
302
+ const transceiver = this._mapMidTransceiver.get(localId);
303
+ if (!transceiver) {
304
+ throw new Error('associated RTCRtpTransceiver not found');
305
+ }
306
+ transceiver.sender.replaceTrack(null);
307
+ this._pc.removeTrack(transceiver.sender);
308
+ const mediaSectionClosed = this._remoteSdp.closeMediaSection(transceiver.mid);
309
+ if (mediaSectionClosed) {
310
+ try {
311
+ transceiver.stop();
312
+ }
313
+ catch (error) { }
314
+ }
315
+ const offer = await this._pc.createOffer();
316
+ logger.debug('stopSending() | calling pc.setLocalDescription() [offer:%o]', offer);
317
+ await this._pc.setLocalDescription(offer);
318
+ const answer = { type: 'answer', sdp: this._remoteSdp.getSdp() };
319
+ logger.debug('stopSending() | calling pc.setRemoteDescription() [answer:%o]', answer);
320
+ await this._pc.setRemoteDescription(answer);
321
+ this._mapMidTransceiver.delete(localId);
322
+ }
323
+ async pauseSending(localId) {
324
+ this.assertSendDirection();
325
+ logger.debug('pauseSending() [localId:%s]', localId);
326
+ const transceiver = this._mapMidTransceiver.get(localId);
327
+ if (!transceiver) {
328
+ throw new Error('associated RTCRtpTransceiver not found');
329
+ }
330
+ transceiver.direction = 'inactive';
331
+ this._remoteSdp.pauseMediaSection(localId);
332
+ const offer = await this._pc.createOffer();
333
+ logger.debug('pauseSending() | calling pc.setLocalDescription() [offer:%o]', offer);
334
+ await this._pc.setLocalDescription(offer);
335
+ const answer = { type: 'answer', sdp: this._remoteSdp.getSdp() };
336
+ logger.debug('pauseSending() | calling pc.setRemoteDescription() [answer:%o]', answer);
337
+ await this._pc.setRemoteDescription(answer);
338
+ }
339
+ async resumeSending(localId) {
340
+ this.assertSendDirection();
341
+ logger.debug('resumeSending() [localId:%s]', localId);
342
+ const transceiver = this._mapMidTransceiver.get(localId);
343
+ this._remoteSdp.resumeSendingMediaSection(localId);
344
+ if (!transceiver) {
345
+ throw new Error('associated RTCRtpTransceiver not found');
346
+ }
347
+ transceiver.direction = 'sendonly';
348
+ const offer = await this._pc.createOffer();
349
+ logger.debug('resumeSending() | calling pc.setLocalDescription() [offer:%o]', offer);
350
+ await this._pc.setLocalDescription(offer);
351
+ const answer = { type: 'answer', sdp: this._remoteSdp.getSdp() };
352
+ logger.debug('resumeSending() | calling pc.setRemoteDescription() [answer:%o]', answer);
353
+ await this._pc.setRemoteDescription(answer);
354
+ }
355
+ async replaceTrack(localId, track) {
356
+ this.assertSendDirection();
357
+ if (track) {
358
+ logger.debug('replaceTrack() [localId:%s, track.id:%s]', localId, track.id);
359
+ }
360
+ else {
361
+ logger.debug('replaceTrack() [localId:%s, no track]', localId);
362
+ }
363
+ const transceiver = this._mapMidTransceiver.get(localId);
364
+ if (!transceiver) {
365
+ throw new Error('associated RTCRtpTransceiver not found');
366
+ }
367
+ await transceiver.sender.replaceTrack(track);
368
+ }
369
+ async setMaxSpatialLayer(localId, spatialLayer) {
370
+ this.assertSendDirection();
371
+ logger.debug('setMaxSpatialLayer() [localId:%s, spatialLayer:%s]', localId, spatialLayer);
372
+ const transceiver = this._mapMidTransceiver.get(localId);
373
+ if (!transceiver) {
374
+ throw new Error('associated RTCRtpTransceiver not found');
375
+ }
376
+ const parameters = transceiver.sender.getParameters();
377
+ parameters.encodings.forEach((encoding, idx) => {
378
+ if (idx <= spatialLayer) {
379
+ encoding.active = true;
380
+ }
381
+ else {
382
+ encoding.active = false;
383
+ }
384
+ });
385
+ await transceiver.sender.setParameters(parameters);
386
+ this._remoteSdp.muxMediaSectionSimulcast(localId, parameters.encodings);
387
+ const offer = await this._pc.createOffer();
388
+ logger.debug('setMaxSpatialLayer() | calling pc.setLocalDescription() [offer:%o]', offer);
389
+ await this._pc.setLocalDescription(offer);
390
+ const answer = { type: 'answer', sdp: this._remoteSdp.getSdp() };
391
+ logger.debug('setMaxSpatialLayer() | calling pc.setRemoteDescription() [answer:%o]', answer);
392
+ await this._pc.setRemoteDescription(answer);
393
+ }
394
+ async setRtpEncodingParameters(localId, params) {
395
+ this.assertSendDirection();
396
+ logger.debug('setRtpEncodingParameters() [localId:%s, params:%o]', localId, params);
397
+ const transceiver = this._mapMidTransceiver.get(localId);
398
+ if (!transceiver) {
399
+ throw new Error('associated RTCRtpTransceiver not found');
400
+ }
401
+ const parameters = transceiver.sender.getParameters();
402
+ parameters.encodings.forEach((encoding, idx) => {
403
+ parameters.encodings[idx] = { ...encoding, ...params };
404
+ });
405
+ await transceiver.sender.setParameters(parameters);
406
+ this._remoteSdp.muxMediaSectionSimulcast(localId, parameters.encodings);
407
+ const offer = await this._pc.createOffer();
408
+ logger.debug('setRtpEncodingParameters() | calling pc.setLocalDescription() [offer:%o]', offer);
409
+ await this._pc.setLocalDescription(offer);
410
+ const answer = { type: 'answer', sdp: this._remoteSdp.getSdp() };
411
+ logger.debug('setRtpEncodingParameters() | calling pc.setRemoteDescription() [answer:%o]', answer);
412
+ await this._pc.setRemoteDescription(answer);
413
+ }
414
+ async getSenderStats(localId) {
415
+ this.assertSendDirection();
416
+ const transceiver = this._mapMidTransceiver.get(localId);
417
+ if (!transceiver) {
418
+ throw new Error('associated RTCRtpTransceiver not found');
419
+ }
420
+ return transceiver.sender.getStats();
421
+ }
422
+ async sendDataChannel({ ordered, maxPacketLifeTime, maxRetransmits, label, protocol }) {
423
+ this.assertSendDirection();
424
+ const options = {
425
+ negotiated: true,
426
+ id: this._nextSendSctpStreamId,
427
+ ordered,
428
+ maxPacketLifeTime,
429
+ maxRetransmits,
430
+ protocol
431
+ };
432
+ logger.debug('sendDataChannel() [options:%o]', options);
433
+ const dataChannel = this._pc.createDataChannel(label, options);
434
+ // Increase next id.
435
+ this._nextSendSctpStreamId =
436
+ ++this._nextSendSctpStreamId % SCTP_NUM_STREAMS.MIS;
437
+ // If this is the first DataChannel we need to create the SDP answer with
438
+ // m=application section.
439
+ if (!this._hasDataChannelMediaSection) {
440
+ const offer = await this._pc.createOffer();
441
+ const localSdpObject = sdpTransform.parse(offer.sdp);
442
+ const offerMediaObject = localSdpObject.media
443
+ .find((m) => m.type === 'application');
444
+ if (!this._transportReady) {
445
+ await this.setupTransport({
446
+ localDtlsRole: this._forcedLocalDtlsRole ?? 'client',
447
+ localSdpObject
448
+ });
449
+ }
450
+ logger.debug('sendDataChannel() | calling pc.setLocalDescription() [offer:%o]', offer);
451
+ await this._pc.setLocalDescription(offer);
452
+ this._remoteSdp.sendSctpAssociation({ offerMediaObject });
453
+ const answer = { type: 'answer', sdp: this._remoteSdp.getSdp() };
454
+ logger.debug('sendDataChannel() | calling pc.setRemoteDescription() [answer:%o]', answer);
455
+ await this._pc.setRemoteDescription(answer);
456
+ this._hasDataChannelMediaSection = true;
457
+ }
458
+ const sctpStreamParameters = {
459
+ streamId: options.id,
460
+ ordered: options.ordered,
461
+ maxPacketLifeTime: options.maxPacketLifeTime,
462
+ maxRetransmits: options.maxRetransmits
463
+ };
464
+ return { dataChannel, sctpStreamParameters };
465
+ }
466
+ async receive(optionsList) {
467
+ this.assertRecvDirection();
468
+ const results = [];
469
+ const mapLocalId = new Map();
470
+ for (const options of optionsList) {
471
+ const { trackId, kind, rtpParameters, streamId } = options;
472
+ logger.debug('receive() [trackId:%s, kind:%s]', trackId, kind);
473
+ const localId = rtpParameters.mid || String(this._mapMidTransceiver.size);
474
+ mapLocalId.set(trackId, localId);
475
+ this._remoteSdp.receive({
476
+ mid: localId,
477
+ kind,
478
+ offerRtpParameters: rtpParameters,
479
+ streamId: streamId || rtpParameters.rtcp.cname,
480
+ trackId
481
+ });
482
+ }
483
+ const offer = { type: 'offer', sdp: this._remoteSdp.getSdp() };
484
+ logger.debug('receive() | calling pc.setRemoteDescription() [offer:%o]', offer);
485
+ await this._pc.setRemoteDescription(offer);
486
+ let answer = await this._pc.createAnswer();
487
+ const localSdpObject = sdpTransform.parse(answer.sdp);
488
+ for (const options of optionsList) {
489
+ const { trackId, rtpParameters } = options;
490
+ const localId = mapLocalId.get(trackId);
491
+ const answerMediaObject = localSdpObject.media
492
+ .find((m) => String(m.mid) === localId);
493
+ // May need to modify codec parameters in the answer based on codec
494
+ // parameters in the offer.
495
+ sdpCommonUtils.applyCodecParameters({
496
+ offerRtpParameters: rtpParameters,
497
+ answerMediaObject
498
+ });
499
+ }
500
+ answer = { type: 'answer', sdp: sdpTransform.write(localSdpObject) };
501
+ if (!this._transportReady) {
502
+ await this.setupTransport({
503
+ localDtlsRole: this._forcedLocalDtlsRole ?? 'client',
504
+ localSdpObject
505
+ });
506
+ }
507
+ logger.debug('receive() | calling pc.setLocalDescription() [answer:%o]', answer);
508
+ await this._pc.setLocalDescription(answer);
509
+ for (const options of optionsList) {
510
+ const { trackId } = options;
511
+ const localId = mapLocalId.get(trackId);
512
+ const transceiver = this._pc.getTransceivers()
513
+ .find((t) => t.mid === localId);
514
+ if (!transceiver) {
515
+ throw new Error('new RTCRtpTransceiver not found');
516
+ }
517
+ else {
518
+ // Store in the map.
519
+ this._mapMidTransceiver.set(localId, transceiver);
520
+ results.push({
521
+ localId,
522
+ track: transceiver.receiver.track,
523
+ rtpReceiver: transceiver.receiver
524
+ });
525
+ }
526
+ }
527
+ return results;
528
+ }
529
+ async stopReceiving(localIds) {
530
+ this.assertRecvDirection();
531
+ for (const localId of localIds) {
532
+ logger.debug('stopReceiving() [localId:%s]', localId);
533
+ const transceiver = this._mapMidTransceiver.get(localId);
534
+ if (!transceiver) {
535
+ throw new Error('associated RTCRtpTransceiver not found');
536
+ }
537
+ this._remoteSdp.closeMediaSection(transceiver.mid);
538
+ }
539
+ const offer = { type: 'offer', sdp: this._remoteSdp.getSdp() };
540
+ logger.debug('stopReceiving() | calling pc.setRemoteDescription() [offer:%o]', offer);
541
+ await this._pc.setRemoteDescription(offer);
542
+ const answer = await this._pc.createAnswer();
543
+ logger.debug('stopReceiving() | calling pc.setLocalDescription() [answer:%o]', answer);
544
+ await this._pc.setLocalDescription(answer);
545
+ for (const localId of localIds) {
546
+ this._mapMidTransceiver.delete(localId);
547
+ }
548
+ }
549
+ async pauseReceiving(localIds) {
550
+ this.assertRecvDirection();
551
+ for (const localId of localIds) {
552
+ logger.debug('pauseReceiving() [localId:%s]', localId);
553
+ const transceiver = this._mapMidTransceiver.get(localId);
554
+ if (!transceiver) {
555
+ throw new Error('associated RTCRtpTransceiver not found');
556
+ }
557
+ transceiver.direction = 'inactive';
558
+ this._remoteSdp.pauseMediaSection(localId);
559
+ }
560
+ const offer = { type: 'offer', sdp: this._remoteSdp.getSdp() };
561
+ logger.debug('pauseReceiving() | calling pc.setRemoteDescription() [offer:%o]', offer);
562
+ await this._pc.setRemoteDescription(offer);
563
+ const answer = await this._pc.createAnswer();
564
+ logger.debug('pauseReceiving() | calling pc.setLocalDescription() [answer:%o]', answer);
565
+ await this._pc.setLocalDescription(answer);
566
+ }
567
+ async resumeReceiving(localIds) {
568
+ this.assertRecvDirection();
569
+ for (const localId of localIds) {
570
+ logger.debug('resumeReceiving() [localId:%s]', localId);
571
+ const transceiver = this._mapMidTransceiver.get(localId);
572
+ if (!transceiver) {
573
+ throw new Error('associated RTCRtpTransceiver not found');
574
+ }
575
+ transceiver.direction = 'recvonly';
576
+ this._remoteSdp.resumeReceivingMediaSection(localId);
577
+ }
578
+ const offer = { type: 'offer', sdp: this._remoteSdp.getSdp() };
579
+ logger.debug('resumeReceiving() | calling pc.setRemoteDescription() [offer:%o]', offer);
580
+ await this._pc.setRemoteDescription(offer);
581
+ const answer = await this._pc.createAnswer();
582
+ logger.debug('resumeReceiving() | calling pc.setLocalDescription() [answer:%o]', answer);
583
+ await this._pc.setLocalDescription(answer);
584
+ }
585
+ async getReceiverStats(localId) {
586
+ this.assertRecvDirection();
587
+ const transceiver = this._mapMidTransceiver.get(localId);
588
+ if (!transceiver) {
589
+ throw new Error('associated RTCRtpTransceiver not found');
590
+ }
591
+ return transceiver.receiver.getStats();
592
+ }
593
+ async receiveDataChannel({ sctpStreamParameters, label, protocol }) {
594
+ this.assertRecvDirection();
595
+ const { streamId, ordered, maxPacketLifeTime, maxRetransmits } = sctpStreamParameters;
596
+ const options = {
597
+ negotiated: true,
598
+ id: streamId,
599
+ ordered,
600
+ maxPacketLifeTime,
601
+ maxRetransmits,
602
+ protocol
603
+ };
604
+ logger.debug('receiveDataChannel() [options:%o]', options);
605
+ const dataChannel = this._pc.createDataChannel(label, options);
606
+ // If this is the first DataChannel we need to create the SDP offer with
607
+ // m=application section.
608
+ if (!this._hasDataChannelMediaSection) {
609
+ this._remoteSdp.receiveSctpAssociation();
610
+ const offer = { type: 'offer', sdp: this._remoteSdp.getSdp() };
611
+ logger.debug('receiveDataChannel() | calling pc.setRemoteDescription() [offer:%o]', offer);
612
+ await this._pc.setRemoteDescription(offer);
613
+ const answer = await this._pc.createAnswer();
614
+ if (!this._transportReady) {
615
+ const localSdpObject = sdpTransform.parse(answer.sdp);
616
+ await this.setupTransport({
617
+ localDtlsRole: this._forcedLocalDtlsRole ?? 'client',
618
+ localSdpObject
619
+ });
620
+ }
621
+ logger.debug('receiveDataChannel() | calling pc.setRemoteDescription() [answer:%o]', answer);
622
+ await this._pc.setLocalDescription(answer);
623
+ this._hasDataChannelMediaSection = true;
624
+ }
625
+ return { dataChannel };
626
+ }
627
+ async setupTransport({ localDtlsRole, localSdpObject }) {
628
+ if (!localSdpObject) {
629
+ localSdpObject = sdpTransform.parse(this._pc.localDescription.sdp);
630
+ }
631
+ // Get our local DTLS parameters.
632
+ const dtlsParameters = sdpCommonUtils.extractDtlsParameters({ sdpObject: localSdpObject });
633
+ // Set our DTLS role.
634
+ dtlsParameters.role = localDtlsRole;
635
+ // Update the remote DTLS role in the SDP.
636
+ this._remoteSdp.updateDtlsRole(localDtlsRole === 'client' ? 'server' : 'client');
637
+ // Need to tell the remote transport about our parameters.
638
+ await new Promise((resolve, reject) => {
639
+ this.safeEmit('@connect', { dtlsParameters }, resolve, reject);
640
+ });
641
+ this._transportReady = true;
642
+ }
643
+ assertSendDirection() {
644
+ if (this._direction !== 'send') {
645
+ throw new Error('method can just be called for handlers with "send" direction');
646
+ }
647
+ }
648
+ assertRecvDirection() {
649
+ if (this._direction !== 'recv') {
650
+ throw new Error('method can just be called for handlers with "recv" direction');
651
+ }
652
+ }
653
+ }
654
+ exports.Chrome111 = Chrome111;