Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
19 changes: 19 additions & 0 deletions src/utils/webrtc/analyzers/AverageStatValue.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ const STAT_VALUE_TYPE = {
* the raw value that was added or the relative one after the conversion (which,
* for non cumulative values, will be the raw value too).
*
* A string representation of the current relative values can be got by calling
* "toString()".
*
* @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
Expand Down Expand Up @@ -127,6 +130,22 @@ AverageStatValue.prototype = {
return weightedValues / weightsSum
},

toString() {
if (!this._relativeValues.length) {
return '[]'
}

let relativeValuesAsString = '[' + this._relativeValues[0]

for (let i = 1; i < this._relativeValues.length; i++) {
relativeValuesAsString += ', ' + this._relativeValues[i]
}

relativeValuesAsString += ']'

return relativeValuesAsString
},

}

export {
Expand Down
37 changes: 37 additions & 0 deletions src/utils/webrtc/analyzers/AverageStatValue.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,43 @@ describe('AverageStatValue', () => {
})
})

describe('to string', () => {
test('no values', () => {
const stat = new AverageStatValue(3, STAT_VALUE_TYPE.CUMULATIVE, 3)
const stat2 = new AverageStatValue(3, STAT_VALUE_TYPE.RELATIVE, 3)

expect(stat.toString()).toBe('[]')
expect(stat2.toString()).toBe('[]')
})

test('single value', () => {
const stat = new AverageStatValue(3, STAT_VALUE_TYPE.CUMULATIVE, 3)
const stat2 = new AverageStatValue(3, STAT_VALUE_TYPE.RELATIVE, 3)

stat.add(42)
stat2.add(42)

// The first cumulative value is treated as 0 as it is the base from
// which the rest of the values will be calculated.
expect(stat.toString()).toBe('[0]')
expect(stat2.toString()).toBe('[42]')
})

test('several values', () => {
const testValues = [100, 200, 150, 123, 30, 50, 22, 33]
const stat = new AverageStatValue(3, STAT_VALUE_TYPE.CUMULATIVE, 3)
const stat2 = new AverageStatValue(3, STAT_VALUE_TYPE.RELATIVE, 3)

testValues.forEach((val, index) => {
stat.add(val)
stat2.add(val)
})

expect(stat.toString()).toBe('[20, -28, 11]')
expect(stat2.toString()).toBe('[50, 22, 33]')
})
})

