@webex/web-client-media-engine 2.1.2 → 2.1.4

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
@@ -8855,6 +8855,30 @@ function eventTargetAgnosticAddListener(emitter, name, listener, flags) {
8855
8855
  class EventEmitter extends events.exports.EventEmitter {
8856
8856
  }
8857
8857
 
8858
+ class MidPredictor {
8859
+ constructor() {
8860
+ this.currentMid = 0;
8861
+ this.midMap = new Map();
8862
+ }
8863
+ getNextMid(mediaType) {
8864
+ const mid = this.currentMid++;
8865
+ const mids = this.midMap.get(mediaType) || [];
8866
+ mids.push(`${mid}`);
8867
+ this.midMap.set(mediaType, mids);
8868
+ return `${mid}`;
8869
+ }
8870
+ allocateMidForDatachannel() {
8871
+ this.currentMid += 1;
8872
+ }
8873
+ reset() {
8874
+ this.midMap = new Map();
8875
+ this.currentMid = 0;
8876
+ }
8877
+ getMidMap() {
8878
+ return this.midMap;
8879
+ }
8880
+ }
8881
+
8858
8882
  var OveruseState;
8859
8883
  (function (OveruseState) {
8860
8884
  OveruseState[OveruseState["NOT_OVERUSED"] = 0] = "NOT_OVERUSED";
@@ -8962,8 +8986,9 @@ class ReceiveSlot extends EventEmitter {
8962
8986
  ReceiveSlot.Events = ReceiveSlotEvents;
8963
8987
 
8964
8988
  class Transceiver {
8965
- constructor(rtcRtpTransceiver) {
8989
+ constructor(rtcRtpTransceiver, mid) {
8966
8990
  this._rtcRtpTransceiver = rtcRtpTransceiver;
8991
+ this.mid = mid;
8967
8992
  }
8968
8993
  replaceTransceiver(newRtcRtpTransceiver) {
8969
8994
  this._rtcRtpTransceiver = newRtcRtpTransceiver;
@@ -8974,22 +8999,20 @@ class Transceiver {
8974
8999
  get sender() {
8975
9000
  return this._rtcRtpTransceiver.sender;
8976
9001
  }
8977
- get mid() {
8978
- return this._rtcRtpTransceiver.mid;
8979
- }
8980
9002
  close() {
8981
9003
  this._rtcRtpTransceiver.stop();
8982
9004
  }
8983
9005
  }
8984
9006
 
8985
9007
  class ReceiveOnlyTransceiver extends Transceiver {
8986
- constructor(rtcRtpTransceiver, idGetter) {
8987
- super(rtcRtpTransceiver);
9008
+ constructor(rtcRtpTransceiver, mid, signaler) {
9009
+ super(rtcRtpTransceiver, mid);
9010
+ this.streamSignaler = signaler;
8988
9011
  this._receiveSlot = new ReceiveSlot(() => {
8989
9012
  if (!this._rtcRtpTransceiver.mid) {
8990
9013
  return null;
8991
9014
  }
8992
- return idGetter(this._rtcRtpTransceiver.mid);
9015
+ return this.streamSignaler.getReceiverId();
8993
9016
  }, this._rtcRtpTransceiver.receiver.track);
8994
9017
  }
8995
9018
  replaceTransceiver(newRtcRtpTransceiver) {
@@ -9006,62 +9029,21 @@ class ReceiveOnlyTransceiver extends Transceiver {
9006
9029
  getStats() {
9007
9030
  return this.receiver.getStats();
9008
9031
  }
9032
+ signalLocalStreams(mLine) {
9033
+ this.streamSignaler.signalLocalStreams(mLine);
9034
+ }
9035
+ signalRemoteStreams(mLine) {
9036
+ this.streamSignaler.signalRemoteStreams(mLine);
9037
+ }
9038
+ get receiverId() {
9039
+ return this.streamSignaler.getReceiverId();
9040
+ }
9041
+ resetStreamSignaler() {
9042
+ this.streamSignaler.reset();
9043
+ }
9009
9044
  }
9010
9045
  ReceiveOnlyTransceiver.rid = '1';
9011
9046
 
9012
- function deepCopy(source) {
9013
- return Array.isArray(source)
9014
- ? source.map((item) => deepCopy(item))
9015
- : source instanceof Map
9016
- ? new Map(source)
9017
- : source instanceof Date
9018
- ? new Date(source.getTime())
9019
- : source && typeof source === 'object'
9020
- ? Object.getOwnPropertyNames(source).reduce((o, prop) => {
9021
- Object.defineProperty(o, prop, Object.getOwnPropertyDescriptor(source, prop));
9022
- o[prop] = deepCopy(source[prop]);
9023
- return o;
9024
- }, Object.create(Object.getPrototypeOf(source)))
9025
- : source;
9026
- }
9027
-
9028
- function matchMlinesInAnswer(parsedOffer, parsedAnswer, streamSignalerManager) {
9029
- parsedAnswer.session.groups = parsedOffer.session.groups;
9030
- parsedAnswer.media = parsedOffer.media.map((offerMline) => {
9031
- if (!offerMline.mid) {
9032
- throw new Error(`Offer mline is missing MID`);
9033
- }
9034
- const answerMline = parsedAnswer.media.find((m) => m.mid === offerMline.mid);
9035
- if (answerMline) {
9036
- if (answerMline instanceof AvMediaDescription) {
9037
- [...answerMline.codecs.values()].forEach((ci) => {
9038
- ci.fmtParams.set('x-google-start-bitrate', '60000');
9039
- });
9040
- }
9041
- return answerMline;
9042
- }
9043
- if (!(offerMline instanceof AvMediaDescription)) {
9044
- throw new Error(`Answer is missing a non-media mline: ${offerMline.mid}`);
9045
- }
9046
- const startingMline = parsedAnswer.avMedia.find((m) => m.type === offerMline.type);
9047
- if (!startingMline) {
9048
- throw new Error(`Answer has no mline of type ${offerMline.type}, can't generate synthetic answer mline for mid ${offerMline.mid}`);
9049
- }
9050
- const fakeCorrespondingMline = deepCopy(startingMline);
9051
- fakeCorrespondingMline.mid = offerMline.mid;
9052
- fakeCorrespondingMline.simulcast = undefined;
9053
- if (offerMline.direction === 'sendrecv' || offerMline.direction === 'sendonly') {
9054
- fakeCorrespondingMline.direction = 'recvonly';
9055
- }
9056
- if (offerMline.direction === 'recvonly') {
9057
- fakeCorrespondingMline.direction = 'sendonly';
9058
- const ingressSignaler = streamSignalerManager.getIngressStreamSignalerOrThrow(offerMline.mid);
9059
- ingressSignaler.signalRemoteStreams(fakeCorrespondingMline);
9060
- }
9061
- return fakeCorrespondingMline;
9062
- });
9063
- }
9064
-
9065
9047
  class JmpLine extends Line {
9066
9048
  constructor(versions) {
9067
9049
  super();
@@ -9235,9 +9217,6 @@ function injectDummyCandidates(parsedSdp) {
9235
9217
  }
9236
9218
  });
9237
9219
  }
9238
- function hasSimulcast(av) {
9239
- return !!av.simulcast || av.ssrcGroups.map((sg) => sg.semantics).some((sem) => sem === 'SIM');
9240
- }
9241
9220
  function addVlaExtension(mLine) {
9242
9221
  const vlaUri = 'http://www.webrtc.org/experiments/rtp-hdrext/video-layers-allocation00';
9243
9222
  if (mLine.extMaps.findIndex((extMapLine) => extMapLine.uri === vlaUri) === -1) {
@@ -9247,13 +9226,147 @@ function addVlaExtension(mLine) {
9247
9226
  }
9248
9227
  }
9249
9228
 
9229
+ const simulcastMaxFrameSizes = {
9230
+ 0: '240',
9231
+ 1: '2304',
9232
+ 2: '8160',
9233
+ };
9234
+
9235
+ class RidIngressStreamSignaler {
9236
+ constructor(mid) {
9237
+ this.mid = mid;
9238
+ }
9239
+ getReceiverId() {
9240
+ return {
9241
+ mid: this.mid,
9242
+ rid: '1',
9243
+ };
9244
+ }
9245
+ signalLocalStreams(mLine) {
9246
+ }
9247
+ signalRemoteStreams(mLine) {
9248
+ }
9249
+ reset() {
9250
+ }
9251
+ }
9252
+ class RidEgressStreamSignaler {
9253
+ constructor(mid) {
9254
+ this.streamIds = [];
9255
+ this.mid = mid;
9256
+ }
9257
+ signalStreams(simulcastEnabled, _rtxEnabled, mLine) {
9258
+ mLine.ssrcGroups = [];
9259
+ if (this.streamIds.length === 0) {
9260
+ if (simulcastEnabled) {
9261
+ this.streamIds = [
9262
+ {
9263
+ mid: this.mid,
9264
+ rid: 'low',
9265
+ },
9266
+ {
9267
+ mid: this.mid,
9268
+ rid: 'medium',
9269
+ },
9270
+ {
9271
+ mid: this.mid,
9272
+ rid: 'high',
9273
+ },
9274
+ ];
9275
+ }
9276
+ else {
9277
+ this.streamIds = [
9278
+ {
9279
+ mid: this.mid,
9280
+ },
9281
+ ];
9282
+ }
9283
+ }
9284
+ if (simulcastEnabled) {
9285
+ mLine.rids = this.streamIds.map((streamId, index) => new RidLine(streamId.rid, 'send', `max-fs=${simulcastMaxFrameSizes[index]}`));
9286
+ mLine.simulcast = new SimulcastLine(SimulcastLayerList.fromString('low;medium;high'), new SimulcastLayerList());
9287
+ addVlaExtension(mLine);
9288
+ }
9289
+ }
9290
+ getSenderIds() {
9291
+ return this.streamIds;
9292
+ }
9293
+ reset() {
9294
+ this.streamIds = [];
9295
+ }
9296
+ getEncodingIndexForStreamId(streamId) {
9297
+ return this.streamIds.findIndex((currStreamId) => compareStreamIds(currStreamId, streamId));
9298
+ }
9299
+ setCodecParameters(parameters) {
9300
+ }
9301
+ deleteCodecParameters(parameters) {
9302
+ }
9303
+ }
9304
+
9305
+ function deepCopy(source) {
9306
+ return Array.isArray(source)
9307
+ ? source.map((item) => deepCopy(item))
9308
+ : source instanceof Map
9309
+ ? new Map(source)
9310
+ : source instanceof Date
9311
+ ? new Date(source.getTime())
9312
+ : source && typeof source === 'object'
9313
+ ? Object.getOwnPropertyNames(source).reduce((o, prop) => {
9314
+ Object.defineProperty(o, prop, Object.getOwnPropertyDescriptor(source, prop));
9315
+ o[prop] = deepCopy(source[prop]);
9316
+ return o;
9317
+ }, Object.create(Object.getPrototypeOf(source)))
9318
+ : source;
9319
+ }
9320
+
9321
+ function matchMlinesInAnswer(parsedOffer, parsedAnswer, recvTransceiversByMid) {
9322
+ parsedAnswer.session.groups = parsedOffer.session.groups;
9323
+ parsedAnswer.media = parsedOffer.media.map((offerMline) => {
9324
+ if (!offerMline.mid) {
9325
+ throw new Error(`Offer mline is missing MID`);
9326
+ }
9327
+ const answerMline = parsedAnswer.media.find((m) => m.mid === offerMline.mid);
9328
+ if (answerMline) {
9329
+ if (answerMline instanceof AvMediaDescription) {
9330
+ [...answerMline.codecs.values()].forEach((ci) => {
9331
+ ci.fmtParams.set('x-google-start-bitrate', '60000');
9332
+ });
9333
+ }
9334
+ return answerMline;
9335
+ }
9336
+ if (!(offerMline instanceof AvMediaDescription)) {
9337
+ throw new Error(`Answer is missing a non-media mline: ${offerMline.mid}`);
9338
+ }
9339
+ const startingMline = parsedAnswer.avMedia.find((m) => m.type === offerMline.type);
9340
+ if (!startingMline) {
9341
+ throw new Error(`Answer has no mline of type ${offerMline.type}, can't generate synthetic answer mline for mid ${offerMline.mid}`);
9342
+ }
9343
+ const fakeCorrespondingMline = deepCopy(startingMline);
9344
+ fakeCorrespondingMline.mid = offerMline.mid;
9345
+ fakeCorrespondingMline.simulcast = undefined;
9346
+ if (offerMline.direction === 'sendrecv' || offerMline.direction === 'sendonly') {
9347
+ fakeCorrespondingMline.direction = 'recvonly';
9348
+ }
9349
+ if (offerMline.direction === 'recvonly') {
9350
+ fakeCorrespondingMline.direction = 'sendonly';
9351
+ const recvTransceiver = recvTransceiversByMid.get(offerMline.mid);
9352
+ if (!recvTransceiver) {
9353
+ throw new Error(`Can't find recv transceiver for mid ${offerMline.mid}`);
9354
+ }
9355
+ recvTransceiver.signalRemoteStreams(fakeCorrespondingMline);
9356
+ }
9357
+ return fakeCorrespondingMline;
9358
+ });
9359
+ }
9360
+
9250
9361
  class SendOnlyTransceiver extends Transceiver {
9251
- constructor(rtcpRtpTransceiver, csi) {
9252
- super(rtcpRtpTransceiver);
9362
+ constructor(rtcpRtpTransceiver, mid, csi, signaler) {
9363
+ super(rtcpRtpTransceiver, mid);
9364
+ this.rtxEnabled = false;
9253
9365
  this.requested = false;
9254
9366
  this.csi = csi;
9255
9367
  this.direction = 'sendrecv';
9256
9368
  this.handleTrackChange = this.handleTrackChange.bind(this);
9369
+ this.streamSignaler = signaler;
9257
9370
  }
9258
9371
  handleTrackChange() {
9259
9372
  var _a;
@@ -9315,12 +9428,17 @@ class SendOnlyTransceiver extends Transceiver {
9315
9428
  }
9316
9429
  updateSendParameters(requestedIdEncodingParamsMap) {
9317
9430
  return __awaiter(this, void 0, void 0, function* () {
9431
+ if (!this.publishedTrack)
9432
+ return;
9433
+ this.setTrackRequested(requestedIdEncodingParamsMap.size > 0);
9318
9434
  const sendParameters = this.sender.getParameters();
9319
9435
  sendParameters.encodings.forEach((encoding, index) => {
9436
+ var _a, _b;
9320
9437
  const encodingParams = requestedIdEncodingParamsMap.get(index);
9321
9438
  encoding.active = !!encodingParams;
9322
9439
  if (encodingParams) {
9323
- const { maxPayloadBitsPerSecond, scaleDownRatio } = encodingParams;
9440
+ const { maxPayloadBitsPerSecond, maxFs, maxWidth, maxHeight } = encodingParams;
9441
+ const scaleDownRatio = getScaleDownRatio((_a = this.publishedTrack) === null || _a === void 0 ? void 0 : _a.getSettings().width, (_b = this.publishedTrack) === null || _b === void 0 ? void 0 : _b.getSettings().height, maxFs, maxWidth, maxHeight);
9324
9442
  if (maxPayloadBitsPerSecond !== undefined && maxPayloadBitsPerSecond >= 0) {
9325
9443
  encoding.maxBitrate = maxPayloadBitsPerSecond;
9326
9444
  }
@@ -9332,88 +9450,27 @@ class SendOnlyTransceiver extends Transceiver {
9332
9450
  yield this.sender.setParameters(sendParameters);
9333
9451
  });
9334
9452
  }
9335
- }
9336
-
9337
- class StatsManager {
9338
- constructor(statsGetter, statsPreprocessor = () => __awaiter(this, void 0, void 0, function* () { })) {
9339
- this.statsGetter = statsGetter;
9340
- this.statsPreProcessor = statsPreprocessor;
9453
+ isSimulcastEnabled() {
9454
+ const params = this.sender.getParameters();
9455
+ return params.encodings.length > 1;
9341
9456
  }
9342
- getStats() {
9343
- return __awaiter(this, void 0, void 0, function* () {
9344
- const statsReport = yield this.statsGetter();
9345
- const statsMap = new Map();
9346
- statsReport.forEach((stats, key) => statsMap.set(key, stats));
9347
- yield this.statsPreProcessor(statsMap);
9348
- return statsMap;
9349
- });
9457
+ signalStreams(mLine) {
9458
+ this.streamSignaler.signalStreams(this.isSimulcastEnabled(), this.rtxEnabled, mLine);
9350
9459
  }
9351
- }
9352
-
9353
- const simulcastMaxFrameSizes = {
9354
- 0: '240',
9355
- 1: '2304',
9356
- 2: '8160',
9357
- };
9358
-
9359
- class RidIngressStreamSignaler {
9360
- constructor(mid) {
9361
- this.mid = mid;
9460
+ get senderIds() {
9461
+ return this.streamSignaler.getSenderIds();
9362
9462
  }
9363
- getReceiverId() {
9364
- return {
9365
- mid: this.mid,
9366
- rid: '1',
9367
- };
9463
+ getEncodingIndexForStreamId(id) {
9464
+ return this.streamSignaler.getEncodingIndexForStreamId(id);
9368
9465
  }
9369
- signalLocalStreams(mLine) {
9466
+ resetStreamSignaler() {
9467
+ this.streamSignaler.reset();
9370
9468
  }
9371
- signalRemoteStreams(mLine) {
9469
+ setCodecParameters(parameters) {
9470
+ this.streamSignaler.setCodecParameters(parameters);
9372
9471
  }
9373
- }
9374
- class RidEgressStreamSignaler {
9375
- constructor(mid) {
9376
- this.streamIds = [];
9377
- this.mid = mid;
9378
- }
9379
- signalStreams(simulcastEnabled, _rtxEnabled, mLine) {
9380
- mLine.ssrcGroups = [];
9381
- if (this.streamIds.length === 0) {
9382
- if (simulcastEnabled) {
9383
- this.streamIds = [
9384
- {
9385
- mid: this.mid,
9386
- rid: 'low',
9387
- },
9388
- {
9389
- mid: this.mid,
9390
- rid: 'medium',
9391
- },
9392
- {
9393
- mid: this.mid,
9394
- rid: 'high',
9395
- },
9396
- ];
9397
- }
9398
- else {
9399
- this.streamIds = [
9400
- {
9401
- mid: this.mid,
9402
- },
9403
- ];
9404
- }
9405
- }
9406
- if (simulcastEnabled) {
9407
- mLine.rids = this.streamIds.map((streamId, index) => new RidLine(streamId.rid, 'send', `max-fs=${simulcastMaxFrameSizes[index]}`));
9408
- mLine.simulcast = new SimulcastLine(SimulcastLayerList.fromString('low;medium;high'), new SimulcastLayerList());
9409
- addVlaExtension(mLine);
9410
- }
9411
- }
9412
- getSenderIds() {
9413
- return this.streamIds;
9414
- }
9415
- getEncodingIndexForStreamId(streamId) {
9416
- return this.streamIds.findIndex((currStreamId) => compareStreamIds(currStreamId, streamId));
9472
+ deleteCodecParameters(parameters) {
9473
+ this.streamSignaler.deleteCodecParameters(parameters);
9417
9474
  }
9418
9475
  }
9419
9476
 
@@ -9421,6 +9478,20 @@ function generateSsrc() {
9421
9478
  return Math.floor(Math.random() * 0xffffffff) + 1;
9422
9479
  }
9423
9480
 
9481
+ function setCustomCodecParams(mLine, paramsMap) {
9482
+ paramsMap.forEach((value, param) => {
9483
+ [...mLine.codecs.values()]
9484
+ .filter((ci) => ci.name === 'H264' || ci.name === 'opus')
9485
+ .forEach((ci) => {
9486
+ if (value === null) {
9487
+ ci.fmtParams.delete(param);
9488
+ }
9489
+ else {
9490
+ ci.fmtParams.set(param, `${value}`);
9491
+ }
9492
+ });
9493
+ });
9494
+ }
9424
9495
  class SsrcIngressStreamSignaler {
9425
9496
  constructor() {
9426
9497
  this.ssrc = generateSsrc();
@@ -9443,10 +9514,17 @@ class SsrcIngressStreamSignaler {
9443
9514
  mLine.addLine(new SsrcGroupLine('FID', [this.ssrc, this.rtxSsrc]));
9444
9515
  }
9445
9516
  }
9517
+ reset() {
9518
+ this.ssrc = generateSsrc();
9519
+ }
9446
9520
  }
9447
9521
  class SsrcEgressStreamSignaler {
9448
9522
  constructor() {
9449
9523
  this.streamIds = [];
9524
+ this.customCodecParameters = new Map();
9525
+ }
9526
+ reset() {
9527
+ this.streamIds = [];
9450
9528
  }
9451
9529
  signalStreams(simulcastEnabled, rtxEnabled, mLine) {
9452
9530
  var _a;
@@ -9516,6 +9594,7 @@ class SsrcEgressStreamSignaler {
9516
9594
  mLine.addLine(new SsrcGroupLine('SIM', this.streamIds.map((streamId) => streamId.ssrc)));
9517
9595
  addVlaExtension(mLine);
9518
9596
  }
9597
+ setCustomCodecParams(mLine, this.customCodecParameters);
9519
9598
  }
9520
9599
  getSenderIds() {
9521
9600
  return this.streamIds;
@@ -9523,64 +9602,31 @@ class SsrcEgressStreamSignaler {
9523
9602
  getEncodingIndexForStreamId(streamId) {
9524
9603
  return this.streamIds.findIndex((currStreamId) => compareStreamIds(currStreamId, streamId));
9525
9604
  }
9526
- }
9527
-
9528
- class StreamSignalerManager {
9529
- constructor(streamSignalingMode) {
9530
- this.egressStreamSignalersByMid = new Map();
9531
- this.ingressStreamsSignalersByMid = new Map();
9532
- this.ingressStreamSignalingMode = streamSignalingMode;
9533
- this.egressStreamSignalingMode = streamSignalingMode;
9534
- }
9535
- getOrCreateEgressStreamSignaler(mid) {
9536
- const existing = this.getEgressStreamSignaler(mid);
9537
- if (existing) {
9538
- return existing;
9539
- }
9540
- let newSignaler;
9541
- if (this.egressStreamSignalingMode === 'MID-RID') {
9542
- newSignaler = new RidEgressStreamSignaler(mid);
9543
- }
9544
- else {
9545
- newSignaler = new SsrcEgressStreamSignaler();
9546
- }
9547
- this.egressStreamSignalersByMid.set(mid, newSignaler);
9548
- return newSignaler;
9549
- }
9550
- getEgressStreamSignalerOrThrow(mid) {
9551
- const existing = this.getEgressStreamSignaler(mid);
9552
- if (!existing) {
9553
- throw new Error(`Couldn't find EgressStreamSignaler for mid ${mid}`);
9554
- }
9555
- return existing;
9556
- }
9557
- getEgressStreamSignaler(mid) {
9558
- return this.egressStreamSignalersByMid.get(mid);
9605
+ setCodecParameters(parameters) {
9606
+ Object.entries(parameters).forEach(([param, value]) => {
9607
+ this.customCodecParameters.set(param, value);
9608
+ });
9559
9609
  }
9560
- getOrCreateIngressStreamSignaler(mid) {
9561
- const existing = this.getIngressStreamSignaler(mid);
9562
- if (existing) {
9563
- return existing;
9564
- }
9565
- let newSignaler;
9566
- if (this.ingressStreamSignalingMode === 'MID-RID') {
9567
- newSignaler = new RidIngressStreamSignaler(mid);
9568
- }
9569
- else {
9570
- newSignaler = new SsrcIngressStreamSignaler();
9571
- }
9572
- this.ingressStreamsSignalersByMid.set(mid, newSignaler);
9573
- return newSignaler;
9610
+ deleteCodecParameters(parameters) {
9611
+ parameters.forEach((param) => {
9612
+ this.customCodecParameters.set(param, null);
9613
+ });
9574
9614
  }
9575
- getIngressStreamSignaler(mid) {
9576
- return this.ingressStreamsSignalersByMid.get(mid);
9615
+ }
9616
+
9617
+ class StatsManager {
9618
+ constructor(statsGetter, statsPreprocessor = () => __awaiter(this, void 0, void 0, function* () { })) {
9619
+ this.statsGetter = statsGetter;
9620
+ this.statsPreProcessor = statsPreprocessor;
9577
9621
  }
9578
- getIngressStreamSignalerOrThrow(mid) {
9579
- const existing = this.getIngressStreamSignaler(mid);
9580
- if (!existing) {
9581
- throw new Error(`Couldn't find IngressStreamSignaler for mid ${mid}`);
9582
- }
9583
- return existing;
9622
+ getStats() {
9623
+ return __awaiter(this, void 0, void 0, function* () {
9624
+ const statsReport = yield this.statsGetter();
9625
+ const statsMap = new Map();
9626
+ statsReport.forEach((stats, key) => statsMap.set(key, stats));
9627
+ yield this.statsPreProcessor(statsMap);
9628
+ return statsMap;
9629
+ });
9584
9630
  }
9585
9631
  }
9586
9632
 
@@ -13184,6 +13230,24 @@ function webRtcVideoContentHintToJmpVideoContentHint(hint) {
13184
13230
  }
13185
13231
  return undefined;
13186
13232
  }
13233
+ function createEgressStreamSignaler(signalingMode, mid) {
13234
+ if (signalingMode === 'MID-RID') {
13235
+ return new RidEgressStreamSignaler(mid);
13236
+ }
13237
+ if (signalingMode === 'SSRC') {
13238
+ return new SsrcEgressStreamSignaler();
13239
+ }
13240
+ throw new Error(`unknown signaling mode`);
13241
+ }
13242
+ function createIngressStreamSignaler(signalingMode, mid) {
13243
+ if (signalingMode === 'MID-RID') {
13244
+ return new RidIngressStreamSignaler(mid);
13245
+ }
13246
+ if (signalingMode === 'SSRC') {
13247
+ return new SsrcIngressStreamSignaler();
13248
+ }
13249
+ throw new Error(`unknown signaling mode`);
13250
+ }
13187
13251
  function toMediaFamily(kind) {
13188
13252
  if (kind === MediaStreamTrackKind.Video) {
13189
13253
  return MediaFamily.Video;
@@ -13217,14 +13281,12 @@ class MultistreamConnection extends EventEmitter {
13217
13281
  this.pendingJmpTasks = [];
13218
13282
  this.metricsCallback = () => { };
13219
13283
  this.overuseUpdateCallback = () => { };
13220
- this.customCodecParameters = new Map();
13221
- this.midMap = new Map();
13222
- this.currentMid = 0;
13284
+ this.midPredictor = new MidPredictor();
13223
13285
  this.offerAnswerQueue = new AsyncQueue();
13286
+ this.requestedIdEncodingParamsMap = new Map();
13224
13287
  this.options = Object.assign(Object.assign({}, defaultMultistreamConnectionOptions), userOptions);
13225
13288
  logger.info(`Creating multistream connection with options ${JSON.stringify(this.options)}`);
13226
13289
  this.initializePeerConnection();
13227
- this.streamSignalerManager = new StreamSignalerManager(this.options.streamSignalingMode);
13228
13290
  this.overuseStateManager = new OveruseStateManager((overuseState) => this.overuseUpdateCallback(overuseState));
13229
13291
  this.overuseStateManager.start();
13230
13292
  this.statsManager = new StatsManager(() => this.pc.getStats(), (stats) => this.preProcessStats(stats));
@@ -13241,16 +13303,6 @@ class MultistreamConnection extends EventEmitter {
13241
13303
  this.createSendTransceiver(MediaType.AudioSlides, contentSceneId);
13242
13304
  }
13243
13305
  }
13244
- addMid(mediaType) {
13245
- const mid = this.currentMid++;
13246
- const mids = this.midMap.get(mediaType) || [];
13247
- mids.push(`${mid}`);
13248
- this.midMap.set(mediaType, mids);
13249
- }
13250
- clearMids() {
13251
- this.midMap = new Map();
13252
- this.currentMid = 0;
13253
- }
13254
13306
  initializePeerConnection() {
13255
13307
  var _a;
13256
13308
  (_a = this.pc) === null || _a === void 0 ? void 0 : _a.close();
@@ -13289,9 +13341,18 @@ class MultistreamConnection extends EventEmitter {
13289
13341
  logger.error(`addTransceiver failed due to : ${e}`);
13290
13342
  throw e;
13291
13343
  }
13292
- this.addMid(mediaType);
13344
+ const mid = this.midPredictor.getNextMid(mediaType);
13293
13345
  const csi = generateCsi(getMediaFamily(mediaType), sceneId);
13294
- this.sendTransceivers.set(mediaType, new SendOnlyTransceiver(rtcTransceiver, csi));
13346
+ const signaler = createEgressStreamSignaler(this.options.streamSignalingMode, mid);
13347
+ const transceiver = new SendOnlyTransceiver(rtcTransceiver, mid, csi, signaler);
13348
+ if (getMediaFamily(mediaType) === MediaFamily.Video) {
13349
+ transceiver.rtxEnabled = true;
13350
+ transceiver.setCodecParameters({
13351
+ 'max-mbps': `${defaultMaxVideoEncodeMbps}`,
13352
+ 'max-fs': `${defaultMaxVideoEncodeFrameSize}`,
13353
+ });
13354
+ }
13355
+ this.sendTransceivers.set(mediaType, transceiver);
13295
13356
  this.createJmpSession(mediaType);
13296
13357
  }
13297
13358
  createJmpSession(mediaType) {
@@ -13339,7 +13400,6 @@ class MultistreamConnection extends EventEmitter {
13339
13400
  }
13340
13401
  updateRequestedStreams(mediaType, requests) {
13341
13402
  const sendTransceiver = this.getSendTransceiverOrThrow(mediaType);
13342
- const signaler = this.streamSignalerManager.getEgressStreamSignalerOrThrow(sendTransceiver.mid);
13343
13403
  const mediaFamily = getMediaFamily(mediaType);
13344
13404
  const requestedIdEncodingParamsMap = new Map();
13345
13405
  const rsRequests = requests.filter((r) => isValidReceiverSelectedInfo(r.policySpecificInfo));
@@ -13347,7 +13407,7 @@ class MultistreamConnection extends EventEmitter {
13347
13407
  logger.warn('Ignoring non-receiver-selected requests');
13348
13408
  }
13349
13409
  rsRequests.forEach(({ ids, policySpecificInfo, codecInfos, maxPayloadBitsPerSecond }) => {
13350
- var _a, _b, _c, _d;
13410
+ var _a, _b, _c;
13351
13411
  if (ids.length > 1) {
13352
13412
  throw new Error(`More than a single ID being unexpected/invalid ${ids}`);
13353
13413
  }
@@ -13360,18 +13420,15 @@ class MultistreamConnection extends EventEmitter {
13360
13420
  }
13361
13421
  const id = ids[0];
13362
13422
  const codecInfo = codecInfos[0];
13363
- const streamIdsMatched = signaler
13364
- .getSenderIds()
13365
- .some((validId) => compareStreamIds(id, validId));
13423
+ const streamIdsMatched = sendTransceiver.senderIds.some((validId) => compareStreamIds(id, validId));
13366
13424
  if (streamIdsMatched) {
13367
- const encodingIndex = signaler.getEncodingIndexForStreamId(id);
13425
+ const encodingIndex = sendTransceiver.getEncodingIndexForStreamId(id);
13368
13426
  if (encodingIndex !== -1) {
13369
13427
  const encodingParams = { maxPayloadBitsPerSecond };
13370
13428
  if (mediaFamily === MediaFamily.Video) {
13371
- const trackSettings = (_a = sendTransceiver.publishedTrack) === null || _a === void 0 ? void 0 : _a.getSettings();
13372
- if (trackSettings) {
13373
- encodingParams.scaleDownRatio = getScaleDownRatio(trackSettings.width, trackSettings.height, (_b = codecInfo === null || codecInfo === void 0 ? void 0 : codecInfo.h264) === null || _b === void 0 ? void 0 : _b.maxFs, (_c = codecInfo === null || codecInfo === void 0 ? void 0 : codecInfo.h264) === null || _c === void 0 ? void 0 : _c.maxWidth, (_d = codecInfo === null || codecInfo === void 0 ? void 0 : codecInfo.h264) === null || _d === void 0 ? void 0 : _d.maxHeight);
13374
- }
13429
+ encodingParams.maxFs = (_a = codecInfo === null || codecInfo === void 0 ? void 0 : codecInfo.h264) === null || _a === void 0 ? void 0 : _a.maxFs;
13430
+ encodingParams.maxWidth = (_b = codecInfo === null || codecInfo === void 0 ? void 0 : codecInfo.h264) === null || _b === void 0 ? void 0 : _b.maxWidth;
13431
+ encodingParams.maxHeight = (_c = codecInfo === null || codecInfo === void 0 ? void 0 : codecInfo.h264) === null || _c === void 0 ? void 0 : _c.maxHeight;
13375
13432
  }
13376
13433
  requestedIdEncodingParamsMap.set(encodingIndex, encodingParams);
13377
13434
  }
@@ -13383,8 +13440,8 @@ class MultistreamConnection extends EventEmitter {
13383
13440
  logger.warn(`${mediaType}: Unable to find matching stream ID for requested ID: ${JSON.stringify(id)}`);
13384
13441
  }
13385
13442
  });
13386
- sendTransceiver.setTrackRequested(requestedIdEncodingParamsMap.size > 0);
13387
13443
  sendTransceiver.updateSendParameters(requestedIdEncodingParamsMap);
13444
+ this.requestedIdEncodingParamsMap = requestedIdEncodingParamsMap;
13388
13445
  }
13389
13446
  createDataChannel() {
13390
13447
  const dataChannel = this.pc.createDataChannel('datachannel', {});
@@ -13446,10 +13503,6 @@ class MultistreamConnection extends EventEmitter {
13446
13503
  return;
13447
13504
  }
13448
13505
  const streamStates = this.getVideoStreamStates(mediaType);
13449
- if (streamStates === null) {
13450
- logger.debug(`Empty streamStates, not sending MediaRequestStatus`);
13451
- return;
13452
- }
13453
13506
  const task = () => {
13454
13507
  var _a;
13455
13508
  (_a = this.jmpSessions.get(mediaType)) === null || _a === void 0 ? void 0 : _a.sendMediaRequestStatus(streamStates);
@@ -13529,8 +13582,9 @@ class MultistreamConnection extends EventEmitter {
13529
13582
  });
13530
13583
  }
13531
13584
  addTrackListeners(mediaType, track) {
13585
+ const sendTransceiver = this.getSendTransceiverOrThrow(mediaType);
13532
13586
  const onTrackResolutionChange = () => {
13533
- this.sendMediaRequestStatus(mediaType);
13587
+ sendTransceiver.updateSendParameters(this.requestedIdEncodingParamsMap);
13534
13588
  };
13535
13589
  track.on(LocalTrack.Events.TrackConstraintsChange, onTrackResolutionChange);
13536
13590
  const onTrackMute = () => {
@@ -13547,21 +13601,19 @@ class MultistreamConnection extends EventEmitter {
13547
13601
  if (!track.muted) {
13548
13602
  this.sendSourceAdvertisement(mediaType);
13549
13603
  this.sendMediaRequestStatus(mediaType);
13604
+ if (mediaType === MediaType.VideoMain) {
13605
+ sendTransceiver.updateSendParameters(this.requestedIdEncodingParamsMap);
13606
+ }
13550
13607
  }
13551
13608
  };
13552
13609
  track.on(LocalTrack.Events.PublishedStateUpdate, onTrackPublish);
13553
13610
  }
13554
13611
  getVideoStreamStates(mediaType) {
13555
- var _a, _b, _c;
13612
+ var _a, _b;
13556
13613
  const sendTransceiver = this.getSendTransceiverOrThrow(mediaType);
13557
- const signaler = this.streamSignalerManager.getEgressStreamSignaler(sendTransceiver.mid);
13558
- if (!signaler) {
13559
- return null;
13560
- }
13561
- const activeSimulcastLayerNumber = ((_a = sendTransceiver.publishedTrack) === null || _a === void 0 ? void 0 : _a.getNumActiveSimulcastLayers()) || 0;
13562
- const published = (_b = sendTransceiver.publishedTrack) === null || _b === void 0 ? void 0 : _b.published;
13563
- const muted = ((_c = sendTransceiver.publishedTrack) === null || _c === void 0 ? void 0 : _c.muted) === true;
13564
- return signaler.getSenderIds().map((id) => {
13614
+ const published = (_a = sendTransceiver.publishedTrack) === null || _a === void 0 ? void 0 : _a.published;
13615
+ const muted = ((_b = sendTransceiver.publishedTrack) === null || _b === void 0 ? void 0 : _b.muted) === true;
13616
+ return sendTransceiver.senderIds.map((id) => {
13565
13617
  let state;
13566
13618
  if (!published) {
13567
13619
  state = 'no source';
@@ -13569,9 +13621,6 @@ class MultistreamConnection extends EventEmitter {
13569
13621
  else if (muted) {
13570
13622
  state = 'avatar';
13571
13623
  }
13572
- else if (activeSimulcastLayerNumber < signaler.getEncodingIndexForStreamId(id)) {
13573
- state = 'no source';
13574
- }
13575
13624
  else {
13576
13625
  state = 'live';
13577
13626
  }
@@ -13585,21 +13634,16 @@ class MultistreamConnection extends EventEmitter {
13585
13634
  const rtcRtpTransceiver = this.pc.addTransceiver(toMediaStreamTrackKind(mediaType), {
13586
13635
  direction: 'recvonly',
13587
13636
  });
13588
- this.addMid(mediaType);
13589
- const recvOnlyTransceiver = new ReceiveOnlyTransceiver(rtcRtpTransceiver, (mid) => {
13590
- const ingressSignaler = this.streamSignalerManager.getIngressStreamSignaler(mid);
13591
- if (!ingressSignaler) {
13592
- return null;
13593
- }
13594
- return ingressSignaler.getReceiverId();
13595
- });
13596
- if (this.pc.getRemoteDescription()) {
13597
- yield this.doLocalOfferAnswer();
13598
- }
13637
+ const transceiverMid = this.midPredictor.getNextMid(mediaType);
13638
+ const ingressSignaler = createIngressStreamSignaler(this.options.streamSignalingMode, transceiverMid);
13639
+ const recvOnlyTransceiver = new ReceiveOnlyTransceiver(rtcRtpTransceiver, transceiverMid, ingressSignaler);
13599
13640
  this.recvTransceivers.set(mediaType, [
13600
13641
  ...(this.recvTransceivers.get(mediaType) || []),
13601
13642
  recvOnlyTransceiver,
13602
13643
  ]);
13644
+ if (this.pc.getRemoteDescription()) {
13645
+ yield this.doLocalOfferAnswer();
13646
+ }
13603
13647
  createReceiveSlotResolve(recvOnlyTransceiver.receiveSlot);
13604
13648
  }));
13605
13649
  });
@@ -13639,7 +13683,7 @@ class MultistreamConnection extends EventEmitter {
13639
13683
  createOffer() {
13640
13684
  return __awaiter(this, void 0, void 0, function* () {
13641
13685
  if (!this.pc.getLocalDescription()) {
13642
- this.currentMid++;
13686
+ this.midPredictor.allocateMidForDatachannel();
13643
13687
  }
13644
13688
  return new Promise((createOfferResolve) => {
13645
13689
  this.offerAnswerQueue.push(() => __awaiter(this, void 0, void 0, function* () {
@@ -13665,7 +13709,6 @@ class MultistreamConnection extends EventEmitter {
13665
13709
  }
13666
13710
  setAnswer(answer) {
13667
13711
  return __awaiter(this, void 0, void 0, function* () {
13668
- const isInitialAnswer = !this.pc.getRemoteDescription();
13669
13712
  const sdp = this.preProcessRemoteAnswer(answer);
13670
13713
  if (!this.setAnswerResolve) {
13671
13714
  throw new Error(`Call to setAnswer without having previously called createOffer`);
@@ -13678,9 +13721,6 @@ class MultistreamConnection extends EventEmitter {
13678
13721
  else {
13679
13722
  logger.debug(`setAnswerResolve function was cleared between setAnswer and result of setRemoteDescription`);
13680
13723
  }
13681
- if (isInitialAnswer && this.customCodecParameters.size > 0) {
13682
- yield this.queueLocalOfferAnswer();
13683
- }
13684
13724
  }));
13685
13725
  });
13686
13726
  }
@@ -13718,43 +13758,17 @@ class MultistreamConnection extends EventEmitter {
13718
13758
  parsed.avMedia
13719
13759
  .filter((av) => av.direction === 'recvonly')
13720
13760
  .forEach((av) => {
13721
- const ingressSignaler = this.streamSignalerManager.getOrCreateIngressStreamSignaler(av.mid);
13722
- ingressSignaler.signalLocalStreams(av);
13761
+ const transceiver = this.getRecvTransceiverByMidOrThrow(av.mid);
13762
+ transceiver.signalLocalStreams(av);
13723
13763
  });
13724
13764
  parsed.avMedia
13725
- .filter((av) => av.direction === 'sendrecv')
13765
+ .filter((av) => av.direction === 'sendrecv' || av.direction === 'inactive')
13726
13766
  .forEach((av) => {
13727
- const egressSignaler = this.streamSignalerManager.getOrCreateEgressStreamSignaler(av.mid);
13728
- const simulcastEnabled = hasSimulcast(av);
13729
- const rtxEnabled = av.type === 'video';
13730
- egressSignaler.signalStreams(simulcastEnabled, rtxEnabled, av);
13731
- if (av.type === 'video') {
13732
- [...av.codecs.values()]
13733
- .filter((ci) => ci.name === 'H264')
13734
- .forEach((ci) => {
13735
- ci.fmtParams.set('max-mbps', `${defaultMaxVideoEncodeMbps}`);
13736
- ci.fmtParams.set('max-fs', `${defaultMaxVideoEncodeFrameSize}`);
13737
- });
13738
- }
13739
- const mediaType = [...this.sendTransceivers.keys()].find((key) => { var _a; return ((_a = this.sendTransceivers.get(key)) === null || _a === void 0 ? void 0 : _a.mid) === av.mid; });
13740
- if (mediaType && this.customCodecParameters.has(mediaType)) {
13741
- [...av.codecs.values()]
13742
- .filter((ci) => ci.name === (av.type === 'audio' ? 'opus' : 'H264'))
13743
- .forEach((ci) => {
13744
- var _a;
13745
- (_a = this.customCodecParameters.get(mediaType)) === null || _a === void 0 ? void 0 : _a.forEach((value, param) => {
13746
- if (value === null) {
13747
- ci.fmtParams.delete(param);
13748
- }
13749
- else {
13750
- ci.fmtParams.set(param, `${value}`);
13751
- }
13752
- });
13753
- });
13754
- }
13767
+ const transceiver = this.getSendTransceiverByMidOrThrow(av.mid);
13768
+ transceiver.signalStreams(av);
13755
13769
  });
13756
13770
  if (getBrowserDetails().name !== 'Firefox') {
13757
- setupBundle(parsed, this.options.bundlePolicy, this.midMap);
13771
+ setupBundle(parsed, this.options.bundlePolicy, this.midPredictor.getMidMap());
13758
13772
  }
13759
13773
  return parsed.toString();
13760
13774
  }
@@ -13783,7 +13797,7 @@ class MultistreamConnection extends EventEmitter {
13783
13797
  }
13784
13798
  });
13785
13799
  if (getBrowserDetails().name === 'Firefox') {
13786
- setupBundle(parsed, this.options.bundlePolicy, this.midMap);
13800
+ setupBundle(parsed, this.options.bundlePolicy, this.midPredictor.getMidMap());
13787
13801
  if (this.options.bundlePolicy === 'max-bundle') {
13788
13802
  parsed.media.forEach((mline, index) => {
13789
13803
  if (index > 0) {
@@ -13798,9 +13812,10 @@ class MultistreamConnection extends EventEmitter {
13798
13812
  var _a;
13799
13813
  const parsedAnswer = parse(answer);
13800
13814
  const parsedOffer = parse((_a = this.pc.getLocalDescription()) === null || _a === void 0 ? void 0 : _a.sdp);
13801
- matchMlinesInAnswer(parsedOffer, parsedAnswer, this.streamSignalerManager);
13815
+ const recvTransceiversByMid = new Map([...this.recvTransceivers.values()].flat().map((t) => [t.mid, t]));
13816
+ matchMlinesInAnswer(parsedOffer, parsedAnswer, recvTransceiversByMid);
13802
13817
  if (getBrowserDetails().name === 'Firefox') {
13803
- setupBundle(parsedAnswer, this.options.bundlePolicy, this.midMap);
13818
+ setupBundle(parsedAnswer, this.options.bundlePolicy, this.midPredictor.getMidMap());
13804
13819
  if (this.options.bundlePolicy === 'max-bundle') {
13805
13820
  const { ufrag, pwd } = parsedAnswer.media[0].iceInfo;
13806
13821
  parsedAnswer.media.forEach((mline, index) => {
@@ -13820,6 +13835,20 @@ class MultistreamConnection extends EventEmitter {
13820
13835
  }
13821
13836
  return sendTransceiver;
13822
13837
  }
13838
+ getSendTransceiverByMidOrThrow(mid) {
13839
+ const transceiver = [...this.sendTransceivers.values()].find((t) => t.mid === mid);
13840
+ if (!transceiver) {
13841
+ throw new Error(`Unable to find send transceiver with mid ${mid}`);
13842
+ }
13843
+ return transceiver;
13844
+ }
13845
+ getRecvTransceiverByMidOrThrow(mid) {
13846
+ const transceiver = [...this.recvTransceivers.values()].flat().find((t) => t.mid === mid);
13847
+ if (!transceiver) {
13848
+ throw new Error(`Unable to find recv transceiver with mid ${mid}`);
13849
+ }
13850
+ return transceiver;
13851
+ }
13823
13852
  getPublishedTracks() {
13824
13853
  return [...this.sendTransceivers.values()]
13825
13854
  .map((transceiver) => transceiver.publishedTrack)
@@ -13827,11 +13856,8 @@ class MultistreamConnection extends EventEmitter {
13827
13856
  }
13828
13857
  setCodecParameters(mediaType, parameters) {
13829
13858
  return __awaiter(this, void 0, void 0, function* () {
13830
- const currentParams = this.customCodecParameters.get(mediaType) || new Map();
13831
- Object.entries(parameters).forEach(([param, value]) => {
13832
- currentParams.set(param, value);
13833
- });
13834
- this.customCodecParameters.set(mediaType, currentParams);
13859
+ const transceiver = this.sendTransceivers.get(mediaType);
13860
+ transceiver === null || transceiver === void 0 ? void 0 : transceiver.setCodecParameters(parameters);
13835
13861
  if (this.pc.getRemoteDescription()) {
13836
13862
  yield this.queueLocalOfferAnswer();
13837
13863
  }
@@ -13839,11 +13865,8 @@ class MultistreamConnection extends EventEmitter {
13839
13865
  }
13840
13866
  deleteCodecParameters(mediaType, parameters) {
13841
13867
  return __awaiter(this, void 0, void 0, function* () {
13842
- const currentParams = this.customCodecParameters.get(mediaType) || new Map();
13843
- parameters.forEach((param) => {
13844
- currentParams.set(param, null);
13845
- });
13846
- this.customCodecParameters.set(mediaType, currentParams);
13868
+ const transceiver = this.sendTransceivers.get(mediaType);
13869
+ transceiver === null || transceiver === void 0 ? void 0 : transceiver.deleteCodecParameters(parameters);
13847
13870
  if (this.pc.getRemoteDescription()) {
13848
13871
  yield this.queueLocalOfferAnswer();
13849
13872
  }
@@ -13887,32 +13910,34 @@ class MultistreamConnection extends EventEmitter {
13887
13910
  this.options = Object.assign(Object.assign({}, this.options), userOptions);
13888
13911
  }
13889
13912
  logger.info(`Renewing multistream connection with options ${JSON.stringify(this.options)}`);
13890
- this.clearMids();
13913
+ this.midPredictor.reset();
13891
13914
  this.initializePeerConnection();
13892
- this.streamSignalerManager = new StreamSignalerManager(this.options.streamSignalingMode);
13893
13915
  const mainSceneId = generateSceneId();
13894
13916
  const slidesSceneId = generateSceneId();
13895
13917
  this.sendTransceivers.forEach((transceiver, mediaType) => {
13896
13918
  var _a;
13897
13919
  const mediaContent = getMediaContent(mediaType);
13898
13920
  const sceneId = mediaContent === MediaContent.Main ? mainSceneId : slidesSceneId;
13899
- this.addMid(mediaType);
13921
+ const mid = this.midPredictor.getNextMid(mediaType);
13900
13922
  transceiver.replaceTransceiver(this.pc.addTransceiver(toMediaStreamTrackKind(mediaType), {
13901
13923
  direction: 'sendrecv',
13902
13924
  sendEncodings: getMediaFamily(mediaType) === MediaFamily.Video
13903
13925
  ? this.getVideoEncodingOptions(mediaContent)
13904
13926
  : undefined,
13905
13927
  }));
13928
+ transceiver.mid = mid;
13906
13929
  transceiver.csi = generateCsi(getMediaFamily(mediaType), sceneId);
13930
+ transceiver.resetStreamSignaler();
13907
13931
  (_a = this.jmpSessions.get(mediaType)) === null || _a === void 0 ? void 0 : _a.close();
13908
13932
  this.createJmpSession(mediaType);
13909
13933
  });
13910
13934
  this.recvTransceivers.forEach((transceivers, mediaType) => {
13911
13935
  transceivers.forEach((t) => {
13912
- this.addMid(mediaType);
13936
+ const mid = this.midPredictor.getNextMid(mediaType);
13913
13937
  t.replaceTransceiver(this.pc.addTransceiver(toMediaStreamTrackKind(mediaType), {
13914
13938
  direction: 'recvonly',
13915
13939
  }));
13940
+ t.mid = mid;
13916
13941
  });
13917
13942
  });
13918
13943
  }
@@ -13961,10 +13986,7 @@ class MultistreamConnection extends EventEmitter {
13961
13986
  statsToModify.mid = (_a = transceiver.receiveSlot.id) === null || _a === void 0 ? void 0 : _a.mid;
13962
13987
  statsToModify.csi = transceiver.receiveSlot.currentRxCsi;
13963
13988
  statsToModify.mediaType = mediaType;
13964
- const signaler = this.streamSignalerManager.getIngressStreamSignaler(statsToModify.mid);
13965
- if (signaler) {
13966
- Object.assign(statsToModify, signaler.getReceiverId());
13967
- }
13989
+ Object.assign(statsToModify, transceiver.receiverId);
13968
13990
  stats.set(receiverStats.id, statsToModify);
13969
13991
  }
13970
13992
  });