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

Merge pull request #151 from jitsi/audio_problem_detection

Implements audio problems detection
dev1
Дамян Минков пре 9 година
родитељ
комит
b2e115a7fa

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

@@ -68,6 +68,7 @@ function JitsiConference(options) {
68 68
         video: undefined
69 69
     };
70 70
     this.isMutedByFocus = false;
71
+    this.reportedAudioSSRCs = {};
71 72
 }
72 73
 
73 74
 /**
@@ -944,6 +945,63 @@ JitsiConference.prototype.isCallstatsEnabled = function () {
944 945
     return this.statistics.isCallstatsEnabled();
945 946
 }
946 947
 
948
+/**
949
+ * Reports detected audio problem with the media stream related to the passed
950
+ * ssrc.
951
+ * @param ssrc {string} the ssrc
952
+ */
953
+JitsiConference.prototype._reportAudioProblem = function (ssrc) {
954
+    if(this.reportedAudioSSRCs[ssrc])
955
+        return;
956
+    var track = this.rtc.getRemoteTrackBySSRC(ssrc);
957
+    if(!track || !track.isAudioTrack())
958
+        return;
959
+
960
+    this.reportedAudioSSRCs[ssrc] = true;
961
+    var errorContent = {
962
+        errMsg: "The audio is received but not played",
963
+        ssrc: ssrc
964
+    };
965
+
966
+    var mstream = track.stream, mtrack = track.track;
967
+    if(mstream) {
968
+        errorContent.MediaStream = {
969
+            active: mstream.active,
970
+            id: mstream.id
971
+        }
972
+    }
973
+
974
+    if(mtrack) {
975
+        errorContent.MediaStreamTrack = {
976
+            enabled: mtrack.enabled,
977
+            id: mtrack.id,
978
+            label: mtrack.label,
979
+            muted: mtrack.muted
980
+        }
981
+    }
982
+
983
+    if(track.containers) {
984
+        errorContent.containers = [];
985
+        track.containers.forEach(function (container) {
986
+            errorContent.containers.push({
987
+                autoplay: container.autoplay,
988
+                muted: container.muted,
989
+                src: container.src,
990
+                volume: container.volume,
991
+                id: container.id,
992
+                ended: container.ended,
993
+                paused: container.paused,
994
+                readyState: container.readyState
995
+            });
996
+        });
997
+    }
998
+
999
+    this.statistics.sendDetectedAudioProblem(
1000
+        new Error(JSON.stringify(errorContent)));
1001
+    logger.error("Audio problem detected. The audio is received but not played",
1002
+        errorContent);
1003
+}
1004
+
947 1005
 /**
948 1006
  * Setups the listeners needed for the conference.
949 1007
  * @param conference the conference
@@ -1309,6 +1367,11 @@ function setupListeners(conference) {
1309 1367
 
1310 1368
             conference.rtc.setAudioLevel(resource, level);
1311 1369
         });
1370
+
1371
+        conference.statistics.addAudioProblemListener(function (ssrc) {
1372
+            conference._reportAudioProblem(ssrc)
1373
+        });
1374
+
1312 1375
         conference.statistics.addConnectionStatsListener(function (stats) {
1313 1376
             var ssrc2resolution = stats.resolution;
1314 1377
 

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

@@ -460,19 +460,26 @@ RTC.prototype.getResourceBySSRC = function (ssrc) {
460 460
         return Strophe.getResourceFromJid(this.room.myroomjid);
461 461
     }
462 462
 
463
-    var self = this;
464
-    var resultResource = null;
465
-    Object.keys(this.remoteTracks).some(function (resource) {
466
-        var audioTrack = self.getRemoteAudioTrack(resource);
467
-        var videoTrack = self.getRemoteVideoTrack(resource);
468
-        if((audioTrack && audioTrack.getSSRC() == ssrc) ||
469
-            (videoTrack && videoTrack.getSSRC() == ssrc)) {
470
-            resultResource = resource;
471
-            return true;
472
-        }
473
-    });
463
+    var track = this.getRemoteTrackBySSRC(ssrc);
464
+    return track? track.getParticipantId() : null;
465
+};
474 466
 
475
-    return resultResource;
467
+/**
468
+ * Searches in remoteTracks for the ssrc and returns the corresponding track.
469
+ * @param ssrc the ssrc to check.
470
+ */
471
+RTC.prototype.getRemoteTrackBySSRC = function (ssrc) {
472
+    for (var resource in this.remoteTracks) {
473
+        var track = this.getRemoteAudioTrack(resource);
474
+        if(track && track.getSSRC() == ssrc) {
475
+            return track;
476
+        }
477
+        track = this.getRemoteVideoTrack(resource);
478
+        if(track && track.getSSRC() == ssrc) {
479
+            return track;
480
+        }
481
+    }
482
+    return null;
476 483
 };
