in src/js/rtc_session.js [905:992]
async getStats() {
var timestamp = new Date();
var impl = async (stream, streamType) => {
var tracks = [];
if (!stream) {
return [];
}
switch (streamType) {
case 'audio_input':
case 'audio_output':
tracks = stream.getAudioTracks();
break;
case 'video_input':
case 'video_output':
tracks = stream.getVideoTracks();
break;
default:
throw new Error('Unsupported stream type while trying to get stats: ' + streamType);
}
return await Promise.all(tracks.map(async(track) => {
// get legacy stats report as a promise
if (this._legacyStatsReportSupport) {
var self = this;
return new Promise(function(resolve) {
self._pc.getStats(function(rawStats) {
var digestedStats = extractMediaStatsFromStats(timestamp, rawStats.result(), streamType);
if (!digestedStats) {
throw new Error('Failed to extract MediaRtpStats from RTCStatsReport for stream type ' + streamType);
}
resolve(digestedStats);
}, track);
});
} else { // get standardized report
return this._pc.getStats().then(function(rawStats) {
var digestedStats = extractMediaStatsFromStats(timestamp, rawStats, streamType);
if (!digestedStats) {
throw new Error('Failed to extract MediaRtpStats from RTCStatsReport for stream type ' + streamType);
}
return digestedStats;
});
}
}));
};
if (this._pc && this._pc.signalingState === 'stable') {
var statsResult = {
audio: {
input: await impl(this._remoteAudioStream, 'audio_input'),
output: await impl(this._localStream, 'audio_output')
},
video: {
input: await impl(this._remoteVideoStream, 'video_input'),
output: await impl(this._localStream, 'video_output')
}
};
// For consistency's sake, coalesce rttMilliseconds into the output for audio and video.
var rttReducer = (acc, stats) => {
if (stats.rttMilliseconds !== null && (acc === null || stats.rttMilliseconds > acc)) {
acc = stats.rttMilliseconds;
}
stats._rttMilliseconds = null;
return acc;
};
var audioInputRttMilliseconds = statsResult.audio.input.reduce(rttReducer, null);
var videoInputRttMilliseconds = statsResult.video.input.reduce(rttReducer, null);
if (audioInputRttMilliseconds !== null) {
statsResult.audio.output.forEach((stats) => { stats._rttMilliseconds = audioInputRttMilliseconds; });
}
if (videoInputRttMilliseconds !== null) {
statsResult.video.output.forEach((stats) => { stats._rttMilliseconds = videoInputRttMilliseconds; });
}
return statsResult;
} else {
return Promise.reject(new IllegalState());
}
}