|
@@ -1,11 +1,14 @@
|
1
|
1
|
/* global ssrc2jid */
|
2
|
2
|
/**
|
3
|
|
- * Calculates packet lost percent using the number of lost packets and the number of all packet.
|
|
3
|
+ * Calculates packet lost percent using the number of lost packets and the
|
|
4
|
+ * number of all packet.
|
4
|
5
|
* @param lostPackets the number of lost packets
|
5
|
6
|
* @param totalPackets the number of all packets.
|
6
|
7
|
* @returns {number} packet loss percent
|
7
|
8
|
*/
|
8
|
9
|
function calculatePacketLoss(lostPackets, totalPackets) {
|
|
10
|
+ if(!totalPackets || totalPackets <= 0 || !lostPackets || lostPackets <= 0)
|
|
11
|
+ return 0;
|
9
|
12
|
return Math.round((lostPackets/totalPackets)*100);
|
10
|
13
|
}
|
11
|
14
|
|
|
@@ -60,11 +63,11 @@ PeerStats.prototype.setSsrcLoss = function (ssrc, lossRate)
|
60
|
63
|
*/
|
61
|
64
|
PeerStats.prototype.setSsrcResolution = function (ssrc, resolution)
|
62
|
65
|
{
|
63
|
|
- if(resolution == null && this.ssrc2resolution[ssrc])
|
|
66
|
+ if(resolution === null && this.ssrc2resolution[ssrc])
|
64
|
67
|
{
|
65
|
68
|
delete this.ssrc2resolution[ssrc];
|
66
|
69
|
}
|
67
|
|
- else if(resolution != null)
|
|
70
|
+ else if(resolution !== null)
|
68
|
71
|
this.ssrc2resolution[ssrc] = resolution;
|
69
|
72
|
};
|
70
|
73
|
|
|
@@ -103,16 +106,18 @@ PeerStats.transport = [];
|
103
|
106
|
* <tt>StatsCollector</tt> registers for stats updates of given
|
104
|
107
|
* <tt>peerconnection</tt> in given <tt>interval</tt>. On each update particular
|
105
|
108
|
* stats are extracted and put in {@link PeerStats} objects. Once the processing
|
106
|
|
- * is done <tt>audioLevelsUpdateCallback</tt> is called with <tt>this</tt> instance as
|
107
|
|
- * an event source.
|
|
109
|
+ * is done <tt>audioLevelsUpdateCallback</tt> is called with <tt>this</tt>
|
|
110
|
+ * instance as an event source.
|
108
|
111
|
*
|
109
|
112
|
* @param peerconnection webRTC peer connection object.
|
110
|
113
|
* @param interval stats refresh interval given in ms.
|
111
|
|
- * @param {function(StatsCollector)} audioLevelsUpdateCallback the callback called on stats
|
112
|
|
- * update.
|
|
114
|
+ * @param {function(StatsCollector)} audioLevelsUpdateCallback the callback
|
|
115
|
+ * called on stats update.
|
113
|
116
|
* @constructor
|
114
|
117
|
*/
|
115
|
|
-function StatsCollector(peerconnection, audioLevelsInterval, audioLevelsUpdateCallback, statsInterval, statsUpdateCallback)
|
|
118
|
+function StatsCollector(peerconnection, audioLevelsInterval,
|
|
119
|
+ audioLevelsUpdateCallback, statsInterval,
|
|
120
|
+ statsUpdateCallback)
|
116
|
121
|
{
|
117
|
122
|
this.peerconnection = peerconnection;
|
118
|
123
|
this.baselineAudioLevelsReport = null;
|
|
@@ -173,7 +178,8 @@ StatsCollector.prototype.start = function ()
|
173
|
178
|
//console.error("Got interval report", results);
|
174
|
179
|
self.currentAudioLevelsReport = results;
|
175
|
180
|
self.processAudioLevelReport();
|
176
|
|
- self.baselineAudioLevelsReport = self.currentAudioLevelsReport;
|
|
181
|
+ self.baselineAudioLevelsReport =
|
|
182
|
+ self.currentAudioLevelsReport;
|
177
|
183
|
},
|
178
|
184
|
self.errorCallback
|
179
|
185
|
);
|
|
@@ -211,10 +217,14 @@ StatsCollector.prototype.processStatsReport = function () {
|
211
|
217
|
|
212
|
218
|
for (var idx in this.currentStatsReport) {
|
213
|
219
|
var now = this.currentStatsReport[idx];
|
214
|
|
- if (now.stat('googAvailableReceiveBandwidth') || now.stat('googAvailableSendBandwidth')) {
|
|
220
|
+ if (now.stat('googAvailableReceiveBandwidth') ||
|
|
221
|
+ now.stat('googAvailableSendBandwidth'))
|
|
222
|
+ {
|
215
|
223
|
PeerStats.bandwidth = {
|
216
|
|
- "download": Math.round((now.stat('googAvailableReceiveBandwidth')) / 1000),
|
217
|
|
- "upload": Math.round((now.stat('googAvailableSendBandwidth')) / 1000)
|
|
224
|
+ "download": Math.round(
|
|
225
|
+ (now.stat('googAvailableReceiveBandwidth')) / 1000),
|
|
226
|
+ "upload": Math.round(
|
|
227
|
+ (now.stat('googAvailableSendBandwidth')) / 1000)
|
218
|
228
|
};
|
219
|
229
|
}
|
220
|
230
|
|
|
@@ -229,7 +239,8 @@ StatsCollector.prototype.processStatsReport = function () {
|
229
|
239
|
var addressSaved = false;
|
230
|
240
|
for(var i = 0; i < PeerStats.transport.length; i++)
|
231
|
241
|
{
|
232
|
|
- if(PeerStats.transport[i].ip == ip && PeerStats.transport[i].type == type &&
|
|
242
|
+ if(PeerStats.transport[i].ip == ip &&
|
|
243
|
+ PeerStats.transport[i].type == type &&
|
233
|
244
|
PeerStats.transport[i].localip == localIP)
|
234
|
245
|
{
|
235
|
246
|
addressSaved = true;
|
|
@@ -241,7 +252,6 @@ StatsCollector.prototype.processStatsReport = function () {
|
241
|
252
|
continue;
|
242
|
253
|
}
|
243
|
254
|
|
244
|
|
-// console.log("bandwidth: " + now.stat('googAvailableReceiveBandwidth') + " - " + now.stat('googAvailableSendBandwidth'));
|
245
|
255
|
if (now.type != 'ssrc') {
|
246
|
256
|
continue;
|
247
|
257
|
}
|
|
@@ -287,7 +297,8 @@ StatsCollector.prototype.processStatsReport = function () {
|
287
|
297
|
if(!packetsBefore || packetsBefore < 0)
|
288
|
298
|
packetsBefore = 0;
|
289
|
299
|
var packetRate = packetsNow - packetsBefore;
|
290
|
|
-
|
|
300
|
+ if(!packetRate || packetRate < 0)
|
|
301
|
+ packetRate = 0;
|
291
|
302
|
var currentLoss = now.stat('packetsLost');
|
292
|
303
|
if(!currentLoss || currentLoss < 0)
|
293
|
304
|
currentLoss = 0;
|
|
@@ -295,17 +306,20 @@ StatsCollector.prototype.processStatsReport = function () {
|
295
|
306
|
if(!previousLoss || previousLoss < 0)
|
296
|
307
|
previousLoss = 0;
|
297
|
308
|
var lossRate = currentLoss - previousLoss;
|
298
|
|
- if(lossRate < 0)
|
|
309
|
+ if(!lossRate || lossRate < 0)
|
299
|
310
|
lossRate = 0;
|
300
|
311
|
var packetsTotal = (packetRate + lossRate);
|
301
|
312
|
|
302
|
|
- jidStats.setSsrcLoss(ssrc, {"packetsTotal": packetsTotal, "packetsLost": lossRate,
|
303
|
|
- "isDownloadStream": isDownloadStream});
|
|
313
|
+ jidStats.setSsrcLoss(ssrc,
|
|
314
|
+ {"packetsTotal": packetsTotal,
|
|
315
|
+ "packetsLost": lossRate,
|
|
316
|
+ "isDownloadStream": isDownloadStream});
|
304
|
317
|
|
305
|
318
|
var bytesReceived = 0, bytesSent = 0;
|
306
|
319
|
if(now.stat("bytesReceived"))
|
307
|
320
|
{
|
308
|
|
- bytesReceived = now.stat("bytesReceived") - before.stat("bytesReceived");
|
|
321
|
+ bytesReceived = now.stat("bytesReceived") -
|
|
322
|
+ before.stat("bytesReceived");
|
309
|
323
|
}
|
310
|
324
|
|
311
|
325
|
if(now.stat("bytesSent"))
|
|
@@ -313,22 +327,37 @@ StatsCollector.prototype.processStatsReport = function () {
|
313
|
327
|
bytesSent = now.stat("bytesSent") - before.stat("bytesSent");
|
314
|
328
|
}
|
315
|
329
|
|
316
|
|
- if(bytesReceived < 0)
|
|
330
|
+ var time = Math.round((now.timestamp - before.timestamp) / 1000);
|
|
331
|
+ if(bytesReceived <= 0 || time <= 0)
|
|
332
|
+ {
|
317
|
333
|
bytesReceived = 0;
|
318
|
|
- if(bytesSent < 0)
|
|
334
|
+ }
|
|
335
|
+ else
|
|
336
|
+ {
|
|
337
|
+ bytesReceived = Math.round(((bytesReceived * 8) / time) / 1000);
|
|
338
|
+ }
|
|
339
|
+
|
|
340
|
+ if(bytesSent <= 0 || time <= 0)
|
|
341
|
+ {
|
319
|
342
|
bytesSent = 0;
|
|
343
|
+ }
|
|
344
|
+ else
|
|
345
|
+ {
|
|
346
|
+ bytesSent = Math.round(((bytesSent * 8) / time) / 1000);
|
|
347
|
+ }
|
320
|
348
|
|
321
|
|
- var time = Math.round((now.timestamp - before.timestamp) / 1000);
|
322
|
349
|
jidStats.setSsrcBitrate(ssrc, {
|
323
|
|
- "download": Math.round(((bytesReceived * 8) / time) / 1000),
|
324
|
|
- "upload": Math.round(((bytesSent * 8) / time) / 1000)});
|
|
350
|
+ "download": bytesReceived,
|
|
351
|
+ "upload": bytesSent});
|
325
|
352
|
var resolution = {height: null, width: null};
|
326
|
|
- if(now.stat("googFrameHeightReceived") && now.stat("googFrameWidthReceived"))
|
|
353
|
+ if(now.stat("googFrameHeightReceived") &&
|
|
354
|
+ now.stat("googFrameWidthReceived"))
|
327
|
355
|
{
|
328
|
356
|
resolution.height = now.stat("googFrameHeightReceived");
|
329
|
357
|
resolution.width = now.stat("googFrameWidthReceived");
|
330
|
358
|
}
|
331
|
|
- else if(now.stat("googFrameHeightSent") && now.stat("googFrameWidthSent"))
|
|
359
|
+ else if(now.stat("googFrameHeightSent") &&
|
|
360
|
+ now.stat("googFrameWidthSent"))
|
332
|
361
|
{
|
333
|
362
|
resolution.height = now.stat("googFrameHeightSent");
|
334
|
363
|
resolution.width = now.stat("googFrameWidthSent");
|
|
@@ -352,7 +381,7 @@ StatsCollector.prototype.processStatsReport = function () {
|
352
|
381
|
var lostPackets = {download: 0, upload: 0};
|
353
|
382
|
var bitrateDownload = 0;
|
354
|
383
|
var bitrateUpload = 0;
|
355
|
|
- var resolution = {};
|
|
384
|
+ var resolutions = {};
|
356
|
385
|
Object.keys(this.jid2stats).forEach(
|
357
|
386
|
function (jid)
|
358
|
387
|
{
|
|
@@ -362,17 +391,21 @@ StatsCollector.prototype.processStatsReport = function () {
|
362
|
391
|
var type = "upload";
|
363
|
392
|
if(self.jid2stats[jid].ssrc2Loss[ssrc].isDownloadStream)
|
364
|
393
|
type = "download";
|
365
|
|
- totalPackets[type] += self.jid2stats[jid].ssrc2Loss[ssrc].packetsTotal;
|
366
|
|
- lostPackets[type] += self.jid2stats[jid].ssrc2Loss[ssrc].packetsLost;
|
|
394
|
+ totalPackets[type] +=
|
|
395
|
+ self.jid2stats[jid].ssrc2Loss[ssrc].packetsTotal;
|
|
396
|
+ lostPackets[type] +=
|
|
397
|
+ self.jid2stats[jid].ssrc2Loss[ssrc].packetsLost;
|
367
|
398
|
}
|
368
|
399
|
);
|
369
|
400
|
Object.keys(self.jid2stats[jid].ssrc2bitrate).forEach(
|
370
|
401
|
function (ssrc) {
|
371
|
|
- bitrateDownload += self.jid2stats[jid].ssrc2bitrate[ssrc].download;
|
372
|
|
- bitrateUpload += self.jid2stats[jid].ssrc2bitrate[ssrc].upload;
|
|
402
|
+ bitrateDownload +=
|
|
403
|
+ self.jid2stats[jid].ssrc2bitrate[ssrc].download;
|
|
404
|
+ bitrateUpload +=
|
|
405
|
+ self.jid2stats[jid].ssrc2bitrate[ssrc].upload;
|
373
|
406
|
}
|
374
|
407
|
);
|
375
|
|
- resolution[jid] = self.jid2stats[jid].ssrc2resolution;
|
|
408
|
+ resolutions[jid] = self.jid2stats[jid].ssrc2resolution;
|
376
|
409
|
}
|
377
|
410
|
);
|
378
|
411
|
|
|
@@ -392,12 +425,12 @@ StatsCollector.prototype.processStatsReport = function () {
|
392
|
425
|
"bitrate": PeerStats.bitrate,
|
393
|
426
|
"packetLoss": PeerStats.packetLoss,
|
394
|
427
|
"bandwidth": PeerStats.bandwidth,
|
395
|
|
- "resolution": resolution,
|
|
428
|
+ "resolution": resolutions,
|
396
|
429
|
"transport": PeerStats.transport
|
397
|
430
|
});
|
398
|
431
|
PeerStats.transport = [];
|
399
|
432
|
|
400
|
|
-}
|
|
433
|
+};
|
401
|
434
|
|
402
|
435
|
/**
|
403
|
436
|
* Stats processing logic.
|