Skip to content

Commit

Permalink
fix: high CPU on Chrome with low fps screen sharing (#1570)
Browse files Browse the repository at this point in the history
* fix: high CPU on Chrome with low fps screen sharing

It turns out that if 5 fps is set on the track constraints,
Chrome will capture the original video in 30 fps and only
further down the pipeline will downsample it to 5 fps.
This results in very high CPU usage. Specify max FPS in
getDisplayMedia to fix the problem.

Getting rid of track.applyConstraints should also fix another
issue on Firefox where it reports 0x0 screen size after this call.

* ref(RTCUtils): remove trackOptions

* remove extra &&
  • Loading branch information
paweldomas authored Apr 21, 2021
1 parent 0dc1540 commit ada0f5e
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 65 deletions.
45 changes: 6 additions & 39 deletions modules/RTC/RTCUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -485,28 +485,6 @@ function getSSConstraints(options = {}) {
return constraints;
}

/**
* Generates constraints for screen sharing when using getDisplayMedia.
* The constraints(MediaTrackConstraints) are applied to the resulting track.
*
* @returns {Object} - MediaTrackConstraints constraints.
*/
function getTrackSSConstraints(options = {}) {
// we used to set height and width in the constraints, but this can lead
// to inconsistencies if the browser is on a lower resolution screen
// and we share a screen with bigger resolution, so they are now not set
const constraints = {
frameRate: SS_DEFAULT_FRAME_RATE
};
const { desktopSharingFrameRate } = options;

if (desktopSharingFrameRate && desktopSharingFrameRate.max) {
constraints.frameRate = desktopSharingFrameRate.max;
}

return constraints;
}

/**
* Updates the granted permissions based on the options we requested and the
* streams we received.
Expand Down Expand Up @@ -1120,8 +1098,7 @@ class RTCUtils extends Listenable {
desktopSharingSources: options.desktopSharingSources,
gumOptions: {
frameRate: options.desktopSharingFrameRate
},
trackOptions: getTrackSSConstraints(options)
}
};
}

Expand Down Expand Up @@ -1199,8 +1176,7 @@ class RTCUtils extends Listenable {

// Leverage the helper used by {@link _newGetDesktopMedia} to
// get constraints for the desktop stream.
const { gumOptions, trackOptions }
= this._parseDesktopSharingOptions(otherOptions);
const { gumOptions } = this._parseDesktopSharingOptions(otherOptions);

const constraints = {
video: {
Expand All @@ -1211,19 +1187,10 @@ class RTCUtils extends Listenable {

return this._getUserMedia(requestedDevices, constraints, timeout)
.then(stream => {
const track = stream && stream.getTracks()[0];
const applyConstrainsPromise
= track && track.applyConstraints
? track.applyConstraints(trackOptions)
: Promise.resolve();

return applyConstrainsPromise
.then(() => {
return {
sourceType: 'device',
stream
};
});
return {
sourceType: 'device',
stream
};
});
}

Expand Down
43 changes: 17 additions & 26 deletions modules/RTC/ScreenObtainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,6 @@ const ScreenObtainer = {
* @param errorCallback - The error callback.
*/
obtainScreenFromGetDisplayMedia(options, callback, errorCallback) {
logger.info('Using getDisplayMedia for screen sharing');

let getDisplayMedia;

if (navigator.getDisplayMedia) {
Expand All @@ -171,32 +169,25 @@ const ScreenObtainer = {
noiseSuppression: false
} : true;

getDisplayMedia({
video: true,
const video = Object.keys(options.gumOptions).length > 0 ? options.gumOptions : true;

// At the time of this writing 'min' constraint for fps is not supported by getDisplayMedia.
video.frameRate && delete video.frameRate.min;

const constraints = {
video,
audio,
cursor: 'always'
})
.then(stream => {
let applyConstraintsPromise;

if (stream
&& stream.getTracks()
&& stream.getTracks().length > 0) {
const videoTrack = stream.getVideoTracks()[0];

// Apply video track constraint.
if (videoTrack) {
applyConstraintsPromise = videoTrack.applyConstraints(options.trackOptions);
}
} else {
applyConstraintsPromise = Promise.resolve();
}
};

logger.info('Using getDisplayMedia for screen sharing', constraints);

applyConstraintsPromise.then(() =>
callback({
stream,
sourceId: stream.id
}));
getDisplayMedia(constraints)
.then(stream => {
callback({
stream,
sourceId: stream.id
});
})
.catch(error => {
const errorDetails = {
Expand All @@ -205,7 +196,7 @@ const ScreenObtainer = {
errorStack: error && error.stack
};

logger.error('getDisplayMedia error', errorDetails);
logger.error('getDisplayMedia error', constraints, errorDetails);

if (errorDetails.errorMsg && errorDetails.errorMsg.indexOf('denied by system') !== -1) {
// On Chrome this is the only thing different between error returned when user cancels
Expand Down

0 comments on commit ada0f5e

Please sign in to comment.