@webex/web-client-media-engine 2.1.1 → 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 +315 -301
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +315 -301
- package/dist/esm/index.js.map +1 -1
- package/dist/types/index.d.ts +30 -9
- package/package.json +1 -1
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,
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
9343
|
-
|
|
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
|
-
|
|
9364
|
-
return
|
|
9365
|
-
mid: this.mid,
|
|
9366
|
-
rid: '1',
|
|
9367
|
-
};
|
|
9458
|
+
getEncodingIndexForStreamId(id) {
|
|
9459
|
+
return this.streamSignaler.getEncodingIndexForStreamId(id);
|
|
9368
9460
|
}
|
|
9369
|
-
|
|
9461
|
+
resetStreamSignaler() {
|
|
9462
|
+
this.streamSignaler.reset();
|
|
9370
9463
|
}
|
|
9371
|
-
|
|
9372
|
-
|
|
9373
|
-
}
|
|
9374
|
-
class RidEgressStreamSignaler {
|
|
9375
|
-
constructor(mid) {
|
|
9376
|
-
this.streamIds = [];
|
|
9377
|
-
this.mid = mid;
|
|
9464
|
+
setCodecParameters(parameters) {
|
|
9465
|
+
this.streamSignaler.setCodecParameters(parameters);
|
|
9378
9466
|
}
|
|
9379
|
-
|
|
9380
|
-
|
|
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
|
-
|
|
9529
|
-
|
|
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
|
-
|
|
9561
|
-
|
|
9562
|
-
|
|
9563
|
-
|
|
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
|
-
|
|
9576
|
-
|
|
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
|
-
|
|
9579
|
-
|
|
9580
|
-
|
|
9581
|
-
|
|
9582
|
-
|
|
9583
|
-
|
|
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.
|
|
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.
|
|
13338
|
+
const mid = this.midPredictor.getNextMid(mediaType);
|
|
13293
13339
|
const csi = generateCsi(getMediaFamily(mediaType), sceneId);
|
|
13294
|
-
this.
|
|
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 =
|
|
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 =
|
|
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);
|
|
@@ -13543,13 +13591,10 @@ class MultistreamConnection extends EventEmitter {
|
|
|
13543
13591
|
track.off(LocalTrack.Events.Muted, onTrackMute);
|
|
13544
13592
|
track.off(LocalTrack.Events.PublishedStateUpdate, onTrackPublish);
|
|
13545
13593
|
track.off(LocalTrack.Events.TrackConstraintsChange, onTrackResolutionChange);
|
|
13546
|
-
if (!track.muted) {
|
|
13547
|
-
this.sendSourceAdvertisement(mediaType);
|
|
13548
|
-
this.sendMediaRequestStatus(mediaType);
|
|
13549
|
-
}
|
|
13550
13594
|
}
|
|
13551
|
-
|
|
13595
|
+
if (!track.muted) {
|
|
13552
13596
|
this.sendSourceAdvertisement(mediaType);
|
|
13597
|
+
this.sendMediaRequestStatus(mediaType);
|
|
13553
13598
|
}
|
|
13554
13599
|
};
|
|
13555
13600
|
track.on(LocalTrack.Events.PublishedStateUpdate, onTrackPublish);
|
|
@@ -13557,14 +13602,10 @@ class MultistreamConnection extends EventEmitter {
|
|
|
13557
13602
|
getVideoStreamStates(mediaType) {
|
|
13558
13603
|
var _a, _b, _c;
|
|
13559
13604
|
const sendTransceiver = this.getSendTransceiverOrThrow(mediaType);
|
|
13560
|
-
const signaler = this.streamSignalerManager.getEgressStreamSignaler(sendTransceiver.mid);
|
|
13561
|
-
if (!signaler) {
|
|
13562
|
-
return null;
|
|
13563
|
-
}
|
|
13564
13605
|
const activeSimulcastLayerNumber = ((_a = sendTransceiver.publishedTrack) === null || _a === void 0 ? void 0 : _a.getNumActiveSimulcastLayers()) || 0;
|
|
13565
13606
|
const published = (_b = sendTransceiver.publishedTrack) === null || _b === void 0 ? void 0 : _b.published;
|
|
13566
13607
|
const muted = ((_c = sendTransceiver.publishedTrack) === null || _c === void 0 ? void 0 : _c.muted) === true;
|
|
13567
|
-
return
|
|
13608
|
+
return sendTransceiver.senderIds.map((id) => {
|
|
13568
13609
|
let state;
|
|
13569
13610
|
if (!published) {
|
|
13570
13611
|
state = 'no source';
|
|
@@ -13572,7 +13613,7 @@ class MultistreamConnection extends EventEmitter {
|
|
|
13572
13613
|
else if (muted) {
|
|
13573
13614
|
state = 'avatar';
|
|
13574
13615
|
}
|
|
13575
|
-
else if (activeSimulcastLayerNumber <
|
|
13616
|
+
else if (activeSimulcastLayerNumber < sendTransceiver.getEncodingIndexForStreamId(id)) {
|
|
13576
13617
|
state = 'no source';
|
|
13577
13618
|
}
|
|
13578
13619
|
else {
|
|
@@ -13588,21 +13629,16 @@ class MultistreamConnection extends EventEmitter {
|
|
|
13588
13629
|
const rtcRtpTransceiver = this.pc.addTransceiver(toMediaStreamTrackKind(mediaType), {
|
|
13589
13630
|
direction: 'recvonly',
|
|
13590
13631
|
});
|
|
13591
|
-
this.
|
|
13592
|
-
const
|
|
13593
|
-
|
|
13594
|
-
if (!ingressSignaler) {
|
|
13595
|
-
return null;
|
|
13596
|
-
}
|
|
13597
|
-
return ingressSignaler.getReceiverId();
|
|
13598
|
-
});
|
|
13599
|
-
if (this.pc.getRemoteDescription()) {
|
|
13600
|
-
yield this.doLocalOfferAnswer();
|
|
13601
|
-
}
|
|
13632
|
+
const transceiverMid = this.midPredictor.getNextMid(mediaType);
|
|
13633
|
+
const ingressSignaler = createIngressStreamSignaler(this.options.streamSignalingMode, transceiverMid);
|
|
13634
|
+
const recvOnlyTransceiver = new ReceiveOnlyTransceiver(rtcRtpTransceiver, transceiverMid, ingressSignaler);
|
|
13602
13635
|
this.recvTransceivers.set(mediaType, [
|
|
13603
13636
|
...(this.recvTransceivers.get(mediaType) || []),
|
|
13604
13637
|
recvOnlyTransceiver,
|
|
13605
13638
|
]);
|
|
13639
|
+
if (this.pc.getRemoteDescription()) {
|
|
13640
|
+
yield this.doLocalOfferAnswer();
|
|
13641
|
+
}
|
|
13606
13642
|
createReceiveSlotResolve(recvOnlyTransceiver.receiveSlot);
|
|
13607
13643
|
}));
|
|
13608
13644
|
});
|
|
@@ -13642,7 +13678,7 @@ class MultistreamConnection extends EventEmitter {
|
|
|
13642
13678
|
createOffer() {
|
|
13643
13679
|
return __awaiter(this, void 0, void 0, function* () {
|
|
13644
13680
|
if (!this.pc.getLocalDescription()) {
|
|
13645
|
-
this.
|
|
13681
|
+
this.midPredictor.allocateMidForDatachannel();
|
|
13646
13682
|
}
|
|
13647
13683
|
return new Promise((createOfferResolve) => {
|
|
13648
13684
|
this.offerAnswerQueue.push(() => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -13668,7 +13704,6 @@ class MultistreamConnection extends EventEmitter {
|
|
|
13668
13704
|
}
|
|
13669
13705
|
setAnswer(answer) {
|
|
13670
13706
|
return __awaiter(this, void 0, void 0, function* () {
|
|
13671
|
-
const isInitialAnswer = !this.pc.getRemoteDescription();
|
|
13672
13707
|
const sdp = this.preProcessRemoteAnswer(answer);
|
|
13673
13708
|
if (!this.setAnswerResolve) {
|
|
13674
13709
|
throw new Error(`Call to setAnswer without having previously called createOffer`);
|
|
@@ -13681,9 +13716,6 @@ class MultistreamConnection extends EventEmitter {
|
|
|
13681
13716
|
else {
|
|
13682
13717
|
logger.debug(`setAnswerResolve function was cleared between setAnswer and result of setRemoteDescription`);
|
|
13683
13718
|
}
|
|
13684
|
-
if (isInitialAnswer && this.customCodecParameters.size > 0) {
|
|
13685
|
-
yield this.queueLocalOfferAnswer();
|
|
13686
|
-
}
|
|
13687
13719
|
}));
|
|
13688
13720
|
});
|
|
13689
13721
|
}
|
|
@@ -13721,43 +13753,17 @@ class MultistreamConnection extends EventEmitter {
|
|
|
13721
13753
|
parsed.avMedia
|
|
13722
13754
|
.filter((av) => av.direction === 'recvonly')
|
|
13723
13755
|
.forEach((av) => {
|
|
13724
|
-
const
|
|
13725
|
-
|
|
13756
|
+
const transceiver = this.getRecvTransceiverByMidOrThrow(av.mid);
|
|
13757
|
+
transceiver.signalLocalStreams(av);
|
|
13726
13758
|
});
|
|
13727
13759
|
parsed.avMedia
|
|
13728
|
-
.filter((av) => av.direction === 'sendrecv')
|
|
13760
|
+
.filter((av) => av.direction === 'sendrecv' || av.direction === 'inactive')
|
|
13729
13761
|
.forEach((av) => {
|
|
13730
|
-
const
|
|
13731
|
-
|
|
13732
|
-
const rtxEnabled = av.type === 'video';
|
|
13733
|
-
egressSignaler.signalStreams(simulcastEnabled, rtxEnabled, av);
|
|
13734
|
-
if (av.type === 'video') {
|
|
13735
|
-
[...av.codecs.values()]
|
|
13736
|
-
.filter((ci) => ci.name === 'H264')
|
|
13737
|
-
.forEach((ci) => {
|
|
13738
|
-
ci.fmtParams.set('max-mbps', `${defaultMaxVideoEncodeMbps}`);
|
|
13739
|
-
ci.fmtParams.set('max-fs', `${defaultMaxVideoEncodeFrameSize}`);
|
|
13740
|
-
});
|
|
13741
|
-
}
|
|
13742
|
-
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; });
|
|
13743
|
-
if (mediaType && this.customCodecParameters.has(mediaType)) {
|
|
13744
|
-
[...av.codecs.values()]
|
|
13745
|
-
.filter((ci) => ci.name === (av.type === 'audio' ? 'opus' : 'H264'))
|
|
13746
|
-
.forEach((ci) => {
|
|
13747
|
-
var _a;
|
|
13748
|
-
(_a = this.customCodecParameters.get(mediaType)) === null || _a === void 0 ? void 0 : _a.forEach((value, param) => {
|
|
13749
|
-
if (value === null) {
|
|
13750
|
-
ci.fmtParams.delete(param);
|
|
13751
|
-
}
|
|
13752
|
-
else {
|
|
13753
|
-
ci.fmtParams.set(param, `${value}`);
|
|
13754
|
-
}
|
|
13755
|
-
});
|
|
13756
|
-
});
|
|
13757
|
-
}
|
|
13762
|
+
const transceiver = this.getSendTransceiverByMidOrThrow(av.mid);
|
|
13763
|
+
transceiver.signalStreams(av);
|
|
13758
13764
|
});
|
|
13759
13765
|
if (getBrowserDetails().name !== 'Firefox') {
|
|
13760
|
-
setupBundle(parsed, this.options.bundlePolicy, this.
|
|
13766
|
+
setupBundle(parsed, this.options.bundlePolicy, this.midPredictor.getMidMap());
|
|
13761
13767
|
}
|
|
13762
13768
|
return parsed.toString();
|
|
13763
13769
|
}
|
|
@@ -13786,7 +13792,7 @@ class MultistreamConnection extends EventEmitter {
|
|
|
13786
13792
|
}
|
|
13787
13793
|
});
|
|
13788
13794
|
if (getBrowserDetails().name === 'Firefox') {
|
|
13789
|
-
setupBundle(parsed, this.options.bundlePolicy, this.
|
|
13795
|
+
setupBundle(parsed, this.options.bundlePolicy, this.midPredictor.getMidMap());
|
|
13790
13796
|
if (this.options.bundlePolicy === 'max-bundle') {
|
|
13791
13797
|
parsed.media.forEach((mline, index) => {
|
|
13792
13798
|
if (index > 0) {
|
|
@@ -13801,9 +13807,10 @@ class MultistreamConnection extends EventEmitter {
|
|
|
13801
13807
|
var _a;
|
|
13802
13808
|
const parsedAnswer = parse(answer);
|
|
13803
13809
|
const parsedOffer = parse((_a = this.pc.getLocalDescription()) === null || _a === void 0 ? void 0 : _a.sdp);
|
|
13804
|
-
|
|
13810
|
+
const recvTransceiversByMid = new Map([...this.recvTransceivers.values()].flat().map((t) => [t.mid, t]));
|
|
13811
|
+
matchMlinesInAnswer(parsedOffer, parsedAnswer, recvTransceiversByMid);
|
|
13805
13812
|
if (getBrowserDetails().name === 'Firefox') {
|
|
13806
|
-
setupBundle(parsedAnswer, this.options.bundlePolicy, this.
|
|
13813
|
+
setupBundle(parsedAnswer, this.options.bundlePolicy, this.midPredictor.getMidMap());
|
|
13807
13814
|
if (this.options.bundlePolicy === 'max-bundle') {
|
|
13808
13815
|
const { ufrag, pwd } = parsedAnswer.media[0].iceInfo;
|
|
13809
13816
|
parsedAnswer.media.forEach((mline, index) => {
|
|
@@ -13823,6 +13830,20 @@ class MultistreamConnection extends EventEmitter {
|
|
|
13823
13830
|
}
|
|
13824
13831
|
return sendTransceiver;
|
|
13825
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
|
+
}
|
|
13826
13847
|
getPublishedTracks() {
|
|
13827
13848
|
return [...this.sendTransceivers.values()]
|
|
13828
13849
|
.map((transceiver) => transceiver.publishedTrack)
|
|
@@ -13830,11 +13851,8 @@ class MultistreamConnection extends EventEmitter {
|
|
|
13830
13851
|
}
|
|
13831
13852
|
setCodecParameters(mediaType, parameters) {
|
|
13832
13853
|
return __awaiter(this, void 0, void 0, function* () {
|
|
13833
|
-
const
|
|
13834
|
-
|
|
13835
|
-
currentParams.set(param, value);
|
|
13836
|
-
});
|
|
13837
|
-
this.customCodecParameters.set(mediaType, currentParams);
|
|
13854
|
+
const transceiver = this.sendTransceivers.get(mediaType);
|
|
13855
|
+
transceiver === null || transceiver === void 0 ? void 0 : transceiver.setCodecParameters(parameters);
|
|
13838
13856
|
if (this.pc.getRemoteDescription()) {
|
|
13839
13857
|
yield this.queueLocalOfferAnswer();
|
|
13840
13858
|
}
|
|
@@ -13842,11 +13860,8 @@ class MultistreamConnection extends EventEmitter {
|
|
|
13842
13860
|
}
|
|
13843
13861
|
deleteCodecParameters(mediaType, parameters) {
|
|
13844
13862
|
return __awaiter(this, void 0, void 0, function* () {
|
|
13845
|
-
const
|
|
13846
|
-
|
|
13847
|
-
currentParams.set(param, null);
|
|
13848
|
-
});
|
|
13849
|
-
this.customCodecParameters.set(mediaType, currentParams);
|
|
13863
|
+
const transceiver = this.sendTransceivers.get(mediaType);
|
|
13864
|
+
transceiver === null || transceiver === void 0 ? void 0 : transceiver.deleteCodecParameters(parameters);
|
|
13850
13865
|
if (this.pc.getRemoteDescription()) {
|
|
13851
13866
|
yield this.queueLocalOfferAnswer();
|
|
13852
13867
|
}
|
|
@@ -13890,32 +13905,34 @@ class MultistreamConnection extends EventEmitter {
|
|
|
13890
13905
|
this.options = Object.assign(Object.assign({}, this.options), userOptions);
|
|
13891
13906
|
}
|
|
13892
13907
|
logger.info(`Renewing multistream connection with options ${JSON.stringify(this.options)}`);
|
|
13893
|
-
this.
|
|
13908
|
+
this.midPredictor.reset();
|
|
13894
13909
|
this.initializePeerConnection();
|
|
13895
|
-
this.streamSignalerManager = new StreamSignalerManager(this.options.streamSignalingMode);
|
|
13896
13910
|
const mainSceneId = generateSceneId();
|
|
13897
13911
|
const slidesSceneId = generateSceneId();
|
|
13898
13912
|
this.sendTransceivers.forEach((transceiver, mediaType) => {
|
|
13899
13913
|
var _a;
|
|
13900
13914
|
const mediaContent = getMediaContent(mediaType);
|
|
13901
13915
|
const sceneId = mediaContent === MediaContent.Main ? mainSceneId : slidesSceneId;
|
|
13902
|
-
this.
|
|
13916
|
+
const mid = this.midPredictor.getNextMid(mediaType);
|
|
13903
13917
|
transceiver.replaceTransceiver(this.pc.addTransceiver(toMediaStreamTrackKind(mediaType), {
|
|
13904
13918
|
direction: 'sendrecv',
|
|
13905
13919
|
sendEncodings: getMediaFamily(mediaType) === MediaFamily.Video
|
|
13906
13920
|
? this.getVideoEncodingOptions(mediaContent)
|
|
13907
13921
|
: undefined,
|
|
13908
13922
|
}));
|
|
13923
|
+
transceiver.mid = mid;
|
|
13909
13924
|
transceiver.csi = generateCsi(getMediaFamily(mediaType), sceneId);
|
|
13925
|
+
transceiver.resetStreamSignaler();
|
|
13910
13926
|
(_a = this.jmpSessions.get(mediaType)) === null || _a === void 0 ? void 0 : _a.close();
|
|
13911
13927
|
this.createJmpSession(mediaType);
|
|
13912
13928
|
});
|
|
13913
13929
|
this.recvTransceivers.forEach((transceivers, mediaType) => {
|
|
13914
13930
|
transceivers.forEach((t) => {
|
|
13915
|
-
this.
|
|
13931
|
+
const mid = this.midPredictor.getNextMid(mediaType);
|
|
13916
13932
|
t.replaceTransceiver(this.pc.addTransceiver(toMediaStreamTrackKind(mediaType), {
|
|
13917
13933
|
direction: 'recvonly',
|
|
13918
13934
|
}));
|
|
13935
|
+
t.mid = mid;
|
|
13919
13936
|
});
|
|
13920
13937
|
});
|
|
13921
13938
|
}
|
|
@@ -13964,10 +13981,7 @@ class MultistreamConnection extends EventEmitter {
|
|
|
13964
13981
|
statsToModify.mid = (_a = transceiver.receiveSlot.id) === null || _a === void 0 ? void 0 : _a.mid;
|
|
13965
13982
|
statsToModify.csi = transceiver.receiveSlot.currentRxCsi;
|
|
13966
13983
|
statsToModify.mediaType = mediaType;
|
|
13967
|
-
|
|
13968
|
-
if (signaler) {
|
|
13969
|
-
Object.assign(statsToModify, signaler.getReceiverId());
|
|
13970
|
-
}
|
|
13984
|
+
Object.assign(statsToModify, transceiver.receiverId);
|
|
13971
13985
|
stats.set(receiverStats.id, statsToModify);
|
|
13972
13986
|
}
|
|
13973
13987
|
});
|