|
|
@@ -6,7 +6,6 @@ import transform from 'sdp-transform';
|
|
6
|
6
|
import * as GlobalOnErrorHandler from '../util/GlobalOnErrorHandler';
|
|
7
|
7
|
import JitsiRemoteTrack from './JitsiRemoteTrack';
|
|
8
|
8
|
import * as MediaType from '../../service/RTC/MediaType';
|
|
9
|
|
-import BandwidthLimiter from './BandwidthLimiter';
|
|
10
|
9
|
import LocalSdpMunger from './LocalSdpMunger';
|
|
11
|
10
|
import RTC from './RTC';
|
|
12
|
11
|
import RTCUtils from './RTCUtils';
|
|
|
@@ -208,8 +207,6 @@ export default function TraceablePeerConnection(
|
|
208
|
207
|
*/
|
|
209
|
208
|
this.localSdpMunger = new LocalSdpMunger(this);
|
|
210
|
209
|
|
|
211
|
|
- this.bandwidthLimiter = new BandwidthLimiter();
|
|
212
|
|
-
|
|
213
|
210
|
/**
|
|
214
|
211
|
* TracablePeerConnection uses RTC's eventEmitter
|
|
215
|
212
|
* @type {EventEmitter}
|
|
|
@@ -217,12 +214,6 @@ export default function TraceablePeerConnection(
|
|
217
|
214
|
this.eventEmitter = rtc.eventEmitter;
|
|
218
|
215
|
this.rtxModifier = new RtxModifier();
|
|
219
|
216
|
|
|
220
|
|
- /**
|
|
221
|
|
- * Whether or not this endpoint has been selected
|
|
222
|
|
- * by a remote participant (via the bridge)
|
|
223
|
|
- */
|
|
224
|
|
- this.isSelected = true;
|
|
225
|
|
-
|
|
226
|
217
|
// override as desired
|
|
227
|
218
|
this.trace = (what, info) => {
|
|
228
|
219
|
logger.debug(what, info);
|
|
|
@@ -1036,20 +1027,6 @@ function extractSSRCMap(desc) {
|
|
1036
|
1027
|
return ssrcMap;
|
|
1037
|
1028
|
}
|
|
1038
|
1029
|
|
|
1039
|
|
-/**
|
|
1040
|
|
- * Get the bitrate cap we should enforce for video given whether or not
|
|
1041
|
|
- * we are selected
|
|
1042
|
|
- * @param {boolean} isSelected whether or not we (the local endpoint) is
|
|
1043
|
|
- * selected by any other endpoints (meaning its HD stream is in use)
|
|
1044
|
|
- * @return {Number} the bitrate cap in kbps, or null if there should be
|
|
1045
|
|
- * no cap
|
|
1046
|
|
- */
|
|
1047
|
|
-function getSuspensionBitrateKbps(isSelected) {
|
|
1048
|
|
- // eslint-disable-next-line max-len
|
|
1049
|
|
- // https://codesearch.chromium.org/chromium/src/third_party/webrtc/media/engine/simulcast.cc?l=55&rcl=28deb90728c06a35d8847d2aeda2fc1aee105c5e
|
|
1050
|
|
- return isSelected ? null : 200;
|
|
1051
|
|
-}
|
|
1052
|
|
-
|
|
1053
|
1030
|
/**
|
|
1054
|
1031
|
* Takes a SessionDescription object and returns a "normalized" version.
|
|
1055
|
1032
|
* Currently it only takes care of ordering the a=ssrc lines.
|
|
|
@@ -1859,21 +1836,6 @@ TraceablePeerConnection.prototype.setRemoteDescription = function(
|
|
1859
|
1836
|
});
|
|
1860
|
1837
|
}
|
|
1861
|
1838
|
|
|
1862
|
|
- if (this.options.enableLayerSuspension) {
|
|
1863
|
|
- logger.debug('Layer suspension enabled,'
|
|
1864
|
|
- + `currently selected? ${this.isSelected}`);
|
|
1865
|
|
- const bitrateCapKbps = getSuspensionBitrateKbps(this.isSelected);
|
|
1866
|
|
-
|
|
1867
|
|
- this.bandwidthLimiter.setBandwidthLimit('video', bitrateCapKbps);
|
|
1868
|
|
- logger.debug(`Layer suspension got bitrate cap of ${bitrateCapKbps}`);
|
|
1869
|
|
- description.sdp
|
|
1870
|
|
- = this.bandwidthLimiter.enforceBandwithLimit(description.sdp);
|
|
1871
|
|
- this.trace(
|
|
1872
|
|
- 'setRemoteDescription::postTransform '
|
|
1873
|
|
- + '(layer suspension bitrate cap)',
|
|
1874
|
|
- dumpSDP(description));
|
|
1875
|
|
- }
|
|
1876
|
|
-
|
|
1877
|
1839
|
// If the browser uses unified plan, transform to it first
|
|
1878
|
1840
|
if (browser.usesUnifiedPlan()) {
|
|
1879
|
1841
|
// eslint-disable-next-line no-param-reassign
|
|
|
@@ -2488,12 +2450,52 @@ TraceablePeerConnection.prototype.generateNewStreamSSRCInfo = function(track) {
|
|
2488
|
2450
|
return ssrcInfo;
|
|
2489
|
2451
|
};
|
|
2490
|
2452
|
|
|
|
2453
|
+const handleLayerSuspension = function(peerConnection, isSelected) {
|
|
|
2454
|
+ const videoSender = peerConnection.getSenders()
|
|
|
2455
|
+ .find(sender => sender.track.kind === 'video');
|
|
|
2456
|
+
|
|
|
2457
|
+ if (!videoSender) {
|
|
|
2458
|
+ logger.warn('handleLayerSuspension unable to find video sender');
|
|
|
2459
|
+
|
|
|
2460
|
+ return;
|
|
|
2461
|
+ }
|
|
|
2462
|
+ if (!videoSender.getParameters) {
|
|
|
2463
|
+ logger.debug('Browser doesn\'t support RTPSender parameters');
|
|
|
2464
|
+
|
|
|
2465
|
+ return;
|
|
|
2466
|
+ }
|
|
|
2467
|
+ const parameters = videoSender.getParameters();
|
|
|
2468
|
+
|
|
|
2469
|
+ if (isSelected) {
|
|
|
2470
|
+ logger.debug('Currently selected, enabling all sim layers');
|
|
|
2471
|
+
|
|
|
2472
|
+ // Make sure all encodings are enabled
|
|
|
2473
|
+ parameters.encodings.forEach(e => {
|
|
|
2474
|
+ e.active = true;
|
|
|
2475
|
+ });
|
|
|
2476
|
+ } else {
|
|
|
2477
|
+ logger.debug('Not currently selected, disabling upper layers');
|
|
|
2478
|
+
|
|
|
2479
|
+ // Turn off the upper simulcast layers
|
|
|
2480
|
+ [ 1, 2 ].forEach(simIndex => {
|
|
|
2481
|
+ if (parameters.encodings[simIndex]) {
|
|
|
2482
|
+ parameters.encodings[simIndex].active = false;
|
|
|
2483
|
+ }
|
|
|
2484
|
+ });
|
|
|
2485
|
+ }
|
|
|
2486
|
+ videoSender.setParameters(parameters);
|
|
|
2487
|
+};
|
|
|
2488
|
+
|
|
2491
|
2489
|
/**
|
|
2492
|
2490
|
* Set whether or not the endpoint is 'selected' by other endpoints, meaning
|
|
2493
|
2491
|
* it appears on their main stage
|
|
2494
|
2492
|
*/
|
|
2495
|
2493
|
TraceablePeerConnection.prototype.setIsSelected = function(isSelected) {
|
|
2496
|
|
- this.isSelected = isSelected;
|
|
|
2494
|
+ if (this.options.enableLayerSuspension) {
|
|
|
2495
|
+ logger.debug('Layer suspension enabled,'
|
|
|
2496
|
+ + `currently selected? ${isSelected}`);
|
|
|
2497
|
+ handleLayerSuspension(this.peerconnection, isSelected);
|
|
|
2498
|
+ }
|
|
2497
|
2499
|
};
|
|
2498
|
2500
|
|
|
2499
|
2501
|
/**
|