@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 +313 -296
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +313 -296
- 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
|
-
|
|
9464
|
+
setCodecParameters(parameters) {
|
|
9465
|
+
this.streamSignaler.setCodecParameters(parameters);
|
|
9372
9466
|
}
|
|
9373
|
-
|
|
9374
|
-
|
|
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
|
-
|
|
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);
|
|
@@ -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
|
|
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 <
|
|
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.
|
|
13589
|
-
const
|
|
13590
|
-
|
|
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.
|
|
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
|
|
13722
|
-
|
|
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
|
|
13728
|
-
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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
|
|
13831
|
-
|
|
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
|
|
13843
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
});
|