|
@@ -32,6 +32,7 @@ const logger = getLogger(__filename);
|
32
|
32
|
* One <tt>JitsiLocalTrack</tt> corresponds to one WebRTC MediaStreamTrack.
|
33
|
33
|
*/
|
34
|
34
|
export default class JitsiLocalTrack extends JitsiTrack {
|
|
35
|
+
|
35
|
36
|
/**
|
36
|
37
|
* Constructs new JitsiLocalTrack instance.
|
37
|
38
|
*
|
|
@@ -43,6 +44,7 @@ export default class JitsiLocalTrack extends JitsiTrack {
|
43
|
44
|
* JitsiRemoteTrack
|
44
|
45
|
* @param trackInfo.mediaType the MediaType of the JitsiRemoteTrack
|
45
|
46
|
* @param trackInfo.videoType the VideoType of the JitsiRemoteTrack
|
|
47
|
+ * @param trackInfo.effects the effects array contains the effect instance to use
|
46
|
48
|
* @param trackInfo.resolution the video resolution if it's a video track
|
47
|
49
|
* @param trackInfo.deviceId the ID of the local device for this track
|
48
|
50
|
* @param trackInfo.facingMode the camera facing mode used in getUserMedia
|
|
@@ -60,7 +62,8 @@ export default class JitsiLocalTrack extends JitsiTrack {
|
60
|
62
|
sourceType,
|
61
|
63
|
stream,
|
62
|
64
|
track,
|
63
|
|
- videoType
|
|
65
|
+ videoType,
|
|
66
|
+ effects = []
|
64
|
67
|
}) {
|
65
|
68
|
super(
|
66
|
69
|
/* conference */ null,
|
|
@@ -70,6 +73,16 @@ export default class JitsiLocalTrack extends JitsiTrack {
|
70
|
73
|
mediaType,
|
71
|
74
|
videoType);
|
72
|
75
|
|
|
76
|
+ const effect = effects.find(e => e.isEnabled(this));
|
|
77
|
+
|
|
78
|
+ this._effectEnabled = false;
|
|
79
|
+ this._streamChangeInProgress = false;
|
|
80
|
+
|
|
81
|
+ if (effect) {
|
|
82
|
+ this._setStream(this._startStreamEffect(effect));
|
|
83
|
+ this._effectEnabled = true;
|
|
84
|
+ }
|
|
85
|
+
|
73
|
86
|
/**
|
74
|
87
|
* The ID assigned by the RTC module on instance creation.
|
75
|
88
|
*
|
|
@@ -306,6 +319,104 @@ export default class JitsiLocalTrack extends JitsiTrack {
|
306
|
319
|
}
|
307
|
320
|
}
|
308
|
321
|
|
|
322
|
+ /**
|
|
323
|
+ * Starts the effect process and returns the modified stream.
|
|
324
|
+ *
|
|
325
|
+ * @private
|
|
326
|
+ * @param {*} effect - Represents effect instance
|
|
327
|
+ * @returns {MediaStream}
|
|
328
|
+ */
|
|
329
|
+ _startStreamEffect(effect) {
|
|
330
|
+ this._streamEffect = effect;
|
|
331
|
+ this._originalStream = this.stream;
|
|
332
|
+ this._streamEffect.startEffect(this._originalStream);
|
|
333
|
+
|
|
334
|
+ return this._streamEffect.getStreamWithEffect();
|
|
335
|
+ }
|
|
336
|
+
|
|
337
|
+ /**
|
|
338
|
+ * Stops the effect process and returns the original stream.
|
|
339
|
+ *
|
|
340
|
+ * @private
|
|
341
|
+ * @returns {MediaStream}
|
|
342
|
+ */
|
|
343
|
+ _stopStreamEffect() {
|
|
344
|
+ this._streamEffect.stopEffect();
|
|
345
|
+ this._streamEffect = null;
|
|
346
|
+
|
|
347
|
+ return this._originalStream;
|
|
348
|
+ }
|
|
349
|
+
|
|
350
|
+ /**
|
|
351
|
+ * Switches the video stream associated with this track and updates the containers.
|
|
352
|
+ *
|
|
353
|
+ * @private
|
|
354
|
+ * @param {MediaStream} newStream - The MediaStream to replace
|
|
355
|
+ * @returns {Promise}
|
|
356
|
+ */
|
|
357
|
+ _switchStream(newStream: MediaStream) {
|
|
358
|
+ if (this._streamChangeInProgress === true) {
|
|
359
|
+ return Promise.reject(new Error('Stream change already in progress!'));
|
|
360
|
+ }
|
|
361
|
+
|
|
362
|
+ this._streamChangeInProgress = true;
|
|
363
|
+
|
|
364
|
+ const conference = this.conference;
|
|
365
|
+
|
|
366
|
+ if (!conference) {
|
|
367
|
+ return Promise.resolve();
|
|
368
|
+ }
|
|
369
|
+
|
|
370
|
+ return conference.removeTrack(this)
|
|
371
|
+ .then(() => {
|
|
372
|
+ this._setStream(newStream);
|
|
373
|
+
|
|
374
|
+ if (!this.isAudioTrack()) {
|
|
375
|
+ this.containers.forEach(
|
|
376
|
+ cont => RTCUtils.attachMediaStream(cont, this.stream));
|
|
377
|
+ }
|
|
378
|
+
|
|
379
|
+ return conference.addTrack(this);
|
|
380
|
+ })
|
|
381
|
+ .then(() => {
|
|
382
|
+ this._streamChangeInProgress = false;
|
|
383
|
+ })
|
|
384
|
+ .catch(error => {
|
|
385
|
+ this._streamChangeInProgress = false;
|
|
386
|
+ logger.error('Failed to switch to new stream!', error);
|
|
387
|
+ throw error;
|
|
388
|
+ });
|
|
389
|
+ }
|
|
390
|
+
|
|
391
|
+ /**
|
|
392
|
+ * Sets the effect and switches between the modified stream and original one.
|
|
393
|
+ *
|
|
394
|
+ * @param {Boolean} enableFlag - Flag to start or stop the effect processing
|
|
395
|
+ * @param {*} effect - Represents the effect instance to use
|
|
396
|
+ * @returns {Promise}
|
|
397
|
+ */
|
|
398
|
+ enableEffect(enableFlag: Boolean, effect) {
|
|
399
|
+ if (this._effectEnabled === enableFlag) {
|
|
400
|
+ return Promise.resolve();
|
|
401
|
+ }
|
|
402
|
+
|
|
403
|
+ if (this.isMuted()) {
|
|
404
|
+ return Promise.resolve();
|
|
405
|
+ }
|
|
406
|
+
|
|
407
|
+ this._effectEnabled = enableFlag;
|
|
408
|
+
|
|
409
|
+ return this._switchStream(enableFlag ? this._startStreamEffect(effect) : this._stopStreamEffect())
|
|
410
|
+ .catch(error => {
|
|
411
|
+ if (enableFlag) {
|
|
412
|
+ this._stopStreamEffect();
|
|
413
|
+ }
|
|
414
|
+ this._effectEnabled = false;
|
|
415
|
+ logger.error('Failed to switch to new stream!', error);
|
|
416
|
+ throw error;
|
|
417
|
+ });
|
|
418
|
+ }
|
|
419
|
+
|
309
|
420
|
/**
|
310
|
421
|
* Asynchronously mutes this track.
|
311
|
422
|
*
|
|
@@ -371,6 +482,7 @@ export default class JitsiLocalTrack extends JitsiTrack {
|
371
|
482
|
this.track.enabled = !muted;
|
372
|
483
|
}
|
373
|
484
|
} else if (muted) {
|
|
485
|
+
|
374
|
486
|
promise = new Promise((resolve, reject) => {
|
375
|
487
|
logMuteInfo();
|
376
|
488
|
this._removeStreamFromConferenceAsMute(
|
|
@@ -385,6 +497,12 @@ export default class JitsiLocalTrack extends JitsiTrack {
|
385
|
497
|
},
|
386
|
498
|
reject);
|
387
|
499
|
});
|
|
500
|
+
|
|
501
|
+ promise.then(() => {
|
|
502
|
+ if (this._effectEnabled) {
|
|
503
|
+ this._stopStreamEffect();
|
|
504
|
+ }
|
|
505
|
+ });
|
388
|
506
|
} else {
|
389
|
507
|
logMuteInfo();
|
390
|
508
|
|
|
@@ -392,6 +510,7 @@ export default class JitsiLocalTrack extends JitsiTrack {
|
392
|
510
|
const streamOptions = {
|
393
|
511
|
cameraDeviceId: this.getDeviceId(),
|
394
|
512
|
devices: [ MediaType.VIDEO ],
|
|
513
|
+ effects: this._streamEffect ? [ this._streamEffect ] : [],
|
395
|
514
|
facingMode: this.getCameraFacingMode()
|
396
|
515
|
};
|
397
|
516
|
|
|
@@ -435,6 +554,10 @@ export default class JitsiLocalTrack extends JitsiTrack {
|
435
|
554
|
throw new JitsiTrackError(TRACK_NO_STREAM_FOUND);
|
436
|
555
|
}
|
437
|
556
|
|
|
557
|
+ if (this._effectEnabled) {
|
|
558
|
+ this._setStream(this._startStreamEffect(this._streamEffect));
|
|
559
|
+ }
|
|
560
|
+
|
438
|
561
|
this.containers.map(
|
439
|
562
|
cont => RTCUtils.attachMediaStream(cont, this.stream));
|
440
|
563
|
|
|
@@ -522,6 +645,10 @@ export default class JitsiLocalTrack extends JitsiTrack {
|
522
|
645
|
* @returns {Promise}
|
523
|
646
|
*/
|
524
|
647
|
dispose() {
|
|
648
|
+ if (this._effectEnabled) {
|
|
649
|
+ this._setStream(this._stopStreamEffect());
|
|
650
|
+ }
|
|
651
|
+
|
525
|
652
|
let promise = Promise.resolve();
|
526
|
653
|
|
527
|
654
|
if (this.conference) {
|
|
@@ -679,7 +806,6 @@ export default class JitsiLocalTrack extends JitsiTrack {
|
679
|
806
|
* Stops the associated MediaStream.
|
680
|
807
|
*/
|
681
|
808
|
stopStream() {
|
682
|
|
-
|
683
|
809
|
/**
|
684
|
810
|
* Indicates that we are executing {@link #stopStream} i.e.
|
685
|
811
|
* {@link RTCUtils#stopMediaStream} for the <tt>MediaStream</tt>
|
|
@@ -751,7 +877,11 @@ export default class JitsiLocalTrack extends JitsiTrack {
|
751
|
877
|
// we aren't receiving any data from the source. We want to notify
|
752
|
878
|
// the users for error if the stream is muted or ended on it's
|
753
|
879
|
// creation.
|
754
|
|
- return this.stream.getTracks().some(track =>
|
|
880
|
+
|
|
881
|
+ // For video blur enabled use the original video stream
|
|
882
|
+ const stream = this._effectEnabled ? this._originalStream : this.stream;
|
|
883
|
+
|
|
884
|
+ return stream.getTracks().some(track =>
|
755
|
885
|
(!('readyState' in track) || track.readyState === 'live')
|
756
|
886
|
&& (!('muted' in track) || track.muted !== true));
|
757
|
887
|
}
|