ref(large-video): permanently enable canvas based background (#3084)

* ref(large-video): permanently enable canvas based background

* squash: leave flag for disabling background
This commit is contained in:
virtuacoplenny 2018-06-15 14:41:37 -07:00 committed by Дамян Минков
parent fc643f06e4
commit 4ab8d98cd1
6 changed files with 196 additions and 304 deletions

View File

@ -5,6 +5,12 @@ var interfaceConfig = {
// methods allowing to use variables both in css and js.
DEFAULT_BACKGROUND: '#474747',
/**
* Whether or not the blurred video background for large video should be
* displayed on browsers that can support it.
*/
DISABLE_VIDEO_BACKGROUND: false,
INITIAL_TOOLBAR_TIMEOUT: 20000,
TOOLBAR_TIMEOUT: 4000,
TOOLBAR_ALWAYS_VISIBLE: false,
@ -142,17 +148,7 @@ var interfaceConfig = {
*
* @type {boolean}
*/
VIDEO_QUALITY_LABEL_DISABLED: false,
/**
* Temporary feature flag to debug performance with the large video
* background blur. On initial implementation, blur was always enabled so a
* falsy value here will be used to keep blur enabled, as will the value
* "video", and will render the blur over a video element. The value
* "canvas" will display the blur over a canvas element, while the value
* "off" will prevent the background from rendering.
*/
_BACKGROUND_BLUR: 'canvas'
VIDEO_QUALITY_LABEL_DISABLED: false
/**
* Specify custom URL for downloading android mobile app.

View File

@ -7,8 +7,7 @@ import ReactDOM from 'react-dom';
import { browser } from '../../../react/features/base/lib-jitsi-meet';
import {
ORIENTATION,
LargeVideoBackground,
LargeVideoBackgroundCanvas
LargeVideoBackground
} from '../../../react/features/large-video';
/* eslint-enable no-unused-vars */
@ -689,21 +688,17 @@ export class VideoContainer extends LargeContainer {
*/
_updateBackground() {
// Do not the background display on browsers that might experience
// performance issues from the presence of the background.
if (interfaceConfig._BACKGROUND_BLUR === 'off'
// performance issues from the presence of the background or if
// explicitly disabled.
if (interfaceConfig.DISABLE_VIDEO_BACKGROUND
|| browser.isFirefox()
|| browser.isSafariWithWebrtc()
|| browser.isTemasysPluginUsed()) {
return;
}
// eslint-disable-next-line no-unused-vars
const Background = interfaceConfig._BACKGROUND_BLUR === 'canvas'
? LargeVideoBackgroundCanvas
: LargeVideoBackground;
ReactDOM.render(
<Background
<LargeVideoBackground
hidden = { this._hideBackground }
mirror = {
this.stream

View File

@ -1,7 +1,6 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
// @flow
import { Video } from '../../base/media';
import React, { Component } from 'react';
/**
* Constants to describe the dimensions of the video. Landscape videos
@ -23,66 +22,125 @@ export const ORIENTATION = {
* @private
* @type {Object}
*/
export const ORIENTATION_TO_CLASS = {
const ORIENTATION_TO_CLASS = {
[ORIENTATION.LANDSCAPE]: 'fit-full-width',
[ORIENTATION.PORTRAIT]: 'fit-full-height'
};
/**
* The type of the React {@code Component} props of
* {@link LargeVideoBackgroundCanvas}.
*/
type Props = {
/**
* Additional CSS class names to add to the root of the component.
*/
className: String,
/**
* Whether or not the background should have its visibility hidden.
*/
hidden: boolean,
/**
* Whether or not the video should display flipped horizontally, so left
* becomes right and right becomes left.
*/
mirror: boolean,
/**
* Whether the component should ensure full width of the video is displayed
* (landscape) or full height (portrait).
*/
orientationFit: string,
/**
* Whether or not to display a filter on the video to visually indicate a
* problem with the video being displayed.
*/
showLocalProblemFilter: boolean,
/**
* Whether or not to display a filter on the video to visually indicate a
* problem with the video being displayed.
*/
showRemoteProblemFilter: boolean,
/**
* The video stream to display.
*/
videoElement: Object
};
/**
* Implements a React Component which shows a video element intended to be used
* as a background to fill the empty space of container with another video.
*
* @extends Component
*/
export class LargeVideoBackground extends Component {
export class LargeVideoBackground extends Component<Props> {
_canvasEl: Object;
_updateCanvasInterval: *;
/**
* {@code LargeVideoBackground} component's property types.
* Initializes new {@code LargeVideoBackground} instance.
*
* @static
* @param {*} props - The read-only properties with which the new instance
* is to be initialized.
*/
static propTypes = {
/**
* Additional CSS class names to add to the root of the component.
*/
className: PropTypes.string,
constructor(props: Props) {
super(props);
/**
* Whether or not the background should have its visibility hidden.
*/
hidden: PropTypes.bool,
// Bind event handlers so they are only bound once per instance.
this._setCanvasEl = this._setCanvasEl.bind(this);
this._updateCanvas = this._updateCanvas.bind(this);
}
/**
* Whether or not the video should display flipped horizontally, so
* left becomes right and right becomes left.
*/
mirror: PropTypes.bool,
/**
* If the canvas is not hidden, sets the initial interval to update the
* image displayed in the canvas.
*
* @inheritdoc
* @returns {void}
*/
componentDidMount() {
if (this.props.videoElement && !this.props.hidden) {
this._updateCanvas();
this._setUpdateCanvasInterval();
}
}
/**
* Whether the component should ensure full width of the video is
* displayed (landscape) or full height (portrait).
*/
orientationFit: PropTypes.oneOf([
ORIENTATION.LANDSCAPE,
ORIENTATION.PORTRAIT
]),
/**
* Starts or stops the interval to update the image displayed in the canvas.
*
* @inheritdoc
* @param {Object} nextProps - The read-only React {@code Component} props
* with which the new instance is to be initialized.
*/
componentWillReceiveProps(nextProps: Props) {
if (this.props.hidden && !nextProps.hidden) {
this._clearCanvas();
this._setUpdateCanvasInterval();
}
/**
* Whether or not to display a filter on the video to visually indicate
* a problem with the video being displayed.
*/
showLocalProblemFilter: PropTypes.bool,
if ((!this.props.hidden && nextProps.hidden)
|| !nextProps.videoElement) {
this._clearCanvas();
this._clearUpdateCanvasInterval();
}
}
/**
* Whether or not to display a filter on the video to visually indicate
* a problem with the video being displayed.
*/
showRemoteProblemFilter: PropTypes.bool,
/**
* The video stream to display.
*/
videoTrack: PropTypes.object
};
/**
* Clears the interval for updating the image displayed in the canvas.
*
* @inheritdoc
*/
componentWillUnmount() {
this._clearUpdateCanvasInterval();
}
/**
* Implements React's {@link Component#render()}.
@ -96,8 +154,7 @@ export class LargeVideoBackground extends Component {
mirror,
orientationFit,
showLocalProblemFilter,
showRemoteProblemFilter,
videoTrack
showRemoteProblemFilter
} = this.props;
const orientationClass = orientationFit
? ORIENTATION_TO_CLASS[orientationFit] : '';
@ -105,17 +162,91 @@ export class LargeVideoBackground extends Component {
hidden ? 'invisible' : ''} ${orientationClass} ${
showLocalProblemFilter ? 'videoProblemFilter' : ''} ${
showRemoteProblemFilter ? 'remoteVideoProblemFilter' : ''}`;
const videoTrackModel = {
jitsiTrack: hidden ? null : videoTrack
};
return (
<div className = { classNames }>
<Video
autoPlay = { true }
<canvas
id = 'largeVideoBackground'
videoTrack = { videoTrackModel } />
ref = { this._setCanvasEl } />
</div>
);
}
/**
* Removes any image displayed on the canvas.
*
* @private
* @returns {void}
*/
_clearCanvas() {
const cavnasContext = this._canvasEl.getContext('2d');
cavnasContext.clearRect(
0, 0, this._canvasEl.width, this._canvasEl.height);
}
/**
* Clears the interval for updating the image displayed in the canvas.
*
* @private
* @returns {void}
*/
_clearUpdateCanvasInterval() {
clearInterval(this._updateCanvasInterval);
}
_setCanvasEl: () => void;
/**
* Sets the instance variable for the component's canvas element so it can
* be accessed directly for drawing on.
*
* @param {Object} element - The DOM element for the component's canvas.
* @private
* @returns {void}
*/
_setCanvasEl(element) {
this._canvasEl = element;
}
/**
* Starts the interval for updating the image displayed in the canvas.
*
* @private
* @returns {void}
*/
_setUpdateCanvasInterval() {
this._clearUpdateCanvasInterval();
this._updateCanvasInterval = setInterval(this._updateCanvas, 200);
}
_updateCanvas: () => void;
/**
* Draws the current frame of the passed in video element onto the canvas.
*
* @private
* @returns {void}
*/
_updateCanvas() {
const { videoElement } = this.props;
const { videoWidth, videoHeight } = videoElement;
const {
height: canvasHeight,
width: canvasWidth
} = this._canvasEl;
const cavnasContext = this._canvasEl.getContext('2d');
if (this.props.orientationFit === ORIENTATION.LANDSCAPE) {
const heightScaledToFit = (canvasWidth / videoWidth) * videoHeight;
cavnasContext.drawImage(
videoElement, 0, 0, canvasWidth, heightScaledToFit);
} else {
const widthScaledToFit = (canvasHeight / videoHeight) * videoWidth;
cavnasContext.drawImage(
videoElement, 0, 0, widthScaledToFit, canvasHeight);
}
}
}

View File

@ -1,229 +0,0 @@
// @flow
import React, { Component } from 'react';
import { ORIENTATION, ORIENTATION_TO_CLASS } from './LargeVideoBackground';
/**
* The type of the React {@code Component} props of
* {@link LargeVideoBackgroundCanvas}.
*/
type Props = {
/**
* Additional CSS class names to add to the root of the component.
*/
className: String,
/**
* Whether or not the background should have its visibility hidden.
*/
hidden: boolean,
/**
* Whether or not the video should display flipped horizontally, so left
* becomes right and right becomes left.
*/
mirror: boolean,
/**
* Whether the component should ensure full width of the video is displayed
* (landscape) or full height (portrait).
*/
orientationFit: String,
/**
* Whether or not to display a filter on the video to visually indicate a
* problem with the video being displayed.
*/
showLocalProblemFilter: boolean,
/**
* Whether or not to display a filter on the video to visually indicate a
* problem with the video being displayed.
*/
showRemoteProblemFilter: boolean,
/**
* The video stream to display.
*/
videoElement: Object
};
/**
* Implements a React Component which shows a video element intended to be used
* as a background to fill the empty space of container with another video.
*
* @extends Component
*/
export class LargeVideoBackgroundCanvas extends Component<Props> {
_canvasEl: Object;
_updateCanvasInterval: *;
/**
* Initializes new {@code LargeVideoBackgroundCanvas} instance.
*
* @param {*} props - The read-only properties with which the new instance
* is to be initialized.
*/
constructor(props: Props) {
super(props);
// Bind event handlers so they are only bound once per instance.
this._setCanvasEl = this._setCanvasEl.bind(this);
this._updateCanvas = this._updateCanvas.bind(this);
}
/**
* If the canvas is not hidden, sets the initial interval to update the
* image displayed in the canvas.
*
* @inheritdoc
* @returns {void}
*/
componentDidMount() {
if (this.props.videoElement && !this.props.hidden) {
this._updateCanvas();
this._setUpdateCanvasInterval();
}
}
/**
* Starts or stops the interval to update the image displayed in the canvas.
*
* @inheritdoc
* @param {Object} nextProps - The read-only React {@code Component} props
* with which the new instance is to be initialized.
*/
componentWillReceiveProps(nextProps: Props) {
if (this.props.hidden && !nextProps.hidden) {
this._clearCanvas();
this._setUpdateCanvasInterval();
}
if ((!this.props.hidden && nextProps.hidden)
|| !nextProps.videoElement) {
this._clearCanvas();
this._clearUpdateCanvasInterval();
}
}
/**
* Clears the interval for updating the image displayed in the canvas.
*
* @inheritdoc
*/
componentWillUnmount() {
this._clearUpdateCanvasInterval();
}
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
* @returns {ReactElement}
*/
render() {
const {
hidden,
mirror,
orientationFit,
showLocalProblemFilter,
showRemoteProblemFilter
} = this.props;
const orientationClass = orientationFit
? ORIENTATION_TO_CLASS[orientationFit] : '';
const classNames = `large-video-background ${mirror ? 'flip-x' : ''} ${
hidden ? 'invisible' : ''} ${orientationClass} ${
showLocalProblemFilter ? 'videoProblemFilter' : ''} ${
showRemoteProblemFilter ? 'remoteVideoProblemFilter' : ''}`;
return (
<div className = { classNames }>
<canvas
id = 'largeVideoBackground'
ref = { this._setCanvasEl } />
</div>
);
}
/**
* Removes any image displayed on the canvas.
*
* @private
* @returns {void}
*/
_clearCanvas() {
const cavnasContext = this._canvasEl.getContext('2d');
cavnasContext.clearRect(
0, 0, this._canvasEl.width, this._canvasEl.height);
}
/**
* Clears the interval for updating the image displayed in the canvas.
*
* @private
* @returns {void}
*/
_clearUpdateCanvasInterval() {
clearInterval(this._updateCanvasInterval);
}
_setCanvasEl: () => void;
/**
* Sets the instance variable for the component's canvas element so it can
* be accessed directly for drawing on.
*
* @param {Object} element - The DOM element for the component's canvas.
* @private
* @returns {void}
*/
_setCanvasEl(element) {
this._canvasEl = element;
}
/**
* Starts the interval for updating the image displayed in the canvas.
*
* @private
* @returns {void}
*/
_setUpdateCanvasInterval() {
this._clearUpdateCanvasInterval();
this._updateCanvasInterval = setInterval(this._updateCanvas, 200);
}
_updateCanvas: () => void;
/**
* Draws the current frame of the passed in video element onto the canvas.
*
* @private
* @returns {void}
*/
_updateCanvas() {
const { videoElement } = this.props;
const { videoWidth, videoHeight } = videoElement;
const {
height: canvasHeight,
width: canvasWidth
} = this._canvasEl;
const cavnasContext = this._canvasEl.getContext('2d');
if (this.props.orientationFit === ORIENTATION.LANDSCAPE) {
const heightScaledToFit = (canvasWidth / videoWidth) * videoHeight;
cavnasContext.drawImage(
videoElement, 0, 0, canvasWidth, heightScaledToFit);
} else {
const widthScaledToFit = (canvasHeight / videoHeight) * videoWidth;
cavnasContext.drawImage(
videoElement, 0, 0, widthScaledToFit, canvasHeight);
}
}
}

View File

@ -1,3 +1,2 @@
export { default as LargeVideo } from './LargeVideo';
export * from './LargeVideoBackground';
export * from './LargeVideoBackgroundCanvas';