Преглед на файлове

Merge pull request #717 from jitsi/promise-based-getStats

Implements the promised based getStats. Enables them for Safari and FF.
dev1
George Politis преди 7 години
родител
ревизия
c78a113705
No account linked to committer's email address
променени са 3 файла, в които са добавени 467 реда и са изтрити 45 реда
  1. 83
    35
      modules/RTC/TraceablePeerConnection.js
  2. 2
    1
      modules/browser/BrowserCapabilities.js
  3. 382
    9
      modules/statistics/RTPStatsCollector.js

+ 83
- 35
modules/RTC/TraceablePeerConnection.js Целия файл

@@ -277,36 +277,26 @@ export default function TraceablePeerConnection(
277 277
         }
278 278
     };
279 279
 
280
-    // XXX: do all non-firefox browsers which we support also support this?
281
-    if (!browser.isFirefox() && this.maxstats) {
280
+    if (this.maxstats) {
282 281
         this.statsinterval = window.setInterval(() => {
283
-            this.peerconnection.getStats(stats => {
284
-                const results = stats.result();
285
-                const now = new Date();
286
-
287
-                for (let i = 0; i < results.length; ++i) {
288
-                    results[i].names().forEach(name => {
289
-                        // eslint-disable-next-line no-shadow
290
-                        const id = `${results[i].id}-${name}`;
291
-                        let s = this.stats[id];
292
-
293
-                        if (!s) {
294
-                            this.stats[id] = s = {
295
-                                startTime: now,
296
-                                endTime: now,
297
-                                values: [],
298
-                                times: []
299
-                            };
300
-                        }
301
-                        s.values.push(results[i].stat(name));
302
-                        s.times.push(now.getTime());
303
-                        if (s.values.length > this.maxstats) {
304
-                            s.values.shift();
305
-                            s.times.shift();
306
-                        }
307
-                        s.endTime = now;
308
-                    });
282
+            this.getStats(stats => {
283
+                if (stats.result
284
+                    && typeof stats.result === 'function') {
285
+                    const results = stats.result();
286
+
287
+                    for (let i = 0; i < results.length; ++i) {
288
+                        const res = results[i];
289
+
290
+                        res.names().forEach(name => {
291
+                            this._processStat(res, name, res.stat(name));
292
+                        });
293
+                    }
294
+                } else {
295
+                    stats.forEach(r => this._processStat(r, '', r));
309 296
                 }
297
+            }, () => {
298
+
299
+                // empty error callback
310 300
             });
311 301
         }, 1000);
312 302
     }
@@ -316,6 +306,36 @@ export default function TraceablePeerConnection(
316 306
 
317 307
 /* eslint-enable max-params */
318 308
 
309
+/**
310
+ * Process stat and adds it to the array of stats we store.
311
+ * @param report the current stats report.
312
+ * @param name the name of the report, if available
313
+ * @param statValue the value to add.
314
+ * @private
315
+ */
316
+TraceablePeerConnection.prototype._processStat
317
+    = function(report, name, statValue) {
318
+        const id = `${report.id}-${name}`;
319
+        let s = this.stats[id];
320
+        const now = new Date();
321
+
322
+        if (!s) {
323
+            this.stats[id] = s = {
324
+                startTime: now,
325
+                endTime: now,
326
+                values: [],
327
+                times: []
328
+            };
329
+        }
330
+        s.values.push(statValue);
331
+        s.times.push(now.getTime());
332
+        if (s.values.length > this.maxstats) {
333
+            s.values.shift();
334
+            s.times.shift();
335
+        }
336
+        s.endTime = now;
337
+    };
338
+
319 339
 /**
320 340
  * Returns a string representation of a SessionDescription object.
321 341
  */
@@ -531,6 +551,30 @@ TraceablePeerConnection.prototype.getTrackBySSRC = function(ssrc) {
531 551
     return null;
532 552
 };
533 553
 
554
+/**
555
+ * Tries to find SSRC number for given {@link JitsiTrack} id. It will search
556
+ * both local and remote tracks bound to this instance.
557
+ * @param {string} id
558
+ * @return {number|null}
559
+ */
560
+TraceablePeerConnection.prototype.getSsrcByTrackId = function(id) {
561
+
562
+    const findTrackById = track => track.getTrack().id === id;
563
+    const localTrack = this.getLocalTracks().find(findTrackById);
564
+
565
+    if (localTrack) {
566
+        return this.getLocalSSRC(localTrack);
567
+    }
568
+
569
+    const remoteTrack = this.getRemoteTracks().find(findTrackById);
570
+
571
+    if (remoteTrack) {
572
+        return remoteTrack.getSSRC();
573
+    }
574
+
575
+    return null;
576
+};
577
+
534 578
 /**
535 579
  * Called when new remote MediaStream is added to the PeerConnection.
536 580
  * @param {MediaStream} stream the WebRTC MediaStream for remote participant
@@ -2303,9 +2347,8 @@ TraceablePeerConnection.prototype.getStats = function(callback, errback) {
2303 2347
     // TODO (brian): After moving all browsers to adapter, check if adapter is
2304 2348
     // accounting for different getStats apis, making the browser-checking-if
2305 2349
     // unnecessary.
2306
-    if (browser.isFirefox()
2307
-            || browser.isTemasysPluginUsed()
2308
-            || browser.isReactNative()) {
2350
+    if (browser.isTemasysPluginUsed()
2351
+        || browser.isReactNative()) {
2309 2352
         this.peerconnection.getStats(
2310 2353
             null,
2311 2354
             callback,
@@ -2314,10 +2357,15 @@ TraceablePeerConnection.prototype.getStats = function(callback, errback) {
2314 2357
                 // Making sure that getStats won't fail if error callback is
2315 2358
                 // not passed.
2316 2359
             }));
2317
-    } else if (browser.isSafariWithWebrtc()) {
2318
-        // FIXME: Safari's native stats implementation is not compatibile with
2319
-        // existing stats processing logic. Skip implementing stats for now to
2320
-        // at least get native webrtc Safari available for use.
2360
+    } else if (browser.isSafariWithWebrtc() || browser.isFirefox()) {
2361
+        // uses the new Promise based getStats
2362
+        this.peerconnection.getStats()
2363
+            .then(callback)
2364
+            .catch(errback || (() => {
2365
+
2366
+                // Making sure that getStats won't fail if error callback is
2367
+                // not passed.
2368
+            }));
2321 2369
     } else {
2322 2370
         this.peerconnection.getStats(callback);
2323 2371
     }

+ 2
- 1
modules/browser/BrowserCapabilities.js Целия файл

@@ -91,7 +91,8 @@ export default class BrowserCapabilities extends BrowserDetection {
91 91
     supportsBandwidthStatistics() {
92 92
         // FIXME bandwidth stats are currently not implemented for FF on our
93 93
         // side, but not sure if not possible ?
94
-        return !this.isFirefox() && !this.isEdge();
94
+        return !this.isFirefox() && !this.isEdge()
95
+            && !this.isSafariWithWebrtc();
95 96
     }
96 97
 
97 98
     /**

+ 382
- 9
modules/statistics/RTPStatsCollector.js Целия файл

@@ -2,6 +2,7 @@ import browser from '../browser';
2 2
 import { browsers } from 'js-utils';
3 3
 
4 4
 import * as StatisticsEvents from '../../service/statistics/Events';
5
+import * as MediaType from '../../service/RTC/MediaType';
5 6
 
6 7
 const GlobalOnErrorHandler = require('../util/GlobalOnErrorHandler');
7 8
 const logger = require('jitsi-meet-logger').getLogger(__filename);
@@ -10,7 +11,8 @@ const logger = require('jitsi-meet-logger').getLogger(__filename);
10 11
 const browserSupported = browser.isChrome()
11 12
         || browser.isOpera() || browser.isFirefox()
12 13
         || browser.isNWJS() || browser.isElectron()
13
-        || browser.isTemasysPluginUsed() || browser.isEdge();
14
+        || browser.isTemasysPluginUsed() || browser.isEdge()
15
+        || browser.isSafariWithWebrtc();
14 16
 
15 17
 /**
16 18
  * The lib-jitsi-meet browser-agnostic names of the browser-specific keys
@@ -25,7 +27,10 @@ KEYS_BY_BROWSER_TYPE[browsers.FIREFOX] = {
25 27
     'packetsSent': 'packetsSent',
26 28
     'bytesReceived': 'bytesReceived',
27 29
     'bytesSent': 'bytesSent',
28
-    'framerateMean': 'framerateMean'
30
+    'framerateMean': 'framerateMean',
31
+    'ip': 'ipAddress',
32
+    'port': 'portNumber',
33
+    'protocol': 'transport'
29 34
 };
30 35
 KEYS_BY_BROWSER_TYPE[browsers.CHROME] = {
31 36
     'receiveBandwidth': 'googAvailableReceiveBandwidth',
@@ -50,7 +55,10 @@ KEYS_BY_BROWSER_TYPE[browsers.CHROME] = {
50 55
     'audioOutputLevel': 'audioOutputLevel',
51 56
     'currentRoundTripTime': 'googRtt',
52 57
     'remoteCandidateType': 'googRemoteCandidateType',
53
-    'localCandidateType': 'googLocalCandidateType'
58
+    'localCandidateType': 'googLocalCandidateType',
59
+    'ip': 'ip',
60
+    'port': 'port',
61
+    'protocol': 'protocol'
54 62
 };
55 63
 KEYS_BY_BROWSER_TYPE[browsers.EDGE] = {
56 64
     'sendBandwidth': 'googAvailableSendBandwidth',
@@ -233,6 +241,13 @@ export default function StatsCollector(
233 241
         throw `The browser type '${this._browserType}' isn't supported!`;
234 242
     }
235 243
 
244
+    /**
245
+     * Whether to use the Promise-based getStats API or not.
246
+     * @type {boolean}
247
+     */
248
+    this._usesPromiseGetStats
249
+        = browser.isSafariWithWebrtc() || browser.isFirefox();
250
+
236 251
     /**
237 252
      * The function which is to be used to retrieve the value associated in a
238 253
      * report returned by RTCPeerConnection#getStats with a lib-jitsi-meet
@@ -241,7 +256,10 @@ export default function StatsCollector(
241 256
      * @function
242 257
      * @private
243 258
      */
244
-    this._getStatValue = this._defineGetStatValueMethod(keys);
259
+    this._getStatValue
260
+        = this._usesPromiseGetStats
261
+            ? this._defineNewGetStatValueMethod(keys)
262
+            : this._defineGetStatValueMethod(keys);
245 263
 
246 264
     this.peerconnection = peerconnection;
247 265
     this.baselineAudioLevelsReport = null;
@@ -313,7 +331,12 @@ StatsCollector.prototype.start = function(startAudioLevelStats) {
313 331
                             results = report.result();
314 332
                         }
315 333
                         self.currentAudioLevelsReport = results;
316
-                        self.processAudioLevelReport();
334
+                        if (this._usesPromiseGetStats) {
335
+                            self.processNewAudioLevelReport();
336
+                        } else {
337
+                            self.processAudioLevelReport();
338
+                        }
339
+
317 340
                         self.baselineAudioLevelsReport
318 341
                             = self.currentAudioLevelsReport;
319 342
                     },
@@ -343,7 +366,11 @@ StatsCollector.prototype.start = function(startAudioLevelStats) {
343 366
 
344 367
                         self.currentStatsReport = results;
345 368
                         try {
346
-                            self.processStatsReport();
369
+                            if (this._usesPromiseGetStats) {
370
+                                self.processNewStatsReport();
371
+                            } else {
372
+                                self.processStatsReport();
373
+                            }
347 374
                         } catch (e) {
348 375
                             GlobalOnErrorHandler.callErrorHandler(e);
349 376
                             logger.error(`Unsupported key:${e}`, e);
@@ -722,6 +749,16 @@ StatsCollector.prototype.processStatsReport = function() {
722 749
         }
723 750
     }
724 751
 
752
+    this.eventEmitter.emit(
753
+        StatisticsEvents.BYTE_SENT_STATS, this.peerconnection, byteSentStats);
754
+
755
+    this._processAndEmitReport();
756
+};
757
+
758
+/**
759
+ *
760
+ */
761
+StatsCollector.prototype._processAndEmitReport = function() {
725 762
     // process stats
726 763
     const totalPackets = {
727 764
         download: 0,
@@ -804,9 +841,6 @@ StatsCollector.prototype.processStatsReport = function() {
804 841
         ssrcStats.resetBitrate();
805 842
     }
806 843
 
807
-    this.eventEmitter.emit(
808
-        StatisticsEvents.BYTE_SENT_STATS, this.peerconnection, byteSentStats);
809
-
810 844
     this.conferenceStats.bitrate = {
811 845
         'upload': bitrateUpload,
812 846
         'download': bitrateDownload
@@ -940,3 +974,342 @@ StatsCollector.prototype.processAudioLevelReport = function() {
940 974
 };
941 975
 
942 976
 /* eslint-enable no-continue */
977
+
978
+/**
979
+ * New promised based getStats report processing.
980
+ * Tested with chrome, firefox and safari. Not switching it on for chrome as
981
+ * frameRate stat is missing and calculating it using framesSent,
982
+ * gives values double the values seen in webrtc-internals.
983
+ * https://w3c.github.io/webrtc-stats/
984
+ */
985
+
986
+/**
987
+ * Defines a function which (1) is to be used as a StatsCollector method and (2)
988
+ * gets the value from a specific report returned by RTCPeerConnection#getStats
989
+ * associated with a lib-jitsi-meet browser-agnostic name in case of using
990
+ * Promised based getStats.
991
+ *
992
+ * @param {Object.<string,string>} keys the map of LibJitsi browser-agnostic
993
+ * names to RTCPeerConnection#getStats browser-specific keys
994
+ */
995
+StatsCollector.prototype._defineNewGetStatValueMethod = function(keys) {
996
+    // Define the function which converts a lib-jitsi-meet browser-asnostic name
997
+    // to a browser-specific key of a report returned by
998
+    // RTCPeerConnection#getStats.
999
+    const keyFromName = function(name) {
1000
+        const key = keys[name];
1001
+
1002
+        if (key) {
1003
+            return key;
1004
+        }
1005
+
1006
+        // eslint-disable-next-line no-throw-literal
1007
+        throw `The property '${name}' isn't supported!`;
1008
+    };
1009
+
1010
+    // Compose the 2 functions defined above to get a function which retrieves
1011
+    // the value from a specific report returned by RTCPeerConnection#getStats
1012
+    // associated with a specific lib-jitsi-meet browser-agnostic name.
1013
+    return (item, name) => item[keyFromName(name)];
1014
+};
1015
+
1016
+/**
1017
+ * Converts the value to a non-negative number.
1018
+ * If the value is either invalid or negative then 0 will be returned.
1019
+ * @param {*} v
1020
+ * @return {number}
1021
+ * @private
1022
+ */
1023
+StatsCollector.prototype.getNonNegativeValue = function(v) {
1024
+    let value = v;
1025
+
1026
+    if (typeof value !== 'number') {
1027
+        value = Number(value);
1028
+    }
1029
+
1030
+    if (isNaN(value)) {
1031
+        return 0;
1032
+    }
1033
+
1034
+    return Math.max(0, value);
1035
+};
1036
+
1037
+/**
1038
+ * Calculates bitrate between before and now using a supplied field name and its
1039
+ * value in the stats.
1040
+ * @param {RTCInboundRtpStreamStats|RTCSentRtpStreamStats} now the current stats
1041
+ * @param {RTCInboundRtpStreamStats|RTCSentRtpStreamStats} before the
1042
+ * previous stats.
1043
+ * @param fieldName the field to use for calculations.
1044
+ * @return {number} the calculated bitrate between now and before.
1045
+ * @private
1046
+ */
1047
+StatsCollector.prototype._calculateBitrate = function(now, before, fieldName) {
1048
+    const bytesNow = this.getNonNegativeValue(now[fieldName]);
1049
+    const bytesBefore = this.getNonNegativeValue(before[fieldName]);
1050
+    const bytesProcessed = Math.max(0, bytesNow - bytesBefore);
1051
+
1052
+    const timeMs = now.timestamp - before.timestamp;
1053
+    let bitrateKbps = 0;
1054
+
1055
+    if (timeMs > 0) {
1056
+        // TODO is there any reason to round here?
1057
+        bitrateKbps = Math.round((bytesProcessed * 8) / timeMs);
1058
+    }
1059
+
1060
+    return bitrateKbps;
1061
+};
1062
+
1063
+/**
1064
+ * Stats processing new getStats logic.
1065
+ */
1066
+StatsCollector.prototype.processNewStatsReport = function() {
1067
+    if (!this.previousStatsReport) {
1068
+        return;
1069
+    }
1070
+
1071
+    const getStatValue = this._getStatValue;
1072
+    const byteSentStats = {};
1073
+
1074
+    this.currentStatsReport.forEach(now => {
1075
+
1076
+        // RTCIceCandidatePairStats
1077
+        // https://w3c.github.io/webrtc-stats/#candidatepair-dict*
1078
+        if (now.type === 'candidate-pair'
1079
+            && now.nominated
1080
+            && now.state === 'succeeded') {
1081
+
1082
+            const availableIncomingBitrate = now.availableIncomingBitrate;
1083
+            const availableOutgoingBitrate = now.availableOutgoingBitrate;
1084
+
1085
+            if (availableIncomingBitrate || availableOutgoingBitrate) {
1086
+                this.conferenceStats.bandwidth = {
1087
+                    'download': Math.round(availableIncomingBitrate / 1000),
1088
+                    'upload': Math.round(availableOutgoingBitrate / 1000)
1089
+                };
1090
+            }
1091
+
1092
+            const remoteUsedCandidate
1093
+                = this.currentStatsReport.get(now.remoteCandidateId);
1094
+            const localUsedCandidate
1095
+                = this.currentStatsReport.get(now.localCandidateId);
1096
+
1097
+            // RTCIceCandidateStats
1098
+            // https://w3c.github.io/webrtc-stats/#icecandidate-dict*
1099
+            // safari currently does not provide ice candidates in stats
1100
+            if (remoteUsedCandidate && localUsedCandidate) {
1101
+                // FF uses non-standard ipAddress, portNumber, transport
1102
+                // instead of ip, port, protocol
1103
+                const remoteIpAddress = getStatValue(remoteUsedCandidate, 'ip');
1104
+                const remotePort = getStatValue(remoteUsedCandidate, 'port');
1105
+                const ip = `${remoteIpAddress}:${remotePort}`;
1106
+
1107
+                const localIpAddress = getStatValue(localUsedCandidate, 'ip');
1108
+                const localPort = getStatValue(localUsedCandidate, 'port');
1109
+
1110
+                const localIp = `${localIpAddress}:${localPort}`;
1111
+                const type = getStatValue(remoteUsedCandidate, 'protocol');
1112
+
1113
+                // Save the address unless it has been saved already.
1114
+                const conferenceStatsTransport = this.conferenceStats.transport;
1115
+
1116
+                if (!conferenceStatsTransport.some(
1117
+                        t =>
1118
+                            t.ip === ip
1119
+                            && t.type === type
1120
+                            && t.localip === localIp)) {
1121
+                    conferenceStatsTransport.push({
1122
+                        ip,
1123
+                        type,
1124
+                        localIp,
1125
+                        p2p: this.peerconnection.isP2P,
1126
+                        localCandidateType: localUsedCandidate.candidateType,
1127
+                        remoteCandidateType: remoteUsedCandidate.candidateType,
1128
+                        networkType: localUsedCandidate.networkType,
1129
+                        rtt: now.currentRoundTripTime * 1000
1130
+                    });
1131
+                }
1132
+            }
1133
+
1134
+        // RTCReceivedRtpStreamStats
1135
+        // https://w3c.github.io/webrtc-stats/#receivedrtpstats-dict*
1136
+        // RTCSentRtpStreamStats
1137
+        // https://w3c.github.io/webrtc-stats/#sentrtpstats-dict*
1138
+        } else if (now.type === 'inbound-rtp' || now.type === 'outbound-rtp') {
1139
+            const before = this.previousStatsReport.get(now.id);
1140
+            const ssrc = this.getNonNegativeValue(now.ssrc);
1141
+
1142
+            if (!before || !ssrc) {
1143
+                return;
1144
+            }
1145
+
1146
+            let ssrcStats = this.ssrc2stats.get(ssrc);
1147
+
1148
+            if (!ssrcStats) {
1149
+                ssrcStats = new SsrcStats();
1150
+                this.ssrc2stats.set(ssrc, ssrcStats);
1151
+            }
1152
+
1153
+            let isDownloadStream = true;
1154
+            let key = 'packetsReceived';
1155
+
1156
+            if (now.type === 'outbound-rtp') {
1157
+                isDownloadStream = false;
1158
+                key = 'packetsSent';
1159
+            }
1160
+
1161
+            let packetsNow = now[key];
1162
+
1163
+            if (!packetsNow || packetsNow < 0) {
1164
+                packetsNow = 0;
1165
+            }
1166
+
1167
+            const packetsBefore = this.getNonNegativeValue(before[key]);
1168
+            const packetsDiff = Math.max(0, packetsNow - packetsBefore);
1169
+
1170
+            const packetsLostNow
1171
+                = this.getNonNegativeValue(now.packetsLost);
1172
+            const packetsLostBefore
1173
+                = this.getNonNegativeValue(before.packetsLost);
1174
+            const packetsLostDiff
1175
+                = Math.max(0, packetsLostNow - packetsLostBefore);
1176
+
1177
+            ssrcStats.setLoss({
1178
+                packetsTotal: packetsDiff + packetsLostDiff,
1179
+                packetsLost: packetsLostDiff,
1180
+                isDownloadStream
1181
+            });
1182
+
1183
+            if (now.type === 'inbound-rtp') {
1184
+
1185
+                ssrcStats.addBitrate({
1186
+                    'download': this._calculateBitrate(
1187
+                                    now, before, 'bytesReceived'),
1188
+                    'upload': 0
1189
+                });
1190
+
1191
+                // RTCInboundRtpStreamStats
1192
+                // https://w3c.github.io/webrtc-stats/#inboundrtpstats-dict*
1193
+                // TODO: can we use framesDecoded for frame rate, available
1194
+                // in chrome
1195
+            } else {
1196
+                byteSentStats[ssrc] = this.getNonNegativeValue(now.bytesSent);
1197
+                ssrcStats.addBitrate({
1198
+                    'download': 0,
1199
+                    'upload': this._calculateBitrate(
1200
+                                now, before, 'bytesSent')
1201
+                });
1202
+
1203
+                // RTCOutboundRtpStreamStats
1204
+                // https://w3c.github.io/webrtc-stats/#outboundrtpstats-dict*
1205
+                // TODO: can we use framesEncoded for frame rate, available
1206
+                // in chrome
1207
+            }
1208
+
1209
+            // FF has framerateMean out of spec
1210
+            const framerateMean = now.framerateMean;
1211
+
1212
+            if (framerateMean) {
1213
+                ssrcStats.setFramerate(Math.round(framerateMean || 0));
1214
+            }
1215
+
1216
+        // track for resolution
1217
+        // RTCVideoHandlerStats
1218
+        // https://w3c.github.io/webrtc-stats/#vststats-dict*
1219
+        // RTCMediaHandlerStats
1220
+        // https://w3c.github.io/webrtc-stats/#mststats-dict*
1221
+        } else if (now.type === 'track') {
1222
+
1223
+            const resolution = {
1224
+                height: now.frameHeight,
1225
+                width: now.frameWidth
1226
+            };
1227
+
1228
+            // Tries to get frame rate
1229
+            let frameRate = now.framesPerSecond;
1230
+
1231
+            if (!frameRate) {
1232
+                // we need to calculate it
1233
+                const before = this.previousStatsReport.get(now.id);
1234
+
1235
+                if (before) {
1236
+                    const timeMs = now.timestamp - before.timestamp;
1237
+
1238
+                    if (timeMs > 0 && now.framesSent) {
1239
+                        const numberOfFramesSinceBefore
1240
+                            = now.framesSent - before.framesSent;
1241
+
1242
+                        frameRate = (numberOfFramesSinceBefore / timeMs) * 1000;
1243
+                    }
1244
+                }
1245
+
1246
+                if (!frameRate) {
1247
+                    return;
1248
+                }
1249
+            }
1250
+
1251
+            const trackIdentifier = now.trackIdentifier;
1252
+            const ssrc = this.peerconnection.getSsrcByTrackId(trackIdentifier);
1253
+            let ssrcStats = this.ssrc2stats.get(ssrc);
1254
+
1255
+            if (!ssrcStats) {
1256
+                ssrcStats = new SsrcStats();
1257
+                this.ssrc2stats.set(ssrc, ssrcStats);
1258
+            }
1259
+            ssrcStats.setFramerate(Math.round(frameRate || 0));
1260
+
1261
+            if (resolution.height && resolution.width) {
1262
+                ssrcStats.setResolution(resolution);
1263
+            } else {
1264
+                ssrcStats.setResolution(null);
1265
+            }
1266
+        }
1267
+    });
1268
+
1269
+    this.eventEmitter.emit(
1270
+        StatisticsEvents.BYTE_SENT_STATS, this.peerconnection, byteSentStats);
1271
+
1272
+    this._processAndEmitReport();
1273
+};
1274
+
1275
+/**
1276
+ * Stats processing logic.
1277
+ */
1278
+StatsCollector.prototype.processNewAudioLevelReport = function() {
1279
+    if (!this.baselineAudioLevelsReport) {
1280
+        return;
1281
+    }
1282
+
1283
+    this.currentAudioLevelsReport.forEach(now => {
1284
+        if (now.type !== 'track') {
1285
+            return;
1286
+        }
1287
+
1288
+        // Audio level
1289
+        const audioLevel = now.audioLevel;
1290
+
1291
+        if (!audioLevel) {
1292
+            return;
1293
+        }
1294
+
1295
+        const trackIdentifier = now.trackIdentifier;
1296
+        const ssrc = this.peerconnection.getSsrcByTrackId(trackIdentifier);
1297
+
1298
+        if (ssrc) {
1299
+            const isLocal
1300
+                = ssrc === this.peerconnection.getLocalSSRC(
1301
+                this.peerconnection.getLocalTracks(MediaType.AUDIO));
1302
+
1303
+            this.eventEmitter.emit(
1304
+                StatisticsEvents.AUDIO_LEVEL,
1305
+                this.peerconnection,
1306
+                ssrc,
1307
+                audioLevel,
1308
+                isLocal);
1309
+        }
1310
+    });
1311
+};
1312
+
1313
+/**
1314
+ * End new promised based getStats processing methods.
1315
+ */

Loading…
Отказ
Запис