|
@@ -412,7 +412,6 @@ export default class JingleSessionPC extends JingleSession {
|
412
|
412
|
}
|
413
|
413
|
pcOptions.forceTurnRelay = options.forceTurnRelay;
|
414
|
414
|
pcOptions.audioQuality = options.audioQuality;
|
415
|
|
- pcOptions.usesUnifiedPlan = this.usesUnifiedPlan = browser.supportsUnifiedPlan();
|
416
|
415
|
pcOptions.disableSimulcast = this.isP2P ? true : options.disableSimulcast;
|
417
|
416
|
|
418
|
417
|
if (!this.isP2P) {
|
|
@@ -557,8 +556,7 @@ export default class JingleSessionPC extends JingleSession {
|
557
|
556
|
if (!this.wasConnected
|
558
|
557
|
&& (this.wasstable
|
559
|
558
|
|| isStable
|
560
|
|
- || (this.usesUnifiedPlan && this.isInitiator
|
561
|
|
- && (browser.isChromiumBased() || browser.isReactNative())))) {
|
|
559
|
+ || (this.isInitiator && (browser.isChromiumBased() || browser.isReactNative())))) {
|
562
|
560
|
|
563
|
561
|
Statistics.sendAnalytics(
|
564
|
562
|
ICE_DURATION,
|
|
@@ -641,8 +639,7 @@ export default class JingleSessionPC extends JingleSession {
|
641
|
639
|
const state = this.peerconnection.signalingState;
|
642
|
640
|
const remoteDescription = this.peerconnection.remoteDescription;
|
643
|
641
|
|
644
|
|
- if (this.usesUnifiedPlan
|
645
|
|
- && !this.isP2P
|
|
642
|
+ if (!this.isP2P
|
646
|
643
|
&& state === 'stable'
|
647
|
644
|
&& remoteDescription
|
648
|
645
|
&& typeof remoteDescription.sdp === 'string') {
|
|
@@ -948,19 +945,6 @@ export default class JingleSessionPC extends JingleSession {
|
948
|
945
|
});
|
949
|
946
|
}
|
950
|
947
|
|
951
|
|
- /**
|
952
|
|
- * Makes the underlying TraceablePeerConnection generate new SSRC for
|
953
|
|
- * the recvonly video stream.
|
954
|
|
- * @deprecated
|
955
|
|
- */
|
956
|
|
- generateRecvonlySsrc() {
|
957
|
|
- if (this.peerconnection) {
|
958
|
|
- this.peerconnection.generateRecvonlySsrc();
|
959
|
|
- } else {
|
960
|
|
- logger.error(`${this} Unable to generate recvonly SSRC - no peerconnection`);
|
961
|
|
- }
|
962
|
|
- }
|
963
|
|
-
|
964
|
948
|
/**
|
965
|
949
|
* Returns the video codec configured as the preferred codec on the peerconnection.
|
966
|
950
|
*/
|
|
@@ -1005,9 +989,7 @@ export default class JingleSessionPC extends JingleSession {
|
1005
|
989
|
const videoTracks = localTracks.filter(track => track.getType() === MediaType.VIDEO);
|
1006
|
990
|
|
1007
|
991
|
videoTracks.length && videoTracks.splice(0, 1);
|
1008
|
|
- if (FeatureFlags.isMultiStreamSendSupportEnabled() && videoTracks.length) {
|
1009
|
|
- this.addTracks(videoTracks);
|
1010
|
|
- }
|
|
992
|
+ videoTracks.length && this.addTracks(videoTracks);
|
1011
|
993
|
},
|
1012
|
994
|
error => {
|
1013
|
995
|
failure(error);
|
|
@@ -1150,7 +1132,7 @@ export default class JingleSessionPC extends JingleSession {
|
1150
|
1132
|
// Add only 1 video track at a time. Adding 2 or more video tracks to the peerconnection at the same time
|
1151
|
1133
|
// makes the browser go into a renegotiation loop by firing 'negotiationneeded' event after every
|
1152
|
1134
|
// renegotiation.
|
1153
|
|
- if (FeatureFlags.isMultiStreamSendSupportEnabled() && videoTracks.length > 1) {
|
|
1135
|
+ if (videoTracks.length > 1) {
|
1154
|
1136
|
tracks = [ ...audioTracks, videoTracks[0] ];
|
1155
|
1137
|
}
|
1156
|
1138
|
for (const track of tracks) {
|
|
@@ -1716,8 +1698,7 @@ export default class JingleSessionPC extends JingleSession {
|
1716
|
1698
|
if (currentRemoteSdp.containsSSRC(ssrc)) {
|
1717
|
1699
|
|
1718
|
1700
|
// Do not print the warning for unified plan p2p case since ssrcs are never removed from the SDP.
|
1719
|
|
- !(self.usesUnifiedPlan && self.isP2P)
|
1720
|
|
- && logger.warn(`${self} Source-add request for existing SSRC: ${ssrc}`);
|
|
1701
|
+ !self.isP2P && logger.warn(`${self} Source-add request for existing SSRC: ${ssrc}`);
|
1721
|
1702
|
|
1722
|
1703
|
return;
|
1723
|
1704
|
}
|
|
@@ -1994,51 +1975,43 @@ export default class JingleSessionPC extends JingleSession {
|
1994
|
1975
|
* in removeSsrcInfo
|
1995
|
1976
|
*/
|
1996
|
1977
|
_processRemoteRemoveSource(removeSsrcInfo) {
|
1997
|
|
- const remoteSdp = this.usesUnifiedPlan
|
1998
|
|
- ? new SDP(this.peerconnection.peerconnection.remoteDescription.sdp)
|
1999
|
|
- : new SDP(this.peerconnection.remoteDescription.sdp);
|
|
1978
|
+ const remoteSdp = new SDP(this.peerconnection.peerconnection.remoteDescription.sdp);
|
2000
|
1979
|
let ssrcs;
|
2001
|
1980
|
|
2002
|
|
- removeSsrcInfo.forEach((lines, idx) => {
|
|
1981
|
+ removeSsrcInfo.forEach(lines => {
|
2003
|
1982
|
// eslint-disable-next-line no-param-reassign
|
2004
|
1983
|
lines = lines.split('\r\n');
|
2005
|
1984
|
lines.pop(); // remove empty last element;
|
2006
|
1985
|
ssrcs = lines.map(line => Number(line.split('a=ssrc:')[1]?.split(' ')[0]));
|
2007
|
1986
|
|
2008
|
|
- if (this.usesUnifiedPlan) {
|
2009
|
|
- let mid;
|
2010
|
|
-
|
2011
|
|
- lines.forEach(line => {
|
2012
|
|
- mid = remoteSdp.media.findIndex(mLine => mLine.includes(line));
|
2013
|
|
- if (mid > -1) {
|
2014
|
|
- remoteSdp.media[mid] = remoteSdp.media[mid].replace(`${line}\r\n`, '');
|
2015
|
|
- if (this.isP2P) {
|
2016
|
|
- const mediaType = SDPUtil.parseMLine(remoteSdp.media[mid].split('\r\n')[0])?.media;
|
2017
|
|
- const desiredDirection = this.peerconnection.getDesiredMediaDirection(mediaType, false);
|
2018
|
|
-
|
2019
|
|
- [ MediaDirection.SENDRECV, MediaDirection.SENDONLY ].forEach(direction => {
|
2020
|
|
- remoteSdp.media[mid] = remoteSdp.media[mid]
|
2021
|
|
- .replace(`a=${direction}`, `a=${desiredDirection}`);
|
2022
|
|
- });
|
2023
|
|
- } else {
|
2024
|
|
- // Jvb connections will have direction set to 'sendonly' for the remote sources.
|
|
1987
|
+ let mid;
|
|
1988
|
+
|
|
1989
|
+ lines.forEach(line => {
|
|
1990
|
+ mid = remoteSdp.media.findIndex(mLine => mLine.includes(line));
|
|
1991
|
+ if (mid > -1) {
|
|
1992
|
+ remoteSdp.media[mid] = remoteSdp.media[mid].replace(`${line}\r\n`, '');
|
|
1993
|
+ if (this.isP2P) {
|
|
1994
|
+ const mediaType = SDPUtil.parseMLine(remoteSdp.media[mid].split('\r\n')[0])?.media;
|
|
1995
|
+ const desiredDirection = this.peerconnection.getDesiredMediaDirection(mediaType, false);
|
|
1996
|
+
|
|
1997
|
+ [ MediaDirection.SENDRECV, MediaDirection.SENDONLY ].forEach(direction => {
|
2025
|
1998
|
remoteSdp.media[mid] = remoteSdp.media[mid]
|
2026
|
|
- .replace(`a=${MediaDirection.SENDONLY}`, `a=${MediaDirection.INACTIVE}`);
|
|
1999
|
+ .replace(`a=${direction}`, `a=${desiredDirection}`);
|
|
2000
|
+ });
|
|
2001
|
+ } else {
|
|
2002
|
+ // Jvb connections will have direction set to 'sendonly' for the remote sources.
|
|
2003
|
+ remoteSdp.media[mid] = remoteSdp.media[mid]
|
|
2004
|
+ .replace(`a=${MediaDirection.SENDONLY}`, `a=${MediaDirection.INACTIVE}`);
|
2027
|
2005
|
|
2028
|
|
- // Reject the m-line so that the browser removes the associated transceiver from the list
|
2029
|
|
- // of available transceivers. This will prevent the client from trying to re-use these
|
2030
|
|
- // inactive transceivers when additional video sources are added to the peerconnection.
|
2031
|
|
- const { media, port } = SDPUtil.parseMLine(remoteSdp.media[mid].split('\r\n')[0]);
|
|
2006
|
+ // Reject the m-line so that the browser removes the associated transceiver from the list
|
|
2007
|
+ // of available transceivers. This will prevent the client from trying to re-use these
|
|
2008
|
+ // inactive transceivers when additional video sources are added to the peerconnection.
|
|
2009
|
+ const { media, port } = SDPUtil.parseMLine(remoteSdp.media[mid].split('\r\n')[0]);
|
2032
|
2010
|
|
2033
|
|
- remoteSdp.media[mid] = remoteSdp.media[mid].replace(`m=${media} ${port}`, `m=${media} 0`);
|
2034
|
|
- }
|
|
2011
|
+ remoteSdp.media[mid] = remoteSdp.media[mid].replace(`m=${media} ${port}`, `m=${media} 0`);
|
2035
|
2012
|
}
|
2036
|
|
- });
|
2037
|
|
- } else {
|
2038
|
|
- lines.forEach(line => {
|
2039
|
|
- remoteSdp.media[idx] = remoteSdp.media[idx].replace(`${line}\r\n`, '');
|
2040
|
|
- });
|
2041
|
|
- }
|
|
2013
|
+ }
|
|
2014
|
+ });
|
2042
|
2015
|
});
|
2043
|
2016
|
|
2044
|
2017
|
// Update the ssrc owners list.
|
|
@@ -2061,9 +2034,7 @@ export default class JingleSessionPC extends JingleSession {
|
2061
|
2034
|
|
2062
|
2035
|
// Add a new m-line in the remote description if the source info for a secondary video source is recceived from
|
2063
|
2036
|
// the remote p2p peer when multi-stream support is enabled.
|
2064
|
|
- if (addSsrcInfo.length > remoteSdp.media.length
|
2065
|
|
- && this.isP2P
|
2066
|
|
- && this.usesUnifiedPlan) {
|
|
2037
|
+ if (addSsrcInfo.length > remoteSdp.media.length && this.isP2P) {
|
2067
|
2038
|
remoteSdp.addMlineForNewLocalSource(MediaType.VIDEO);
|
2068
|
2039
|
remoteSdp = new SDP(remoteSdp.raw);
|
2069
|
2040
|
}
|
|
@@ -2072,7 +2043,7 @@ export default class JingleSessionPC extends JingleSession {
|
2072
|
2043
|
|
2073
|
2044
|
// Make sure to change the direction to 'sendrecv/sendonly' only for p2p connections. For jvb connections,
|
2074
|
2045
|
// a new m-line is added for the new remote sources.
|
2075
|
|
- if (this.isP2P && this.usesUnifiedPlan) {
|
|
2046
|
+ if (this.isP2P) {
|
2076
|
2047
|
const mediaType = SDPUtil.parseMLine(remoteSdp.media[idx].split('\r\n')[0])?.media;
|
2077
|
2048
|
const desiredDirection = this.peerconnection.getDesiredMediaDirection(mediaType, true);
|
2078
|
2049
|
|
|
@@ -2152,9 +2123,11 @@ export default class JingleSessionPC extends JingleSession {
|
2152
|
2123
|
* otherwise.
|
2153
|
2124
|
*/
|
2154
|
2125
|
addTracks(localTracks = null) {
|
2155
|
|
- if (!FeatureFlags.isMultiStreamSendSupportEnabled()
|
2156
|
|
- || !localTracks?.length
|
2157
|
|
- || localTracks.find(track => track.getType() !== MediaType.VIDEO)) {
|
|
2126
|
+ if (!localTracks?.length) {
|
|
2127
|
+ Promise.reject(new Error('No tracks passed'));
|
|
2128
|
+ }
|
|
2129
|
+
|
|
2130
|
+ if (localTracks.find(track => track.getType() !== MediaType.VIDEO)) {
|
2158
|
2131
|
return Promise.reject(new Error('Multiple tracks of the given media type are not supported'));
|
2159
|
2132
|
}
|
2160
|
2133
|
|
|
@@ -2254,41 +2227,6 @@ export default class JingleSessionPC extends JingleSession {
|
2254
|
2227
|
const workFunction = finishedCallback => {
|
2255
|
2228
|
logger.debug(`${this} replaceTrack worker started. oldTrack = ${oldTrack}, newTrack = ${newTrack}`);
|
2256
|
2229
|
|
2257
|
|
- if (!this.usesUnifiedPlan) {
|
2258
|
|
- // NOTE the code below assumes that no more than 1 video track
|
2259
|
|
- // can be added to the peer connection.
|
2260
|
|
- // Transition from camera to desktop share
|
2261
|
|
- // or transition from one camera source to another.
|
2262
|
|
- if (this.peerconnection.options.capScreenshareBitrate
|
2263
|
|
- && oldTrack && newTrack && newTrack.isVideoTrack()) {
|
2264
|
|
- // Clearing current primary SSRC will make
|
2265
|
|
- // the SdpConsistency generate a new one which will result
|
2266
|
|
- // with:
|
2267
|
|
- // 1. source-remove for the old video stream.
|
2268
|
|
- // 2. source-add for the new video stream.
|
2269
|
|
- this.peerconnection.clearRecvonlySsrc();
|
2270
|
|
- }
|
2271
|
|
-
|
2272
|
|
- // Transition from no video to video (unmute).
|
2273
|
|
- if (!oldTrack && newTrack && newTrack.isVideoTrack()) {
|
2274
|
|
- // Clearing current primary SSRC will make
|
2275
|
|
- // the SdpConsistency generate a new one which will result
|
2276
|
|
- // with:
|
2277
|
|
- // 1. source-remove for the recvonly
|
2278
|
|
- // 2. source-add for the new video stream
|
2279
|
|
- this.peerconnection.clearRecvonlySsrc();
|
2280
|
|
-
|
2281
|
|
- // Transition from video to no video
|
2282
|
|
- } else if (oldTrack && oldTrack.isVideoTrack() && !newTrack) {
|
2283
|
|
- // Clearing current primary SSRC and generating the recvonly
|
2284
|
|
- // will result in:
|
2285
|
|
- // 1. source-remove for the old video stream
|
2286
|
|
- // 2. source-add for the recvonly stream
|
2287
|
|
- this.peerconnection.clearRecvonlySsrc();
|
2288
|
|
- this.peerconnection.generateRecvonlySsrc();
|
2289
|
|
- }
|
2290
|
|
- }
|
2291
|
|
-
|
2292
|
2230
|
this.peerconnection.replaceTrack(oldTrack, newTrack)
|
2293
|
2231
|
.then(shouldRenegotiate => {
|
2294
|
2232
|
let promise = Promise.resolve();
|
|
@@ -2407,42 +2345,6 @@ export default class JingleSessionPC extends JingleSession {
|
2407
|
2345
|
return removeSsrcInfo;
|
2408
|
2346
|
}
|
2409
|
2347
|
|
2410
|
|
- /**
|
2411
|
|
- * Will print an error if there is any difference, between the SSRCs given
|
2412
|
|
- * in the <tt>oldSDP</tt> and the ones currently described in
|
2413
|
|
- * the peerconnection's local description.
|
2414
|
|
- * @param {string} operationName the operation's name which will be printed
|
2415
|
|
- * in the error message.
|
2416
|
|
- * @param {SDP} oldSDP the old local SDP which will be compared with
|
2417
|
|
- * the current one.
|
2418
|
|
- * @return {boolean} <tt>true</tt> if there was any change or <tt>false</tt>
|
2419
|
|
- * otherwise.
|
2420
|
|
- * @private
|
2421
|
|
- */
|
2422
|
|
- _verifyNoSSRCChanged(operationName, oldSDP) {
|
2423
|
|
- const currentLocalSDP
|
2424
|
|
- = new SDP(this.peerconnection.localDescription.sdp);
|
2425
|
|
- let sdpDiff = new SDPDiffer(oldSDP, currentLocalSDP);
|
2426
|
|
- const addedMedia = sdpDiff.getNewMedia();
|
2427
|
|
-
|
2428
|
|
- if (Object.keys(addedMedia).length) {
|
2429
|
|
- logger.error(`${this} - some SSRC were added on ${operationName}`, addedMedia);
|
2430
|
|
-
|
2431
|
|
- return false;
|
2432
|
|
- }
|
2433
|
|
-
|
2434
|
|
- sdpDiff = new SDPDiffer(currentLocalSDP, oldSDP);
|
2435
|
|
- const removedMedia = sdpDiff.getNewMedia();
|
2436
|
|
-
|
2437
|
|
- if (Object.keys(removedMedia).length) {
|
2438
|
|
- logger.error(`${this} - some SSRCs were removed on ${operationName}`, removedMedia);
|
2439
|
|
-
|
2440
|
|
- return false;
|
2441
|
|
- }
|
2442
|
|
-
|
2443
|
|
- return true;
|
2444
|
|
- }
|
2445
|
|
-
|
2446
|
2348
|
/**
|
2447
|
2349
|
* Adds local track back to the peerconnection associated with this session.
|
2448
|
2350
|
* @param {JitsiLocalTrack} track
|
|
@@ -2492,7 +2394,6 @@ export default class JingleSessionPC extends JingleSession {
|
2492
|
2394
|
|
2493
|
2395
|
return;
|
2494
|
2396
|
}
|
2495
|
|
- const oldLocalSDP = tpc.localDescription.sdp;
|
2496
|
2397
|
const operationPromise
|
2497
|
2398
|
= isRemove
|
2498
|
2399
|
? tpc.removeTrackFromPc(track)
|
|
@@ -2500,14 +2401,8 @@ export default class JingleSessionPC extends JingleSession {
|
2500
|
2401
|
|
2501
|
2402
|
operationPromise
|
2502
|
2403
|
.then(shouldRenegotiate => {
|
2503
|
|
- if (shouldRenegotiate && oldLocalSDP && tpc.remoteDescription.sdp) {
|
2504
|
|
- this._renegotiate()
|
2505
|
|
- .then(() => {
|
2506
|
|
- // The results are ignored, as this check failure is not enough to fail the whole
|
2507
|
|
- // operation. It will log an error inside for plan-b.
|
2508
|
|
- !this.usesUnifiedPlan && this._verifyNoSSRCChanged(operationName, new SDP(oldLocalSDP));
|
2509
|
|
- finishedCallback();
|
2510
|
|
- });
|
|
2404
|
+ if (shouldRenegotiate) {
|
|
2405
|
+ this._renegotiate().then(finishedCallback);
|
2511
|
2406
|
} else {
|
2512
|
2407
|
finishedCallback();
|
2513
|
2408
|
}
|