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}
This commit is contained in:
parent
1b1863a11a
commit
63489787a0
@ -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;
|
||||
};
|
||||
|
||||
|
||||
@ -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 },
|
||||
|
||||
@ -348,8 +348,11 @@ void VerifyVoiceReceiverInfoReport(
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -148,6 +148,7 @@ class StatsReport {
|
||||
kStatsValueNameDecodingCNG,
|
||||
kStatsValueNameDecodingCTN,
|
||||
kStatsValueNameDecodingCTSG,
|
||||
kStatsValueNameDecodingMutedOutput,
|
||||
kStatsValueNameDecodingNormal,
|
||||
kStatsValueNameDecodingPLC,
|
||||
kStatsValueNameDecodingPLCCNG,
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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 @@ 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user