@webex/web-client-media-engine 3.11.0 → 3.11.2

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/esm/index.js CHANGED
@@ -486,6 +486,7 @@ var WebrtcCoreErrorType;
486
486
  (function (WebrtcCoreErrorType) {
487
487
  WebrtcCoreErrorType["DEVICE_PERMISSION_DENIED"] = "DEVICE_PERMISSION_DENIED";
488
488
  WebrtcCoreErrorType["CREATE_STREAM_FAILED"] = "CREATE_STREAM_FAILED";
489
+ WebrtcCoreErrorType["ADD_EFFECT_FAILED"] = "ADD_EFFECT_FAILED";
489
490
  })(WebrtcCoreErrorType || (WebrtcCoreErrorType = {}));
490
491
  /**
491
492
  * Represents a WebRTC core error, which contains error type and error message.
@@ -1246,11 +1247,12 @@ class _Stream {
1246
1247
  _a$1$1 = StreamEventNames.MuteStateChange, _b$1 = StreamEventNames.Ended;
1247
1248
  const Stream = AddEvents(_Stream);
1248
1249
 
1249
- var _a$6, _b;
1250
+ var _a$6, _b, _c;
1250
1251
  var LocalStreamEventNames;
1251
1252
  (function (LocalStreamEventNames) {
1252
1253
  LocalStreamEventNames["ConstraintsChange"] = "constraints-change";
1253
1254
  LocalStreamEventNames["OutputTrackChange"] = "output-track-change";
1255
+ LocalStreamEventNames["EffectAdded"] = "effect-added";
1254
1256
  })(LocalStreamEventNames || (LocalStreamEventNames = {}));
1255
1257
  /**
1256
1258
  * A stream which originates on the local device.
@@ -1265,6 +1267,7 @@ class _LocalStream extends Stream {
1265
1267
  super(stream);
1266
1268
  this[_a$6] = new TypedEvent$1();
1267
1269
  this[_b] = new TypedEvent$1();
1270
+ this[_c] = new TypedEvent$1();
1268
1271
  this.effects = [];
1269
1272
  this.loadingEffects = new Map();
1270
1273
  this.inputStream = stream;
@@ -1278,11 +1281,30 @@ class _LocalStream extends Stream {
1278
1281
  get inputTrack() {
1279
1282
  return this.inputStream.getTracks()[0];
1280
1283
  }
1284
+ /**
1285
+ * @inheritdoc
1286
+ */
1287
+ handleTrackMuted() {
1288
+ if (this.inputTrack.enabled) {
1289
+ super.handleTrackMuted();
1290
+ }
1291
+ }
1292
+ /**
1293
+ * @inheritdoc
1294
+ */
1295
+ handleTrackUnmuted() {
1296
+ if (this.inputTrack.enabled) {
1297
+ super.handleTrackUnmuted();
1298
+ }
1299
+ }
1281
1300
  /**
1282
1301
  * @inheritdoc
1283
1302
  */
1284
1303
  get muted() {
1285
- return !this.inputTrack.enabled;
1304
+ // Calls to `setMuted` will only affect the "enabled" state, but there are specific cases in
1305
+ // which the browser may mute the track, which will affect the "muted" state but not the
1306
+ // "enabled" state, e.g. minimizing a shared window or unplugging a shared screen.
1307
+ return !this.inputTrack.enabled || this.inputTrack.muted;
1286
1308
  }
1287
1309
  /**
1288
1310
  * Set the mute state of this stream.
@@ -1293,7 +1315,9 @@ class _LocalStream extends Stream {
1293
1315
  if (this.inputTrack.enabled === isMuted) {
1294
1316
  this.inputTrack.enabled = !isMuted;
1295
1317
  // setting `enabled` will not automatically emit MuteStateChange, so we emit it here
1296
- this[StreamEventNames.MuteStateChange].emit(isMuted);
1318
+ if (!this.inputTrack.muted) {
1319
+ this[StreamEventNames.MuteStateChange].emit(isMuted);
1320
+ }
1297
1321
  }
1298
1322
  }
1299
1323
  /**
@@ -1356,55 +1380,110 @@ class _LocalStream extends Stream {
1356
1380
  /**
1357
1381
  * Adds an effect to a local stream.
1358
1382
  *
1359
- * @param name - The name of the effect.
1360
1383
  * @param effect - The effect to add.
1361
1384
  */
