Sfoglia il codice sorgente

feat(virtual-background): Desktop share as virtual background wip

master
tudordan7 4 anni fa
parent
commit
be0632783d

+ 32
- 3
css/modals/virtual-background/_virtual-background.scss Vedi File

7
     grid-template-columns: auto auto auto auto auto;
7
     grid-template-columns: auto auto auto auto auto;
8
     column-gap: 9px;
8
     column-gap: 9px;
9
     cursor: pointer;
9
     cursor: pointer;
10
-    .thumbnail:hover, .blur:hover, .slight-blur:hover, .virtual-background-none:hover{
10
+    .desktop-share:hover, .thumbnail:hover, .blur:hover, .slight-blur:hover, .virtual-background-none:hover{
11
         height: 56px;
11
         height: 56px;
12
         width: 103px;
12
         width: 103px;
13
         opacity: .5;
13
         opacity: .5;
113
         vertical-align: middle;
113
         vertical-align: middle;
114
         line-height: 60px;
114
         line-height: 60px;
115
     }
115
     }
116
+    .desktop-share{
117
+        margin-top: 8px;
118
+        background: #525252;
119
+        font-weight: bold;
120
+        height: 60px;
121
+        width: 107px;
122
+        border-radius: 6px;
123
+        text-align: center;
124
+        vertical-align: middle;
125
+        line-height: 60px;
126
+    }
127
+    .desktop-share-selected{
128
+        margin-top: 8px;
129
+        background: #525252;
130
+        font-weight: bold;
131
+        height: 56px;
132
+        width: 103px;
133
+        border-radius: 6px;
134
+        border: 2px solid #246FE5;
135
+        text-align: center;
136
+        vertical-align: middle;
137
+        line-height: 60px;
138
+    }
139
+    .share-desktop-icon{
140
+        margin-top: 15%;
141
+    }
116
 
142
 
