Add new ANA stats to the old GetStats() to count the number of actions taken by each controller.

This CL only wires up the new stats but does not set the values yet. This will be added in a follow-up CL.

BUG=webrtc:8127

Review-Url: https://codereview.webrtc.org/3011623002
Cr-Commit-Position: refs/heads/master@{#19751}
This commit is contained in:
ivoc 2017-09-08 08:13:19 -07:00 committed by Commit Bot
parent 01410dcc99
commit e1198e068b
27 changed files with 217 additions and 1 deletions

View File

@ -15,6 +15,10 @@
namespace webrtc {
ANAStats::ANAStats() = default;
ANAStats::~ANAStats() = default;
ANAStats::ANAStats(const ANAStats&) = default;
AudioEncoder::EncodedInfo::EncodedInfo() = default;
AudioEncoder::EncodedInfo::EncodedInfo(const EncodedInfo&) = default;
AudioEncoder::EncodedInfo::EncodedInfo(EncodedInfo&&) = default;
@ -95,4 +99,8 @@ void AudioEncoder::OnReceivedOverhead(size_t overhead_bytes_per_packet) {}
void AudioEncoder::SetReceiverFrameLengthRange(int min_frame_length_ms,
int max_frame_length_ms) {}
ANAStats AudioEncoder::GetANAStats() const {
return ANAStats();
}
} // namespace webrtc

View File

@ -27,6 +27,33 @@ namespace webrtc {
class Clock;
class RtcEventLog;
// Statistics related to Audio Network Adaptation.
struct ANAStats {
ANAStats();
ANAStats(const ANAStats&);
~ANAStats();
// Number of actions taken by the ANA bitrate controller since the start of
// the call. If this value is not set, it indicates that the bitrate
// controller is disabled.
rtc::Optional<uint32_t> bitrate_action_counter;
// Number of actions taken by the ANA channel controller since the start of
// the call. If this value is not set, it indicates that the channel
// controller is disabled.
rtc::Optional<uint32_t> channel_action_counter;
// Number of actions taken by the ANA DTX controller since the start of the
// call. If this value is not set, it indicates that the DTX controller is
// disabled.
rtc::Optional<uint32_t> dtx_action_counter;
// Number of actions taken by the ANA FEC controller since the start of the
// call. If this value is not set, it indicates that the FEC controller is
// disabled.
rtc::Optional<uint32_t> fec_action_counter;
// Number of actions taken by the ANA frame length controller since the start
// of the call. If this value is not set, it indicates that the frame length
// controller is disabled.
rtc::Optional<uint32_t> frame_length_action_counter;
};
// This is the interface class for encoders in AudioCoding module. Each codec
// type must have an implementation of this class.
class AudioEncoder {
@ -203,6 +230,9 @@ class AudioEncoder {
virtual void SetReceiverFrameLengthRange(int min_frame_length_ms,
int max_frame_length_ms);
// Get statistics related to audio network adaptation.
virtual ANAStats GetANAStats() const;
protected:
// Subclasses implement this to perform the actual encoding. Called by
// Encode().

View File

@ -586,6 +586,16 @@ const char* StatsReport::Value::display_name() const {
return "googResidualEchoLikelihood";
case kStatsValueNameResidualEchoLikelihoodRecentMax:
return "googResidualEchoLikelihoodRecentMax";
case kStatsValueNameAnaBitrateActionCounter:
return "googAnaBitrateActionCounter";
case kStatsValueNameAnaChannelActionCounter:
return "googAnaChannelActionCounter";
case kStatsValueNameAnaDtxActionCounter:
return "googAnaDtxActionCounter";
case kStatsValueNameAnaFecActionCounter:
return "googAnaFecActionCounter";
case kStatsValueNameAnaFrameLengthActionCounter:
return "googAnaFrameLengthActionCounter";
case kStatsValueNameRetransmitBitrate:
return "googRetransmitBitrate";
case kStatsValueNameRtt:

View File

@ -208,6 +208,11 @@ class StatsReport {
kStatsValueNameRenderDelayMs,
kStatsValueNameResidualEchoLikelihood,
kStatsValueNameResidualEchoLikelihoodRecentMax,
kStatsValueNameAnaBitrateActionCounter,
kStatsValueNameAnaChannelActionCounter,
kStatsValueNameAnaDtxActionCounter,
kStatsValueNameAnaFecActionCounter,
kStatsValueNameAnaFrameLengthActionCounter,
kStatsValueNameRetransmitBitrate,
kStatsValueNameRtt,
kStatsValueNameSecondaryDecodedRate,

View File

@ -333,6 +333,7 @@ webrtc::AudioSendStream::Stats AudioSendStream::GetStats() const {
internal::AudioState* audio_state =
static_cast<internal::AudioState*>(audio_state_.get());
stats.typing_noise_detected = audio_state->typing_noise_detected();
stats.ana_statistics = channel_proxy_->GetANAStatistics();
return stats;
}

View File

@ -301,6 +301,8 @@ struct ConfigHelper {
.WillRepeatedly(Return(kCallStats));
EXPECT_CALL(*channel_proxy_, GetRemoteRTCPReportBlocks())
.WillRepeatedly(Return(report_blocks));
EXPECT_CALL(*channel_proxy_, GetANAStatistics())
.WillRepeatedly(Return(ANAStats()));
EXPECT_CALL(voice_engine_, transmit_mixer())
.WillRepeatedly(Return(&transmit_mixer_));

View File

@ -15,6 +15,7 @@
#include <string>
#include <vector>
#include "webrtc/api/audio_codecs/audio_encoder.h"
#include "webrtc/api/audio_codecs/audio_encoder_factory.h"
#include "webrtc/api/audio_codecs/audio_format.h"
#include "webrtc/api/call/transport.h"
@ -61,6 +62,7 @@ class AudioSendStream {
float residual_echo_likelihood = -1.0f;
float residual_echo_likelihood_recent_max = -1.0f;
bool typing_noise_detected = false;
ANAStats ana_statistics;
};
struct Config {

View File

@ -15,6 +15,7 @@
#include <string>
#include <vector>
#include "webrtc/api/audio_codecs/audio_encoder.h"
#include "webrtc/api/optional.h"
#include "webrtc/api/rtpparameters.h"
#include "webrtc/api/rtpreceiverinterface.h"
@ -641,6 +642,7 @@ struct VoiceSenderInfo : public MediaSenderInfo {
float residual_echo_likelihood;
float residual_echo_likelihood_recent_max;
bool typing_noise_detected;
webrtc::ANAStats ana_statistics;
};
struct VoiceReceiverInfo : public MediaReceiverInfo {

View File

@ -2260,6 +2260,7 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
sinfo.residual_echo_likelihood_recent_max =
stats.residual_echo_likelihood_recent_max;
sinfo.typing_noise_detected = (send_ ? stats.typing_noise_detected : false);
sinfo.ana_statistics = stats.ana_statistics;
info->senders.push_back(sinfo);
}

View File

@ -546,6 +546,12 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
stats.echo_return_loss_enhancement = 1234;
stats.residual_echo_likelihood = 0.432f;
stats.residual_echo_likelihood_recent_max = 0.6f;
stats.ana_statistics.bitrate_action_counter = rtc::Optional<uint32_t>(321);
stats.ana_statistics.channel_action_counter = rtc::Optional<uint32_t>(432);
stats.ana_statistics.dtx_action_counter = rtc::Optional<uint32_t>(543);
stats.ana_statistics.fec_action_counter = rtc::Optional<uint32_t>(654);
stats.ana_statistics.frame_length_action_counter =
rtc::Optional<uint32_t>(765);
stats.typing_noise_detected = true;
return stats;
}
@ -577,6 +583,16 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
EXPECT_EQ(info.residual_echo_likelihood, stats.residual_echo_likelihood);
EXPECT_EQ(info.residual_echo_likelihood_recent_max,
stats.residual_echo_likelihood_recent_max);
EXPECT_EQ(info.ana_statistics.bitrate_action_counter,
stats.ana_statistics.bitrate_action_counter);
EXPECT_EQ(info.ana_statistics.channel_action_counter,
stats.ana_statistics.channel_action_counter);
EXPECT_EQ(info.ana_statistics.dtx_action_counter,
stats.ana_statistics.dtx_action_counter);
EXPECT_EQ(info.ana_statistics.fec_action_counter,
stats.ana_statistics.fec_action_counter);
EXPECT_EQ(info.ana_statistics.frame_length_action_counter,
stats.ana_statistics.frame_length_action_counter);
EXPECT_EQ(info.typing_noise_detected,
stats.typing_noise_detected && is_sending);
}

View File

@ -913,6 +913,7 @@ rtc_static_library("audio_network_adaptor") {
deps = [
"../..:webrtc_common",
"../../api:optional",
"../../api/audio_codecs:audio_codecs_api",
"../../common_audio",
"../../logging:rtc_event_log_api",
"../../rtc_base:protobuf_utils",

View File

@ -204,6 +204,8 @@ class AudioCodingModuleImpl final : public AudioCodingModule {
void GetDecodingCallStatistics(AudioDecodingCallStats* stats) const override;
ANAStats GetANAStats() const override;
private:
struct InputData {
uint32_t input_timestamp;
@ -1273,6 +1275,14 @@ void AudioCodingModuleImpl::GetDecodingCallStatistics(
receiver_.GetDecodingCallStatistics(call_stats);
}
ANAStats AudioCodingModuleImpl::GetANAStats() const {
rtc::CritScope lock(&acm_crit_sect_);
if (encoder_stack_)
return encoder_stack_->GetANAStats();
// If no encoder is set, return default stats.
return ANAStats();
}
} // namespace
AudioCodingModule::Config::Config()

View File

@ -135,6 +135,12 @@ void AudioNetworkAdaptorImpl::StopDebugDump() {
debug_dump_writer_.reset(nullptr);
}
ANAStats AudioNetworkAdaptorImpl::GetStats() const {
// TODO(ivoc): Actually implement the stat.
// Tracking bug: https://crbug.com/webrtc/8127
return ANAStats();
}
void AudioNetworkAdaptorImpl::DumpNetworkMetrics() {
if (debug_dump_writer_)
debug_dump_writer_->DumpNetworkMetrics(last_metrics_, rtc::TimeMillis());

View File

@ -58,6 +58,8 @@ class AudioNetworkAdaptorImpl final : public AudioNetworkAdaptor {
void StopDebugDump() override;
ANAStats GetStats() const override;
private:
void DumpNetworkMetrics();

View File

@ -270,4 +270,36 @@ TEST(AudioNetworkAdaptorImplTest, LogRuntimeConfigOnGetEncoderRuntimeConfig) {
states.audio_network_adaptor->GetEncoderRuntimeConfig();
}
TEST(AudioNetworkAdaptorImplTest, TestANAStats) {
auto states = CreateAudioNetworkAdaptor();
// Simulate some adaptation, otherwise the stats will not show anything.
AudioEncoderRuntimeConfig config1, config2;
config1.bitrate_bps = rtc::Optional<int>(32000);
config1.enable_fec = rtc::Optional<bool>(true);
config2.bitrate_bps = rtc::Optional<int>(16000);
config2.enable_fec = rtc::Optional<bool>(false);
EXPECT_CALL(*states.mock_controllers[0], MakeDecision(_))
.WillOnce(SetArgPointee<0>(config1));
states.audio_network_adaptor->GetEncoderRuntimeConfig();
EXPECT_CALL(*states.mock_controllers[0], MakeDecision(_))
.WillOnce(SetArgPointee<0>(config2));
states.audio_network_adaptor->GetEncoderRuntimeConfig();
auto ana_stats = states.audio_network_adaptor->GetStats();
// Check that the default stats are returned, as these have not been
// implemented yet). Tracking bug: https://crbug.com/8127
auto default_stats = ANAStats();
EXPECT_EQ(ana_stats.bitrate_action_counter,
default_stats.bitrate_action_counter);
EXPECT_EQ(ana_stats.channel_action_counter,
default_stats.channel_action_counter);
EXPECT_EQ(ana_stats.dtx_action_counter, default_stats.dtx_action_counter);
EXPECT_EQ(ana_stats.fec_action_counter, default_stats.fec_action_counter);
EXPECT_EQ(ana_stats.frame_length_action_counter,
default_stats.frame_length_action_counter);
}
} // namespace webrtc

View File

@ -11,6 +11,7 @@
#ifndef WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_INCLUDE_AUDIO_NETWORK_ADAPTOR_H_
#define WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_INCLUDE_AUDIO_NETWORK_ADAPTOR_H_
#include "webrtc/api/audio_codecs/audio_encoder.h"
#include "webrtc/api/optional.h"
namespace webrtc {
@ -38,7 +39,6 @@ struct AudioEncoderRuntimeConfig {
// encoder based on network metrics.
class AudioNetworkAdaptor {
public:
virtual ~AudioNetworkAdaptor() = default;
virtual void SetUplinkBandwidth(int uplink_bandwidth_bps) = 0;
@ -60,6 +60,8 @@ class AudioNetworkAdaptor {
virtual void StartDebugDump(FILE* file_handle) = 0;
virtual void StopDebugDump() = 0;
virtual ANAStats GetStats() const = 0;
};
} // namespace webrtc

View File

@ -40,6 +40,8 @@ class MockAudioNetworkAdaptor : public AudioNetworkAdaptor {
MOCK_METHOD1(StartDebugDump, void(FILE* file_handle));
MOCK_METHOD0(StopDebugDump, void());
MOCK_CONST_METHOD0(GetStats, ANAStats());
};
} // namespace webrtc

View File

@ -773,4 +773,11 @@ void AudioEncoderOpus::MaybeUpdateUplinkBandwidth() {
}
}
ANAStats AudioEncoderOpus::GetANAStats() const {
if (audio_network_adaptor_) {
return audio_network_adaptor_->GetStats();
}
return ANAStats();
}
} // namespace webrtc

View File

@ -116,6 +116,7 @@ class AudioEncoderOpus final : public AudioEncoder {
void OnReceivedOverhead(size_t overhead_bytes_per_packet) override;
void SetReceiverFrameLengthRange(int min_frame_length_ms,
int max_frame_length_ms) override;
ANAStats GetANAStats() const override;
rtc::ArrayView<const int> supported_frame_lengths_ms() const {
return config_.supported_frame_lengths_ms;
}

View File

@ -823,6 +823,8 @@ class AudioCodingModule {
virtual void GetDecodingCallStatistics(
AudioDecodingCallStats* call_stats) const = 0;
virtual ANAStats GetANAStats() const = 0;
};
} // namespace webrtc

View File

@ -224,6 +224,26 @@ void ExtractStats(const cricket::VoiceSenderInfo& info, StatsReport* report) {
}
}
report->AddString(StatsReport::kStatsValueNameMediaType, "audio");
if (info.ana_statistics.bitrate_action_counter) {
report->AddInt(StatsReport::kStatsValueNameAnaBitrateActionCounter,
*info.ana_statistics.bitrate_action_counter);
}
if (info.ana_statistics.channel_action_counter) {
report->AddInt(StatsReport::kStatsValueNameAnaChannelActionCounter,
*info.ana_statistics.channel_action_counter);
}
if (info.ana_statistics.dtx_action_counter) {
report->AddInt(StatsReport::kStatsValueNameAnaDtxActionCounter,
*info.ana_statistics.dtx_action_counter);
}
if (info.ana_statistics.fec_action_counter) {
report->AddInt(StatsReport::kStatsValueNameAnaFecActionCounter,
*info.ana_statistics.fec_action_counter);
}
if (info.ana_statistics.frame_length_action_counter) {
report->AddInt(StatsReport::kStatsValueNameAnaFrameLengthActionCounter,
*info.ana_statistics.frame_length_action_counter);
}
}
void ExtractStats(const cricket::VideoReceiverInfo& info, StatsReport* report) {

View File

@ -430,6 +430,37 @@ void VerifyVoiceSenderInfoReport(const StatsReport* report,
report, StatsReport::kStatsValueNameTypingNoiseState, &value_in_report));
std::string typing_detected = sinfo.typing_noise_detected ? "true" : "false";
EXPECT_EQ(typing_detected, value_in_report);
EXPECT_TRUE(GetValue(report,
StatsReport::kStatsValueNameAnaBitrateActionCounter,
&value_in_report));
ASSERT_TRUE(sinfo.ana_statistics.bitrate_action_counter);
EXPECT_EQ(
rtc::ToString<uint32_t>(*sinfo.ana_statistics.bitrate_action_counter),
value_in_report);
EXPECT_TRUE(GetValue(report,
StatsReport::kStatsValueNameAnaChannelActionCounter,
&value_in_report));
ASSERT_TRUE(sinfo.ana_statistics.channel_action_counter);
EXPECT_EQ(
rtc::ToString<uint32_t>(*sinfo.ana_statistics.channel_action_counter),
value_in_report);
EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameAnaDtxActionCounter,
&value_in_report));
ASSERT_TRUE(sinfo.ana_statistics.dtx_action_counter);
EXPECT_EQ(rtc::ToString<uint32_t>(*sinfo.ana_statistics.dtx_action_counter),
value_in_report);
EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameAnaFecActionCounter,
&value_in_report));
ASSERT_TRUE(sinfo.ana_statistics.fec_action_counter);
EXPECT_EQ(rtc::ToString<uint32_t>(*sinfo.ana_statistics.fec_action_counter),
value_in_report);
EXPECT_TRUE(GetValue(report,
StatsReport::kStatsValueNameAnaFrameLengthActionCounter,
&value_in_report));
ASSERT_TRUE(sinfo.ana_statistics.frame_length_action_counter);
EXPECT_EQ(rtc::ToString<uint32_t>(
*sinfo.ana_statistics.frame_length_action_counter),
value_in_report);
}
// Helper methods to avoid duplication of code.
@ -450,6 +481,16 @@ void InitVoiceSenderInfo(cricket::VoiceSenderInfo* voice_sender_info) {
voice_sender_info->echo_delay_std_ms = 111;
voice_sender_info->aec_quality_min = 112.0f;
voice_sender_info->typing_noise_detected = false;
voice_sender_info->ana_statistics.bitrate_action_counter =
rtc::Optional<uint32_t>(113);
voice_sender_info->ana_statistics.channel_action_counter =
rtc::Optional<uint32_t>(114);
voice_sender_info->ana_statistics.dtx_action_counter =
rtc::Optional<uint32_t>(115);
voice_sender_info->ana_statistics.fec_action_counter =
rtc::Optional<uint32_t>(116);
voice_sender_info->ana_statistics.frame_length_action_counter =
rtc::Optional<uint32_t>(117);
}
void UpdateVoiceSenderInfoFromAudioTrack(
@ -1988,6 +2029,7 @@ TEST_F(StatsCollectorTest, TwoLocalTracksWithSameSsrc) {
stats.AddLocalAudioTrack(audio_track_, kSsrcOfTrack);
cricket::VoiceSenderInfo voice_sender_info;
InitVoiceSenderInfo(&voice_sender_info);
voice_sender_info.add_ssrc(kSsrcOfTrack);
cricket::VoiceMediaInfo stats_read;

View File

@ -52,6 +52,7 @@ class MockVoEChannelProxy : public voe::ChannelProxy {
MOCK_CONST_METHOD0(GetRemoteRTCPReportBlocks, std::vector<ReportBlock>());
MOCK_CONST_METHOD0(GetNetworkStatistics, NetworkStatistics());
MOCK_CONST_METHOD0(GetDecodingCallStatistics, AudioDecodingCallStats());
MOCK_CONST_METHOD0(GetANAStatistics, ANAStats());
MOCK_CONST_METHOD0(GetSpeechOutputLevel, int());
MOCK_CONST_METHOD0(GetSpeechOutputLevelFullRange, int());
MOCK_CONST_METHOD0(GetTotalOutputEnergy, double());

View File

@ -2856,6 +2856,10 @@ void Channel::GetDecodingCallStatistics(AudioDecodingCallStats* stats) const {
audio_coding_->GetDecodingCallStatistics(stats);
}
ANAStats Channel::GetANAStatistics() const {
return audio_coding_->GetANAStats();
}
uint32_t Channel::GetDelayEstimate() const {
rtc::CritScope lock(&video_sync_lock_);
return audio_coding_->FilteredCurrentDelayMs() + playout_delay_ms_;

View File

@ -268,6 +268,7 @@ class Channel
// Stats.
int GetNetworkStatistics(NetworkStatistics& stats);
void GetDecodingCallStatistics(AudioDecodingCallStats* stats) const;
ANAStats GetANAStatistics() const;
// Audio+Video Sync.
uint32_t GetDelayEstimate() const;

View File

@ -144,6 +144,11 @@ AudioDecodingCallStats ChannelProxy::GetDecodingCallStatistics() const {
return stats;
}
ANAStats ChannelProxy::GetANAStatistics() const {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return channel()->GetANAStatistics();
}
int ChannelProxy::GetSpeechOutputLevel() const {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return channel()->GetSpeechOutputLevel();

View File

@ -81,6 +81,7 @@ class ChannelProxy : public RtpPacketSinkInterface {
virtual std::vector<ReportBlock> GetRemoteRTCPReportBlocks() const;
virtual NetworkStatistics GetNetworkStatistics() const;
virtual AudioDecodingCallStats GetDecodingCallStatistics() const;
virtual ANAStats GetANAStatistics() const;
virtual int GetSpeechOutputLevel() const;
virtual int GetSpeechOutputLevelFullRange() const;
// See description of "totalAudioEnergy" in the WebRTC stats spec: