@webex/web-client-media-engine 1.40.3 → 1.40.5
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/dist/cjs/index.js +236 -185
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +236 -185
- package/dist/esm/index.js.map +1 -1
- package/dist/types/index.d.ts +3 -2
- package/package.json +3 -3
package/dist/esm/index.js
CHANGED
|
@@ -477,6 +477,134 @@ var media = /*#__PURE__*/Object.freeze({
|
|
|
477
477
|
ensureDevicePermissions: ensureDevicePermissions
|
|
478
478
|
});
|
|
479
479
|
|
|
480
|
+
var ErrorTypes;
|
|
481
|
+
(function (ErrorTypes) {
|
|
482
|
+
ErrorTypes["DEVICE_PERMISSION_DENIED"] = "DEVICE_PERMISSION_DENIED";
|
|
483
|
+
ErrorTypes["CREATE_CAMERA_TRACK_FAILED"] = "CREATE_CAMERA_TRACK_FAILED";
|
|
484
|
+
ErrorTypes["CREATE_MICROPHONE_TRACK_FAILED"] = "CREATE_MICROPHONE_TRACK_FAILED";
|
|
485
|
+
})(ErrorTypes || (ErrorTypes = {}));
|
|
486
|
+
/**
|
|
487
|
+
* Represents a WCME error, which contains error type and error message.
|
|
488
|
+
*/
|
|
489
|
+
class WcmeError {
|
|
490
|
+
/**
|
|
491
|
+
* Creates new error.
|
|
492
|
+
*
|
|
493
|
+
* @param type - Error type.
|
|
494
|
+
* @param message - Error message.
|
|
495
|
+
*/
|
|
496
|
+
constructor(type, message = '') {
|
|
497
|
+
this.type = type;
|
|
498
|
+
this.message = message;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* Creates a camera video track. Please note that the constraint params in second getUserMedia call would NOT take effect when:
|
|
503
|
+
*
|
|
504
|
+
* 1. Previous captured video track from the same device is not stopped .
|
|
505
|
+
* 2. Previous createCameraTrack() call for the same device is in progress.
|
|
506
|
+
*
|
|
507
|
+
* @param constructor - Constructor for the local camera track.
|
|
508
|
+
* @param constraints - Video device constraints.
|
|
509
|
+
* @returns A LocalTrack object or an error.
|
|
510
|
+
*/
|
|
511
|
+
function createCameraTrack(constructor, constraints) {
|
|
512
|
+
return __awaiter$1(this, void 0, void 0, function* () {
|
|
513
|
+
let stream;
|
|
514
|
+
try {
|
|
515
|
+
stream = yield getUserMedia({ video: Object.assign({}, constraints) });
|
|
516
|
+
}
|
|
517
|
+
catch (error) {
|
|
518
|
+
throw new WcmeError(ErrorTypes.CREATE_CAMERA_TRACK_FAILED, `Failed to create camera track ${error}`);
|
|
519
|
+
}
|
|
520
|
+
return new constructor(stream);
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* Creates a microphone audio track.
|
|
525
|
+
*
|
|
526
|
+
* @param constructor - Constructor for the local microphone track.
|
|
527
|
+
* @param constraints - Audio device constraints.
|
|
528
|
+
* @returns A LocalTrack object or an error.
|
|
529
|
+
*/
|
|
530
|
+
function createMicrophoneTrack(constructor, constraints) {
|
|
531
|
+
return __awaiter$1(this, void 0, void 0, function* () {
|
|
532
|
+
let stream;
|
|
533
|
+
try {
|
|
534
|
+
stream = yield getUserMedia({ audio: Object.assign({}, constraints) });
|
|
535
|
+
}
|
|
536
|
+
catch (error) {
|
|
537
|
+
throw new WcmeError(ErrorTypes.CREATE_MICROPHONE_TRACK_FAILED, `Failed to create microphone track ${error}`);
|
|
538
|
+
}
|
|
539
|
+
return new constructor(stream);
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
* Creates a display video track.
|
|
544
|
+
*
|
|
545
|
+
* @param constructor - Constructor for the local display track.
|
|
546
|
+
* @param videoContentHint - An optional parameters to give a hint for the content of the track.
|
|
547
|
+
* @returns A Promise that resolves to a LocalDisplayTrack.
|
|
548
|
+
*/
|
|
549
|
+
function createDisplayTrack(constructor, videoContentHint) {
|
|
550
|
+
return __awaiter$1(this, void 0, void 0, function* () {
|
|
551
|
+
const stream = yield getDisplayMedia({ video: true });
|
|
552
|
+
return new constructor(stream, videoContentHint);
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* Enumerates the media input and output devices available.
|
|
557
|
+
*
|
|
558
|
+
* @param deviceKind - Optional filter to return a specific device kind.
|
|
559
|
+
* @returns List of media devices in an array of MediaDeviceInfo objects.
|
|
560
|
+
*/
|
|
561
|
+
function getDevices(deviceKind) {
|
|
562
|
+
return __awaiter$1(this, void 0, void 0, function* () {
|
|
563
|
+
let devices;
|
|
564
|
+
try {
|
|
565
|
+
devices = yield ensureDevicePermissions([DeviceKind.AudioInput, DeviceKind.VideoInput], enumerateDevices);
|
|
566
|
+
}
|
|
567
|
+
catch (error) {
|
|
568
|
+
throw new WcmeError(ErrorTypes.DEVICE_PERMISSION_DENIED, 'Failed to ensure device permissions');
|
|
569
|
+
}
|
|
570
|
+
return devices.filter((v) => (deviceKind ? v.kind === deviceKind : true));
|
|
571
|
+
});
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* Helper function to get a list of microphone devices.
|
|
575
|
+
*
|
|
576
|
+
* @returns List of microphone devices in an array of MediaDeviceInfo objects.
|
|
577
|
+
*/
|
|
578
|
+
function getAudioInputDevices() {
|
|
579
|
+
return __awaiter$1(this, void 0, void 0, function* () {
|
|
580
|
+
return getDevices(DeviceKind.AudioInput);
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* Helper function to get a list of speaker devices.
|
|
585
|
+
*
|
|
586
|
+
* @returns List of speaker devices in an array of MediaDeviceInfo objects.
|
|
587
|
+
*/
|
|
588
|
+
function getAudioOutputDevices() {
|
|
589
|
+
return __awaiter$1(this, void 0, void 0, function* () {
|
|
590
|
+
return getDevices(DeviceKind.AudioOutput);
|
|
591
|
+
});
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* Helper function to get a list of camera devices.
|
|
595
|
+
*
|
|
596
|
+
* @returns List of camera devices in an array of MediaDeviceInfo objects.
|
|
597
|
+
*/
|
|
598
|
+
function getVideoInputDevices() {
|
|
599
|
+
return __awaiter$1(this, void 0, void 0, function* () {
|
|
600
|
+
return getDevices(DeviceKind.VideoInput);
|
|
601
|
+
});
|
|
602
|
+
}
|
|
603
|
+
/**
|
|
604
|
+
* Export the setOnDeviceChangeHandler method directly from the core lib.
|
|
605
|
+
*/
|
|
606
|
+
const { setOnDeviceChangeHandler } = media;
|
|
607
|
+
|
|
480
608
|
var events$1 = {exports: {}};
|
|
481
609
|
|
|
482
610
|
var R$1 = typeof Reflect === 'object' ? Reflect : null;
|
|
@@ -1227,6 +1355,25 @@ class LocalCameraTrack extends LocalTrack {
|
|
|
1227
1355
|
* Represents a local track for a display source.
|
|
1228
1356
|
*/
|
|
1229
1357
|
class LocalDisplayTrack extends LocalTrack {
|
|
1358
|
+
/**
|
|
1359
|
+
* Create a LocalDisplayTrack from the given values.
|
|
1360
|
+
*
|
|
1361
|
+
* @param stream - The MediaStream for this track.
|
|
1362
|
+
* @param videoContentHint - An optional content hint, describing the content of the track.
|
|
1363
|
+
*/
|
|
1364
|
+
constructor(stream, videoContentHint) {
|
|
1365
|
+
super(stream);
|
|
1366
|
+
this._videoContentHint = videoContentHint;
|
|
1367
|
+
this.underlyingTrack.contentHint = videoContentHint || '';
|
|
1368
|
+
}
|
|
1369
|
+
/**
|
|
1370
|
+
* Get the VideoContentHint for this track.
|
|
1371
|
+
*
|
|
1372
|
+
* @returns The VideoContentHint for this track.
|
|
1373
|
+
*/
|
|
1374
|
+
get videoContentHint() {
|
|
1375
|
+
return this._videoContentHint;
|
|
1376
|
+
}
|
|
1230
1377
|
}
|
|
1231
1378
|
|
|
1232
1379
|
/**
|
|
@@ -1235,130 +1382,6 @@ class LocalDisplayTrack extends LocalTrack {
|
|
|
1235
1382
|
class LocalMicrophoneTrack extends LocalTrack {
|
|
1236
1383
|
}
|
|
1237
1384
|
|
|
1238
|
-
var ErrorTypes;
|
|
1239
|
-
(function (ErrorTypes) {
|
|
1240
|
-
ErrorTypes["DEVICE_PERMISSION_DENIED"] = "DEVICE_PERMISSION_DENIED";
|
|
1241
|
-
ErrorTypes["CREATE_CAMERA_TRACK_FAILED"] = "CREATE_CAMERA_TRACK_FAILED";
|
|
1242
|
-
ErrorTypes["CREATE_MICROPHONE_TRACK_FAILED"] = "CREATE_MICROPHONE_TRACK_FAILED";
|
|
1243
|
-
})(ErrorTypes || (ErrorTypes = {}));
|
|
1244
|
-
/**
|
|
1245
|
-
* Represents a WCME error, which contains error type and error message.
|
|
1246
|
-
*/
|
|
1247
|
-
class WcmeError {
|
|
1248
|
-
/**
|
|
1249
|
-
* Creates new error.
|
|
1250
|
-
*
|
|
1251
|
-
* @param type - Error type.
|
|
1252
|
-
* @param message - Error message.
|
|
1253
|
-
*/
|
|
1254
|
-
constructor(type, message = '') {
|
|
1255
|
-
this.type = type;
|
|
1256
|
-
this.message = message;
|
|
1257
|
-
}
|
|
1258
|
-
}
|
|
1259
|
-
/**
|
|
1260
|
-
* Creates a camera video track. Please note that the constraint params in second getUserMedia call would NOT take effect when:
|
|
1261
|
-
*
|
|
1262
|
-
* 1. Previous captured video track from the same device is not stopped .
|
|
1263
|
-
* 2. Previous createCameraTrack() call for the same device is in progress.
|
|
1264
|
-
*
|
|
1265
|
-
* @param constraints - Video device constraints.
|
|
1266
|
-
* @returns A LocalTrack object or an error.
|
|
1267
|
-
*/
|
|
1268
|
-
function createCameraTrack(constraints) {
|
|
1269
|
-
return __awaiter$1(this, void 0, void 0, function* () {
|
|
1270
|
-
let stream;
|
|
1271
|
-
try {
|
|
1272
|
-
stream = yield getUserMedia({ video: Object.assign({}, constraints) });
|
|
1273
|
-
}
|
|
1274
|
-
catch (error) {
|
|
1275
|
-
throw new WcmeError(ErrorTypes.CREATE_CAMERA_TRACK_FAILED, `Failed to create camera track ${error}`);
|
|
1276
|
-
}
|
|
1277
|
-
return new LocalCameraTrack(stream);
|
|
1278
|
-
});
|
|
1279
|
-
}
|
|
1280
|
-
/**
|
|
1281
|
-
* Creates a microphone audio track.
|
|
1282
|
-
*
|
|
1283
|
-
* @param constraints - Audio device constraints.
|
|
1284
|
-
* @returns A LocalTrack object or an error.
|
|
1285
|
-
*/
|
|
1286
|
-
function createMicrophoneTrack(constraints) {
|
|
1287
|
-
return __awaiter$1(this, void 0, void 0, function* () {
|
|
1288
|
-
let stream;
|
|
1289
|
-
try {
|
|
1290
|
-
stream = yield getUserMedia({ audio: Object.assign({}, constraints) });
|
|
1291
|
-
}
|
|
1292
|
-
catch (error) {
|
|
1293
|
-
throw new WcmeError(ErrorTypes.CREATE_MICROPHONE_TRACK_FAILED, `Failed to create microphone track ${error}`);
|
|
1294
|
-
}
|
|
1295
|
-
return new LocalMicrophoneTrack(stream);
|
|
1296
|
-
});
|
|
1297
|
-
}
|
|
1298
|
-
/**
|
|
1299
|
-
* Creates a display video track.
|
|
1300
|
-
*
|
|
1301
|
-
* @returns A Promise that resolves to a LocalDisplayTrack.
|
|
1302
|
-
*/
|
|
1303
|
-
function createDisplayTrack() {
|
|
1304
|
-
return __awaiter$1(this, void 0, void 0, function* () {
|
|
1305
|
-
const stream = yield getDisplayMedia({ video: true });
|
|
1306
|
-
return new LocalDisplayTrack(stream);
|
|
1307
|
-
});
|
|
1308
|
-
}
|
|
1309
|
-
/**
|
|
1310
|
-
* Enumerates the media input and output devices available.
|
|
1311
|
-
*
|
|
1312
|
-
* @param deviceKind - Optional filter to return a specific device kind.
|
|
1313
|
-
* @returns List of media devices in an array of MediaDeviceInfo objects.
|
|
1314
|
-
*/
|
|
1315
|
-
function getDevices(deviceKind) {
|
|
1316
|
-
return __awaiter$1(this, void 0, void 0, function* () {
|
|
1317
|
-
let devices;
|
|
1318
|
-
try {
|
|
1319
|
-
devices = yield ensureDevicePermissions([DeviceKind.AudioInput, DeviceKind.VideoInput], enumerateDevices);
|
|
1320
|
-
}
|
|
1321
|
-
catch (error) {
|
|
1322
|
-
throw new WcmeError(ErrorTypes.DEVICE_PERMISSION_DENIED, 'Failed to ensure device permissions');
|
|
1323
|
-
}
|
|
1324
|
-
return devices.filter((v) => (deviceKind ? v.kind === deviceKind : true));
|
|
1325
|
-
});
|
|
1326
|
-
}
|
|
1327
|
-
/**
|
|
1328
|
-
* Helper function to get a list of microphone devices.
|
|
1329
|
-
*
|
|
1330
|
-
* @returns List of microphone devices in an array of MediaDeviceInfo objects.
|
|
1331
|
-
*/
|
|
1332
|
-
function getAudioInputDevices() {
|
|
1333
|
-
return __awaiter$1(this, void 0, void 0, function* () {
|
|
1334
|
-
return getDevices(DeviceKind.AudioInput);
|
|
1335
|
-
});
|
|
1336
|
-
}
|
|
1337
|
-
/**
|
|
1338
|
-
* Helper function to get a list of speaker devices.
|
|
1339
|
-
*
|
|
1340
|
-
* @returns List of speaker devices in an array of MediaDeviceInfo objects.
|
|
1341
|
-
*/
|
|
1342
|
-
function getAudioOutputDevices() {
|
|
1343
|
-
return __awaiter$1(this, void 0, void 0, function* () {
|
|
1344
|
-
return getDevices(DeviceKind.AudioOutput);
|
|
1345
|
-
});
|
|
1346
|
-
}
|
|
1347
|
-
/**
|
|
1348
|
-
* Helper function to get a list of camera devices.
|
|
1349
|
-
*
|
|
1350
|
-
* @returns List of camera devices in an array of MediaDeviceInfo objects.
|
|
1351
|
-
*/
|
|
1352
|
-
function getVideoInputDevices() {
|
|
1353
|
-
return __awaiter$1(this, void 0, void 0, function* () {
|
|
1354
|
-
return getDevices(DeviceKind.VideoInput);
|
|
1355
|
-
});
|
|
1356
|
-
}
|
|
1357
|
-
/**
|
|
1358
|
-
* Export the setOnDeviceChangeHandler method directly from the core lib.
|
|
1359
|
-
*/
|
|
1360
|
-
const { setOnDeviceChangeHandler } = media;
|
|
1361
|
-
|
|
1362
1385
|
// Overall connection state (based on the ICE and DTLS connection states)
|
|
1363
1386
|
var ConnectionState;
|
|
1364
1387
|
(function (ConnectionState) {
|
|
@@ -5702,11 +5725,12 @@ function compareStreamIds(id1, id2) {
|
|
|
5702
5725
|
}
|
|
5703
5726
|
|
|
5704
5727
|
class SourceIndicationMsg {
|
|
5705
|
-
constructor(seqNum, numTotalSources, numLiveSources, sources) {
|
|
5728
|
+
constructor(seqNum, numTotalSources, numLiveSources, sources, videoContentHint) {
|
|
5706
5729
|
this.seqNum = seqNum;
|
|
5707
5730
|
this.numTotalSources = numTotalSources;
|
|
5708
5731
|
this.numLiveSources = numLiveSources;
|
|
5709
5732
|
this.sources = sources;
|
|
5733
|
+
this.videoContentHint = videoContentHint;
|
|
5710
5734
|
}
|
|
5711
5735
|
sourcesToString() {
|
|
5712
5736
|
return this.sources
|
|
@@ -5802,13 +5826,13 @@ class JmpSession extends EventEmitter$3 {
|
|
|
5802
5826
|
this.logger.warn(`Retransmits for message expired: ${expiredJmpMsg}`);
|
|
5803
5827
|
});
|
|
5804
5828
|
}
|
|
5805
|
-
updateSourceIndication(numTotalSources, numLiveSources, sources) {
|
|
5829
|
+
updateSourceIndication(numTotalSources, numLiveSources, sources, videoContentHint) {
|
|
5806
5830
|
var _a;
|
|
5807
5831
|
const filteredSources = sources.filter((source) => {
|
|
5808
5832
|
var _a;
|
|
5809
5833
|
return (_a = this.lastReceivedScr) === null || _a === void 0 ? void 0 : _a.requests.some((req) => req.ids.find((streamId) => compareStreamIds(streamId, source.id)));
|
|
5810
5834
|
});
|
|
5811
|
-
const sourceIndicationMsg = new SourceIndicationMsg(this.currSourceIndicationSeqNum++, numTotalSources, numLiveSources, filteredSources);
|
|
5835
|
+
const sourceIndicationMsg = new SourceIndicationMsg(this.currSourceIndicationSeqNum++, numTotalSources, numLiveSources, filteredSources, videoContentHint);
|
|
5812
5836
|
const jmpMsg = new JmpMsg(this.mediaFamily, this.mediaContent, {
|
|
5813
5837
|
msgType: JmpMsgType.SourceIndication,
|
|
5814
5838
|
payload: sourceIndicationMsg,
|
|
@@ -9194,23 +9218,58 @@ class SsrcEgressStreamSignaler {
|
|
|
9194
9218
|
this.streamIds = [];
|
|
9195
9219
|
}
|
|
9196
9220
|
signalStreams(simulcastEnabled, rtxEnabled, mLine) {
|
|
9221
|
+
var _a;
|
|
9197
9222
|
mLine.rids = [];
|
|
9198
9223
|
mLine.simulcast = undefined;
|
|
9199
|
-
mLine.ssrcs = [];
|
|
9200
|
-
mLine.ssrcGroups = [];
|
|
9201
9224
|
mLine.extMaps = mLine.extMaps.filter((extMapLine) => !/^urn:ietf:params:rtp-hdrext:sdes:(?:mid|rtp-stream-id|repaired-rtp-stream-id)$/.test(extMapLine.uri));
|
|
9202
|
-
|
|
9203
|
-
|
|
9204
|
-
|
|
9205
|
-
const
|
|
9206
|
-
|
|
9207
|
-
|
|
9208
|
-
|
|
9209
|
-
|
|
9225
|
+
const numStreams = simulcastEnabled ? 3 : 1;
|
|
9226
|
+
if (!this.streamIds.length) {
|
|
9227
|
+
if (mLine.ssrcs.length) {
|
|
9228
|
+
const ssrcs = [...new Set(mLine.ssrcs.map((ssrcLine) => ssrcLine.ssrcId))];
|
|
9229
|
+
mLine.ssrcGroups.forEach((sg) => {
|
|
9230
|
+
if (!sg.ssrcs.every((ssrc) => ssrcs.includes(ssrc))) {
|
|
9231
|
+
throw new Error('SSRC present in SSRC groups is missing from SSRC lines');
|
|
9232
|
+
}
|
|
9233
|
+
});
|
|
9234
|
+
const rtxSsrcGroups = mLine.ssrcGroups.filter((sg) => sg.semantics === 'FID');
|
|
9235
|
+
if (rtxSsrcGroups.length && rtxSsrcGroups.length !== numStreams) {
|
|
9236
|
+
throw new Error(`Expect ${numStreams} RTX SSRC groups, got ${rtxSsrcGroups.length}`);
|
|
9210
9237
|
}
|
|
9211
|
-
|
|
9212
|
-
|
|
9238
|
+
rtxSsrcGroups.forEach((sg) => {
|
|
9239
|
+
this.streamIds.push({
|
|
9240
|
+
ssrc: sg.ssrcs[0],
|
|
9241
|
+
rtxSsrc: sg.ssrcs[1],
|
|
9242
|
+
});
|
|
9243
|
+
});
|
|
9244
|
+
const simulcastSsrcs = (_a = mLine.ssrcGroups.find((sg) => sg.semantics === 'SIM')) === null || _a === void 0 ? void 0 : _a.ssrcs;
|
|
9245
|
+
if (simulcastSsrcs) {
|
|
9246
|
+
if (simulcastSsrcs.length !== numStreams ||
|
|
9247
|
+
!this.streamIds.every((streamId) => simulcastSsrcs.includes(streamId.ssrc))) {
|
|
9248
|
+
throw new Error('SSRCs in simulcast SSRC group do not match primary SSRCs in RTX SSRC groups');
|
|
9249
|
+
}
|
|
9250
|
+
this.streamIds.sort((a, b) => simulcastSsrcs.indexOf(a.ssrc) - simulcastSsrcs.indexOf(b.ssrc));
|
|
9251
|
+
}
|
|
9252
|
+
else if (rtxSsrcGroups.length > 1) {
|
|
9253
|
+
throw new Error('Multiple RTX SSRC groups but no simulcast SSRC group found');
|
|
9254
|
+
}
|
|
9255
|
+
if (!this.streamIds.length) {
|
|
9256
|
+
this.streamIds.push({ ssrc: ssrcs[0] });
|
|
9257
|
+
}
|
|
9258
|
+
}
|
|
9259
|
+
else {
|
|
9260
|
+
[...Array(numStreams).keys()].forEach(() => {
|
|
9261
|
+
const newStreamId = {
|
|
9262
|
+
ssrc: generateSsrc(),
|
|
9263
|
+
};
|
|
9264
|
+
if (rtxEnabled) {
|
|
9265
|
+
newStreamId.rtxSsrc = generateSsrc();
|
|
9266
|
+
}
|
|
9267
|
+
this.streamIds.push(newStreamId);
|
|
9268
|
+
});
|
|
9269
|
+
}
|
|
9213
9270
|
}
|
|
9271
|
+
mLine.ssrcs = [];
|
|
9272
|
+
mLine.ssrcGroups = [];
|
|
9214
9273
|
this.streamIds.forEach((streamId) => {
|
|
9215
9274
|
const rtpSsrc = streamId.ssrc;
|
|
9216
9275
|
mLine.addLine(new SsrcLine(rtpSsrc, 'cname', `${rtpSsrc}-cname`));
|
|
@@ -9678,6 +9737,15 @@ function toMediaStreamTrackKind(mediaType) {
|
|
|
9678
9737
|
? MediaStreamTrackKind.Video
|
|
9679
9738
|
: MediaStreamTrackKind.Audio;
|
|
9680
9739
|
}
|
|
9740
|
+
function webRtcVideoContentHintToJmpVideoContentHint(hint) {
|
|
9741
|
+
if (hint === 'motion') {
|
|
9742
|
+
return 'motion';
|
|
9743
|
+
}
|
|
9744
|
+
if (hint === 'detail') {
|
|
9745
|
+
return 'sharpness';
|
|
9746
|
+
}
|
|
9747
|
+
return undefined;
|
|
9748
|
+
}
|
|
9681
9749
|
function toMediaFamily(kind) {
|
|
9682
9750
|
if (kind === MediaStreamTrackKind.Video) {
|
|
9683
9751
|
return MediaFamily.Video;
|
|
@@ -9926,24 +9994,8 @@ class MultistreamConnection extends EventEmitter {
|
|
|
9926
9994
|
const dataChannel = this.pc.createDataChannel('datachannel', {});
|
|
9927
9995
|
dataChannel.onopen = (e) => {
|
|
9928
9996
|
logger.info('DataChannel opened: ', e);
|
|
9929
|
-
this.sendTransceivers.forEach((
|
|
9930
|
-
|
|
9931
|
-
if (track) {
|
|
9932
|
-
if (getMediaFamily(mediaType) === MediaFamily.Audio) {
|
|
9933
|
-
this.sendSourceIndication(mediaType, +!track.muted);
|
|
9934
|
-
}
|
|
9935
|
-
else {
|
|
9936
|
-
const signaler = this.streamSignalerManager.getEgressStreamSignalerOrThrow(transceiver.mid);
|
|
9937
|
-
const state = track.muted ? 'avatar' : 'live';
|
|
9938
|
-
const sources = signaler
|
|
9939
|
-
.getSenderIds()
|
|
9940
|
-
.map((id) => ({ id, state, csi: transceiver.csi }));
|
|
9941
|
-
this.sendSourceIndication(mediaType, +!track.muted, sources);
|
|
9942
|
-
}
|
|
9943
|
-
}
|
|
9944
|
-
else {
|
|
9945
|
-
this.sendSourceIndication(mediaType, 0);
|
|
9946
|
-
}
|
|
9997
|
+
[...this.sendTransceivers.keys()].forEach((mediaType) => {
|
|
9998
|
+
this.maybeSendSourceIndication(mediaType);
|
|
9947
9999
|
});
|
|
9948
10000
|
logger.info(`Flushing pending JMP task queue`);
|
|
9949
10001
|
this.pendingJmpTasks.forEach((t) => t());
|
|
@@ -9992,11 +10044,31 @@ class MultistreamConnection extends EventEmitter {
|
|
|
9992
10044
|
});
|
|
9993
10045
|
this.pc.close();
|
|
9994
10046
|
}
|
|
9995
|
-
|
|
10047
|
+
maybeSendSourceIndication(mediaType) {
|
|
10048
|
+
var _a;
|
|
10049
|
+
const transceiver = this.getSendTransceiverOrThrow(mediaType);
|
|
10050
|
+
const numLiveSources = ((_a = transceiver.publishedTrack) === null || _a === void 0 ? void 0 : _a.muted) === false ? 1 : 0;
|
|
10051
|
+
if (getMediaFamily(mediaType) === MediaFamily.Video) {
|
|
10052
|
+
const sources = this.getVideoSources(mediaType);
|
|
10053
|
+
if (sources === null) {
|
|
10054
|
+
return;
|
|
10055
|
+
}
|
|
10056
|
+
let webRtcVideoContentHint;
|
|
10057
|
+
if (transceiver.publishedTrack instanceof LocalDisplayTrack) {
|
|
10058
|
+
webRtcVideoContentHint = transceiver.publishedTrack.videoContentHint;
|
|
10059
|
+
}
|
|
10060
|
+
this.sendSourceIndication(mediaType, numLiveSources, sources, webRtcVideoContentHintToJmpVideoContentHint(webRtcVideoContentHint));
|
|
10061
|
+
}
|
|
10062
|
+
else {
|
|
10063
|
+
this.sendSourceIndication(mediaType, numLiveSources);
|
|
10064
|
+
}
|
|
10065
|
+
}
|
|
10066
|
+
sendSourceIndication(mediaType, numLiveSources, sources = [], videoContentHint = undefined) {
|
|
9996
10067
|
var _a;
|
|
9997
10068
|
const task = () => {
|
|
9998
10069
|
var _a;
|
|
9999
|
-
(_a = this.jmpSessions
|
|
10070
|
+
(_a = this.jmpSessions
|
|
10071
|
+
.get(mediaType)) === null || _a === void 0 ? void 0 : _a.updateSourceIndication(1, numLiveSources, sources, videoContentHint);
|
|
10000
10072
|
};
|
|
10001
10073
|
if (((_a = this.dataChannel) === null || _a === void 0 ? void 0 : _a.readyState) === 'open') {
|
|
10002
10074
|
task();
|
|
@@ -10041,24 +10113,9 @@ class MultistreamConnection extends EventEmitter {
|
|
|
10041
10113
|
});
|
|
10042
10114
|
}
|
|
10043
10115
|
addTrackListeners(mediaType, track) {
|
|
10044
|
-
const onTrackResolutionChange = () =>
|
|
10045
|
-
const sources = this.getVideoSources(mediaType);
|
|
10046
|
-
if (sources != null) {
|
|
10047
|
-
this.sendSourceIndication(mediaType, 1, sources);
|
|
10048
|
-
}
|
|
10049
|
-
};
|
|
10116
|
+
const onTrackResolutionChange = () => this.maybeSendSourceIndication(mediaType);
|
|
10050
10117
|
track.on(LocalTrack.Events.TrackConstraintsChange, onTrackResolutionChange);
|
|
10051
|
-
const onTrackMute = (
|
|
10052
|
-
if (getMediaFamily(mediaType) === MediaFamily.Audio) {
|
|
10053
|
-
this.sendSourceIndication(mediaType, +!event.trackState.muted);
|
|
10054
|
-
}
|
|
10055
|
-
else {
|
|
10056
|
-
const sources = this.getVideoSources(mediaType);
|
|
10057
|
-
if (sources != null) {
|
|
10058
|
-
this.sendSourceIndication(mediaType, +!event.trackState.muted, sources);
|
|
10059
|
-
}
|
|
10060
|
-
}
|
|
10061
|
-
};
|
|
10118
|
+
const onTrackMute = () => this.maybeSendSourceIndication(mediaType);
|
|
10062
10119
|
track.on(LocalTrack.Events.Muted, onTrackMute);
|
|
10063
10120
|
const onTrackPublish = (event) => {
|
|
10064
10121
|
if (!event.isPublished) {
|
|
@@ -10066,14 +10123,8 @@ class MultistreamConnection extends EventEmitter {
|
|
|
10066
10123
|
track.off(LocalTrack.Events.PublishedStateUpdate, onTrackPublish);
|
|
10067
10124
|
track.off(LocalTrack.Events.TrackConstraintsChange, onTrackResolutionChange);
|
|
10068
10125
|
}
|
|
10069
|
-
if (
|
|
10070
|
-
this.
|
|
10071
|
-
}
|
|
10072
|
-
else {
|
|
10073
|
-
const sources = this.getVideoSources(mediaType);
|
|
10074
|
-
if (sources != null) {
|
|
10075
|
-
this.sendSourceIndication(mediaType, +event.isPublished, sources);
|
|
10076
|
-
}
|
|
10126
|
+
if (!track.muted) {
|
|
10127
|
+
this.maybeSendSourceIndication(mediaType);
|
|
10077
10128
|
}
|
|
10078
10129
|
};
|
|
10079
10130
|
track.on(LocalTrack.Events.PublishedStateUpdate, onTrackPublish);
|
|
@@ -10365,7 +10416,7 @@ class MultistreamConnection extends EventEmitter {
|
|
|
10365
10416
|
}
|
|
10366
10417
|
renewPeerConnection(userOptions) {
|
|
10367
10418
|
if (userOptions) {
|
|
10368
|
-
this.options = Object.assign(Object.assign({},
|
|
10419
|
+
this.options = Object.assign(Object.assign({}, this.options), userOptions);
|
|
10369
10420
|
}
|
|
10370
10421
|
logger.info(`Renewing multistream connection with options ${JSON.stringify(this.options)}`);
|
|
10371
10422
|
this.clearMids();
|