Преглед изворни кода

feat(JitsiLocalTrack): Implement camera issues detection

tags/v0.0.2
hristoterezov пре 8 година
родитељ
комит
0d037bad65
5 измењених фајлова са 99 додато и 4 уклоњено
  1. 2
    0
      JitsiTrackError.js
  2. 5
    0
      JitsiTrackErrors.js
  3. 5
    0
      JitsiTrackEvents.js
  4. 74
    3
      modules/RTC/JitsiLocalTrack.js
  5. 13
    1
      modules/RTC/RTC.js

+ 2
- 0
JitsiTrackError.js Прегледај датотеку

26
     = "Track does not have an associated Media Stream";
26
     = "Track does not have an associated Media Stream";
27
 TRACK_ERROR_TO_MESSAGE_MAP[JitsiTrackErrors.TRACK_MUTE_UNMUTE_IN_PROGRESS]
27
 TRACK_ERROR_TO_MESSAGE_MAP[JitsiTrackErrors.TRACK_MUTE_UNMUTE_IN_PROGRESS]
28
     = "Track mute/unmute process is currently in progress";
28
     = "Track mute/unmute process is currently in progress";
29
+TRACK_ERROR_TO_MESSAGE_MAP[JitsiTrackErrors.NO_DATA_FROM_SOURCE]
30
+    = "The track has stopped receiving data from it's source";
29
 
31
 
30
 /**
32
 /**
31
  * Represents an error that occurred to a JitsiTrack. Can represent various
33
  * Represents an error that occurred to a JitsiTrack. Can represent various

+ 5
- 0
JitsiTrackErrors.js Прегледај датотеку

61
  * by a webcam.
61
  * by a webcam.
62
  */
62
  */
63
 export const UNSUPPORTED_RESOLUTION = "gum.unsupported_resolution";
63
 export const UNSUPPORTED_RESOLUTION = "gum.unsupported_resolution";
64
+/**
65
+ * Indicates that the track is no receiving any data without reason(the
66
+ * stream was stopped, etc)
67
+ */
68
+export const NO_DATA_FROM_SOURCE = "track.no_data_from_source";

+ 5
- 0
JitsiTrackEvents.js Прегледај датотеку

22
  * The video type("camera" or "desktop") of the track was changed.
22
  * The video type("camera" or "desktop") of the track was changed.
23
  */
23
  */
24
 export const TRACK_VIDEOTYPE_CHANGED = "track.videoTypeChanged";
24
 export const TRACK_VIDEOTYPE_CHANGED = "track.videoTypeChanged";
25
+/**
26
+ * Indicates that the track is no receiving any data without reason(the
27
+ * stream was stopped, etc)
28
+ */
29
+export const NO_DATA_FROM_SOURCE = "track.no_data_from_source";

+ 74
- 3
modules/RTC/JitsiLocalTrack.js Прегледај датотеку

73
     // called.
73
     // called.
74
     this._realDeviceId = this.deviceId === '' ? undefined : this.deviceId;
74
     this._realDeviceId = this.deviceId === '' ? undefined : this.deviceId;
75
 
75
 
76
+    /**
77
+     * Indicates that we have called RTCUtils.stopMediaStream for the
78
+     * MediaStream related to this JitsiTrack object.
79
+     */
80
+    this.stopStreamInProgress = false;
81
+
76
     this._onDeviceListChanged = function (devices) {
82
     this._onDeviceListChanged = function (devices) {
77
         self._setRealDeviceIdFromDeviceList(devices);
83
         self._setRealDeviceIdFromDeviceList(devices);
78
 
84
 
101
 
107
 
102
     RTCUtils.addListener(RTCEvents.DEVICE_LIST_CHANGED,
108
     RTCUtils.addListener(RTCEvents.DEVICE_LIST_CHANGED,
103
         this._onDeviceListChanged);
109
         this._onDeviceListChanged);
110
+
111
+    if(this.isVideoTrack() && this.videoType === VideoType.CAMERA) {
112
+        this._setHandler("track_mute", function () {
113
+            if(!this._checkForCameraIssues())
114
+                return;
115
+            this.eventEmitter.emit(JitsiTrackEvents.NO_DATA_FROM_SOURCE);
116
+        }.bind(this));
117
+        this._setHandler("track_ended", function () {
118
+            if(!this._checkForCameraIssues())
119
+                return;
120
+            this.eventEmitter.emit(JitsiTrackEvents.NO_DATA_FROM_SOURCE);
121
+        }.bind(this));
122
+    }
104
 }
123
 }
105
 
124
 
106
 JitsiLocalTrack.prototype = Object.create(JitsiTrack.prototype);
125
 JitsiLocalTrack.prototype = Object.create(JitsiTrack.prototype);
