@webex/web-client-media-engine 3.17.2 → 3.19.0

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 CHANGED
@@ -10441,6 +10441,25 @@ class ReceiveSlot extends EventEmitter$2 {
10441
10441
  }
10442
10442
  ReceiveSlot.Events = exports.ReceiveSlotEvents;
10443
10443
 
10444
+ function getCurrentTimestamp() {
10445
+ return performance.timeOrigin + performance.now();
10446
+ }
10447
+ class StatsManager {
10448
+ constructor(statsGetter, statsPreprocessor = () => __awaiter$1(this, void 0, void 0, function* () { })) {
10449
+ this.statsGetter = statsGetter;
10450
+ this.statsPreProcessor = statsPreprocessor;
10451
+ }
10452
+ getStats() {
10453
+ return __awaiter$1(this, void 0, void 0, function* () {
10454
+ const statsReport = yield this.statsGetter();
10455
+ const statsMap = new Map();
10456
+ statsReport.forEach((stats, key) => statsMap.set(key, stats));
10457
+ yield this.statsPreProcessor(statsMap);
10458
+ return statsMap;
10459
+ });
10460
+ }
10461
+ }
10462
+
10444
10463
  class Transceiver {
10445
10464
  constructor(rtcRtpTransceiver, mid) {
10446
10465
  this.twccDisabled = false;
@@ -10464,7 +10483,7 @@ class Transceiver {
10464
10483
  class ReceiveOnlyTransceiver extends Transceiver {
10465
10484
  constructor(rtcRtpTransceiver, mid, munger) {
10466
10485
  super(rtcRtpTransceiver, mid);
10467
- this.metadata = { isActiveSpeaker: false };
10486
+ this.metadata = { isRequested: false, isActiveSpeaker: false };
10468
10487
  this.munger = munger;
10469
10488
  this._receiveSlot = new ReceiveSlot(() => {
10470
10489
  if (!this._rtcRtpTransceiver.mid) {
@@ -10495,6 +10514,8 @@ class ReceiveOnlyTransceiver extends Transceiver {
10495
10514
  stats.calliopeMediaType = this.metadata.mediaType;
10496
10515
  stats.requestedBitrate = this.metadata.requestedBitrate;
10497
10516
  stats.requestedFrameSize = this.metadata.requestedFrameSize;
10517
+ stats.isRequested = this.metadata.isRequested;
10518
+ stats.lastRequestedUpdateTimestamp = this.metadata.lastRequestedUpdateTimestamp;
10498
10519
  stats.isActiveSpeaker = this.metadata.isActiveSpeaker;
10499
10520
  stats.lastActiveSpeakerUpdateTimestamp = this.metadata.lastActiveSpeakerUpdateTimestamp;
10500
10521
  Object.assign(stats, this.receiverId);
@@ -10518,10 +10539,18 @@ class ReceiveOnlyTransceiver extends Transceiver {
10518
10539
  }
10519
10540
  handleRequested(streamRequest) {
10520
10541
  var _a, _b;
10542
+ if (!this.metadata.isRequested) {
10543
+ this.metadata.isRequested = true;
10544
+ this.metadata.lastRequestedUpdateTimestamp = getCurrentTimestamp();
10545
+ }
10521
10546
  this.metadata.requestedBitrate = streamRequest.maxPayloadBitsPerSecond;
10522
10547
  this.metadata.requestedFrameSize = (_b = (_a = streamRequest.codecInfos[0]) === null || _a === void 0 ? void 0 : _a.h264) === null || _b === void 0 ? void 0 : _b.maxFs;
10523
10548
  }
10524
10549
  handleUnrequested() {
10550
+ if (this.metadata.isRequested) {
10551
+ this.metadata.isRequested = false;
10552
+ this.metadata.lastRequestedUpdateTimestamp = getCurrentTimestamp();
10553
+ }
10525
10554
  this.metadata.requestedBitrate = undefined;
10526
10555
  this.metadata.requestedFrameSize = undefined;
10527
10556
  this.receiveSlot._updateSource('no source', undefined);
@@ -10529,7 +10558,7 @@ class ReceiveOnlyTransceiver extends Transceiver {
10529
10558
  handleActiveSpeakerUpdate(value) {
10530
10559
  if (this.metadata.isActiveSpeaker !== value) {
10531
10560
  this.metadata.isActiveSpeaker = value;
10532
- this.metadata.lastActiveSpeakerUpdateTimestamp = performance.timeOrigin + performance.now();
10561
+ this.metadata.lastActiveSpeakerUpdateTimestamp = getCurrentTimestamp();
10533
10562
  }
10534
10563
  }
10535
10564
  }
@@ -14250,6 +14279,7 @@ class SendOnlyTransceiver extends Transceiver {
14250
14279
  this.namedMediaGroupsChange = new TypedEvent();
14251
14280
  this.requestedIdEncodingParamsMap = new Map();
14252
14281
  this.updateSendParametersQueue = new AsyncQueue();
14282
+ this.metadata = { lastRequestedUpdateTimestampsMap: new Map() };
14253
14283
  this.csi = csi;
14254
14284
  this.direction = 'sendrecv';
14255
14285
  this.handleTrackChange = this.handleTrackChange.bind(this);
@@ -14360,8 +14390,16 @@ class SendOnlyTransceiver extends Transceiver {
14360
14390
  stats.mid = this.mid;
14361
14391
  stats.csi = this.csi;
14362
14392
  stats.calliopeMediaType = this.mediaType;
14363
- stats.requestedBitrate = this.getRequestedBitrate(stats.ssrc);
14364
- stats.requestedFrameSize = this.getRequestedFrameSize(stats.ssrc);
14393
+ const senderId = this.munger.getSenderIds().find((id) => id.ssrc === stats.ssrc);
14394
+ if (senderId) {
14395
+ const encodingIndex = this.getEncodingIndexForStreamId(senderId);
14396
+ const encodingParams = this.requestedIdEncodingParamsMap.get(encodingIndex);
14397
+ stats.requestedBitrate = encodingParams === null || encodingParams === void 0 ? void 0 : encodingParams.maxPayloadBitsPerSecond;
14398
+ stats.requestedFrameSize = encodingParams === null || encodingParams === void 0 ? void 0 : encodingParams.maxFs;
14399
+ stats.isRequested = !!encodingParams;
14400
+ stats.lastRequestedUpdateTimestamp =
14401
+ this.metadata.lastRequestedUpdateTimestampsMap.get(encodingIndex);
14402
+ }
14365
14403
  const trackSettings = (_a = this.publishedStream) === null || _a === void 0 ? void 0 : _a.getSettings();
14366
14404
  if (trackSettings === null || trackSettings === void 0 ? void 0 : trackSettings.frameRate) {
14367
14405
  stats.targetFrameRate = trackSettings === null || trackSettings === void 0 ? void 0 : trackSettings.frameRate;
@@ -14395,6 +14433,17 @@ class SendOnlyTransceiver extends Transceiver {
14395
14433
  }
14396
14434
  });
14397
14435
  yield this.sender.setParameters(sendParameters);
14436
+ const timestamp = getCurrentTimestamp();
14437
+ requestedIdEncodingParamsMap.forEach((_, index) => {
14438
+ if (!this.requestedIdEncodingParamsMap.has(index)) {
14439
+ this.metadata.lastRequestedUpdateTimestampsMap.set(index, timestamp);
14440
+ }
14441
+ });
14442
+ this.requestedIdEncodingParamsMap.forEach((_, index) => {
14443
+ if (!requestedIdEncodingParamsMap.has(index)) {
14444
+ this.metadata.lastRequestedUpdateTimestampsMap.set(index, timestamp);
14445
+ }
14446
+ });
14398
14447
  const oldRequested = this.requested;
14399
14448
  const newRequested = requestedIdEncodingParamsMap.size > 0;
14400
14449
  this.requestedIdEncodingParamsMap = requestedIdEncodingParamsMap;
@@ -14404,22 +14453,6 @@ class SendOnlyTransceiver extends Transceiver {
14404
14453
  }));
14405
14454
  });
14406
14455
  }
14407
- getRequestedBitrate(ssrc) {
14408
- const index = this.senderIds.findIndex((streamId) => streamId.ssrc === ssrc);
14409
- if (this.requestedIdEncodingParamsMap.has(index)) {
14410
- const encodingParams = this.requestedIdEncodingParamsMap.get(index);
14411
- return encodingParams === null || encodingParams === void 0 ? void 0 : encodingParams.maxPayloadBitsPerSecond;
14412
- }
14413
- return undefined;
14414
- }
14415
- getRequestedFrameSize(ssrc) {
14416
- const index = this.senderIds.findIndex((streamId) => streamId.ssrc === ssrc);
14417
- if (this.requestedIdEncodingParamsMap.has(index)) {
14418
- const encodingParams = this.requestedIdEncodingParamsMap.get(index);
14419
- return encodingParams === null || encodingParams === void 0 ? void 0 : encodingParams.maxFs;
14420
- }
14421
- return undefined;
14422
- }
14423
14456
  isSimulcastEnabled() {
14424
14457
  const params = this.sender.getParameters();
14425
14458
  return params.encodings.length > 1;
@@ -14507,22 +14540,6 @@ class SendSlot {
14507
14540
  }
14508
14541
  }
14509
14542
 
14510
- class StatsManager {
14511
- constructor(statsGetter, statsPreprocessor = () => __awaiter$1(this, void 0, void 0, function* () { })) {
14512
- this.statsGetter = statsGetter;
14513
- this.statsPreProcessor = statsPreprocessor;
14514
- }
14515
- getStats() {
14516
- return __awaiter$1(this, void 0, void 0, function* () {
14517
- const statsReport = yield this.statsGetter();
14518
- const statsMap = new Map();
14519
- statsReport.forEach((stats, key) => statsMap.set(key, stats));
14520
- yield this.statsPreProcessor(statsMap);
14521
- return statsMap;
14522
- });
14523
- }
14524
- }
14525
-
14526
14543
  const organizeTransceiverStats = (sendTransceivers, recvTransceivers) => __awaiter$1(void 0, void 0, void 0, function* () {
14527
14544
  const result = {
14528
14545
  audio: {
@@ -15285,12 +15302,20 @@ SCTP Max Message Size: ${maxMessageSize}`);
15285
15302
  }
15286
15303
  const requestedReceiveSlotIds = [];
15287
15304
  streamRequests.forEach((request) => {
15305
+ if (request.receiveSlots.length === 0) {
15306
+ logger.error('Stream request ids cannot be empty.');
15307
+ return;
15308
+ }
15288
15309
  request.receiveSlots.forEach((slot) => {
15289
15310
  if (!slot.id) {
15290
- logger.error(`Running stream request task, but ReceiveSlot ID is missing!`);
15291
- return;
15311
+ logger.error('Running stream request task, but ReceiveSlot ID is missing.');
15312
+ }
15313
+ if (!requestedReceiveSlotIds.some((id) => compareStreamIds(id, slot.id))) {
15314
+ requestedReceiveSlotIds.push(slot.id);
15315
+ }
15316
+ else {
15317
+ logger.error(`Stream id duplicate found ${JSON.stringify(slot.id)}.`);
15292
15318
  }
15293
- requestedReceiveSlotIds.push(slot.id);
15294
15319
  });
15295
15320
  });
15296
15321
  jmpSession.sendRequests(streamRequests.map((sr) => sr._toJmpStreamRequest()));