mediasoup-client 3.7.4 → 3.7.6

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.
package/lib/Device.d.ts CHANGED
@@ -4,7 +4,7 @@ import { HandlerFactory } from './handlers/HandlerInterface';
4
4
  import { RtpCapabilities, MediaKind } from './RtpParameters';
5
5
  import { SctpCapabilities } from './SctpParameters';
6
6
  import { AppData } from './types';
7
- export type BuiltinHandlerName = 'Chrome111' | 'Chrome74' | 'Chrome70' | 'Chrome67' | 'Chrome55' | 'Firefox60' | 'Safari12' | 'Safari11' | 'Edge11' | 'ReactNativeUnifiedPlan' | 'ReactNative';
7
+ export type BuiltinHandlerName = 'Chrome111' | 'Chrome74' | 'Chrome70' | 'Chrome67' | 'Chrome55' | 'Firefox120' | 'Firefox60' | 'Safari12' | 'Safari11' | 'Edge11' | 'ReactNativeUnifiedPlan' | 'ReactNative';
8
8
  export type DeviceOptions = {
9
9
  /**
10
10
  * The name of one of the builtin handlers.
@@ -1 +1 @@
1
- {"version":3,"file":"Device.d.ts","sourceRoot":"","sources":["../src/Device.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAI9D,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAoB,MAAM,aAAa,CAAC;AAC5E,OAAO,EAAE,cAAc,EAAoB,MAAM,6BAA6B,CAAC;AAY/E,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAIlC,MAAM,MAAM,kBAAkB,GAC3B,WAAW,GACX,UAAU,GACV,UAAU,GACV,UAAU,GACV,UAAU,GACV,WAAW,GACX,UAAU,GACV,UAAU,GACV,QAAQ,GACR,wBAAwB,GACxB,aAAa,CAAC;AAEjB,MAAM,MAAM,aAAa,GAAG;IAC3B;;OAEG;IACH,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC;;OAEG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,wBAAgB,YAAY,IAAI,kBAAkB,GAAG,SAAS,CAgK7D;AAED,MAAM,MAAM,oBAAoB,GAAG;IAClC,YAAY,EAAE,CAAC,SAAS,CAAC,CAAC;CAC1B,CAAC;AAEF,qBAAa,MAAM;IAElB,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAiB;IAEjD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IAEtC,OAAO,CAAC,OAAO,CAAS;IAExB,OAAO,CAAC,wBAAwB,CAAC,CAAM;IAEvC,OAAO,CAAC,oBAAoB,CAAC,CAAkB;IAG/C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAmB;IAErD,OAAO,CAAC,iBAAiB,CAAC,CAAmB;IAE7C,SAAS,CAAC,QAAQ,CAAC,SAAS,6CACsB;IAElD;;;;OAIG;gBACS,EAAE,WAAW,EAAE,cAAc,EAAE,OAAO,EAAE,GAAE,aAAkB;IAqHxE;;OAEG;IACH,IAAI,WAAW,IAAI,MAAM,CAExB;IAED;;OAEG;IACH,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED;;;;OAIG;IACH,IAAI,eAAe,IAAI,eAAe,CAMrC;IAED;;;;OAIG;IACH,IAAI,gBAAgB,IAAI,gBAAgB,CAMvC;IAED,IAAI,QAAQ,IAAI,oBAAoB,CAEnC;IAED;;OAEG;IACG,IAAI,CAAC,EACV,qBAAqB,GACrB,EAAE;QACF,qBAAqB,EAAE,eAAe,CAAC;KACvC,GAAG,OAAO,CAAC,IAAI,CAAC;IAuFjB;;;;;OAKG;IACH,UAAU,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO;IAUpC;;;;;OAKG;IACH,mBAAmB,CAAC,gBAAgB,SAAS,OAAO,GAAG,OAAO,EAAE,EAC/D,EAAE,EACF,aAAa,EACb,aAAa,EACb,cAAc,EACd,cAAc,EACd,UAAU,EACV,kBAAkB,EAClB,kBAAkB,EAClB,sBAAsB,EACtB,OAAO,GACP,EAAE,gBAAgB,CAAC,gBAAgB,CAAC,GAAG,SAAS,CAAC,gBAAgB,CAAC;IAkBnE;;;;;OAKG;IACH,mBAAmB,CAAC,gBAAgB,SAAS,OAAO,GAAG,OAAO,EAAE,EAC/D,EAAE,EACF,aAAa,EACb,aAAa,EACb,cAAc,EACd,cAAc,EACd,UAAU,EACV,kBAAkB,EAClB,kBAAkB,EAClB,sBAAsB,EACtB,OAAO,GACP,EAAE,gBAAgB,CAAC,gBAAgB,CAAC,GAAG,SAAS,CAAC,gBAAgB,CAAC;IAkBnE,OAAO,CAAC,eAAe;CAsDvB"}
1
+ {"version":3,"file":"Device.d.ts","sourceRoot":"","sources":["../src/Device.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAI9D,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAoB,MAAM,aAAa,CAAC;AAC5E,OAAO,EAAE,cAAc,EAAoB,MAAM,6BAA6B,CAAC;AAa/E,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAIlC,MAAM,MAAM,kBAAkB,GAC3B,WAAW,GACX,UAAU,GACV,UAAU,GACV,UAAU,GACV,UAAU,GACV,YAAY,GACZ,WAAW,GACX,UAAU,GACV,UAAU,GACV,QAAQ,GACR,wBAAwB,GACxB,aAAa,CAAC;AAEjB,MAAM,MAAM,aAAa,GAAG;IAC3B;;OAEG;IACH,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC;;OAEG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,wBAAgB,YAAY,IAAI,kBAAkB,GAAG,SAAS,CAkK7D;AAED,MAAM,MAAM,oBAAoB,GAAG;IAClC,YAAY,EAAE,CAAC,SAAS,CAAC,CAAC;CAC1B,CAAC;AAEF,qBAAa,MAAM;IAElB,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAiB;IAEjD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IAEtC,OAAO,CAAC,OAAO,CAAS;IAExB,OAAO,CAAC,wBAAwB,CAAC,CAAM;IAEvC,OAAO,CAAC,oBAAoB,CAAC,CAAkB;IAG/C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAmB;IAErD,OAAO,CAAC,iBAAiB,CAAC,CAAmB;IAE7C,SAAS,CAAC,QAAQ,CAAC,SAAS,6CACsB;IAElD;;;;OAIG;gBACS,EAAE,WAAW,EAAE,cAAc,EAAE,OAAO,EAAE,GAAE,aAAkB;IA0HxE;;OAEG;IACH,IAAI,WAAW,IAAI,MAAM,CAExB;IAED;;OAEG;IACH,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED;;;;OAIG;IACH,IAAI,eAAe,IAAI,eAAe,CAMrC;IAED;;;;OAIG;IACH,IAAI,gBAAgB,IAAI,gBAAgB,CAMvC;IAED,IAAI,QAAQ,IAAI,oBAAoB,CAEnC;IAED;;OAEG;IACG,IAAI,CAAC,EACV,qBAAqB,GACrB,EAAE;QACF,qBAAqB,EAAE,eAAe,CAAC;KACvC,GAAG,OAAO,CAAC,IAAI,CAAC;IAuFjB;;;;;OAKG;IACH,UAAU,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO;IAUpC;;;;;OAKG;IACH,mBAAmB,CAAC,gBAAgB,SAAS,OAAO,GAAG,OAAO,EAAE,EAC/D,EAAE,EACF,aAAa,EACb,aAAa,EACb,cAAc,EACd,cAAc,EACd,UAAU,EACV,kBAAkB,EAClB,kBAAkB,EAClB,sBAAsB,EACtB,OAAO,GACP,EAAE,gBAAgB,CAAC,gBAAgB,CAAC,GAAG,SAAS,CAAC,gBAAgB,CAAC;IAkBnE;;;;;OAKG;IACH,mBAAmB,CAAC,gBAAgB,SAAS,OAAO,GAAG,OAAO,EAAE,EAC/D,EAAE,EACF,aAAa,EACb,aAAa,EACb,cAAc,EACd,cAAc,EACd,UAAU,EACV,kBAAkB,EAClB,kBAAkB,EAClB,sBAAsB,EACtB,OAAO,GACP,EAAE,gBAAgB,CAAC,gBAAgB,CAAC,GAAG,SAAS,CAAC,gBAAgB,CAAC;IAkBnE,OAAO,CAAC,eAAe;CAsDvB"}
package/lib/Device.js CHANGED
@@ -36,6 +36,7 @@ const Chrome74_1 = require("./handlers/Chrome74");
36
36
  const Chrome70_1 = require("./handlers/Chrome70");
37
37
  const Chrome67_1 = require("./handlers/Chrome67");
38
38
  const Chrome55_1 = require("./handlers/Chrome55");
39
+ const Firefox120_1 = require("./handlers/Firefox120");
39
40
  const Firefox60_1 = require("./handlers/Firefox60");
40
41
  const Safari12_1 = require("./handlers/Safari12");
41
42
  const Safari11_1 = require("./handlers/Safari11");
@@ -109,6 +110,9 @@ function detectDevice() {
109
110
  return 'Chrome55';
110
111
  }
111
112
  // Firefox.
113
+ else if (isFirefox && !isIOS && browserVersion >= 120) {
114
+ return 'Firefox120';
115
+ }
112
116
  else if (isFirefox && !isIOS && browserVersion >= 60) {
113
117
  return 'Firefox60';
114
118
  }
@@ -238,6 +242,10 @@ class Device {
238
242
  this._handlerFactory = Chrome55_1.Chrome55.createFactory();
239
243
  break;
240
244
  }
245
+ case 'Firefox120': {
246
+ this._handlerFactory = Firefox120_1.Firefox120.createFactory();
247
+ break;
248
+ }
241
249
  case 'Firefox60': {
242
250
  this._handlerFactory = Firefox60_1.Firefox60.createFactory();
243
251
  break;
@@ -1 +1 @@
1
- {"version":3,"file":"Chrome111.d.ts","sourceRoot":"","sources":["../../src/handlers/Chrome111.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Chrome111.d.ts","sourceRoot":"","sources":["../../src/handlers/Chrome111.ts"],"names":[],"mappings":"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"}
@@ -224,15 +224,11 @@ class Chrome111 extends HandlerInterface_1.HandlerInterface {
224
224
  this.assertSendDirection();
225
225
  logger.debug('send() [kind:%s, track.id:%s]', track.kind, track.id);
226
226
  if (encodings && encodings.length > 1) {
227
- encodings.forEach((encoding, idx) => {
228
- encoding.rid = `r${idx}`;
229
- });
230
227
  // Set rid and verify scalabilityMode in each encoding.
231
228
  // NOTE: Even if WebRTC allows different scalabilityMode (different number
232
229
  // of temporal layers) per simulcast stream, we need that those are the
233
230
  // same in all them, so let's pick up the highest value.
234
231
  // NOTE: If scalabilityMode is not given, Chrome will use L1T3.
235
- let nextRid = 1;
236
232
  let maxTemporalLayers = 1;
237
233
  for (const encoding of encodings) {
238
234
  const temporalLayers = encoding.scalabilityMode
@@ -242,10 +238,10 @@ class Chrome111 extends HandlerInterface_1.HandlerInterface {
242
238
  maxTemporalLayers = temporalLayers;
243
239
  }
244
240
  }
245
- for (const encoding of encodings) {
246
- encoding.rid = `r${nextRid++}`;
241
+ encodings.forEach((encoding, idx) => {
242
+ encoding.rid = `r${idx}`;
247
243
  encoding.scalabilityMode = `L1T${maxTemporalLayers}`;
248
- }
244
+ });
249
245
  }
250
246
  const sendingRtpParameters = utils.clone(this._sendingRtpParametersByKind[track.kind]);
251
247
  // This may throw.
@@ -0,0 +1,50 @@
1
+ import { HandlerFactory, HandlerInterface, HandlerRunOptions, HandlerSendOptions, HandlerSendResult, HandlerReceiveOptions, HandlerReceiveResult, HandlerSendDataChannelOptions, HandlerSendDataChannelResult, HandlerReceiveDataChannelOptions, HandlerReceiveDataChannelResult } from './HandlerInterface';
2
+ import { IceParameters } from '../Transport';
3
+ import { RtpCapabilities } from '../RtpParameters';
4
+ import { SctpCapabilities } from '../SctpParameters';
5
+ export declare class Firefox120 extends HandlerInterface {
6
+ private _closed;
7
+ private _direction?;
8
+ private _remoteSdp?;
9
+ private _sendingRtpParametersByKind?;
10
+ private _sendingRemoteRtpParametersByKind?;
11
+ private _pc;
12
+ private readonly _mapMidTransceiver;
13
+ private readonly _sendStream;
14
+ private _hasDataChannelMediaSection;
15
+ private _nextSendSctpStreamId;
16
+ private _transportReady;
17
+ /**
18
+ * Creates a factory function.
19
+ */
20
+ static createFactory(): HandlerFactory;
21
+ constructor();
22
+ get name(): string;
23
+ close(): void;
24
+ getNativeRtpCapabilities(): Promise<RtpCapabilities>;
25
+ getNativeSctpCapabilities(): Promise<SctpCapabilities>;
26
+ run({ direction, iceParameters, iceCandidates, dtlsParameters, sctpParameters, iceServers, iceTransportPolicy, additionalSettings, proprietaryConstraints, extendedRtpCapabilities, }: HandlerRunOptions): void;
27
+ updateIceServers(iceServers: RTCIceServer[]): Promise<void>;
28
+ restartIce(iceParameters: IceParameters): Promise<void>;
29
+ getTransportStats(): Promise<RTCStatsReport>;
30
+ send({ track, encodings, codecOptions, codec, }: HandlerSendOptions): Promise<HandlerSendResult>;
31
+ stopSending(localId: string): Promise<void>;
32
+ pauseSending(localId: string): Promise<void>;
33
+ resumeSending(localId: string): Promise<void>;
34
+ replaceTrack(localId: string, track: MediaStreamTrack | null): Promise<void>;
35
+ setMaxSpatialLayer(localId: string, spatialLayer: number): Promise<void>;
36
+ setRtpEncodingParameters(localId: string, params: any): Promise<void>;
37
+ getSenderStats(localId: string): Promise<RTCStatsReport>;
38
+ sendDataChannel({ ordered, maxPacketLifeTime, maxRetransmits, label, protocol, }: HandlerSendDataChannelOptions): Promise<HandlerSendDataChannelResult>;
39
+ receive(optionsList: HandlerReceiveOptions[]): Promise<HandlerReceiveResult[]>;
40
+ stopReceiving(localIds: string[]): Promise<void>;
41
+ pauseReceiving(localIds: string[]): Promise<void>;
42
+ resumeReceiving(localIds: string[]): Promise<void>;
43
+ getReceiverStats(localId: string): Promise<RTCStatsReport>;
44
+ receiveDataChannel({ sctpStreamParameters, label, protocol, }: HandlerReceiveDataChannelOptions): Promise<HandlerReceiveDataChannelResult>;
45
+ private setupTransport;
46
+ private assertNotClosed;
47
+ private assertSendDirection;
48
+ private assertRecvDirection;
49
+ }
50
+ //# sourceMappingURL=Firefox120.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Firefox120.d.ts","sourceRoot":"","sources":["../../src/handlers/Firefox120.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,713 @@
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.Firefox120 = void 0;
27
+ const sdpTransform = __importStar(require("sdp-transform"));
28
+ const Logger_1 = require("../Logger");
29
+ const errors_1 = require("../errors");
30
+ const utils = __importStar(require("../utils"));
31
+ const ortc = __importStar(require("../ortc"));
32
+ const sdpCommonUtils = __importStar(require("./sdp/commonUtils"));
33
+ const sdpUnifiedPlanUtils = __importStar(require("./sdp/unifiedPlanUtils"));
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('Firefox120');
38
+ const SCTP_NUM_STREAMS = { OS: 16, MIS: 2048 };
39
+ class Firefox120 extends HandlerInterface_1.HandlerInterface {
40
+ /**
41
+ * Creates a factory function.
42
+ */
43
+ static createFactory() {
44
+ return () => new Firefox120();
45
+ }
46
+ constructor() {
47
+ super();
48
+ // Closed flag.
49
+ this._closed = false;
50
+ // Map of RTCTransceivers indexed by MID.
51
+ this._mapMidTransceiver = new Map();
52
+ // Local stream for sending.
53
+ this._sendStream = new MediaStream();
54
+ // Whether a DataChannel m=application section has been created.
55
+ this._hasDataChannelMediaSection = false;
56
+ // Sending DataChannel id value counter. Incremented for each new DataChannel.
57
+ this._nextSendSctpStreamId = 0;
58
+ // Got transport local and remote parameters.
59
+ this._transportReady = false;
60
+ }
61
+ get name() {
62
+ return 'Firefox120';
63
+ }
64
+ close() {
65
+ logger.debug('close()');
66
+ if (this._closed) {
67
+ return;
68
+ }
69
+ this._closed = true;
70
+ // Close RTCPeerConnection.
71
+ if (this._pc) {
72
+ try {
73
+ this._pc.close();
74
+ }
75
+ catch (error) { }
76
+ }
77
+ this.emit('@close');
78
+ }
79
+ async getNativeRtpCapabilities() {
80
+ logger.debug('getNativeRtpCapabilities()');
81
+ const pc = new RTCPeerConnection({
82
+ iceServers: [],
83
+ iceTransportPolicy: 'all',
84
+ bundlePolicy: 'max-bundle',
85
+ rtcpMuxPolicy: 'require',
86
+ });
87
+ // NOTE: We need to add a real video track to get the RID extension mapping,
88
+ // otherwiser Firefox doesn't include it in the SDP.
89
+ const canvas = document.createElement('canvas');
90
+ // NOTE: Otherwise Firefox fails in next line.
91
+ canvas.getContext('2d');
92
+ const fakeStream = canvas.captureStream();
93
+ const fakeVideoTrack = fakeStream.getVideoTracks()[0];
94
+ try {
95
+ pc.addTransceiver('audio', { direction: 'sendrecv' });
96
+ pc.addTransceiver(fakeVideoTrack, {
97
+ direction: 'sendrecv',
98
+ sendEncodings: [
99
+ { rid: 'r0', maxBitrate: 100000 },
100
+ { rid: 'r1', maxBitrate: 500000 },
101
+ ],
102
+ });
103
+ const offer = await pc.createOffer();
104
+ try {
105
+ canvas.remove();
106
+ }
107
+ catch (error) { }
108
+ try {
109
+ fakeVideoTrack.stop();
110
+ }
111
+ catch (error) { }
112
+ try {
113
+ pc.close();
114
+ }
115
+ catch (error) { }
116
+ const sdpObject = sdpTransform.parse(offer.sdp);
117
+ const nativeRtpCapabilities = sdpCommonUtils.extractRtpCapabilities({
118
+ sdpObject,
119
+ });
120
+ return nativeRtpCapabilities;
121
+ }
122
+ catch (error) {
123
+ try {
124
+ canvas.remove();
125
+ }
126
+ catch (error2) { }
127
+ try {
128
+ fakeVideoTrack.stop();
129
+ }
130
+ catch (error2) { }
131
+ try {
132
+ pc.close();
133
+ }
134
+ catch (error2) { }
135
+ throw error;
136
+ }
137
+ }
138
+ async getNativeSctpCapabilities() {
139
+ logger.debug('getNativeSctpCapabilities()');
140
+ return {
141
+ numStreams: SCTP_NUM_STREAMS,
142
+ };
143
+ }
144
+ run({ direction, iceParameters, iceCandidates, dtlsParameters, sctpParameters, iceServers, iceTransportPolicy, additionalSettings, proprietaryConstraints, extendedRtpCapabilities, }) {
145
+ this.assertNotClosed();
146
+ logger.debug('run()');
147
+ this._direction = direction;
148
+ this._remoteSdp = new RemoteSdp_1.RemoteSdp({
149
+ iceParameters,
150
+ iceCandidates,
151
+ dtlsParameters,
152
+ sctpParameters,
153
+ });
154
+ this._sendingRtpParametersByKind = {
155
+ audio: ortc.getSendingRtpParameters('audio', extendedRtpCapabilities),
156
+ video: ortc.getSendingRtpParameters('video', extendedRtpCapabilities),
157
+ };
158
+ this._sendingRemoteRtpParametersByKind = {
159
+ audio: ortc.getSendingRemoteRtpParameters('audio', extendedRtpCapabilities),
160
+ video: ortc.getSendingRemoteRtpParameters('video', extendedRtpCapabilities),
161
+ };
162
+ this._pc = new RTCPeerConnection({
163
+ iceServers: iceServers || [],
164
+ iceTransportPolicy: iceTransportPolicy || 'all',
165
+ bundlePolicy: 'max-bundle',
166
+ rtcpMuxPolicy: 'require',
167
+ ...additionalSettings,
168
+ }, proprietaryConstraints);
169
+ this._pc.addEventListener('icegatheringstatechange', () => {
170
+ this.emit('@icegatheringstatechange', this._pc.iceGatheringState);
171
+ });
172
+ if (this._pc.connectionState) {
173
+ this._pc.addEventListener('connectionstatechange', () => {
174
+ this.emit('@connectionstatechange', this._pc.connectionState);
175
+ });
176
+ }
177
+ else {
178
+ this._pc.addEventListener('iceconnectionstatechange', () => {
179
+ logger.warn('run() | pc.connectionState not supported, using pc.iceConnectionState');
180
+ switch (this._pc.iceConnectionState) {
181
+ case 'checking': {
182
+ this.emit('@connectionstatechange', 'connecting');
183
+ break;
184
+ }
185
+ case 'connected':
186
+ case 'completed': {
187
+ this.emit('@connectionstatechange', 'connected');
188
+ break;
189
+ }
190
+ case 'failed': {
191
+ this.emit('@connectionstatechange', 'failed');
192
+ break;
193
+ }
194
+ case 'disconnected': {
195
+ this.emit('@connectionstatechange', 'disconnected');
196
+ break;
197
+ }
198
+ case 'closed': {
199
+ this.emit('@connectionstatechange', 'closed');
200
+ break;
201
+ }
202
+ }
203
+ });
204
+ }
205
+ }
206
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
207
+ async updateIceServers(iceServers) {
208
+ this.assertNotClosed();
209
+ // NOTE: Firefox does not implement pc.setConfiguration().
210
+ throw new errors_1.UnsupportedError('not supported');
211
+ }
212
+ async restartIce(iceParameters) {
213
+ this.assertNotClosed();
214
+ logger.debug('restartIce()');
215
+ // Provide the remote SDP handler with new remote ICE parameters.
216
+ this._remoteSdp.updateIceParameters(iceParameters);
217
+ if (!this._transportReady) {
218
+ return;
219
+ }
220
+ if (this._direction === 'send') {
221
+ const offer = await this._pc.createOffer({ iceRestart: true });
222
+ logger.debug('restartIce() | calling pc.setLocalDescription() [offer:%o]', offer);
223
+ await this._pc.setLocalDescription(offer);
224
+ const answer = { type: 'answer', sdp: this._remoteSdp.getSdp() };
225
+ logger.debug('restartIce() | calling pc.setRemoteDescription() [answer:%o]', answer);
226
+ await this._pc.setRemoteDescription(answer);
227
+ }
228
+ else {
229
+ const offer = { type: 'offer', sdp: this._remoteSdp.getSdp() };
230
+ logger.debug('restartIce() | calling pc.setRemoteDescription() [offer:%o]', offer);
231
+ await this._pc.setRemoteDescription(offer);
232
+ const answer = await this._pc.createAnswer();
233
+ logger.debug('restartIce() | calling pc.setLocalDescription() [answer:%o]', answer);
234
+ await this._pc.setLocalDescription(answer);
235
+ }
236
+ }
237
+ async getTransportStats() {
238
+ this.assertNotClosed();
239
+ return this._pc.getStats();
240
+ }
241
+ async send({ track, encodings, codecOptions, codec, }) {
242
+ this.assertNotClosed();
243
+ this.assertSendDirection();
244
+ logger.debug('send() [kind:%s, track.id:%s]', track.kind, track.id);
245
+ if (encodings && encodings.length > 1) {
246
+ encodings.forEach((encoding, idx) => {
247
+ encoding.rid = `r${idx}`;
248
+ });
249
+ }
250
+ const sendingRtpParameters = utils.clone(this._sendingRtpParametersByKind[track.kind]);
251
+ // This may throw.
252
+ sendingRtpParameters.codecs = ortc.reduceCodecs(sendingRtpParameters.codecs, codec);
253
+ const sendingRemoteRtpParameters = utils.clone(this._sendingRemoteRtpParametersByKind[track.kind]);
254
+ // This may throw.
255
+ sendingRemoteRtpParameters.codecs = ortc.reduceCodecs(sendingRemoteRtpParameters.codecs, codec);
256
+ // NOTE: Firefox fails sometimes to properly anticipate the closed media
257
+ // section that it should use, so don't reuse closed media sections.
258
+ // https://github.com/versatica/mediasoup-client/issues/104
259
+ //
260
+ // const mediaSectionIdx = this._remoteSdp!.getNextMediaSectionIdx();
261
+ const transceiver = this._pc.addTransceiver(track, {
262
+ direction: 'sendonly',
263
+ streams: [this._sendStream],
264
+ sendEncodings: encodings,
265
+ });
266
+ const offer = await this._pc.createOffer();
267
+ let localSdpObject = sdpTransform.parse(offer.sdp);
268
+ // In Firefox use DTLS role client even if we are the "offerer" since
269
+ // Firefox does not respect ICE-Lite.
270
+ if (!this._transportReady) {
271
+ await this.setupTransport({ localDtlsRole: 'client', localSdpObject });
272
+ }
273
+ const layers = (0, scalabilityModes_1.parse)((encodings || [{}])[0].scalabilityMode);
274
+ logger.debug('send() | calling pc.setLocalDescription() [offer:%o]', offer);
275
+ await this._pc.setLocalDescription(offer);
276
+ // We can now get the transceiver.mid.
277
+ const localId = transceiver.mid;
278
+ // Set MID.
279
+ sendingRtpParameters.mid = localId;
280
+ localSdpObject = sdpTransform.parse(this._pc.localDescription.sdp);
281
+ const offerMediaObject = localSdpObject.media[localSdpObject.media.length - 1];
282
+ // Set RTCP CNAME.
283
+ sendingRtpParameters.rtcp.cname = sdpCommonUtils.getCname({
284
+ offerMediaObject,
285
+ });
286
+ // Set RTP encodings by parsing the SDP offer if no encodings are given.
287
+ if (!encodings) {
288
+ sendingRtpParameters.encodings = sdpUnifiedPlanUtils.getRtpEncodings({
289
+ offerMediaObject,
290
+ });
291
+ }
292
+ // Set RTP encodings by parsing the SDP offer and complete them with given
293
+ // one if just a single encoding has been given.
294
+ else if (encodings.length === 1) {
295
+ const newEncodings = sdpUnifiedPlanUtils.getRtpEncodings({
296
+ offerMediaObject,
297
+ });
298
+ Object.assign(newEncodings[0], encodings[0]);
299
+ sendingRtpParameters.encodings = newEncodings;
300
+ }
301
+ // Otherwise if more than 1 encoding are given use them verbatim.
302
+ else {
303
+ sendingRtpParameters.encodings = encodings;
304
+ }
305
+ // If VP8 or H264 and there is effective simulcast, add scalabilityMode to
306
+ // each encoding.
307
+ if (sendingRtpParameters.encodings.length > 1 &&
308
+ (sendingRtpParameters.codecs[0].mimeType.toLowerCase() === 'video/vp8' ||
309
+ sendingRtpParameters.codecs[0].mimeType.toLowerCase() === 'video/h264')) {
310
+ for (const encoding of sendingRtpParameters.encodings) {
311
+ if (encoding.scalabilityMode) {
312
+ encoding.scalabilityMode = `L1T${layers.temporalLayers}`;
313
+ }
314
+ else {
315
+ encoding.scalabilityMode = 'L1T3';
316
+ }
317
+ }
318
+ }
319
+ this._remoteSdp.send({
320
+ offerMediaObject,
321
+ offerRtpParameters: sendingRtpParameters,
322
+ answerRtpParameters: sendingRemoteRtpParameters,
323
+ codecOptions,
324
+ extmapAllowMixed: true,
325
+ });
326
+ const answer = { type: 'answer', sdp: this._remoteSdp.getSdp() };
327
+ logger.debug('send() | calling pc.setRemoteDescription() [answer:%o]', answer);
328
+ await this._pc.setRemoteDescription(answer);
329
+ // Store in the map.
330
+ this._mapMidTransceiver.set(localId, transceiver);
331
+ return {
332
+ localId,
333
+ rtpParameters: sendingRtpParameters,
334
+ rtpSender: transceiver.sender,
335
+ };
336
+ }
337
+ async stopSending(localId) {
338
+ this.assertSendDirection();
339
+ logger.debug('stopSending() [localId:%s]', localId);
340
+ if (this._closed) {
341
+ return;
342
+ }
343
+ const transceiver = this._mapMidTransceiver.get(localId);
344
+ if (!transceiver) {
345
+ throw new Error('associated transceiver not found');
346
+ }
347
+ transceiver.sender.replaceTrack(null);
348
+ // NOTE: Cannot use stop() the transceiver due to the the note above in
349
+ // send() method.
350
+ // try
351
+ // {
352
+ // transceiver.stop();
353
+ // }
354
+ // catch (error)
355
+ // {}
356
+ this._pc.removeTrack(transceiver.sender);
357
+ // NOTE: Cannot use closeMediaSection() due to the the note above in send()
358
+ // method.
359
+ // this._remoteSdp!.closeMediaSection(transceiver.mid);
360
+ this._remoteSdp.disableMediaSection(transceiver.mid);
361
+ const offer = await this._pc.createOffer();
362
+ logger.debug('stopSending() | calling pc.setLocalDescription() [offer:%o]', offer);
363
+ await this._pc.setLocalDescription(offer);
364
+ const answer = { type: 'answer', sdp: this._remoteSdp.getSdp() };
365
+ logger.debug('stopSending() | calling pc.setRemoteDescription() [answer:%o]', answer);
366
+ await this._pc.setRemoteDescription(answer);
367
+ this._mapMidTransceiver.delete(localId);
368
+ }
369
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
370
+ async pauseSending(localId) {
371
+ this.assertNotClosed();
372
+ this.assertSendDirection();
373
+ logger.debug('pauseSending() [localId:%s]', localId);
374
+ const transceiver = this._mapMidTransceiver.get(localId);
375
+ if (!transceiver) {
376
+ throw new Error('associated RTCRtpTransceiver not found');
377
+ }
378
+ transceiver.direction = 'inactive';
379
+ this._remoteSdp.pauseMediaSection(localId);
380
+ const offer = await this._pc.createOffer();
381
+ logger.debug('pauseSending() | calling pc.setLocalDescription() [offer:%o]', offer);
382
+ await this._pc.setLocalDescription(offer);
383
+ const answer = { type: 'answer', sdp: this._remoteSdp.getSdp() };
384
+ logger.debug('pauseSending() | calling pc.setRemoteDescription() [answer:%o]', answer);
385
+ await this._pc.setRemoteDescription(answer);
386
+ }
387
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
388
+ async resumeSending(localId) {
389
+ this.assertNotClosed();
390
+ this.assertSendDirection();
391
+ logger.debug('resumeSending() [localId:%s]', localId);
392
+ const transceiver = this._mapMidTransceiver.get(localId);
393
+ if (!transceiver) {
394
+ throw new Error('associated RTCRtpTransceiver not found');
395
+ }
396
+ transceiver.direction = 'sendonly';
397
+ this._remoteSdp.resumeSendingMediaSection(localId);
398
+ const offer = await this._pc.createOffer();
399
+ logger.debug('resumeSending() | calling pc.setLocalDescription() [offer:%o]', offer);
400
+ await this._pc.setLocalDescription(offer);
401
+ const answer = { type: 'answer', sdp: this._remoteSdp.getSdp() };
402
+ logger.debug('resumeSending() | calling pc.setRemoteDescription() [answer:%o]', answer);
403
+ await this._pc.setRemoteDescription(answer);
404
+ }
405
+ async replaceTrack(localId, track) {
406
+ this.assertNotClosed();
407
+ this.assertSendDirection();
408
+ if (track) {
409
+ logger.debug('replaceTrack() [localId:%s, track.id:%s]', localId, track.id);
410
+ }
411
+ else {
412
+ logger.debug('replaceTrack() [localId:%s, no track]', localId);
413
+ }
414
+ const transceiver = this._mapMidTransceiver.get(localId);
415
+ if (!transceiver) {
416
+ throw new Error('associated RTCRtpTransceiver not found');
417
+ }
418
+ await transceiver.sender.replaceTrack(track);
419
+ }
420
+ async setMaxSpatialLayer(localId, spatialLayer) {
421
+ this.assertNotClosed();
422
+ this.assertSendDirection();
423
+ logger.debug('setMaxSpatialLayer() [localId:%s, spatialLayer:%s]', localId, spatialLayer);
424
+ const transceiver = this._mapMidTransceiver.get(localId);
425
+ if (!transceiver) {
426
+ throw new Error('associated transceiver not found');
427
+ }
428
+ const parameters = transceiver.sender.getParameters();
429
+ parameters.encodings.forEach((encoding, idx) => {
430
+ if (idx <= spatialLayer) {
431
+ encoding.active = true;
432
+ }
433
+ else {
434
+ encoding.active = false;
435
+ }
436
+ });
437
+ await transceiver.sender.setParameters(parameters);
438
+ this._remoteSdp.muxMediaSectionSimulcast(localId, parameters.encodings);
439
+ const offer = await this._pc.createOffer();
440
+ logger.debug('setMaxSpatialLayer() | calling pc.setLocalDescription() [offer:%o]', offer);
441
+ await this._pc.setLocalDescription(offer);
442
+ const answer = { type: 'answer', sdp: this._remoteSdp.getSdp() };
443
+ logger.debug('setMaxSpatialLayer() | calling pc.setRemoteDescription() [answer:%o]', answer);
444
+ await this._pc.setRemoteDescription(answer);
445
+ }
446
+ async setRtpEncodingParameters(localId, params) {
447
+ this.assertNotClosed();
448
+ this.assertSendDirection();
449
+ logger.debug('setRtpEncodingParameters() [localId:%s, params:%o]', localId, params);
450
+ const transceiver = this._mapMidTransceiver.get(localId);
451
+ if (!transceiver) {
452
+ throw new Error('associated RTCRtpTransceiver not found');
453
+ }
454
+ const parameters = transceiver.sender.getParameters();
455
+ parameters.encodings.forEach((encoding, idx) => {
456
+ parameters.encodings[idx] = { ...encoding, ...params };
457
+ });
458
+ await transceiver.sender.setParameters(parameters);
459
+ this._remoteSdp.muxMediaSectionSimulcast(localId, parameters.encodings);
460
+ const offer = await this._pc.createOffer();
461
+ logger.debug('setRtpEncodingParameters() | calling pc.setLocalDescription() [offer:%o]', offer);
462
+ await this._pc.setLocalDescription(offer);
463
+ const answer = { type: 'answer', sdp: this._remoteSdp.getSdp() };
464
+ logger.debug('setRtpEncodingParameters() | calling pc.setRemoteDescription() [answer:%o]', answer);
465
+ await this._pc.setRemoteDescription(answer);
466
+ }
467
+ async getSenderStats(localId) {
468
+ this.assertNotClosed();
469
+ this.assertSendDirection();
470
+ const transceiver = this._mapMidTransceiver.get(localId);
471
+ if (!transceiver) {
472
+ throw new Error('associated RTCRtpTransceiver not found');
473
+ }
474
+ return transceiver.sender.getStats();
475
+ }
476
+ async sendDataChannel({ ordered, maxPacketLifeTime, maxRetransmits, label, protocol, }) {
477
+ this.assertNotClosed();
478
+ this.assertSendDirection();
479
+ const options = {
480
+ negotiated: true,
481
+ id: this._nextSendSctpStreamId,
482
+ ordered,
483
+ maxPacketLifeTime,
484
+ maxRetransmits,
485
+ protocol,
486
+ };
487
+ logger.debug('sendDataChannel() [options:%o]', options);
488
+ const dataChannel = this._pc.createDataChannel(label, options);
489
+ // Increase next id.
490
+ this._nextSendSctpStreamId =
491
+ ++this._nextSendSctpStreamId % SCTP_NUM_STREAMS.MIS;
492
+ // If this is the first DataChannel we need to create the SDP answer with
493
+ // m=application section.
494
+ if (!this._hasDataChannelMediaSection) {
495
+ const offer = await this._pc.createOffer();
496
+ const localSdpObject = sdpTransform.parse(offer.sdp);
497
+ const offerMediaObject = localSdpObject.media.find((m) => m.type === 'application');
498
+ if (!this._transportReady) {
499
+ await this.setupTransport({ localDtlsRole: 'client', localSdpObject });
500
+ }
501
+ logger.debug('sendDataChannel() | calling pc.setLocalDescription() [offer:%o]', offer);
502
+ await this._pc.setLocalDescription(offer);
503
+ this._remoteSdp.sendSctpAssociation({ offerMediaObject });
504
+ const answer = { type: 'answer', sdp: this._remoteSdp.getSdp() };
505
+ logger.debug('sendDataChannel() | calling pc.setRemoteDescription() [answer:%o]', answer);
506
+ await this._pc.setRemoteDescription(answer);
507
+ this._hasDataChannelMediaSection = true;
508
+ }
509
+ const sctpStreamParameters = {
510
+ streamId: options.id,
511
+ ordered: options.ordered,
512
+ maxPacketLifeTime: options.maxPacketLifeTime,
513
+ maxRetransmits: options.maxRetransmits,
514
+ };
515
+ return { dataChannel, sctpStreamParameters };
516
+ }
517
+ async receive(
518
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
519
+ optionsList) {
520
+ this.assertNotClosed();
521
+ this.assertRecvDirection();
522
+ const results = [];
523
+ const mapLocalId = new Map();
524
+ for (const options of optionsList) {
525
+ const { trackId, kind, rtpParameters, streamId } = options;
526
+ logger.debug('receive() [trackId:%s, kind:%s]', trackId, kind);
527
+ const localId = rtpParameters.mid || String(this._mapMidTransceiver.size);
528
+ mapLocalId.set(trackId, localId);
529
+ this._remoteSdp.receive({
530
+ mid: localId,
531
+ kind,
532
+ offerRtpParameters: rtpParameters,
533
+ streamId: streamId || rtpParameters.rtcp.cname,
534
+ trackId,
535
+ });
536
+ }
537
+ const offer = { type: 'offer', sdp: this._remoteSdp.getSdp() };
538
+ logger.debug('receive() | calling pc.setRemoteDescription() [offer:%o]', offer);
539
+ await this._pc.setRemoteDescription(offer);
540
+ let answer = await this._pc.createAnswer();
541
+ const localSdpObject = sdpTransform.parse(answer.sdp);
542
+ for (const options of optionsList) {
543
+ const { trackId, rtpParameters } = options;
544
+ const localId = mapLocalId.get(trackId);
545
+ const answerMediaObject = localSdpObject.media.find((m) => String(m.mid) === localId);
546
+ // May need to modify codec parameters in the answer based on codec
547
+ // parameters in the offer.
548
+ sdpCommonUtils.applyCodecParameters({
549
+ offerRtpParameters: rtpParameters,
550
+ answerMediaObject,
551
+ });
552
+ answer = { type: 'answer', sdp: sdpTransform.write(localSdpObject) };
553
+ }
554
+ if (!this._transportReady) {
555
+ await this.setupTransport({ localDtlsRole: 'client', localSdpObject });
556
+ }
557
+ logger.debug('receive() | calling pc.setLocalDescription() [answer:%o]', answer);
558
+ await this._pc.setLocalDescription(answer);
559
+ for (const options of optionsList) {
560
+ const { trackId } = options;
561
+ const localId = mapLocalId.get(trackId);
562
+ const transceiver = this._pc
563
+ .getTransceivers()
564
+ .find((t) => t.mid === localId);
565
+ if (!transceiver) {
566
+ throw new Error('new RTCRtpTransceiver not found');
567
+ }
568
+ // Store in the map.
569
+ this._mapMidTransceiver.set(localId, transceiver);
570
+ results.push({
571
+ localId,
572
+ track: transceiver.receiver.track,
573
+ rtpReceiver: transceiver.receiver,
574
+ });
575
+ }
576
+ return results;
577
+ }
578
+ async stopReceiving(localIds) {
579
+ this.assertRecvDirection();
580
+ if (this._closed) {
581
+ return;
582
+ }
583
+ for (const localId of localIds) {
584
+ logger.debug('stopReceiving() [localId:%s]', localId);
585
+ const transceiver = this._mapMidTransceiver.get(localId);
586
+ if (!transceiver) {
587
+ throw new Error('associated RTCRtpTransceiver not found');
588
+ }
589
+ this._remoteSdp.closeMediaSection(transceiver.mid);
590
+ }
591
+ const offer = { type: 'offer', sdp: this._remoteSdp.getSdp() };
592
+ logger.debug('stopReceiving() | calling pc.setRemoteDescription() [offer:%o]', offer);
593
+ await this._pc.setRemoteDescription(offer);
594
+ const answer = await this._pc.createAnswer();
595
+ logger.debug('stopReceiving() | calling pc.setLocalDescription() [answer:%o]', answer);
596
+ await this._pc.setLocalDescription(answer);
597
+ for (const localId of localIds) {
598
+ this._mapMidTransceiver.delete(localId);
599
+ }
600
+ }
601
+ async pauseReceiving(localIds) {
602
+ this.assertNotClosed();
603
+ this.assertRecvDirection();
604
+ for (const localId of localIds) {
605
+ logger.debug('pauseReceiving() [localId:%s]', localId);
606
+ const transceiver = this._mapMidTransceiver.get(localId);
607
+ if (!transceiver) {
608
+ throw new Error('associated RTCRtpTransceiver not found');
609
+ }
610
+ transceiver.direction = 'inactive';
611
+ this._remoteSdp.pauseMediaSection(localId);
612
+ }
613
+ const offer = { type: 'offer', sdp: this._remoteSdp.getSdp() };
614
+ logger.debug('pauseReceiving() | calling pc.setRemoteDescription() [offer:%o]', offer);
615
+ await this._pc.setRemoteDescription(offer);
616
+ const answer = await this._pc.createAnswer();
617
+ logger.debug('pauseReceiving() | calling pc.setLocalDescription() [answer:%o]', answer);
618
+ await this._pc.setLocalDescription(answer);
619
+ }
620
+ async resumeReceiving(localIds) {
621
+ this.assertNotClosed();
622
+ this.assertRecvDirection();
623
+ for (const localId of localIds) {
624
+ logger.debug('resumeReceiving() [localId:%s]', localId);
625
+ const transceiver = this._mapMidTransceiver.get(localId);
626
+ if (!transceiver) {
627
+ throw new Error('associated RTCRtpTransceiver not found');
628
+ }
629
+ transceiver.direction = 'recvonly';
630
+ this._remoteSdp.resumeReceivingMediaSection(localId);
631
+ }
632
+ const offer = { type: 'offer', sdp: this._remoteSdp.getSdp() };
633
+ logger.debug('resumeReceiving() | calling pc.setRemoteDescription() [offer:%o]', offer);
634
+ await this._pc.setRemoteDescription(offer);
635
+ const answer = await this._pc.createAnswer();
636
+ logger.debug('resumeReceiving() | calling pc.setLocalDescription() [answer:%o]', answer);
637
+ await this._pc.setLocalDescription(answer);
638
+ }
639
+ async getReceiverStats(localId) {
640
+ this.assertRecvDirection();
641
+ const transceiver = this._mapMidTransceiver.get(localId);
642
+ if (!transceiver) {
643
+ throw new Error('associated RTCRtpTransceiver not found');
644
+ }
645
+ return transceiver.receiver.getStats();
646
+ }
647
+ async receiveDataChannel({ sctpStreamParameters, label, protocol, }) {
648
+ this.assertNotClosed();
649
+ this.assertRecvDirection();
650
+ const { streamId, ordered, maxPacketLifeTime, maxRetransmits, } = sctpStreamParameters;
651
+ const options = {
652
+ negotiated: true,
653
+ id: streamId,
654
+ ordered,
655
+ maxPacketLifeTime,
656
+ maxRetransmits,
657
+ protocol,
658
+ };
659
+ logger.debug('receiveDataChannel() [options:%o]', options);
660
+ const dataChannel = this._pc.createDataChannel(label, options);
661
+ // If this is the first DataChannel we need to create the SDP offer with
662
+ // m=application section.
663
+ if (!this._hasDataChannelMediaSection) {
664
+ this._remoteSdp.receiveSctpAssociation();
665
+ const offer = { type: 'offer', sdp: this._remoteSdp.getSdp() };
666
+ logger.debug('receiveDataChannel() | calling pc.setRemoteDescription() [offer:%o]', offer);
667
+ await this._pc.setRemoteDescription(offer);
668
+ const answer = await this._pc.createAnswer();
669
+ if (!this._transportReady) {
670
+ const localSdpObject = sdpTransform.parse(answer.sdp);
671
+ await this.setupTransport({ localDtlsRole: 'client', localSdpObject });
672
+ }
673
+ logger.debug('receiveDataChannel() | calling pc.setRemoteDescription() [answer:%o]', answer);
674
+ await this._pc.setLocalDescription(answer);
675
+ this._hasDataChannelMediaSection = true;
676
+ }
677
+ return { dataChannel };
678
+ }
679
+ async setupTransport({ localDtlsRole, localSdpObject, }) {
680
+ if (!localSdpObject) {
681
+ localSdpObject = sdpTransform.parse(this._pc.localDescription.sdp);
682
+ }
683
+ // Get our local DTLS parameters.
684
+ const dtlsParameters = sdpCommonUtils.extractDtlsParameters({
685
+ sdpObject: localSdpObject,
686
+ });
687
+ // Set our DTLS role.
688
+ dtlsParameters.role = localDtlsRole;
689
+ // Update the remote DTLS role in the SDP.
690
+ this._remoteSdp.updateDtlsRole(localDtlsRole === 'client' ? 'server' : 'client');
691
+ // Need to tell the remote transport about our parameters.
692
+ await new Promise((resolve, reject) => {
693
+ this.safeEmit('@connect', { dtlsParameters }, resolve, reject);
694
+ });
695
+ this._transportReady = true;
696
+ }
697
+ assertNotClosed() {
698
+ if (this._closed) {
699
+ throw new errors_1.InvalidStateError('method called in a closed handler');
700
+ }
701
+ }
702
+ assertSendDirection() {
703
+ if (this._direction !== 'send') {
704
+ throw new Error('method can just be called for handlers with "send" direction');
705
+ }
706
+ }
707
+ assertRecvDirection() {
708
+ if (this._direction !== 'recv') {
709
+ throw new Error('method can just be called for handlers with "recv" direction');
710
+ }
711
+ }
712
+ }
713
+ exports.Firefox120 = Firefox120;
package/lib/index.d.ts CHANGED
@@ -8,7 +8,7 @@ export { types };
8
8
  /**
9
9
  * Expose mediasoup-client version.
10
10
  */
