From ada0f5e537b8e8102cc99cf8982236e4aa6223d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Domas?= <2965063+paweldomas@users.noreply.github.com> Date: Wed, 21 Apr 2021 13:36:39 -0500 Subject: [PATCH] fix: high CPU on Chrome with low fps screen sharing (#1570) * 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 && --- modules/RTC/RTCUtils.js | 45 +++++------------------------------ modules/RTC/ScreenObtainer.js | 43 +++++++++++++-------------------- 2 files changed, 23 insertions(+), 65 deletions(-) diff --git a/modules/RTC/RTCUtils.js b/modules/RTC/RTCUtils.js index 2eba057a29..2471295fdc 100644 --- a/modules/RTC/RTCUtils.js +++ b/modules/RTC/RTCUtils.js @@ -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. @@ -1120,8 +1098,7 @@ class RTCUtils extends Listenable { desktopSharingSources: options.desktopSharingSources, gumOptions: { frameRate: options.desktopSharingFrameRate - }, - trackOptions: getTrackSSConstraints(options) + } }; } @@ -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: { @@ -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 + }; }); } diff --git a/modules/RTC/ScreenObtainer.js b/modules/RTC/ScreenObtainer.js index c624ed9d12..94ffd49b52 100644 --- a/modules/RTC/ScreenObtainer.js +++ b/modules/RTC/ScreenObtainer.js @@ -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) { @@ -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 = { @@ -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