Skip to content

Commit

Permalink
feat: Apply max bitrates on video sender (#1275)
Browse files Browse the repository at this point in the history
* feat: Apply max bitrates on video sender
Add the ability to control the max bitrates on the video sender through a config.js videoQuality setting.

* ref: Use '_' prefix only for internal methods
  • Loading branch information
jallamsetty1 committed Aug 5, 2020
1 parent ae2f3a7 commit f74cd0a
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 24 deletions.
23 changes: 14 additions & 9 deletions modules/RTC/TPCUtils.js
Expand Up @@ -20,10 +20,15 @@ export const SIM_LAYER_RIDS = [ SIM_LAYER_1_RID, SIM_LAYER_2_RID, SIM_LAYER_3_RI
*/
export class TPCUtils {
/**
* @constructor
* Creates a new instance for a given TraceablePeerConnection
*
* @param peerconnection - the tpc instance for which we have utility functions.
* @param videoBitrates - the bitrates to be configured on the video senders when
* simulcast is enabled.
*/
constructor(peerconnection) {
constructor(peerconnection, videoBitrates) {
this.pc = peerconnection;
this.videoBitrates = videoBitrates;

/**
* The simulcast encodings that will be configured on the RTCRtpSender
Expand All @@ -32,19 +37,19 @@ export class TPCUtils {
this.simulcastEncodings = [
{
active: true,
maxBitrate: browser.isFirefox() ? 2500000 : 200000,
maxBitrate: browser.isFirefox() ? this.videoBitrates.high : this.videoBitrates.low,
rid: SIM_LAYER_1_RID,
scaleResolutionDownBy: browser.isFirefox() ? 1.0 : 4.0
},
{
active: true,
maxBitrate: 700000,
maxBitrate: this.videoBitrates.standard,
rid: SIM_LAYER_2_RID,
scaleResolutionDownBy: 2.0
},
{
active: true,
maxBitrate: browser.isFirefox() ? 200000 : 2500000,
maxBitrate: browser.isFirefox() ? this.videoBitrates.low : this.videoBitrates.high,
rid: SIM_LAYER_3_RID,
scaleResolutionDownBy: browser.isFirefox() ? 4.0 : 1.0
}
Expand All @@ -65,7 +70,7 @@ export class TPCUtils {
* description.
* @private
*/
_ensureCorrectOrderOfSsrcs(description) {
ensureCorrectOrderOfSsrcs(description) {
const parsedSdp = transform.parse(description.sdp);

parsedSdp.media.forEach(mLine => {
Expand Down Expand Up @@ -113,7 +118,7 @@ export class TPCUtils {
* @return {Object} A session description (same format as above) object
* with its sdp field modified to advertise simulcast receive support
*/
_insertUnifiedPlanSimulcastReceive(desc) {
insertUnifiedPlanSimulcastReceive(desc) {
// a=simulcast line is not needed on browsers where
// we munge SDP for turning on simulcast. Remove this check
// when we move to RID/MID based simulcast on all browsers.
Expand Down Expand Up @@ -182,7 +187,7 @@ export class TPCUtils {
* @param {MediaStreamTrack} track - the local video track.
* @returns {void}
*/
_setSimulcastStreamConstraints(track) {
setSimulcastStreamConstraints(track) {
if (browser.isReactNative()) {
return;
}
Expand Down Expand Up @@ -230,7 +235,7 @@ export class TPCUtils {

// Construct the simulcast stream constraints for the newly added track.
if (localTrack.isVideoTrack() && localTrack.videoType === VideoType.CAMERA && this.pc.isSimulcastOn()) {
this._setSimulcastStreamConstraints(localTrack.getTrack());
this.setSimulcastStreamConstraints(localTrack.getTrack());
}
}

Expand Down
49 changes: 37 additions & 12 deletions modules/RTC/TraceablePeerConnection.js
Expand Up @@ -25,10 +25,13 @@ import { SIM_LAYER_RIDS, TPCUtils } from './TPCUtils';
// FIXME SDP tools should end up in some kind of util module

const logger = getLogger(__filename);
const MAX_BITRATE = 2500000;
const DESKSTOP_SHARE_RATE = 500000;
const DEGRADATION_PREFERENCE_CAMERA = 'maintain-framerate';
const DEGRADATION_PREFERENCE_DESKTOP = 'maintain-resolution';
const DESKSTOP_SHARE_RATE = 500000;
const HD_BITRATE = 2500000;
const LD_BITRATE = 200000;
const SD_BITRATE = 700000;

/* eslint-disable max-params */

/**
Expand Down Expand Up @@ -209,7 +212,23 @@ export default function TraceablePeerConnection(

this.peerconnection
= new RTCUtils.RTCPeerConnectionType(iceConfig, constraints);
this.tpcUtils = new TPCUtils(this);

// The standard video bitrates are used in Unified plan when switching
// between camera/desktop tracks on the same sender.
const standardVideoBitrates = {
low: LD_BITRATE,
standard: SD_BITRATE,
high: HD_BITRATE
};

// Check if the max. bitrates for video are specified through config.js
// videoQuality settings. These bitrates will be applied on all browsers
// for camera sources in simulcast mode.
const videoBitrates = this.options.videoQuality
? this.options.videoQuality.maxBitratesVideo
: standardVideoBitrates;

this.tpcUtils = new TPCUtils(this, videoBitrates);
this.updateLog = [];
this.stats = {};
this.statsinterval = null;
Expand Down Expand Up @@ -1526,7 +1545,7 @@ TraceablePeerConnection.prototype.addTrack = function(track, isInitiator = false

// Construct the simulcast stream constraints for the newly added track.
if (track.isVideoTrack() && track.videoType === VideoType.CAMERA && this.isSimulcastOn()) {
this.tpcUtils._setSimulcastStreamConstraints(track.getTrack());
this.tpcUtils.setSimulcastStreamConstraints(track.getTrack());
}
};

Expand Down Expand Up @@ -1982,15 +2001,21 @@ TraceablePeerConnection.prototype.setSenderVideoDegradationPreference = function
* @param {JitsiLocalTrack} localTrack - the local track whose
* max bitrate is to be configured.
*/
TraceablePeerConnection.prototype.setMaxBitRate = function(localTrack) {
TraceablePeerConnection.prototype.setMaxBitRate = function(localTrack = null) {
if (!localTrack) {
// eslint-disable-next-line no-param-reassign
localTrack = Array.from(this.localTracks.values()).find(t => t.isVideoTrack());
}
const trackId = localTrack.track.id;
const videoType = localTrack.videoType;

// No need to set max bitrates on the streams in the following cases.
// 1. When a 'camera' track is replaced in plan-b mode, since its a new sender.
// 2. When the config.js option for capping the SS bitrate is not enabled.
if ((browser.usesPlanB() && !this.options.capScreenshareBitrate)
|| (browser.usesPlanB() && videoType === VideoType.CAMERA)) {
// The above two conditions are ignored When max video bitrates are specified through config.js.
if (((browser.usesPlanB() && !this.options.capScreenshareBitrate)
|| (browser.usesPlanB() && videoType === VideoType.CAMERA))
&& !(this.options.videoQuality && this.options.videoQuality.maxBitratesVideo)) {
return;
}
if (!this.peerconnection.getSenders) {
Expand All @@ -2017,15 +2042,15 @@ TraceablePeerConnection.prototype.setMaxBitRate = function(localTrack) {
// capScreenshareBitrate is enabled through config.js and presenter
// is not turned on.
parameters.encodings[encoding].maxBitrate
= browser.usesPlanB()
? presenterEnabled ? MAX_BITRATE : DESKSTOP_SHARE_RATE
= browser.usesPlanB() && videoType === VideoType.DESKTOP
? presenterEnabled ? HD_BITRATE : DESKSTOP_SHARE_RATE

// In unified plan, simulcast for SS is on by default.
// When simulcast is disabled through a config.js option,
// we cap the bitrate on desktop and camera tracks to 2500 Kbps.
: this.isSimulcastOn()
? this.tpcUtils.simulcastEncodings[encoding].maxBitrate
: MAX_BITRATE;
: HD_BITRATE;
}
}
sender.setParameters(parameters);
Expand Down Expand Up @@ -2078,13 +2103,13 @@ TraceablePeerConnection.prototype.setRemoteDescription = function(description) {
description = this.simulcast.mungeRemoteDescription(description);

// eslint-disable-next-line no-param-reassign
description = this.tpcUtils._insertUnifiedPlanSimulcastReceive(description);
description = this.tpcUtils.insertUnifiedPlanSimulcastReceive(description);
this.trace(
'setRemoteDescription::postTransform (sim receive)',
dumpSDP(description));

// eslint-disable-next-line no-param-reassign
description = this.tpcUtils._ensureCorrectOrderOfSsrcs(description);
description = this.tpcUtils.ensureCorrectOrderOfSsrcs(description);
}
}

Expand Down
3 changes: 3 additions & 0 deletions modules/qualitycontrol/QualityController.js
Expand Up @@ -46,6 +46,9 @@ export class QualityController {

// Set the degradation preference on the local video track.
mediaSession.setSenderVideoDegradationPreference();

// Set the max bitrates on video sender if they are specified in config.js videoQuality settings.
mediaSession.setSenderMaxBitrates();
}

/**
Expand Down
20 changes: 17 additions & 3 deletions modules/xmpp/JingleSessionPC.js
Expand Up @@ -329,6 +329,7 @@ export default class JingleSessionPC extends JingleSession {
}
pcOptions.capScreenshareBitrate = false;
pcOptions.enableInsertableStreams = options.enableInsertableStreams;
pcOptions.videoQuality = options.videoQuality;

if (this.isP2P) {
// simulcast needs to be disabled for P2P (121) calls
Expand Down Expand Up @@ -1394,6 +1395,18 @@ export default class JingleSessionPC extends JingleSession {
IQ_TIMEOUT);
}

/**
* Sets the maximum bitrates on the local video track if the current
* session is a JVB session. Bitrate values from videoQuality settings
* in config.js will be used for configuring the sender.
* @returns {void}
*/
setSenderMaxBitrates() {
if (this._assertNotEnded() && !this.isP2P) {
return this.peerconnection.setMaxBitRate();
}
}

/**
* Sets the resolution constraint on the local camera track.
* @param {number} maxFrameHeight - The user preferred max frame height.
Expand Down Expand Up @@ -2071,11 +2084,12 @@ export default class JingleSessionPC extends JingleSession {
return this._addRemoveTrackAsMuteUnmute(
false /* add as unmute */, track)
.then(() => {
// Apply the video constraints and degradation preference on
// Apply the video constraints, max bitrates and degradation preference on
// the video sender if needed.
if (track.isVideoTrack() && browser.doesVideoMuteByStreamRemove()) {
this.peerconnection.setSenderVideoDegradationPreference();
this.peerconnection.setSenderVideoConstraint();
this.setSenderMaxBitrates();
this.setSenderVideoDegradationPreference();
this.setSenderVideoConstraint();
}
});
}
Expand Down

0 comments on commit f74cd0a

Please sign in to comment.