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

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;
@@ -9332,88 +9445,27 @@ class SendOnlyTransceiver extends Transceiver {
9332
9445
  yield this.sender.setParameters(sendParameters);
9333
9446
  });
9334
9447
  }
9335
- }
9336
-
9337
- class StatsManager {
9338
- constructor(statsGetter, statsPreprocessor = () => __awaiter(this, void 0, void 0, function* () { })) {
9339
- this.statsGetter = statsGetter;
9340
- this.statsPreProcessor = statsPreprocessor;
9448
+ isSimulcastEnabled() {
9449
+ const params = this.sender.getParameters();
9450
+ return params.encodings.length > 1;
9341
9451
  }
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
- });
9452
+ signalStreams(mLine) {
9453
+ this.streamSignaler.signalStreams(this.isSimulcastEnabled(), this.rtxEnabled, mLine);
9350
9454
  }
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;
9455
+ get senderIds() {
9456
+ return this.streamSignaler.getSenderIds();
9362
9457
  }
9363
- getReceiverId() {
9364
- return {
9365
- mid: this.mid,
9366
- rid: '1',
9367
- };
9458
+ getEncodingIndexForStreamId(id) {
9459
+ return this.streamSignaler.getEncodingIndexForStreamId(id);
9368
9460
  }
9369
- signalLocalStreams(mLine) {
9461
+ resetStreamSignaler() {
9462
+ this.streamSignaler.reset();
9370
9463
  }
9371
- signalRemoteStreams(mLine) {
9464
+ setCodecParameters(parameters) {
9465
+ this.streamSignaler.setCodecParameters(parameters);
9372
9466
  }
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));
9467
+ deleteCodecParameters(parameters) {
9468
+ this.streamSignaler.deleteCodecParameters(parameters);
9417
9469
  }
9418
9470
  }
9419
9471
 
@@ -9421,6 +9473,20 @@ function generateSsrc() {
9421
9473
  return Math.floor(Math.random() * 0xffffffff) + 1;
9422
9474
  }
9423
9475
 
9476
+ function setCustomCodecParams(mLine, paramsMap) {
9477
+ paramsMap.forEach((value, param) => {
9478
+ [...mLine.codecs.values()]
9479
+ .filter((ci) => ci.name === 'H264' || ci.name === 'opus')
9480
+ .forEach((ci) => {
9481
+ if (value === null) {
9482
+ ci.fmtParams.delete(param);
9483
+ }
9484
+ else {
9485
+ ci.fmtParams.set(param, `${value}`);
9486
+ }
9487
+ });
9488
+ });
9489
+ }
9424
9490
  class SsrcIngressStreamSignaler {
9425
9491
  constructor() {
9426
9492
  this.ssrc = generateSsrc();
@@ -9443,10 +9509,17 @@ class SsrcIngressStreamSignaler {
9443
9509
  mLine.addLine(new SsrcGroupLine('FID', [this.ssrc, this.rtxSsrc]));
9444
9510
  }
9445
9511
  }
9512
+ reset() {
9513
+ this.ssrc = generateSsrc();
9514
+ }
9446
9515
  }
