fix(screenshot-capture): Prevent effect initialization on each toggle

This commit is contained in:
Mihai Uscat 2020-02-26 17:50:54 +02:00 committed by Jaya Allamsetty
parent 95eb551156
commit 2064fc8937
3 changed files with 51 additions and 33 deletions

View File

@ -2,9 +2,11 @@
import { createScreenshotCaptureEffect } from '../stream-effects/screenshot-capture';
import { getLocalVideoTrack } from '../../features/base/tracks';
import logger from './logger';
import { SET_SCREENSHOT_CAPTURE } from './actionTypes';
let ongoingEffect;
/**
* Marks the on-off state of screenshot captures.
*
@ -28,19 +30,34 @@ function setScreenshotCapture(enabled) {
* @returns {Promise}
*/
export function toggleScreenshotCaptureEffect(enabled: boolean) {
return function(dispatch: (Object) => Object, getState: () => any) {
return async function(dispatch: (Object) => Object, getState: () => any) {
const state = getState();
if (state['features/screenshot-capture'].capturesEnabled !== enabled) {
const { jitsiTrack } = getLocalVideoTrack(state['features/base/tracks']);
if (!ongoingEffect) {
ongoingEffect = await createScreenshotCaptureEffect(state);
}
// Screenshot capture effect doesn't return a modified stream. Therefore, we don't have to
// switch the stream at the conference level, starting/stopping the effect will suffice here.
return createScreenshotCaptureEffect(state)
.then(effect => {
enabled ? effect.startEffect(jitsiTrack.getOriginalStream()) : effect.stopEffect();
if (enabled) {
try {
await ongoingEffect.startEffect(
jitsiTrack.getOriginalStream(),
jitsiTrack.videoType
);
dispatch(setScreenshotCapture(enabled));
});
} catch {
// Handle promise rejection from {@code startEffect} due to stream type not being desktop.
logger.error('Unsupported stream type.');
}
} else {
ongoingEffect.stopEffect();
dispatch(setScreenshotCapture(enabled));
}
}
return Promise.resolve();

View File

@ -0,0 +1,5 @@
// @flow
import { getLogger } from '../base/logging/functions';
export default getLogger('features/screenshot-capture');

View File

@ -50,40 +50,36 @@ export default class ScreenshotCaptureEffect {
this._streamWorker.onmessage = this._handleWorkerAction;
}
/**
* Checks if the local track supports this effect.
*
* @param {JitsiLocalTrack} jitsiLocalTrack - Targeted local track.
* @returns {boolean} - Returns true if this effect can run on the specified track, false otherwise.
*/
isEnabled(jitsiLocalTrack: Object) {
return jitsiLocalTrack.isVideoTrack() && jitsiLocalTrack.videoType === 'desktop';
}
/**
* Starts the screenshot capture event on a loop.
*
* @param {MediaStream} stream - The desktop stream from which screenshots are to be sent.
* @returns {MediaStream} - The same stream, with the interval set.
* @param {string} videoType - The type of the media stream.
* @returns {Promise} - Promise that resolves once effect has started or rejects if the
* videoType parameter is not desktop.
*/
startEffect(stream: MediaStream) {
const desktopTrack = stream.getVideoTracks()[0];
const { height, width }
= desktopTrack.getSettings() ?? desktopTrack.getConstraints();
startEffect(stream: MediaStream, videoType: string) {
return new Promise<void>((resolve, reject) => {
if (videoType !== 'desktop') {
reject();
}
const desktopTrack = stream.getVideoTracks()[0];
const { height, width }
= desktopTrack.getSettings() ?? desktopTrack.getConstraints();
this._streamHeight = height;
this._streamWidth = width;
this._currentCanvas.height = parseInt(height, 10);
this._currentCanvas.width = parseInt(width, 10);
this._videoElement.height = parseInt(height, 10);
this._videoElement.width = parseInt(width, 10);
this._videoElement.srcObject = stream;
this._videoElement.play();
this._streamHeight = height;
this._streamWidth = width;
this._currentCanvas.height = parseInt(height, 10);
this._currentCanvas.width = parseInt(width, 10);
this._videoElement.height = parseInt(height, 10);
this._videoElement.width = parseInt(width, 10);
this._videoElement.srcObject = stream;
this._videoElement.play();
// Store first capture for comparisons in {@code this._handleScreenshot}.
this._videoElement.addEventListener('loadeddata', this._initScreenshotCapture);
return stream;
// Store first capture for comparisons in {@code this._handleScreenshot}.
this._videoElement.addEventListener('loadeddata', this._initScreenshotCapture);
resolve();
});
}
/**