Expose delayed packet outage as a cumulative metric of samples in the new getStats API.

The stat will be exposed through origin trial described in:
https://docs.google.com/document/d/1stYIZhEmDZ7NJF9gjjsM66eLFJUdc-14a3QutrFbIwI

Change-Id: Ib191a11c6bd9e617abbe9dd82239b0c5b4e6b4e0
Bug: webrtc:10043
Reviewed-on: https://webrtc-review.googlesource.com/c/111922
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Ivo Creusen <ivoc@webrtc.org>
Reviewed-by: Henrik Lundin <henrik.lundin@webrtc.org>
Reviewed-by: Minyue Li <minyue@webrtc.org>
Commit-Queue: Jakob Ivarsson‎ <jakobi@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#25802}
This commit is contained in:
Jakob Ivarsson
2018-11-27 12:52:16 +01:00
committed by Commit Bot
parent 59cfd35438
commit 352ce5c419
16 changed files with 49 additions and 25 deletions

View File

@ -309,8 +309,9 @@ class RTC_EXPORT RTCMediaStreamTrackStats final : public RTCStats {
RTCStatsMember<uint64_t> concealed_samples; RTCStatsMember<uint64_t> concealed_samples;
RTCStatsMember<uint64_t> concealment_events; RTCStatsMember<uint64_t> concealment_events;
// Non-standard audio-only member // Non-standard audio-only member
// TODO(kuddai): Add descriptoin to standard. crbug.com/webrtc/10042 // TODO(kuddai): Add description to standard. crbug.com/webrtc/10042
RTCNonStandardStatsMember<uint64_t> jitter_buffer_flushes; RTCNonStandardStatsMember<uint64_t> jitter_buffer_flushes;
RTCNonStandardStatsMember<uint64_t> delayed_packet_outage_samples;
}; };
// https://w3c.github.io/webrtc-stats/#pcstats-dict* // https://w3c.github.io/webrtc-stats/#pcstats-dict*

View File

