@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/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;
@@ -9336,88 +9449,27 @@ class SendOnlyTransceiver extends Transceiver {
9336
9449
  yield this.sender.setParameters(sendParameters);
9337
9450
  });
9338
9451
  }
9339
- }
9340
-
9341
- class StatsManager {
9342
- constructor(statsGetter, statsPreprocessor = () => __awaiter(this, void 0, void 0, function* () { })) {
9343
- this.statsGetter = statsGetter;
9344
- this.statsPreProcessor = statsPreprocessor;
9452
+ isSimulcastEnabled() {
9453
+ const params = this.sender.getParameters();
9454
+ return params.encodings.length > 1;
9345
9455
  }
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
- });
9456
+ signalStreams(mLine) {
9457
+ this.streamSignaler.signalStreams(this.isSimulcastEnabled(), this.rtxEnabled, mLine);
9354
9458
  }
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;
9459
+ get senderIds() {
9460
+ return this.streamSignaler.getSenderIds();
9366
9461
  }
9367
- getReceiverId() {
9368
- return {
9369
- mid: this.mid,
9370
- rid: '1',
9371
- };
9462
+ getEncodingIndexForStreamId(id) {
9463
+ return this.streamSignaler.getEncodingIndexForStreamId(id);
9372
9464
  }
9373
- signalLocalStreams(mLine) {
9465
+ resetStreamSignaler() {
9466
+ this.streamSignaler.reset();
9374
9467
  }
9375
- signalRemoteStreams(mLine) {
9468
+ setCodecParameters(parameters) {
9469
+ this.streamSignaler.setCodecParameters(parameters);
9376
9470
  }
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));
9471
+ deleteCodecParameters(parameters) {
9472
+ this.streamSignaler.deleteCodecParameters(parameters);
9421
9473
  }
9422
9474
  }
9423
9475
 
@@ -9425,6 +9477,20 @@ function generateSsrc() {
9425
9477
  return Math.floor(Math.random() * 0xffffffff) + 1;
9426
9478
  }
9427
9479
 
9480
+ function setCustomCodecParams(mLine, paramsMap) {
9481
+ paramsMap.forEach((value, param) => {
9482
+ [...mLine.codecs.values()]
9483
+ .filter((ci) => ci.name === 'H264' || ci.name === 'opus')
9484
+ .forEach((ci) => {
9485
+ if (value === null) {
9486
+ ci.fmtParams.delete(param);
9487
+ }
9488
+ else {
9489
+ ci.fmtParams.set(param, `${value}`);
9490
+ }
9491
+ });
9492
+ });
9493
+ }
9428
9494
  class SsrcIngressStreamSignaler {
9429
9495
  constructor() {
9430
9496
  this.ssrc = generateSsrc();
@@ -9447,10 +9513,17 @@ class SsrcIngressStreamSignaler {
9447
9513
  mLine.addLine(new SsrcGroupLine('FID', [this.ssrc, this.rtxSsrc]));
9448
9514
  }
9449
9515
  }
9516
+ reset() {
9517
+ this.ssrc = generateSsrc();
9518
+ }
9450
9519
  }
9451
9520
  class SsrcEgressStreamSignaler {
9452
9521
  constructor() {
9453
9522
  this.streamIds = [];
9523
+ this.customCodecParameters = new Map();
9524
+ }
9525
+ reset() {
9526
+ this.streamIds = [];
9454
9527
  }
9455
9528
  signalStreams(simulcastEnabled, rtxEnabled, mLine) {
9456
9529
  var _a;
@@ -9520,6 +9593,7 @@ class SsrcEgressStreamSignaler {
9520
9593
  mLine.addLine(new SsrcGroupLine('SIM', this.streamIds.map((streamId) => streamId.ssrc)));
9521
9594
  addVlaExtension(mLine);
9522
9595
  }
9596
+ setCustomCodecParams(mLine, this.customCodecParameters);
9523
9597
  }
9524
9598
  getSenderIds() {
9525
9599
  return this.streamIds;
@@ -9527,64 +9601,31 @@ class SsrcEgressStreamSignaler {
9527
9601
  getEncodingIndexForStreamId(streamId) {
9528
9602
  return this.streamIds.findIndex((currStreamId) => compareStreamIds(currStreamId, streamId));
9529
9603
  }
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);
9604
+ setCodecParameters(parameters) {
9605
+ Object.entries(parameters).forEach(([param, value]) => {
9606
+ this.customCodecParameters.set(param, value);
9607
+ });
9563
9608
  }
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;
9609
+ deleteCodecParameters(parameters) {
9610
+ parameters.forEach((param) => {
9611
+ this.customCodecParameters.set(param, null);
9612
+ });
9578
9613
  }
9579
- getIngressStreamSignaler(mid) {
9580
- return this.ingressStreamsSignalersByMid.get(mid);
9614
+ }
9615
+
9616
+ class StatsManager {
9617
+ constructor(statsGetter, statsPreprocessor = () => __awaiter(this, void 0, void 0, function* () { })) {
9618
+ this.statsGetter = statsGetter;
9619
+ this.statsPreProcessor = statsPreprocessor;
9581
9620
  }
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;
9621
+ getStats() {
9622
+ return __awaiter(this, void 0, void 0, function* () {
9623
+ const statsReport = yield this.statsGetter();
9624
+ const statsMap = new Map();
9625
+ statsReport.forEach((stats, key) => statsMap.set(key, stats));
9626
+ yield this.statsPreProcessor(statsMap);
9627
+ return statsMap;
9628
+ });
9588
9629
  }
9589
9630
  }
9590
9631
 
@@ -13188,6 +13229,24 @@ function webRtcVideoContentHintToJmpVideoContentHint(hint) {
13188
13229
  }
13189
13230
  return undefined;
13190
13231
  }
13232
+ function createEgressStreamSignaler(signalingMode, mid) {
13233
+ if (signalingMode === 'MID-RID') {
13234
+ return new RidEgressStreamSignaler(mid);
13235
+ }
13236
+ if (signalingMode === 'SSRC') {
13237
+ return new SsrcEgressStreamSignaler();
13238
+ }
13239
+ throw new Error(`unknown signaling mode`);
13240
+ }
13241
+ function createIngressStreamSignaler(signalingMode, mid) {
13242
+ if (signalingMode === 'MID-RID') {
13243
+ return new RidIngressStreamSignaler(mid);
13244
+ }
13245
+ if (signalingMode === 'SSRC') {
13246
+ return new SsrcIngressStreamSignaler();
13247
+ }
13248
+ throw new Error(`unknown signaling mode`);
13249
+ }
13191
13250
  function toMediaFamily(kind) {
13192
13251
  if (kind === exports.MediaStreamTrackKind.Video) {
13193
13252
  return MediaFamily.Video;
@@ -13221,14 +13280,11 @@ class MultistreamConnection extends EventEmitter {
13221
13280
  this.pendingJmpTasks = [];
13222
13281
  this.metricsCallback = () => { };
13223
13282
  this.overuseUpdateCallback = () => { };
13224
- this.customCodecParameters = new Map();
13225
- this.midMap = new Map();
13226
- this.currentMid = 0;
13283
+ this.midPredictor = new MidPredictor();
13227
13284
  this.offerAnswerQueue = new AsyncQueue();
13228
13285
  this.options = Object.assign(Object.assign({}, defaultMultistreamConnectionOptions), userOptions);
13229
13286
  logger.info(`Creating multistream connection with options ${JSON.stringify(this.options)}`);
13230
13287
  this.initializePeerConnection();
13231
- this.streamSignalerManager = new StreamSignalerManager(this.options.streamSignalingMode);
13232
13288
  this.overuseStateManager = new OveruseStateManager((overuseState) => this.overuseUpdateCallback(overuseState));
13233
13289
  this.overuseStateManager.start();
13234
13290
  this.statsManager = new StatsManager(() => this.pc.getStats(), (stats) => this.preProcessStats(stats));
@@ -13245,16 +13301,6 @@ class MultistreamConnection extends EventEmitter {
13245
13301
  this.createSendTransceiver(MediaType.AudioSlides, contentSceneId);
13246
13302
  }
13247
13303
  }
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
13304
  initializePeerConnection() {
13259
13305
  var _a;
13260
13306
  (_a = this.pc) === null || _a === void 0 ? void 0 : _a.close();
@@ -13293,9 +13339,18 @@ class MultistreamConnection extends EventEmitter {
13293
13339
  logger.error(`addTransceiver failed due to : ${e}`);
13294
13340
  throw e;
13295
13341
  }
13296
- this.addMid(mediaType);
13342
+ const mid = this.midPredictor.getNextMid(mediaType);
13297
13343
  const csi = generateCsi(getMediaFamily(mediaType), sceneId);
13298
- this.sendTransceivers.set(mediaType, new SendOnlyTransceiver(rtcTransceiver, csi));
13344
+ const signaler = createEgressStreamSignaler(this.options.streamSignalingMode, mid);
13345
+ const transceiver = new SendOnlyTransceiver(rtcTransceiver, mid, csi, signaler);
13346
+ if (getMediaFamily(mediaType) === MediaFamily.Video) {
13347
+ transceiver.rtxEnabled = true;
13348
+ transceiver.setCodecParameters({
13349
+ 'max-mbps': `${defaultMaxVideoEncodeMbps}`,
13350
+ 'max-fs': `${defaultMaxVideoEncodeFrameSize}`,
13351
+ });
13352
+ }
13353
+ this.sendTransceivers.set(mediaType, transceiver);
13299
13354
  this.createJmpSession(mediaType);
13300
13355
  }
13301
13356
  createJmpSession(mediaType) {
@@ -13343,7 +13398,6 @@ class MultistreamConnection extends EventEmitter {
13343
13398
  }
13344
13399
  updateRequestedStreams(mediaType, requests) {
13345
13400
  const sendTransceiver = this.getSendTransceiverOrThrow(mediaType);
13346
- const signaler = this.streamSignalerManager.getEgressStreamSignalerOrThrow(sendTransceiver.mid);
13347
13401
  const mediaFamily = getMediaFamily(mediaType);
13348
13402
  const requestedIdEncodingParamsMap = new Map();
13349
13403
  const rsRequests = requests.filter((r) => isValidReceiverSelectedInfo(r.policySpecificInfo));
@@ -13364,11 +13418,9 @@ class MultistreamConnection extends EventEmitter {
13364
13418
  }
13365
13419
  const id = ids[0];
13366
13420
  const codecInfo = codecInfos[0];
13367
- const streamIdsMatched = signaler
13368
- .getSenderIds()
13369
- .some((validId) => compareStreamIds(id, validId));
13421
+ const streamIdsMatched = sendTransceiver.senderIds.some((validId) => compareStreamIds(id, validId));
13370
13422
  if (streamIdsMatched) {
13371
- const encodingIndex = signaler.getEncodingIndexForStreamId(id);
13423
+ const encodingIndex = sendTransceiver.getEncodingIndexForStreamId(id);
13372
13424
  if (encodingIndex !== -1) {
13373
13425
  const encodingParams = { maxPayloadBitsPerSecond };
13374
13426
  if (mediaFamily === MediaFamily.Video) {
@@ -13450,10 +13502,6 @@ class MultistreamConnection extends EventEmitter {
13450
13502
  return;
13451
13503
  }
13452
13504
  const streamStates = this.getVideoStreamStates(mediaType);
13453
- if (streamStates === null) {
13454
- logger.debug(`Empty streamStates, not sending MediaRequestStatus`);
13455
- return;
13456
- }
13457
13505
  const task = () => {
13458
13506
  var _a;
13459
13507
  (_a = this.jmpSessions.get(mediaType)) === null || _a === void 0 ? void 0 : _a.sendMediaRequestStatus(streamStates);
@@ -13558,14 +13606,10 @@ class MultistreamConnection extends EventEmitter {
13558
13606
  getVideoStreamStates(mediaType) {
13559
13607
  var _a, _b, _c;
13560
13608
  const sendTransceiver = this.getSendTransceiverOrThrow(mediaType);
13561
- const signaler = this.streamSignalerManager.getEgressStreamSignaler(sendTransceiver.mid);
13562
- if (!signaler) {
13563
- return null;
13564
- }
13565
13609
  const activeSimulcastLayerNumber = ((_a = sendTransceiver.publishedTrack) === null || _a === void 0 ? void 0 : _a.getNumActiveSimulcastLayers()) || 0;
13566
13610
  const published = (_b = sendTransceiver.publishedTrack) === null || _b === void 0 ? void 0 : _b.published;
13567
13611
  const muted = ((_c = sendTransceiver.publishedTrack) === null || _c === void 0 ? void 0 : _c.muted) === true;
13568
- return signaler.getSenderIds().map((id) => {
13612
+ return sendTransceiver.senderIds.map((id) => {
13569
13613
  let state;
13570
13614
  if (!published) {
13571
13615
  state = 'no source';
@@ -13573,7 +13617,7 @@ class MultistreamConnection extends EventEmitter {
13573
13617
  else if (muted) {
13574
13618
  state = 'avatar';
13575
13619
  }
13576
- else if (activeSimulcastLayerNumber < signaler.getEncodingIndexForStreamId(id)) {
13620
+ else if (activeSimulcastLayerNumber < sendTransceiver.getEncodingIndexForStreamId(id)) {
13577
13621
  state = 'no source';
13578
13622
  }
13579
13623
  else {
@@ -13589,21 +13633,16 @@ class MultistreamConnection extends EventEmitter {
13589
13633
  const rtcRtpTransceiver = this.pc.addTransceiver(toMediaStreamTrackKind(mediaType), {
13590
13634
  direction: 'recvonly',
13591
13635
  });
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
- }
13636
+ const transceiverMid = this.midPredictor.getNextMid(mediaType);
13637
+ const ingressSignaler = createIngressStreamSignaler(this.options.streamSignalingMode, transceiverMid);
13638
+ const recvOnlyTransceiver = new ReceiveOnlyTransceiver(rtcRtpTransceiver, transceiverMid, ingressSignaler);
13603
13639
  this.recvTransceivers.set(mediaType, [
13604
13640
  ...(this.recvTransceivers.get(mediaType) || []),
13605
13641
  recvOnlyTransceiver,
13606
13642
  ]);
13643
+ if (this.pc.getRemoteDescription()) {
13644
+ yield this.doLocalOfferAnswer();
13645
+ }
13607
13646
  createReceiveSlotResolve(recvOnlyTransceiver.receiveSlot);
13608
13647
  }));
13609
13648
  });
@@ -13643,7 +13682,7 @@ class MultistreamConnection extends EventEmitter {
13643
13682
  createOffer() {
13644
13683
  return __awaiter(this, void 0, void 0, function* () {
13645
13684
  if (!this.pc.getLocalDescription()) {
13646
- this.currentMid++;
13685
+ this.midPredictor.allocateMidForDatachannel();
13647
13686
  }
13648
13687
  return new Promise((createOfferResolve) => {
13649
13688
  this.offerAnswerQueue.push(() => __awaiter(this, void 0, void 0, function* () {
@@ -13669,7 +13708,6 @@ class MultistreamConnection extends EventEmitter {
13669
13708
  }
13670
13709
  setAnswer(answer) {
13671
13710
  return __awaiter(this, void 0, void 0, function* () {
13672
- const isInitialAnswer = !this.pc.getRemoteDescription();
13673
13711
  const sdp = this.preProcessRemoteAnswer(answer);
13674
13712
  if (!this.setAnswerResolve) {
13675
13713
  throw new Error(`Call to setAnswer without having previously called createOffer`);
@@ -13682,9 +13720,6 @@ class MultistreamConnection extends EventEmitter {
13682
13720
  else {
13683
13721
  logger.debug(`setAnswerResolve function was cleared between setAnswer and result of setRemoteDescription`);
13684
13722
  }
13685
- if (isInitialAnswer && this.customCodecParameters.size > 0) {
13686
- yield this.queueLocalOfferAnswer();
13687
- }
13688
13723
  }));
13689
13724
  });
13690
13725
  }
@@ -13722,43 +13757,17 @@ class MultistreamConnection extends EventEmitter {
13722
13757
  parsed.avMedia
13723
13758
  .filter((av) => av.direction === 'recvonly')
13724
13759
  .forEach((av) => {
13725
- const ingressSignaler = this.streamSignalerManager.getOrCreateIngressStreamSignaler(av.mid);
13726
- ingressSignaler.signalLocalStreams(av);
13760
+ const transceiver = this.getRecvTransceiverByMidOrThrow(av.mid);
13761
+ transceiver.signalLocalStreams(av);
13727
13762
  });
13728
13763
  parsed.avMedia
13729
- .filter((av) => av.direction === 'sendrecv')
13764
+ .filter((av) => av.direction === 'sendrecv' || av.direction === 'inactive')
13730
13765
  .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
- }
13766
+ const transceiver = this.getSendTransceiverByMidOrThrow(av.mid);
13767
+ transceiver.signalStreams(av);
13759
13768
  });
13760
13769
  if (getBrowserDetails().name !== 'Firefox') {
13761
- setupBundle(parsed, this.options.bundlePolicy, this.midMap);
13770
+ setupBundle(parsed, this.options.bundlePolicy, this.midPredictor.getMidMap());
13762
13771
  }
13763
13772
  return parsed.toString();
13764
13773
  }
@@ -13787,7 +13796,7 @@ class MultistreamConnection extends EventEmitter {
13787
13796
  }
13788
13797
  });
13789
13798
  if (getBrowserDetails().name === 'Firefox') {
13790
- setupBundle(parsed, this.options.bundlePolicy, this.midMap);
13799
+ setupBundle(parsed, this.options.bundlePolicy, this.midPredictor.getMidMap());
13791
13800
  if (this.options.bundlePolicy === 'max-bundle') {
13792
13801
  parsed.media.forEach((mline, index) => {
13793
13802
  if (index > 0) {
@@ -13802,9 +13811,10 @@ class MultistreamConnection extends EventEmitter {
13802
13811
  var _a;
13803
13812
  const parsedAnswer = parse(answer);
13804
13813
  const parsedOffer = parse((_a = this.pc.getLocalDescription()) === null || _a === void 0 ? void 0 : _a.sdp);
13805
- matchMlinesInAnswer(parsedOffer, parsedAnswer, this.streamSignalerManager);
13814
+ const recvTransceiversByMid = new Map([...this.recvTransceivers.values()].flat().map((t) => [t.mid, t]));
13815
+ matchMlinesInAnswer(parsedOffer, parsedAnswer, recvTransceiversByMid);
13806
13816
  if (getBrowserDetails().name === 'Firefox') {
13807
- setupBundle(parsedAnswer, this.options.bundlePolicy, this.midMap);
13817
+ setupBundle(parsedAnswer, this.options.bundlePolicy, this.midPredictor.getMidMap());
13808
13818
  if (this.options.bundlePolicy === 'max-bundle') {
13809
13819
  const { ufrag, pwd } = parsedAnswer.media[0].iceInfo;
13810
13820
  parsedAnswer.media.forEach((mline, index) => {
@@ -13824,6 +13834,20 @@ class MultistreamConnection extends EventEmitter {
13824
13834
  }
13825
13835
  return sendTransceiver;
13826
13836
  }
13837
+ getSendTransceiverByMidOrThrow(mid) {
13838
+ const transceiver = [...this.sendTransceivers.values()].find((t) => t.mid === mid);
13839
+ if (!transceiver) {
13840
+ throw new Error(`Unable to find send transceiver with mid ${mid}`);
13841
+ }
13842
+ return transceiver;
13843
+ }
13844
+ getRecvTransceiverByMidOrThrow(mid) {
13845
+ const transceiver = [...this.recvTransceivers.values()].flat().find((t) => t.mid === mid);
13846
+ if (!transceiver) {
13847
+ throw new Error(`Unable to find recv transceiver with mid ${mid}`);
13848
+ }
13849
+ return transceiver;
13850
+ }
13827
13851
  getPublishedTracks() {
13828
13852
  return [...this.sendTransceivers.values()]
13829
13853
  .map((transceiver) => transceiver.publishedTrack)
@@ -13831,11 +13855,8 @@ class MultistreamConnection extends EventEmitter {
13831
13855
  }
13832
13856
  setCodecParameters(mediaType, parameters) {
13833
13857
  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);
13858
+ const transceiver = this.sendTransceivers.get(mediaType);
13859
+ transceiver === null || transceiver === void 0 ? void 0 : transceiver.setCodecParameters(parameters);
13839
13860
  if (this.pc.getRemoteDescription()) {
13840
13861
  yield this.queueLocalOfferAnswer();
13841
13862
  }
@@ -13843,11 +13864,8 @@ class MultistreamConnection extends EventEmitter {
13843
13864
  }
13844
13865
  deleteCodecParameters(mediaType, parameters) {
13845
13866
  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);
13867
+ const transceiver = this.sendTransceivers.get(mediaType);
13868
+ transceiver === null || transceiver === void 0 ? void 0 : transceiver.deleteCodecParameters(parameters);
13851
13869
  if (this.pc.getRemoteDescription()) {
13852
13870
  yield this.queueLocalOfferAnswer();
13853
13871
  }
@@ -13891,32 +13909,34 @@ class MultistreamConnection extends EventEmitter {
13891
13909
  this.options = Object.assign(Object.assign({}, this.options), userOptions);
13892
13910
  }
13893
13911
  logger.info(`Renewing multistream connection with options ${JSON.stringify(this.options)}`);
13894
- this.clearMids();
13912
+ this.midPredictor.reset();
13895
13913
  this.initializePeerConnection();
13896
- this.streamSignalerManager = new StreamSignalerManager(this.options.streamSignalingMode);
13897
13914
  const mainSceneId = generateSceneId();
13898
13915
  const slidesSceneId = generateSceneId();
13899
13916
  this.sendTransceivers.forEach((transceiver, mediaType) => {
13900
13917
  var _a;
13901
13918
  const mediaContent = getMediaContent(mediaType);
13902
13919
  const sceneId = mediaContent === MediaContent.Main ? mainSceneId : slidesSceneId;
13903
- this.addMid(mediaType);
13920
+ const mid = this.midPredictor.getNextMid(mediaType);
13904
13921
  transceiver.replaceTransceiver(this.pc.addTransceiver(toMediaStreamTrackKind(mediaType), {
13905
13922
  direction: 'sendrecv',
13906
13923
  sendEncodings: getMediaFamily(mediaType) === MediaFamily.Video
13907
13924
  ? this.getVideoEncodingOptions(mediaContent)
13908
13925
  : undefined,
13909
13926
  }));
13927
+ transceiver.mid = mid;
13910
13928
  transceiver.csi = generateCsi(getMediaFamily(mediaType), sceneId);
13929
+ transceiver.resetStreamSignaler();
13911
13930
  (_a = this.jmpSessions.get(mediaType)) === null || _a === void 0 ? void 0 : _a.close();
13912
13931
  this.createJmpSession(mediaType);
13913
13932
  });
13914
13933
  this.recvTransceivers.forEach((transceivers, mediaType) => {
13915
13934
  transceivers.forEach((t) => {
13916
- this.addMid(mediaType);
13935
+ const mid = this.midPredictor.getNextMid(mediaType);
13917
13936
  t.replaceTransceiver(this.pc.addTransceiver(toMediaStreamTrackKind(mediaType), {
13918
13937
  direction: 'recvonly',
13919
13938
  }));
13939
+ t.mid = mid;
13920
13940
  });
13921
13941
  });
13922
13942
  }
@@ -13965,10 +13985,7 @@ class MultistreamConnection extends EventEmitter {
13965
13985
  statsToModify.mid = (_a = transceiver.receiveSlot.id) === null || _a === void 0 ? void 0 : _a.mid;
13966
13986
  statsToModify.csi = transceiver.receiveSlot.currentRxCsi;
13967
13987
  statsToModify.mediaType = mediaType;
13968
- const signaler = this.streamSignalerManager.getIngressStreamSignaler(statsToModify.mid);
13969
- if (signaler) {
13970
- Object.assign(statsToModify, signaler.getReceiverId());
13971
- }
13988
+ Object.assign(statsToModify, transceiver.receiverId);
13972
13989
  stats.set(receiverStats.id, statsToModify);
13973
13990
  }
13974
13991
  });