Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
1a09ea7
Add analyzer for the quality of peer connections
danxuliu Jun 22, 2020
5c45e23
Take round trip time into account when calculating the quality
danxuliu Jul 7, 2020
949f10a
Trigger events when the quality changes
danxuliu Jun 22, 2020
e2aa17d
Make possible to enable and disable the analysis of audio or video
danxuliu Jul 3, 2020
97e12ca
Guard against null screen peer
danxuliu Jul 2, 2020
a205ca4
Move peer and screenPeer to attributes in CallParticipantModel
danxuliu Jul 3, 2020
790c981
Add peer and screenPeer attributes to LocalCallParticipantModel
danxuliu Jul 3, 2020
ca4fdd1
Add analyzer for participants
danxuliu Jul 3, 2020
b5e724e
Add analyzer for calls
danxuliu Jul 3, 2020
58fc1f5
Show warning when the quality of the connection is bad
danxuliu Jul 3, 2020
d4ec4d9
Add a grace period before hiding the quality warning
danxuliu Jul 3, 2020
581d68a
Show tooltip only if the quality warning has not been recently shown
danxuliu Jul 3, 2020
6cb8de5
Take video and screen quality into account in the quality warning
danxuliu Jul 6, 2020
ffe3cf6
Move setting class attributes to its own method
danxuliu Jul 9, 2020
a6b897a
Increase grace period for quality tooltip
danxuliu Jul 9, 2020
087330b
Fix duplicated event listeners in ParticipantAnalyzer
danxuliu Jul 16, 2020
ad27de1
Dedicated connection warning icon
nickvergessen Jul 15, 2020
e12ca19
Add buttons to disable video and screen share to quality warning tooltip
Jul 17, 2020
1bff844
Add button to explicitly dismiss the quality warning tooltip
Jul 17, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Add analyzer for the quality of peer connections
Signed-off-by: Daniel Calviño Sánchez <[email protected]>
  • Loading branch information
danxuliu committed Jul 21, 2020
commit 1a09ea7fd05f6ba8747bd6b84d81333cec31c130
135 changes: 135 additions & 0 deletions src/utils/webrtc/analyzers/AverageStatValue.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/**
*
* @copyright Copyright (c) 2020, Daniel Calviño Sánchez ([email protected])
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

const STAT_VALUE_TYPE = {
CUMULATIVE: 0,
RELATIVE: 1,
}

/**
* Helper to calculate the average of the last N instances of an RTCStatsReport
* value.
*
* The average is a weighted average in which the latest elements have a higher
* weight. Specifically, the first item has a weight of 1, the last item has a
* weight of 3, and all the intermediate items have a weight that increases
* linearly from 1 to 3. The weights can be set when the AverageStatValue is
* created by specifying the weight of the last item.
*
* The number of items to keep track of must be set when the AverageStatValue is
* created. Once N items have been added adding a new one will discard the
* oldest value. "hasEnoughData()" can be used to check if at least N items have
* been added already and the average is reliable.
*
* An RTCStatsReport value can be cumulative since the creation of the
* RTCPeerConnection (like a sent packet count), or it can be an independent
* value at a certain point of time (like the round trip time). To be able to
* calculate the average the AverageStatValue converts cumulative values to
* relative ones. When the AverageStatValue is created it must be set whether
* the values that will be added are cumulative or not.
*
* The conversion from cumulative to relative is done automatically. Note,
* however, that the first value added to a cumulative AverageStatValue after
* creating or resetting it will be treated as 0 in the average calculation,
* as it will be the base from which the rest of relative values are calculated.
*
* Besides the weighted average it is possible to "peek" the last value, either
* the raw value that was added or the relative one after the conversion (which,
* for non cumulative values, will be the raw value too).
*
* @param {int} count the number of instances to take into account.
* @param {STAT_VALUE_TYPE} type whether the value is cumulative or relative.
* @param {int} lastValueWeight the value to calculate the weights of all the
* items, from the first (weight 1) to the last one.
*/
function AverageStatValue(count, type = STAT_VALUE_TYPE.CUMULATIVE, lastValueWeight = 3) {
this._count = count
this._type = type
this._extraWeightForEachElement = (lastValueWeight - 1) / (count - 1)

this._rawValues = []
this._relativeValues = []
}
AverageStatValue.prototype = {

reset: function() {
this._rawValues = []
this._relativeValues = []
},

add: function(value) {
if (this._rawValues.length === this._count) {
this._rawValues.shift()
this._relativeValues.shift()
}

let relativeValue = value
if (this._type === STAT_VALUE_TYPE.CUMULATIVE) {
// The first added value will be meaningless as it will be 0 and
// used as the base for the rest of values.
const lastRawValue = this._rawValues.length ? this._rawValues[this._rawValues.length - 1] : value
relativeValue = value - lastRawValue
}

this._rawValues.push(value)
this._relativeValues.push(relativeValue)
},

getLastRawValue: function() {
if (this._rawValues.length < 1) {
return NaN
}

return this._rawValues[this._rawValues.length - 1]
},

getLastRelativeValue: function() {
if (this._relativeValues.length < 1) {
return NaN
}

return this._relativeValues[this._relativeValues.length - 1]
},

hasEnoughData: function() {
return this._rawValues.length === this._count
},

getWeightedAverage: function() {
let weightedValues = 0
let weightsSum = 0

for (let i = 0; i < this._relativeValues.length; i++) {
const weight = 1 + (i * this._extraWeightForEachElement)

weightedValues += this._relativeValues[i] * weight
weightsSum += weight
}

return weightedValues / weightsSum
},

}

export {
STAT_VALUE_TYPE,
AverageStatValue,
}
Loading