@ -214,6 +214,7 @@ webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const {
stats.accelerate_rate = Q14ToFloat(ns.currentAccelerateRate); stats.accelerate_rate = Q14ToFloat(ns.currentAccelerateRate);
stats.preemptive_expand_rate = Q14ToFloat(ns.currentPreemptiveRate); stats.preemptive_expand_rate = Q14ToFloat(ns.currentPreemptiveRate);
stats.jitter_buffer_flushes = ns.packetBufferFlushes; stats.jitter_buffer_flushes = ns.packetBufferFlushes;
stats.delayed_packet_outage_samples = ns.delayedPacketOutageSamples;
auto ds = channel_receive_->GetDecodingCallStatistics(); auto ds = channel_receive_->GetDecodingCallStatistics();
stats.decoding_calls_to_silence_generator = ds.calls_to_silence_generator; stats.decoding_calls_to_silence_generator = ds.calls_to_silence_generator;

View File

@ -63,6 +63,7 @@ class AudioReceiveStream {
float secondary_discarded_rate = 0.0f; float secondary_discarded_rate = 0.0f;
float accelerate_rate = 0.0f; float accelerate_rate = 0.0f;
float preemptive_expand_rate = 0.0f; float preemptive_expand_rate = 0.0f;
uint64_t delayed_packet_outage_samples = 0;
int32_t decoding_calls_to_silence_generator = 0; int32_t decoding_calls_to_silence_generator = 0;
int32_t decoding_calls_to_neteq = 0; int32_t decoding_calls_to_neteq = 0;
int32_t decoding_normal = 0; int32_t decoding_normal = 0;

View File

@ -478,6 +478,8 @@ struct VoiceReceiverInfo : public MediaReceiverInfo {
int64_t capture_start_ntp_time_ms = -1; int64_t capture_start_ntp_time_ms = -1;
// Count of the number of buffer flushes. // Count of the number of buffer flushes.
uint64_t jitter_buffer_flushes = 0; uint64_t jitter_buffer_flushes = 0;
// Number of samples expanded due to delayed packets.
uint64_t delayed_packet_outage_samples = 0;
}; };
struct VideoSenderInfo : public MediaSenderInfo { struct VideoSenderInfo : public MediaSenderInfo {

View File

@ -2233,6 +2233,7 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
rinfo.secondary_discarded_rate = stats.secondary_discarded_rate; rinfo.secondary_discarded_rate = stats.secondary_discarded_rate;
rinfo.accelerate_rate = stats.accelerate_rate; rinfo.accelerate_rate = stats.accelerate_rate;
rinfo.preemptive_expand_rate = stats.preemptive_expand_rate; rinfo.preemptive_expand_rate = stats.preemptive_expand_rate;
rinfo.delayed_packet_outage_samples = stats.delayed_packet_outage_samples;
rinfo.decoding_calls_to_silence_generator = rinfo.decoding_calls_to_silence_generator =
stats.decoding_calls_to_silence_generator; stats.decoding_calls_to_silence_generator;
rinfo.decoding_calls_to_neteq = stats.decoding_calls_to_neteq; rinfo.decoding_calls_to_neteq = stats.decoding_calls_to_neteq;

View File

@ -345,6 +345,8 @@ void AcmReceiver::GetNetworkStatistics(NetworkStatistics* acm_stat) {
acm_stat->concealedSamples = neteq_lifetime_stat.concealed_samples; acm_stat->concealedSamples = neteq_lifetime_stat.concealed_samples;
acm_stat->concealmentEvents = neteq_lifetime_stat.concealment_events; acm_stat->concealmentEvents = neteq_lifetime_stat.concealment_events;
acm_stat->jitterBufferDelayMs = neteq_lifetime_stat.jitter_buffer_delay_ms; acm_stat->jitterBufferDelayMs = neteq_lifetime_stat.jitter_buffer_delay_ms;
acm_stat->delayedPacketOutageSamples =
neteq_lifetime_stat.delayed_packet_outage_samples;
NetEqOperationsAndState neteq_operations_and_state = NetEqOperationsAndState neteq_operations_and_state =
neteq_->GetOperationsAndState(); neteq_->GetOperationsAndState();

View File

@ -119,6 +119,8 @@ struct NetworkStatistics {
size_t addedSamples; size_t addedSamples;
// count of the number of buffer flushes // count of the number of buffer flushes
uint64_t packetBufferFlushes; uint64_t packetBufferFlushes;
// number of samples expanded due to delayed packets
uint64_t delayedPacketOutageSamples;
}; };
} // namespace webrtc } // namespace webrtc

View File

@ -323,8 +323,7 @@ void Expand::SetParametersForNormalAfterExpand() {
current_lag_index_ = 0; current_lag_index_ = 0;
lag_index_direction_ = 0; lag_index_direction_ = 0;
stop_muting_ = true; // Do not mute signal any more. stop_muting_ = true; // Do not mute signal any more.
statistics_->LogDelayedPacketOutageEvent( statistics_->LogDelayedPacketOutageEvent(expand_duration_samples_, fs_hz_);
rtc::dchecked_cast<int>(expand_duration_samples_) / (fs_hz_ / 1000));
} }
void Expand::SetParametersForMergeAfterExpand() { void Expand::SetParametersForMergeAfterExpand() {

View File

@ -51,14 +51,16 @@ TEST(Expand, CreateUsingFactory) {
namespace { namespace {
class FakeStatisticsCalculator : public StatisticsCalculator { class FakeStatisticsCalculator : public StatisticsCalculator {
public: public:
void LogDelayedPacketOutageEvent(int outage_duration_ms) override { void LogDelayedPacketOutageEvent(int num_samples, int fs_hz) override {
last_outage_duration_ms_ = outage_duration_ms; last_outage_duration_samples_ = num_samples;
} }
int last_outage_duration_ms() const { return last_outage_duration_ms_; } int last_outage_duration_samples() const {
return last_outage_duration_samples_;
}
private: private:
int last_outage_duration_ms_ = 0; int last_outage_duration_samples_ = 0;
}; };
// This is the same size that is given to the SyncBuffer object in NetEq. // This is the same size that is given to the SyncBuffer object in NetEq.
@ -120,13 +122,12 @@ TEST_F(ExpandTest, DelayedPacketOutage) {
EXPECT_EQ(0, expand_.Process(&output)); EXPECT_EQ(0, expand_.Process(&output));
EXPECT_GT(output.Size(), 0u); EXPECT_GT(output.Size(), 0u);
sum_output_len_samples += output.Size(); sum_output_len_samples += output.Size();
EXPECT_EQ(0, statistics_.last_outage_duration_ms()); EXPECT_EQ(0, statistics_.last_outage_duration_samples());
} }
expand_.SetParametersForNormalAfterExpand(); expand_.SetParametersForNormalAfterExpand();
// Convert |sum_output_len_samples| to milliseconds. // Convert |sum_output_len_samples| to milliseconds.
EXPECT_EQ(rtc::checked_cast<int>(sum_output_len_samples / EXPECT_EQ(rtc::checked_cast<int>(sum_output_len_samples),
(test_sample_rate_hz_ / 1000)), statistics_.last_outage_duration_samples());
statistics_.last_outage_duration_ms());
} }
// This test is similar to DelayedPacketOutage, but ends by calling // This test is similar to DelayedPacketOutage, but ends by calling
@ -140,10 +141,10 @@ TEST_F(ExpandTest, LostPacketOutage) {
EXPECT_EQ(0, expand_.Process(&output)); EXPECT_EQ(0, expand_.Process(&output));
EXPECT_GT(output.Size(), 0u); EXPECT_GT(output.Size(), 0u);
sum_output_len_samples += output.Size(); sum_output_len_samples += output.Size();
EXPECT_EQ(0, statistics_.last_outage_duration_ms()); EXPECT_EQ(0, statistics_.last_outage_duration_samples());
} }
expand_.SetParametersForMergeAfterExpand(); expand_.SetParametersForMergeAfterExpand();
EXPECT_EQ(0, statistics_.last_outage_duration_ms()); EXPECT_EQ(0, statistics_.last_outage_duration_samples());
} }
// This test is similar to the DelayedPacketOutage test above, but with the // This test is similar to the DelayedPacketOutage test above, but with the
@ -161,13 +162,12 @@ TEST_F(ExpandTest, CheckOutageStatsAfterReset) {
expand_.Reset(); expand_.Reset();
sum_output_len_samples = 0; sum_output_len_samples = 0;
} }
EXPECT_EQ(0, statistics_.last_outage_duration_ms()); EXPECT_EQ(0, statistics_.last_outage_duration_samples());
} }
expand_.SetParametersForNormalAfterExpand(); expand_.SetParametersForNormalAfterExpand();
// Convert |sum_output_len_samples| to milliseconds. // Convert |sum_output_len_samples| to milliseconds.
EXPECT_EQ(rtc::checked_cast<int>(sum_output_len_samples / EXPECT_EQ(rtc::checked_cast<int>(sum_output_len_samples),
(test_sample_rate_hz_ / 1000)), statistics_.last_outage_duration_samples());
statistics_.last_outage_duration_ms());
} }
namespace { namespace {

View File

@ -72,6 +72,7 @@ struct NetEqLifetimeStatistics {
uint64_t jitter_buffer_delay_ms = 0; uint64_t jitter_buffer_delay_ms = 0;
// Below stat is not part of the spec. // Below stat is not part of the spec.
uint64_t voice_concealed_samples = 0; uint64_t voice_concealed_samples = 0;
uint64_t delayed_packet_outage_samples = 0;
}; };
// Metrics that describe the operations performed in NetEq, and the internal // Metrics that describe the operations performed in NetEq, and the internal

View File

@ -257,11 +257,14 @@ void StatisticsCalculator::FlushedPacketBuffer() {
buffer_full_counter_.RegisterSample(); buffer_full_counter_.RegisterSample();
} }
void StatisticsCalculator::LogDelayedPacketOutageEvent(int outage_duration_ms) { void StatisticsCalculator::LogDelayedPacketOutageEvent(int num_samples,
int fs_hz) {
int outage_duration_ms = num_samples / (fs_hz / 1000);
RTC_HISTOGRAM_COUNTS("WebRTC.Audio.DelayedPacketOutageEventMs", RTC_HISTOGRAM_COUNTS("WebRTC.Audio.DelayedPacketOutageEventMs",
outage_duration_ms, 1 /* min */, 2000 /* max */, outage_duration_ms, 1 /* min */, 2000 /* max */,
100 /* bucket count */); 100 /* bucket count */);
delayed_packet_outage_counter_.RegisterSample(); delayed_packet_outage_counter_.RegisterSample();
lifetime_stats_.delayed_packet_outage_samples += num_samples;
} }
void StatisticsCalculator::StoreWaitingTime(int waiting_time_ms) { void StatisticsCalculator::StoreWaitingTime(int waiting_time_ms) {

View File

@ -86,10 +86,10 @@ class StatisticsCalculator {
// Rerport that the packet buffer was flushed. // Rerport that the packet buffer was flushed.
void FlushedPacketBuffer(); void FlushedPacketBuffer();
// Logs a delayed packet outage event of |outage_duration_ms|. A delayed // Logs a delayed packet outage event of |num_samples| expanded at a sample
// packet outage event is defined as an expand period caused not by an actual // rate of |fs_hz|. A delayed packet outage event is defined as an expand
// packet loss, but by a delayed packet. // period caused not by an actual packet loss, but by a delayed packet.
virtual void LogDelayedPacketOutageEvent(int outage_duration_ms); virtual void LogDelayedPacketOutageEvent(int num_samples, int fs_hz);
// Returns the current network statistics in |stats|. The current sample rate // Returns the current network statistics in |stats|. The current sample rate
// is |fs_hz|, the total number of samples in packet buffer and sync buffer // is |fs_hz|, the total number of samples in packet buffer and sync buffer

View File

@ -606,12 +606,16 @@ class RTCStatsReportVerifier {
media_stream_track.concealment_events); media_stream_track.concealment_events);
verifier.TestMemberIsNonNegative<uint64_t>( verifier.TestMemberIsNonNegative<uint64_t>(
media_stream_track.jitter_buffer_flushes); media_stream_track.jitter_buffer_flushes);
verifier.TestMemberIsNonNegative<uint64_t>(
media_stream_track.delayed_packet_outage_samples);
} else { } else {
verifier.TestMemberIsUndefined(media_stream_track.jitter_buffer_delay); verifier.TestMemberIsUndefined(media_stream_track.jitter_buffer_delay);
verifier.TestMemberIsUndefined(media_stream_track.total_samples_received); verifier.TestMemberIsUndefined(media_stream_track.total_samples_received);
verifier.TestMemberIsUndefined(media_stream_track.concealed_samples); verifier.TestMemberIsUndefined(media_stream_track.concealed_samples);
verifier.TestMemberIsUndefined(media_stream_track.concealment_events); verifier.TestMemberIsUndefined(media_stream_track.concealment_events);
verifier.TestMemberIsUndefined(media_stream_track.jitter_buffer_flushes); verifier.TestMemberIsUndefined(media_stream_track.jitter_buffer_flushes);
verifier.TestMemberIsUndefined(
media_stream_track.delayed_packet_outage_samples);
} }
return verifier.ExpectAllMembersSuccessfullyTested(); return verifier.ExpectAllMembersSuccessfullyTested();
} }

