@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/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
|
-
|
|
9376
|
-
|
|
9377
|
-
}
|
|
9378
|
-
class RidEgressStreamSignaler {
|
|
9379
|
-
constructor(mid) {
|
|
9380
|
-
this.streamIds = [];
|
|
9381
|
-
this.mid = mid;
|
|
9468
|
+
setCodecParameters(parameters) {
|
|
9469
|
+
this.streamSignaler.setCodecParameters(parameters);
|
|
9382
9470
|
}
|
|
9383
|
-
|
|
9384
|
-
|
|
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);
|
|
@@ -13547,13 +13595,10 @@ class MultistreamConnection extends EventEmitter {
|
|
|
13547
13595
|
track.off(LocalTrack.Events.Muted, onTrackMute);
|
|
13548
13596
|
track.off(LocalTrack.Events.PublishedStateUpdate, onTrackPublish);
|
|
13549
13597
|
track.off(LocalTrack.Events.TrackConstraintsChange, onTrackResolutionChange);
|
|
13550
|
-
if (!track.muted) {
|
|
13551
|
-
this.sendSourceAdvertisement(mediaType);
|
|
13552
|
-
this.sendMediaRequestStatus(mediaType);
|
|
13553
|
-
}
|
|
13554
13598
|
}
|
|
13555
|
-
|
|
13599
|
+
if (!track.muted) {
|
|
13556
13600
|
this.sendSourceAdvertisement(mediaType);
|
|
13601
|
+
this.sendMediaRequestStatus(mediaType);
|
|
13557
13602
|
}
|
|
13558
13603
|
};
|
|
13559
13604
|
track.on(LocalTrack.Events.PublishedStateUpdate, onTrackPublish);
|
|
@@ -13561,14 +13606,10 @@ class MultistreamConnection extends EventEmitter {
|
|
|
13561
13606
|
getVideoStreamStates(mediaType) {
|
|
13562
13607
|
var _a, _b, _c;
|
|
13563
13608
|
const sendTransceiver = this.getSendTransceiverOrThrow(mediaType);
|
|
13564
|
-
const signaler = this.streamSignalerManager.getEgressStreamSignaler(sendTransceiver.mid);
|
|
13565
|
-
if (!signaler) {
|
|
13566
|
-
return null;
|
|
13567
|
-
}
|
|
13568
13609
|
const activeSimulcastLayerNumber = ((_a = sendTransceiver.publishedTrack) === null || _a === void 0 ? void 0 : _a.getNumActiveSimulcastLayers()) || 0;
|
|
13569
13610
|
const published = (_b = sendTransceiver.publishedTrack) === null || _b === void 0 ? void 0 : _b.published;
|
|
13570
13611
|
const muted = ((_c = sendTransceiver.publishedTrack) === null || _c === void 0 ? void 0 : _c.muted) === true;
|
|
13571
|
-
return
|
|
13612
|
+
return sendTransceiver.senderIds.map((id) => {
|
|
13572
13613
|
let state;
|
|
13573
13614
|
if (!published) {
|
|
13574
13615
|
state = 'no source';
|
|
@@ -13576,7 +13617,7 @@ class MultistreamConnection extends EventEmitter {
|
|
|
13576
13617
|
else if (muted) {
|
|
13577
13618
|
state = 'avatar';
|
|
13578
13619
|
}
|
|
13579
|
-
else if (activeSimulcastLayerNumber <
|
|
13620
|
+
else if (activeSimulcastLayerNumber < sendTransceiver.getEncodingIndexForStreamId(id)) {
|
|
13580
13621
|
state = 'no source';
|
|
13581
13622
|
}
|
|
13582
13623
|
else {
|
|
@@ -13592,21 +13633,16 @@ class MultistreamConnection extends EventEmitter {
|
|
|
13592
13633
|
const rtcRtpTransceiver = this.pc.addTransceiver(toMediaStreamTrackKind(mediaType), {
|
|
13593
13634
|
direction: 'recvonly',
|
|
13594
13635
|
});
|
|
13595
|
-
this.
|
|
13596
|
-
const
|
|
13597
|
-
|
|
13598
|
-
if (!ingressSignaler) {
|
|
13599
|
-
return null;
|
|
13600
|
-
}
|
|
13601
|
-
return ingressSignaler.getReceiverId();
|
|
13602
|
-
});
|
|
13603
|
-
if (this.pc.getRemoteDescription()) {
|
|
13604
|
-
yield this.doLocalOfferAnswer();
|
|
13605
|
-
}
|
|
13636
|
+
const transceiverMid = this.midPredictor.getNextMid(mediaType);
|
|
13637
|
+
const ingressSignaler = createIngressStreamSignaler(this.options.streamSignalingMode, transceiverMid);
|
|
13638
|
+
const recvOnlyTransceiver = new ReceiveOnlyTransceiver(rtcRtpTransceiver, transceiverMid, ingressSignaler);
|
|
13606
13639
|
this.recvTransceivers.set(mediaType, [
|
|
13607
13640
|
...(this.recvTransceivers.get(mediaType) || []),
|
|
13608
13641
|
recvOnlyTransceiver,
|
|
13609
13642
|
]);
|
|
13643
|
+
if (this.pc.getRemoteDescription()) {
|
|
13644
|
+
yield this.doLocalOfferAnswer();
|
|
13645
|
+
}
|
|
13610
13646
|
createReceiveSlotResolve(recvOnlyTransceiver.receiveSlot);
|
|
13611
13647
|
}));
|
|
13612
13648
|
});
|
|
@@ -13646,7 +13682,7 @@ class MultistreamConnection extends EventEmitter {
|
|
|
13646
13682
|
createOffer() {
|
|
13647
13683
|
return __awaiter(this, void 0, void 0, function* () {
|
|
13648
13684
|
if (!this.pc.getLocalDescription()) {
|
|
13649
|
-
this.
|
|
13685
|
+
this.midPredictor.allocateMidForDatachannel();
|
|
13650
13686
|
}
|
|
13651
13687
|
return new Promise((createOfferResolve) => {
|
|
13652
13688
|
this.offerAnswerQueue.push(() => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -13672,7 +13708,6 @@ class MultistreamConnection extends EventEmitter {
|
|
|
13672
13708
|
}
|
|
13673
13709
|
setAnswer(answer) {
|
|
13674
13710
|
return __awaiter(this, void 0, void 0, function* () {
|
|
13675
|
-
const isInitialAnswer = !this.pc.getRemoteDescription();
|
|
13676
13711
|
const sdp = this.preProcessRemoteAnswer(answer);
|
|
13677
13712
|
if (!this.setAnswerResolve) {
|
|
13678
13713
|
throw new Error(`Call to setAnswer without having previously called createOffer`);
|
|
@@ -13685,9 +13720,6 @@ class MultistreamConnection extends EventEmitter {
|
|
|
13685
13720
|
else {
|
|
13686
13721
|
logger.debug(`setAnswerResolve function was cleared between setAnswer and result of setRemoteDescription`);
|
|
13687
13722
|
}
|
|
13688
|
-
if (isInitialAnswer && this.customCodecParameters.size > 0) {
|
|
13689
|
-
yield this.queueLocalOfferAnswer();
|
|
13690
|
-
}
|
|
13691
13723
|
}));
|
|
13692
13724
|
});
|
|
13693
13725
|
}
|
|
@@ -13725,43 +13757,17 @@ class MultistreamConnection extends EventEmitter {
|
|
|
13725
13757
|
parsed.avMedia
|
|
13726
13758
|
.filter((av) => av.direction === 'recvonly')
|
|
13727
13759
|
.forEach((av) => {
|
|
13728
|
-
const
|
|
13729
|
-
|
|
13760
|
+
const transceiver = this.getRecvTransceiverByMidOrThrow(av.mid);
|
|
13761
|
+
transceiver.signalLocalStreams(av);
|
|
13730
13762
|
});
|
|
13731
13763
|
parsed.avMedia
|
|
13732
|
-
.filter((av) => av.direction === 'sendrecv')
|
|
13764
|
+
.filter((av) => av.direction === 'sendrecv' || av.direction === 'inactive')
|
|
13733
13765
|
.forEach((av) => {
|
|
13734
|
-
const
|
|
13735
|
-
|
|
13736
|
-
const rtxEnabled = av.type === 'video';
|
|
13737
|
-
egressSignaler.signalStreams(simulcastEnabled, rtxEnabled, av);
|
|
13738
|
-
if (av.type === 'video') {
|
|
13739
|
-
[...av.codecs.values()]
|
|
13740
|
-
.filter((ci) => ci.name === 'H264')
|
|
13741
|
-
.forEach((ci) => {
|
|
13742
|
-
ci.fmtParams.set('max-mbps', `${defaultMaxVideoEncodeMbps}`);
|
|
13743
|
-
ci.fmtParams.set('max-fs', `${defaultMaxVideoEncodeFrameSize}`);
|
|
13744
|
-
});
|
|
13745
|
-
}
|
|
13746
|
-
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; });
|
|
13747
|
-
if (mediaType && this.customCodecParameters.has(mediaType)) {
|
|
13748
|
-
[...av.codecs.values()]
|
|
13749
|
-
.filter((ci) => ci.name === (av.type === 'audio' ? 'opus' : 'H264'))
|
|
13750
|
-
.forEach((ci) => {
|
|
13751
|
-
var _a;
|
|
13752
|
-
(_a = this.customCodecParameters.get(mediaType)) === null || _a === void 0 ? void 0 : _a.forEach((value, param) => {
|
|
13753
|
-
if (value === null) {
|
|
13754
|
-
ci.fmtParams.delete(param);
|
|
13755
|
-
}
|
|
13756
|
-
else {
|
|
13757
|
-
ci.fmtParams.set(param, `${value}`);
|
|
13758
|
-
}
|
|
13759
|
-
});
|
|
13760
|
-
});
|
|
13761
|
-
}
|
|
13766
|
+
const transceiver = this.getSendTransceiverByMidOrThrow(av.mid);
|
|
13767
|
+
transceiver.signalStreams(av);
|
|
13762
13768
|
});
|
|
13763
13769
|
if (getBrowserDetails().name !== 'Firefox') {
|
|
13764
|
-
setupBundle(parsed, this.options.bundlePolicy, this.
|
|
13770
|
+
setupBundle(parsed, this.options.bundlePolicy, this.midPredictor.getMidMap());
|
|
13765
13771
|
}
|
|
13766
13772
|
return parsed.toString();
|
|
13767
13773
|
}
|
|
@@ -13790,7 +13796,7 @@ class MultistreamConnection extends EventEmitter {
|
|
|
13790
13796
|
}
|
|
13791
13797
|
});
|
|
13792
13798
|
if (getBrowserDetails().name === 'Firefox') {
|
|
13793
|
-
setupBundle(parsed, this.options.bundlePolicy, this.
|
|
13799
|
+
setupBundle(parsed, this.options.bundlePolicy, this.midPredictor.getMidMap());
|
|
13794
13800
|
if (this.options.bundlePolicy === 'max-bundle') {
|
|
13795
13801
|
parsed.media.forEach((mline, index) => {
|
|
13796
13802
|
if (index > 0) {
|
|
@@ -13805,9 +13811,10 @@ class MultistreamConnection extends EventEmitter {
|
|
|
13805
13811
|
var _a;
|
|
13806
13812
|
const parsedAnswer = parse(answer);
|
|
13807
13813
|
const parsedOffer = parse((_a = this.pc.getLocalDescription()) === null || _a === void 0 ? void 0 : _a.sdp);
|
|
13808
|
-
|
|
13814
|
+
const recvTransceiversByMid = new Map([...this.recvTransceivers.values()].flat().map((t) => [t.mid, t]));
|
|
13815
|
+
matchMlinesInAnswer(parsedOffer, parsedAnswer, recvTransceiversByMid);
|
|
13809
13816
|
if (getBrowserDetails().name === 'Firefox') {
|
|
13810
|
-
setupBundle(parsedAnswer, this.options.bundlePolicy, this.
|
|
13817
|
+
setupBundle(parsedAnswer, this.options.bundlePolicy, this.midPredictor.getMidMap());
|
|
13811
13818
|
if (this.options.bundlePolicy === 'max-bundle') {
|
|
13812
13819
|
const { ufrag, pwd } = parsedAnswer.media[0].iceInfo;
|
|
13813
13820
|
parsedAnswer.media.forEach((mline, index) => {
|
|
@@ -13827,6 +13834,20 @@ class MultistreamConnection extends EventEmitter {
|
|
|
13827
13834
|
}
|
|
13828
13835
|
return sendTransceiver;
|
|
13829
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
|
+
}
|
|
13830
13851
|
getPublishedTracks() {
|
|
13831
13852
|
return [...this.sendTransceivers.values()]
|
|
13832
13853
|
.map((transceiver) => transceiver.publishedTrack)
|
|
@@ -13834,11 +13855,8 @@ class MultistreamConnection extends EventEmitter {
|
|
|
13834
13855
|
}
|
|
13835
13856
|
setCodecParameters(mediaType, parameters) {
|
|
13836
13857
|
return __awaiter(this, void 0, void 0, function* () {
|
|
13837
|
-
const
|
|
13838
|
-
|
|
13839
|
-
currentParams.set(param, value);
|
|
13840
|
-
});
|
|
13841
|
-
this.customCodecParameters.set(mediaType, currentParams);
|
|
13858
|
+
const transceiver = this.sendTransceivers.get(mediaType);
|
|
13859
|
+
transceiver === null || transceiver === void 0 ? void 0 : transceiver.setCodecParameters(parameters);
|
|
13842
13860
|
if (this.pc.getRemoteDescription()) {
|
|
13843
13861
|
yield this.queueLocalOfferAnswer();
|
|
13844
13862
|
}
|
|
@@ -13846,11 +13864,8 @@ class MultistreamConnection extends EventEmitter {
|
|
|
13846
13864
|
}
|
|
13847
13865
|
deleteCodecParameters(mediaType, parameters) {
|
|
13848
13866
|
return __awaiter(this, void 0, void 0, function* () {
|
|
13849
|
-
const
|
|
13850
|
-
|
|
13851
|
-
currentParams.set(param, null);
|
|
13852
|
-
});
|
|
13853
|
-
this.customCodecParameters.set(mediaType, currentParams);
|
|
13867
|
+
const transceiver = this.sendTransceivers.get(mediaType);
|
|
13868
|
+
transceiver === null || transceiver === void 0 ? void 0 : transceiver.deleteCodecParameters(parameters);
|
|
13854
13869
|
if (this.pc.getRemoteDescription()) {
|
|
13855
13870
|
yield this.queueLocalOfferAnswer();
|
|
13856
13871
|
}
|
|
@@ -13894,32 +13909,34 @@ class MultistreamConnection extends EventEmitter {
|
|
|
13894
13909
|
this.options = Object.assign(Object.assign({}, this.options), userOptions);
|
|
13895
13910
|
}
|
|
13896
13911
|
logger.info(`Renewing multistream connection with options ${JSON.stringify(this.options)}`);
|
|
13897
|
-
this.
|
|
13912
|
+
this.midPredictor.reset();
|
|
13898
13913
|
this.initializePeerConnection();
|
|
13899
|
-
this.streamSignalerManager = new StreamSignalerManager(this.options.streamSignalingMode);
|
|
13900
13914
|
const mainSceneId = generateSceneId();
|
|
13901
13915
|
const slidesSceneId = generateSceneId();
|
|
13902
13916
|
this.sendTransceivers.forEach((transceiver, mediaType) => {
|
|
13903
13917
|
var _a;
|
|
13904
13918
|
const mediaContent = getMediaContent(mediaType);
|
|
13905
13919
|
const sceneId = mediaContent === MediaContent.Main ? mainSceneId : slidesSceneId;
|
|
13906
|
-
this.
|
|
13920
|
+
const mid = this.midPredictor.getNextMid(mediaType);
|
|
13907
13921
|
transceiver.replaceTransceiver(this.pc.addTransceiver(toMediaStreamTrackKind(mediaType), {
|
|
13908
13922
|
direction: 'sendrecv',
|
|
13909
13923
|
sendEncodings: getMediaFamily(mediaType) === MediaFamily.Video
|
|
13910
13924
|
? this.getVideoEncodingOptions(mediaContent)
|
|
13911
13925
|
: undefined,
|
|
13912
13926
|
}));
|
|
13927
|
+
transceiver.mid = mid;
|
|
13913
13928
|
transceiver.csi = generateCsi(getMediaFamily(mediaType), sceneId);
|
|
13929
|
+
transceiver.resetStreamSignaler();
|
|
13914
13930
|
(_a = this.jmpSessions.get(mediaType)) === null || _a === void 0 ? void 0 : _a.close();
|
|
13915
13931
|
this.createJmpSession(mediaType);
|
|
13916
13932
|
});
|
|
13917
13933
|
this.recvTransceivers.forEach((transceivers, mediaType) => {
|
|
13918
13934
|
transceivers.forEach((t) => {
|
|
13919
|
-
this.
|
|
13935
|
+
const mid = this.midPredictor.getNextMid(mediaType);
|
|
13920
13936
|
t.replaceTransceiver(this.pc.addTransceiver(toMediaStreamTrackKind(mediaType), {
|
|
13921
13937
|
direction: 'recvonly',
|
|
13922
13938
|
}));
|
|
13939
|
+
t.mid = mid;
|
|
13923
13940
|
});
|
|
13924
13941
|
});
|
|
13925
13942
|
}
|
|
@@ -13968,10 +13985,7 @@ class MultistreamConnection extends EventEmitter {
|
|
|
13968
13985
|
statsToModify.mid = (_a = transceiver.receiveSlot.id) === null || _a === void 0 ? void 0 : _a.mid;
|
|
13969
13986
|
statsToModify.csi = transceiver.receiveSlot.currentRxCsi;
|
|
13970
13987
|
statsToModify.mediaType = mediaType;
|
|
13971
|
-
|
|
13972
|
-
if (signaler) {
|
|
13973
|
-
Object.assign(statsToModify, signaler.getReceiverId());
|
|
13974
|
-
}
|
|
13988
|
+
Object.assign(statsToModify, transceiver.receiverId);
|
|
13975
13989
|
stats.set(receiverStats.id, statsToModify);
|
|
13976
13990
|
}
|
|
13977
13991
|
});
|