Add stats totalSamplesReceived and concealedSamples
Adds two new stats to RTCMediaStreamTrackStats:
* totalSamplesReceived is the total number of samples received on
the audio channel and includes real and synthetic samples.
* concealedSamples is the total number of synthetic samples
received on the audio channel used to conceal packet loss.
Bug: webrtc:8076
Change-Id: I36e9828525ec341490cf3310a972b56a8b443667
Reviewed-on: https://chromium-review.googlesource.com/615902
Commit-Queue: Steve Anton <steveanton@webrtc.org>
Reviewed-by: Tommi <tommi@webrtc.org>
Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Henrik Lundin <henrik.lundin@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#19506}
This commit is contained in:
@ -273,9 +273,11 @@ class RTCMediaStreamTrackStats final : public RTCStats {
|
|||||||
// Audio-only members
|
// Audio-only members
|
||||||
RTCStatsMember<double> audio_level;
|
RTCStatsMember<double> audio_level;
|
||||||
RTCStatsMember<double> total_audio_energy;
|
RTCStatsMember<double> total_audio_energy;
|
||||||
RTCStatsMember<double> total_samples_duration;
|
|
||||||
RTCStatsMember<double> echo_return_loss;
|
RTCStatsMember<double> echo_return_loss;
|
||||||
RTCStatsMember<double> echo_return_loss_enhancement;
|
RTCStatsMember<double> echo_return_loss_enhancement;
|
||||||
|
RTCStatsMember<uint64_t> total_samples_received;
|
||||||
|
RTCStatsMember<double> total_samples_duration;
|
||||||
|
RTCStatsMember<uint64_t> concealed_samples;
|
||||||
};
|
};
|
||||||
|
|
||||||
// https://w3c.github.io/webrtc-stats/#pcstats-dict*
|
// https://w3c.github.io/webrtc-stats/#pcstats-dict*
|
||||||
|
|||||||
@ -371,6 +371,8 @@ const char* StatsReport::Value::display_name() const {
|
|||||||
return "audioInputLevel";
|
return "audioInputLevel";
|
||||||
case kStatsValueNameBytesSent:
|
case kStatsValueNameBytesSent:
|
||||||
return "bytesSent";
|
return "bytesSent";
|
||||||
|
case kStatsValueNameConcealedSamples:
|
||||||
|
return "concealedSamples";
|
||||||
case kStatsValueNamePacketsSent:
|
case kStatsValueNamePacketsSent:
|
||||||
return "packetsSent";
|
return "packetsSent";
|
||||||
case kStatsValueNameBytesReceived:
|
case kStatsValueNameBytesReceived:
|
||||||
@ -383,6 +385,8 @@ const char* StatsReport::Value::display_name() const {
|
|||||||
return "packetsLost";
|
return "packetsLost";
|
||||||
case kStatsValueNameProtocol:
|
case kStatsValueNameProtocol:
|
||||||
return "protocol";
|
return "protocol";
|
||||||
|
case kStatsValueNameTotalSamplesReceived:
|
||||||
|
return "totalSamplesReceived";
|
||||||
case kStatsValueNameTransportId:
|
case kStatsValueNameTransportId:
|
||||||
return "transportId";
|
return "transportId";
|
||||||
case kStatsValueNameSelectedCandidatePairId:
|
case kStatsValueNameSelectedCandidatePairId:
|
||||||
|
|||||||
@ -104,6 +104,7 @@ class StatsReport {
|
|||||||
kStatsValueNameBytesReceived,
|
kStatsValueNameBytesReceived,
|
||||||
kStatsValueNameBytesSent,
|
kStatsValueNameBytesSent,
|
||||||
kStatsValueNameCodecImplementationName,
|
kStatsValueNameCodecImplementationName,
|
||||||
|
kStatsValueNameConcealedSamples,
|
||||||
kStatsValueNameDataChannelId,
|
kStatsValueNameDataChannelId,
|
||||||
kStatsValueNameFramesDecoded,
|
kStatsValueNameFramesDecoded,
|
||||||
kStatsValueNameFramesEncoded,
|
kStatsValueNameFramesEncoded,
|
||||||
@ -120,6 +121,7 @@ class StatsReport {
|
|||||||
kStatsValueNameState,
|
kStatsValueNameState,
|
||||||
kStatsValueNameTotalAudioEnergy,
|
kStatsValueNameTotalAudioEnergy,
|
||||||
kStatsValueNameTotalSamplesDuration,
|
kStatsValueNameTotalSamplesDuration,
|
||||||
|
kStatsValueNameTotalSamplesReceived,
|
||||||
kStatsValueNameTransportId,
|
kStatsValueNameTransportId,
|
||||||
kStatsValueNameSentPingRequestsTotal,
|
kStatsValueNameSentPingRequestsTotal,
|
||||||
kStatsValueNameSentPingRequestsBeforeFirstResponse,
|
kStatsValueNameSentPingRequestsBeforeFirstResponse,
|
||||||
|
|||||||
@ -194,6 +194,8 @@ webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const {
|
|||||||
auto ns = channel_proxy_->GetNetworkStatistics();
|
auto ns = channel_proxy_->GetNetworkStatistics();
|
||||||
stats.jitter_buffer_ms = ns.currentBufferSize;
|
stats.jitter_buffer_ms = ns.currentBufferSize;
|
||||||
stats.jitter_buffer_preferred_ms = ns.preferredBufferSize;
|
stats.jitter_buffer_preferred_ms = ns.preferredBufferSize;
|
||||||
|
stats.total_samples_received = ns.totalSamplesReceived;
|
||||||
|
stats.concealed_samples = ns.concealedSamples;
|
||||||
stats.expand_rate = Q14ToFloat(ns.currentExpandRate);
|
stats.expand_rate = Q14ToFloat(ns.currentExpandRate);
|
||||||
stats.speech_expand_rate = Q14ToFloat(ns.currentSpeechExpandRate);
|
stats.speech_expand_rate = Q14ToFloat(ns.currentSpeechExpandRate);
|
||||||
stats.secondary_decoded_rate = Q14ToFloat(ns.currentSecondaryDecodedRate);
|
stats.secondary_decoded_rate = Q14ToFloat(ns.currentSecondaryDecodedRate);
|
||||||
|
|||||||
@ -64,8 +64,9 @@ const CallStatistics kCallStats = {
|
|||||||
345, 678, 901, 234, -12, 3456, 7890, 567, 890, 123};
|
345, 678, 901, 234, -12, 3456, 7890, 567, 890, 123};
|
||||||
const CodecInst kCodecInst = {
|
const CodecInst kCodecInst = {
|
||||||
123, "codec_name_recv", 96000, -187, 0, -103};
|
123, "codec_name_recv", 96000, -187, 0, -103};
|
||||||
const NetworkStatistics kNetworkStats = {
|
const NetworkStatistics kNetworkStats = {123, 456, false, 789012, 3456, 0, {},
|
||||||
123, 456, false, 0, {}, 789, 12, 345, 678, 901, 0, -1, -1, -1, -1, -1, 0};
|
789, 12, 345, 678, 901, 0, -1,
|
||||||
|
-1, -1, -1, -1, 0};
|
||||||
const AudioDecodingCallStats kAudioDecodeStats = MakeAudioDecodeStatsForTest();
|
const AudioDecodingCallStats kAudioDecodeStats = MakeAudioDecodeStatsForTest();
|
||||||
|
|
||||||
struct ConfigHelper {
|
struct ConfigHelper {
|
||||||
@ -318,7 +319,9 @@ TEST(AudioReceiveStreamTest, GetStats) {
|
|||||||
stats.delay_estimate_ms);
|
stats.delay_estimate_ms);
|
||||||
EXPECT_EQ(static_cast<int32_t>(kSpeechOutputLevel), stats.audio_level);
|
EXPECT_EQ(static_cast<int32_t>(kSpeechOutputLevel), stats.audio_level);
|
||||||
EXPECT_EQ(kTotalOutputEnergy, stats.total_output_energy);
|
EXPECT_EQ(kTotalOutputEnergy, stats.total_output_energy);
|
||||||
|
EXPECT_EQ(kNetworkStats.totalSamplesReceived, stats.total_samples_received);
|
||||||
EXPECT_EQ(kTotalOutputDuration, stats.total_output_duration);
|
EXPECT_EQ(kTotalOutputDuration, stats.total_output_duration);
|
||||||
|
EXPECT_EQ(kNetworkStats.concealedSamples, stats.concealed_samples);
|
||||||
EXPECT_EQ(Q14ToFloat(kNetworkStats.currentExpandRate), stats.expand_rate);
|
EXPECT_EQ(Q14ToFloat(kNetworkStats.currentExpandRate), stats.expand_rate);
|
||||||
EXPECT_EQ(Q14ToFloat(kNetworkStats.currentSpeechExpandRate),
|
EXPECT_EQ(Q14ToFloat(kNetworkStats.currentSpeechExpandRate),
|
||||||
stats.speech_expand_rate);
|
stats.speech_expand_rate);
|
||||||
|
|||||||
@ -52,7 +52,15 @@ class AudioReceiveStream {
|
|||||||
// See description of "totalAudioEnergy" in the WebRTC stats spec:
|
// See description of "totalAudioEnergy" in the WebRTC stats spec:
|
||||||
// https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-totalaudioenergy
|
// https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-totalaudioenergy
|
||||||
double total_output_energy = 0.0;
|
double total_output_energy = 0.0;
|
||||||
|
// See description of "totalSamplesReceived" in the WebRTC stats spec:
|
||||||
|
// https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-totalsamplesreceived
|
||||||
|
uint64_t total_samples_received = 0;
|
||||||
|
// See description of "totalSamplesDuration" in the WebRTC stats spec:
|
||||||
|
// https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-totalsamplesduration
|
||||||
double total_output_duration = 0.0;
|
double total_output_duration = 0.0;
|
||||||
|
// See description of "concealedSamples" in the WebRTC stats spec:
|
||||||
|
// https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-concealedsamples
|
||||||
|
uint64_t concealed_samples = 0;
|
||||||
float expand_rate = 0.0f;
|
float expand_rate = 0.0f;
|
||||||
float speech_expand_rate = 0.0f;
|
float speech_expand_rate = 0.0f;
|
||||||
float secondary_decoded_rate = 0.0f;
|
float secondary_decoded_rate = 0.0f;
|
||||||
|
|||||||
@ -367,6 +367,13 @@ struct NetworkStatistics {
|
|||||||
uint16_t preferredBufferSize;
|
uint16_t preferredBufferSize;
|
||||||
// adding extra delay due to "peaky jitter"
|
// adding extra delay due to "peaky jitter"
|
||||||
bool jitterPeaksFound;
|
bool jitterPeaksFound;
|
||||||
|
// Total number of audio samples received, including synthesized samples.
|
||||||
|
// https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-totalsamplesreceived
|
||||||
|
uint64_t totalSamplesReceived;
|
||||||
|
// Total number of inbound audio samples that are based on synthesized data to
|
||||||
|
// conceal packet loss.
|
||||||
|
// https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-concealedsamples
|
||||||
|
uint64_t concealedSamples;
|
||||||
// Loss rate (network + late); fraction between 0 and 1, scaled to Q14.
|
// Loss rate (network + late); fraction between 0 and 1, scaled to Q14.
|
||||||
uint16_t currentPacketLossRate;
|
uint16_t currentPacketLossRate;
|
||||||
// Late loss rate; fraction between 0 and 1, scaled to Q14.
|
// Late loss rate; fraction between 0 and 1, scaled to Q14.
|
||||||
|
|||||||
@ -652,7 +652,9 @@ struct VoiceReceiverInfo : public MediaReceiverInfo {
|
|||||||
delay_estimate_ms(0),
|
delay_estimate_ms(0),
|
||||||
audio_level(0),
|
audio_level(0),
|
||||||
total_output_energy(0.0),
|
total_output_energy(0.0),
|
||||||
|
total_samples_received(0),
|
||||||
total_output_duration(0.0),
|
total_output_duration(0.0),
|
||||||
|
concealed_samples(0),
|
||||||
expand_rate(0),
|
expand_rate(0),
|
||||||
speech_expand_rate(0),
|
speech_expand_rate(0),
|
||||||
secondary_decoded_rate(0),
|
secondary_decoded_rate(0),
|
||||||
@ -676,7 +678,15 @@ struct VoiceReceiverInfo : public MediaReceiverInfo {
|
|||||||
// See description of "totalAudioEnergy" in the WebRTC stats spec:
|
// See description of "totalAudioEnergy" in the WebRTC stats spec:
|
||||||
// https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-totalaudioenergy
|
// https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-totalaudioenergy
|
||||||
double total_output_energy;
|
double total_output_energy;
|
||||||
|
// See description of "totalSamplesReceived" in the WebRTC stats spec:
|
||||||
|
// https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-totalsamplesreceived
|
||||||
|
uint64_t total_samples_received;
|
||||||
|
// See description of "totalSamplesDuration" in the WebRTC stats spec:
|
||||||
|
// https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-totalsamplesduration
|
||||||
double total_output_duration;
|
double total_output_duration;
|
||||||
|
// See description of "concealedSamples" in the WebRTC stats spec:
|
||||||
|
// https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-concealedsamples
|
||||||
|
uint64_t concealed_samples;
|
||||||
// fraction of synthesized audio inserted through expansion.
|
// fraction of synthesized audio inserted through expansion.
|
||||||
float expand_rate;
|
float expand_rate;
|
||||||
// fraction of synthesized speech inserted through expansion.
|
// fraction of synthesized speech inserted through expansion.
|
||||||
|
|||||||
@ -2282,7 +2282,9 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
|
|||||||
rinfo.delay_estimate_ms = stats.delay_estimate_ms;
|
rinfo.delay_estimate_ms = stats.delay_estimate_ms;
|
||||||
rinfo.audio_level = stats.audio_level;
|
rinfo.audio_level = stats.audio_level;
|
||||||
rinfo.total_output_energy = stats.total_output_energy;
|
rinfo.total_output_energy = stats.total_output_energy;
|
||||||
|
rinfo.total_samples_received = stats.total_samples_received;
|
||||||
rinfo.total_output_duration = stats.total_output_duration;
|
rinfo.total_output_duration = stats.total_output_duration;
|
||||||
|
rinfo.concealed_samples = stats.concealed_samples;
|
||||||
rinfo.expand_rate = stats.expand_rate;
|
rinfo.expand_rate = stats.expand_rate;
|
||||||
rinfo.speech_expand_rate = stats.speech_expand_rate;
|
rinfo.speech_expand_rate = stats.speech_expand_rate;
|
||||||
rinfo.secondary_decoded_rate = stats.secondary_decoded_rate;
|
rinfo.secondary_decoded_rate = stats.secondary_decoded_rate;
|
||||||
|
|||||||
@ -596,6 +596,8 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
|
|||||||
stats.jitter_buffer_preferred_ms = 567;
|
stats.jitter_buffer_preferred_ms = 567;
|
||||||
stats.delay_estimate_ms = 890;
|
stats.delay_estimate_ms = 890;
|
||||||
stats.audio_level = 1234;
|
stats.audio_level = 1234;
|
||||||
|
stats.total_samples_received = 5678901;
|
||||||
|
stats.concealed_samples = 234;
|
||||||
stats.expand_rate = 5.67f;
|
stats.expand_rate = 5.67f;
|
||||||
stats.speech_expand_rate = 8.90f;
|
stats.speech_expand_rate = 8.90f;
|
||||||
stats.secondary_decoded_rate = 1.23f;
|
stats.secondary_decoded_rate = 1.23f;
|
||||||
@ -632,6 +634,8 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
|
|||||||
stats.jitter_buffer_preferred_ms);
|
stats.jitter_buffer_preferred_ms);
|
||||||
EXPECT_EQ(info.delay_estimate_ms, stats.delay_estimate_ms);
|
EXPECT_EQ(info.delay_estimate_ms, stats.delay_estimate_ms);
|
||||||
EXPECT_EQ(info.audio_level, stats.audio_level);
|
EXPECT_EQ(info.audio_level, stats.audio_level);
|
||||||
|
EXPECT_EQ(info.total_samples_received, stats.total_samples_received);
|
||||||
|
EXPECT_EQ(info.concealed_samples, stats.concealed_samples);
|
||||||
EXPECT_EQ(info.expand_rate, stats.expand_rate);
|
EXPECT_EQ(info.expand_rate, stats.expand_rate);
|
||||||
EXPECT_EQ(info.speech_expand_rate, stats.speech_expand_rate);
|
EXPECT_EQ(info.speech_expand_rate, stats.speech_expand_rate);
|
||||||
EXPECT_EQ(info.secondary_decoded_rate, stats.secondary_decoded_rate);
|
EXPECT_EQ(info.secondary_decoded_rate, stats.secondary_decoded_rate);
|
||||||
|
|||||||
@ -332,6 +332,10 @@ void AcmReceiver::GetNetworkStatistics(NetworkStatistics* acm_stat) {
|
|||||||
acm_stat->medianWaitingTimeMs = neteq_stat.median_waiting_time_ms;
|
acm_stat->medianWaitingTimeMs = neteq_stat.median_waiting_time_ms;
|
||||||
acm_stat->minWaitingTimeMs = neteq_stat.min_waiting_time_ms;
|
acm_stat->minWaitingTimeMs = neteq_stat.min_waiting_time_ms;
|
||||||
acm_stat->maxWaitingTimeMs = neteq_stat.max_waiting_time_ms;
|
acm_stat->maxWaitingTimeMs = neteq_stat.max_waiting_time_ms;
|
||||||
|
|
||||||
|
NetEqLifetimeStatistics neteq_lifetime_stat = neteq_->GetLifetimeStatistics();
|
||||||
|
acm_stat->totalSamplesReceived = neteq_lifetime_stat.total_samples_received;
|
||||||
|
acm_stat->concealedSamples = neteq_lifetime_stat.concealed_samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
int AcmReceiver::DecoderByPayloadType(uint8_t payload_type,
|
int AcmReceiver::DecoderByPayloadType(uint8_t payload_type,
|
||||||
|
|||||||
@ -58,6 +58,18 @@ struct NetEqNetworkStatistics {
|
|||||||
int max_waiting_time_ms;
|
int max_waiting_time_ms;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// NetEq statistics that persist over the lifetime of the class.
|
||||||
|
// These metrics are never reset.
|
||||||
|
struct NetEqLifetimeStatistics {
|
||||||
|
// Total number of audio samples received, including synthesized samples.
|
||||||
|
// https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-totalsamplesreceived
|
||||||
|
uint64_t total_samples_received = 0;
|
||||||
|
// Total number of inbound audio samples that are based on synthesized data to
|
||||||
|
// conceal packet loss.
|
||||||
|
// https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-concealedsamples
|
||||||
|
uint64_t concealed_samples = 0;
|
||||||
|
};
|
||||||
|
|
||||||
enum NetEqPlayoutMode {
|
enum NetEqPlayoutMode {
|
||||||
kPlayoutOn,
|
kPlayoutOn,
|
||||||
kPlayoutOff,
|
kPlayoutOff,
|
||||||
@ -220,6 +232,10 @@ class NetEq {
|
|||||||
// after the call.
|
// after the call.
|
||||||
virtual int NetworkStatistics(NetEqNetworkStatistics* stats) = 0;
|
virtual int NetworkStatistics(NetEqNetworkStatistics* stats) = 0;
|
||||||
|
|
||||||
|
// Returns a copy of this class's lifetime statistics. These statistics are
|
||||||
|
// never reset.
|
||||||
|
virtual NetEqLifetimeStatistics GetLifetimeStatistics() const = 0;
|
||||||
|
|
||||||
// Writes the current RTCP statistics to |stats|. The statistics are reset
|
// Writes the current RTCP statistics to |stats|. The statistics are reset
|
||||||
// and a new report period is started with the call.
|
// and a new report period is started with the call.
|
||||||
virtual void GetRtcpStatistics(RtcpStatistics* stats) = 0;
|
virtual void GetRtcpStatistics(RtcpStatistics* stats) = 0;
|
||||||
|
|||||||
@ -380,6 +380,11 @@ int NetEqImpl::NetworkStatistics(NetEqNetworkStatistics* stats) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetEqLifetimeStatistics NetEqImpl::GetLifetimeStatistics() const {
|
||||||
|
rtc::CritScope lock(&crit_sect_);
|
||||||
|
return stats_.GetLifetimeStatistics();
|
||||||
|
}
|
||||||
|
|
||||||
void NetEqImpl::GetRtcpStatistics(RtcpStatistics* stats) {
|
void NetEqImpl::GetRtcpStatistics(RtcpStatistics* stats) {
|
||||||
rtc::CritScope lock(&crit_sect_);
|
rtc::CritScope lock(&crit_sect_);
|
||||||
if (stats) {
|
if (stats) {
|
||||||
|
|||||||
@ -185,6 +185,8 @@ class NetEqImpl : public webrtc::NetEq {
|
|||||||
// and a new report period is started with the call.
|
// and a new report period is started with the call.
|
||||||
void GetRtcpStatistics(RtcpStatistics* stats) override;
|
void GetRtcpStatistics(RtcpStatistics* stats) override;
|
||||||
|
|
||||||
|
NetEqLifetimeStatistics GetLifetimeStatistics() const override;
|
||||||
|
|
||||||
// Same as RtcpStatistics(), but does not reset anything.
|
// Same as RtcpStatistics(), but does not reset anything.
|
||||||
void GetRtcpStatisticsNoReset(RtcpStatistics* stats) override;
|
void GetRtcpStatisticsNoReset(RtcpStatistics* stats) override;
|
||||||
|
|
||||||
|
|||||||
@ -153,24 +153,29 @@ void StatisticsCalculator::ResetMcu() {
|
|||||||
|
|
||||||
void StatisticsCalculator::ExpandedVoiceSamples(size_t num_samples) {
|
void StatisticsCalculator::ExpandedVoiceSamples(size_t num_samples) {
|
||||||
expanded_speech_samples_ += num_samples;
|
expanded_speech_samples_ += num_samples;
|
||||||
|
lifetime_stats_.concealed_samples += num_samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatisticsCalculator::ExpandedNoiseSamples(size_t num_samples) {
|
void StatisticsCalculator::ExpandedNoiseSamples(size_t num_samples) {
|
||||||
expanded_noise_samples_ += num_samples;
|
expanded_noise_samples_ += num_samples;
|
||||||
|
lifetime_stats_.concealed_samples += num_samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatisticsCalculator::ExpandedVoiceSamplesCorrection(int num_samples) {
|
void StatisticsCalculator::ExpandedVoiceSamplesCorrection(int num_samples) {
|
||||||
expanded_speech_samples_ =
|
expanded_speech_samples_ =
|
||||||
AddIntToSizeTWithLowerCap(num_samples, expanded_speech_samples_);
|
AddIntToSizeTWithLowerCap(num_samples, expanded_speech_samples_);
|
||||||
|
lifetime_stats_.concealed_samples += num_samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatisticsCalculator::ExpandedNoiseSamplesCorrection(int num_samples) {
|
void StatisticsCalculator::ExpandedNoiseSamplesCorrection(int num_samples) {
|
||||||
expanded_noise_samples_ =
|
expanded_noise_samples_ =
|
||||||
AddIntToSizeTWithLowerCap(num_samples, expanded_noise_samples_);
|
AddIntToSizeTWithLowerCap(num_samples, expanded_noise_samples_);
|
||||||
|
lifetime_stats_.concealed_samples += num_samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatisticsCalculator::PreemptiveExpandedSamples(size_t num_samples) {
|
void StatisticsCalculator::PreemptiveExpandedSamples(size_t num_samples) {
|
||||||
preemptive_samples_ += num_samples;
|
preemptive_samples_ += num_samples;
|
||||||
|
lifetime_stats_.concealed_samples += num_samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatisticsCalculator::AcceleratedSamples(size_t num_samples) {
|
void StatisticsCalculator::AcceleratedSamples(size_t num_samples) {
|
||||||
@ -205,6 +210,7 @@ void StatisticsCalculator::IncreaseCounter(size_t num_samples, int fs_hz) {
|
|||||||
timestamps_since_last_report_ = 0;
|
timestamps_since_last_report_ = 0;
|
||||||
discarded_packets_ = 0;
|
discarded_packets_ = 0;
|
||||||
}
|
}
|
||||||
|
lifetime_stats_.total_samples_received += num_samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatisticsCalculator::SecondaryDecodedSamples(int num_samples) {
|
void StatisticsCalculator::SecondaryDecodedSamples(int num_samples) {
|
||||||
@ -307,6 +313,10 @@ void StatisticsCalculator::GetNetworkStatistics(
|
|||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetEqLifetimeStatistics StatisticsCalculator::GetLifetimeStatistics() const {
|
||||||
|
return lifetime_stats_;
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t StatisticsCalculator::CalculateQ14Ratio(size_t numerator,
|
uint16_t StatisticsCalculator::CalculateQ14Ratio(size_t numerator,
|
||||||
uint32_t denominator) {
|
uint32_t denominator) {
|
||||||
if (numerator == 0) {
|
if (numerator == 0) {
|
||||||
|
|||||||
@ -99,6 +99,10 @@ class StatisticsCalculator {
|
|||||||
const DecisionLogic& decision_logic,
|
const DecisionLogic& decision_logic,
|
||||||
NetEqNetworkStatistics *stats);
|
NetEqNetworkStatistics *stats);
|
||||||
|
|
||||||
|
// Returns a copy of this class's lifetime statistics. These statistics are
|
||||||
|
// never reset.
|
||||||
|
NetEqLifetimeStatistics GetLifetimeStatistics() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const int kMaxReportPeriod = 60; // Seconds before auto-reset.
|
static const int kMaxReportPeriod = 60; // Seconds before auto-reset.
|
||||||
static const size_t kLenWaitingTimes = 100;
|
static const size_t kLenWaitingTimes = 100;
|
||||||
@ -158,6 +162,8 @@ class StatisticsCalculator {
|
|||||||
// Calculates numerator / denominator, and returns the value in Q14.
|
// Calculates numerator / denominator, and returns the value in Q14.
|
||||||
static uint16_t CalculateQ14Ratio(size_t numerator, uint32_t denominator);
|
static uint16_t CalculateQ14Ratio(size_t numerator, uint32_t denominator);
|
||||||
|
|
||||||
|
// TODO(steveanton): Add unit tests for the lifetime stats.
|
||||||
|
NetEqLifetimeStatistics lifetime_stats_;
|
||||||
size_t preemptive_samples_;
|
size_t preemptive_samples_;
|
||||||
size_t accelerate_samples_;
|
size_t accelerate_samples_;
|
||||||
size_t added_zero_samples_;
|
size_t added_zero_samples_;
|
||||||
|
|||||||
@ -525,6 +525,18 @@ class RTCStatsReportVerifier {
|
|||||||
verifier.MarkMemberTested(
|
verifier.MarkMemberTested(
|
||||||
media_stream_track.echo_return_loss_enhancement, true);
|
media_stream_track.echo_return_loss_enhancement, true);
|
||||||
}
|
}
|
||||||
|
// totalSamplesReceived and concealedSamples are only present on inbound
|
||||||
|
// audio tracks.
|
||||||
|
if (*media_stream_track.kind == RTCMediaStreamTrackKind::kAudio &&
|
||||||
|
*media_stream_track.remote_source) {
|
||||||
|
verifier.TestMemberIsNonNegative<uint64_t>(
|
||||||
|
media_stream_track.total_samples_received);
|
||||||
|
verifier.TestMemberIsNonNegative<uint64_t>(
|
||||||
|
media_stream_track.concealed_samples);
|
||||||
|
} else {
|
||||||
|
verifier.TestMemberIsUndefined(media_stream_track.total_samples_received);
|
||||||
|
verifier.TestMemberIsUndefined(media_stream_track.concealed_samples);
|
||||||
|
}
|
||||||
return verifier.ExpectAllMembersSuccessfullyTested();
|
return verifier.ExpectAllMembersSuccessfullyTested();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -424,8 +424,11 @@ ProduceMediaStreamTrackStatsFromVoiceReceiverInfo(
|
|||||||
}
|
}
|
||||||
audio_track_stats->total_audio_energy =
|
audio_track_stats->total_audio_energy =
|
||||||
voice_receiver_info.total_output_energy;
|
voice_receiver_info.total_output_energy;
|
||||||
|
audio_track_stats->total_samples_received =
|
||||||
|
voice_receiver_info.total_samples_received;
|
||||||
audio_track_stats->total_samples_duration =
|
audio_track_stats->total_samples_duration =
|
||||||
voice_receiver_info.total_output_duration;
|
voice_receiver_info.total_output_duration;
|
||||||
|
audio_track_stats->concealed_samples = voice_receiver_info.concealed_samples;
|
||||||
return audio_track_stats;
|
return audio_track_stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1554,7 +1554,9 @@ TEST_F(RTCStatsCollectorTest,
|
|||||||
voice_receiver_info.local_stats[0].ssrc = 3;
|
voice_receiver_info.local_stats[0].ssrc = 3;
|
||||||
voice_receiver_info.audio_level = 16383;
|
voice_receiver_info.audio_level = 16383;
|
||||||
voice_receiver_info.total_output_energy = 0.125;
|
voice_receiver_info.total_output_energy = 0.125;
|
||||||
|
voice_receiver_info.total_samples_received = 4567;
|
||||||
voice_receiver_info.total_output_duration = 0.25;
|
voice_receiver_info.total_output_duration = 0.25;
|
||||||
|
voice_receiver_info.concealed_samples = 123;
|
||||||
|
|
||||||
test_->CreateMockRtpSendersReceiversAndChannels(
|
test_->CreateMockRtpSendersReceiversAndChannels(
|
||||||
{ std::make_pair(local_audio_track.get(), voice_sender_info_ssrc1),
|
{ std::make_pair(local_audio_track.get(), voice_sender_info_ssrc1),
|
||||||
@ -1628,7 +1630,9 @@ TEST_F(RTCStatsCollectorTest,
|
|||||||
expected_remote_audio_track.detached = false;
|
expected_remote_audio_track.detached = false;
|
||||||
expected_remote_audio_track.audio_level = 16383.0 / 32767.0;
|
expected_remote_audio_track.audio_level = 16383.0 / 32767.0;
|
||||||
expected_remote_audio_track.total_audio_energy = 0.125;
|
expected_remote_audio_track.total_audio_energy = 0.125;
|
||||||
|
expected_remote_audio_track.total_samples_received = 4567;
|
||||||
expected_remote_audio_track.total_samples_duration = 0.25;
|
expected_remote_audio_track.total_samples_duration = 0.25;
|
||||||
|
expected_remote_audio_track.concealed_samples = 123;
|
||||||
ASSERT_TRUE(report->Get(expected_remote_audio_track.id()));
|
ASSERT_TRUE(report->Get(expected_remote_audio_track.id()));
|
||||||
EXPECT_EQ(expected_remote_audio_track,
|
EXPECT_EQ(expected_remote_audio_track,
|
||||||
report->Get(expected_remote_audio_track.id())->cast_to<
|
report->Get(expected_remote_audio_track.id())->cast_to<
|
||||||
|
|||||||
@ -379,9 +379,11 @@ WEBRTC_RTCSTATS_IMPL(RTCMediaStreamTrackStats, RTCStats, "track",
|
|||||||
&full_frames_lost,
|
&full_frames_lost,
|
||||||
&audio_level,
|
&audio_level,
|
||||||
&total_audio_energy,
|
&total_audio_energy,
|
||||||
&total_samples_duration,
|
|
||||||
&echo_return_loss,
|
&echo_return_loss,
|
||||||
&echo_return_loss_enhancement);
|
&echo_return_loss_enhancement,
|
||||||
|
&total_samples_received,
|
||||||
|
&total_samples_duration,
|
||||||
|
&concealed_samples);
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
RTCMediaStreamTrackStats::RTCMediaStreamTrackStats(
|
RTCMediaStreamTrackStats::RTCMediaStreamTrackStats(
|
||||||
@ -410,9 +412,11 @@ RTCMediaStreamTrackStats::RTCMediaStreamTrackStats(std::string&& id,
|
|||||||
full_frames_lost("fullFramesLost"),
|
full_frames_lost("fullFramesLost"),
|
||||||
audio_level("audioLevel"),
|
audio_level("audioLevel"),
|
||||||
total_audio_energy("totalAudioEnergy"),
|
total_audio_energy("totalAudioEnergy"),
|
||||||
total_samples_duration("totalSamplesDuration"),
|
|
||||||
echo_return_loss("echoReturnLoss"),
|
echo_return_loss("echoReturnLoss"),
|
||||||
echo_return_loss_enhancement("echoReturnLossEnhancement") {
|
echo_return_loss_enhancement("echoReturnLossEnhancement"),
|
||||||
|
total_samples_received("totalSamplesReceived"),
|
||||||
|
total_samples_duration("totalSamplesDuration"),
|
||||||
|
concealed_samples("concealedSamples") {
|
||||||
RTC_DCHECK(kind == RTCMediaStreamTrackKind::kAudio ||
|
RTC_DCHECK(kind == RTCMediaStreamTrackKind::kAudio ||
|
||||||
kind == RTCMediaStreamTrackKind::kVideo);
|
kind == RTCMediaStreamTrackKind::kVideo);
|
||||||
}
|
}
|
||||||
@ -437,9 +441,11 @@ RTCMediaStreamTrackStats::RTCMediaStreamTrackStats(
|
|||||||
full_frames_lost(other.full_frames_lost),
|
full_frames_lost(other.full_frames_lost),
|
||||||
audio_level(other.audio_level),
|
audio_level(other.audio_level),
|
||||||
total_audio_energy(other.total_audio_energy),
|
total_audio_energy(other.total_audio_energy),
|
||||||
total_samples_duration(other.total_samples_duration),
|
|
||||||
echo_return_loss(other.echo_return_loss),
|
echo_return_loss(other.echo_return_loss),
|
||||||
echo_return_loss_enhancement(other.echo_return_loss_enhancement) {}
|
echo_return_loss_enhancement(other.echo_return_loss_enhancement),
|
||||||
|
total_samples_received(other.total_samples_received),
|
||||||
|
total_samples_duration(other.total_samples_duration),
|
||||||
|
concealed_samples(other.concealed_samples) {}
|
||||||
|
|
||||||
RTCMediaStreamTrackStats::~RTCMediaStreamTrackStats() {
|
RTCMediaStreamTrackStats::~RTCMediaStreamTrackStats() {
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user