View File

@ -456,6 +456,8 @@ ProduceMediaStreamTrackStatsFromVoiceReceiverInfo(
voice_receiver_info.concealment_events; voice_receiver_info.concealment_events;
audio_track_stats->jitter_buffer_flushes = audio_track_stats->jitter_buffer_flushes =
voice_receiver_info.jitter_buffer_flushes; voice_receiver_info.jitter_buffer_flushes;
audio_track_stats->delayed_packet_outage_samples =
voice_receiver_info.delayed_packet_outage_samples;
return audio_track_stats; return audio_track_stats;
} }

View File

@ -1427,6 +1427,7 @@ TEST_F(RTCStatsCollectorTest,
voice_receiver_info.concealment_events = 12; voice_receiver_info.concealment_events = 12;
voice_receiver_info.jitter_buffer_delay_seconds = 3456; voice_receiver_info.jitter_buffer_delay_seconds = 3456;
voice_receiver_info.jitter_buffer_flushes = 7; voice_receiver_info.jitter_buffer_flushes = 7;
voice_receiver_info.delayed_packet_outage_samples = 15;
stats_->CreateMockRtpSendersReceiversAndChannels( stats_->CreateMockRtpSendersReceiversAndChannels(
{}, {std::make_pair(remote_audio_track.get(), voice_receiver_info)}, {}, {}, {std::make_pair(remote_audio_track.get(), voice_receiver_info)}, {},
@ -1461,6 +1462,7 @@ TEST_F(RTCStatsCollectorTest,
expected_remote_audio_track.concealment_events = 12; expected_remote_audio_track.concealment_events = 12;
expected_remote_audio_track.jitter_buffer_delay = 3456; expected_remote_audio_track.jitter_buffer_delay = 3456;
expected_remote_audio_track.jitter_buffer_flushes = 7; expected_remote_audio_track.jitter_buffer_flushes = 7;
expected_remote_audio_track.delayed_packet_outage_samples = 15;
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()) report->Get(expected_remote_audio_track.id())

View File

@ -375,7 +375,8 @@ WEBRTC_RTCSTATS_IMPL(RTCMediaStreamTrackStats, RTCStats, "track",
&total_samples_duration, &total_samples_duration,
&concealed_samples, &concealed_samples,
&concealment_events, &concealment_events,
&jitter_buffer_flushes); &jitter_buffer_flushes,
&delayed_packet_outage_samples);
// clang-format on // clang-format on
RTCMediaStreamTrackStats::RTCMediaStreamTrackStats(const std::string& id, RTCMediaStreamTrackStats::RTCMediaStreamTrackStats(const std::string& id,
@ -412,7 +413,8 @@ RTCMediaStreamTrackStats::RTCMediaStreamTrackStats(std::string&& id,
total_samples_duration("totalSamplesDuration"), total_samples_duration("totalSamplesDuration"),
concealed_samples("concealedSamples"), concealed_samples("concealedSamples"),
concealment_events("concealmentEvents"), concealment_events("concealmentEvents"),
jitter_buffer_flushes("jitterBufferFlushes") { jitter_buffer_flushes("jitterBufferFlushes"),
delayed_packet_outage_samples("delayedPacketOutageSamples") {
RTC_DCHECK(kind == RTCMediaStreamTrackKind::kAudio || RTC_DCHECK(kind == RTCMediaStreamTrackKind::kAudio ||
kind == RTCMediaStreamTrackKind::kVideo); kind == RTCMediaStreamTrackKind::kVideo);
} }
@ -445,7 +447,8 @@ RTCMediaStreamTrackStats::RTCMediaStreamTrackStats(
total_samples_duration(other.total_samples_duration), total_samples_duration(other.total_samples_duration),
concealed_samples(other.concealed_samples), concealed_samples(other.concealed_samples),
concealment_events(other.concealment_events), concealment_events(other.concealment_events),
jitter_buffer_flushes(other.jitter_buffer_flushes) {} jitter_buffer_flushes(other.jitter_buffer_flushes),
delayed_packet_outage_samples(other.delayed_packet_outage_samples) {}
RTCMediaStreamTrackStats::~RTCMediaStreamTrackStats() {} RTCMediaStreamTrackStats::~RTCMediaStreamTrackStats() {}