1362
- addEffect(name, effect) {
1385
+ addEffect(effect) {
1363
1386
  return __awaiter$2(this, void 0, void 0, function* () {
1364
- // Load the effect
1365
- this.loadingEffects.set(name, effect);
1366
- const outputTrack = yield effect.load(this.outputTrack);
1367
- // Check that the loaded effect is the latest one and dispose if not
1368
- if (effect !== this.loadingEffects.get(name)) {
1387
+ // Check if the effect has already been added.
1388
+ if (this.effects.some((e) => e.id === effect.id)) {
1389
+ return;
1390
+ }
1391
+ // Load the effect. Because loading is asynchronous, keep track of the loading effects.
1392
+ this.loadingEffects.set(effect.kind, effect);
1393
+ yield effect.load(this.outputTrack);
1394
+ // After loading, check whether or not we still want to use this effect. If another effect of
1395
+ // the same kind was added while this effect was loading, we only want to use the latest effect,
1396
+ // so dispose this one. If the effects list was cleared while this effect was loading, also
1397
+ // dispose it.
1398
+ if (effect !== this.loadingEffects.get(effect.kind)) {
1369
1399
  yield effect.dispose();
1370
- throw new Error(`Effect "${name}" not required after loading`);
1400
+ throw new WebrtcCoreError(WebrtcCoreErrorType.ADD_EFFECT_FAILED, `Another effect with kind ${effect.kind} was added while effect ${effect.id} was loading, or the effects list was cleared.`);
1371
1401
  }
1372
- // Use the effect
1373
- this.loadingEffects.delete(name);
1374
- this.effects.push({ name, effect });
1375
- this.changeOutputTrack(outputTrack);
1376
- // When the effect's track is updated, update the next effect or output stream.
1377
- // TODO: using EffectEvent.TrackUpdated will cause the entire web-media-effects lib to be built
1378
- // and makes the size of the webrtc-core build much larger, so we use type assertion here as a
1379
- // temporary workaround.
1380
- effect.on('track-updated', (track) => {
1381
- var _c;
1382
- const effectIndex = this.effects.findIndex((e) => e.name === name);
1402
+ this.loadingEffects.delete(effect.kind);
1403
+ /**
1404
+ * Handle when the effect's output track has been changed. This will update the input of the
1405
+ * next effect in the effects list of the output of the stream.
1406
+ *
1407
+ * @param track - The new output track of the effect.
1408
+ */
1409
+ const handleEffectTrackUpdated = (track) => {
1410
+ var _d;
1411
+ const effectIndex = this.effects.findIndex((e) => e.id === effect.id);
1383
1412
  if (effectIndex === this.effects.length - 1) {
1384
1413
  this.changeOutputTrack(track);
1385
1414
  }
1415
+ else if (effectIndex >= 0) {
1416
+ (_d = this.effects[effectIndex + 1]) === null || _d === void 0 ? void 0 : _d.replaceInputTrack(track);
1417
+ }
1386
1418
  else {
1387
- (_c = this.effects[effectIndex + 1]) === null || _c === void 0 ? void 0 : _c.effect.replaceInputTrack(track);
1419
+ logger$3.error(`Effect with ID ${effect.id} not found in effects list.`);
1388
1420
  }
1389
- });
1421
+ };
1422
+ /**
1423
+ * Handle when the effect has been disposed. This will remove all event listeners from the
1424
+ * effect.
1425
+ */
1426
+ const handleEffectDisposed = () => {
1427
+ effect.off('track-updated', handleEffectTrackUpdated);
1428
+ effect.off('disposed', handleEffectDisposed);
1429
+ };
1430
+ // TODO: using EffectEvent.TrackUpdated or EffectEvent.Disposed will cause the entire
1431
+ // web-media-effects lib to be rebuilt and inflates the size of the webrtc-core build, so
1432
+ // we use type assertion here as a temporary workaround.
1433
+ effect.on('track-updated', handleEffectTrackUpdated);
1434
+ effect.on('disposed', handleEffectDisposed);
1435
+ // Add the effect to the effects list. If an effect of the same kind has already been added,
1436
+ // dispose the existing effect and replace it with the new effect. If the existing effect was
1437
+ // enabled, also enable the new effect.
1438
+ const existingEffectIndex = this.effects.findIndex((e) => e.kind === effect.kind);
1439
+ if (existingEffectIndex >= 0) {
1440
+ const [existingEffect] = this.effects.splice(existingEffectIndex, 1, effect);
1441
+ if (existingEffect.isEnabled) {
1442
+ // If the existing effect is not the first effect in the effects list, then the input of the
1443
+ // new effect should be the output of the previous effect in the effects list. We know the
1444
+ // output track of the previous effect must exist because it must have been loaded (and all
1445
+ // loaded effects have an output track).
1446
+ const inputTrack = existingEffectIndex === 0
1447
+ ? this.inputTrack
1448
+ : this.effects[existingEffectIndex - 1].getOutputTrack();
1449
+ yield effect.replaceInputTrack(inputTrack);
1450
+ // Enabling the new effect will trigger the track-updated event, which will handle the new
1451
+ // effect's updated output track.
1452
+ yield effect.enable();
1453
+ }
1454
+ yield existingEffect.dispose();
1455
+ }
1456
+ else {
1457
+ this.effects.push(effect);
1458
+ }
1459
+ // Emit an event with the effect so others can listen to the effect events.
1460
+ this[LocalStreamEventNames.EffectAdded].emit(effect);
1390
1461
  });
1391
1462
  }
1392
1463
  /**
1393
- * Get an effect from the effects list.
1464
+ * Get an effect from the effects list by ID.
1394
1465
  *
1395
- * @param name - The name of the effect you want to get.
1466
+ * @param id - The id of the effect you want to get.
1396
1467
  * @returns The effect or undefined.
1397
1468
  */
1398
- getEffect(name) {
1399
- var _c;
1400
- return (_c = this.effects.find((e) => e.name === name)) === null || _c === void 0 ? void 0 : _c.effect;
1469
+ getEffectById(id) {
1470
+ return this.effects.find((effect) => effect.id === id);
1471
+ }
1472
+ /**
1473
+ * Get an effect from the effects list by kind.
1474
+ *
1475
+ * @param kind - The kind of the effect you want to get.
1476
+ * @returns The effect or undefined.
1477
+ */
1478
+ getEffectByKind(kind) {
1479
+ return this.effects.find((effect) => effect.kind === kind);
1401
1480
  }
1402
1481
  /**
1403
1482
  * Get all the effects from the effects list.
1404
1483
  *
1405
- * @returns A list of effect items, each containing the name and the effect itself.
1484
+ * @returns A list of effects.
1406
1485
  */
1407
- getAllEffects() {
1486
+ getEffects() {
1408
1487
  return this.effects;
1409
1488
  }
1410
1489
  /**
@@ -1416,13 +1495,13 @@ class _LocalStream extends Stream {
1416
1495
  // Dispose of any effects currently in use
1417
1496
  if (this.effects.length > 0) {
1418
1497
  this.changeOutputTrack(this.inputTrack);
1419
- yield Promise.all(this.effects.map((item) => item.effect.dispose()));
1498
+ yield Promise.all(this.effects.map((effect) => effect.dispose()));
1420
1499
  this.effects = [];
1421
1500
  }
1422
1501
  });
1423
1502
  }
1424
1503
  }
1425
- _a$6 = LocalStreamEventNames.ConstraintsChange, _b = LocalStreamEventNames.OutputTrackChange;
1504
+ _a$6 = LocalStreamEventNames.ConstraintsChange, _b = LocalStreamEventNames.OutputTrackChange, _c = LocalStreamEventNames.EffectAdded;
1426
1505
  const LocalStream = AddEvents(_LocalStream);
1427
1506
 
1428
1507
  /**
@@ -6166,6 +6245,80 @@ Logger$1.useDefaults({
6166
6245
  },
6167
6246
  });
6168
6247
 
6248
+ var MediaFamily;
6249
+ (function (MediaFamily) {
6250
+ MediaFamily["Audio"] = "AUDIO";
6251
+ MediaFamily["Video"] = "VIDEO";
6252
+ })(MediaFamily || (MediaFamily = {}));
6253
+ var MediaContent;
6254
+ (function (MediaContent) {
6255
+ MediaContent["Main"] = "MAIN";
6256
+ MediaContent["Slides"] = "SLIDES";
6257
+ })(MediaContent || (MediaContent = {}));
6258
+ var Policy;
6259
+ (function (Policy) {
6260
+ Policy["ActiveSpeaker"] = "active-speaker";
6261
+ Policy["ReceiverSelected"] = "receiver-selected";
6262
+ })(Policy || (Policy = {}));
6263
+ var MediaType;
6264
+ (function (MediaType) {
6265
+ MediaType["VideoMain"] = "VIDEO-MAIN";
6266
+ MediaType["VideoSlides"] = "VIDEO-SLIDES";
6267
+ MediaType["AudioMain"] = "AUDIO-MAIN";
6268
+ MediaType["AudioSlides"] = "AUDIO-SLIDES";
6269
+ })(MediaType || (MediaType = {}));
6270
+
6271
+ function randomInteger(min, max) {
6272
+ return Math.floor(Math.random() * (max - min + 1)) + min;
6273
+ }
6274
+ function generateSceneId() {
6275
+ return randomInteger(0, 0x7fffff);
6276
+ }
6277
+ function generateCsi(mediaFamily, sceneId) {
6278
+ let av;
6279
+ if (mediaFamily === MediaFamily.Audio) {
6280
+ av = 0;
6281
+ }
6282
+ else {
6283
+ av = 1;
6284
+ }
6285
+ return (sceneId << 8) | av;
6286
+ }
6287
+ function getMediaType(mediaFamily, mediaContent) {
6288
+ if (mediaFamily === MediaFamily.Video && mediaContent === MediaContent.Main) {
6289
+ return MediaType.VideoMain;
6290
+ }
6291
+ if (mediaFamily === MediaFamily.Video && mediaContent === MediaContent.Slides) {
6292
+ return MediaType.VideoSlides;
6293
+ }
6294
+ if (mediaFamily === MediaFamily.Audio && mediaContent === MediaContent.Main) {
6295
+ return MediaType.AudioMain;
6296
+ }
6297
+ return MediaType.AudioSlides;
6298
+ }
6299
+ function getMediaFamily(mediaType) {
6300
+ return [MediaType.VideoMain, MediaType.VideoSlides].includes(mediaType)
6301
+ ? MediaFamily.Video
6302
+ : MediaFamily.Audio;
6303
+ }
6304
+ function getMediaContent(mediaType) {
6305
+ return [MediaType.VideoMain, MediaType.AudioMain].includes(mediaType)
6306
+ ? MediaContent.Main
6307
+ : MediaContent.Slides;
6308
+ }
6309
+ const truthyOrZero = (value) => value === 0 || value;
6310
+ function arraysAreEqual(left, right, predicate) {
6311
+ if (left.length !== right.length) {
6312
+ return false;
6313
+ }
6314
+ for (let i = 0; i < left.length; i += 1) {
6315
+ if (!predicate(left[i], right[i])) {
6316
+ return false;
6317
+ }
6318
+ }
6319
+ return true;
6320
+ }
6321
+
6169
6322
  class ActiveSpeakerInfo {
6170
6323
  constructor(priority, crossPriorityDuplication, crossPolicyDuplication, preferLiveVideo, namedMediaGroups) {
6171
6324
  this.priority = priority;
@@ -6189,15 +6342,7 @@ function areNamedMediaGroupArraysEqual(left, right) {
6189
6342
  if (left === undefined || right === undefined) {
6190
6343
  return left === right;
6191
6344
  }
6192
- if (left.length !== right.length) {
6193
- return false;
6194
- }
6195
- for (let i = 0; i < left.length; i += 1) {
6196
- if (left[i] !== right[i]) {
6197
- return false;
6198
- }
6199
- }
6200
- return true;
6345
+ return arraysAreEqual(left, right, (l, r) => l.type === r.type && l.value === r.value);
6201
6346
  }
6202
6347
  function areActiveSpeakerInfosEqual(left, right) {
6203
6348
  return (left.priority === right.priority &&
@@ -6399,69 +6544,6 @@ function areReceiverSelectedInfosEqual(left, right) {
6399
6544
  return left.csi === right.csi;
6400
6545
  }
6401
6546
 
6402
- var MediaFamily;
6403
- (function (MediaFamily) {
6404
- MediaFamily["Audio"] = "AUDIO";
6405
- MediaFamily["Video"] = "VIDEO";
6406
- })(MediaFamily || (MediaFamily = {}));
6407
- var MediaContent;
6408
- (function (MediaContent) {
6409
- MediaContent["Main"] = "MAIN";
6410
- MediaContent["Slides"] = "SLIDES";
6411
- })(MediaContent || (MediaContent = {}));
6412
- var Policy;
6413
- (function (Policy) {
6414
- Policy["ActiveSpeaker"] = "active-speaker";
6415
- Policy["ReceiverSelected"] = "receiver-selected";
6416
- })(Policy || (Policy = {}));
6417
- var MediaType;
6418
- (function (MediaType) {
6419
- MediaType["VideoMain"] = "VIDEO-MAIN";
6420
- MediaType["VideoSlides"] = "VIDEO-SLIDES";
6421
- MediaType["AudioMain"] = "AUDIO-MAIN";
6422
- MediaType["AudioSlides"] = "AUDIO-SLIDES";
6423
- })(MediaType || (MediaType = {}));
6424
-
6425
- function randomInteger(min, max) {
6426
- return Math.floor(Math.random() * (max - min + 1)) + min;
6427
- }
6428
- function generateSceneId() {
6429
- return randomInteger(0, 0x7fffff);
6430
- }
6431
- function generateCsi(mediaFamily, sceneId) {
6432
- let av;
6433
- if (mediaFamily === MediaFamily.Audio) {
6434
- av = 0;
6435
- }
6436
- else {
6437
- av = 1;
6438
- }
6439
- return (sceneId << 8) | av;
6440
- }
6441
- function getMediaType(mediaFamily, mediaContent) {
6442
- if (mediaFamily === MediaFamily.Video && mediaContent === MediaContent.Main) {
6443
- return MediaType.VideoMain;
6444
- }
6445
- if (mediaFamily === MediaFamily.Video && mediaContent === MediaContent.Slides) {
6446
- return MediaType.VideoSlides;
6447
- }
6448
- if (mediaFamily === MediaFamily.Audio && mediaContent === MediaContent.Main) {
6449
- return MediaType.AudioMain;
6450
- }
6451
- return MediaType.AudioSlides;
6452
- }
6453
- function getMediaFamily(mediaType) {
6454
- return [MediaType.VideoMain, MediaType.VideoSlides].includes(mediaType)
6455
- ? MediaFamily.Video
6456
- : MediaFamily.Audio;
6457
- }
6458
- function getMediaContent(mediaType) {
6459
- return [MediaType.VideoMain, MediaType.AudioMain].includes(mediaType)
6460
- ? MediaContent.Main
6461
- : MediaContent.Slides;
6462
- }
6463
- const truthyOrZero = (value) => value === 0 || value;
6464
-
6465
6547
  class SourceAdvertisementMsg {
6466
6548
  constructor(seqNum, numTotalSources, numLiveSources, namedMediaGroups, videoContentHint) {
6467
6549
  this.seqNum = seqNum;
@@ -6522,26 +6604,10 @@ function arePolicySpecificInfosEqual(left, right) {
6522
6604
  throw new Error('Invalid PolicySpecificInfo');
6523
6605
  }
6524
6606
  function areCodecInfoArraysEqual(left, right) {
6525
- if (left.length !== right.length) {
6526
- return false;
6527
- }
6528
- for (let i = 0; i < left.length; i += 1) {
6529
- if (!areCodecInfosEqual(left[i], right[i])) {
6530
- return false;
6531
- }
6532
- }
6533
- return true;
6607
+ return arraysAreEqual(left, right, areCodecInfosEqual);
6534
6608
  }
6535
6609
  function areStreamIdArraysEqual(left, right) {
6536
- if (left.length !== right.length) {
6537
- return false;
6538
- }
6539
- for (let i = 0; i < left.length; i += 1) {
6540
- if (!compareStreamIds(left[i], right[i])) {
6541
- return false;
6542
- }
6543
- }
6544
- return true;
6610
+ return arraysAreEqual(left, right, compareStreamIds);
6545
6611
  }
6546
6612
  function areStreamRequestsEqual(left, right) {
6547
6613
  if (left.policy !== right.policy) {
@@ -6613,7 +6679,7 @@ function areStreamRequestArraysEqual(left, right) {
6613
6679
  return true;
6614
6680
  }
6615
6681
  class JmpSession extends EventEmitter$5 {
6616
- constructor(mediaFamily, mediaContent, maxNumRetransmits = 3, retransmitIntervalMs = 250) {
6682
+ constructor(mediaFamily, mediaContent, maxNumRetransmits = 200, retransmitIntervalMs = 250) {
6617
6683
  super();
6618
6684
  this.currMediaRequestSeqNum = 1;
6619
6685
  this.currSourceAdvertisementSeqNum = 1;
@@ -6638,16 +6704,25 @@ class JmpSession extends EventEmitter$5 {
6638
6704
  !areStreamRequestArraysEqual(this.lastSentMediaRequest.msg.requests, requests)) {
6639
6705
  this.sendJmpMsg(JmpMsgType.MediaRequest, mediaRequestMsg);
6640
6706
  (_a = this.lastSentMediaRequest) === null || _a === void 0 ? void 0 : _a.cancel();
6641
- this.lastSentMediaRequest = new RetransmitHandler(mediaRequestMsg, this.maxNumRetransmits, this.retransmitIntervalMs, () => this.sendJmpMsg(JmpMsgType.MediaRequest, mediaRequestMsg), (expiredJmpMsg) => {
6707
+ this.lastSentMediaRequest = new RetransmitHandler(mediaRequestMsg, this.maxNumRetransmits, this.retransmitIntervalMs, () => {
6708
+ this.logger.info(`Retransmitting previously sent MediaRequest...`);
6709
+ this.sendJmpMsg(JmpMsgType.MediaRequest, mediaRequestMsg);
6710
+ }, (expiredJmpMsg) => {
6642
6711
  this.logger.warn(`Retransmits for message expired: ${expiredJmpMsg}`);
6643
6712
  });
6644
6713
  this.currMediaRequestSeqNum++;
6645
6714
  }
6715
+ else {
6716
+ this.logger.info(`Duplicate MediaRequest detected and will not be sent: ${mediaRequestMsg}`);
6717
+ }
6646
6718
  }
6647
6719
  sendSourceAdvertisement(numTotalSources, numLiveSources, namedMediaGroups, videoContentHint) {
6648
6720
  const sourceAdvertisementMsg = new SourceAdvertisementMsg(this.currSourceAdvertisementSeqNum++, numTotalSources, numLiveSources, namedMediaGroups, videoContentHint);
6649
6721
  this.sendJmpMsg(JmpMsgType.SourceAdvertisement, sourceAdvertisementMsg);
6650
- this.lastSentSourceAdvertisement = new RetransmitHandler(sourceAdvertisementMsg, this.maxNumRetransmits, this.retransmitIntervalMs, () => this.sendJmpMsg(JmpMsgType.SourceAdvertisement, sourceAdvertisementMsg), (expiredMsg) => {
6722
+ this.lastSentSourceAdvertisement = new RetransmitHandler(sourceAdvertisementMsg, this.maxNumRetransmits, this.retransmitIntervalMs, () => {
6723
+ this.logger.info(`Retransmitting previously sent SourceAdvertisement...`);
6724
+ this.sendJmpMsg(JmpMsgType.SourceAdvertisement, sourceAdvertisementMsg);
6725
+ }, (expiredMsg) => {
6651
6726
  this.logger.warn(`Retransmits for message expired: `, expiredMsg);
6652
6727
  });
6653
6728
  }
@@ -6662,11 +6737,17 @@ class JmpSession extends EventEmitter$5 {
6662
6737
  !compareStreamStateArrays(filteredStreamStates, this.lastSentMediaRequestStatus.msg.streamStates)) {
6663
6738
  this.sendJmpMsg(JmpMsgType.MediaRequestStatus, mediaRequestStatus);
6664
6739
  (_b = this.lastSentMediaRequestStatus) === null || _b === void 0 ? void 0 : _b.cancel();
6665
- this.lastSentMediaRequestStatus = new RetransmitHandler(mediaRequestStatus, this.maxNumRetransmits, this.retransmitIntervalMs, () => this.sendJmpMsg(JmpMsgType.MediaRequestStatus, mediaRequestStatus), (expiredMsg) => {
6740
+ this.lastSentMediaRequestStatus = new RetransmitHandler(mediaRequestStatus, this.maxNumRetransmits, this.retransmitIntervalMs, () => {
6741
+ this.logger.info(`Retransmitting previously sent MediaRequestStatus...`);
6742
+ this.sendJmpMsg(JmpMsgType.MediaRequestStatus, mediaRequestStatus);
6743
+ }, (expiredMsg) => {
6666
6744
  this.logger.warn(`Retransmits for message expired: `, expiredMsg);
6667
6745
  });
6668
6746
  this.currMediaRequestStatusSeqNum++;
6669
6747
  }
6748
+ else {
6749
+ this.logger.info(`Duplicate MediaRequestStatus detected and will not be sent: `, mediaRequestStatus);
6750
+ }
6670
6751
  }
6671
6752
  receive(jmpMsg) {
6672
6753
  if (jmpMsg.mediaContent !== this.mediaContent || jmpMsg.mediaFamily !== this.mediaFamily) {
@@ -6863,6 +6944,26 @@ class JmpSession extends EventEmitter$5 {
6863
6944
  }
6864
6945
  }
6865
6946
 
6947
+ var WcmeErrorType;
6948
+ (function (WcmeErrorType) {
6949
+ WcmeErrorType["CREATE_OFFER_FAILED"] = "CREATE_OFFER_FAILED";
6950
+ WcmeErrorType["SET_ANSWER_FAILED"] = "SET_ANSWER_FAILED";
6951
+ WcmeErrorType["OFFER_ANSWER_MISMATCH"] = "OFFER_ANSWER_MISMATCH";
6952
+ WcmeErrorType["SDP_MUNGE_FAILED"] = "SDP_MUNGE_FAILED";
6953
+ WcmeErrorType["SDP_MUNGE_MISSING_CODECS"] = "SDP_MUNGE_MISSING_CODECS";
6954
+ WcmeErrorType["INVALID_STREAM_REQUEST"] = "INVALID_STREAM_REQUEST";
6955
+ WcmeErrorType["GET_TRANSCEIVER_FAILED"] = "GET_TRANSCEIVER_FAILED";
6956
+ WcmeErrorType["GET_MAX_BITRATE_FAILED"] = "GET_MAX_BITRATE_FAILED";
6957
+ WcmeErrorType["GET_PAYLOAD_TYPE_FAILED"] = "GET_PAYLOAD_TYPE_FAILED";
6958
+ WcmeErrorType["SET_NMG_FAILED"] = "SET_NMG_FAILED";
6959
+ })(WcmeErrorType || (WcmeErrorType = {}));
6960
+ class WcmeError {
6961
+ constructor(type, message = '') {
6962
+ this.type = type;
6963
+ this.message = message;
6964
+ }
6965
+ }
6966
+
6866
6967
  var commonjsGlobal$1 = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
6867
6968
 
6868
6969
  var logger$1 = {exports: {}};
@@ -7149,26 +7250,6 @@ var logger$1 = {exports: {}};
7149
7250
 
7150
7251
  var Logger = logger$1.exports;
7151
7252
 
7152
- var WcmeErrorType;
7153
- (function (WcmeErrorType) {
7154
- WcmeErrorType["CREATE_OFFER_FAILED"] = "CREATE_OFFER_FAILED";
7155
- WcmeErrorType["SET_ANSWER_FAILED"] = "SET_ANSWER_FAILED";
7156
- WcmeErrorType["OFFER_ANSWER_MISMATCH"] = "OFFER_ANSWER_MISMATCH";
7157
- WcmeErrorType["SDP_MUNGE_FAILED"] = "SDP_MUNGE_FAILED";
7158
- WcmeErrorType["SDP_MUNGE_MISSING_CODECS"] = "SDP_MUNGE_MISSING_CODECS";
7159
- WcmeErrorType["INVALID_STREAM_REQUEST"] = "INVALID_STREAM_REQUEST";
7160
- WcmeErrorType["GET_TRANSCEIVER_FAILED"] = "GET_TRANSCEIVER_FAILED";
7161
- WcmeErrorType["GET_MAX_BITRATE_FAILED"] = "GET_MAX_BITRATE_FAILED";
7162
- WcmeErrorType["GET_PAYLOAD_TYPE_FAILED"] = "GET_PAYLOAD_TYPE_FAILED";
7163
- WcmeErrorType["SET_NMG_FAILED"] = "SET_NMG_FAILED";
7164
- })(WcmeErrorType || (WcmeErrorType = {}));
7165
- class WcmeError {
7166
- constructor(type, message = '') {
7167
- this.type = type;
7168
- this.message = message;
7169
- }
7170
- }
7171
-
7172
7253
  const DEFAULT_LOGGER_NAME = 'web-client-media-engine';
7173
7254
  const logger = Logger.get(DEFAULT_LOGGER_NAME);
7174
7255
  logger.setLevel(Logger.DEBUG);