@@ -396,6 +396,19 @@ PeerConnectionAnalyzer.prototype = {
396
396
packetsLost [ kind ] = this . _packetsLost [ kind ] . getLastRawValue ( )
397
397
}
398
398
399
+ // In some (also strange) cases a newer stat may report a lower
400
+ // value than a previous one (it happens sometimes with garbage
401
+ // remote reports in simulcast video that cause the values to
402
+ // overflow, although it was also seen with a small value regression
403
+ // when enabling video). If that happens the stats are reset to
404
+ // prevent distorting the analysis with negative packet counts; note
405
+ // that in this case the previous value is not kept because it is
406
+ // not just an isolated wrong value, all the following stats
407
+ // increase from the regressed value.
408
+ if ( packets [ kind ] >= 0 && packets [ kind ] < this . _packets [ kind ] . getLastRawValue ( ) ) {
409
+ this . _resetStats ( kind )
410
+ }
411
+
399
412
this . _addStats ( kind , packets [ kind ] , packetsLost [ kind ] , timestamp [ kind ] , roundTripTime [ kind ] )
400
413
}
401
414
} ,
@@ -466,12 +479,13 @@ PeerConnectionAnalyzer.prototype = {
466
479
* The stats reported by the browser can sometimes stall for a second (or
467
480
* more, but typically they stall only for a single report). When that
468
481
* happens the stats are still reported, but with the same number of packets
469
- * as in the previous report (timestamp and round trip time are updated,
470
- * though). In that case the given stats are not added yet to the average
471
- * stats; they are kept on hold until more stats are provided by the browser
472
- * and it can be determined if the previous stats were stalled or not. If
473
- * they were stalled the previous and new stats are distributed, and if they
474
- * were not they are added as is to the average stats.
482
+ * as in the previous report (timestamp and round trip time may be updated
483
+ * or not, apparently depending on browser version and/or Janus version). In
484
+ * that case the given stats are not added yet to the average stats; they
485
+ * are kept on hold until more stats are provided by the browser and it can
486
+ * be determined if the previous stats were stalled or not. If they were
487
+ * stalled the previous and new stats are distributed, and if they were not
488
+ * they are added as is to the average stats.
475
489
*
476
490
* @param {string } kind the type of the stats ("audio" or "video")
477
491
* @param {number } packets the cumulative number of packets
@@ -536,6 +550,18 @@ PeerConnectionAnalyzer.prototype = {
536
550
let packetsLostTotal = 0
537
551
let timestampsTotal = 0
538
552
553
+ // If the first timestamp stalled it is assumed that all of them
554
+ // stalled and are thus evenly distributed based on the new timestamp.
555
+ if ( this . _stagedTimestamps [ kind ] [ 0 ] === timestampsBase ) {
556
+ const lastTimestamp = this . _stagedTimestamps [ kind ] [ this . _stagedTimestamps [ kind ] . length - 1 ]
557
+ const timestampsTotalDifference = lastTimestamp - timestampsBase
558
+ const timestampsDelta = timestampsTotalDifference / this . _stagedTimestamps [ kind ] . length
559
+
560
+ for ( let i = 0 ; i < this . _stagedTimestamps [ kind ] . length - 1 ; i ++ ) {
561
+ this . _stagedTimestamps [ kind ] [ i ] += timestampsDelta * ( i + 1 )
562
+ }
563
+ }
564
+
539
565
for ( let i = 0 ; i < this . _stagedPackets [ kind ] . length ; i ++ ) {
540
566
packetsTotal += ( this . _stagedPackets [ kind ] [ i ] - packetsBase )
541
567
packetsBase = this . _stagedPackets [ kind ] [ i ]
@@ -562,7 +588,11 @@ PeerConnectionAnalyzer.prototype = {
562
588
packetsLostBase = this . _stagedPacketsLost [ kind ] [ i ]
563
589
564
590
// Timestamps and round trip time are not distributed, as those
565
- // values are properly updated even if the stats are stalled.
591
+ // values may be properly updated even if the stats are stalled. In
592
+ // case they were not timestamps were already evenly distributed
593
+ // above, and round trip time can not be distributed, as it is
594
+ // already provided in the stats as a relative value rather than a
595
+ // cumulative one.
566
596
}
567
597
} ,
568
598
@@ -612,11 +642,19 @@ PeerConnectionAnalyzer.prototype = {
612
642
} ,
613
643
614
644
_calculateConnectionQuality ( kind ) {
645
+ const packets = this . _packets [ kind ]
646
+ const packetsLost = this . _packetsLost [ kind ]
647
+ const timestamps = this . _timestamps [ kind ]
615
648
const packetsLostRatio = this . _packetsLostRatio [ kind ]
616
649
const packetsPerSecond = this . _packetsPerSecond [ kind ]
617
650
const roundTripTime = this . _roundTripTime [ kind ]
618
651
619
- if ( ! packetsLostRatio . hasEnoughData ( ) || ! packetsPerSecond . hasEnoughData ( ) ) {
652
+ // packetsLostRatio and packetsPerSecond are relative values, but they
653
+ // are calculated from cumulative values. Therefore, it is necessary to
654
+ // check if the cumulative values that are their source have enough data
655
+ // or not, rather than checking if the relative values themselves have
656
+ // enough data.
657
+ if ( ! packets . hasEnoughData ( ) || ! packetsLost . hasEnoughData ( ) || ! timestamps . hasEnoughData ( ) ) {
620
658
return CONNECTION_QUALITY . UNKNOWN
621
659
}
622
660
@@ -655,10 +693,13 @@ PeerConnectionAnalyzer.prototype = {
655
693
// quality to keep a smooth video, albeit on a lower resolution. Thus
656
694
// with a threshold of 10 packets issues can be detected too for videos,
657
695
// although only once they can not be further downscaled.
696
+ // Despite all of the above it has been observed that less than 10
697
+ // packets are sometimes sent without any connection problem (for
698
+ // example, when the background is blurred and the video quality is
699
+ // reduced due to being in a call with several participants), so for now
700
+ // it is only logged but not reported.
658
701
if ( packetsPerSecond . getWeightedAverage ( ) < 10 ) {
659
702
this . _logStats ( kind , 'Low packets per second: ' + packetsPerSecond . getWeightedAverage ( ) )
660
-
661
- return CONNECTION_QUALITY . VERY_BAD
662
703
}
663
704
664
705
if ( packetsLostRatioWeightedAverage > 0.3 ) {
0 commit comments