477 484
 
478 485
 module.exports = RTC;

+ 12
- 0
modules/statistics/CallStats.js Прегледај датотеку

@@ -330,6 +330,18 @@ CallStats.prototype.sendTerminateEvent = _try_catch(function () {
330 330
         callStats.fabricEvent.fabricTerminated, this.confID);
331 331
 });
332 332
 
333
+/**
334
+ * Notifies CallStats that audio problems are detected.
335
+ *
336
+ * @param {Error} e error to send
337
+ * @param {CallStats} cs callstats instance related to the error (optional)
338
+ */
339
+CallStats.prototype.sendDetectedAudioProblem = _try_catch(function (e) {
340
+    CallStats._reportError.call(this, wrtcFuncNames.signalingError, e,
341
+        this.peerconnection);
342
+});
343
+
344
+
333 345
 /**
334 346
  * Notifies CallStats for ice connection failed
335 347
  * @param {RTCPeerConnection} pc connection on which failure occured.

+ 5
- 0
modules/statistics/RTPStatsCollector.js Прегледај датотеку

@@ -639,6 +639,11 @@ StatsCollector.prototype.processStatsReport = function () {
639 639
             bytesSent = Math.round(((bytesSent * 8) / time) / 1000);
640 640
         }
641 641
 
642
+        //detect audio issues (receiving data but audioLevel == 0)
643
+        if(bytesReceived > 10 && ssrcStats.ssrc2AudioLevel === 0) {
644
+            this.eventEmitter.emit(StatisticsEvents.AUDIO_NOT_WORKING, ssrc);
645
+        }
646
+
642 647
         ssrcStats.setSsrcBitrate({
643 648
             "download": bytesReceived,
644 649
             "upload": bytesSent

+ 18
- 0
modules/statistics/statistics.js Прегледај датотеку

@@ -139,6 +139,14 @@ Statistics.prototype.addConnectionStatsListener = function (listener) {
139 139
     this.eventEmitter.on(StatisticsEvents.CONNECTION_STATS, listener);
140 140
 };
141 141
 
142
+/**
143
+ * Adds listener for detected audio problems.
144
+ * @param listener the listener.
145
+ */
146
+Statistics.prototype.addAudioProblemListener = function (listener) {
147
+    this.eventEmitter.on(StatisticsEvents.AUDIO_NOT_WORKING, listener);
148
+};
149
+
142 150
 Statistics.prototype.removeConnectionStatsListener = function (listener) {
143 151
     this.eventEmitter.removeListener(StatisticsEvents.CONNECTION_STATS, listener);
144 152
 };
@@ -364,6 +372,16 @@ Statistics.prototype.sendAddIceCandidateFailed = function (e, pc) {
364 372
         CallStats.sendAddIceCandidateFailed(e, pc, this.callstats);
365 373
 };
366 374
 
375
+/**
376
+ * Notifies CallStats that audio problems are detected.
377
+ *
378
+ * @param {Error} e error to send
379
+ */
380
+Statistics.prototype.sendDetectedAudioProblem = function (e) {
381
+    if(this.callstats)
382
+        this.callstats.sendDetectedAudioProblem(e);
383
+};
384
+
367 385
 /**
368 386
  * Adds to CallStats an application log.
369 387
  *

+ 4
- 0
service/statistics/Events.js Прегледај датотеку

@@ -7,4 +7,8 @@ module.exports = {
7 7
      * FIXME: needs documentation.
8 8
      */
9 9
     AUDIO_LEVEL: "statistics.audioLevel",
10
+    /**
11
+     * Notifies about audio problem with remote participant.
12
+     */
13
+    AUDIO_NOT_WORKING: "statistics.audio_not_working"
10 14
 };

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