Adding APM configuration in AEC dump.

The AEC dump was not self-contented enough in the sense that APM configuration is missing, and therefore, given an AEC dump, it is sometimes not clear how to reproduce problems.

This CL tries to address the problem.

Note that this cannot guarantee a perfect reproduction in all cases. Dumping from the middle of a call makes the initial states unknown and thus may make the result non-reproducible.

BUG=
TEST= 1. new dump in Chromium and unpack
      2. unpack old dump

R=andrew@webrtc.org, peah@webrtc.org

Review URL: https://codereview.webrtc.org/1348903004 .

Cr-Commit-Position: refs/heads/master@{#10155}
This commit is contained in:
Minyue 2015-10-03 00:39:14 +02:00
parent 371dc7e560
commit 13b96ba90f
9 changed files with 143 additions and 19 deletions

View File

@ -539,6 +539,8 @@ int AudioProcessingImpl::ProcessStream(const float* const* src,
#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
if (debug_file_->Open()) {
RETURN_ON_ERR(WriteConfigMessage(false));
event_msg_->set_type(audioproc::Event::STREAM);
audioproc::Stream* msg = event_msg_->mutable_stream();
const size_t channel_size =
@ -920,10 +922,8 @@ int AudioProcessingImpl::StartDebugRecording(
return kFileError;
}
int err = WriteInitMessage();
if (err != kNoError) {
return err;
}
RETURN_ON_ERR(WriteConfigMessage(true));
RETURN_ON_ERR(WriteInitMessage());
return kNoError;
#else
return kUnsupportedFunctionError;
@ -949,10 +949,8 @@ int AudioProcessingImpl::StartDebugRecording(FILE* handle) {
return kFileError;
}
int err = WriteInitMessage();
if (err != kNoError) {
return err;
}
RETURN_ON_ERR(WriteConfigMessage(true));
RETURN_ON_ERR(WriteInitMessage());
return kNoError;
#else
return kUnsupportedFunctionError;
@ -1222,11 +1220,52 @@ int AudioProcessingImpl::WriteInitMessage() {
msg->set_output_sample_rate(api_format_.output_stream().sample_rate_hz());
// TODO(ekmeyerson): Add reverse output fields to event_msg_.
int err = WriteMessageToDebugFile();
if (err != kNoError) {
return err;
RETURN_ON_ERR(WriteMessageToDebugFile());
return kNoError;
}
int AudioProcessingImpl::WriteConfigMessage(bool forced) {
audioproc::Config config;
config.set_aec_enabled(echo_cancellation_->is_enabled());
config.set_aec_delay_agnostic_enabled(
echo_cancellation_->is_delay_agnostic_enabled());
config.set_aec_drift_compensation_enabled(
echo_cancellation_->is_drift_compensation_enabled());
config.set_aec_extended_filter_enabled(
echo_cancellation_->is_extended_filter_enabled());
config.set_aec_suppression_level(
static_cast<int>(echo_cancellation_->suppression_level()));
config.set_aecm_enabled(echo_control_mobile_->is_enabled());
config.set_aecm_comfort_noise_enabled(
echo_control_mobile_->is_comfort_noise_enabled());
config.set_aecm_routing_mode(
static_cast<int>(echo_control_mobile_->routing_mode()));
config.set_agc_enabled(gain_control_->is_enabled());
config.set_agc_mode(static_cast<int>(gain_control_->mode()));
config.set_agc_limiter_enabled(gain_control_->is_limiter_enabled());
config.set_noise_robust_agc_enabled(use_new_agc_);
config.set_hpf_enabled(high_pass_filter_->is_enabled());
config.set_ns_enabled(noise_suppression_->is_enabled());
config.set_ns_level(static_cast<int>(noise_suppression_->level()));
config.set_transient_suppression_enabled(transient_suppressor_enabled_);
std::string serialized_config = config.SerializeAsString();
if (!forced && last_serialized_config_ == serialized_config) {
return kNoError;
}
last_serialized_config_ = serialized_config;
event_msg_->set_type(audioproc::Event::CONFIG);
event_msg_->mutable_config()->CopyFrom(config);
RETURN_ON_ERR(WriteMessageToDebugFile());
return kNoError;
}
#endif // WEBRTC_AUDIOPROC_DEBUG_DUMP

View File

@ -162,9 +162,18 @@ class AudioProcessingImpl : public AudioProcessing {
// out into a separate class with an "enabled" and "disabled" implementation.
int WriteMessageToDebugFile();
int WriteInitMessage();
// Writes Config message. If not |forced|, only writes the current config if
// it is different from the last saved one; if |forced|, writes the config
// regardless of the last saved.
int WriteConfigMessage(bool forced);
rtc::scoped_ptr<FileWrapper> debug_file_;
rtc::scoped_ptr<audioproc::Event> event_msg_; // Protobuf message.
std::string event_str_; // Memory for protobuf serialization.
// Serialized string of last saved APM configuration.
std::string last_serialized_config_;
#endif
// Format of processing streams at input/output call sites.

View File

@ -2,6 +2,8 @@ syntax = "proto2";
option optimize_for = LITE_RUNTIME;
package webrtc.audioproc;
// Contains the format of input/output/reverse audio. An Init message is added
// when any of the fields are changed.
message Init {
optional int32 sample_rate = 1;
optional int32 device_sample_rate = 2 [deprecated=true];
@ -39,11 +41,41 @@ message Stream {
repeated bytes output_channel = 8;
}
// Contains the configurations of various APM component. A Config message is
// added when any of the fields are changed.
message Config {
// Next field number 17.
// Acoustic echo canceler.
optional bool aec_enabled = 1;
optional bool aec_delay_agnostic_enabled = 2;
optional bool aec_drift_compensation_enabled = 3;
optional bool aec_extended_filter_enabled = 4;
optional int32 aec_suppression_level = 5;
// Mobile AEC.
optional bool aecm_enabled = 6;
optional bool aecm_comfort_noise_enabled = 7;
optional int32 aecm_routing_mode = 8;
// Automatic gain controller.
optional bool agc_enabled = 9;
optional int32 agc_mode = 10;
optional bool agc_limiter_enabled = 11;
optional bool noise_robust_agc_enabled = 12;
// High pass filter.
optional bool hpf_enabled = 13;
// Noise suppression.
optional bool ns_enabled = 14;
optional int32 ns_level = 15;
// Transient suppression.
optional bool transient_suppression_enabled = 16;
}
message Event {
enum Type {
INIT = 0;
REVERSE_STREAM = 1;
STREAM = 2;
CONFIG = 3;
UNKNOWN_EVENT = 4;
}
required Type type = 1;
@ -51,4 +83,5 @@ message Event {
optional Init init = 2;
optional ReverseStream reverse_stream = 3;
optional Stream stream = 4;
optional Config config = 5;
}

View File

@ -280,6 +280,14 @@ bool EchoCancellationImpl::is_delay_logging_enabled() const {
return delay_logging_enabled_;
}
bool EchoCancellationImpl::is_delay_agnostic_enabled() const {
return delay_agnostic_enabled_;
}
bool EchoCancellationImpl::is_extended_filter_enabled() const {
return extended_filter_enabled_;
}
// TODO(bjornv): How should we handle the multi-channel case?
int EchoCancellationImpl::GetDelayMetrics(int* median, int* std) {
float fraction_poor_delays = 0;

View File

@ -32,19 +32,22 @@ class EchoCancellationImpl : public EchoCancellation,
// EchoCancellation implementation.
bool is_enabled() const override;
int stream_drift_samples() const override;
SuppressionLevel suppression_level() const override;
bool is_drift_compensation_enabled() const override;
// ProcessingComponent implementation.
int Initialize() override;
void SetExtraOptions(const Config& config) override;
bool is_delay_agnostic_enabled() const;
bool is_extended_filter_enabled() const;
private:
// EchoCancellation implementation.
int Enable(bool enable) override;
int enable_drift_compensation(bool enable) override;
bool is_drift_compensation_enabled() const override;
void set_stream_drift_samples(int drift) override;
int set_suppression_level(SuppressionLevel level) override;
SuppressionLevel suppression_level() const override;
int enable_metrics(bool enable) override;
bool are_metrics_enabled() const override;
bool stream_has_echo() const override;

View File

@ -31,6 +31,8 @@ class EchoControlMobileImpl : public EchoControlMobile,
// EchoControlMobile implementation.
bool is_enabled() const override;
RoutingMode routing_mode() const override;
bool is_comfort_noise_enabled() const override;
// ProcessingComponent implementation.
int Initialize() override;
@ -39,9 +41,7 @@ class EchoControlMobileImpl : public EchoControlMobile,
// EchoControlMobile implementation.
int Enable(bool enable) override;
int set_routing_mode(RoutingMode mode) override;
RoutingMode routing_mode() const override;
int enable_comfort_noise(bool enable) override;
bool is_comfort_noise_enabled() const override;
int SetEchoPath(const void* echo_path, size_t size_bytes) override;
int GetEchoPath(void* echo_path, size_t size_bytes) const override;

View File

@ -38,19 +38,19 @@ class GainControlImpl : public GainControl,
// GainControl implementation.
bool is_enabled() const override;
int stream_analog_level() override;
bool is_limiter_enabled() const override;
Mode mode() const override;
private:
// GainControl implementation.
int Enable(bool enable) override;
int set_stream_analog_level(int level) override;
int set_mode(Mode mode) override;
Mode mode() const override;
int set_target_level_dbfs(int level) override;
int target_level_dbfs() const override;
int set_compression_gain_db(int gain) override;
int compression_gain_db() const override;
int enable_limiter(bool enable) override;
bool is_limiter_enabled() const override;
int set_analog_level_limits(int minimum, int maximum) override;
int analog_level_minimum() const override;
int analog_level_maximum() const override;

View File

@ -32,12 +32,12 @@ class NoiseSuppressionImpl : public NoiseSuppression,
// NoiseSuppression implementation.
bool is_enabled() const override;
float speech_probability() const override;
Level level() const override;
private:
// NoiseSuppression implementation.
int Enable(bool enable) override;
int set_level(Level level) override;
Level level() const override;
// ProcessingComponent implementation.
void* CreateHandle() const override;

View File

@ -40,6 +40,11 @@ DEFINE_bool(text,
false,
"Write non-audio files as text files instead of binary files.");
#define PRINT_CONFIG(field_name) \
if (msg.has_##field_name()) { \
fprintf(settings_file, " " #field_name ": %d\n", msg.field_name()); \
}
namespace webrtc {
using audioproc::Event;
@ -83,6 +88,9 @@ int do_main(int argc, char* argv[]) {
rtc::scoped_ptr<RawFile> reverse_raw_file;
rtc::scoped_ptr<RawFile> input_raw_file;
rtc::scoped_ptr<RawFile> output_raw_file;
FILE* settings_file = OpenFile(FLAGS_settings_file, "wb");
while (ReadMessageFromFile(debug_file, &event_msg)) {
if (event_msg.type() == Event::REVERSE_STREAM) {
if (!event_msg.has_reverse_stream()) {
@ -217,13 +225,37 @@ int do_main(int argc, char* argv[]) {
}
}
}
} else if (event_msg.type() == Event::CONFIG) {
if (!event_msg.has_config()) {
printf("Corrupt input file: Config missing.\n");
return 1;
}
const audioproc::Config msg = event_msg.config();
fprintf(settings_file, "APM re-config at frame: %d\n", frame_count);
PRINT_CONFIG(aec_enabled);
PRINT_CONFIG(aec_delay_agnostic_enabled);
PRINT_CONFIG(aec_drift_compensation_enabled);
PRINT_CONFIG(aec_extended_filter_enabled);
PRINT_CONFIG(aec_suppression_level);
PRINT_CONFIG(aecm_enabled);
PRINT_CONFIG(aecm_comfort_noise_enabled);
PRINT_CONFIG(aecm_routing_mode);
PRINT_CONFIG(agc_enabled);
PRINT_CONFIG(agc_mode);
PRINT_CONFIG(agc_limiter_enabled);
PRINT_CONFIG(noise_robust_agc_enabled);
PRINT_CONFIG(hpf_enabled);
PRINT_CONFIG(ns_enabled);
PRINT_CONFIG(ns_level);
PRINT_CONFIG(transient_suppression_enabled);
} else if (event_msg.type() == Event::INIT) {
if (!event_msg.has_init()) {
printf("Corrupt input file: Init missing.\n");
return 1;
}
static FILE* settings_file = OpenFile(FLAGS_settings_file, "wb");
const Init msg = event_msg.init();
// These should print out zeros if they're missing.
fprintf(settings_file, "Init at frame: %d\n", frame_count);