11
- export declare const version = "3.7.4";
11
+ export declare const version = "3.7.6";
12
12
  /**
13
13
  * Expose Device class and detectDevice() helper.
14
14
  */
package/lib/index.js CHANGED
@@ -37,7 +37,7 @@ exports.types = types;
37
37
  /**
38
38
  * Expose mediasoup-client version.
39
39
  */
40
- exports.version = '3.7.4';
40
+ exports.version = '3.7.6';
41
41
  /**
42
42
  * Expose parseScalabilityMode() function.
43
43
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mediasoup-client",
3
- "version": "3.7.4",
3
+ "version": "3.7.6",
4
4
  "description": "mediasoup client side TypeScript library",
5
5
  "contributors": [
6
6
  "Iñaki Baz Castillo <ibc@aliax.net> (https://inakibaz.me)",
@@ -80,11 +80,11 @@
80
80
  "@types/jest": "^29.5.12",
81
81
  "@types/sdp-transform": "^2.4.9",
82
82
  "@types/ua-parser-js": "^0.7.39",
83
- "@typescript-eslint/eslint-plugin": "^7.0.1",
84
- "@typescript-eslint/parser": "^7.0.1",
85
- "eslint": "^8.56.0",
83
+ "@typescript-eslint/eslint-plugin": "^7.1.0",
84
+ "@typescript-eslint/parser": "^7.1.0",
85
+ "eslint": "^8.57.0",
86
86
  "eslint-config-prettier": "^9.1.0",
87
- "eslint-plugin-jest": "^27.8.0",
87
+ "eslint-plugin-jest": "^27.9.0",
88
88
  "eslint-plugin-prettier": "^5.1.3",
89
89
  "jest": "^29.7.0",
90
90
  "open-cli": "^8.0.0",