mirror of
https://github.com/servo/servo.git
synced 2025-06-25 09:34:32 +01:00
973 lines
36 KiB
JavaScript
973 lines
36 KiB
JavaScript
'use strict';
|
|
|
|
// Test is based on the following editor draft:
|
|
// webrtc-pc 20171130
|
|
// webrtc-stats 20171122
|
|
|
|
// This file depends on dictionary-helper.js which should
|
|
// be loaded from the main HTML file.
|
|
|
|
/*
|
|
[webrtc-stats]
|
|
6.1. RTCStatsType enum
|
|
enum RTCStatsType {
|
|
"codec",
|
|
"inbound-rtp",
|
|
"outbound-rtp",
|
|
"remote-inbound-rtp",
|
|
"remote-outbound-rtp",
|
|
"csrc",
|
|
"peer-connection",
|
|
"data-channel",
|
|
"transport",
|
|
"candidate-pair",
|
|
"local-candidate",
|
|
"remote-candidate",
|
|
"certificate",
|
|
"ice-server"
|
|
};
|
|
*/
|
|
const statsValidatorTable = {
|
|
'codec': validateCodecStats,
|
|
'inbound-rtp': validateInboundRtpStreamStats,
|
|
'outbound-rtp': validateOutboundRtpStreamStats,
|
|
'remote-inbound-rtp': validateRemoteInboundRtpStreamStats,
|
|
'remote-outbound-rtp': validateRemoteOutboundRtpStreamStats,
|
|
'media-source': validateMediaSourceStats,
|
|
'csrc': validateContributingSourceStats,
|
|
'peer-connection': validatePeerConnectionStats,
|
|
'data-channel': validateDataChannelStats,
|
|
'transport': validateTransportStats,
|
|
'candidate-pair': validateIceCandidatePairStats,
|
|
'local-candidate': validateIceCandidateStats,
|
|
'remote-candidate': validateIceCandidateStats,
|
|
'certificate': validateCertificateStats,
|
|
'ice-server': validateIceServerStats
|
|
};
|
|
|
|
// Validate that the stats objects in a stats report
|
|
// follows the respective definitions.
|
|
// Stats objects with unknown type are ignored and
|
|
// only basic validation is done.
|
|
function validateStatsReport(statsReport) {
|
|
for(const [id, stats] of statsReport.entries()) {
|
|
assert_equals(stats.id, id,
|
|
'expect stats.id to be the same as the key in statsReport');
|
|
|
|
const validator = statsValidatorTable[stats.type];
|
|
if(validator) {
|
|
validator(statsReport, stats);
|
|
} else {
|
|
validateRtcStats(statsReport, stats);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Assert that the stats report have stats objects of
|
|
// given types
|
|
function assert_stats_report_has_stats(statsReport, statsTypes) {
|
|
const hasTypes = new Set([...statsReport.values()]
|
|
.map(stats => stats.type));
|
|
|
|
for(const type of statsTypes) {
|
|
assert_true(hasTypes.has(type),
|
|
`Expect statsReport to contain stats object of type ${type}`);
|
|
}
|
|
}
|
|
|
|
function findStatsFromReport(statsReport, predicate, message) {
|
|
for (const stats of statsReport.values()) {
|
|
if (predicate(stats)) {
|
|
return stats;
|
|
}
|
|
}
|
|
|
|
assert_unreached(message || 'none of stats in statsReport satisfy given condition')
|
|
}
|
|
|
|
// Get stats object of type that is expected to be
|
|
// found in the statsReport
|
|
function getRequiredStats(statsReport, type) {
|
|
for(const stats of statsReport.values()) {
|
|
if(stats.type === type) {
|
|
return stats;
|
|
}
|
|
}
|
|
|
|
assert_unreached(`required stats of type ${type} is not found in stats report`);
|
|
}
|
|
|
|
// Get stats object by the stats ID.
|
|
// This is used to retreive other stats objects
|
|
// linked to a stats object
|
|
function getStatsById(statsReport, statsId) {
|
|
assert_true(statsReport.has(statsId),
|
|
`Expect stats report to have stats object with id ${statsId}`);
|
|
|
|
return statsReport.get(statsId);
|
|
}
|
|
|
|
// Validate an ID field in a stats object by making sure
|
|
// that the linked stats object is found in the stats report
|
|
// and have the type field value same as expected type
|
|
// It doesn't validate the other fields of the linked stats
|
|
// as validateStatsReport already does all validations
|
|
function validateIdField(statsReport, stats, field, type) {
|
|
assert_string_field(stats, field);
|
|
const linkedStats = getStatsById(statsReport, stats[field]);
|
|
assert_equals(linkedStats.type, type,
|
|
`Expect linked stats object to have type ${type}`);
|
|
}
|
|
|
|
function validateOptionalIdField(statsReport, stats, field, type) {
|
|
if(stats[field] !== undefined) {
|
|
validateIdField(statsReport, stats, field, type);
|
|
}
|
|
}
|
|
|
|
/*
|
|
[webrtc-pc]
|
|
8.4. RTCStats Dictionary
|
|
dictionary RTCStats {
|
|
required DOMHighResTimeStamp timestamp;
|
|
required RTCStatsType type;
|
|
required DOMString id;
|
|
};
|
|
*/
|
|
function validateRtcStats(statsReport, stats) {
|
|
assert_number_field(stats, 'timestamp');
|
|
assert_string_field(stats, 'type');
|
|
assert_string_field(stats, 'id');
|
|
}
|
|
|
|
/*
|
|
[webrtc-stats]
|
|
7.1. RTCRtpStreamStats dictionary
|
|
dictionary RTCRtpStreamStats : RTCStats {
|
|
unsigned long ssrc;
|
|
DOMString kind;
|
|
DOMString transportId;
|
|
DOMString codecId;
|
|
};
|
|
|
|
kind of type DOMString
|
|
Either "audio" or "video".
|
|
|
|
[webrtc-pc]
|
|
8.6. Mandatory To Implement Stats
|
|
- RTCRtpStreamStats, with attributes ssrc, kind, transportId, codecId
|
|
*/
|
|
function validateRtpStreamStats(statsReport, stats) {
|
|
validateRtcStats(statsReport, stats);
|
|
|
|
assert_unsigned_int_field(stats, 'ssrc');
|
|
assert_string_field(stats, 'kind');
|
|
assert_enum_field(stats, 'kind', ['audio', 'video'])
|
|
|
|
validateIdField(statsReport, stats, 'transportId', 'transport');
|
|
validateIdField(statsReport, stats, 'codecId', 'codec');
|
|
|
|
}
|
|
|
|
/*
|
|
[webrtc-stats]
|
|
7.2. RTCCodecStats dictionary
|
|
dictionary RTCCodecStats : RTCStats {
|
|
required unsigned long payloadType;
|
|
RTCCodecType codecType;
|
|
required DOMString transportId;
|
|
required DOMString mimeType;
|
|
unsigned long clockRate;
|
|
unsigned long channels;
|
|
DOMString sdpFmtpLine;
|
|
};
|
|
|
|
enum RTCCodecType {
|
|
"encode",
|
|
"decode",
|
|
};
|
|
|
|
[webrtc-pc]
|
|
8.6. Mandatory To Implement Stats
|
|
- RTCCodecStats, with attributes payloadType, codecType, mimeType, clockRate, channels, sdpFmtpLine
|
|
*/
|
|
|
|
function validateCodecStats(statsReport, stats) {
|
|
validateRtcStats(statsReport, stats);
|
|
|
|
assert_unsigned_int_field(stats, 'payloadType');
|
|
assert_optional_enum_field(stats, 'codecType', ['encode', 'decode']);
|
|
|
|
validateOptionalIdField(statsReport, stats, 'transportId', 'transport');
|
|
|
|
assert_string_field(stats, 'mimeType');
|
|
assert_unsigned_int_field(stats, 'clockRate');
|
|
if (stats.kind === 'audio') {
|
|
assert_unsigned_int_field(stats, 'channels');
|
|
}
|
|
assert_string_field(stats, 'sdpFmtpLine');
|
|
}
|
|
|
|
/*
|
|
[webrtc-stats]
|
|
7.3. RTCReceivedRtpStreamStats dictionary
|
|
dictionary RTCReceivedRtpStreamStats : RTCRtpStreamStats {
|
|
unsigned long long packetsReceived;
|
|
long long packetsLost;
|
|
double jitter;
|
|
unsigned long long packetsDiscarded;
|
|
unsigned long long packetsRepaired;
|
|
unsigned long long burstPacketsLost;
|
|
unsigned long long burstPacketsDiscarded;
|
|
unsigned long burstLossCount;
|
|
unsigned long burstDiscardCount;
|
|
double burstLossRate;
|
|
double burstDiscardRate;
|
|
double gapLossRate;
|
|
double gapDiscardRate;
|
|
unsigned long framesDropped;
|
|
unsigned long partialFramesLost;
|
|
unsigned long fullFramesLost;
|
|
};
|
|
|
|
[webrtc-pc]
|
|
8.6. Mandatory To Implement Stats
|
|
- RTCReceivedRtpStreamStats, with all required attributes from its
|
|
inherited dictionaries, and also attributes packetsReceived,
|
|
packetsLost, jitter, packetsDiscarded, framesDropped
|
|
*/
|
|
function validateReceivedRtpStreamStats(statsReport, stats) {
|
|
validateRtpStreamStats(statsReport, stats);
|
|
|
|
assert_unsigned_int_field(stats, 'packetsReceived');
|
|
assert_unsigned_int_field(stats, 'packetsLost');
|
|
|
|
assert_number_field(stats, 'jitter');
|
|
|
|
assert_unsigned_int_field(stats, 'packetsDiscarded');
|
|
assert_unsigned_int_field(stats, 'framesDropped');
|
|
|
|
assert_optional_unsigned_int_field(stats, 'packetsRepaired');
|
|
assert_optional_unsigned_int_field(stats, 'burstPacketsLost');
|
|
assert_optional_unsigned_int_field(stats, 'burstPacketsDiscarded');
|
|
assert_optional_unsigned_int_field(stats, 'burstLossCount');
|
|
assert_optional_unsigned_int_field(stats, 'burstDiscardCount');
|
|
|
|
assert_optional_number_field(stats, 'burstLossRate');
|
|
assert_optional_number_field(stats, 'burstDiscardRate');
|
|
assert_optional_number_field(stats, 'gapLossRate');
|
|
assert_optional_number_field(stats, 'gapDiscardRate');
|
|
|
|
assert_optional_unsigned_int_field(stats, 'partialFramesLost');
|
|
assert_optional_unsigned_int_field(stats, 'fullFramesLost');
|
|
}
|
|
|
|
/*
|
|
[webrtc-stats]
|
|
7.4. RTCInboundRtpStreamStats dictionary
|
|
dictionary RTCInboundRtpStreamStats : RTCReceivedRtpStreamStats {
|
|
DOMString trackIdentifier;
|
|
DOMString remoteId;
|
|
unsigned long framesDecoded;
|
|
unsigned long keyFramesDecoded;
|
|
unsigned long frameWidth;
|
|
unsigned long frameHeight;
|
|
unsigned long frameBitDepth;
|
|
double framesPerSecond;
|
|
unsigned long long qpSum;
|
|
double totalDecodeTime;
|
|
double totalInterFrameDelay;
|
|
double totalSquaredInterFrameDelay;
|
|
boolean voiceActivityFlag;
|
|
DOMHighResTimeStamp lastPacketReceivedTimestamp;
|
|
double averageRtcpInterval;
|
|
unsigned long long headerBytesReceived;
|
|
unsigned long long fecPacketsReceived;
|
|
unsigned long long fecPacketsDiscarded;
|
|
unsigned long long bytesReceived;
|
|
unsigned long long packetsFailedDecryption;
|
|
unsigned long long packetsDuplicated;
|
|
record<USVString, unsigned long long> perDscpPacketsReceived;
|
|
unsigned long nackCount;
|
|
unsigned long firCount;
|
|
unsigned long pliCount;
|
|
unsigned long sliCount;
|
|
DOMHighResTimeStamp estimatedPlayoutTimestamp;
|
|
double jitterBufferDelay;
|
|
unsigned long long jitterBufferEmittedCount;
|
|
unsigned long long totalSamplesReceived;
|
|
unsigned long long samplesDecodedWithSilk;
|
|
unsigned long long samplesDecodedWithCelt;
|
|
unsigned long long concealedSamples;
|
|
unsigned long long silentConcealedSamples;
|
|
unsigned long long concealmentEvents;
|
|
unsigned long long insertedSamplesForDeceleration;
|
|
unsigned long long removedSamplesForAcceleration;
|
|
double audioLevel;
|
|
double totalAudioEnergy;
|
|
double totalSamplesDuration;
|
|
unsigned long framesReceived;
|
|
DOMString decoderImplementation;
|
|
};
|
|
|
|
[webrtc-pc]
|
|
8.6. Mandatory To Implement Stats
|
|
- RTCInboundRtpStreamStats, with all required attributes from its inherited
|
|
dictionaries, and also attributes remoteId, framesDecoded, nackCount, framesReceived, bytesReceived, totalAudioEnergy, totalSampleDuration
|
|
*/
|
|
function validateInboundRtpStreamStats(statsReport, stats) {
|
|
validateReceivedRtpStreamStats(statsReport, stats);
|
|
assert_string_field(stats, 'trackIdentifier');
|
|
validateOptionalIdField(statsReport, stats, 'remoteId', 'remote-outbound-rtp');
|
|
assert_unsigned_int_field(stats, 'framesDecoded');
|
|
assert_optional_unsigned_int_field(stats, 'keyFramesDecoded');
|
|
assert_optional_unsigned_int_field(stats, 'frameWidth');
|
|
assert_optional_unsigned_int_field(stats, 'frameHeight');
|
|
assert_optional_unsigned_int_field(stats, 'frameBitDepth');
|
|
assert_optional_number_field(stats, 'framesPerSecond');
|
|
assert_optional_unsigned_int_field(stats, 'qpSum');
|
|
assert_optional_number_field(stats, 'totalDecodeTime');
|
|
assert_optional_number_field(stats, 'totalInterFrameDelay');
|
|
assert_optional_number_field(stats, 'totalSquaredInterFrameDelay');
|
|
|
|
assert_optional_boolean_field(stats, 'voiceActivityFlag');
|
|
|
|
assert_optional_number_field(stats, 'lastPacketReceivedTimeStamp');
|
|
assert_optional_number_field(stats, 'averageRtcpInterval');
|
|
|
|
assert_optional_unsigned_int_field(stats, 'fecPacketsReceived');
|
|
assert_optional_unsigned_int_field(stats, 'fecPacketsDiscarded');
|
|
assert_unsigned_int_field(stats, 'bytesReceived');
|
|
assert_optional_unsigned_int_field(stats, 'packetsFailedDecryption');
|
|
assert_optional_unsigned_int_field(stats, 'packetsDuplicated');
|
|
|
|
assert_optional_dict_field(stats, 'perDscpPacketsReceived');
|
|
if (stats['perDscpPacketsReceived']) {
|
|
Object.keys(stats['perDscpPacketsReceived'])
|
|
.forEach(k =>
|
|
assert_equals(typeof k, 'string', 'Expect keys of perDscpPacketsReceived to be strings')
|
|
);
|
|
Object.values(stats['perDscpPacketsReceived'])
|
|
.forEach(v =>
|
|
assert_true(Number.isInteger(v) && (v >= 0), 'Expect values of perDscpPacketsReceived to be strings')
|
|
);
|
|
}
|
|
|
|
assert_unsigned_int_field(stats, 'nackCount');
|
|
|
|
assert_optional_unsigned_int_field(stats, 'firCount');
|
|
assert_optional_unsigned_int_field(stats, 'pliCount');
|
|
assert_optional_unsigned_int_field(stats, 'sliCount');
|
|
|
|
assert_optional_number_field(stats, 'estimatedPlayoutTimestamp');
|
|
assert_optional_number_field(stats, 'jitterBufferDelay');
|
|
assert_optional_unsigned_int_field(stats, 'jitterBufferEmittedCount');
|
|
assert_optional_unsigned_int_field(stats, 'totalSamplesReceived');
|
|
assert_optional_unsigned_int_field(stats, 'samplesDecodedWithSilk');
|
|
assert_optional_unsigned_int_field(stats, 'samplesDecodedWithCelt');
|
|
assert_optional_unsigned_int_field(stats, 'concealedSamples');
|
|
assert_optional_unsigned_int_field(stats, 'silentConcealedSamples');
|
|
assert_optional_unsigned_int_field(stats, 'concealmentEvents');
|
|
assert_optional_unsigned_int_field(stats, 'insertedSamplesForDeceleration');
|
|
assert_optional_unsigned_int_field(stats, 'removedSamplesForAcceleration');
|
|
assert_optional_number_field(stats, 'audioLevel');
|
|
assert_optional_number_field(stats, 'totalAudioEnergy');
|
|
assert_optional_number_field(stats, 'totalSamplesDuration');
|
|
assert_unsigned_int_field(stats, 'framesReceived');
|
|
assert_optional_string_field(stats, 'decoderImplementation');
|
|
assert_optional_boolean_field(stats, 'powerEfficientDecoder');
|
|
}
|
|
|
|
/*
|
|
[webrtc-stats]
|
|
7.5. RTCRemoteInboundRtpStreamStats dictionary
|
|
dictionary RTCRemoteInboundRtpStreamStats : RTCReceivedRtpStreamStats {
|
|
DOMString localId;
|
|
double roundTripTime;
|
|
double totalRoundTripTime;
|
|
double fractionLost;
|
|
unsigned long long reportsReceived;
|
|
unsigned long long roundTripTimeMeasurements;
|
|
};
|
|
|
|
[webrtc-pc]
|
|
8.6. Mandatory To Implement Stats
|
|
- RTCRemoteInboundRtpStreamStats, with all required attributes from its
|
|
inherited dictionaries, and also attributes localId, roundTripTime
|
|
*/
|
|
function validateRemoteInboundRtpStreamStats(statsReport, stats) {
|
|
validateReceivedRtpStreamStats(statsReport, stats);
|
|
|
|
validateIdField(statsReport, stats, 'localId', 'outbound-rtp');
|
|
assert_number_field(stats, 'roundTripTime');
|
|
assert_optional_number_field(stats, 'totalRoundTripTime');
|
|
assert_optional_number_field(stats, 'fractionLost');
|
|
assert_optional_unsigned_int_field(stats, 'reportsReceived');
|
|
assert_optional_unsigned_int_field(stats, 'roundTripTimeMeasurements');
|
|
}
|
|
|
|
/*
|
|
[webrtc-stats]
|
|
7.6. RTCSentRtpStreamStats dictionary
|
|
dictionary RTCSentRtpStreamStats : RTCRtpStreamStats {
|
|
unsigned long packetsSent;
|
|
unsigned long long bytesSent;
|
|
};
|
|
|
|
[webrtc-pc]
|
|
8.6. Mandatory To Implement Stats
|
|
- RTCSentRtpStreamStats, with all required attributes from its inherited
|
|
dictionaries, and also attributes packetsSent, bytesSent
|
|
*/
|
|
function validateSentRtpStreamStats(statsReport, stats) {
|
|
validateRtpStreamStats(statsReport, stats);
|
|
|
|
assert_unsigned_int_field(stats, 'packetsSent');
|
|
assert_unsigned_int_field(stats, 'bytesSent');
|
|
}
|
|
|
|
/*
|
|
[webrtc-stats]
|
|
7.7. RTCOutboundRtpStreamStats dictionary
|
|
dictionary RTCOutboundRtpStreamStats : RTCSentRtpStreamStats {
|
|
DOMString mediaSourceId;
|
|
DOMString remoteId;
|
|
DOMString rid;
|
|
DOMHighResTimeStamp lastPacketSentTimestamp;
|
|
unsigned long long headerBytesSent;
|
|
unsigned long packetsDiscardedOnSend;
|
|
unsigned long long bytesDiscardedOnSend;
|
|
unsigned long fecPacketsSent;
|
|
unsigned long long retransmittedPacketsSent;
|
|
unsigned long long retransmittedBytesSent;
|
|
double targetBitrate;
|
|
unsigned long long totalEncodedBytesTarget;
|
|
unsigned long frameWidth;
|
|
unsigned long frameHeight;
|
|
unsigned long frameBitDepth;
|
|
double framesPerSecond;
|
|
unsigned long framesSent;
|
|
unsigned long hugeFramesSent;
|
|
unsigned long framesEncoded;
|
|
unsigned long keyFramesEncoded;
|
|
unsigned long framesDiscardedOnSend;
|
|
unsigned long long qpSum;
|
|
unsigned long long totalSamplesSent;
|
|
unsigned long long samplesEncodedWithSilk;
|
|
unsigned long long samplesEncodedWithCelt;
|
|
boolean voiceActivityFlag;
|
|
double totalEncodeTime;
|
|
double totalPacketSendDelay;
|
|
double averageRtcpInterval;
|
|
RTCQualityLimitationReason qualityLimitationReason;
|
|
record<DOMString, double> qualityLimitationDurations;
|
|
unsigned long qualityLimitationResolutionChanges;
|
|
record<USVString, unsigned long long> perDscpPacketsSent;
|
|
unsigned long nackCount;
|
|
unsigned long firCount;
|
|
unsigned long pliCount;
|
|
unsigned long sliCount;
|
|
DOMString encoderImplementation;
|
|
};
|
|
[webrtc-pc]
|
|
8.6. Mandatory To Implement Stats
|
|
- RTCOutboundRtpStreamStats, with all required attributes from its
|
|
inherited dictionaries, and also attributes remoteId, framesEncoded, nackCount, framesSent
|
|
*/
|
|
function validateOutboundRtpStreamStats(statsReport, stats) {
|
|
validateSentRtpStreamStats(statsReport, stats)
|
|
|
|
validateOptionalIdField(statsReport, stats, 'mediaSourceId', 'media-source');
|
|
validateOptionalIdField(statsReport, stats, 'remoteId', 'remote-inbound-rtp');
|
|
|
|
assert_optional_string_field(stats, 'rid');
|
|
|
|
assert_optional_number_field(stats, 'lastPacketSentTimestamp');
|
|
assert_optional_unsigned_int_field(stats, 'headerBytesSent');
|
|
assert_optional_unsigned_int_field(stats, 'packetsDiscardedOnSend');
|
|
assert_optional_unsigned_int_field(stats, 'bytesDiscardedOnSend');
|
|
assert_optional_unsigned_int_field(stats, 'fecPacketsSent');
|
|
assert_optional_unsigned_int_field(stats, 'retransmittedPacketsSent');
|
|
assert_optional_unsigned_int_field(stats, 'retransmittedBytesSent');
|
|
assert_optional_number_field(stats, 'targetBitrate');
|
|
assert_optional_unsigned_int_field(stats, 'totalEncodedBytesTarget');
|
|
if (stats['kind'] === 'video') {
|
|
assert_optional_unsigned_int_field(stats, 'frameWidth');
|
|
assert_optional_unsigned_int_field(stats, 'frameHeight');
|
|
assert_optional_unsigned_int_field(stats, 'frameBitDepth');
|
|
assert_optional_number_field(stats, 'framesPerSecond');
|
|
assert_unsigned_int_field(stats, 'framesSent');
|
|
assert_optional_unsigned_int_field(stats, 'hugeFramesSent');
|
|
assert_unsigned_int_field(stats, 'framesEncoded');
|
|
assert_optional_unsigned_int_field(stats, 'keyFramesEncoded');
|
|
assert_optional_unsigned_int_field(stats, 'framesDiscardedOnSend');
|
|
assert_optional_unsigned_int_field(stats, 'qpSum');
|
|
} else if (stats['kind'] === 'audio') {
|
|
assert_optional_unsigned_int_field(stats, 'totalSamplesSent');
|
|
assert_optional_unsigned_int_field(stats, 'samplesEncodedWithSilk');
|
|
assert_optional_unsigned_int_field(stats, 'samplesEncodedWithCelt');
|
|
assert_optional_boolean_field(stats, 'voiceActivityFlag');
|
|
}
|
|
assert_optional_number_field(stats, 'totalEncodeTime');
|
|
assert_optional_number_field(stats, 'totalPacketSendDelay');
|
|
assert_optional_number_field(stats, 'averageRTCPInterval');
|
|
|
|
if (stats['kind'] === 'video') {
|
|
assert_optional_enum_field(stats, 'qualityLimitationReason', ['none', 'cpu', 'bandwidth', 'other']);
|
|
|
|
assert_optional_dict_field(stats, 'qualityLimitationDurations');
|
|
if (stats['qualityLimitationDurations']) {
|
|
Object.keys(stats['qualityLimitationDurations'])
|
|
.forEach(k =>
|
|
assert_equals(typeof k, 'string', 'Expect keys of qualityLimitationDurations to be strings')
|
|
);
|
|
Object.values(stats['qualityLimitationDurations'])
|
|
.forEach(v =>
|
|
assert_equals(typeof num, 'number', 'Expect values of qualityLimitationDurations to be numbers')
|
|
);
|
|
}
|
|
|
|
assert_optional_unsigned_int_field(stats, 'qualityLimitationResolutionChanges');
|
|
}
|
|
assert_unsigned_int_field(stats, 'nackCount');
|
|
assert_optional_dict_field(stats, 'perDscpPacketsSent');
|
|
if (stats['perDscpPacketsSent']) {
|
|
Object.keys(stats['perDscpPacketsSent'])
|
|
.forEach(k =>
|
|
assert_equals(typeof k, 'string', 'Expect keys of perDscpPacketsSent to be strings')
|
|
);
|
|
Object.values(stats['perDscpPacketsSent'])
|
|
.forEach(v =>
|
|
assert_true(Number.isInteger(v) && (v >= 0), 'Expect values of perDscpPacketsSent to be strings')
|
|
);
|
|
}
|
|
|
|
assert_optional_unsigned_int_field(stats, 'firCount');
|
|
assert_optional_unsigned_int_field(stats, 'pliCount');
|
|
assert_optional_unsigned_int_field(stats, 'sliCount');
|
|
assert_optional_string_field(stats, 'encoderImplementation');
|
|
assert_optional_boolean_field(stats, 'powerEfficientEncoder');
|
|
assert_optional_string_field(stats, 'scalabilityMode');
|
|
}
|
|
|
|
/*
|
|
[webrtc-stats]
|
|
7.8. RTCRemoteOutboundRtpStreamStats dictionary
|
|
dictionary RTCRemoteOutboundRtpStreamStats : RTCSentRtpStreamStats {
|
|
DOMString localId;
|
|
DOMHighResTimeStamp remoteTimestamp;
|
|
unsigned long long reportsSent;
|
|
};
|
|
|
|
[webrtc-pc]
|
|
8.6. Mandatory To Implement Stats
|
|
- RTCRemoteOutboundRtpStreamStats, with all required attributes from its
|
|
inherited dictionaries, and also attributes localId, remoteTimestamp
|
|
*/
|
|
function validateRemoteOutboundRtpStreamStats(statsReport, stats) {
|
|
validateSentRtpStreamStats(statsReport, stats);
|
|
|
|
validateIdField(statsReport, stats, 'localId', 'inbound-rtp');
|
|
assert_number_field(stats, 'remoteTimeStamp');
|
|
assert_optional_unsigned_int_field(stats, 'reportsSent');
|
|
}
|
|
|
|
/*
|
|
[webrtc-stats]
|
|
7.11 RTCMediaSourceStats dictionary
|
|
dictionary RTCMediaSourceStats : RTCStats {
|
|
DOMString trackIdentifier;
|
|
DOMString kind;
|
|
};
|
|
|
|
dictionary RTCAudioSourceStats : RTCMediaSourceStats {
|
|
double audioLevel;
|
|
double totalAudioEnergy;
|
|
double totalSamplesDuration;
|
|
double echoReturnLoss;
|
|
double echoReturnLossEnhancement;
|
|
};
|
|
|
|
dictionary RTCVideoSourceStats : RTCMediaSourceStats {
|
|
unsigned long width;
|
|
unsigned long height;
|
|
unsigned long bitDepth;
|
|
unsigned long frames;
|
|
// see https://github.com/w3c/webrtc-stats/issues/540
|
|
double framesPerSecond;
|
|
};
|
|
|
|
[webrtc-pc]
|
|
8.6. Mandatory To Implement Stats
|
|
RTCMediaSourceStats with attributes trackIdentifier, kind
|
|
RTCAudioSourceStats, with all required attributes from its inherited dictionaries and totalAudioEnergy, totalSamplesDuration
|
|
RTCVideoSourceStats, with all required attributes from its inherited dictionaries and width, height, framesPerSecond
|
|
*/
|
|
function validateMediaSourceStats(statsReport, stats) {
|
|
validateRtcStats(statsReport, stats);
|
|
assert_string_field(stats, 'trackIdentifier');
|
|
assert_enum_field(stats, 'kind', ['audio', 'video']);
|
|
|
|
if (stats.kind === 'audio') {
|
|
assert_optional_number_field(stats, 'audioLevel');
|
|
assert_number_field(stats, 'totalAudioEnergy');
|
|
assert_number_field(stats, 'totalSamplesDuration');
|
|
assert_optional_number_field(stats, 'echoReturnLoss');
|
|
assert_optional_number_field(stats, 'echoReturnLossEnhancement');
|
|
} else if (stats.kind === 'video') {
|
|
assert_unsigned_int_field(stats, 'width');
|
|
assert_unsigned_int_field(stats, 'height');
|
|
assert_optional_unsigned_int_field(stats, 'bitDpeth');
|
|
assert_optional_unsigned_int_field(stats, 'frames');
|
|
assert_number_field(stats, 'framesPerSecond');
|
|
}
|
|
}
|
|
|
|
/*
|
|
[webrtc-stats]
|
|
7.9. RTCRTPContributingSourceStats
|
|
dictionary RTCRTPContributingSourceStats : RTCStats {
|
|
unsigned long contributorSsrc;
|
|
DOMString inboundRtpStreamId;
|
|
unsigned long packetsContributedTo;
|
|
double audioLevel;
|
|
};
|
|
*/
|
|
function validateContributingSourceStats(statsReport, stats) {
|
|
validateRtcStats(statsReport, stats);
|
|
|
|
assert_optional_unsigned_int_field(stats, 'contributorSsrc');
|
|
|
|
validateOptionalIdField(statsReport, stats, 'inboundRtpStreamId', 'inbound-rtp');
|
|
assert_optional_unsigned_int_field(stats, 'packetsContributedTo');
|
|
assert_optional_number_field(stats, 'audioLevel');
|
|
}
|
|
|
|
/*
|
|
[webrtc-stats]
|
|
7.10. RTCPeerConnectionStats dictionary
|
|
dictionary RTCPeerConnectionStats : RTCStats {
|
|
unsigned long dataChannelsOpened;
|
|
unsigned long dataChannelsClosed;
|
|
unsigned long dataChannelsRequested;
|
|
unsigned long dataChannelsAccepted;
|
|
};
|
|
|
|
[webrtc-pc]
|
|
8.6. Mandatory To Implement Stats
|
|
- RTCPeerConnectionStats, with attributes dataChannelsOpened, dataChannelsClosed
|
|
*/
|
|
function validatePeerConnectionStats(statsReport, stats) {
|
|
validateRtcStats(statsReport, stats);
|
|
|
|
assert_unsigned_int_field(stats, 'dataChannelsOpened');
|
|
assert_unsigned_int_field(stats, 'dataChannelsClosed');
|
|
assert_optional_unsigned_int_field(stats, 'dataChannelsRequested');
|
|
assert_optional_unsigned_int_field(stats, 'dataChannelsAccepted');
|
|
}
|
|
|
|
/*
|
|
[webrtc-stats]
|
|
7.13. RTCDataChannelStats dictionary
|
|
dictionary RTCDataChannelStats : RTCStats {
|
|
DOMString label;
|
|
DOMString protocol;
|
|
// see https://github.com/w3c/webrtc-stats/issues/541
|
|
unsigned short dataChannelIdentifier;
|
|
DOMString transportId;
|
|
RTCDataChannelState state;
|
|
unsigned long messagesSent;
|
|
unsigned long long bytesSent;
|
|
unsigned long messagesReceived;
|
|
unsigned long long bytesReceived;
|
|
};
|
|
|
|
[webrtc-pc]
|
|
6.2. RTCDataChannel
|
|
enum RTCDataChannelState {
|
|
"connecting",
|
|
"open",
|
|
"closing",
|
|
"closed"
|
|
};
|
|
|
|
8.6. Mandatory To Implement Stats
|
|
- RTCDataChannelStats, with attributes label, protocol, datachannelIdentifier, state,
|
|
messagesSent, bytesSent, messagesReceived, bytesReceived
|
|
*/
|
|
function validateDataChannelStats(statsReport, stats) {
|
|
validateRtcStats(statsReport, stats);
|
|
|
|
assert_string_field(stats, 'label');
|
|
assert_string_field(stats, 'protocol');
|
|
assert_unsigned_int_field(stats, 'dataChannelIdentifier');
|
|
|
|
validateOptionalIdField(statsReport, stats, 'transportId', 'transport');
|
|
|
|
assert_enum_field(stats, 'state',
|
|
['connecting', 'open', 'closing', 'closed']);
|
|
|
|
assert_unsigned_int_field(stats, 'messagesSent');
|
|
assert_unsigned_int_field(stats, 'bytesSent');
|
|
assert_unsigned_int_field(stats, 'messagesReceived');
|
|
assert_unsigned_int_field(stats, 'bytesReceived');
|
|
}
|
|
|
|
/*
|
|
[webrtc-stats]
|
|
7.14. RTCTransportStats dictionary
|
|
dictionary RTCTransportStats : RTCStats {
|
|
unsigned long long packetsSent;
|
|
unsigned long long packetsReceived;
|
|
unsigned long long bytesSent;
|
|
unsigned long long bytesReceived;
|
|
DOMString rtcpTransportStatsId;
|
|
RTCIceRole iceRole;
|
|
RTCDtlsTransportState dtlsState;
|
|
DOMString selectedCandidatePairId;
|
|
DOMString localCertificateId;
|
|
DOMString remoteCertificateId;
|
|
DOMString tlsVersion;
|
|
DOMString dtlsCipher;
|
|
DOMString srtpCipher;
|
|
DOMString tlsGroup;
|
|
unsigned long selectedCandidatePairChanges;
|
|
};
|
|
|
|
[webrtc-pc]
|
|
5.5. RTCDtlsTransportState Enum
|
|
enum RTCDtlsTransportState {
|
|
"new",
|
|
"connecting",
|
|
"connected",
|
|
"closed",
|
|
"failed"
|
|
};
|
|
|
|
5.6. RTCIceRole Enum
|
|
enum RTCIceRole {
|
|
"unknown",
|
|
"controlling",
|
|
"controlled"
|
|
};
|
|
|
|
8.6. Mandatory To Implement Stats
|
|
- RTCTransportStats, with attributes bytesSent, bytesReceived,
|
|
selectedCandidatePairId, localCertificateId,
|
|
remoteCertificateId
|
|
*/
|
|
function validateTransportStats(statsReport, stats) {
|
|
validateRtcStats(statsReport, stats);
|
|
|
|
assert_optional_unsigned_int_field(stats, 'packetsSent');
|
|
assert_optional_unsigned_int_field(stats, 'packetsReceived');
|
|
assert_unsigned_int_field(stats, 'bytesSent');
|
|
assert_unsigned_int_field(stats, 'bytesReceived');
|
|
|
|
validateOptionalIdField(statsReport, stats, 'rtcpTransportStatsId',
|
|
'transport');
|
|
|
|
assert_optional_enum_field(stats, 'iceRole',
|
|
['unknown', 'controlling', 'controlled']);
|
|
|
|
assert_optional_enum_field(stats, 'dtlsState',
|
|
['new', 'connecting', 'connected', 'closed', 'failed']);
|
|
|
|
validateIdField(statsReport, stats, 'selectedCandidatePairId', 'candidate-pair');
|
|
validateIdField(statsReport, stats, 'localCertificateId', 'certificate');
|
|
validateIdField(statsReport, stats, 'remoteCertificateId', 'certificate');
|
|
assert_optional_string_field(stats, 'tlsVersion');
|
|
assert_optional_string_field(stats, 'dtlsCipher');
|
|
assert_optional_string_field(stats, 'srtpCipher');
|
|
assert_optional_string_field(stats, 'tlsGroup');
|
|
assert_optional_unsigned_int_field(stats, 'selectedCandidatePairChanges');
|
|
}
|
|
|
|
/*
|
|
[webrtc-stats]
|
|
7.15. RTCIceCandidateStats dictionary
|
|
dictionary RTCIceCandidateStats : RTCStats {
|
|
required DOMString transportId;
|
|
DOMString? address;
|
|
long port;
|
|
DOMString protocol;
|
|
RTCIceCandidateType candidateType;
|
|
long priority;
|
|
DOMString url;
|
|
DOMString relayProtocol;
|
|
};
|
|
|
|
[webrtc-pc]
|
|
4.8.1.3. RTCIceCandidateType Enum
|
|
enum RTCIceCandidateType {
|
|
"host",
|
|
"srflx",
|
|
"prflx",
|
|
"relay"
|
|
};
|
|
|
|
8.6. Mandatory To Implement Stats
|
|
- RTCIceCandidateStats, with attributes address, port, protocol, candidateType, url
|
|
*/
|
|
function validateIceCandidateStats(statsReport, stats) {
|
|
validateRtcStats(statsReport, stats);
|
|
|
|
validateIdField(statsReport, stats, 'transportId', 'transport');
|
|
// The address is mandatory to implement, but is allowed to be null
|
|
// when hidden for privacy reasons.
|
|
if (stats.address != null) {
|
|
// Departure from strict spec reading:
|
|
// This field is populated in a racy manner in Chrome.
|
|
// We allow it to be present or not present for the time being.
|
|
// TODO(https://bugs.chromium.org/1092721): Become consistent.
|
|
assert_optional_string_field(stats, 'address');
|
|
}
|
|
assert_unsigned_int_field(stats, 'port');
|
|
assert_string_field(stats, 'protocol');
|
|
|
|
assert_enum_field(stats, 'candidateType',
|
|
['host', 'srflx', 'prflx', 'relay']);
|
|
|
|
assert_optional_int_field(stats, 'priority');
|
|
// The url field is mandatory for local candidates gathered from
|
|
// a STUN or TURN server, and MUST NOT be present otherwise.
|
|
// TODO(hta): Improve checking.
|
|
assert_optional_string_field(stats, 'url');
|
|
assert_optional_string_field(stats, 'relayProtocol');
|
|
}
|
|
|
|
/*
|
|
[webrtc-stats]
|
|
7.16. RTCIceCandidatePairStats dictionary
|
|
dictionary RTCIceCandidatePairStats : RTCStats {
|
|
DOMString transportId;
|
|
DOMString localCandidateId;
|
|
DOMString remoteCandidateId;
|
|
RTCStatsIceCandidatePairState state;
|
|
boolean nominated;
|
|
unsigned long packetsSent;
|
|
unsigned long packetsReceived;
|
|
unsigned long long bytesSent;
|
|
unsigned long long bytesReceived;
|
|
DOMHighResTimeStamp lastPacketSentTimestamp;
|
|
DOMHighResTimeStamp lastPacketReceivedTimestamp;
|
|
DOMHighResTimeStamp firstRequestTimestamp;
|
|
DOMHighResTimeStamp lastRequestTimestamp;
|
|
DOMHighResTimeStamp lastResponseTimestamp;
|
|
double totalRoundTripTime;
|
|
double currentRoundTripTime;
|
|
double availableOutgoingBitrate;
|
|
double availableIncomingBitrate;
|
|
unsigned long circuitBreakerTriggerCount;
|
|
unsigned long long requestsReceived;
|
|
unsigned long long requestsSent;
|
|
unsigned long long responsesReceived;
|
|
unsigned long long responsesSent;
|
|
unsigned long long retransmissionsReceived;
|
|
unsigned long long retransmissionsSent;
|
|
unsigned long long consentRequestsSent;
|
|
DOMHighResTimeStamp consentExpiredTimestamp;
|
|
unsigned long packetsDiscardedOnSend;
|
|
unsigned long long bytesDiscardedOnSend; };
|
|
|
|
enum RTCStatsIceCandidatePairState {
|
|
"frozen",
|
|
"waiting",
|
|
"in-progress",
|
|
"failed",
|
|
"succeeded"
|
|
};
|
|
|
|
[webrtc-pc]
|
|
8.6. Mandatory To Implement Stats
|
|
- RTCIceCandidatePairStats, with attributes transportId, localCandidateId,
|
|
remoteCandidateId, state, nominated, bytesSent, bytesReceived, totalRoundTripTime, currentRoundTripTime
|
|
// not including priority per https://github.com/w3c/webrtc-pc/issues/2457
|
|
*/
|
|
function validateIceCandidatePairStats(statsReport, stats) {
|
|
validateRtcStats(statsReport, stats);
|
|
|
|
validateIdField(statsReport, stats, 'transportId', 'transport');
|
|
validateIdField(statsReport, stats, 'localCandidateId', 'local-candidate');
|
|
validateIdField(statsReport, stats, 'remoteCandidateId', 'remote-candidate');
|
|
|
|
assert_enum_field(stats, 'state',
|
|
['frozen', 'waiting', 'in-progress', 'failed', 'succeeded']);
|
|
|
|
assert_boolean_field(stats, 'nominated');
|
|
assert_optional_unsigned_int_field(stats, 'packetsSent');
|
|
assert_optional_unsigned_int_field(stats, 'packetsReceived');
|
|
assert_unsigned_int_field(stats, 'bytesSent');
|
|
assert_unsigned_int_field(stats, 'bytesReceived');
|
|
|
|
assert_optional_number_field(stats, 'lastPacketSentTimestamp');
|
|
assert_optional_number_field(stats, 'lastPacketReceivedTimestamp');
|
|
assert_optional_number_field(stats, 'firstRequestTimestamp');
|
|
assert_optional_number_field(stats, 'lastRequestTimestamp');
|
|
assert_optional_number_field(stats, 'lastResponseTimestamp');
|
|
|
|
assert_number_field(stats, 'totalRoundTripTime');
|
|
assert_number_field(stats, 'currentRoundTripTime');
|
|
|
|
assert_optional_number_field(stats, 'availableOutgoingBitrate');
|
|
assert_optional_number_field(stats, 'availableIncomingBitrate');
|
|
|
|
assert_optional_unsigned_int_field(stats, 'circuitBreakerTriggerCount');
|
|
assert_optional_unsigned_int_field(stats, 'requestsReceived');
|
|
assert_optional_unsigned_int_field(stats, 'requestsSent');
|
|
assert_optional_unsigned_int_field(stats, 'responsesReceived');
|
|
assert_optional_unsigned_int_field(stats, 'responsesSent');
|
|
assert_optional_unsigned_int_field(stats, 'retransmissionsReceived');
|
|
assert_optional_unsigned_int_field(stats, 'retransmissionsSent');
|
|
assert_optional_unsigned_int_field(stats, 'consentRequestsSent');
|
|
assert_optional_number_field(stats, 'consentExpiredTimestamp');
|
|
assert_optional_unsigned_int_field(stats, 'packetsDiscardedOnSend');
|
|
assert_optional_unsigned_int_field(stats, 'bytesDiscardedOnSend');
|
|
}
|
|
|
|
/*
|
|
[webrtc-stats]
|
|
7.17. RTCCertificateStats dictionary
|
|
dictionary RTCCertificateStats : RTCStats {
|
|
DOMString fingerprint;
|
|
DOMString fingerprintAlgorithm;
|
|
DOMString base64Certificate;
|
|
DOMString issuerCertificateId;
|
|
};
|
|
|
|
[webrtc-pc]
|
|
8.6. Mandatory To Implement Stats
|
|
- RTCCertificateStats, with attributes fingerprint, fingerprintAlgorithm,
|
|
base64Certificate, issuerCertificateId
|
|
*/
|
|
function validateCertificateStats(statsReport, stats) {
|
|
validateRtcStats(statsReport, stats);
|
|
|
|
assert_string_field(stats, 'fingerprint');
|
|
assert_string_field(stats, 'fingerprintAlgorithm');
|
|
assert_string_field(stats, 'base64Certificate');
|
|
assert_optional_string_field(stats, 'issuerCertificateId');
|
|
}
|
|
|
|
/*
|
|
[webrtc-stats]
|
|
7.30. RTCIceServerStats dictionary
|
|
dictionary RTCIceServerStats : RTCStats {
|
|
DOMString url;
|
|
long port;
|
|
DOMString protocol;
|
|
unsigned long totalRequestsSent;
|
|
unsigned long totalResponsesReceived;
|
|
double totalRoundTripTime;
|
|
};
|
|
*/
|
|
function validateIceServerStats(statsReport, stats) {
|
|
validateRtcStats(statsReport, stats);
|
|
|
|
assert_optional_string_field(stats, 'url');
|
|
assert_optional_int_field(stats, 'port');
|
|
assert_optional_string_field(stats, 'protocol');
|
|
assert_optional_unsigned_int_field(stats, 'totalRequestsSent');
|
|
assert_optional_unsigned_int_field(stats, 'totalResponsesReceived');
|
|
assert_optional_number_field(stats, 'totalRoundTripTime');
|
|
}
|