describe('cumulative average', () => {
test('returns the last relative value', () => {
const testValues = [
Expand Down
36 changes: 33 additions & 3 deletions src/utils/webrtc/analyzers/PeerConnectionAnalyzer.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ function PeerConnectionAnalyzer() {
audio: new AverageStatValue(2, STAT_VALUE_TYPE.CUMULATIVE),
video: new AverageStatValue(2, STAT_VALUE_TYPE.CUMULATIVE),
}
this._timestampsForLogs = {
audio: new AverageStatValue(5, STAT_VALUE_TYPE.CUMULATIVE),
video: new AverageStatValue(5, STAT_VALUE_TYPE.CUMULATIVE),
}

this._analysisEnabled = {
audio: true,
Expand Down Expand Up @@ -224,6 +228,7 @@ PeerConnectionAnalyzer.prototype = {
this._packetsLostRatio[kind].reset()
this._packetsPerSecond[kind].reset()
this._timestamps[kind].reset()
this._timestampsForLogs[kind].reset()
},

_handleIceConnectionStateChanged() {
Expand Down Expand Up @@ -405,6 +410,7 @@ PeerConnectionAnalyzer.prototype = {
}
if (timestamp[kind] >= 0) {
this._timestamps[kind].add(timestamp[kind])
this._timestampsForLogs[kind].add(timestamp[kind])
}
if (packets[kind] >= 0 && timestamp[kind] >= 0) {
const elapsedSeconds = this._timestamps[kind].getLastRelativeValue() / 1000
Expand Down Expand Up @@ -495,6 +501,7 @@ PeerConnectionAnalyzer.prototype = {
}
if (timestamp[kind] >= 0) {
this._timestamps[kind].add(timestamp[kind])
this._timestampsForLogs[kind].add(timestamp[kind])
}
if (packets[kind] >= 0 && timestamp[kind] >= 0) {
const elapsedSeconds = this._timestamps[kind].getLastRelativeValue() / 1000
Expand All @@ -507,20 +514,22 @@ PeerConnectionAnalyzer.prototype = {
},

_calculateConnectionQualityAudio() {
return this._calculateConnectionQuality(this._packetsLostRatio.audio, this._packetsPerSecond.audio, this._roundTripTime.audio)
return this._calculateConnectionQuality(this._packetsLostRatio.audio, this._packetsPerSecond.audio, this._roundTripTime.audio, 'audio')
},

_calculateConnectionQualityVideo() {
return this._calculateConnectionQuality(this._packetsLostRatio.video, this._packetsPerSecond.video, this._roundTripTime.video)
return this._calculateConnectionQuality(this._packetsLostRatio.video, this._packetsPerSecond.video, this._roundTripTime.video, 'video')
},

_calculateConnectionQuality(packetsLostRatio, packetsPerSecond, roundTripTime) {
_calculateConnectionQuality(packetsLostRatio, packetsPerSecond, roundTripTime, kind) {
if (!packetsLostRatio.hasEnoughData() || !packetsPerSecond.hasEnoughData()) {
return CONNECTION_QUALITY.UNKNOWN
}

const packetsLostRatioWeightedAverage = packetsLostRatio.getWeightedAverage()
if (packetsLostRatioWeightedAverage >= 1) {
this._logStats(kind, 'No transmitted data, packet lost ratio: ' + packetsLostRatioWeightedAverage)

return CONNECTION_QUALITY.NO_TRANSMITTED_DATA
}

Expand All @@ -529,6 +538,8 @@ PeerConnectionAnalyzer.prototype = {
// discarded to try to keep the playing rate in real time.
// Round trip time is measured in seconds.
if (roundTripTime.hasEnoughData() && roundTripTime.getWeightedAverage() > 1.5) {
this._logStats(kind, 'High round trip time: ' + roundTripTime.getWeightedAverage())

return CONNECTION_QUALITY.VERY_BAD
}

Expand All @@ -544,10 +555,14 @@ PeerConnectionAnalyzer.prototype = {
// with a threshold of 10 packets issues can be detected too for videos,
// although only once they can not be further downscaled.
if (packetsPerSecond.getWeightedAverage() < 10) {
this._logStats(kind, 'Low packets per second: ' + packetsPerSecond.getWeightedAverage())

return CONNECTION_QUALITY.VERY_BAD
}

if (packetsLostRatioWeightedAverage > 0.3) {
this._logStats(kind, 'High packet lost ratio: ' + packetsLostRatioWeightedAverage)

return CONNECTION_QUALITY.VERY_BAD
}

Expand All @@ -562,6 +577,21 @@ PeerConnectionAnalyzer.prototype = {
return CONNECTION_QUALITY.GOOD
},

_logStats(kind, message) {
const tag = 'PeerConnectionAnalyzer: ' + kind + ': '

if (message) {
console.debug(tag + message)
}

console.debug(tag + 'Packets: ' + this._packets[kind].toString())
console.debug(tag + 'Packets lost: ' + this._packetsLost[kind].toString())
console.debug(tag + 'Packets lost ratio: ' + this._packetsLostRatio[kind].toString())
console.debug(tag + 'Packets per second: ' + this._packetsPerSecond[kind].toString())
console.debug(tag + 'Round trip time: ' + this._roundTripTime[kind].toString())
console.debug(tag + 'Timestamps: ' + this._timestampsForLogs[kind].toString())
},

}

export {
Expand Down