Implements firefox support for the rtp stats

This commit is contained in:
hristoterezov 2014-11-28 19:47:19 +02:00
parent 9b5edde621
commit 501c97b27c
2 changed files with 159 additions and 61 deletions

View File

@ -102,6 +102,7 @@ PeerStats.prototype.setSsrcAudioLevel = function (ssrc, audioLevel)
*/
PeerStats.transport = [];
/**
* <tt>StatsCollector</tt> registers for stats updates of given
* <tt>peerconnection</tt> in given <tt>interval</tt>. On each update particular
@ -174,9 +175,15 @@ StatsCollector.prototype.start = function ()
self.peerconnection.getStats(
function (report)
{
var results = null;
if(!report || !report.result || typeof report.result != 'function')
return;
var results = report.result();
{
results = report;
}
else
{
results = report.result();
}
//console.error("Got interval report", results);
self.currentAudioLevelsReport = results;
self.processAudioLevelReport();
@ -195,12 +202,28 @@ StatsCollector.prototype.start = function ()
self.peerconnection.getStats(
function (report)
{
var results = null;
if(!report || !report.result || typeof report.result != 'function')
return;
var results = report.result();
{
//firefox
results = report;
}
else
{
//chrome
results = report.result();
}
//console.error("Got interval report", results);
self.currentStatsReport = results;
self.processStatsReport();
try
{
self.processStatsReport();
}
catch(e)
{
console.error("Unsupported key:" + e);
}
self.baselineStatsReport = self.currentStatsReport;
},
self.errorCallback
@ -210,6 +233,36 @@ StatsCollector.prototype.start = function ()
);
};
var keyMap = {
"firefox": {
"ssrc": "ssrc",
"packetsReceived": "packetsReceived",
"packetsLost": "packetsLost",
"packetsSent": "packetsSent",
"bytesReceived": "bytesReceived",
"bytesSent": "bytesSent"
},
"chrome": {
"receiveBandwidth": "googAvailableReceiveBandwidth",
"sendBandwidth": "googAvailableSendBandwidth",
"remoteAddress": "googRemoteAddress",
"transportType": "googTransportType",
"localAddress": "googLocalAddress",
"activeConnection": "googActiveConnection",
"ssrc": "ssrc",
"packetsReceived": "packetsReceived",
"packetsSent": "packetsSent",
"packetsLost": "packetsLost",
"bytesReceived": "bytesReceived",
"bytesSent": "bytesSent",
"googFrameHeightReceived": "googFrameHeightReceived",
"googFrameWidthReceived": "googFrameWidthReceived",
"googFrameHeightSent": "googFrameHeightSent",
"googFrameWidthSent": "googFrameWidthSent",
"audioInputLevel": "audioInputLevel",
"audioOutputLevel": "audioOutputLevel"
}
};
/**
* Stats processing logic.
@ -221,23 +274,29 @@ StatsCollector.prototype.processStatsReport = function () {
for (var idx in this.currentStatsReport) {
var now = this.currentStatsReport[idx];
if (now.stat('googAvailableReceiveBandwidth') ||
now.stat('googAvailableSendBandwidth'))
{
PeerStats.bandwidth = {
"download": Math.round(
(now.stat('googAvailableReceiveBandwidth')) / 1000),
"upload": Math.round(
(now.stat('googAvailableSendBandwidth')) / 1000)
};
try {
if (getStatValue(now, 'receiveBandwidth') ||
getStatValue(now, 'sendBandwidth')) {
PeerStats.bandwidth = {
"download": Math.round(
(getStatValue(now, 'receiveBandwidth')) / 1000),
"upload": Math.round(
(getStatValue(now, 'sendBandwidth')) / 1000)
};
}
}
catch(e){/*not supported*/}
if(now.type == 'googCandidatePair')
{
var ip = now.stat('googRemoteAddress');
var type = now.stat("googTransportType");
var localIP = now.stat("googLocalAddress");
var active = now.stat("googActiveConnection");
var ip, type, localIP, active;
try {
ip = getStatValue(now, 'remoteAddress');
type = getStatValue(now, "transportType");
localIP = getStatValue(now, "localAddress");
active = getStatValue(now, "activeConnection");
}
catch(e){/*not supported*/}
if(!ip || !type || !localIP || active != "true")
continue;
var addressSaved = false;
@ -256,17 +315,32 @@ StatsCollector.prototype.processStatsReport = function () {
continue;
}
if (now.type != 'ssrc') {
if(now.type == "candidatepair")
{
if(now.state == "succeeded")
continue;
var local = this.currentStatsReport[now.localCandidateId];
var remote = this.currentStatsReport[now.remoteCandidateId];
PeerStats.transport.push({localip: local.ipAddress + ":" + local.portNumber,
ip: remote.ipAddress + ":" + remote.portNumber, type: local.transport});
}
if (now.type != 'ssrc' && now.type != "outboundrtp" &&
now.type != "inboundrtp") {
continue;
}
var before = this.baselineStatsReport[idx];
if (!before) {
console.warn(now.stat('ssrc') + ' not enough data');
console.warn(getStatValue(now, 'ssrc') + ' not enough data');
continue;
}
var ssrc = now.stat('ssrc');
var ssrc = getStatValue(now, 'ssrc');
if(!ssrc)
continue;
var jid = ssrc2jid[ssrc];
if (!jid) {
console.warn("No jid for ssrc: " + ssrc);
@ -282,31 +356,30 @@ StatsCollector.prototype.processStatsReport = function () {
var isDownloadStream = true;
var key = 'packetsReceived';
if (!now.stat(key))
if (!getStatValue(now, key))
{
isDownloadStream = false;
key = 'packetsSent';
if (!now.stat(key))
if (!getStatValue(now, key))
{
console.error("No packetsReceived nor packetSent stat found");
this.stop();
return;
console.warn("No packetsReceived nor packetSent stat found");
continue;
}
}
var packetsNow = now.stat(key);
var packetsNow = getStatValue(now, key);
if(!packetsNow || packetsNow < 0)
packetsNow = 0;
var packetsBefore = before.stat(key);
var packetsBefore = getStatValue(before, key);
if(!packetsBefore || packetsBefore < 0)
packetsBefore = 0;
var packetRate = packetsNow - packetsBefore;
if(!packetRate || packetRate < 0)
packetRate = 0;
var currentLoss = now.stat('packetsLost');
var currentLoss = getStatValue(now, 'packetsLost');
if(!currentLoss || currentLoss < 0)
currentLoss = 0;
var previousLoss = before.stat('packetsLost');
var previousLoss = getStatValue(before, 'packetsLost');
if(!previousLoss || previousLoss < 0)
previousLoss = 0;
var lossRate = currentLoss - previousLoss;
@ -320,15 +393,15 @@ StatsCollector.prototype.processStatsReport = function () {
"isDownloadStream": isDownloadStream});
var bytesReceived = 0, bytesSent = 0;
if(now.stat("bytesReceived"))
if(getStatValue(now, "bytesReceived"))
{
bytesReceived = now.stat("bytesReceived") -
before.stat("bytesReceived");
bytesReceived = getStatValue(now, "bytesReceived") -
getStatValue(before, "bytesReceived");
}
if(now.stat("bytesSent"))
if(getStatValue(now, "bytesSent"))
{
bytesSent = now.stat("bytesSent") - before.stat("bytesSent");
bytesSent = getStatValue(now, "bytesSent") - getStatValue(before, "bytesSent");
}
var time = Math.round((now.timestamp - before.timestamp) / 1000);
@ -354,18 +427,19 @@ StatsCollector.prototype.processStatsReport = function () {
"download": bytesReceived,
"upload": bytesSent});
var resolution = {height: null, width: null};
if(now.stat("googFrameHeightReceived") &&
now.stat("googFrameWidthReceived"))
{
resolution.height = now.stat("googFrameHeightReceived");
resolution.width = now.stat("googFrameWidthReceived");
}
else if(now.stat("googFrameHeightSent") &&
now.stat("googFrameWidthSent"))
{
resolution.height = now.stat("googFrameHeightSent");
resolution.width = now.stat("googFrameWidthSent");
try {
if (getStatValue(now, "googFrameHeightReceived") &&
getStatValue(now, "googFrameWidthReceived")) {
resolution.height = getStatValue(now, "googFrameHeightReceived");
resolution.width = getStatValue(now, "googFrameWidthReceived");
}
else if (getStatValue(now, "googFrameHeightSent") &&
getStatValue(now, "googFrameWidthSent")) {
resolution.height = getStatValue(now, "googFrameHeightSent");
resolution.width = getStatValue(now, "googFrameWidthSent");
}
}
catch(e){/*not supported*/}
if(resolution.height && resolution.width)
{
@ -413,6 +487,7 @@ StatsCollector.prototype.processStatsReport = function () {
}
);
console.log("!!!!!!!!!! " + bitrateDownload + " - " + bitrateUpload);
PeerStats.bitrate = {"upload": bitrateUpload, "download": bitrateDownload};
PeerStats.packetLoss = {
@ -458,11 +533,11 @@ StatsCollector.prototype.processAudioLevelReport = function ()
var before = this.baselineAudioLevelsReport[idx];
if (!before)
{
console.warn(now.stat('ssrc') + ' not enough data');
console.warn(getStatValue(now, 'ssrc') + ' not enough data');
continue;
}
var ssrc = now.stat('ssrc');
var ssrc = getStatValue(now, 'ssrc');
var jid = ssrc2jid[ssrc];
if (!jid)
{
@ -478,9 +553,19 @@ StatsCollector.prototype.processAudioLevelReport = function ()
}
// Audio level
var audioLevel = now.stat('audioInputLevel');
if (!audioLevel)
audioLevel = now.stat('audioOutputLevel');
var audioLevel = null;
try {
audioLevel = getStatValue(now, 'audioInputLevel');
if (!audioLevel)
audioLevel = getStatValue(now, 'audioOutputLevel');
}
catch(e) {/*not supported*/
console.warn("Audio Levels are not available in the statistics.");
clearInterval(this.audioLevelsIntervalId);
return;
}
if (audioLevel)
{
// TODO: can't find specs about what this value really is,
@ -495,3 +580,10 @@ StatsCollector.prototype.processAudioLevelReport = function ()
};
function getStatValue(item, name) {
if(!keyMap[RTC.browser][name])
throw "The property isn't supported!";
var key = keyMap[RTC.browser][name];
return RTC.browser == "chrome"? item.stat(key) : item[key];
}

View File

@ -1640,7 +1640,7 @@ var VideoLayout = (function (my) {
endpointSimulcastLayers.forEach(function (esl) {
var resource = esl.endpoint;
if (lastNCount < 1 || lastNEndpointsCache.indexOf(resource) === -1) {
if (lastNCount !== -1 && (lastNCount < 1 || lastNEndpointsCache.indexOf(resource) === -1)) {
return;
}
@ -1686,7 +1686,7 @@ var VideoLayout = (function (my) {
endpointSimulcastLayers.forEach(function (esl) {
var resource = esl.endpoint;
if (lastNCount < 1 || lastNEndpointsCache.indexOf(resource) === -1) {
if (lastNCount !== -1 && (lastNCount < 1 || lastNEndpointsCache.indexOf(resource) === -1)) {
return;
}
@ -1861,19 +1861,25 @@ var VideoLayout = (function (my) {
if(this.jid==null)
{
resolution = "";
for(var i in this.resolution)
if(this.resolution == null || !Object.keys(this.resolution)
|| Object.keys(this.resolution).length == 0)
{
resolutionValue = this.resolution[i];
if(resolutionValue)
resolution = "N/A";
}
else
for(var i in this.resolution)
{
if(resolutionValue.height &&
resolutionValue.width)
resolutionValue = this.resolution[i];
if(resolutionValue)
{
resolution += (resolution == ""? "" : ", ")
+ resolutionValue.width + "x" + resolutionValue.height;
if(resolutionValue.height &&
resolutionValue.width)
{
resolution += (resolution == ""? "" : ", ")
+ resolutionValue.width + "x" + resolutionValue.height;
}
}
}
}
}
else if(!resolutionValue ||
!resolutionValue.height ||