@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/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,
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
9347
|
-
|
|
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
|
-
|
|
9368
|
-
return
|
|
9369
|
-
mid: this.mid,
|
|
9370
|
-
rid: '1',
|
|
9371
|
-
};
|
|
9462
|
+
getEncodingIndexForStreamId(id) {
|
|
9463
|
+
return this.streamSignaler.getEncodingIndexForStreamId(id);
|
|
9372
9464
|
}
|
|
9373
|
-
|
|
9465
|
+
resetStreamSignaler() {
|
|
9466
|
+
this.streamSignaler.reset();
|
|
9374
9467
|
}
|
|
9375
|
-
|
|
9468
|
+
setCodecParameters(parameters) {
|
|
9469
|
+
this.streamSignaler.setCodecParameters(parameters);
|
|
9376
9470
|
}
|
|
9377
|
-
|
|
9378
|
-
|
|
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
|
-
|
|
9533
|
-
|
|
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
|
-
|
|
9565
|
-
|
|
9566
|
-
|
|
9567
|
-
|
|
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
|
-
|
|
9580
|
-
|
|
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
|
-
|
|
9583
|
-
|
|
9584
|
-
|
|
9585
|
-
|
|
9586
|
-
|
|
9587
|
-
|
|
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.
|
|
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.
|
|
13342
|
+
const mid = this.midPredictor.getNextMid(mediaType);
|
|
13297
13343
|
const csi = generateCsi(getMediaFamily(mediaType), sceneId);
|
|
13298
|
-
this.
|
|
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 =
|
|
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 =
|
|
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
|
|
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 <
|
|
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.
|
|
13593
|
-
const
|
|
13594
|
-
|
|
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.
|
|
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
|
|
13726
|
-
|
|
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
|
|
13732
|
-
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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
|
|
13835
|
-
|
|
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
|
|
13847
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
});
|