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