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.
This commit is contained in:
Leonard Kim 2017-05-10 17:19:35 -07:00 committed by hristoterezov
parent b8189a31ad
commit a88409bbfa
6 changed files with 73 additions and 38 deletions

View File

@ -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.

View File

@ -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.
*/

View File

@ -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.
*/

View File

@ -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));
}
}

View File

@ -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);

View File

@ -51,6 +51,7 @@ class Conference extends Component {
* @inheritdoc
*/
componentWillUnmount() {
APP.UI.stopDaemons();
APP.UI.unregisterListeners();
APP.UI.unbindEvents();