| '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", |
| "stream", |
| "track", |
| "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, |
| 'transceiver': validateTransceiverStats, |
| 'sender': validateSenderStats, |
| 'receiver': validateReceiverStats, |
| '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 trackId; |
| DOMString receiverId; |
| 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 receiverId, remoteId, framesDecoded, nackCount, framesReceived, bytesReceived, totalAudioEnergy, totalSampleDuration |
| */ |
| function validateInboundRtpStreamStats(statsReport, stats) { |
| validateReceivedRtpStreamStats(statsReport, stats); |
| validateOptionalIdField(statsReport, stats, 'trackId', 'track'); |
| validateIdField(statsReport, stats, 'receiverId', 'receiver'); |
| validateIdField(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'); |
| } |
| |
| /* |
| [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 senderId; |
| 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; |
| }; |
| Obsolete members: |
| partial dictionary RTCOutboundStreamStats { |
| DOMString trackId; |
| }; |
| [webrtc-pc] |
| 8.6. Mandatory To Implement Stats |
| - RTCOutboundRtpStreamStats, with all required attributes from its |
| inherited dictionaries, and also attributes senderId, remoteId, framesEncoded, nackCount, framesSent |
| */ |
| function validateOutboundRtpStreamStats(statsReport, stats) { |
| validateSentRtpStreamStats(statsReport, stats) |
| |
| validateOptionalIdField(statsReport, stats, 'mediaSourceId', 'media-source'); |
| validateIdField(statsReport, stats, 'senderId', 'sender'); |
| validateIdField(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'); |
| // Obsolete stats |
| validateOptionalIdField(statsReport, stats, 'trackId', 'track'); |
| } |
| |
| /* |
| [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.16 RTCRtpTransceiverStats dictionary |
| dictionary RTCRtpTransceiverStats { |
| DOMString senderId; |
| DOMString receiverId; |
| DOMString mid; |
| }; |
| */ |
| function validateTransceiverStats(statsReport, stats) { |
| validateRtcStats(statsReport, stats); |
| validateOptionalIdField(statsReport, stats, 'senderId', 'sender'); |
| validateOptionalIdField(statsReport, stats, 'receiverId', 'sender'); |
| assert_optional_string_field(stats, 'mid'); |
| } |
| |
| /* |
| [webrtc-stats] |
| dictionary RTCMediaHandlerStats : RTCStats { |
| DOMString trackIdentifier; |
| boolean remoteSource; |
| boolean ended; |
| DOMString kind; |
| RTCPriorityType priority; |
| }; |
| dictionary RTCVideoHandlerStats : RTCMediaHandlerStats { |
| }; |
| dictionary RTCAudioHandlerStats : RTCMediaHandlerStats { |
| }; |
| Used from validateSenderStats and validateReceiverStats |
| |
| [webrtc-priority] |
| enum RTCPriorityType { |
| "very-low", |
| "low", |
| "medium", |
| "high" |
| }; |
| |
| [webrtc-pc] |
| MTI: |
| RTCMediaHandlerStats with attributes trackIdentifier |
| RTCAudioHandlerStats, with all required attributes from its inherited dictionaries |
| RTCVideoHandlerStats, with all required attributes from its inherited dictionaries |
| |
| */ |
| function validateMediaHandlerStats(statsReport, stats) { |
| validateRtcStats(statsReport, stats); |
| assert_string_field(stats, 'trackIdentifier'); |
| assert_optional_boolean_field(stats, 'remoteSource'); |
| assert_optional_boolean_field(stats, 'ended'); |
| assert_optional_string_field(stats, 'kind'); |
| assert_enum_field(stats, 'priority', ['very-low', 'low', 'medium', 'high']); |
| } |
| |
| /* |
| [webrtc-stats] |
| dictionary RTCAudioSenderStats : RTCAudioHandlerStats { |
| DOMString mediaSourceId; |
| }; |
| dictionary RTCVideoSenderStats : RTCVideoHandlerStats { |
| DOMString mediaSourceId; |
| }; |
| |
| [webrtc-pc] |
| MTI: |
| RTCVideoSenderStats, with all required attributes from its inherited dictionaries |
| */ |
| function validateSenderStats(statsReport, stats) { |
| validateMediaHandlerStats(statsReport, stats); |
| validateOptionalIdField(statsReport, stats, 'mediaSourceId', 'media-source'); |
| } |
| |
| /* |
| [webrtc-stats] |
| dictionary RTCAudioReceiverStats : RTCAudioHandlerStats { |
| }; |
| dictionary RTCVideoReceiverStats : RTCVideoHandlerStats { |
| }; |
| |
| [webrtc-pc] |
| MTI: |
| RTCVideoReceiverStats, with all required attributes from its inherited dictionaries |
| */ |
| function validateReceiverStats(statsReport, stats) { |
| validateMediaHandlerStats(statsReport, stats); |
| } |
| |
| |
| /* |
| [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'); |
| } |