diff --git a/api/stats/rtcstats_objects.h b/api/stats/rtcstats_objects.h index e69bc8e34f..b27bf73df6 100644 --- a/api/stats/rtcstats_objects.h +++ b/api/stats/rtcstats_objects.h @@ -284,6 +284,7 @@ class RTC_EXPORT RTCMediaStreamTrackStats final : public RTCStats { // implemented for audio only). // https://crbug.com/webrtc/8318 RTCStatsMember jitter_buffer_delay; + RTCStatsMember jitter_buffer_emitted_count; // Video-only members RTCStatsMember frame_width; RTCStatsMember frame_height; diff --git a/audio/audio_receive_stream.cc b/audio/audio_receive_stream.cc index 690bb90dc5..58eca4f006 100644 --- a/audio/audio_receive_stream.cc +++ b/audio/audio_receive_stream.cc @@ -207,6 +207,7 @@ webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const { stats.jitter_buffer_delay_seconds = static_cast(ns.jitterBufferDelayMs) / static_cast(rtc::kNumMillisecsPerSec); + stats.jitter_buffer_emitted_count = ns.jitterBufferEmittedCount; stats.expand_rate = Q14ToFloat(ns.currentExpandRate); stats.speech_expand_rate = Q14ToFloat(ns.currentSpeechExpandRate); stats.secondary_decoded_rate = Q14ToFloat(ns.currentSecondaryDecodedRate); diff --git a/audio/audio_receive_stream_unittest.cc b/audio/audio_receive_stream_unittest.cc index 25ca5282f2..cc1e9d4513 100644 --- a/audio/audio_receive_stream_unittest.cc +++ b/audio/audio_receive_stream_unittest.cc @@ -67,8 +67,8 @@ const CallReceiveStatistics kCallStats = {345, 678, 901, 234, const std::pair kReceiveCodec = {123, {"codec_name_recv", 96000, 0}}; const NetworkStatistics kNetworkStats = { - 123, 456, false, 789012, 3456, 123, 456, 0, {}, 789, 12, - 345, 678, 901, 0, -1, -1, -1, -1, -1, 0}; + 123, 456, false, 789012, 3456, 123, 456, 789, 0, {}, 789, + 12, 345, 678, 901, 0, -1, -1, -1, -1, -1, 0}; const AudioDecodingCallStats kAudioDecodeStats = MakeAudioDecodeStatsForTest(); struct ConfigHelper { @@ -288,6 +288,8 @@ TEST(AudioReceiveStreamTest, GetStats) { EXPECT_EQ(static_cast(kNetworkStats.jitterBufferDelayMs) / static_cast(rtc::kNumMillisecsPerSec), stats.jitter_buffer_delay_seconds); + EXPECT_EQ(kNetworkStats.jitterBufferEmittedCount, + stats.jitter_buffer_emitted_count); EXPECT_EQ(Q14ToFloat(kNetworkStats.currentExpandRate), stats.expand_rate); EXPECT_EQ(Q14ToFloat(kNetworkStats.currentSpeechExpandRate), stats.speech_expand_rate); diff --git a/call/audio_receive_stream.h b/call/audio_receive_stream.h index e850954069..f1aeb88242 100644 --- a/call/audio_receive_stream.h +++ b/call/audio_receive_stream.h @@ -56,6 +56,7 @@ class AudioReceiveStream { uint64_t concealed_samples = 0; uint64_t concealment_events = 0; double jitter_buffer_delay_seconds = 0.0; + uint64_t jitter_buffer_emitted_count = 0; // Stats below DO NOT correspond directly to anything in the WebRTC stats float expand_rate = 0.0f; float speech_expand_rate = 0.0f; diff --git a/media/base/media_channel.h b/media/base/media_channel.h index 8eecaa0fe9..a55c191696 100644 --- a/media/base/media_channel.h +++ b/media/base/media_channel.h @@ -449,7 +449,8 @@ struct VoiceReceiverInfo : public MediaReceiverInfo { double total_output_duration = 0.0; uint64_t concealed_samples = 0; uint64_t concealment_events = 0; - double jitter_buffer_delay_seconds = 0; + double jitter_buffer_delay_seconds = 0.0; + uint64_t jitter_buffer_emitted_count = 0; // Stats below DO NOT correspond directly to anything in the WebRTC stats // fraction of synthesized audio inserted through expansion. float expand_rate = 0.0f; diff --git a/media/engine/webrtc_voice_engine.cc b/media/engine/webrtc_voice_engine.cc index 88fc4d812f..9c84f7cf61 100644 --- a/media/engine/webrtc_voice_engine.cc +++ b/media/engine/webrtc_voice_engine.cc @@ -2244,6 +2244,7 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) { rinfo.concealed_samples = stats.concealed_samples; rinfo.concealment_events = stats.concealment_events; rinfo.jitter_buffer_delay_seconds = stats.jitter_buffer_delay_seconds; + rinfo.jitter_buffer_emitted_count = stats.jitter_buffer_emitted_count; rinfo.expand_rate = stats.expand_rate; rinfo.speech_expand_rate = stats.speech_expand_rate; rinfo.secondary_decoded_rate = stats.secondary_decoded_rate; diff --git a/media/engine/webrtc_voice_engine_unittest.cc b/media/engine/webrtc_voice_engine_unittest.cc index 06bf3fdf2b..8204010f56 100644 --- a/media/engine/webrtc_voice_engine_unittest.cc +++ b/media/engine/webrtc_voice_engine_unittest.cc @@ -655,6 +655,7 @@ class WebRtcVoiceEngineTestFake : public testing::Test { stats.concealed_samples = 234; stats.concealment_events = 12; stats.jitter_buffer_delay_seconds = 34; + stats.jitter_buffer_emitted_count = 77; stats.expand_rate = 5.67f; stats.speech_expand_rate = 8.90f; stats.secondary_decoded_rate = 1.23f; @@ -702,6 +703,8 @@ class WebRtcVoiceEngineTestFake : public testing::Test { EXPECT_EQ(info.concealment_events, stats.concealment_events); EXPECT_EQ(info.jitter_buffer_delay_seconds, stats.jitter_buffer_delay_seconds); + EXPECT_EQ(info.jitter_buffer_emitted_count, + stats.jitter_buffer_emitted_count); EXPECT_EQ(info.expand_rate, stats.expand_rate); EXPECT_EQ(info.speech_expand_rate, stats.speech_expand_rate); EXPECT_EQ(info.secondary_decoded_rate, stats.secondary_decoded_rate); diff --git a/modules/audio_coding/acm2/acm_receiver.cc b/modules/audio_coding/acm2/acm_receiver.cc index 2810294e1d..ba36278059 100644 --- a/modules/audio_coding/acm2/acm_receiver.cc +++ b/modules/audio_coding/acm2/acm_receiver.cc @@ -245,6 +245,8 @@ void AcmReceiver::GetNetworkStatistics(NetworkStatistics* acm_stat) { acm_stat->concealedSamples = neteq_lifetime_stat.concealed_samples; acm_stat->concealmentEvents = neteq_lifetime_stat.concealment_events; acm_stat->jitterBufferDelayMs = neteq_lifetime_stat.jitter_buffer_delay_ms; + acm_stat->jitterBufferEmittedCount = + neteq_lifetime_stat.jitter_buffer_emitted_count; acm_stat->delayedPacketOutageSamples = neteq_lifetime_stat.delayed_packet_outage_samples; diff --git a/modules/audio_coding/include/audio_coding_module_typedefs.h b/modules/audio_coding/include/audio_coding_module_typedefs.h index bafff72e5a..0db423b543 100644 --- a/modules/audio_coding/include/audio_coding_module_typedefs.h +++ b/modules/audio_coding/include/audio_coding_module_typedefs.h @@ -80,6 +80,7 @@ struct NetworkStatistics { uint64_t concealedSamples; uint64_t concealmentEvents; uint64_t jitterBufferDelayMs; + uint64_t jitterBufferEmittedCount; // Stats below DO NOT correspond directly to anything in the WebRTC stats // Loss rate (network + late); fraction between 0 and 1, scaled to Q14. uint16_t currentPacketLossRate; diff --git a/modules/audio_coding/neteq/include/neteq.h b/modules/audio_coding/neteq/include/neteq.h index 6eecc65ca8..d4e842310e 100644 --- a/modules/audio_coding/neteq/include/neteq.h +++ b/modules/audio_coding/neteq/include/neteq.h @@ -70,6 +70,7 @@ struct NetEqLifetimeStatistics { uint64_t concealed_samples = 0; uint64_t concealment_events = 0; uint64_t jitter_buffer_delay_ms = 0; + uint64_t jitter_buffer_emitted_count = 0; // Below stat is not part of the spec. uint64_t voice_concealed_samples = 0; uint64_t delayed_packet_outage_samples = 0; diff --git a/modules/audio_coding/neteq/neteq_unittest.cc b/modules/audio_coding/neteq/neteq_unittest.cc index b562ede063..b9b8d08d16 100644 --- a/modules/audio_coding/neteq/neteq_unittest.cc +++ b/modules/audio_coding/neteq/neteq_unittest.cc @@ -1656,6 +1656,7 @@ void NetEqDecodingTestFaxMode::TestJitterBufferDelay(bool apply_packet_loss) { int packets_sent = 0; int packets_received = 0; int expected_delay = 0; + uint64_t expected_emitted_count = 0; while (packets_received < kNumPackets) { // Insert packet. if (packets_sent < kNumPackets) { @@ -1679,6 +1680,7 @@ void NetEqDecodingTestFaxMode::TestJitterBufferDelay(bool apply_packet_loss) { // number of samples that are sent for play out. int current_delay_ms = packets_delay * kPacketLenMs; expected_delay += current_delay_ms * kSamples; + expected_emitted_count += kSamples; } } @@ -1690,6 +1692,7 @@ void NetEqDecodingTestFaxMode::TestJitterBufferDelay(bool apply_packet_loss) { // Check jitter buffer delay. NetEqLifetimeStatistics stats = neteq_->GetLifetimeStatistics(); EXPECT_EQ(expected_delay, static_cast(stats.jitter_buffer_delay_ms)); + EXPECT_EQ(expected_emitted_count, stats.jitter_buffer_emitted_count); } TEST_F(NetEqDecodingTestFaxMode, TestJitterBufferDelayWithoutLoss) { diff --git a/modules/audio_coding/neteq/statistics_calculator.cc b/modules/audio_coding/neteq/statistics_calculator.cc index 5d94abd8b8..7ad1a28b69 100644 --- a/modules/audio_coding/neteq/statistics_calculator.cc +++ b/modules/audio_coding/neteq/statistics_calculator.cc @@ -246,6 +246,7 @@ void StatisticsCalculator::IncreaseCounter(size_t num_samples, int fs_hz) { void StatisticsCalculator::JitterBufferDelay(size_t num_samples, uint64_t waiting_time_ms) { lifetime_stats_.jitter_buffer_delay_ms += waiting_time_ms * num_samples; + lifetime_stats_.jitter_buffer_emitted_count += num_samples; } void StatisticsCalculator::SecondaryDecodedSamples(int num_samples) { diff --git a/pc/rtc_stats_collector.cc b/pc/rtc_stats_collector.cc index b1a44ee794..245293aa33 100644 --- a/pc/rtc_stats_collector.cc +++ b/pc/rtc_stats_collector.cc @@ -445,6 +445,8 @@ ProduceMediaStreamTrackStatsFromVoiceReceiverInfo( } audio_track_stats->jitter_buffer_delay = voice_receiver_info.jitter_buffer_delay_seconds; + audio_track_stats->jitter_buffer_emitted_count = + voice_receiver_info.jitter_buffer_emitted_count; audio_track_stats->total_audio_energy = voice_receiver_info.total_output_energy; audio_track_stats->total_samples_received = diff --git a/pc/rtc_stats_collector_unittest.cc b/pc/rtc_stats_collector_unittest.cc index 4635d0e9b4..468e2c4bca 100644 --- a/pc/rtc_stats_collector_unittest.cc +++ b/pc/rtc_stats_collector_unittest.cc @@ -1425,6 +1425,7 @@ TEST_F(RTCStatsCollectorTest, voice_receiver_info.concealed_samples = 123; voice_receiver_info.concealment_events = 12; voice_receiver_info.jitter_buffer_delay_seconds = 3456; + voice_receiver_info.jitter_buffer_emitted_count = 13; voice_receiver_info.jitter_buffer_flushes = 7; voice_receiver_info.delayed_packet_outage_samples = 15; @@ -1460,6 +1461,7 @@ TEST_F(RTCStatsCollectorTest, expected_remote_audio_track.concealed_samples = 123; expected_remote_audio_track.concealment_events = 12; expected_remote_audio_track.jitter_buffer_delay = 3456; + expected_remote_audio_track.jitter_buffer_emitted_count = 13; 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())); diff --git a/pc/rtc_stats_integrationtest.cc b/pc/rtc_stats_integrationtest.cc index cae01ae4a5..a9ebc800c5 100644 --- a/pc/rtc_stats_integrationtest.cc +++ b/pc/rtc_stats_integrationtest.cc @@ -611,6 +611,8 @@ class RTCStatsReportVerifier { *media_stream_track.remote_source) { verifier.TestMemberIsNonNegative( media_stream_track.jitter_buffer_delay); + verifier.TestMemberIsNonNegative( + media_stream_track.jitter_buffer_emitted_count); verifier.TestMemberIsNonNegative( media_stream_track.total_samples_received); verifier.TestMemberIsNonNegative( @@ -623,6 +625,8 @@ class RTCStatsReportVerifier { media_stream_track.delayed_packet_outage_samples); } else { verifier.TestMemberIsUndefined(media_stream_track.jitter_buffer_delay); + verifier.TestMemberIsUndefined( + media_stream_track.jitter_buffer_emitted_count); verifier.TestMemberIsUndefined(media_stream_track.total_samples_received); verifier.TestMemberIsUndefined(media_stream_track.concealed_samples); verifier.TestMemberIsUndefined(media_stream_track.concealment_events); diff --git a/stats/rtcstats_objects.cc b/stats/rtcstats_objects.cc index 4ba0b28f40..2451e12169 100644 --- a/stats/rtcstats_objects.cc +++ b/stats/rtcstats_objects.cc @@ -360,6 +360,7 @@ WEBRTC_RTCSTATS_IMPL(RTCMediaStreamTrackStats, RTCStats, "track", &detached, &kind, &jitter_buffer_delay, + &jitter_buffer_emitted_count, &frame_width, &frame_height, &frames_per_second, @@ -398,6 +399,7 @@ RTCMediaStreamTrackStats::RTCMediaStreamTrackStats(std::string&& id, detached("detached"), kind("kind", kind), jitter_buffer_delay("jitterBufferDelay"), + jitter_buffer_emitted_count("jitterBufferEmittedCount"), frame_width("frameWidth"), frame_height("frameHeight"), frames_per_second("framesPerSecond"), @@ -432,6 +434,7 @@ RTCMediaStreamTrackStats::RTCMediaStreamTrackStats( detached(other.detached), kind(other.kind), jitter_buffer_delay(other.jitter_buffer_delay), + jitter_buffer_emitted_count(other.jitter_buffer_emitted_count), frame_width(other.frame_width), frame_height(other.frame_height), frames_per_second(other.frames_per_second),