215
                 this._removeStreamFromConferenceAsMute(() => {
234
                 this._removeStreamFromConferenceAsMute(() => {
216
                     //FIXME: Maybe here we should set the SRC for the containers
235
                     //FIXME: Maybe here we should set the SRC for the containers
217
                     // to something
236
                     // to something
218
-                    RTCUtils.stopMediaStream(this.stream);
237
+                    this._stopMediaStream();
219
                     this._setStream(null);
238
                     this._setStream(null);
220
                     resolve();
239
                     resolve();
221
                 }, (err) => {
240
                 }, (err) => {
363
     }
382
     }
364
 
383
 
365
     if (this.stream) {
384
     if (this.stream) {
366
-        RTCUtils.stopMediaStream(this.stream);
385
+        this._stopMediaStream();
367
         this.detach();
386
         this.detach();
368
     }
387
     }
369
 
388
 
468
         setTimeout(function () {
487
         setTimeout(function () {
469
             if(this._bytesSent <= 0){
488
             if(this._bytesSent <= 0){
470
                 //we are not receiving anything from the microphone
489
                 //we are not receiving anything from the microphone
471
-                this.eventEmitter.emit(JitsiTrackEvents.TRACK_AUDIO_NOT_WORKING);
490
+                this.eventEmitter.emit(JitsiTrackEvents.NO_DATA_FROM_SOURCE);
472
             }
491
             }
473
         }.bind(this), 3000);
492
         }.bind(this), 3000);
474
         this._testByteSent = false;
493
         this._testByteSent = false;
516
     return undefined;
535
     return undefined;
517
 };
536
 };
518
 
537
 
538
+/**
539
+ * Stops the associated MediaStream.
540
+ */
541
+JitsiLocalTrack.prototype._stopMediaStream = function () {
542
+    this.stopStreamInProgress = true;
543
+    RTCUtils.stopMediaStream(this.stream);
544
+    this.stopStreamInProgress = false;
545
+}
546
+
547
+/**
548
+ * Detects camera issues on ended and mute events from MediaStreamTrack.
549
+ * @returns {boolean} true if an issue is detected and false otherwise
550
+ */
551
+JitsiLocalTrack.prototype._checkForCameraIssues = function () {
552
+    if(!this.isVideoTrack() || this.stopStreamInProgress ||
553
+        this.videoType === VideoType.DESKTOP)
554
+        return false;
555
+
556
+    return !this._isReceivingData();
557
+}
558
+
559
+/**
560
+ * Checks whether the attached MediaStream is reveiving data from source or
561
+ * not. If the stream property is null(because of mute or another reason) this
562
+ * method will return false.
563
+ * NOTE: This method doesn't indicate problem with the streams directly.
564
+ * For example in case of video mute the method will return false or if the
565
+ * user has disposed the track.
566
+ * @returns {boolean} true if the stream is receiving data and false otherwise.
567
+ */
568
+JitsiLocalTrack.prototype._isReceivingData = function () {
569
+    if(!this.stream)
570
+        return false;
571
+    var isReceivingData = false;
572
+    var tracks = this.stream.getTracks();
573
+    tracks.some(function (track) {
574
+        // In older version of the spec there is no muted property and
575
+        // readyState can have value muted. In the latest versions
576
+        // readyState can have values "live" and "ended" and there is
577
+        // muted boolean property. If the stream is muted that means that
578
+        // we aren't receiving any data from the source. We want to notify
579
+        // the users for error if the stream is muted or ended on it's
580
+        // creation.
581
+        if((!("readyState" in track) || track.readyState === "live")
582
+            && (!("muted" in track) || track.muted === false)) {
583
+            isReceivingData = true;
584
+            return true;
585
+        }
586
+        return false;
587
+    });
588
+    return isReceivingData;
589
+}
519
 
590
 
520
 module.exports = JitsiLocalTrack;
591
 module.exports = JitsiLocalTrack;

+ 13
- 1
modules/RTC/RTC.js Прегледај датотеку

6
 var RTCUtils = require("./RTCUtils.js");
6
 var RTCUtils = require("./RTCUtils.js");
7
 var JitsiTrack = require("./JitsiTrack");
7
 var JitsiTrack = require("./JitsiTrack");
8
 var JitsiLocalTrack = require("./JitsiLocalTrack.js");
8
 var JitsiLocalTrack = require("./JitsiLocalTrack.js");
9
+var JitsiTrackErrors = require("../../JitsiTrackErrors");
10
+var JitsiTrackError = require("../../JitsiTrackError");
9
 var DataChannels = require("./DataChannels");
11
 var DataChannels = require("./DataChannels");
10
 var JitsiRemoteTrack = require("./JitsiRemoteTrack.js");
12
 var JitsiRemoteTrack = require("./JitsiRemoteTrack.js");
11
 var MediaType = require("../../service/RTC/MediaType");
13
 var MediaType = require("../../service/RTC/MediaType");
79
 RTC.obtainAudioAndVideoPermissions = function (options) {
81
 RTC.obtainAudioAndVideoPermissions = function (options) {
80
     return RTCUtils.obtainAudioAndVideoPermissions(options).then(
82
     return RTCUtils.obtainAudioAndVideoPermissions(options).then(
81
         function (tracksInfo) {
83
         function (tracksInfo) {
82
-            return createLocalTracks(tracksInfo, options);
84
+            var tracks = createLocalTracks(tracksInfo, options);
85
+            var allTracksAreReceivingData = true;
86
+            tracks.some(function (track) {
87
+                if(!track._isReceivingData()) {
88
+                    allTracksAreReceivingData = false;
89
+                    return true;
90
+                }
91
+                return false;
92
+            });
93
+            return allTracksAreReceivingData? tracks : Promise.reject(
94
+                new JitsiTrackError(JitsiTrackErrors.NO_DATA_FROM_SOURCE));
83
     });
95
     });
84
 };
96
 };
85
 
97
 

Loading…
Откажи
Сачувај