Browse Source

fix(virtual-background): Fix resize action and prevent mirror behavio… (#9441)

* fix(virtual-background): Fix resize action and prevent mirror behaviour on desktop share as a virtual background.
Co-authored-by: tudordan7 <tudor.pop@decagon.tech>
master
Tudor D. Pop 3 years ago
parent
commit
74d65ff596
No account linked to committer's email address

+ 22
- 11
react/features/stream-effects/virtual-background/JitsiStreamBackgroundEffect.js View File

17
 export default class JitsiStreamBackgroundEffect {
17
 export default class JitsiStreamBackgroundEffect {
18
     _model: Object;
18
     _model: Object;
19
     _options: Object;
19
     _options: Object;
20
-    _desktopShareDimensions: Object;
20
+    _stream: Object;
21
     _segmentationPixelCount: number;
21
     _segmentationPixelCount: number;
22
     _inputVideoElement: HTMLVideoElement;
22
     _inputVideoElement: HTMLVideoElement;
23
     _onMaskFrameTimer: Function;
23
     _onMaskFrameTimer: Function;
85
      * @returns {void}
85
      * @returns {void}
86
      */
86
      */
87
     runPostProcessing() {
87
     runPostProcessing() {
88
+
89
+        const track = this._stream.getVideoTracks()[0];
90
+        const { height, width } = track.getSettings() ?? track.getConstraints();
91
+
92
+        this._outputCanvasElement.height = height;
93
+        this._outputCanvasElement.width = width;
88
         this._outputCanvasCtx.globalCompositeOperation = 'copy';
94
         this._outputCanvasCtx.globalCompositeOperation = 'copy';
89
 
95
 
90
         // Draw segmentation mask.
96
         // Draw segmentation mask.
130
             );
136
             );
131
         }
137
         }
132
         if (this._options.virtualBackground.backgroundType === VIRTUAL_BACKGROUND_TYPE.DESKTOP_SHARE) {
138
         if (this._options.virtualBackground.backgroundType === VIRTUAL_BACKGROUND_TYPE.DESKTOP_SHARE) {
139
+
140
+            // save current context before applying transformations
141
+            this._outputCanvasCtx.save();
142
+
143
+            // flip the canvas and prevent mirror behaviour
144
+            this._outputCanvasCtx.scale(-1, 1);
145
+            this._outputCanvasCtx.translate(-this._outputCanvasElement.width, 0);
133
             this._outputCanvasCtx.drawImage(
146
             this._outputCanvasCtx.drawImage(
134
                 this._virtualVideo,
147
                 this._virtualVideo,
135
                 0,
148
                 0,
136
                 0,
149
                 0,
137
-                this._desktopShareDimensions.width,
138
-                this._desktopShareDimensions.height
150
+                this._outputCanvasElement.width,
151
+                this._outputCanvasElement.height
139
             );
152
             );
153
+
154
+            // restore the canvas
155
+            this._outputCanvasCtx.restore();
140
         } else {
156
         } else {
141
             this._outputCanvasCtx.filter = `blur(${this._options.virtualBackground.blurValue}px)`;
157
             this._outputCanvasCtx.filter = `blur(${this._options.virtualBackground.blurValue}px)`;
142
             this._outputCanvasCtx.drawImage(this._inputVideoElement, 0, 0);
158
             this._outputCanvasCtx.drawImage(this._inputVideoElement, 0, 0);
172
      * @returns {void}
188
      * @returns {void}
173
      */
189
      */
174
     _renderMask() {
190
     _renderMask() {
175
-        const desktopShareTrack = this._options?.virtualBackground?.virtualSource?.track;
176
-
177
-        if (desktopShareTrack) {
178
-            this._desktopShareDimensions = desktopShareTrack.getSettings ? desktopShareTrack.getSettings()
179
-                : desktopShareTrack.getConstraints();
180
-        }
181
         this.resizeSource();
191
         this.resizeSource();
182
         this.runInference();
192
         this.runInference();
183
         this.runPostProcessing();
193
         this.runPostProcessing();
239
      * @returns {MediaStream} - The stream with the applied effect.
249
      * @returns {MediaStream} - The stream with the applied effect.
240
      */
250
      */
241
     startEffect(stream: MediaStream) {
251
     startEffect(stream: MediaStream) {
252
+        this._stream = stream;
242
         this._maskFrameTimerWorker = new Worker(timerWorkerScript, { name: 'Blur effect worker' });
253
         this._maskFrameTimerWorker = new Worker(timerWorkerScript, { name: 'Blur effect worker' });
243
         this._maskFrameTimerWorker.onmessage = this._onMaskFrameTimer;
254
         this._maskFrameTimerWorker.onmessage = this._onMaskFrameTimer;
244
-        const firstVideoTrack = stream.getVideoTracks()[0];
255
+        const firstVideoTrack = this._stream.getVideoTracks()[0];
245
         const { height, frameRate, width }
256
         const { height, frameRate, width }
246
             = firstVideoTrack.getSettings ? firstVideoTrack.getSettings() : firstVideoTrack.getConstraints();
257
             = firstVideoTrack.getSettings ? firstVideoTrack.getSettings() : firstVideoTrack.getConstraints();
247
 
258
 
257
         this._inputVideoElement.width = parseInt(width, 10);
268
         this._inputVideoElement.width = parseInt(width, 10);
258
         this._inputVideoElement.height = parseInt(height, 10);
269
         this._inputVideoElement.height = parseInt(height, 10);
259
         this._inputVideoElement.autoplay = true;
270
         this._inputVideoElement.autoplay = true;
260
-        this._inputVideoElement.srcObject = stream;
271
+        this._inputVideoElement.srcObject = this._stream;
261
         this._inputVideoElement.onloadeddata = () => {
272
         this._inputVideoElement.onloadeddata = () => {
262
             this._maskFrameTimerWorker.postMessage({
273
             this._maskFrameTimerWorker.postMessage({
263
                 id: SET_TIMEOUT,
274
                 id: SET_TIMEOUT,

+ 16
- 1
react/features/virtual-background/components/VirtualBackgroundDialog.js View File

13
 import { createLocalTrack } from '../../base/lib-jitsi-meet/functions';
13
 import { createLocalTrack } from '../../base/lib-jitsi-meet/functions';
14
 import { VIDEO_TYPE } from '../../base/media';
14
 import { VIDEO_TYPE } from '../../base/media';
15
 import { connect } from '../../base/redux';
15
 import { connect } from '../../base/redux';
16
+import { updateSettings } from '../../base/settings';
16
 import { Tooltip } from '../../base/tooltip';
17
 import { Tooltip } from '../../base/tooltip';
17
 import { getLocalVideoTrack } from '../../base/tracks';
18
 import { getLocalVideoTrack } from '../../base/tracks';
18
 import { showErrorNotification } from '../../notifications';
19
 import { showErrorNotification } from '../../notifications';
73
 ];
74
 ];
74
 type Props = {
75
 type Props = {
75
 
76
 
77
+    /**
78
+     * The current local flip x status.
79
+     */
80
+    _localFlipX: boolean,
81
+
76
     /**
82
     /**
77
      * Returns the jitsi track that will have backgraund effect applied.
83
      * Returns the jitsi track that will have backgraund effect applied.
78
      */
84
      */
121
  * @returns {{Props}}
127
  * @returns {{Props}}
122
  */
128
  */
123
 function _mapStateToProps(state): Object {
129
 function _mapStateToProps(state): Object {
130
+    const { localFlipX } = state['features/base/settings'];
131
+
124
     return {
132
     return {
133
+        _localFlipX: Boolean(localFlipX),
125
         _virtualBackground: state['features/virtual-background'],
134
         _virtualBackground: state['features/virtual-background'],
126
         _selectedThumbnail: state['features/virtual-background'].selectedThumbnail,
135
         _selectedThumbnail: state['features/virtual-background'].selectedThumbnail,
127
         _jitsiTrack: getLocalVideoTrack(state['features/base/tracks'])?.jitsiTrack
136
         _jitsiTrack: getLocalVideoTrack(state['features/base/tracks'])?.jitsiTrack
136
  * @returns {ReactElement}
145
  * @returns {ReactElement}
137
  */
146
  */
138
 function VirtualBackground({
147
 function VirtualBackground({
148
+    _localFlipX,
139
     _jitsiTrack,
149
     _jitsiTrack,
140
     _selectedThumbnail,
150
     _selectedThumbnail,
141
     _virtualBackground,
151
     _virtualBackground,
178
         if (storedImages.length === backgroundsLimit) {
188
         if (storedImages.length === backgroundsLimit) {
179
             setStoredImages(storedImages.slice(1));
189
             setStoredImages(storedImages.slice(1));
180
         }
190
         }
181
-    }, [ storedImages ]);
191
+        if (!_localFlipX) {
192
+            dispatch(updateSettings({
193
+                localFlipX: !_localFlipX
194
+            }));
195
+        }
196
+    }, [ storedImages, _localFlipX ]);
182
 
197
 
183
 
198
 
184
     const enableBlur = useCallback(async () => {
199
     const enableBlur = useCallback(async () => {

+ 1
- 1
react/features/virtual-background/components/VirtualBackgroundPreview.js View File

13
 import { VIRTUAL_BACKGROUND_TYPE } from '../constants';
13
 import { VIRTUAL_BACKGROUND_TYPE } from '../constants';
14
 import { localTrackStopped } from '../functions';
14
 import { localTrackStopped } from '../functions';
15
 
15
 
16
-const videoClassName = 'video-preview-video';
16
+const videoClassName = 'video-preview-video flipVideoX';
17
 
17
 
18
 /**
18
 /**
19
  * The type of the React {@code PureComponent} props of {@link VirtualBackgroundPreview}.
19
  * The type of the React {@code PureComponent} props of {@link VirtualBackgroundPreview}.

Loading…
Cancel
Save