Add new decoding statistics for muted output
This change adds a new statistic for logging how many calls to
NetEq::GetAudio resulted in a "muted output". A muted output happens
if the packet stream has been dead for some time (and the last decoded
packet was not comfort noise).
BUG=webrtc:5606
BUG=b/31256483
Review-Url: https://codereview.webrtc.org/2341293002
Cr-Commit-Position: refs/heads/master@{#14302}
diff --git a/webrtc/api/call/audio_receive_stream.h b/webrtc/api/call/audio_receive_stream.h
index 096cbc7..ec80a9e 100644
--- a/webrtc/api/call/audio_receive_stream.h
+++ b/webrtc/api/call/audio_receive_stream.h
@@ -57,6 +57,7 @@
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 d21fc30..4dd5305 100644
--- a/webrtc/api/statscollector.cc
+++ b/webrtc/api/statscollector.cc
@@ -143,6 +143,8 @@
{ 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 f71a168..b2fb93c 100644
--- a/webrtc/api/statscollector_unittest.cc
+++ b/webrtc/api/statscollector_unittest.cc
@@ -348,8 +348,11 @@
EXPECT_TRUE(GetValue(
report, StatsReport::kStatsValueNameDecodingPLCCNG, &value_in_report));
EXPECT_EQ(rtc::ToString<int>(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<int>(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 9e5e176..eb6b30c 100644
--- a/webrtc/api/statstypes.cc
+++ b/webrtc/api/statstypes.cc
@@ -456,6 +456,8 @@
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 093bdbf..a0a85c9 100644
--- a/webrtc/api/statstypes.h
+++ b/webrtc/api/statstypes.h
@@ -148,6 +148,7 @@
kStatsValueNameDecodingCNG,
kStatsValueNameDecodingCTN,
kStatsValueNameDecodingCTSG,
+ kStatsValueNameDecodingMutedOutput,
kStatsValueNameDecodingNormal,
kStatsValueNameDecodingPLC,
kStatsValueNameDecodingPLCCNG,
diff --git a/webrtc/audio/audio_receive_stream.cc b/webrtc/audio/audio_receive_stream.cc
index 91237c3..57e62f5 100644
--- a/webrtc/audio/audio_receive_stream.cc
+++ b/webrtc/audio/audio_receive_stream.cc
@@ -211,6 +211,7 @@
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 dd66cc6..9276c28 100644
--- a/webrtc/audio/audio_receive_stream_unittest.cc
+++ b/webrtc/audio/audio_receive_stream_unittest.cc
@@ -43,6 +43,7 @@
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 @@
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 6d30719..b8c0df4 100644
--- a/webrtc/common_types.h
+++ b/webrtc/common_types.h
@@ -385,7 +385,8 @@
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 @@
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 1355b36..b71a309 100644
--- a/webrtc/media/base/mediachannel.h
+++ b/webrtc/media/base/mediachannel.h
@@ -620,6 +620,7 @@
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 @@
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 235b9b3..e066f30 100644
--- a/webrtc/media/engine/webrtcvoiceengine.cc
+++ b/webrtc/media/engine/webrtcvoiceengine.cc
@@ -2611,6 +2611,7 @@
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 ead706f..e40bc77 100644
--- a/webrtc/media/engine/webrtcvoiceengine_unittest.cc
+++ b/webrtc/media/engine/webrtcvoiceengine_unittest.cc
@@ -450,7 +450,8 @@
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 @@
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 9a882aa..417a346 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::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 @@
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 6220c05..2a8b834 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 @@
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 @@
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 @@
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 4441932..7ac9fc4 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 <assert.h>
+#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 @@
}
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 888afea..3993319 100644
--- a/webrtc/modules/audio_coding/acm2/call_statistics.h
+++ b/webrtc/modules/audio_coding/acm2/call_statistics.h
@@ -37,8 +37,9 @@
~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 9ba0774..284532f 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 @@
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 @@
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 @@
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