9447
9516
  class SsrcEgressStreamSignaler {
9448
9517
  constructor() {
9449
9518
  this.streamIds = [];
9519
+ this.customCodecParameters = new Map();
9520
+ }
9521
+ reset() {
9522
+ this.streamIds = [];
9450
9523
  }
9451
9524
  signalStreams(simulcastEnabled, rtxEnabled, mLine) {
9452
9525
  var _a;
@@ -9516,6 +9589,7 @@ class SsrcEgressStreamSignaler {
9516
9589
  mLine.addLine(new SsrcGroupLine('SIM', this.streamIds.map((streamId) => streamId.ssrc)));
9517
9590
  addVlaExtension(mLine);
9518
9591
  }
9592
+ setCustomCodecParams(mLine, this.customCodecParameters);
9519
9593
  }
9520
9594
  getSenderIds() {
9521
9595
  return this.streamIds;
@@ -9523,64 +9597,31 @@ class SsrcEgressStreamSignaler {
9523
9597
  getEncodingIndexForStreamId(streamId) {
9524
9598
  return this.streamIds.findIndex((currStreamId) => compareStreamIds(currStreamId, streamId));
9525
9599
  }
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);
9600
+ setCodecParameters(parameters) {
9601
+ Object.entries(parameters).forEach(([param, value]) => {
9602
+ this.customCodecParameters.set(param, value);
9603
+ });
9559
9604
  }
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;
9605
+ deleteCodecParameters(parameters) {
9606
+ parameters.forEach((param) => {
9607
+ this.customCodecParameters.set(param, null);
9608
+ });
9574
9609
  }
9575
- getIngressStreamSignaler(mid) {
9576
- return this.ingressStreamsSignalersByMid.get(mid);
9610
+ }
9611
+
9612
+ class StatsManager {
9613
+ constructor(statsGetter, statsPreprocessor = () => __awaiter(this, void 0, void 0, function* () { })) {
9614
+ this.statsGetter = statsGetter;
9615
+ this.statsPreProcessor = statsPreprocessor;
9577
9616
  }
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;
9617
+ getStats() {
9618
+ return __awaiter(this, void 0, void 0, function* () {
9619
+ const statsReport = yield this.statsGetter();
9620
+ const statsMap = new Map();
9621
+ statsReport.forEach((stats, key) => statsMap.set(key, stats));
9622
+ yield this.statsPreProcessor(statsMap);
9623
+ return statsMap;
9624
+ });
9584
9625
  }
9585
9626
  }
9586
9627
 
@@ -13184,6 +13225,24 @@ function webRtcVideoContentHintToJmpVideoContentHint(hint) {
13184
13225
  }
13185
13226
  return undefined;
13186
13227
  }
13228
+ function createEgressStreamSignaler(signalingMode, mid) {
13229
+ if (signalingMode === 'MID-RID') {
13230
+ return new RidEgressStreamSignaler(mid);
13231
+ }
13232
+ if (signalingMode === 'SSRC') {
13233
+ return new SsrcEgressStreamSignaler();
13234
+ }
13235
+ throw new Error(`unknown signaling mode`);
13236
+ }
13237
+ function createIngressStreamSignaler(signalingMode, mid) {
13238
+ if (signalingMode === 'MID-RID') {
13239
+ return new RidIngressStreamSignaler(mid);
13240
+ }
13241
+ if (signalingMode === 'SSRC') {
13242
+ return new SsrcIngressStreamSignaler();
13243
+ }
13244
+ throw new Error(`unknown signaling mode`);
13245
+ }
13187
13246
  function toMediaFamily(kind) {
13188
13247
  if (kind === MediaStreamTrackKind.Video) {
13189
13248
  return MediaFamily.Video;
@@ -13217,14 +13276,11 @@ class MultistreamConnection extends EventEmitter {
13217
13276
  this.pendingJmpTasks = [];
13218
13277
  this.metricsCallback = () => { };
13219
13278
  this.overuseUpdateCallback = () => { };
13220
- this.customCodecParameters = new Map();
13221
- this.midMap = new Map();
13222
- this.currentMid = 0;
13279
+ this.midPredictor = new MidPredictor();
13223
13280
  this.offerAnswerQueue = new AsyncQueue();
13224
13281
  this.options = Object.assign(Object.assign({}, defaultMultistreamConnectionOptions), userOptions);
13225
13282
  logger.info(`Creating multistream connection with options ${JSON.stringify(this.options)}`);
13226
13283
  this.initializePeerConnection();
13227
- this.streamSignalerManager = new StreamSignalerManager(this.options.streamSignalingMode);
13228
13284
  this.overuseStateManager = new OveruseStateManager((overuseState) => this.overuseUpdateCallback(overuseState));
13229
13285
  this.overuseStateManager.start();
13230
13286
  this.statsManager = new StatsManager(() => this.pc.getStats(), (stats) => this.preProcessStats(stats));
@@ -13241,16 +13297,6 @@ class MultistreamConnection extends EventEmitter {
13241
13297
  this.createSendTransceiver(MediaType.AudioSlides, contentSceneId);
13242
13298
  }
13243
13299
  }
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
13300
  initializePeerConnection() {
13255
13301
  var _a;
13256
13302
  (_a = this.pc) === null || _a === void 0 ? void 0 : _a.close();
@@ -13289,9 +13335,18 @@ class MultistreamConnection extends EventEmitter {
13289
13335
  logger.error(`addTransceiver failed due to : ${e}`);
13290
13336
  throw e;
13291
13337
  }
13292
- this.addMid(mediaType);
13338
+ const mid = this.midPredictor.getNextMid(mediaType);
13293
13339
  const csi = generateCsi(getMediaFamily(mediaType), sceneId);
13294
- this.sendTransceivers.set(mediaType, new SendOnlyTransceiver(rtcTransceiver, csi));
13340
+ const signaler = createEgressStreamSignaler(this.options.streamSignalingMode, mid);
13341
+ const transceiver = new SendOnlyTransceiver(rtcTransceiver, mid, csi, signaler);
13342
+ if (getMediaFamily(mediaType) === MediaFamily.Video) {
13343
+ transceiver.rtxEnabled = true;
13344
+ transceiver.setCodecParameters({
13345
+ 'max-mbps': `${defaultMaxVideoEncodeMbps}`,
13346
+ 'max-fs': `${defaultMaxVideoEncodeFrameSize}`,
13347
+ });
13348
+ }
13349
+ this.sendTransceivers.set(mediaType, transceiver);
13295
13350
  this.createJmpSession(mediaType);
13296
13351
  }
13297
13352
  createJmpSession(mediaType) {
@@ -13339,7 +13394,6 @@ class MultistreamConnection extends EventEmitter {
13339
13394
  }
13340
13395
  updateRequestedStreams(mediaType, requests) {
13341
13396
  const sendTransceiver = this.getSendTransceiverOrThrow(mediaType);
13342
- const signaler = this.streamSignalerManager.getEgressStreamSignalerOrThrow(sendTransceiver.mid);
13343
13397
  const mediaFamily = getMediaFamily(mediaType);
13344
13398
  const requestedIdEncodingParamsMap = new Map();
13345
13399
  const rsRequests = requests.filter((r) => isValidReceiverSelectedInfo(r.policySpecificInfo));
@@ -13360,11 +13414,9 @@ class MultistreamConnection extends EventEmitter {
13360
13414
  }
13361
13415
  const id = ids[0];
13362
13416
  const codecInfo = codecInfos[0];
13363
- const streamIdsMatched = signaler
13364
- .getSenderIds()
13365
- .some((validId) => compareStreamIds(id, validId));
13417
+ const streamIdsMatched = sendTransceiver.senderIds.some((validId) => compareStreamIds(id, validId));
13366
13418
  if (streamIdsMatched) {
13367
- const encodingIndex = signaler.getEncodingIndexForStreamId(id);
13419
+ const encodingIndex = sendTransceiver.getEncodingIndexForStreamId(id);
13368
13420
  if (encodingIndex !== -1) {
13369
13421
  const encodingParams = { maxPayloadBitsPerSecond };
13370
13422
  if (mediaFamily === MediaFamily.Video) {
@@ -13446,10 +13498,6 @@ class MultistreamConnection extends EventEmitter {
13446
13498
  return;
13447
13499
  }
13448
13500
  const streamStates = this.getVideoStreamStates(mediaType);
13449
- if (streamStates === null) {
13450
- logger.debug(`Empty streamStates, not sending MediaRequestStatus`);
13451
- return;
13452
- }
13453
13501
  const task = () => {
13454
13502
  var _a;
13455
13503
  (_a = this.jmpSessions.get(mediaType)) === null || _a === void 0 ? void 0 : _a.sendMediaRequestStatus(streamStates);
@@ -13554,14 +13602,10 @@ class MultistreamConnection extends EventEmitter {
13554
13602
  getVideoStreamStates(mediaType) {
13555
13603
  var _a, _b, _c;
13556
13604
  const sendTransceiver = this.getSendTransceiverOrThrow(mediaType);
13557
- const signaler = this.streamSignalerManager.getEgressStreamSignaler(sendTransceiver.mid);
13558
- if (!signaler) {
13559
- return null;
13560
- }
13561
13605
  const activeSimulcastLayerNumber = ((_a = sendTransceiver.publishedTrack) === null || _a === void 0 ? void 0 : _a.getNumActiveSimulcastLayers()) || 0;
13562
13606
  const published = (_b = sendTransceiver.publishedTrack) === null || _b === void 0 ? void 0 : _b.published;
13563
13607
  const muted = ((_c = sendTransceiver.publishedTrack) === null || _c === void 0 ? void 0 : _c.muted) === true;
13564
- return signaler.getSenderIds().map((id) => {
13608
+ return sendTransceiver.senderIds.map((id) => {
13565
13609
  let state;
13566
13610
  if (!published) {
13567
13611
  state = 'no source';
@@ -13569,7 +13613,7 @@ class MultistreamConnection extends EventEmitter {
13569
13613
  else if (muted) {
13570
13614
  state = 'avatar';
13571
13615
  }
13572
- else if (activeSimulcastLayerNumber < signaler.getEncodingIndexForStreamId(id)) {
13616
+ else if (activeSimulcastLayerNumber < sendTransceiver.getEncodingIndexForStreamId(id)) {
13573
13617
  state = 'no source';
13574
13618
  }
13575
13619
  else {
@@ -13585,21 +13629,16 @@ class MultistreamConnection extends EventEmitter {
13585
13629
  const rtcRtpTransceiver = this.pc.addTransceiver(toMediaStreamTrackKind(mediaType), {
13586
13630
  direction: 'recvonly',
13587
13631
  });
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
- }
13632
+ const transceiverMid = this.midPredictor.getNextMid(mediaType);
13633
+ const ingressSignaler = createIngressStreamSignaler(this.options.streamSignalingMode, transceiverMid);
13634
+ const recvOnlyTransceiver = new ReceiveOnlyTransceiver(rtcRtpTransceiver, transceiverMid, ingressSignaler);
13599
13635
  this.recvTransceivers.set(mediaType, [
13600
13636
  ...(this.recvTransceivers.get(mediaType) || []),
13601
13637
  recvOnlyTransceiver,
13602
13638
  ]);
13639
+ if (this.pc.getRemoteDescription()) {
13640
+ yield this.doLocalOfferAnswer();
13641
+ }
13603
13642
  createReceiveSlotResolve(recvOnlyTransceiver.receiveSlot);
13604
13643
  }));
13605
13644
  });
@@ -13639,7 +13678,7 @@ class MultistreamConnection extends EventEmitter {
13639
13678
  createOffer() {
13640
13679
  return __awaiter(this, void 0, void 0, function* () {
13641
13680
  if (!this.pc.getLocalDescription()) {
13642
- this.currentMid++;
13681
+ this.midPredictor.allocateMidForDatachannel();
13643
13682
  }
13644
13683
  return new Promise((createOfferResolve) => {
13645
13684
  this.offerAnswerQueue.push(() => __awaiter(this, void 0, void 0, function* () {
@@ -13665,7 +13704,6 @@ class MultistreamConnection extends EventEmitter {
13665
13704
  }
13666
13705
  setAnswer(answer) {
13667
13706
  return __awaiter(this, void 0, void 0, function* () {
13668
- const isInitialAnswer = !this.pc.getRemoteDescription();
13669
13707
  const sdp = this.preProcessRemoteAnswer(answer);
13670
13708
  if (!this.setAnswerResolve) {
13671
13709
  throw new Error(`Call to setAnswer without having previously called createOffer`);
@@ -13678,9 +13716,6 @@ class MultistreamConnection extends EventEmitter {
13678
13716
  else {
13679
13717
  logger.debug(`setAnswerResolve function was cleared between setAnswer and result of setRemoteDescription`);
13680
13718
  }
13681
- if (isInitialAnswer && this.customCodecParameters.size > 0) {
13682
- yield this.queueLocalOfferAnswer();
13683
- }
13684
13719
  }));
13685
13720
  });
13686
13721
  }
@@ -13718,43 +13753,17 @@ class MultistreamConnection extends EventEmitter {
13718
13753
  parsed.avMedia
13719
13754
  .filter((av) => av.direction === 'recvonly')
13720
13755
  .forEach((av) => {
13721
- const ingressSignaler = this.streamSignalerManager.getOrCreateIngressStreamSignaler(av.mid);
13722
- ingressSignaler.signalLocalStreams(av);
13756
+ const transceiver = this.getRecvTransceiverByMidOrThrow(av.mid);
13757
+ transceiver.signalLocalStreams(av);
13723
13758
  });
13724
13759
  parsed.avMedia
13725
- .filter((av) => av.direction === 'sendrecv')
13760
+ .filter((av) => av.direction === 'sendrecv' || av.direction === 'inactive')
13726
13761
  .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
- }
13762
+ const transceiver = this.getSendTransceiverByMidOrThrow(av.mid);
13763
+ transceiver.signalStreams(av);
13755
13764
  });
13756
13765
  if (getBrowserDetails().name !== 'Firefox') {
13757
- setupBundle(parsed, this.options.bundlePolicy, this.midMap);
13766
+ setupBundle(parsed, this.options.bundlePolicy, this.midPredictor.getMidMap());
13758
13767
  }
13759
13768
  return parsed.toString();
13760
13769
  }
@@ -13783,7 +13792,7 @@ class MultistreamConnection extends EventEmitter {
13783
13792
  }
13784
13793
  });
13785
13794
  if (getBrowserDetails().name === 'Firefox') {
13786
- setupBundle(parsed, this.options.bundlePolicy, this.midMap);
13795
+ setupBundle(parsed, this.options.bundlePolicy, this.midPredictor.getMidMap());
13787
13796
  if (this.options.bundlePolicy === 'max-bundle') {
13788
13797
  parsed.media.forEach((mline, index) => {
13789
13798
  if (index > 0) {
@@ -13798,9 +13807,10 @@ class MultistreamConnection extends EventEmitter {
13798
13807
  var _a;
13799
13808
  const parsedAnswer = parse(answer);
13800
13809
  const parsedOffer = parse((_a = this.pc.getLocalDescription()) === null || _a === void 0 ? void 0 : _a.sdp);
13801
- matchMlinesInAnswer(parsedOffer, parsedAnswer, this.streamSignalerManager);
13810
+ const recvTransceiversByMid = new Map([...this.recvTransceivers.values()].flat().map((t) => [t.mid, t]));
13811
+ matchMlinesInAnswer(parsedOffer, parsedAnswer, recvTransceiversByMid);
13802
13812
  if (getBrowserDetails().name === 'Firefox') {
13803
- setupBundle(parsedAnswer, this.options.bundlePolicy, this.midMap);
13813
+ setupBundle(parsedAnswer, this.options.bundlePolicy, this.midPredictor.getMidMap());
13804
13814
  if (this.options.bundlePolicy === 'max-bundle') {
13805
13815
  const { ufrag, pwd } = parsedAnswer.media[0].iceInfo;
13806
13816
  parsedAnswer.media.forEach((mline, index) => {
@@ -13820,6 +13830,20 @@ class MultistreamConnection extends EventEmitter {
13820
13830
  }
13821
13831
  return sendTransceiver;
13822
13832
  }
13833
+ getSendTransceiverByMidOrThrow(mid) {
13834
+ const transceiver = [...this.sendTransceivers.values()].find((t) => t.mid === mid);
13835
+ if (!transceiver) {
13836
+ throw new Error(`Unable to find send transceiver with mid ${mid}`);
13837
+ }
13838
+ return transceiver;
13839
+ }
13840
+ getRecvTransceiverByMidOrThrow(mid) {
13841
+ const transceiver = [...this.recvTransceivers.values()].flat().find((t) => t.mid === mid);
13842
+ if (!transceiver) {
13843
+ throw new Error(`Unable to find recv transceiver with mid ${mid}`);
13844
+ }
13845
+ return transceiver;
13846
+ }
13823
13847
  getPublishedTracks() {
13824
13848
  return [...this.sendTransceivers.values()]
13825
13849
  .map((transceiver) => transceiver.publishedTrack)
@@ -13827,11 +13851,8 @@ class MultistreamConnection extends EventEmitter {
13827
13851
  }
13828
13852
  setCodecParameters(mediaType, parameters) {
13829
13853
  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);
13854
+ const transceiver = this.sendTransceivers.get(mediaType);
13855
+ transceiver === null || transceiver === void 0 ? void 0 : transceiver.setCodecParameters(parameters);
13835
13856
  if (this.pc.getRemoteDescription()) {
13836
13857
  yield this.queueLocalOfferAnswer();
13837
13858
  }
@@ -13839,11 +13860,8 @@ class MultistreamConnection extends EventEmitter {
13839
13860
  }
13840
13861
  deleteCodecParameters(mediaType, parameters) {
13841
13862
  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);
13863
+ const transceiver = this.sendTransceivers.get(mediaType);
13864
+ transceiver === null || transceiver === void 0 ? void 0 : transceiver.deleteCodecParameters(parameters);
13847
13865
  if (this.pc.getRemoteDescription()) {
13848
13866
  yield this.queueLocalOfferAnswer();
13849
13867
  }
@@ -13887,32 +13905,34 @@ class MultistreamConnection extends EventEmitter {
13887
13905
  this.options = Object.assign(Object.assign({}, this.options), userOptions);
13888
13906
  }
13889
13907
  logger.info(`Renewing multistream connection with options ${JSON.stringify(this.options)}`);
13890
- this.clearMids();
13908
+ this.midPredictor.reset();
13891
13909
  this.initializePeerConnection();
13892
- this.streamSignalerManager = new StreamSignalerManager(this.options.streamSignalingMode);
13893
13910
  const mainSceneId = generateSceneId();
13894
13911
  const slidesSceneId = generateSceneId();
13895
13912
  this.sendTransceivers.forEach((transceiver, mediaType) => {
13896
13913
  var _a;
13897
13914
  const mediaContent = getMediaContent(mediaType);
13898
13915
  const sceneId = mediaContent === MediaContent.Main ? mainSceneId : slidesSceneId;
13899
- this.addMid(mediaType);
13916
+ const mid = this.midPredictor.getNextMid(mediaType);
13900
13917
  transceiver.replaceTransceiver(this.pc.addTransceiver(toMediaStreamTrackKind(mediaType), {
13901
13918
  direction: 'sendrecv',
13902
13919
  sendEncodings: getMediaFamily(mediaType) === MediaFamily.Video
13903
13920
  ? this.getVideoEncodingOptions(mediaContent)
13904
13921
  : undefined,
13905
13922
  }));
13923
+ transceiver.mid = mid;
13906
13924
  transceiver.csi = generateCsi(getMediaFamily(mediaType), sceneId);
13925
+ transceiver.resetStreamSignaler();
13907
13926
  (_a = this.jmpSessions.get(mediaType)) === null || _a === void 0 ? void 0 : _a.close();
13908
13927
  this.createJmpSession(mediaType);
13909
13928
  });
13910
13929
  this.recvTransceivers.forEach((transceivers, mediaType) => {
13911
13930
  transceivers.forEach((t) => {
13912
- this.addMid(mediaType);
13931
+ const mid = this.midPredictor.getNextMid(mediaType);
13913
13932
  t.replaceTransceiver(this.pc.addTransceiver(toMediaStreamTrackKind(mediaType), {
13914
13933
  direction: 'recvonly',
13915
13934
  }));
13935
+ t.mid = mid;
13916
13936
  });
13917
13937
  });
13918
13938
  }
@@ -13961,10 +13981,7 @@ class MultistreamConnection extends EventEmitter {
13961
13981
  statsToModify.mid = (_a = transceiver.receiveSlot.id) === null || _a === void 0 ? void 0 : _a.mid;
13962
13982
  statsToModify.csi = transceiver.receiveSlot.currentRxCsi;
13963
13983
  statsToModify.mediaType = mediaType;
13964
- const signaler = this.streamSignalerManager.getIngressStreamSignaler(statsToModify.mid);
13965
- if (signaler) {
13966
- Object.assign(statsToModify, signaler.getReceiverId());
13967
- }
13984
+ Object.assign(statsToModify, transceiver.receiverId);
13968
13985
  stats.set(receiverStats.id, statsToModify);
13969
13986
  }
13970
13987
  });