Skip to content

Commit

Permalink
fix(TPC): make screen share bitrate configurable (#2215)
Browse files Browse the repository at this point in the history
* fix(TPC): make screen share bitrate configurable

* fix(TPC): make local stream encodings configurable

* fix(TPC): fix lint error

* fix(TPC): alpha sort methods and update check for VP8
  • Loading branch information
DanielMcAssey authored Feb 14, 2023
1 parent f487740 commit 829f5ac
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 45 deletions.
98 changes: 55 additions & 43 deletions modules/RTC/TPCUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,48 +38,15 @@ export class TPCUtils {
const standardBitrates = {
low: LD_BITRATE,
standard: SD_BITRATE,
high: HD_BITRATE
high: HD_BITRATE,
ssHigh: HD_BITRATE
};

// Check if the max. bitrates for video are specified through config.js videoQuality settings.
// Right now only VP8 bitrates are configured on the simulcast encodings, VP9 bitrates have to be
// configured on the SDP using b:AS line.
this.videoBitrates = bitrateSettings ?? standardBitrates;
const encodingBitrates = this.videoBitrates.VP8 ?? this.videoBitrates;

/**
* The startup configuration for the stream encodings that are applicable to
* the video stream when a new sender is created on the peerconnection. The initial
* config takes into account the differences in browser's simulcast implementation.
*
* Encoding parameters:
* active - determine the on/off state of a particular encoding.
* maxBitrate - max. bitrate value to be applied to that particular encoding
* based on the encoding's resolution and config.js videoQuality settings if applicable.
* rid - Rtp Stream ID that is configured for a particular simulcast stream.
* scaleResolutionDownBy - the factor by which the encoding is scaled down from the
* original resolution of the captured video.
*/
this.localStreamEncodingsConfig = [
{
active: true,
maxBitrate: browser.isFirefox() ? encodingBitrates.high : encodingBitrates.low,
rid: SIM_LAYER_1_RID,
scaleResolutionDownBy: browser.isFirefox() ? HD_SCALE_FACTOR : LD_SCALE_FACTOR
},
{
active: true,
maxBitrate: encodingBitrates.standard,
rid: SIM_LAYER_2_RID,
scaleResolutionDownBy: SD_SCALE_FACTOR
},
{
active: true,
maxBitrate: browser.isFirefox() ? encodingBitrates.low : encodingBitrates.high,
rid: SIM_LAYER_3_RID,
scaleResolutionDownBy: browser.isFirefox() ? LD_SCALE_FACTOR : HD_SCALE_FACTOR
}
];
this.encodingBitrates = this.videoBitrates.VP8 ?? this.videoBitrates;
}

/**
Expand All @@ -89,7 +56,7 @@ export class TPCUtils {
*/
_getStreamEncodings(localTrack) {
if (this.pc.isSimulcastOn() && localTrack.isVideoTrack()) {
return this.localStreamEncodingsConfig;
return this._getVideoStreamEncodings(localTrack.getVideoType());
}

return localTrack.isVideoTrack()
Expand All @@ -100,6 +67,47 @@ export class TPCUtils {
: [ { active: true } ];
}

/**
* The startup configuration for the stream encodings that are applicable to
* the video stream when a new sender is created on the peerconnection. The initial
* config takes into account the differences in browser's simulcast implementation.
*
* Encoding parameters:
* active - determine the on/off state of a particular encoding.
* maxBitrate - max. bitrate value to be applied to that particular encoding
* based on the encoding's resolution and config.js videoQuality settings if applicable.
* rid - Rtp Stream ID that is configured for a particular simulcast stream.
* scaleResolutionDownBy - the factor by which the encoding is scaled down from the
* original resolution of the captured video.
*
* @param {VideoType} videoType
*/
_getVideoStreamEncodings(videoType) {
const maxVideoBitrate = videoType === VideoType.DESKTOP && this.encodingBitrates.ssHigh
? this.encodingBitrates.ssHigh : this.encodingBitrates.high;

return [
{
active: true,
maxBitrate: browser.isFirefox() ? maxVideoBitrate : this.encodingBitrates.low,
rid: SIM_LAYER_1_RID,
scaleResolutionDownBy: browser.isFirefox() ? HD_SCALE_FACTOR : LD_SCALE_FACTOR
},
{
active: true,
maxBitrate: this.encodingBitrates.standard,
rid: SIM_LAYER_2_RID,
scaleResolutionDownBy: SD_SCALE_FACTOR
},
{
active: true,
maxBitrate: browser.isFirefox() ? this.encodingBitrates.low : maxVideoBitrate,
rid: SIM_LAYER_3_RID,
scaleResolutionDownBy: browser.isFirefox() ? LD_SCALE_FACTOR : HD_SCALE_FACTOR
}
];
}

/**
* Ensures that the ssrcs associated with a FID ssrc-group appear in the correct order, i.e.,
* the primary ssrc first and the secondary rtx ssrc later. This is important for unified
Expand Down Expand Up @@ -277,7 +285,8 @@ export class TPCUtils {
calculateEncodingsActiveState(localVideoTrack, newHeight) {
const localTrack = localVideoTrack.getTrack();
const { height } = localTrack.getSettings();
const encodingsState = this.localStreamEncodingsConfig
const videoStreamEncodings = this._getVideoStreamEncodings(localVideoTrack.getVideoType());
const encodingsState = videoStreamEncodings
.map(encoding => height / encoding.scaleResolutionDownBy)
.map((frameHeight, idx) => {
let active = localVideoTrack.getVideoType() === VideoType.CAMERA
Expand All @@ -286,7 +295,7 @@ export class TPCUtils {
// resolution. This can happen when camera is captured at resolutions higher than 720p but the
// requested resolution is 180. Since getParameters doesn't give us information about the resolutions
// of the simulcast encodings, we have to rely on our initial config for the simulcast streams.
? newHeight > 0 && this.localStreamEncodingsConfig[idx]?.scaleResolutionDownBy === LD_SCALE_FACTOR
? newHeight > 0 && videoStreamEncodings[idx]?.scaleResolutionDownBy === LD_SCALE_FACTOR
? true
: frameHeight <= newHeight

Expand All @@ -302,7 +311,7 @@ export class TPCUtils {
&& this.pc._capScreenshareBitrate
&& this.pc.usesUnifiedPlan()
&& !browser.isWebKitBased()
&& this.localStreamEncodingsConfig[idx].scaleResolutionDownBy !== HD_SCALE_FACTOR) {
&& videoStreamEncodings[idx].scaleResolutionDownBy !== HD_SCALE_FACTOR) {
active = false;
}

Expand All @@ -325,7 +334,7 @@ export class TPCUtils {
const lowFpsScreenshare = localVideoTrack.getVideoType() === VideoType.DESKTOP
&& this.pc._capScreenshareBitrate
&& !browser.isWebKitBased();
const encodingsBitrates = this.localStreamEncodingsConfig
const encodingsBitrates = this._getVideoStreamEncodings(localVideoTrack.getVideoType())
.map(encoding => {
const bitrate = lowFpsScreenshare
? desktopShareBitrate
Expand Down Expand Up @@ -491,10 +500,11 @@ export class TPCUtils {
* that were configured on the RTCRtpSender when the source was added to the peerconnection.
* This should prevent us from overriding the default values if the browser returns
* erroneous values when RTCRtpSender.getParameters is used for getting the encodings info.
* @param {JitsiLocalTrack} localVideoTrack The local video track.
* @param {Object} parameters - the RTCRtpEncodingParameters obtained from the browser.
* @returns {void}
*/
updateEncodingsResolution(parameters) {
updateEncodingsResolution(localVideoTrack, parameters) {
if (!(browser.isWebKitBased() && parameters.encodings && Array.isArray(parameters.encodings))) {
return;
}
Expand All @@ -504,8 +514,10 @@ export class TPCUtils {

// Implement the workaround only when all the encodings report the same resolution.
if (allEqualEncodings(parameters.encodings)) {
const videoStreamEncodings = this._getVideoStreamEncodings(localVideoTrack.getVideoType());

parameters.encodings.forEach((encoding, idx) => {
encoding.scaleResolutionDownBy = this.localStreamEncodingsConfig[idx].scaleResolutionDownBy;
encoding.scaleResolutionDownBy = videoStreamEncodings[idx].scaleResolutionDownBy;
});
}
}
Expand Down
5 changes: 3 additions & 2 deletions modules/RTC/TraceablePeerConnection.js
Original file line number Diff line number Diff line change
Expand Up @@ -2396,11 +2396,12 @@ TraceablePeerConnection.prototype._setVp9MaxBitrates = function(description, isL
if (this.codecPreference.mimeType === CodecMimeType.VP9) {
const bitrates = this.tpcUtils.videoBitrates.VP9 || this.tpcUtils.videoBitrates;
const hdBitrate = bitrates.high ? bitrates.high : HD_BITRATE;
const ssHdBitrate = bitrates.ssHigh ? bitrates.ssHigh : HD_BITRATE;
const mid = mLine.mid;
const isSharingScreen = FeatureFlags.isMultiStreamSendSupportEnabled()
? mid === this._getDesktopTrackMid()
: this._isSharingScreen();
const limit = Math.floor((isSharingScreen ? HD_BITRATE : hdBitrate) / 1000);
const limit = Math.floor((isSharingScreen ? ssHdBitrate : hdBitrate) / 1000);

// Use only the HD bitrate for now as there is no API available yet for configuring
// the bitrates on the individual SVC layers.
Expand Down Expand Up @@ -2641,7 +2642,7 @@ TraceablePeerConnection.prototype.setSenderVideoConstraints = function(frameHeig
}
}
}
this.tpcUtils.updateEncodingsResolution(parameters);
this.tpcUtils.updateEncodingsResolution(localVideoTrack, parameters);

// For p2p and cases and where simulcast is explicitly disabled.
} else if (frameHeight > 0) {
Expand Down

0 comments on commit 829f5ac

Please sign in to comment.