diff --git a/webrtc/api/call/audio_receive_stream.h b/webrtc/api/call/audio_receive_stream.h index 096cbc775e..ec80a9e3f0 100644 --- a/webrtc/api/call/audio_receive_stream.h +++ b/webrtc/api/call/audio_receive_stream.h @@ -57,6 +57,7 @@ class AudioReceiveStream { int32_t decoding_plc = 0; int32_t decoding_cng = 0; int32_t decoding_plc_cng = 0; + int32_t decoding_muted_output = 0; int64_t capture_start_ntp_time_ms = 0; }; diff --git a/webrtc/api/statscollector.cc b/webrtc/api/statscollector.cc index d21fc3009a..4dd5305528 100644 --- a/webrtc/api/statscollector.cc +++ b/webrtc/api/statscollector.cc @@ -143,6 +143,8 @@ void ExtractStats(const cricket::VoiceReceiverInfo& info, StatsReport* report) { { StatsReport::kStatsValueNameDecodingCTN, info.decoding_calls_to_neteq }, { StatsReport::kStatsValueNameDecodingCTSG, info.decoding_calls_to_silence_generator }, + { StatsReport::kStatsValueNameDecodingMutedOutput, + info.decoding_muted_output }, { StatsReport::kStatsValueNameDecodingNormal, info.decoding_normal }, { StatsReport::kStatsValueNameDecodingPLC, info.decoding_plc }, { StatsReport::kStatsValueNameDecodingPLCCNG, info.decoding_plc_cng }, diff --git a/webrtc/api/statscollector_unittest.cc b/webrtc/api/statscollector_unittest.cc index f71a168e06..b2fb93cb70 100644 --- a/webrtc/api/statscollector_unittest.cc +++ b/webrtc/api/statscollector_unittest.cc @@ -348,8 +348,11 @@ void VerifyVoiceReceiverInfoReport( EXPECT_TRUE(GetValue( report, StatsReport::kStatsValueNameDecodingPLCCNG, &value_in_report)); EXPECT_EQ(rtc::ToString(info.decoding_plc_cng), value_in_report); - EXPECT_TRUE(GetValue( - report, StatsReport::kStatsValueNameCodecName, &value_in_report)); + EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingMutedOutput, + &value_in_report)); + EXPECT_EQ(rtc::ToString(info.decoding_muted_output), value_in_report); + EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameCodecName, + &value_in_report)); } diff --git a/webrtc/api/statstypes.cc b/webrtc/api/statstypes.cc index 9e5e176d82..eb6b30cca6 100644 --- a/webrtc/api/statstypes.cc +++ b/webrtc/api/statstypes.cc @@ -456,6 +456,8 @@ const char* StatsReport::Value::display_name() const { return "googDecodingCTSG"; case kStatsValueNameDecodingCTN: return "googDecodingCTN"; + case kStatsValueNameDecodingMutedOutput: + return "googDecodingMuted"; case kStatsValueNameDecodingNormal: return "googDecodingNormal"; case kStatsValueNameDecodingPLC: diff --git a/webrtc/api/statstypes.h b/webrtc/api/statstypes.h index 093bdbffe1..a0a85c91a1 100644 --- a/webrtc/api/statstypes.h +++ b/webrtc/api/statstypes.h @@ -148,6 +148,7 @@ class StatsReport { kStatsValueNameDecodingCNG, kStatsValueNameDecodingCTN, kStatsValueNameDecodingCTSG, + kStatsValueNameDecodingMutedOutput, kStatsValueNameDecodingNormal, kStatsValueNameDecodingPLC, kStatsValueNameDecodingPLCCNG, diff --git a/webrtc/audio/audio_receive_stream.cc b/webrtc/audio/audio_receive_stream.cc index 91237c341b..57e62f50fd 100644 --- a/webrtc/audio/audio_receive_stream.cc +++ b/webrtc/audio/audio_receive_stream.cc @@ -211,6 +211,7 @@ webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const { stats.decoding_plc = ds.decoded_plc; stats.decoding_cng = ds.decoded_cng; stats.decoding_plc_cng = ds.decoded_plc_cng; + stats.decoding_muted_output = ds.decoded_muted_output; return stats; } diff --git a/webrtc/audio/audio_receive_stream_unittest.cc b/webrtc/audio/audio_receive_stream_unittest.cc index dd66cc67d8..9276c28312 100644 --- a/webrtc/audio/audio_receive_stream_unittest.cc +++ b/webrtc/audio/audio_receive_stream_unittest.cc @@ -43,6 +43,7 @@ AudioDecodingCallStats MakeAudioDecodeStatsForTest() { audio_decode_stats.decoded_plc = 123; audio_decode_stats.decoded_cng = 456; audio_decode_stats.decoded_plc_cng = 789; + audio_decode_stats.decoded_muted_output = 987; return audio_decode_stats; } @@ -356,6 +357,8 @@ TEST(AudioReceiveStreamTest, GetStats) { EXPECT_EQ(kAudioDecodeStats.decoded_plc, stats.decoding_plc); EXPECT_EQ(kAudioDecodeStats.decoded_cng, stats.decoding_cng); EXPECT_EQ(kAudioDecodeStats.decoded_plc_cng, stats.decoding_plc_cng); + EXPECT_EQ(kAudioDecodeStats.decoded_muted_output, + stats.decoding_muted_output); EXPECT_EQ(kCallStats.capture_start_ntp_time_ms_, stats.capture_start_ntp_time_ms); } diff --git a/webrtc/common_types.h b/webrtc/common_types.h index 6d30719ddc..b8c0df4b08 100644 --- a/webrtc/common_types.h +++ b/webrtc/common_types.h @@ -385,7 +385,8 @@ struct AudioDecodingCallStats { decoded_normal(0), decoded_plc(0), decoded_cng(0), - decoded_plc_cng(0) {} + decoded_plc_cng(0), + decoded_muted_output(0) {} int calls_to_silence_generator; // Number of calls where silence generated, // and NetEq was disengaged from decoding. @@ -394,6 +395,7 @@ struct AudioDecodingCallStats { int decoded_plc; // Number of calls resulted in PLC. int decoded_cng; // Number of calls where comfort noise generated due to DTX. int decoded_plc_cng; // Number of calls resulted where PLC faded to CNG. + int decoded_muted_output; // Number of calls returning a muted state output. }; // Type of Noise Suppression. diff --git a/webrtc/media/base/mediachannel.h b/webrtc/media/base/mediachannel.h index 1355b36679..b71a309233 100644 --- a/webrtc/media/base/mediachannel.h +++ b/webrtc/media/base/mediachannel.h @@ -620,6 +620,7 @@ struct VoiceReceiverInfo : public MediaReceiverInfo { decoding_plc(0), decoding_cng(0), decoding_plc_cng(0), + decoding_muted_output(0), capture_start_ntp_time_ms(-1) {} int ext_seqnum; @@ -644,6 +645,7 @@ struct VoiceReceiverInfo : public MediaReceiverInfo { int decoding_plc; int decoding_cng; int decoding_plc_cng; + int decoding_muted_output; // Estimated capture start time in NTP time in ms. int64_t capture_start_ntp_time_ms; }; diff --git a/webrtc/media/engine/webrtcvoiceengine.cc b/webrtc/media/engine/webrtcvoiceengine.cc index 235b9b3aaf..e066f309a7 100644 --- a/webrtc/media/engine/webrtcvoiceengine.cc +++ b/webrtc/media/engine/webrtcvoiceengine.cc @@ -2611,6 +2611,7 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) { rinfo.decoding_plc = stats.decoding_plc; rinfo.decoding_cng = stats.decoding_cng; rinfo.decoding_plc_cng = stats.decoding_plc_cng; + rinfo.decoding_muted_output = stats.decoding_muted_output; rinfo.capture_start_ntp_time_ms = stats.capture_start_ntp_time_ms; info->receivers.push_back(rinfo); } diff --git a/webrtc/media/engine/webrtcvoiceengine_unittest.cc b/webrtc/media/engine/webrtcvoiceengine_unittest.cc index ead706fb3a..e40bc773b6 100644 --- a/webrtc/media/engine/webrtcvoiceengine_unittest.cc +++ b/webrtc/media/engine/webrtcvoiceengine_unittest.cc @@ -450,7 +450,8 @@ class WebRtcVoiceEngineTestFake : public testing::Test { stats.decoding_plc = 1234; stats.decoding_cng = 5678; stats.decoding_plc_cng = 9012; - stats.capture_start_ntp_time_ms = 3456; + stats.decoding_muted_output = 3456; + stats.capture_start_ntp_time_ms = 7890; return stats; } void SetAudioReceiveStreamStats() { @@ -485,6 +486,7 @@ class WebRtcVoiceEngineTestFake : public testing::Test { EXPECT_EQ(info.decoding_plc, stats.decoding_plc); EXPECT_EQ(info.decoding_cng, stats.decoding_cng); EXPECT_EQ(info.decoding_plc_cng, stats.decoding_plc_cng); + EXPECT_EQ(info.decoding_muted_output, stats.decoding_muted_output); EXPECT_EQ(info.capture_start_ntp_time_ms, stats.capture_start_ntp_time_ms); } diff --git a/webrtc/modules/audio_coding/acm2/acm_receiver.cc b/webrtc/modules/audio_coding/acm2/acm_receiver.cc index 9a882aac37..417a34637c 100644 --- a/webrtc/modules/audio_coding/acm2/acm_receiver.cc +++ b/webrtc/modules/audio_coding/acm2/acm_receiver.cc @@ -135,6 +135,7 @@ int AcmReceiver::InsertPacket(const WebRtcRTPHeader& rtp_header, int AcmReceiver::GetAudio(int desired_freq_hz, AudioFrame* audio_frame, bool* muted) { + RTC_DCHECK(muted); // Accessing members, take the lock. rtc::CritScope lock(&crit_sect_); @@ -191,7 +192,7 @@ int AcmReceiver::GetAudio(int desired_freq_hz, sizeof(int16_t) * audio_frame->samples_per_channel_ * audio_frame->num_channels_); - call_stats_.DecodedByNetEq(audio_frame->speech_type_); + call_stats_.DecodedByNetEq(audio_frame->speech_type_, *muted); return 0; } diff --git a/webrtc/modules/audio_coding/acm2/audio_coding_module_unittest_oldapi.cc b/webrtc/modules/audio_coding/acm2/audio_coding_module_unittest_oldapi.cc index 6220c05fe6..2a8b834f96 100644 --- a/webrtc/modules/audio_coding/acm2/audio_coding_module_unittest_oldapi.cc +++ b/webrtc/modules/audio_coding/acm2/audio_coding_module_unittest_oldapi.cc @@ -253,6 +253,7 @@ TEST_F(AudioCodingModuleTestOldApi, MAYBE_InitializedToZero) { EXPECT_EQ(0, stats.decoded_cng); EXPECT_EQ(0, stats.decoded_plc); EXPECT_EQ(0, stats.decoded_plc_cng); + EXPECT_EQ(0, stats.decoded_muted_output); } // Insert some packets and pull audio. Check statistics are valid. Then, @@ -278,6 +279,7 @@ TEST_F(AudioCodingModuleTestOldApi, MAYBE_NetEqCalls) { EXPECT_EQ(0, stats.decoded_cng); EXPECT_EQ(0, stats.decoded_plc); EXPECT_EQ(0, stats.decoded_plc_cng); + EXPECT_EQ(0, stats.decoded_muted_output); const int kNumPlc = 3; const int kNumPlcCng = 5; @@ -293,6 +295,8 @@ TEST_F(AudioCodingModuleTestOldApi, MAYBE_NetEqCalls) { EXPECT_EQ(0, stats.decoded_cng); EXPECT_EQ(kNumPlc, stats.decoded_plc); EXPECT_EQ(kNumPlcCng, stats.decoded_plc_cng); + EXPECT_EQ(0, stats.decoded_muted_output); + // TODO(henrik.lundin) Add a test with muted state enabled. } TEST_F(AudioCodingModuleTestOldApi, VerifyOutputFrame) { diff --git a/webrtc/modules/audio_coding/acm2/call_statistics.cc b/webrtc/modules/audio_coding/acm2/call_statistics.cc index 4441932c8c..7ac9fc4b0f 100644 --- a/webrtc/modules/audio_coding/acm2/call_statistics.cc +++ b/webrtc/modules/audio_coding/acm2/call_statistics.cc @@ -10,14 +10,18 @@ #include "webrtc/modules/audio_coding/acm2/call_statistics.h" -#include +#include "webrtc/base/checks.h" namespace webrtc { namespace acm2 { -void CallStatistics::DecodedByNetEq(AudioFrame::SpeechType speech_type) { +void CallStatistics::DecodedByNetEq(AudioFrame::SpeechType speech_type, + bool muted) { ++decoding_stat_.calls_to_neteq; + if (muted) { + ++decoding_stat_.decoded_muted_output; + } switch (speech_type) { case AudioFrame::kNormalSpeech: { ++decoding_stat_.decoded_normal; @@ -37,7 +41,7 @@ void CallStatistics::DecodedByNetEq(AudioFrame::SpeechType speech_type) { } case AudioFrame::kUndefined: { // If the audio is decoded by NetEq, |kUndefined| is not an option. - assert(false); + RTC_NOTREACHED(); } } } diff --git a/webrtc/modules/audio_coding/acm2/call_statistics.h b/webrtc/modules/audio_coding/acm2/call_statistics.h index 888afea0a7..3993319e89 100644 --- a/webrtc/modules/audio_coding/acm2/call_statistics.h +++ b/webrtc/modules/audio_coding/acm2/call_statistics.h @@ -37,8 +37,9 @@ class CallStatistics { ~CallStatistics() {} // Call this method to indicate that NetEq engaged in decoding. |speech_type| - // is the audio-type according to NetEq. - void DecodedByNetEq(AudioFrame::SpeechType speech_type); + // is the audio-type according to NetEq, and |muted| indicates if the decoded + // frame was produced in muted state. + void DecodedByNetEq(AudioFrame::SpeechType speech_type, bool muted); // Call this method to indicate that a decoding call resulted in generating // silence, i.e. call to NetEq is bypassed and the output audio is zero. diff --git a/webrtc/modules/audio_coding/acm2/call_statistics_unittest.cc b/webrtc/modules/audio_coding/acm2/call_statistics_unittest.cc index 9ba0774ce1..284532fbfd 100644 --- a/webrtc/modules/audio_coding/acm2/call_statistics_unittest.cc +++ b/webrtc/modules/audio_coding/acm2/call_statistics_unittest.cc @@ -26,6 +26,7 @@ TEST(CallStatisticsTest, InitializedZero) { EXPECT_EQ(0, stats.decoded_cng); EXPECT_EQ(0, stats.decoded_plc); EXPECT_EQ(0, stats.decoded_plc_cng); + EXPECT_EQ(0, stats.decoded_muted_output); } TEST(CallStatisticsTest, AllCalls) { @@ -33,10 +34,10 @@ TEST(CallStatisticsTest, AllCalls) { AudioDecodingCallStats stats; call_stats.DecodedBySilenceGenerator(); - call_stats.DecodedByNetEq(AudioFrame::kNormalSpeech); - call_stats.DecodedByNetEq(AudioFrame::kPLC); - call_stats.DecodedByNetEq(AudioFrame::kPLCCNG); - call_stats.DecodedByNetEq(AudioFrame::kCNG); + call_stats.DecodedByNetEq(AudioFrame::kNormalSpeech, false); + call_stats.DecodedByNetEq(AudioFrame::kPLC, false); + call_stats.DecodedByNetEq(AudioFrame::kPLCCNG, true); // Let this be muted. + call_stats.DecodedByNetEq(AudioFrame::kCNG, false); stats = call_stats.GetDecodingStatistics(); EXPECT_EQ(4, stats.calls_to_neteq); @@ -45,6 +46,7 @@ TEST(CallStatisticsTest, AllCalls) { EXPECT_EQ(1, stats.decoded_cng); EXPECT_EQ(1, stats.decoded_plc); EXPECT_EQ(1, stats.decoded_plc_cng); + EXPECT_EQ(1, stats.decoded_muted_output); } } // namespace acm2