mediasoup-client 3.6.45 → 3.6.49
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/.vimrc +21 -0
- package/NO_GIT/Notes.txt +18 -0
- package/lib/DataConsumer.d.ts +2 -2
- package/lib/DataConsumer.d.ts.map +1 -1
- package/lib/Device.d.ts.map +1 -1
- package/lib/Device.js +7 -3
- package/lib/Logger.js +6 -6
- package/lib/Transport.d.ts +3 -0
- package/lib/Transport.d.ts.map +1 -1
- package/lib/Transport.js +111 -40
- package/lib/handlers/Chrome55.d.ts +1 -1
- package/lib/handlers/Chrome55.d.ts.map +1 -1
- package/lib/handlers/Chrome55.js +51 -30
- package/lib/handlers/Chrome67.d.ts +1 -1
- package/lib/handlers/Chrome67.d.ts.map +1 -1
- package/lib/handlers/Chrome67.js +55 -33
- package/lib/handlers/Chrome70.d.ts +1 -1
- package/lib/handlers/Chrome70.d.ts.map +1 -1
- package/lib/handlers/Chrome70.js +53 -33
- package/lib/handlers/Chrome74.d.ts +1 -1
- package/lib/handlers/Chrome74.d.ts.map +1 -1
- package/lib/handlers/Chrome74.js +56 -33
- package/lib/handlers/Edge11.d.ts +1 -1
- package/lib/handlers/Edge11.d.ts.map +1 -1
- package/lib/handlers/Edge11.js +31 -22
- package/lib/handlers/FakeHandler.d.ts +1 -1
- package/lib/handlers/FakeHandler.d.ts.map +1 -1
- package/lib/handlers/FakeHandler.js +14 -11
- package/lib/handlers/Firefox60.d.ts +1 -1
- package/lib/handlers/Firefox60.d.ts.map +1 -1
- package/lib/handlers/Firefox60.js +54 -33
- package/lib/handlers/HandlerInterface.d.ts +1 -1
- package/lib/handlers/HandlerInterface.d.ts.map +1 -1
- package/lib/handlers/ReactNative.d.ts +1 -1
- package/lib/handlers/ReactNative.d.ts.map +1 -1
- package/lib/handlers/ReactNative.js +59 -36
- package/lib/handlers/Safari11.d.ts +1 -1
- package/lib/handlers/Safari11.d.ts.map +1 -1
- package/lib/handlers/Safari11.js +52 -33
- package/lib/handlers/Safari12.d.ts +1 -1
- package/lib/handlers/Safari12.d.ts.map +1 -1
- package/lib/handlers/Safari12.js +51 -32
- package/lib/handlers/ortc/edgeUtils.js +1 -1
- package/lib/handlers/sdp/MediaSection.js +1 -1
- package/lib/handlers/sdp/RemoteSdp.js +1 -1
- package/lib/handlers/sdp/commonUtils.js +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.js +3 -3
- package/lib/ortc.js +5 -7
- package/lib/types.js +1 -1
- package/package.json +11 -11
- package/src/DataConsumer.ts +2 -2
- package/src/Device.ts +7 -2
- package/src/Transport.ts +162 -58
- package/src/handlers/Chrome55.ts +53 -32
- package/src/handlers/Chrome67.ts +55 -34
- package/src/handlers/Chrome70.ts +52 -32
- package/src/handlers/Chrome74.ts +56 -32
- package/src/handlers/Edge11.ts +42 -26
- package/src/handlers/FakeHandler.ts +18 -10
- package/src/handlers/Firefox60.ts +54 -33
- package/src/handlers/HandlerInterface.ts +2 -2
- package/src/handlers/ReactNative.ts +63 -39
- package/src/handlers/Safari11.ts +55 -34
- package/src/handlers/Safari12.ts +52 -32
- package/src/ortc.ts +6 -8
- package/tsconfig.json +1 -1
package/lib/handlers/Safari12.js
CHANGED
|
@@ -14,7 +14,7 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
14
14
|
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
15
|
if (mod && mod.__esModule) return mod;
|
|
16
16
|
var result = {};
|
|
17
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
18
|
__setModuleDefault(result, mod);
|
|
19
19
|
return result;
|
|
20
20
|
};
|
|
@@ -121,7 +121,13 @@ class Safari12 extends HandlerInterface_1.HandlerInterface {
|
|
|
121
121
|
? 'client'
|
|
122
122
|
: 'server';
|
|
123
123
|
}
|
|
124
|
-
this._pc = new RTCPeerConnection(
|
|
124
|
+
this._pc = new RTCPeerConnection({
|
|
125
|
+
iceServers: iceServers || [],
|
|
126
|
+
iceTransportPolicy: iceTransportPolicy || 'all',
|
|
127
|
+
bundlePolicy: 'max-bundle',
|
|
128
|
+
rtcpMuxPolicy: 'require',
|
|
129
|
+
...additionalSettings
|
|
130
|
+
}, proprietaryConstraints);
|
|
125
131
|
// Handle RTCPeerConnection connection status.
|
|
126
132
|
this._pc.addEventListener('iceconnectionstatechange', () => {
|
|
127
133
|
switch (this._pc.iceConnectionState) {
|
|
@@ -310,7 +316,7 @@ class Safari12 extends HandlerInterface_1.HandlerInterface {
|
|
|
310
316
|
throw new Error('associated RTCRtpTransceiver not found');
|
|
311
317
|
const parameters = transceiver.sender.getParameters();
|
|
312
318
|
parameters.encodings.forEach((encoding, idx) => {
|
|
313
|
-
parameters.encodings[idx] =
|
|
319
|
+
parameters.encodings[idx] = { ...encoding, ...params };
|
|
314
320
|
});
|
|
315
321
|
await transceiver.sender.setParameters(parameters);
|
|
316
322
|
}
|
|
@@ -366,31 +372,39 @@ class Safari12 extends HandlerInterface_1.HandlerInterface {
|
|
|
366
372
|
};
|
|
367
373
|
return { dataChannel, sctpStreamParameters };
|
|
368
374
|
}
|
|
369
|
-
async receive(
|
|
375
|
+
async receive(optionsList) {
|
|
370
376
|
var _a;
|
|
371
377
|
this._assertRecvDirection();
|
|
372
|
-
|
|
373
|
-
const
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
378
|
+
const results = [];
|
|
379
|
+
for (const options of optionsList) {
|
|
380
|
+
const { trackId, kind, rtpParameters } = options;
|
|
381
|
+
logger.debug('receive() [trackId:%s, kind:%s]', trackId, kind);
|
|
382
|
+
const localId = rtpParameters.mid || String(this._mapMidTransceiver.size);
|
|
383
|
+
this._remoteSdp.receive({
|
|
384
|
+
mid: localId,
|
|
385
|
+
kind,
|
|
386
|
+
offerRtpParameters: rtpParameters,
|
|
387
|
+
streamId: rtpParameters.rtcp.cname,
|
|
388
|
+
trackId
|
|
389
|
+
});
|
|
390
|
+
}
|
|
381
391
|
const offer = { type: 'offer', sdp: this._remoteSdp.getSdp() };
|
|
382
392
|
logger.debug('receive() | calling pc.setRemoteDescription() [offer:%o]', offer);
|
|
383
393
|
await this._pc.setRemoteDescription(offer);
|
|
384
394
|
let answer = await this._pc.createAnswer();
|
|
385
395
|
const localSdpObject = sdpTransform.parse(answer.sdp);
|
|
386
|
-
const
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
396
|
+
for (const options of optionsList) {
|
|
397
|
+
const { rtpParameters } = options;
|
|
398
|
+
const localId = rtpParameters.mid || String(this._mapMidTransceiver.size);
|
|
399
|
+
const answerMediaObject = localSdpObject.media
|
|
400
|
+
.find((m) => String(m.mid) === localId);
|
|
401
|
+
// May need to modify codec parameters in the answer based on codec
|
|
402
|
+
// parameters in the offer.
|
|
403
|
+
sdpCommonUtils.applyCodecParameters({
|
|
404
|
+
offerRtpParameters: rtpParameters,
|
|
405
|
+
answerMediaObject
|
|
406
|
+
});
|
|
407
|
+
}
|
|
394
408
|
answer = { type: 'answer', sdp: sdpTransform.write(localSdpObject) };
|
|
395
409
|
if (!this._transportReady) {
|
|
396
410
|
await this._setupTransport({
|
|
@@ -400,17 +414,22 @@ class Safari12 extends HandlerInterface_1.HandlerInterface {
|
|
|
400
414
|
}
|
|
401
415
|
logger.debug('receive() | calling pc.setLocalDescription() [answer:%o]', answer);
|
|
402
416
|
await this._pc.setLocalDescription(answer);
|
|
403
|
-
const
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
417
|
+
for (const options of optionsList) {
|
|
418
|
+
const { rtpParameters } = options;
|
|
419
|
+
const localId = rtpParameters.mid || String(this._mapMidTransceiver.size);
|
|
420
|
+
const transceiver = this._pc.getTransceivers()
|
|
421
|
+
.find((t) => t.mid === localId);
|
|
422
|
+
if (!transceiver)
|
|
423
|
+
throw new Error('new RTCRtpTransceiver not found');
|
|
424
|
+
// Store in the map.
|
|
425
|
+
this._mapMidTransceiver.set(localId, transceiver);
|
|
426
|
+
results.push({
|
|
427
|
+
localId,
|
|
428
|
+
track: transceiver.receiver.track,
|
|
429
|
+
rtpReceiver: transceiver.receiver
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
return results;
|
|
414
433
|
}
|
|
415
434
|
async stopReceiving(localId) {
|
|
416
435
|
this._assertRecvDirection();
|
|
@@ -14,7 +14,7 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
14
14
|
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
15
|
if (mod && mod.__esModule) return mod;
|
|
16
16
|
var result = {};
|
|
17
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
18
|
__setModuleDefault(result, mod);
|
|
19
19
|
return result;
|
|
20
20
|
};
|
|
@@ -14,7 +14,7 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
14
14
|
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
15
|
if (mod && mod.__esModule) return mod;
|
|
16
16
|
var result = {};
|
|
17
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
18
|
__setModuleDefault(result, mod);
|
|
19
19
|
return result;
|
|
20
20
|
};
|
|
@@ -14,7 +14,7 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
14
14
|
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
15
|
if (mod && mod.__esModule) return mod;
|
|
16
16
|
var result = {};
|
|
17
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
18
|
__setModuleDefault(result, mod);
|
|
19
19
|
return result;
|
|
20
20
|
};
|
|
@@ -14,7 +14,7 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
14
14
|
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
15
|
if (mod && mod.__esModule) return mod;
|
|
16
16
|
var result = {};
|
|
17
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
18
|
__setModuleDefault(result, mod);
|
|
19
19
|
return result;
|
|
20
20
|
};
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
14
14
|
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
15
|
if (mod && mod.__esModule) return mod;
|
|
16
16
|
var result = {};
|
|
17
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
18
|
__setModuleDefault(result, mod);
|
|
19
19
|
return result;
|
|
20
20
|
};
|
|
@@ -22,7 +22,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
22
22
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
23
|
};
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
exports.debug = exports.detectDevice = exports.Device = exports.version = exports.types = void 0;
|
|
25
|
+
exports.debug = exports.parseScalabilityMode = exports.detectDevice = exports.Device = exports.version = exports.types = void 0;
|
|
26
26
|
const debug_1 = __importDefault(require("debug"));
|
|
27
27
|
exports.debug = debug_1.default;
|
|
28
28
|
const Device_1 = require("./Device");
|
|
@@ -33,7 +33,7 @@ exports.types = types;
|
|
|
33
33
|
/**
|
|
34
34
|
* Expose mediasoup-client version.
|
|
35
35
|
*/
|
|
36
|
-
exports.version = '3.6.
|
|
36
|
+
exports.version = '3.6.49';
|
|
37
37
|
/**
|
|
38
38
|
* Expose parseScalabilityMode() function.
|
|
39
39
|
*/
|
package/lib/ortc.js
CHANGED
|
@@ -14,7 +14,7 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
14
14
|
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
15
|
if (mod && mod.__esModule) return mod;
|
|
16
16
|
var result = {};
|
|
17
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
18
|
__setModuleDefault(result, mod);
|
|
19
19
|
return result;
|
|
20
20
|
};
|
|
@@ -780,12 +780,11 @@ function matchCodecs(aCodec, bCodec, { strict = false, modify = false } = {}) {
|
|
|
780
780
|
switch (aMimeType) {
|
|
781
781
|
case 'video/h264':
|
|
782
782
|
{
|
|
783
|
-
const aPacketizationMode = aCodec.parameters['packetization-mode'] || 0;
|
|
784
|
-
const bPacketizationMode = bCodec.parameters['packetization-mode'] || 0;
|
|
785
|
-
if (aPacketizationMode !== bPacketizationMode)
|
|
786
|
-
return false;
|
|
787
|
-
// If strict matching check profile-level-id.
|
|
788
783
|
if (strict) {
|
|
784
|
+
const aPacketizationMode = aCodec.parameters['packetization-mode'] || 0;
|
|
785
|
+
const bPacketizationMode = bCodec.parameters['packetization-mode'] || 0;
|
|
786
|
+
if (aPacketizationMode !== bPacketizationMode)
|
|
787
|
+
return false;
|
|
789
788
|
if (!h264.isSameProfile(aCodec.parameters, bCodec.parameters))
|
|
790
789
|
return false;
|
|
791
790
|
let selectedProfileLevelId;
|
|
@@ -811,7 +810,6 @@ function matchCodecs(aCodec, bCodec, { strict = false, modify = false } = {}) {
|
|
|
811
810
|
}
|
|
812
811
|
case 'video/vp9':
|
|
813
812
|
{
|
|
814
|
-
// If strict matching check profile-id.
|
|
815
813
|
if (strict) {
|
|
816
814
|
const aProfileId = aCodec.parameters['profile-id'] || 0;
|
|
817
815
|
const bProfileId = bCodec.parameters['profile-id'] || 0;
|
package/lib/types.js
CHANGED
|
@@ -7,7 +7,7 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
|
|
|
7
7
|
o[k2] = m[k];
|
|
8
8
|
}));
|
|
9
9
|
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
10
|
-
for (var p in m) if (p !== "default" && !
|
|
10
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
11
11
|
};
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
13
|
__exportStar(require("./Device"), exports);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mediasoup-client",
|
|
3
|
-
"version": "3.6.
|
|
3
|
+
"version": "3.6.49",
|
|
4
4
|
"description": "mediasoup client side JavaScript library",
|
|
5
5
|
"contributors": [
|
|
6
6
|
"Iñaki Baz Castillo <ibc@aliax.net> (https://inakibaz.me)",
|
|
@@ -39,25 +39,25 @@
|
|
|
39
39
|
"@types/events": "^3.0.0",
|
|
40
40
|
"awaitqueue": "^2.3.3",
|
|
41
41
|
"bowser": "^2.11.0",
|
|
42
|
-
"debug": "^4.3.
|
|
42
|
+
"debug": "^4.3.3",
|
|
43
43
|
"events": "^3.3.0",
|
|
44
44
|
"fake-mediastreamtrack": "^1.1.6",
|
|
45
45
|
"h264-profile-level-id": "^1.0.1",
|
|
46
46
|
"sdp-transform": "^2.14.1",
|
|
47
|
-
"supports-color": "^
|
|
47
|
+
"supports-color": "^9.2.1"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@types/sdp-transform": "^2.4.5",
|
|
51
51
|
"@types/uuid": "^3.4.9",
|
|
52
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
53
|
-
"@typescript-eslint/parser": "^
|
|
54
|
-
"eslint": "^
|
|
55
|
-
"eslint-plugin-jest": "^
|
|
56
|
-
"jest": "^27.
|
|
52
|
+
"@typescript-eslint/eslint-plugin": "^5.9.1",
|
|
53
|
+
"@typescript-eslint/parser": "^5.9.1",
|
|
54
|
+
"eslint": "^8.6.0",
|
|
55
|
+
"eslint-plugin-jest": "^25.3.4",
|
|
56
|
+
"jest": "^27.4.7",
|
|
57
57
|
"jest-tobetype": "^1.2.3",
|
|
58
|
-
"open-cli": "^
|
|
59
|
-
"tsc-watch": "^4.
|
|
60
|
-
"typescript": "^
|
|
58
|
+
"open-cli": "^7.0.1",
|
|
59
|
+
"tsc-watch": "^4.6.0",
|
|
60
|
+
"typescript": "^4.5.4",
|
|
61
61
|
"uuid": "^3.4.0"
|
|
62
62
|
}
|
|
63
63
|
}
|
package/src/DataConsumer.ts
CHANGED
|
@@ -128,7 +128,7 @@ export class DataConsumer extends EnhancedEventEmitter
|
|
|
128
128
|
/**
|
|
129
129
|
* DataChannel binaryType.
|
|
130
130
|
*/
|
|
131
|
-
get binaryType():
|
|
131
|
+
get binaryType(): BinaryType
|
|
132
132
|
{
|
|
133
133
|
return this._dataChannel.binaryType;
|
|
134
134
|
}
|
|
@@ -136,7 +136,7 @@ export class DataConsumer extends EnhancedEventEmitter
|
|
|
136
136
|
/**
|
|
137
137
|
* Set DataChannel binaryType.
|
|
138
138
|
*/
|
|
139
|
-
set binaryType(binaryType:
|
|
139
|
+
set binaryType(binaryType: BinaryType)
|
|
140
140
|
{
|
|
141
141
|
this._dataChannel.binaryType = binaryType;
|
|
142
142
|
}
|
package/src/Device.ts
CHANGED
|
@@ -80,8 +80,8 @@ export function detectDevice(): BuiltinHandlerName | undefined
|
|
|
80
80
|
const browser = Bowser.getParser(ua);
|
|
81
81
|
const engine = browser.getEngine();
|
|
82
82
|
|
|
83
|
-
// Chrome and
|
|
84
|
-
if (browser.satisfies({ chrome: '>=74', chromium: '>=74' }))
|
|
83
|
+
// Chrome, Chromium, and Edge.
|
|
84
|
+
if (browser.satisfies({ chrome: '>=74', chromium: '>=74', 'microsoft edge': '>=88' }))
|
|
85
85
|
{
|
|
86
86
|
return 'Chrome74';
|
|
87
87
|
}
|
|
@@ -102,6 +102,11 @@ export function detectDevice(): BuiltinHandlerName | undefined
|
|
|
102
102
|
{
|
|
103
103
|
return 'Firefox60';
|
|
104
104
|
}
|
|
105
|
+
// Firefox on iOS.
|
|
106
|
+
else if (browser.satisfies({ ios: { OS: '>=14.3', firefox: '>=30.0' } }))
|
|
107
|
+
{
|
|
108
|
+
return 'Safari12';
|
|
109
|
+
}
|
|
105
110
|
// Safari with Unified-Plan support enabled.
|
|
106
111
|
else if (
|
|
107
112
|
browser.satisfies({ safari: '>=12.0' }) &&
|
package/src/Transport.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { EnhancedEventEmitter } from './EnhancedEventEmitter';
|
|
|
4
4
|
import { UnsupportedError, InvalidStateError } from './errors';
|
|
5
5
|
import * as utils from './utils';
|
|
6
6
|
import * as ortc from './ortc';
|
|
7
|
-
import { HandlerFactory, HandlerInterface } from './handlers/HandlerInterface';
|
|
7
|
+
import { HandlerFactory, HandlerInterface, HandlerReceiveOptions } from './handlers/HandlerInterface';
|
|
8
8
|
import { Producer, ProducerOptions } from './Producer';
|
|
9
9
|
import { Consumer, ConsumerOptions } from './Consumer';
|
|
10
10
|
import { DataProducer, DataProducerOptions } from './DataProducer';
|
|
@@ -19,6 +19,24 @@ interface InternalTransportOptions extends TransportOptions
|
|
|
19
19
|
canProduceByKind: CanProduceByKind;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
class ConsumerCreationTask
|
|
23
|
+
{
|
|
24
|
+
consumerOptions: ConsumerOptions;
|
|
25
|
+
promise: Promise<Consumer>;
|
|
26
|
+
resolve?: (consumer: Consumer) => void;
|
|
27
|
+
reject?: (error: Error) => void;
|
|
28
|
+
|
|
29
|
+
constructor(consumerOptions: ConsumerOptions)
|
|
30
|
+
{
|
|
31
|
+
this.consumerOptions = consumerOptions;
|
|
32
|
+
this.promise = new Promise((resolve, reject) =>
|
|
33
|
+
{
|
|
34
|
+
this.resolve = resolve;
|
|
35
|
+
this.reject = reject;
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
22
40
|
export type TransportOptions =
|
|
23
41
|
{
|
|
24
42
|
id: string;
|
|
@@ -165,6 +183,10 @@ export class Transport extends EnhancedEventEmitter
|
|
|
165
183
|
private _probatorConsumerCreated = false;
|
|
166
184
|
// AwaitQueue instance to make async tasks happen sequentially.
|
|
167
185
|
private readonly _awaitQueue = new AwaitQueue({ ClosedErrorClass: InvalidStateError });
|
|
186
|
+
// Consumer creation tasks awaiting to be processed.
|
|
187
|
+
private _pendingConsumerTasks: ConsumerCreationTask[] = [];
|
|
188
|
+
// Consumer creation in progress flag.
|
|
189
|
+
private _consumerCreationInProgress = false;
|
|
168
190
|
// Observer instance.
|
|
169
191
|
protected readonly _observer = new EnhancedEventEmitter();
|
|
170
192
|
|
|
@@ -583,68 +605,33 @@ export class Transport extends EnhancedEventEmitter
|
|
|
583
605
|
else if (appData && typeof appData !== 'object')
|
|
584
606
|
throw new TypeError('if given, appData must be an object');
|
|
585
607
|
|
|
586
|
-
//
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
{
|
|
590
|
-
// Ensure the device can consume it.
|
|
591
|
-
const canConsume = ortc.canReceive(
|
|
592
|
-
rtpParameters, this._extendedRtpCapabilities);
|
|
593
|
-
|
|
594
|
-
if (!canConsume)
|
|
595
|
-
throw new UnsupportedError('cannot consume this Producer');
|
|
596
|
-
|
|
597
|
-
const { localId, rtpReceiver, track } =
|
|
598
|
-
await this._handler.receive({ trackId: id, kind, rtpParameters });
|
|
599
|
-
|
|
600
|
-
const consumer = new Consumer(
|
|
601
|
-
{
|
|
602
|
-
id,
|
|
603
|
-
localId,
|
|
604
|
-
producerId,
|
|
605
|
-
rtpReceiver,
|
|
606
|
-
track,
|
|
607
|
-
rtpParameters,
|
|
608
|
-
appData
|
|
609
|
-
});
|
|
610
|
-
|
|
611
|
-
this._consumers.set(consumer.id, consumer);
|
|
612
|
-
this._handleConsumer(consumer);
|
|
613
|
-
|
|
614
|
-
// If this is the first video Consumer and the Consumer for RTP probation
|
|
615
|
-
// has not yet been created, create it now.
|
|
616
|
-
if (!this._probatorConsumerCreated && kind === 'video')
|
|
617
|
-
{
|
|
618
|
-
try
|
|
619
|
-
{
|
|
620
|
-
const probatorRtpParameters =
|
|
621
|
-
ortc.generateProbatorRtpParameters(consumer.rtpParameters);
|
|
608
|
+
// Ensure the device can consume it.
|
|
609
|
+
const canConsume = ortc.canReceive(
|
|
610
|
+
rtpParameters, this._extendedRtpCapabilities);
|
|
622
611
|
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
trackId : 'probator',
|
|
626
|
-
kind : 'video',
|
|
627
|
-
rtpParameters : probatorRtpParameters
|
|
628
|
-
});
|
|
612
|
+
if (!canConsume)
|
|
613
|
+
throw new UnsupportedError('cannot consume this Producer');
|
|
629
614
|
|
|
630
|
-
|
|
615
|
+
const consumerCreationTask = new ConsumerCreationTask(
|
|
616
|
+
{
|
|
617
|
+
id,
|
|
618
|
+
producerId,
|
|
619
|
+
kind,
|
|
620
|
+
rtpParameters,
|
|
621
|
+
appData
|
|
622
|
+
}
|
|
623
|
+
);
|
|
631
624
|
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
catch (error)
|
|
635
|
-
{
|
|
636
|
-
logger.error(
|
|
637
|
-
'consume() | failed to create Consumer for RTP probation:%o',
|
|
638
|
-
error);
|
|
639
|
-
}
|
|
640
|
-
}
|
|
625
|
+
// Store the Consumer creation task.
|
|
626
|
+
this._pendingConsumerTasks.push(consumerCreationTask);
|
|
641
627
|
|
|
642
|
-
|
|
643
|
-
|
|
628
|
+
// There is no Consumer creation in progress, create it now.
|
|
629
|
+
if (this._consumerCreationInProgress === false)
|
|
630
|
+
{
|
|
631
|
+
this._createPendingConsumers();
|
|
632
|
+
}
|
|
644
633
|
|
|
645
|
-
|
|
646
|
-
},
|
|
647
|
-
'transport.consume()');
|
|
634
|
+
return consumerCreationTask.promise;
|
|
648
635
|
}
|
|
649
636
|
|
|
650
637
|
/**
|
|
@@ -788,6 +775,123 @@ export class Transport extends EnhancedEventEmitter
|
|
|
788
775
|
'transport.consumeData()');
|
|
789
776
|
}
|
|
790
777
|
|
|
778
|
+
// This method is guaranteed to never throw.
|
|
779
|
+
async _createPendingConsumers(): Promise<void>
|
|
780
|
+
{
|
|
781
|
+
this._awaitQueue.push(
|
|
782
|
+
async () =>
|
|
783
|
+
{
|
|
784
|
+
this._consumerCreationInProgress = true;
|
|
785
|
+
|
|
786
|
+
const pendingConsumerTasks = [ ...this._pendingConsumerTasks ];
|
|
787
|
+
|
|
788
|
+
// Clear pending Consumer tasks.
|
|
789
|
+
this._pendingConsumerTasks = [];
|
|
790
|
+
|
|
791
|
+
// Video Consumer in order to create the probator.
|
|
792
|
+
let videoConsumerForProbator: Consumer | undefined = undefined;
|
|
793
|
+
|
|
794
|
+
// Fill options list.
|
|
795
|
+
const optionsList: HandlerReceiveOptions[] = [];
|
|
796
|
+
|
|
797
|
+
for (const task of pendingConsumerTasks)
|
|
798
|
+
{
|
|
799
|
+
const { id, kind, rtpParameters } = task.consumerOptions;
|
|
800
|
+
|
|
801
|
+
optionsList.push({
|
|
802
|
+
trackId : id!,
|
|
803
|
+
kind : kind as 'audio' | 'video',
|
|
804
|
+
rtpParameters
|
|
805
|
+
});
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
try
|
|
809
|
+
{
|
|
810
|
+
const results = await this._handler.receive(optionsList);
|
|
811
|
+
|
|
812
|
+
for (let idx=0; idx < results.length; idx++)
|
|
813
|
+
{
|
|
814
|
+
const task = pendingConsumerTasks[idx];
|
|
815
|
+
const result = results[idx];
|
|
816
|
+
const { id, producerId, kind, rtpParameters, appData } = task.consumerOptions;
|
|
817
|
+
const { localId, rtpReceiver, track } = result;
|
|
818
|
+
const consumer = new Consumer(
|
|
819
|
+
{
|
|
820
|
+
id : id!,
|
|
821
|
+
localId,
|
|
822
|
+
producerId : producerId!,
|
|
823
|
+
rtpReceiver,
|
|
824
|
+
track,
|
|
825
|
+
rtpParameters,
|
|
826
|
+
appData
|
|
827
|
+
});
|
|
828
|
+
|
|
829
|
+
this._consumers.set(consumer.id, consumer);
|
|
830
|
+
this._handleConsumer(consumer);
|
|
831
|
+
|
|
832
|
+
// If this is the first video Consumer and the Consumer for RTP probation
|
|
833
|
+
// has not yet been created, it's time to create it.
|
|
834
|
+
if (!this._probatorConsumerCreated && !videoConsumerForProbator && kind === 'video')
|
|
835
|
+
{
|
|
836
|
+
videoConsumerForProbator = consumer;
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
// Emit observer event.
|
|
840
|
+
this._observer.safeEmit('newconsumer', consumer);
|
|
841
|
+
|
|
842
|
+
task.resolve!(consumer);
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
catch (error)
|
|
846
|
+
{
|
|
847
|
+
for (const task of pendingConsumerTasks)
|
|
848
|
+
{
|
|
849
|
+
task.reject!(error as Error);
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
// If RTP probation must be handled, do it now.
|
|
854
|
+
if (videoConsumerForProbator)
|
|
855
|
+
{
|
|
856
|
+
try
|
|
857
|
+
{
|
|
858
|
+
const probatorRtpParameters =
|
|
859
|
+
ortc.generateProbatorRtpParameters(videoConsumerForProbator!.rtpParameters);
|
|
860
|
+
|
|
861
|
+
await this._handler.receive(
|
|
862
|
+
[ {
|
|
863
|
+
trackId : 'probator',
|
|
864
|
+
kind : 'video',
|
|
865
|
+
rtpParameters : probatorRtpParameters
|
|
866
|
+
} ]);
|
|
867
|
+
|
|
868
|
+
logger.debug('_createPendingConsumers() | Consumer for RTP probation created');
|
|
869
|
+
|
|
870
|
+
this._probatorConsumerCreated = true;
|
|
871
|
+
}
|
|
872
|
+
catch (error)
|
|
873
|
+
{
|
|
874
|
+
logger.error(
|
|
875
|
+
'_createPendingConsumers() | failed to create Consumer for RTP probation:%o',
|
|
876
|
+
error);
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
this._consumerCreationInProgress = false;
|
|
881
|
+
},
|
|
882
|
+
'transport._createPendingConsumers()')
|
|
883
|
+
.then(() =>
|
|
884
|
+
{
|
|
885
|
+
// There are pending Consumer tasks, enqueue their creation.
|
|
886
|
+
if (this._pendingConsumerTasks.length > 0)
|
|
887
|
+
{
|
|
888
|
+
this._createPendingConsumers();
|
|
889
|
+
}
|
|
890
|
+
})
|
|
891
|
+
// NOTE: We only get here when the await queue is closed.
|
|
892
|
+
.catch(() => {});
|
|
893
|
+
}
|
|
894
|
+
|
|
791
895
|
_handleHandler(): void
|
|
792
896
|
{
|
|
793
897
|
const handler = this._handler;
|