From a88409bbfa3d4d040c0386007d56dfec4eb24149 Mon Sep 17 00:00:00 2001 From: Leonard Kim Date: Wed, 10 May 2017 17:19:35 -0700 Subject: [PATCH] fix(video-label): Display based on video dimensions in LargeVideoManager In its current implementation, the VideoStatusLabel shows HD based on peer connection stats. These stats will be available on temasys browsers soon but will remain unavailable on Firefox, which does not collect height/width stats. To support VideoStatusLabel showing cross-browser, move the high-definition detection out of stat sniffing and instead check the video element itself using an interval in LargeVideoManager. (An interval was used because the temasys video object does not support the onresize event.) Also, add a cleanup path from conference.web to LargeVideoManager to remove the interval. --- config.js | 4 +- modules/UI/UI.js | 9 ++++ modules/UI/videolayout/ConnectionIndicator.js | 37 +-------------- modules/UI/videolayout/LargeVideoManager.js | 46 ++++++++++++++++++- modules/UI/videolayout/VideoLayout.js | 14 ++++++ .../conference/components/Conference.web.js | 1 + 6 files changed, 73 insertions(+), 38 deletions(-) diff --git a/config.js b/config.js index 43cc72575..cbc6799b9 100644 --- a/config.js +++ b/config.js @@ -76,7 +76,9 @@ var config = { // eslint-disable-line no-unused-vars 'During that time service will not be available. ' + 'Apologise for inconvenience.',*/ disableThirdPartyRequests: false, - minHDHeight: 540, + // The minumum value a video's height or width can be, whichever is + // smaller, to be considered high-definition. + minHDSize: 540, // If true - all users without token will be considered guests and all users // with token will be considered non-guests. Only guests will be allowed to // edit their profile. diff --git a/modules/UI/UI.js b/modules/UI/UI.js index b61ed45ea..ee5ce9e04 100644 --- a/modules/UI/UI.js +++ b/modules/UI/UI.js @@ -367,6 +367,15 @@ UI.start = function () { callee && UI.showRingOverlay(); }; +/** + * Invokes cleanup of any deferred execution within relevant UI modules. + * + * @returns {void} + */ +UI.stopDaemons = () => { + VideoLayout.resetLargeVideo(); +}; + /** * Setup some UI event listeners. */ diff --git a/modules/UI/videolayout/ConnectionIndicator.js b/modules/UI/videolayout/ConnectionIndicator.js index 3e88ed04c..2959d4b7b 100644 --- a/modules/UI/videolayout/ConnectionIndicator.js +++ b/modules/UI/videolayout/ConnectionIndicator.js @@ -1,11 +1,7 @@ -/* global $, APP, config */ +/* global $, APP */ /* jshint -W101 */ -import { - setLargeVideoHDStatus -} from '../../../react/features/base/conference'; import JitsiPopover from "../util/JitsiPopover"; -import VideoLayout from "./VideoLayout"; import UIUtil from "../util/UIUtil"; /** @@ -38,7 +34,6 @@ function ConnectionIndicator(videoContainer, videoId) { this.bitrate = null; this.showMoreValue = false; this.resolution = null; - this.isResolutionHD = null; this.transport = []; this.framerate = null; this.popover = null; @@ -405,10 +400,6 @@ ConnectionIndicator.prototype.updateConnectionQuality = let width = qualityToWidth.find(x => percent >= x.percent); this.fullIcon.style.width = width.width; - if (object && typeof object.isResolutionHD === 'boolean') { - this.isResolutionHD = object.isResolutionHD; - } - this.updateResolutionIndicator(); this.updatePopoverData(); }; @@ -418,7 +409,6 @@ ConnectionIndicator.prototype.updateConnectionQuality = */ ConnectionIndicator.prototype.updateResolution = function (resolution) { this.resolution = resolution; - this.updateResolutionIndicator(); this.updatePopoverData(); }; @@ -461,31 +451,6 @@ ConnectionIndicator.prototype.hideIndicator = function () { this.popover.forceHide(); }; -/** - * Updates the resolution indicator. - */ -ConnectionIndicator.prototype.updateResolutionIndicator = function () { - - if (this.id !== null - && VideoLayout.isCurrentlyOnLarge(this.id)) { - - let showResolutionLabel = false; - - if (this.isResolutionHD !== null) - showResolutionLabel = this.isResolutionHD; - else if (this.resolution !== null) { - let resolutions = this.resolution || {}; - Object.keys(resolutions).map(function (ssrc) { - const { height } = resolutions[ssrc]; - if (height >= config.minHDHeight) - showResolutionLabel = true; - }); - } - - APP.store.dispatch(setLargeVideoHDStatus(showResolutionLabel)); - } -}; - /** * Adds a hover listener to the popover. */ diff --git a/modules/UI/videolayout/LargeVideoManager.js b/modules/UI/videolayout/LargeVideoManager.js index a4b11d28a..42581a675 100644 --- a/modules/UI/videolayout/LargeVideoManager.js +++ b/modules/UI/videolayout/LargeVideoManager.js @@ -1,6 +1,8 @@ -/* global $, APP, JitsiMeetJS */ +/* global $, APP, config, JitsiMeetJS */ const logger = require("jitsi-meet-logger").getLogger(__filename); +import { setLargeVideoHDStatus } from '../../../react/features/base/conference'; + import Avatar from "../avatar/Avatar"; import {createDeferred} from '../../util/helpers'; import UIEvents from "../../../service/UI/UIEvents"; @@ -12,6 +14,13 @@ import AudioLevels from "../audio_levels/AudioLevels"; const ParticipantConnectionStatus = JitsiMeetJS.constants.participantConnectionStatus; const DESKTOP_CONTAINER_TYPE = 'desktop'; +/** + * The time interval in milliseconds to check the video resolution of the video + * being displayed. + * + * @type {number} + */ +const VIDEO_RESOLUTION_POLL_INTERVAL = 2000; /** * Manager for all Large containers. @@ -49,6 +58,27 @@ export default class LargeVideoManager { e => this.onHoverIn(e), e => this.onHoverOut(e) ); + + // TODO Use the onresize event when temasys video objects support it. + /** + * The interval for checking if the displayed video resolution is or is + * not high-definition. + * + * @private + * @type {timeoutId} + */ + this._updateVideoResolutionInterval = window.setInterval( + () => this._updateVideoResolutionStatus(), + VIDEO_RESOLUTION_POLL_INTERVAL); + } + + /** + * Stops any polling intervals on the instance. + * + * @returns {void} + */ + destroy() { + window.clearInterval(this._updateVideoResolutionInterval); } onHoverIn (e) { @@ -517,4 +547,18 @@ export default class LargeVideoManager { onLocalFlipXChange(val) { this.videoContainer.setLocalFlipX(val); } + + /** + * Dispatches an action to update the known resolution state of the + * large video. + * + * @private + * @returns {void} + */ + _updateVideoResolutionStatus() { + const { height, width } = this.videoContainer.getStreamSize(); + const isCurrentlyHD = Math.min(height, width) >= config.minHDSize; + + APP.store.dispatch(setLargeVideoHDStatus(isCurrentlyHD)); + } } diff --git a/modules/UI/videolayout/VideoLayout.js b/modules/UI/videolayout/VideoLayout.js index 741bc218c..7deb8555f 100644 --- a/modules/UI/videolayout/VideoLayout.js +++ b/modules/UI/videolayout/VideoLayout.js @@ -111,6 +111,18 @@ var VideoLayout = { this.registerListeners(); }, + /** + * Cleans up any existing largeVideo instance. + * + * @returns {void} + */ + resetLargeVideo() { + if (largeVideo) { + largeVideo.destroy(); + } + largeVideo = null; + }, + /** * Registering listeners for UI events in Video layout component. * @@ -132,6 +144,8 @@ var VideoLayout = { }, initLargeVideo () { + this.resetLargeVideo(); + largeVideo = new LargeVideoManager(eventEmitter); if(localFlipX) { largeVideo.onLocalFlipXChange(localFlipX); diff --git a/react/features/conference/components/Conference.web.js b/react/features/conference/components/Conference.web.js index 10e419506..8b91441f1 100644 --- a/react/features/conference/components/Conference.web.js +++ b/react/features/conference/components/Conference.web.js @@ -51,6 +51,7 @@ class Conference extends Component { * @inheritdoc */ componentWillUnmount() { + APP.UI.stopDaemons(); APP.UI.unregisterListeners(); APP.UI.unbindEvents();