From 1d52b158f824ec32fa754a19008df50b61f1f774 Mon Sep 17 00:00:00 2001
From: prlanzarin <prlanzarin@inf.ufrgs.br>
Date: Wed, 27 May 2020 15:15:48 +0000
Subject: [PATCH] video-provider: fix safari resolution change on
 applyConstraints, only reapply bitrate when needed

---
 .../ui/components/video-provider/service.js   | 55 ++++++++++++++-----
 1 file changed, 40 insertions(+), 15 deletions(-)

diff --git a/bigbluebutton-html5/imports/ui/components/video-provider/service.js b/bigbluebutton-html5/imports/ui/components/video-provider/service.js
index f322acef79..33d2ced3e8 100755
--- a/bigbluebutton-html5/imports/ui/components/video-provider/service.js
+++ b/bigbluebutton-html5/imports/ui/components/video-provider/service.js
@@ -434,25 +434,49 @@ class VideoService {
             parameters.encodings = [{}];
           }
 
-          parameters.encodings[0].maxBitrate = bitrate * 1000;
-          sender.setParameters(parameters)
-            .then(() => {
-              logger.info({
-                logCode: 'video_provider_bitratechange',
-                extraInfo: { bitrate },
-              }, `Bitrate changed: ${bitrate}`);
-            })
-            .catch(error => {
-              logger.warn({
-                logCode: 'video_provider_bitratechange_failed',
-                extraInfo: { bitrate, errorMessage: error.message, errorCode: error.code },
-              }, `Bitrate change failed.`);
-            });
+          const normalizedBitrate = bitrate * 1000;
+          // Only reset bitrate if it changed in some way to avoid enconder fluctuations
+          if (parameters.encodings[0].maxBitrate !== normalizedBitrate) {
+            parameters.encodings[0].maxBitrate = normalizedBitrate;
+            sender.setParameters(parameters)
+              .then(() => {
+                logger.info({
+                  logCode: 'video_provider_bitratechange',
+                  extraInfo: { bitrate },
+                }, `Bitrate changed: ${bitrate}`);
+              })
+              .catch(error => {
+                logger.warn({
+                  logCode: 'video_provider_bitratechange_failed',
+                  extraInfo: { bitrate, errorMessage: error.message, errorCode: error.code },
+                }, `Bitrate change failed.`);
+              });
+          }
         }
       })
     }
   }
 
+  // Some browsers (mainly iOS Safari) garble the stream if a constraint is
+  // reconfigured without propagating previous height/width info
+  reapplyResolutionIfNeeded (track, constraints) {
+    if (typeof track.getSettings !== 'function') {
+      return constraints;
+    }
+
+    const trackSettings = track.getSettings();
+
+    if (trackSettings.width && trackSettings.height) {
+      return {
+        ...constraints,
+        width: trackSettings.width,
+        height: trackSettings.height
+      };
+    } else {
+      return constraints;
+    }
+  }
+
   applyCameraProfile (peer, profileId) {
     const profile = CAMERA_PROFILES.find(targetProfile => targetProfile.id === profileId);
 
@@ -481,7 +505,8 @@ class VideoService {
       peer.peerConnection.getSenders().forEach(sender => {
         const { track } = sender;
         if (track && track.kind === 'video' && typeof track.applyConstraints  === 'function') {
-          track.applyConstraints(constraints.video)
+          let normalizedVideoConstraints = this.reapplyResolutionIfNeeded(track, constraints.video);
+          track.applyConstraints(normalizedVideoConstraints)
             .then(() => {
               logger.info({
                 logCode: 'video_provider_profile_applied',
-- 
GitLab