|
@@ -26,6 +26,8 @@ const SIM_LAYER_1_RID = '1';
|
26
|
26
|
const SIM_LAYER_2_RID = '2';
|
27
|
27
|
const SIM_LAYER_3_RID = '3';
|
28
|
28
|
const SIM_LAYER_RIDS = [ SIM_LAYER_1_RID, SIM_LAYER_2_RID, SIM_LAYER_3_RID ];
|
|
29
|
+const SIM_LAYER_BITRATES_BPS = [ 200000, 700000, 2500000 ];
|
|
30
|
+const DESKSTOP_SHARE_RATE = 500000;
|
29
|
31
|
|
30
|
32
|
/* eslint-disable max-params */
|
31
|
33
|
|
|
@@ -45,6 +47,9 @@ const SIM_LAYER_RIDS = [ SIM_LAYER_1_RID, SIM_LAYER_2_RID, SIM_LAYER_3_RID ];
|
45
|
47
|
* @param {boolean} options.disableRtx if set to 'true' will disable the RTX
|
46
|
48
|
* @param {boolean} options.enableFirefoxSimulcast if set to 'true' will enable
|
47
|
49
|
* experimental simulcast support on Firefox.
|
|
50
|
+ * @param {boolean} options.capScreenshareBitrate if set to 'true' simulcast will
|
|
51
|
+ * be disabled for screenshare and a max bitrate of 500Kbps will applied on the
|
|
52
|
+ * stream.
|
48
|
53
|
* @param {boolean} options.disableH264 If set to 'true' H264 will be
|
49
|
54
|
* disabled by removing it from the SDP.
|
50
|
55
|
* @param {boolean} options.preferH264 if set to 'true' H264 will be preferred
|
|
@@ -1883,6 +1888,55 @@ TraceablePeerConnection.prototype._insertUnifiedPlanSimulcastReceive
|
1883
|
1888
|
});
|
1884
|
1889
|
};
|
1885
|
1890
|
|
|
1891
|
+/**
|
|
1892
|
+ * Sets the max bitrate on the RTCRtpSender so that the
|
|
1893
|
+ * bitrate of the enocder doesn't exceed the configured value.
|
|
1894
|
+ * This is needed for the desktop share until spec-complaint
|
|
1895
|
+ * simulcast is implemented.
|
|
1896
|
+ * @param {JitsiLocalTrack} localTrack - the local track whose
|
|
1897
|
+ * max bitrate is to be configured.
|
|
1898
|
+ */
|
|
1899
|
+TraceablePeerConnection.prototype.setMaxBitRate = function(localTrack) {
|
|
1900
|
+ const mediaType = localTrack.type;
|
|
1901
|
+
|
|
1902
|
+ if (!this.options.capScreenshareBitrate
|
|
1903
|
+ || mediaType === MediaType.AUDIO) {
|
|
1904
|
+
|
|
1905
|
+ return;
|
|
1906
|
+ }
|
|
1907
|
+ if (!this.peerconnection.getSenders) {
|
|
1908
|
+ logger.debug('Browser doesn\'t support RTCRtpSender');
|
|
1909
|
+
|
|
1910
|
+ return;
|
|
1911
|
+ }
|
|
1912
|
+ const videoType = localTrack.videoType;
|
|
1913
|
+ const trackId = localTrack.track.id;
|
|
1914
|
+
|
|
1915
|
+ this.peerconnection.getSenders()
|
|
1916
|
+ .filter(s => s.track && s.track.id === trackId)
|
|
1917
|
+ .forEach(sender => {
|
|
1918
|
+ try {
|
|
1919
|
+ const parameters = sender.getParameters();
|
|
1920
|
+
|
|
1921
|
+ if (parameters.encodings && parameters.encodings.length) {
|
|
1922
|
+ logger.info('Setting max bitrate on video stream');
|
|
1923
|
+ for (const encoding in parameters.encodings) {
|
|
1924
|
+ if (parameters.encodings.hasOwnProperty(encoding)) {
|
|
1925
|
+ parameters.encodings[encoding].maxBitrate
|
|
1926
|
+ = videoType === 'desktop'
|
|
1927
|
+ ? DESKSTOP_SHARE_RATE
|
|
1928
|
+ : SIM_LAYER_BITRATES_BPS[encoding];
|
|
1929
|
+ }
|
|
1930
|
+ }
|
|
1931
|
+ sender.setParameters(parameters);
|
|
1932
|
+ }
|
|
1933
|
+ } catch (err) {
|
|
1934
|
+ logger.error('Browser does not support getParameters/setParamters '
|
|
1935
|
+ + 'or setting max bitrate on the encodings: ', err);
|
|
1936
|
+ }
|
|
1937
|
+ });
|
|
1938
|
+};
|
|
1939
|
+
|
1886
|
1940
|
TraceablePeerConnection.prototype.setRemoteDescription = function(description) {
|
1887
|
1941
|
this.trace('setRemoteDescription::preTransform', dumpSDP(description));
|
1888
|
1942
|
|
|
@@ -2240,6 +2294,17 @@ TraceablePeerConnection.prototype.createOffer = function(constraints) {
|
2240
|
2294
|
return this._createOfferOrAnswer(true /* offer */, constraints);
|
2241
|
2295
|
};
|
2242
|
2296
|
|
|
2297
|
+/**
|
|
2298
|
+ * Checks if a camera track has been added to the peerconnection
|
|
2299
|
+ * @param {TraceablePeerConnection} peerConnection
|
|
2300
|
+ * @return {boolean} <tt>true</tt> if the peerconnection has
|
|
2301
|
+ * a camera track for its video source <tt>false</tt> otherwise.
|
|
2302
|
+ */
|
|
2303
|
+function hasCameraTrack(peerConnection) {
|
|
2304
|
+ return peerConnection.getLocalTracks()
|
|
2305
|
+ .some(t => t.videoType === 'camera');
|
|
2306
|
+}
|
|
2307
|
+
|
2243
|
2308
|
TraceablePeerConnection.prototype._createOfferOrAnswer = function(
|
2244
|
2309
|
isOffer,
|
2245
|
2310
|
constraints) {
|
|
@@ -2298,8 +2363,12 @@ TraceablePeerConnection.prototype._createOfferOrAnswer = function(
|
2298
|
2363
|
dumpSDP(resultSdp));
|
2299
|
2364
|
}
|
2300
|
2365
|
|
2301
|
|
- // Add simulcast streams if simulcast is enabled
|
2302
|
|
- if (this.isSimulcastOn()) {
|
|
2366
|
+ // configure simulcast for camera tracks always and for
|
|
2367
|
+ // desktop tracks only when the testing flag for maxbitrates
|
|
2368
|
+ // in config.js is disabled.
|
|
2369
|
+ if (this.isSimulcastOn()
|
|
2370
|
+ && (!this.options.capScreenshareBitrate
|
|
2371
|
+ || (this.options.capScreenshareBitrate && hasCameraTrack(this)))) {
|
2303
|
2372
|
// eslint-disable-next-line no-param-reassign
|
2304
|
2373
|
resultSdp = this.simulcast.mungeLocalDescription(resultSdp);
|
2305
|
2374
|
this.trace(
|
|
@@ -2500,7 +2569,13 @@ TraceablePeerConnection.prototype.generateNewStreamSSRCInfo = function(track) {
|
2500
|
2569
|
if (ssrcInfo) {
|
2501
|
2570
|
logger.error(`Will overwrite local SSRCs for track ID: ${rtcId}`);
|
2502
|
2571
|
}
|
2503
|
|
- if (this.isSimulcastOn()) {
|
|
2572
|
+
|
|
2573
|
+ // configure simulcast for camera tracks always and for
|
|
2574
|
+ // desktop tracks only when the testing flag for maxbitrates
|
|
2575
|
+ // in config.js is disabled.
|
|
2576
|
+ if (this.isSimulcastOn()
|
|
2577
|
+ && (!this.options.capScreenshareBitrate
|
|
2578
|
+ || (this.options.capScreenshareBitrate && hasCameraTrack(this)))) {
|
2504
|
2579
|
ssrcInfo = {
|
2505
|
2580
|
ssrcs: [],
|
2506
|
2581
|
groups: []
|