117
     @media (min-width: 432px) and (max-width: 632px) {
143
     @media (min-width: 432px) and (max-width: 632px) {
118
         font-size: 1.5vw;
144
         font-size: 1.5vw;
119
-        .virtual-background-none, .thumbnail, .blur, .slight-blur{
145
+        .share-desktop-icon{
146
+            margin-top: 25%;
147
+        }
148
+        .desktop-share, .virtual-background-none, .thumbnail, .blur, .slight-blur{
120
             height: 60px;
149
             height: 60px;
121
             width: 60px;
150
             width: 60px;
122
         }
151
         }
123
-        .thumbnail-selected, .none-selected, .blur-selected, .slight-blur-selected{
152
+        .desktop-share-selected, .thumbnail-selected, .none-selected, .blur-selected, .slight-blur-selected{
124
             height: 56px;
153
             height: 56px;
125
             width: 56px;
154
             width: 56px;
126
         }
155
         }

+ 28
- 1
react/features/stream-effects/virtual-background/JitsiStreamBackgroundEffect.js Vedi File

1
 // @flow
1
 // @flow
2
+import { JitsiTrackEvents } from '../../base/lib-jitsi-meet';
3
+
2
 import {
4
 import {
3
     CLEAR_TIMEOUT,
5
     CLEAR_TIMEOUT,
4
     TIMEOUT_TICK,
6
     TIMEOUT_TICK,
14
 export default class JitsiStreamBackgroundEffect {
16
 export default class JitsiStreamBackgroundEffect {
15
     _model: Object;
17
     _model: Object;
16
     _options: Object;
18
     _options: Object;
19
+    _stream: Object;
17
     _segmentationPixelCount: number;
20
     _segmentationPixelCount: number;
18
     _inputVideoElement: HTMLVideoElement;
21
     _inputVideoElement: HTMLVideoElement;
19
     _onMaskFrameTimer: Function;
22
     _onMaskFrameTimer: Function;
25
     _segmentationMaskCanvas: Object;
28
     _segmentationMaskCanvas: Object;
26
     _renderMask: Function;
29
     _renderMask: Function;
27
     _virtualImage: HTMLImageElement;
30
     _virtualImage: HTMLImageElement;
31
+    _virtualVideo: HTMLVideoElement;
28
     isEnabled: Function;
32
     isEnabled: Function;
29
     startEffect: Function;
33
     startEffect: Function;
30
     stopEffect: Function;
34
     stopEffect: Function;
35
      * @class
39
      * @class
36
      * @param {Object} model - Meet model.
40
      * @param {Object} model - Meet model.
37
      * @param {Object} options - Segmentation dimensions.
41
      * @param {Object} options - Segmentation dimensions.
42
+     * @param {Object} screenSharing - Desktop track for displaying desktop share as virtual background.
38
      */
43
      */
39
-    constructor(model: Object, options: Object) {
44
+    constructor(model: Object, options: Object, screenSharing: Object) {
40
         this._options = options;
45
         this._options = options;
46
+        this._stream = screenSharing;
41
 
47
 
42
         if (this._options.virtualBackground.backgroundType === 'image') {
48
         if (this._options.virtualBackground.backgroundType === 'image') {
43
             this._virtualImage = document.createElement('img');
49
             this._virtualImage = document.createElement('img');
44
             this._virtualImage.crossOrigin = 'anonymous';
50
             this._virtualImage.crossOrigin = 'anonymous';
45
             this._virtualImage.src = this._options.virtualBackground.virtualSource;
51
             this._virtualImage.src = this._options.virtualBackground.virtualSource;
46
         }
52
         }
53
+        if (this._options.virtualBackground.backgroundType === 'desktop-share' && this._stream) {
54
+            this._virtualVideo = document.createElement('video');
55
+            this._virtualVideo.autoplay = true;
56
+            this._virtualVideo.srcObject = this._stream.stream;
57
+        }
47
         this._model = model;
58
         this._model = model;
48
         this._options = options;
59
         this._options = options;
49
         this._segmentationPixelCount = this._options.width * this._options.height;
60
         this._segmentationPixelCount = this._options.width * this._options.height;
119
                 this._inputVideoElement.width,
130
                 this._inputVideoElement.width,
120
                 this._inputVideoElement.height
131
                 this._inputVideoElement.height
121
             );
132
             );
133
+        }
134
+        if (this._options.virtualBackground.backgroundType === 'desktop-share') {
135
+            this._outputCanvasCtx.drawImage(
136
+                this._virtualVideo,
137
+                0,
138
+                0
139
+            );
122
         } else {
140
         } else {
123
             this._outputCanvasCtx.filter = `blur(${this._options.virtualBackground.blurValue}px)`;
141
             this._outputCanvasCtx.filter = `blur(${this._options.virtualBackground.blurValue}px)`;
124
             this._outputCanvasCtx.drawImage(this._inputVideoElement, 0, 0);
142
             this._outputCanvasCtx.drawImage(this._inputVideoElement, 0, 0);
234
         this._inputVideoElement.height = parseInt(height, 10);
252
         this._inputVideoElement.height = parseInt(height, 10);
235
         this._inputVideoElement.autoplay = true;
253
         this._inputVideoElement.autoplay = true;
236
         this._inputVideoElement.srcObject = stream;
254
         this._inputVideoElement.srcObject = stream;
255
+        this._stream && this._stream.on(
256
+            JitsiTrackEvents.LOCAL_TRACK_STOPPED,
257
+            () => {
258
+                this._options.virtualBackground.enabled = false;
259
+                this._options.virtualBackground.backgroundType = 'none';
260
+                this._options.virtualBackground.selectedThumbnail = 'none';
261
+                this._options.virtualBackground.backgroundEffectEnabled = false;
262
+                this._options.virtualBackground.enabled = false;
263
+            });
237
         this._inputVideoElement.onloadeddata = () => {
264
         this._inputVideoElement.onloadeddata = () => {
238
             this._maskFrameTimerWorker.postMessage({
265
             this._maskFrameTimerWorker.postMessage({
239
                 id: SET_TIMEOUT,
266
                 id: SET_TIMEOUT,

+ 8
- 1
react/features/stream-effects/virtual-background/index.js Vedi File

2
 
2
 
3
 import * as wasmCheck from 'wasm-check';
3
 import * as wasmCheck from 'wasm-check';
4
 
4
 
5
+import { createLocalTrack } from '../../base/lib-jitsi-meet/functions';
6
+
5
 import JitsiStreamBackgroundEffect from './JitsiStreamBackgroundEffect';
7
 import JitsiStreamBackgroundEffect from './JitsiStreamBackgroundEffect';
6
 import createTFLiteModule from './vendor/tflite/tflite';
8
 import createTFLiteModule from './vendor/tflite/tflite';
7
 import createTFLiteSIMDModule from './vendor/tflite/tflite-simd';
9
 import createTFLiteSIMDModule from './vendor/tflite/tflite-simd';
35
         throw new Error('JitsiStreamBackgroundEffect not supported!');
37
         throw new Error('JitsiStreamBackgroundEffect not supported!');
36
     }
38
     }
37
     let tflite;
39
     let tflite;
40
+    let screenSharing;
38
 
41
 
39
     if (wasmCheck.feature.simd) {
42
     if (wasmCheck.feature.simd) {
40
         tflite = await createTFLiteSIMDModule();
43
         tflite = await createTFLiteSIMDModule();
55
 
58
 
56
     tflite._loadModel(model.byteLength);
59
     tflite._loadModel(model.byteLength);
57
 
60
 
61
+    if (virtualBackground.backgroundType === 'desktop-share') {
62
+        screenSharing = await createLocalTrack('desktop', '');
63
+    }
64
+
58
     const options = {
65
     const options = {
59
         ...wasmCheck.feature.simd ? segmentationDimensions.model144 : segmentationDimensions.model96,
66
         ...wasmCheck.feature.simd ? segmentationDimensions.model144 : segmentationDimensions.model96,
60
         virtualBackground
67
         virtualBackground
61
     };
68
     };
62
 
69
 
63
-    return new JitsiStreamBackgroundEffect(tflite, options);
70
+    return new JitsiStreamBackgroundEffect(tflite, options, screenSharing);
64
 }
71
 }

+ 19
- 1
react/features/virtual-background/components/VirtualBackgroundDialog.js Vedi File

7
 
7
 
8
 import { Dialog, hideDialog } from '../../base/dialog';
8
 import { Dialog, hideDialog } from '../../base/dialog';
9
 import { translate } from '../../base/i18n';
9
 import { translate } from '../../base/i18n';
10
-import { Icon, IconCloseSmall, IconPlusCircle } from '../../base/icons';
10
+import { Icon, IconCloseSmall, IconPlusCircle, IconShareDesktop } from '../../base/icons';
11
 import { connect } from '../../base/redux';
11
 import { connect } from '../../base/redux';
12
 import { getLocalVideoTrack } from '../../base/tracks';
12
 import { getLocalVideoTrack } from '../../base/tracks';
13
 import { toggleBackgroundEffect } from '../actions';
13
 import { toggleBackgroundEffect } from '../actions';
119
         });
119
         });
120
     };
120
     };
121
 
121
 
122
+    const shareDesktop = async selection => {
123
+        setOptions({
124
+            backgroundType: 'desktop-share',
125
+            enabled: true,
126
+            selectedThumbnail: selection
127
+        });
128
+    };
129
+
122
     const setUploadedImageBackground = async image => {
130
     const setUploadedImageBackground = async image => {
123
         setOptions({
131
         setOptions({
124
             backgroundType: 'image',
132
             backgroundType: 'image',
222
                             onClick = { () => enableBlur(25, 'blur') }>
230
                             onClick = { () => enableBlur(25, 'blur') }>
223
                             {t('virtualBackground.blur')}
231
                             {t('virtualBackground.blur')}
224
                         </div>
232
                         </div>
233
+                        <div
234
+                            className = { _selectedThumbnail === 'desktop-share'
235
+                                ? 'desktop-share-selected'
236
+                                : 'desktop-share' }
237
+                            onClick = { () => shareDesktop('desktop-share') }>
238
+                            <Icon
239
+                                className = 'share-desktop-icon'
240
+                                size = { 30 }
241
+                                src = { IconShareDesktop } />
242
+                        </div>
225
                         {images.map((image, index) => (
243
                         {images.map((image, index) => (
226
                             <img
244
                             <img
227
                                 className = {
245
                                 className = {

+ 5
- 5
react/features/virtual-background/reducer.js Vedi File

6
 
6
 
7
 const STORE_NAME = 'features/virtual-background';
7
 const STORE_NAME = 'features/virtual-background';
8
 
8
 
9
-/**
10
- * Sets up the persistence of the feature {@code virtual-background}.
11
- */
12
-PersistenceRegistry.register(STORE_NAME, true);
13
-
14
 /**
9
 /**
15
  * Reduces redux actions which activate/deactivate virtual background image, or
10
  * Reduces redux actions which activate/deactivate virtual background image, or
16
  * indicate if the virtual image background is activated/deactivated. The
11
  * indicate if the virtual image background is activated/deactivated. The
25
 ReducerRegistry.register(STORE_NAME, (state = {}, action) => {
20
 ReducerRegistry.register(STORE_NAME, (state = {}, action) => {
26
     const { virtualSource, backgroundEffectEnabled, blurValue, backgroundType, selectedThumbnail } = action;
21
     const { virtualSource, backgroundEffectEnabled, blurValue, backgroundType, selectedThumbnail } = action;
27
 
22
 
23
+    /**
24
+     * Sets up the persistence of the feature {@code virtual-background}.
25
+     */
26
+    PersistenceRegistry.register(STORE_NAME, state.backgroundType !== 'desktop-share');
27
+
28
     switch (action.type) {
28
     switch (action.type) {
29
     case SET_VIRTUAL_BACKGROUND: {
29
     case SET_VIRTUAL_BACKGROUND: {
30
         return {
30
         return {

Loading…
Annulla
Salva