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:
committed by
Commit Bot
parent
59cfd35438
commit
352ce5c419
@ -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*
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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();
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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() {
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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())
|
||||||
|
|||||||
@ -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() {}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user