|
@@ -6,9 +6,6 @@ import {
|
6
|
6
|
timerWorkerScript
|
7
|
7
|
} from './TimerWorker';
|
8
|
8
|
|
9
|
|
-const segmentationWidth = 256;
|
10
|
|
-const segmentationHeight = 144;
|
11
|
|
-const segmentationPixelCount = segmentationWidth * segmentationHeight;
|
12
|
9
|
const blurValue = '25px';
|
13
|
10
|
|
14
|
11
|
/**
|
|
@@ -18,6 +15,8 @@ const blurValue = '25px';
|
18
|
15
|
*/
|
19
|
16
|
export default class JitsiStreamBlurEffect {
|
20
|
17
|
_model: Object;
|
|
18
|
+ _options: Object;
|
|
19
|
+ _segmentationPixelCount: number;
|
21
|
20
|
_inputVideoElement: HTMLVideoElement;
|
22
|
21
|
_onMaskFrameTimer: Function;
|
23
|
22
|
_maskFrameTimerWorker: Worker;
|
|
@@ -35,10 +34,13 @@ export default class JitsiStreamBlurEffect {
|
35
|
34
|
* Represents a modified video MediaStream track.
|
36
|
35
|
*
|
37
|
36
|
* @class
|
38
|
|
- * @param {BodyPix} bpModel - BodyPix model.
|
|
37
|
+ * @param {Object} model - Meet model.
|
|
38
|
+ * @param {Object} options - Segmentation dimensions.
|
39
|
39
|
*/
|
40
|
|
- constructor(bpModel: Object) {
|
41
|
|
- this._model = bpModel;
|
|
40
|
+ constructor(model: Object, options: Object) {
|
|
41
|
+ this._model = model;
|
|
42
|
+ this._options = options;
|
|
43
|
+ this._segmentationPixelCount = this._options.width * this._options.height;
|
42
|
44
|
|
43
|
45
|
// Bind event handler so it is only bound once for every instance.
|
44
|
46
|
this._onMaskFrameTimer = this._onMaskFrameTimer.bind(this);
|
|
@@ -76,8 +78,8 @@ export default class JitsiStreamBlurEffect {
|
76
|
78
|
this._segmentationMaskCanvas,
|
77
|
79
|
0,
|
78
|
80
|
0,
|
79
|
|
- segmentationWidth,
|
80
|
|
- segmentationHeight,
|
|
81
|
+ this._options.width,
|
|
82
|
+ this._options.height,
|
81
|
83
|
0,
|
82
|
84
|
0,
|
83
|
85
|
this._inputVideoElement.width,
|
|
@@ -89,7 +91,7 @@ export default class JitsiStreamBlurEffect {
|
89
|
91
|
this._outputCanvasCtx.drawImage(this._inputVideoElement, 0, 0);
|
90
|
92
|
|
91
|
93
|
this._outputCanvasCtx.globalCompositeOperation = 'destination-over';
|
92
|
|
- this._outputCanvasCtx.filter = `blur(${blurValue})`; // FIXME Does not work on Safari.
|
|
94
|
+ this._outputCanvasCtx.filter = `blur(${blurValue})`;
|
93
|
95
|
this._outputCanvasCtx.drawImage(this._inputVideoElement, 0, 0);
|
94
|
96
|
}
|
95
|
97
|
|
|
@@ -102,7 +104,7 @@ export default class JitsiStreamBlurEffect {
|
102
|
104
|
this._model._runInference();
|
103
|
105
|
const outputMemoryOffset = this._model._getOutputMemoryOffset() / 4;
|
104
|
106
|
|
105
|
|
- for (let i = 0; i < segmentationPixelCount; i++) {
|
|
107
|
+ for (let i = 0; i < this._segmentationPixelCount; i++) {
|
106
|
108
|
const background = this._model.HEAPF32[outputMemoryOffset + (i * 2)];
|
107
|
109
|
const person = this._model.HEAPF32[outputMemoryOffset + (i * 2) + 1];
|
108
|
110
|
const shift = Math.max(background, person);
|
|
@@ -146,19 +148,19 @@ export default class JitsiStreamBlurEffect {
|
146
|
148
|
this._inputVideoElement.height,
|
147
|
149
|
0,
|
148
|
150
|
0,
|
149
|
|
- segmentationWidth,
|
150
|
|
- segmentationHeight
|
|
151
|
+ this._options.width,
|
|
152
|
+ this._options.height
|
151
|
153
|
);
|
152
|
154
|
|
153
|
155
|
const imageData = this._segmentationMaskCtx.getImageData(
|
154
|
156
|
0,
|
155
|
157
|
0,
|
156
|
|
- segmentationWidth,
|
157
|
|
- segmentationHeight
|
|
158
|
+ this._options.width,
|
|
159
|
+ this._options.height
|
158
|
160
|
);
|
159
|
161
|
const inputMemoryOffset = this._model._getInputMemoryOffset() / 4;
|
160
|
162
|
|
161
|
|
- for (let i = 0; i < segmentationPixelCount; i++) {
|
|
163
|
+ for (let i = 0; i < this._segmentationPixelCount; i++) {
|
162
|
164
|
this._model.HEAPF32[inputMemoryOffset + (i * 3)] = imageData.data[i * 4] / 255;
|
163
|
165
|
this._model.HEAPF32[inputMemoryOffset + (i * 3) + 1] = imageData.data[(i * 4) + 1] / 255;
|
164
|
166
|
this._model.HEAPF32[inputMemoryOffset + (i * 3) + 2] = imageData.data[(i * 4) + 2] / 255;
|
|
@@ -189,10 +191,10 @@ export default class JitsiStreamBlurEffect {
|
189
|
191
|
const { height, frameRate, width }
|
190
|
192
|
= firstVideoTrack.getSettings ? firstVideoTrack.getSettings() : firstVideoTrack.getConstraints();
|
191
|
193
|
|
192
|
|
- this._segmentationMask = new ImageData(segmentationWidth, segmentationHeight);
|
|
194
|
+ this._segmentationMask = new ImageData(this._options.width, this._options.height);
|
193
|
195
|
this._segmentationMaskCanvas = document.createElement('canvas');
|
194
|
|
- this._segmentationMaskCanvas.width = segmentationWidth;
|
195
|
|
- this._segmentationMaskCanvas.height = segmentationHeight;
|
|
196
|
+ this._segmentationMaskCanvas.width = this._options.width;
|
|
197
|
+ this._segmentationMaskCanvas.height = this._options.height;
|
196
|
198
|
this._segmentationMaskCtx = this._segmentationMaskCanvas.getContext('2d');
|
197
|
199
|
this._outputCanvasElement.width = parseInt(width, 10);
|
198
|
200
|
this._outputCanvasElement.height = parseInt(height, 10);
|