Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(478)

Unified Diff: webrtc/modules/audio_processing/audio_processing_impl.cc

Issue 1424663003: Lock scheme #8: Introduced the new locking scheme (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@add_threadcheckers_CL
Patch Set: Created a threadsafe wrapper for the random generator in the locktest. Fixed an unprotected variabl… Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webrtc/modules/audio_processing/audio_processing_impl.cc
diff --git a/webrtc/modules/audio_processing/audio_processing_impl.cc b/webrtc/modules/audio_processing/audio_processing_impl.cc
index 75bfb20a9002ff41a3c435b1576b434ae41f637c..48f23b18563754d2db7159042cf5eee2fa525c96 100644
--- a/webrtc/modules/audio_processing/audio_processing_impl.cc
+++ b/webrtc/modules/audio_processing/audio_processing_impl.cc
@@ -37,7 +37,6 @@ extern "C" {
#include "webrtc/modules/audio_processing/transient/transient_suppressor.h"
#include "webrtc/modules/audio_processing/voice_detection_impl.h"
#include "webrtc/modules/include/module_common_types.h"
-#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
#include "webrtc/system_wrappers/include/file_wrapper.h"
#include "webrtc/system_wrappers/include/logging.h"
#include "webrtc/system_wrappers/include/metrics.h"
@@ -75,9 +74,41 @@ static bool LayoutHasKeyboard(AudioProcessing::ChannelLayout layout) {
assert(false);
return false;
}
-
} // namespace
+struct AudioProcessingImpl::ApmPublicSubmodules {
+ ApmPublicSubmodules()
+ : echo_cancellation(nullptr),
+ echo_control_mobile(nullptr),
+ gain_control(nullptr),
+ high_pass_filter(nullptr),
+ level_estimator(nullptr),
+ noise_suppression(nullptr),
+ voice_detection(nullptr) {}
+ // Accessed externally of APM without any lock acquired.
+ EchoCancellationImpl* echo_cancellation;
+ EchoControlMobileImpl* echo_control_mobile;
+ GainControlImpl* gain_control;
+ HighPassFilterImpl* high_pass_filter;
+ LevelEstimatorImpl* level_estimator;
+ NoiseSuppressionImpl* noise_suppression;
+ VoiceDetectionImpl* voice_detection;
+ rtc::scoped_ptr<GainControlForNewAgc> gain_control_for_new_agc;
+
+ // Accessed internally from both render and capture.
+ rtc::scoped_ptr<TransientSuppressor> transient_suppressor;
+ rtc::scoped_ptr<IntelligibilityEnhancer> intelligibility_enhancer;
+};
+
+struct AudioProcessingImpl::ApmPrivateSubmodules {
+ explicit ApmPrivateSubmodules(Beamformer<float>* beamformer)
+ : beamformer(beamformer) {}
+ // Accessed internally from capture or during initialization
+ std::list<ProcessingComponent*> component_list;
+ rtc::scoped_ptr<Beamformer<float>> beamformer;
+ rtc::scoped_ptr<AgcManagerDirect> agc_manager;
+};
+
// Throughout webrtc, it's assumed that success is represented by zero.
static_assert(AudioProcessing::kNoError == 0, "kNoError must be zero");
@@ -172,7 +203,7 @@ AudioProcessing* AudioProcessing::Create(const Config& config,
AudioProcessingImpl* apm = new AudioProcessingImpl(config, beamformer);
if (apm->Initialize() != kNoError) {
delete apm;
- apm = NULL;
+ apm = nullptr;
}
return apm;
@@ -183,98 +214,90 @@ AudioProcessingImpl::AudioProcessingImpl(const Config& config)
AudioProcessingImpl::AudioProcessingImpl(const Config& config,
Beamformer<float>* beamformer)
- : echo_cancellation_(NULL),
- echo_control_mobile_(NULL),
- gain_control_(NULL),
- high_pass_filter_(NULL),
- level_estimator_(NULL),
- noise_suppression_(NULL),
- voice_detection_(NULL),
- crit_(CriticalSectionWrapper::CreateCriticalSection()),
-#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
- debug_file_(FileWrapper::Create()),
- event_msg_(new audioproc::Event()),
-#endif
- fwd_proc_format_(kSampleRate16kHz),
- rev_proc_format_(kSampleRate16kHz, 1),
- split_rate_(kSampleRate16kHz),
- stream_delay_ms_(0),
- delay_offset_ms_(0),
- was_stream_delay_set_(false),
- last_stream_delay_ms_(0),
- last_aec_system_delay_ms_(0),
- stream_delay_jumps_(-1),
- aec_system_delay_jumps_(-1),
- output_will_be_muted_(false),
- key_pressed_(false),
+ : public_submodules_(new ApmPublicSubmodules()),
+ private_submodules_(new ApmPrivateSubmodules(beamformer)),
+ constants_(config.Get<ExperimentalAgc>().startup_min_volume,
+ config.Get<Beamforming>().array_geometry,
+ config.Get<Beamforming>().target_direction,
#if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS)
- use_new_agc_(false),
+ false,
#else
- use_new_agc_(config.Get<ExperimentalAgc>().enabled),
+ config.Get<ExperimentalAgc>().enabled,
#endif
- agc_startup_min_volume_(config.Get<ExperimentalAgc>().startup_min_volume),
+ config.Get<Intelligibility>().enabled,
+ config.Get<Beamforming>().enabled),
+
#if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS)
- transient_suppressor_enabled_(false),
+ capture_(false)
#else
- transient_suppressor_enabled_(config.Get<ExperimentalNs>().enabled),
+ capture_(config.Get<ExperimentalNs>().enabled)
#endif
- beamformer_enabled_(config.Get<Beamforming>().enabled),
- beamformer_(beamformer),
- array_geometry_(config.Get<Beamforming>().array_geometry),
- target_direction_(config.Get<Beamforming>().target_direction),
- intelligibility_enabled_(config.Get<Intelligibility>().enabled) {
- echo_cancellation_ = new EchoCancellationImpl(this, crit_);
- component_list_.push_back(echo_cancellation_);
-
- echo_control_mobile_ = new EchoControlMobileImpl(this, crit_);
- component_list_.push_back(echo_control_mobile_);
-
- gain_control_ = new GainControlImpl(this, crit_);
- component_list_.push_back(gain_control_);
-
- high_pass_filter_ = new HighPassFilterImpl(this, crit_);
- component_list_.push_back(high_pass_filter_);
-
- level_estimator_ = new LevelEstimatorImpl(this, crit_);
- component_list_.push_back(level_estimator_);
-
- noise_suppression_ = new NoiseSuppressionImpl(this, crit_);
- component_list_.push_back(noise_suppression_);
-
- voice_detection_ = new VoiceDetectionImpl(this, crit_);
- component_list_.push_back(voice_detection_);
-
- gain_control_for_new_agc_.reset(new GainControlForNewAgc(gain_control_));
+{
+ {
+ rtc::CritScope cs_render(&crit_render_);
+ rtc::CritScope cs_capture(&crit_capture_);
+
+ public_submodules_->echo_cancellation =
+ new EchoCancellationImpl(this, &crit_render_, &crit_capture_);
+ public_submodules_->echo_control_mobile =
+ new EchoControlMobileImpl(this, &crit_render_, &crit_capture_);
+ public_submodules_->gain_control =
+ new GainControlImpl(this, &crit_capture_, &crit_capture_);
+ public_submodules_->high_pass_filter =
+ new HighPassFilterImpl(this, &crit_capture_);
+ public_submodules_->level_estimator =
+ new LevelEstimatorImpl(this, &crit_capture_);
+ public_submodules_->noise_suppression =
+ new NoiseSuppressionImpl(this, &crit_capture_);
+ public_submodules_->voice_detection =
+ new VoiceDetectionImpl(this, &crit_capture_);
+ public_submodules_->gain_control_for_new_agc.reset(
+ new GainControlForNewAgc(public_submodules_->gain_control));
+
+ private_submodules_->component_list.push_back(
+ public_submodules_->echo_cancellation);
+ private_submodules_->component_list.push_back(
+ public_submodules_->echo_control_mobile);
+ private_submodules_->component_list.push_back(
+ public_submodules_->gain_control);
+ private_submodules_->component_list.push_back(
+ public_submodules_->high_pass_filter);
+ private_submodules_->component_list.push_back(
+ public_submodules_->level_estimator);
+ private_submodules_->component_list.push_back(
+ public_submodules_->noise_suppression);
+ private_submodules_->component_list.push_back(
+ public_submodules_->voice_detection);
+ }
SetExtraOptions(config);
}
AudioProcessingImpl::~AudioProcessingImpl() {
- {
- CriticalSectionScoped crit_scoped(crit_);
- // Depends on gain_control_ and gain_control_for_new_agc_.
- agc_manager_.reset();
- // Depends on gain_control_.
- gain_control_for_new_agc_.reset();
- while (!component_list_.empty()) {
- ProcessingComponent* component = component_list_.front();
- component->Destroy();
- delete component;
- component_list_.pop_front();
- }
+ // Depends on gain_control_ and
+ // public_submodules_->gain_control_for_new_agc.
+ private_submodules_->agc_manager.reset();
+ // Depends on gain_control_.
+ public_submodules_->gain_control_for_new_agc.reset();
+ while (!private_submodules_->component_list.empty()) {
+ ProcessingComponent* component =
+ private_submodules_->component_list.front();
+ component->Destroy();
+ delete component;
+ private_submodules_->component_list.pop_front();
+ }
#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
- if (debug_file_->Open()) {
- debug_file_->CloseFile();
- }
-#endif
+ if (debug_dump_.debug_file->Open()) {
+ debug_dump_.debug_file->CloseFile();
}
- delete crit_;
- crit_ = NULL;
+#endif
}
int AudioProcessingImpl::Initialize() {
- CriticalSectionScoped crit_scoped(crit_);
+ // Run in a single-threaded manner during initialization.
+ rtc::CritScope cs_render(&crit_render_);
+ rtc::CritScope cs_capture(&crit_capture_);
return InitializeLocked();
}
@@ -302,66 +325,73 @@ int AudioProcessingImpl::Initialize(int input_sample_rate_hz,
}
int AudioProcessingImpl::Initialize(const ProcessingConfig& processing_config) {
- CriticalSectionScoped crit_scoped(crit_);
+ // Run in a single-threaded manner during initialization.
+ rtc::CritScope cs_render(&crit_render_);
+ rtc::CritScope cs_capture(&crit_capture_);
return InitializeLocked(processing_config);
}
-int AudioProcessingImpl::MaybeInitializeLockedRender(
+int AudioProcessingImpl::MaybeInitializeRender(
const ProcessingConfig& processing_config) {
- return MaybeInitializeLocked(processing_config);
+ return MaybeInitialize(processing_config);
}
-int AudioProcessingImpl::MaybeInitializeLockedCapture(
+int AudioProcessingImpl::MaybeInitializeCapture(
const ProcessingConfig& processing_config) {
- return MaybeInitializeLocked(processing_config);
+ return MaybeInitialize(processing_config);
}
// Calls InitializeLocked() if any of the audio parameters have changed from
-// their current values.
-int AudioProcessingImpl::MaybeInitializeLocked(
+// their current values (needs to be called while holding the crit_render_lock).
+int AudioProcessingImpl::MaybeInitialize(
const ProcessingConfig& processing_config) {
- if (processing_config == shared_state_.api_format_) {
+ // Called from both threads. Thread check is therefore not possible.
+ if (processing_config == formats_.api_format) {
return kNoError;
}
+
+ rtc::CritScope cs_capture(&crit_capture_);
return InitializeLocked(processing_config);
}
int AudioProcessingImpl::InitializeLocked() {
const int fwd_audio_buffer_channels =
- beamformer_enabled_
- ? shared_state_.api_format_.input_stream().num_channels()
- : shared_state_.api_format_.output_stream().num_channels();
+ constants_.beamformer_enabled
+ ? formats_.api_format.input_stream().num_channels()
+ : formats_.api_format.output_stream().num_channels();
const int rev_audio_buffer_out_num_frames =
- shared_state_.api_format_.reverse_output_stream().num_frames() == 0
- ? rev_proc_format_.num_frames()
- : shared_state_.api_format_.reverse_output_stream().num_frames();
- if (shared_state_.api_format_.reverse_input_stream().num_channels() > 0) {
- render_audio_.reset(new AudioBuffer(
- shared_state_.api_format_.reverse_input_stream().num_frames(),
- shared_state_.api_format_.reverse_input_stream().num_channels(),
- rev_proc_format_.num_frames(), rev_proc_format_.num_channels(),
+ formats_.api_format.reverse_output_stream().num_frames() == 0
+ ? formats_.rev_proc_format.num_frames()
+ : formats_.api_format.reverse_output_stream().num_frames();
+ if (formats_.api_format.reverse_input_stream().num_channels() > 0) {
+ render_.render_audio.reset(new AudioBuffer(
+ formats_.api_format.reverse_input_stream().num_frames(),
+ formats_.api_format.reverse_input_stream().num_channels(),
+ formats_.rev_proc_format.num_frames(),
+ formats_.rev_proc_format.num_channels(),
rev_audio_buffer_out_num_frames));
if (rev_conversion_needed()) {
- render_converter_ = AudioConverter::Create(
- shared_state_.api_format_.reverse_input_stream().num_channels(),
- shared_state_.api_format_.reverse_input_stream().num_frames(),
- shared_state_.api_format_.reverse_output_stream().num_channels(),
- shared_state_.api_format_.reverse_output_stream().num_frames());
+ render_.render_converter = AudioConverter::Create(
+ formats_.api_format.reverse_input_stream().num_channels(),
+ formats_.api_format.reverse_input_stream().num_frames(),
+ formats_.api_format.reverse_output_stream().num_channels(),
+ formats_.api_format.reverse_output_stream().num_frames());
} else {
- render_converter_.reset(nullptr);
+ render_.render_converter.reset(nullptr);
}
} else {
- render_audio_.reset(nullptr);
- render_converter_.reset(nullptr);
+ render_.render_audio.reset(nullptr);
+ render_.render_converter.reset(nullptr);
}
- capture_audio_.reset(
- new AudioBuffer(shared_state_.api_format_.input_stream().num_frames(),
- shared_state_.api_format_.input_stream().num_channels(),
- fwd_proc_format_.num_frames(), fwd_audio_buffer_channels,
- shared_state_.api_format_.output_stream().num_frames()));
+ capture_.capture_audio.reset(
+ new AudioBuffer(formats_.api_format.input_stream().num_frames(),
+ formats_.api_format.input_stream().num_channels(),
+ capture_nonlocked_.fwd_proc_format.num_frames(),
+ fwd_audio_buffer_channels,
+ formats_.api_format.output_stream().num_frames()));
// Initialize all components.
- for (auto item : component_list_) {
+ for (auto item : private_submodules_->component_list) {
int err = item->Initialize();
if (err != kNoError) {
return err;
@@ -377,7 +407,7 @@ int AudioProcessingImpl::InitializeLocked() {
InitializeIntelligibility();
#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
- if (debug_file_->Open()) {
+ if (debug_dump_.debug_file->Open()) {
int err = WriteInitMessage();
if (err != kNoError) {
return err;
@@ -389,7 +419,6 @@ int AudioProcessingImpl::InitializeLocked() {
}
int AudioProcessingImpl::InitializeLocked(const ProcessingConfig& config) {
- // TODO(peah): Refactor to be allowed to verify using thread annotations.
for (const auto& stream : config.streams) {
if (stream.num_channels() < 0) {
return kBadNumberChannelsError;
@@ -409,18 +438,18 @@ int AudioProcessingImpl::InitializeLocked(const ProcessingConfig& config) {
return kBadNumberChannelsError;
}
- if (beamformer_enabled_ &&
- (static_cast<size_t>(num_in_channels) != array_geometry_.size() ||
- num_out_channels > 1)) {
+ if (constants_.beamformer_enabled && (static_cast<size_t>(num_in_channels) !=
+ constants_.array_geometry.size() ||
+ num_out_channels > 1)) {
return kBadNumberChannelsError;
}
- shared_state_.api_format_ = config;
+ formats_.api_format = config;
// We process at the closest native rate >= min(input rate, output rate)...
const int min_proc_rate =
- std::min(shared_state_.api_format_.input_stream().sample_rate_hz(),
- shared_state_.api_format_.output_stream().sample_rate_hz());
+ std::min(formats_.api_format.input_stream().sample_rate_hz(),
+ formats_.api_format.output_stream().sample_rate_hz());
int fwd_proc_rate;
for (size_t i = 0; i < kNumNativeSampleRates; ++i) {
fwd_proc_rate = kNativeSampleRatesHz[i];
@@ -429,20 +458,20 @@ int AudioProcessingImpl::InitializeLocked(const ProcessingConfig& config) {
}
}
// ...with one exception.
- if (echo_control_mobile_->is_enabled() &&
+ if (public_submodules_->echo_control_mobile->is_enabled() &&
min_proc_rate > kMaxAECMSampleRateHz) {
fwd_proc_rate = kMaxAECMSampleRateHz;
}
- fwd_proc_format_ = StreamConfig(fwd_proc_rate);
+ capture_nonlocked_.fwd_proc_format = StreamConfig(fwd_proc_rate);
// We normally process the reverse stream at 16 kHz. Unless...
int rev_proc_rate = kSampleRate16kHz;
- if (fwd_proc_format_.sample_rate_hz() == kSampleRate8kHz) {
+ if (capture_nonlocked_.fwd_proc_format.sample_rate_hz() == kSampleRate8kHz) {
// ...the forward stream is at 8 kHz.
rev_proc_rate = kSampleRate8kHz;
} else {
- if (shared_state_.api_format_.reverse_input_stream().sample_rate_hz() ==
+ if (formats_.api_format.reverse_input_stream().sample_rate_hz() ==
kSampleRate32kHz) {
// ...or the input is at 32 kHz, in which case we use the splitting
// filter rather than the resampler.
@@ -452,61 +481,66 @@ int AudioProcessingImpl::InitializeLocked(const ProcessingConfig& config) {
// Always downmix the reverse stream to mono for analysis. This has been
// demonstrated to work well for AEC in most practical scenarios.
- rev_proc_format_ = StreamConfig(rev_proc_rate, 1);
+ formats_.rev_proc_format = StreamConfig(rev_proc_rate, 1);
- if (fwd_proc_format_.sample_rate_hz() == kSampleRate32kHz ||
- fwd_proc_format_.sample_rate_hz() == kSampleRate48kHz) {
- split_rate_ = kSampleRate16kHz;
+ if (capture_nonlocked_.fwd_proc_format.sample_rate_hz() == kSampleRate32kHz ||
+ capture_nonlocked_.fwd_proc_format.sample_rate_hz() == kSampleRate48kHz) {
+ capture_nonlocked_.split_rate = kSampleRate16kHz;
} else {
- split_rate_ = fwd_proc_format_.sample_rate_hz();
+ capture_nonlocked_.split_rate =
+ capture_nonlocked_.fwd_proc_format.sample_rate_hz();
}
return InitializeLocked();
}
void AudioProcessingImpl::SetExtraOptions(const Config& config) {
- CriticalSectionScoped crit_scoped(crit_);
- for (auto item : component_list_) {
+ // Run in a single-threaded manner when setting the extra options.
+ rtc::CritScope cs_render(&crit_render_);
+ rtc::CritScope cs_capture(&crit_capture_);
+ for (auto item : private_submodules_->component_list) {
item->SetExtraOptions(config);
}
- if (transient_suppressor_enabled_ != config.Get<ExperimentalNs>().enabled) {
- transient_suppressor_enabled_ = config.Get<ExperimentalNs>().enabled;
+ if (capture_.transient_suppressor_enabled !=
+ config.Get<ExperimentalNs>().enabled) {
+ capture_.transient_suppressor_enabled =
+ config.Get<ExperimentalNs>().enabled;
InitializeTransient();
}
}
-
int AudioProcessingImpl::proc_sample_rate_hz() const {
- // TODO(peah): Refactor to be allowed to verify using thread annotations.
- return fwd_proc_format_.sample_rate_hz();
+ // Used as callback from submodules, hence locking is not allowed.
+ return capture_nonlocked_.fwd_proc_format.sample_rate_hz();
}
int AudioProcessingImpl::proc_split_sample_rate_hz() const {
- // TODO(peah): Refactor to be allowed to verify using thread annotations.
-
- return split_rate_;
+ // Used as callback from submodules, hence locking is not allowed.
+ return capture_nonlocked_.split_rate;
}
int AudioProcessingImpl::num_reverse_channels() const {
- // TODO(peah): Refactor to be allowed to verify using thread annotations.
- return rev_proc_format_.num_channels();
+ // Used as callback from submodules, hence locking is not allowed.
+ return formats_.rev_proc_format.num_channels();
}
int AudioProcessingImpl::num_input_channels() const {
- return shared_state_.api_format_.input_stream().num_channels();
+ // Used as callback from submodules, hence locking is not allowed.
+ return formats_.api_format.input_stream().num_channels();
}
int AudioProcessingImpl::num_output_channels() const {
- // TODO(peah): Refactor to be allowed to verify using thread annotations.
- return shared_state_.api_format_.output_stream().num_channels();
+ // Used as callback from submodules, hence locking is not allowed.
+ return formats_.api_format.output_stream().num_channels();
}
void AudioProcessingImpl::set_output_will_be_muted(bool muted) {
- CriticalSectionScoped lock(crit_);
- output_will_be_muted_ = muted;
- if (agc_manager_.get()) {
- agc_manager_->SetCaptureMuted(output_will_be_muted_);
+ rtc::CritScope cs(&crit_capture_);
+ capture_.output_will_be_muted = muted;
+ if (private_submodules_->agc_manager.get()) {
+ private_submodules_->agc_manager->SetCaptureMuted(
+ capture_.output_will_be_muted);
}
}
@@ -518,13 +552,20 @@ int AudioProcessingImpl::ProcessStream(const float* const* src,
int output_sample_rate_hz,
ChannelLayout output_layout,
float* const* dest) {
- CriticalSectionScoped crit_scoped(crit_);
- StreamConfig input_stream = shared_state_.api_format_.input_stream();
+ StreamConfig input_stream;
+ StreamConfig output_stream;
+ {
+ // Access the formats_.api_format.input_stream beneath the capture lock.
+ // The lock must be released as it is later required in the call
+ // to ProcessStream(,,,);
+ rtc::CritScope cs(&crit_capture_);
+ input_stream = formats_.api_format.input_stream();
+ output_stream = formats_.api_format.output_stream();
+ }
+
input_stream.set_sample_rate_hz(input_sample_rate_hz);
input_stream.set_num_channels(ChannelsFromLayout(input_layout));
input_stream.set_has_keyboard(LayoutHasKeyboard(input_layout));
-
- StreamConfig output_stream = shared_state_.api_format_.output_stream();
output_stream.set_sample_rate_hz(output_sample_rate_hz);
output_stream.set_num_channels(ChannelsFromLayout(output_layout));
output_stream.set_has_keyboard(LayoutHasKeyboard(output_layout));
@@ -539,50 +580,61 @@ int AudioProcessingImpl::ProcessStream(const float* const* src,
const StreamConfig& input_config,
const StreamConfig& output_config,
float* const* dest) {
- CriticalSectionScoped crit_scoped(crit_);
- if (!src || !dest) {
- return kNullPointerError;
- }
+ ProcessingConfig processing_config;
+ {
+ // Acquire the capture lock in order to safely call the function
+ // that retrieves the render side data. This function accesses apm
+ // getters that need the capture lock held when being called.
+ rtc::CritScope cs_capture(&crit_capture_);
+ public_submodules_->echo_cancellation->ReadQueuedRenderData();
+ public_submodules_->echo_control_mobile->ReadQueuedRenderData();
+ public_submodules_->gain_control->ReadQueuedRenderData();
+
+ if (!src || !dest) {
+ return kNullPointerError;
+ }
- echo_cancellation_->ReadQueuedRenderData();
- echo_control_mobile_->ReadQueuedRenderData();
- gain_control_->ReadQueuedRenderData();
+ processing_config = formats_.api_format;
+ }
- ProcessingConfig processing_config = shared_state_.api_format_;
processing_config.input_stream() = input_config;
processing_config.output_stream() = output_config;
- RETURN_ON_ERR(MaybeInitializeLockedCapture(processing_config));
+ {
+ // Do conditional reinitialization.
+ rtc::CritScope cs_render(&crit_render_);
+ RETURN_ON_ERR(MaybeInitializeCapture(processing_config));
+ }
+ rtc::CritScope cs_capture(&crit_capture_);
assert(processing_config.input_stream().num_frames() ==
- shared_state_.api_format_.input_stream().num_frames());
+ formats_.api_format.input_stream().num_frames());
#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
- if (debug_file_->Open()) {
+ if (debug_dump_.debug_file->Open()) {
RETURN_ON_ERR(WriteConfigMessage(false));
- event_msg_->set_type(audioproc::Event::STREAM);
- audioproc::Stream* msg = event_msg_->mutable_stream();
+ debug_dump_.capture.event_msg->set_type(audioproc::Event::STREAM);
+ audioproc::Stream* msg = debug_dump_.capture.event_msg->mutable_stream();
const size_t channel_size =
- sizeof(float) * shared_state_.api_format_.input_stream().num_frames();
- for (int i = 0; i < shared_state_.api_format_.input_stream().num_channels();
- ++i)
+ sizeof(float) * formats_.api_format.input_stream().num_frames();
+ for (int i = 0; i < formats_.api_format.input_stream().num_channels(); ++i)
msg->add_input_channel(src[i], channel_size);
}
#endif
- capture_audio_->CopyFrom(src, shared_state_.api_format_.input_stream());
+ capture_.capture_audio->CopyFrom(src, formats_.api_format.input_stream());
RETURN_ON_ERR(ProcessStreamLocked());
- capture_audio_->CopyTo(shared_state_.api_format_.output_stream(), dest);
+ capture_.capture_audio->CopyTo(formats_.api_format.output_stream(), dest);
#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
- if (debug_file_->Open()) {
- audioproc::Stream* msg = event_msg_->mutable_stream();
+ if (debug_dump_.debug_file->Open()) {
+ audioproc::Stream* msg = debug_dump_.capture.event_msg->mutable_stream();
const size_t channel_size =
- sizeof(float) * shared_state_.api_format_.output_stream().num_frames();
- for (int i = 0;
- i < shared_state_.api_format_.output_stream().num_channels(); ++i)
+ sizeof(float) * formats_.api_format.output_stream().num_frames();
+ for (int i = 0; i < formats_.api_format.output_stream().num_channels(); ++i)
msg->add_output_channel(dest[i], channel_size);
- RETURN_ON_ERR(WriteMessageToDebugFile());
+ RETURN_ON_ERR(WriteMessageToDebugFile(debug_dump_.debug_file.get(),
+ &crit_debug_, &debug_dump_.capture));
}
#endif
@@ -590,10 +642,18 @@ int AudioProcessingImpl::ProcessStream(const float* const* src,
}
int AudioProcessingImpl::ProcessStream(AudioFrame* frame) {
- CriticalSectionScoped crit_scoped(crit_);
- echo_cancellation_->ReadQueuedRenderData();
- echo_control_mobile_->ReadQueuedRenderData();
- gain_control_->ReadQueuedRenderData();
+ {
+ // Acquire the capture lock in order to safely call the function
+ // that retrieves the render side data. This function accesses apm
+ // getters that need the capture lock held when being called.
+ // The lock needs to be released as
+ // public_submodules_->echo_control_mobile->is_enabled() aquires this lock
+ // as well.
+ rtc::CritScope cs_capture(&crit_capture_);
+ public_submodules_->echo_cancellation->ReadQueuedRenderData();
+ public_submodules_->echo_control_mobile->ReadQueuedRenderData();
+ public_submodules_->gain_control->ReadQueuedRenderData();
+ }
if (!frame) {
return kNullPointerError;
@@ -606,47 +666,61 @@ int AudioProcessingImpl::ProcessStream(AudioFrame* frame) {
return kBadSampleRateError;
}
- if (echo_control_mobile_->is_enabled() &&
+ if (public_submodules_->echo_control_mobile->is_enabled() &&
frame->sample_rate_hz_ > kMaxAECMSampleRateHz) {
LOG(LS_ERROR) << "AECM only supports 16 or 8 kHz sample rates";
return kUnsupportedComponentError;
}
- // TODO(ajm): The input and output rates and channels are currently
- // constrained to be identical in the int16 interface.
- ProcessingConfig processing_config = shared_state_.api_format_;
+ ProcessingConfig processing_config;
+ {
+ // Aquire lock for the access of api_format.
+ // The lock is released immediately due to the conditional
+ // reinitialization.
+ rtc::CritScope cs_capture(&crit_capture_);
+ // TODO(ajm): The input and output rates and channels are currently
+ // constrained to be identical in the int16 interface.
+ processing_config = formats_.api_format;
+ }
processing_config.input_stream().set_sample_rate_hz(frame->sample_rate_hz_);
processing_config.input_stream().set_num_channels(frame->num_channels_);
processing_config.output_stream().set_sample_rate_hz(frame->sample_rate_hz_);
processing_config.output_stream().set_num_channels(frame->num_channels_);
- RETURN_ON_ERR(MaybeInitializeLockedCapture(processing_config));
+ {
+ // Do conditional reinitialization.
+ rtc::CritScope cs_render(&crit_render_);
+ RETURN_ON_ERR(MaybeInitializeCapture(processing_config));
+ }
+ rtc::CritScope cs_capture(&crit_capture_);
if (frame->samples_per_channel_ !=
- shared_state_.api_format_.input_stream().num_frames()) {
+ formats_.api_format.input_stream().num_frames()) {
return kBadDataLengthError;
}
#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
- if (debug_file_->Open()) {
- event_msg_->set_type(audioproc::Event::STREAM);
- audioproc::Stream* msg = event_msg_->mutable_stream();
+ if (debug_dump_.debug_file->Open()) {
+ debug_dump_.capture.event_msg->set_type(audioproc::Event::STREAM);
+ audioproc::Stream* msg = debug_dump_.capture.event_msg->mutable_stream();
const size_t data_size =
sizeof(int16_t) * frame->samples_per_channel_ * frame->num_channels_;
msg->set_input_data(frame->data_, data_size);
}
#endif
- capture_audio_->DeinterleaveFrom(frame);
+ capture_.capture_audio->DeinterleaveFrom(frame);
RETURN_ON_ERR(ProcessStreamLocked());
- capture_audio_->InterleaveTo(frame, output_copy_needed(is_data_processed()));
+ capture_.capture_audio->InterleaveTo(frame,
+ output_copy_needed(is_data_processed()));
#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
- if (debug_file_->Open()) {
- audioproc::Stream* msg = event_msg_->mutable_stream();
+ if (debug_dump_.debug_file->Open()) {
+ audioproc::Stream* msg = debug_dump_.capture.event_msg->mutable_stream();
const size_t data_size =
sizeof(int16_t) * frame->samples_per_channel_ * frame->num_channels_;
msg->set_output_data(frame->data_, data_size);
- RETURN_ON_ERR(WriteMessageToDebugFile());
+ RETURN_ON_ERR(WriteMessageToDebugFile(debug_dump_.debug_file.get(),
+ &crit_debug_, &debug_dump_.capture));
}
#endif
@@ -655,22 +729,25 @@ int AudioProcessingImpl::ProcessStream(AudioFrame* frame) {
int AudioProcessingImpl::ProcessStreamLocked() {
#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
- if (debug_file_->Open()) {
- audioproc::Stream* msg = event_msg_->mutable_stream();
- msg->set_delay(stream_delay_ms_);
- msg->set_drift(echo_cancellation_->stream_drift_samples());
+ if (debug_dump_.debug_file->Open()) {
+ audioproc::Stream* msg = debug_dump_.capture.event_msg->mutable_stream();
+ msg->set_delay(capture_nonlocked_.stream_delay_ms);
+ msg->set_drift(
+ public_submodules_->echo_cancellation->stream_drift_samples());
msg->set_level(gain_control()->stream_analog_level());
- msg->set_keypress(key_pressed_);
+ msg->set_keypress(capture_.key_pressed);
}
#endif
MaybeUpdateHistograms();
- AudioBuffer* ca = capture_audio_.get(); // For brevity.
+ AudioBuffer* ca = capture_.capture_audio.get(); // For brevity.
- if (use_new_agc_ && gain_control_->is_enabled()) {
- agc_manager_->AnalyzePreProcess(ca->channels()[0], ca->num_channels(),
- fwd_proc_format_.num_frames());
+ if (constants_.use_new_agc &&
+ public_submodules_->gain_control->is_enabled()) {
+ private_submodules_->agc_manager->AnalyzePreProcess(
+ ca->channels()[0], ca->num_channels(),
+ capture_nonlocked_.fwd_proc_format.num_frames());
}
bool data_processed = is_data_processed();
@@ -678,34 +755,41 @@ int AudioProcessingImpl::ProcessStreamLocked() {
ca->SplitIntoFrequencyBands();
}
- if (intelligibility_enabled_) {
- intelligibility_enhancer_->AnalyzeCaptureAudio(
- ca->split_channels_f(kBand0To8kHz), split_rate_, ca->num_channels());
+ if (constants_.intelligibility_enabled) {
+ public_submodules_->intelligibility_enhancer->AnalyzeCaptureAudio(
+ ca->split_channels_f(kBand0To8kHz), capture_nonlocked_.split_rate,
+ ca->num_channels());
}
- if (beamformer_enabled_) {
- beamformer_->ProcessChunk(*ca->split_data_f(), ca->split_data_f());
+ if (constants_.beamformer_enabled) {
+ private_submodules_->beamformer->ProcessChunk(*ca->split_data_f(),
+ ca->split_data_f());
ca->set_num_channels(1);
}
- RETURN_ON_ERR(high_pass_filter_->ProcessCaptureAudio(ca));
- RETURN_ON_ERR(gain_control_->AnalyzeCaptureAudio(ca));
- RETURN_ON_ERR(noise_suppression_->AnalyzeCaptureAudio(ca));
- RETURN_ON_ERR(echo_cancellation_->ProcessCaptureAudio(ca));
+ RETURN_ON_ERR(public_submodules_->high_pass_filter->ProcessCaptureAudio(ca));
+ RETURN_ON_ERR(public_submodules_->gain_control->AnalyzeCaptureAudio(ca));
+ RETURN_ON_ERR(public_submodules_->noise_suppression->AnalyzeCaptureAudio(ca));
+ RETURN_ON_ERR(public_submodules_->echo_cancellation->ProcessCaptureAudio(ca));
- if (echo_control_mobile_->is_enabled() && noise_suppression_->is_enabled()) {
+ if (public_submodules_->echo_control_mobile->is_enabled() &&
+ public_submodules_->noise_suppression->is_enabled()) {
ca->CopyLowPassToReference();
}
- RETURN_ON_ERR(noise_suppression_->ProcessCaptureAudio(ca));
- RETURN_ON_ERR(echo_control_mobile_->ProcessCaptureAudio(ca));
- RETURN_ON_ERR(voice_detection_->ProcessCaptureAudio(ca));
+ RETURN_ON_ERR(public_submodules_->noise_suppression->ProcessCaptureAudio(ca));
+ RETURN_ON_ERR(
+ public_submodules_->echo_control_mobile->ProcessCaptureAudio(ca));
+ RETURN_ON_ERR(public_submodules_->voice_detection->ProcessCaptureAudio(ca));
- if (use_new_agc_ && gain_control_->is_enabled() &&
- (!beamformer_enabled_ || beamformer_->is_target_present())) {
- agc_manager_->Process(ca->split_bands_const(0)[kBand0To8kHz],
- ca->num_frames_per_band(), split_rate_);
+ if (constants_.use_new_agc &&
+ public_submodules_->gain_control->is_enabled() &&
+ (!constants_.beamformer_enabled ||
+ private_submodules_->beamformer->is_target_present())) {
+ private_submodules_->agc_manager->Process(
+ ca->split_bands_const(0)[kBand0To8kHz], ca->num_frames_per_band(),
+ capture_nonlocked_.split_rate);
}
- RETURN_ON_ERR(gain_control_->ProcessCaptureAudio(ca));
+ RETURN_ON_ERR(public_submodules_->gain_control->ProcessCaptureAudio(ca));
if (synthesis_needed(data_processed)) {
ca->MergeFrequencyBands();
@@ -713,21 +797,23 @@ int AudioProcessingImpl::ProcessStreamLocked() {
// TODO(aluebs): Investigate if the transient suppression placement should be
// before or after the AGC.
- if (transient_suppressor_enabled_) {
+ if (capture_.transient_suppressor_enabled) {
float voice_probability =
- agc_manager_.get() ? agc_manager_->voice_probability() : 1.f;
+ private_submodules_->agc_manager.get()
+ ? private_submodules_->agc_manager->voice_probability()
+ : 1.f;
- transient_suppressor_->Suppress(
+ public_submodules_->transient_suppressor->Suppress(
ca->channels_f()[0], ca->num_frames(), ca->num_channels(),
ca->split_bands_const_f(0)[kBand0To8kHz], ca->num_frames_per_band(),
ca->keyboard_data(), ca->num_keyboard_frames(), voice_probability,
- key_pressed_);
+ capture_.key_pressed);
}
// The level estimator operates on the recombined data.
- RETURN_ON_ERR(level_estimator_->ProcessStream(ca));
+ RETURN_ON_ERR(public_submodules_->level_estimator->ProcessStream(ca));
- was_stream_delay_set_ = false;
+ capture_.was_stream_delay_set = false;
return kNoError;
}
@@ -735,13 +821,14 @@ int AudioProcessingImpl::AnalyzeReverseStream(const float* const* data,
size_t samples_per_channel,
int rev_sample_rate_hz,
ChannelLayout layout) {
+ rtc::CritScope cs(&crit_render_);
const StreamConfig reverse_config = {
rev_sample_rate_hz, ChannelsFromLayout(layout), LayoutHasKeyboard(layout),
};
if (samples_per_channel != reverse_config.num_frames()) {
return kBadDataLengthError;
}
- return AnalyzeReverseStream(data, reverse_config, reverse_config);
+ return AnalyzeReverseStreamLocked(data, reverse_config, reverse_config);
}
int AudioProcessingImpl::ProcessReverseStream(
@@ -749,14 +836,16 @@ int AudioProcessingImpl::ProcessReverseStream(
const StreamConfig& reverse_input_config,
const StreamConfig& reverse_output_config,
float* const* dest) {
- RETURN_ON_ERR(
- AnalyzeReverseStream(src, reverse_input_config, reverse_output_config));
+ rtc::CritScope cs(&crit_render_);
+ RETURN_ON_ERR(AnalyzeReverseStreamLocked(src, reverse_input_config,
+ reverse_output_config));
if (is_rev_processed()) {
- render_audio_->CopyTo(shared_state_.api_format_.reverse_output_stream(),
- dest);
+ render_.render_audio->CopyTo(formats_.api_format.reverse_output_stream(),
+ dest);
} else if (render_check_rev_conversion_needed()) {
- render_converter_->Convert(src, reverse_input_config.num_samples(), dest,
- reverse_output_config.num_samples());
+ render_.render_converter->Convert(src, reverse_input_config.num_samples(),
+ dest,
+ reverse_output_config.num_samples());
} else {
CopyAudioIfNeeded(src, reverse_input_config.num_frames(),
reverse_input_config.num_channels(), dest);
@@ -765,12 +854,11 @@ int AudioProcessingImpl::ProcessReverseStream(
return kNoError;
}
-int AudioProcessingImpl::AnalyzeReverseStream(
+int AudioProcessingImpl::AnalyzeReverseStreamLocked(
const float* const* src,
const StreamConfig& reverse_input_config,
const StreamConfig& reverse_output_config) {
- CriticalSectionScoped crit_scoped(crit_);
- if (src == NULL) {
+ if (src == nullptr) {
return kNullPointerError;
}
@@ -778,46 +866,47 @@ int AudioProcessingImpl::AnalyzeReverseStream(
return kBadNumberChannelsError;
}
- ProcessingConfig processing_config = shared_state_.api_format_;
+ ProcessingConfig processing_config = formats_.api_format;
processing_config.reverse_input_stream() = reverse_input_config;
processing_config.reverse_output_stream() = reverse_output_config;
- RETURN_ON_ERR(MaybeInitializeLockedRender(processing_config));
+ RETURN_ON_ERR(MaybeInitializeRender(processing_config));
assert(reverse_input_config.num_frames() ==
- shared_state_.api_format_.reverse_input_stream().num_frames());
+ formats_.api_format.reverse_input_stream().num_frames());
#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
- if (debug_file_->Open()) {
- event_msg_->set_type(audioproc::Event::REVERSE_STREAM);
- audioproc::ReverseStream* msg = event_msg_->mutable_reverse_stream();
+ if (debug_dump_.debug_file->Open()) {
+ debug_dump_.render.event_msg->set_type(audioproc::Event::REVERSE_STREAM);
+ audioproc::ReverseStream* msg =
+ debug_dump_.render.event_msg->mutable_reverse_stream();
const size_t channel_size =
- sizeof(float) *
- shared_state_.api_format_.reverse_input_stream().num_frames();
+ sizeof(float) * formats_.api_format.reverse_input_stream().num_frames();
for (int i = 0;
- i < shared_state_.api_format_.reverse_input_stream().num_channels();
- ++i)
+ i < formats_.api_format.reverse_input_stream().num_channels(); ++i)
msg->add_channel(src[i], channel_size);
- RETURN_ON_ERR(WriteMessageToDebugFile());
+ RETURN_ON_ERR(WriteMessageToDebugFile(debug_dump_.debug_file.get(),
+ &crit_debug_, &debug_dump_.render));
}
#endif
- render_audio_->CopyFrom(src,
- shared_state_.api_format_.reverse_input_stream());
+ render_.render_audio->CopyFrom(src,
+ formats_.api_format.reverse_input_stream());
return ProcessReverseStreamLocked();
}
int AudioProcessingImpl::ProcessReverseStream(AudioFrame* frame) {
RETURN_ON_ERR(AnalyzeReverseStream(frame));
+ rtc::CritScope cs(&crit_render_);
if (is_rev_processed()) {
- render_audio_->InterleaveTo(frame, true);
+ render_.render_audio->InterleaveTo(frame, true);
}
return kNoError;
}
int AudioProcessingImpl::AnalyzeReverseStream(AudioFrame* frame) {
- CriticalSectionScoped crit_scoped(crit_);
- if (frame == NULL) {
+ rtc::CritScope cs(&crit_render_);
+ if (frame == nullptr) {
return kNullPointerError;
}
// Must be a native rate.
@@ -829,7 +918,7 @@ int AudioProcessingImpl::AnalyzeReverseStream(AudioFrame* frame) {
}
// This interface does not tolerate different forward and reverse rates.
if (frame->sample_rate_hz_ !=
- shared_state_.api_format_.input_stream().sample_rate_hz()) {
+ formats_.api_format.input_stream().sample_rate_hz()) {
return kBadSampleRateError;
}
@@ -837,7 +926,7 @@ int AudioProcessingImpl::AnalyzeReverseStream(AudioFrame* frame) {
return kBadNumberChannelsError;
}
- ProcessingConfig processing_config = shared_state_.api_format_;
+ ProcessingConfig processing_config = formats_.api_format;
processing_config.reverse_input_stream().set_sample_rate_hz(
frame->sample_rate_hz_);
processing_config.reverse_input_stream().set_num_channels(
@@ -847,44 +936,52 @@ int AudioProcessingImpl::AnalyzeReverseStream(AudioFrame* frame) {
processing_config.reverse_output_stream().set_num_channels(
frame->num_channels_);
- RETURN_ON_ERR(MaybeInitializeLockedRender(processing_config));
+ RETURN_ON_ERR(MaybeInitializeRender(processing_config));
if (frame->samples_per_channel_ !=
- shared_state_.api_format_.reverse_input_stream().num_frames()) {
+ formats_.api_format.reverse_input_stream().num_frames()) {
return kBadDataLengthError;
}
#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
- if (debug_file_->Open()) {
- event_msg_->set_type(audioproc::Event::REVERSE_STREAM);
- audioproc::ReverseStream* msg = event_msg_->mutable_reverse_stream();
+ if (debug_dump_.debug_file->Open()) {
+ debug_dump_.render.event_msg->set_type(audioproc::Event::REVERSE_STREAM);
+ audioproc::ReverseStream* msg =
+ debug_dump_.render.event_msg->mutable_reverse_stream();
const size_t data_size =
sizeof(int16_t) * frame->samples_per_channel_ * frame->num_channels_;
msg->set_data(frame->data_, data_size);
- RETURN_ON_ERR(WriteMessageToDebugFile());
+ RETURN_ON_ERR(WriteMessageToDebugFile(debug_dump_.debug_file.get(),
+ &crit_debug_, &debug_dump_.render));
}
#endif
- render_audio_->DeinterleaveFrom(frame);
+ render_.render_audio->DeinterleaveFrom(frame);
return ProcessReverseStreamLocked();
}
int AudioProcessingImpl::ProcessReverseStreamLocked() {
- AudioBuffer* ra = render_audio_.get(); // For brevity.
- if (rev_proc_format_.sample_rate_hz() == kSampleRate32kHz) {
+ AudioBuffer* ra = render_.render_audio.get(); // For brevity.
+ if (formats_.rev_proc_format.sample_rate_hz() == kSampleRate32kHz) {
ra->SplitIntoFrequencyBands();
}
- if (intelligibility_enabled_) {
- intelligibility_enhancer_->ProcessRenderAudio(
- ra->split_channels_f(kBand0To8kHz), split_rate_, ra->num_channels());
+ if (constants_.intelligibility_enabled) {
+ // Currently run in single-threaded mode when the intelligibility
+ // enhancer is activated.
+ // TODO(peah): Fix to be properly multi-threaded.
+ rtc::CritScope cs(&crit_capture_);
+ public_submodules_->intelligibility_enhancer->ProcessRenderAudio(
+ ra->split_channels_f(kBand0To8kHz), capture_nonlocked_.split_rate,
+ ra->num_channels());
}
- RETURN_ON_ERR(echo_cancellation_->ProcessRenderAudio(ra));
- RETURN_ON_ERR(echo_control_mobile_->ProcessRenderAudio(ra));
- if (!use_new_agc_) {
- RETURN_ON_ERR(gain_control_->ProcessRenderAudio(ra));
+ RETURN_ON_ERR(public_submodules_->echo_cancellation->ProcessRenderAudio(ra));
+ RETURN_ON_ERR(
+ public_submodules_->echo_control_mobile->ProcessRenderAudio(ra));
+ if (!constants_.use_new_agc) {
+ RETURN_ON_ERR(public_submodules_->gain_control->ProcessRenderAudio(ra));
}
- if (rev_proc_format_.sample_rate_hz() == kSampleRate32kHz &&
+ if (formats_.rev_proc_format.sample_rate_hz() == kSampleRate32kHz &&
is_rev_processed()) {
ra->MergeFrequencyBands();
}
@@ -893,9 +990,10 @@ int AudioProcessingImpl::ProcessReverseStreamLocked() {
}
int AudioProcessingImpl::set_stream_delay_ms(int delay) {
+ rtc::CritScope cs(&crit_capture_);
Error retval = kNoError;
- was_stream_delay_set_ = true;
- delay += delay_offset_ms_;
+ capture_.was_stream_delay_set = true;
+ delay += capture_.delay_offset_ms;
if (delay < 0) {
delay = 0;
@@ -908,50 +1006,56 @@ int AudioProcessingImpl::set_stream_delay_ms(int delay) {
retval = kBadStreamParameterWarning;
}
- stream_delay_ms_ = delay;
+ capture_nonlocked_.stream_delay_ms = delay;
return retval;
}
int AudioProcessingImpl::stream_delay_ms() const {
- return stream_delay_ms_;
+ // Used as callback from submodules, hence locking is not allowed.
+ return capture_nonlocked_.stream_delay_ms;
}
bool AudioProcessingImpl::was_stream_delay_set() const {
- return was_stream_delay_set_;
+ // Used as callback from submodules, hence locking is not allowed.
+ return capture_.was_stream_delay_set;
}
void AudioProcessingImpl::set_stream_key_pressed(bool key_pressed) {
- key_pressed_ = key_pressed;
+ rtc::CritScope cs(&crit_capture_);
+ capture_.key_pressed = key_pressed;
}
void AudioProcessingImpl::set_delay_offset_ms(int offset) {
- CriticalSectionScoped crit_scoped(crit_);
- delay_offset_ms_ = offset;
+ rtc::CritScope cs(&crit_capture_);
+ capture_.delay_offset_ms = offset;
}
int AudioProcessingImpl::delay_offset_ms() const {
- return delay_offset_ms_;
+ rtc::CritScope cs(&crit_capture_);
+ return capture_.delay_offset_ms;
}
int AudioProcessingImpl::StartDebugRecording(
const char filename[AudioProcessing::kMaxFilenameSize]) {
- CriticalSectionScoped crit_scoped(crit_);
+ // Run in a single-threaded manner.
+ rtc::CritScope cs_render(&crit_render_);
+ rtc::CritScope cs_capture(&crit_capture_);
static_assert(kMaxFilenameSize == FileWrapper::kMaxFileNameSize, "");
- if (filename == NULL) {
+ if (filename == nullptr) {
return kNullPointerError;
}
#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
// Stop any ongoing recording.
- if (debug_file_->Open()) {
- if (debug_file_->CloseFile() == -1) {
+ if (debug_dump_.debug_file->Open()) {
+ if (debug_dump_.debug_file->CloseFile() == -1) {
return kFileError;
}
}
- if (debug_file_->OpenFile(filename, false) == -1) {
- debug_file_->CloseFile();
+ if (debug_dump_.debug_file->OpenFile(filename, false) == -1) {
+ debug_dump_.debug_file->CloseFile();
return kFileError;
}
@@ -964,21 +1068,23 @@ int AudioProcessingImpl::StartDebugRecording(
}
int AudioProcessingImpl::StartDebugRecording(FILE* handle) {
- CriticalSectionScoped crit_scoped(crit_);
+ // Run in a single-threaded manner.
+ rtc::CritScope cs_render(&crit_render_);
+ rtc::CritScope cs_capture(&crit_capture_);
- if (handle == NULL) {
+ if (handle == nullptr) {
return kNullPointerError;
}
#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
// Stop any ongoing recording.
- if (debug_file_->Open()) {
- if (debug_file_->CloseFile() == -1) {
+ if (debug_dump_.debug_file->Open()) {
+ if (debug_dump_.debug_file->CloseFile() == -1) {
return kFileError;
}
}
- if (debug_file_->OpenFromFileHandle(handle, true, false) == -1) {
+ if (debug_dump_.debug_file->OpenFromFileHandle(handle, true, false) == -1) {
return kFileError;
}
@@ -992,17 +1098,22 @@ int AudioProcessingImpl::StartDebugRecording(FILE* handle) {
int AudioProcessingImpl::StartDebugRecordingForPlatformFile(
rtc::PlatformFile handle) {
+ // Run in a single-threaded manner.
+ rtc::CritScope cs_render(&crit_render_);
+ rtc::CritScope cs_capture(&crit_capture_);
FILE* stream = rtc::FdopenPlatformFileForWriting(handle);
return StartDebugRecording(stream);
}
int AudioProcessingImpl::StopDebugRecording() {
- CriticalSectionScoped crit_scoped(crit_);
+ // Run in a single-threaded manner.
+ rtc::CritScope cs_render(&crit_render_);
+ rtc::CritScope cs_capture(&crit_capture_);
#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
// We just return if recording hasn't started.
- if (debug_file_->Open()) {
- if (debug_file_->CloseFile() == -1) {
+ if (debug_dump_.debug_file->Open()) {
+ if (debug_dump_.debug_file->CloseFile() == -1) {
return kFileError;
}
}
@@ -1013,58 +1124,75 @@ int AudioProcessingImpl::StopDebugRecording() {
}
EchoCancellation* AudioProcessingImpl::echo_cancellation() const {
- return echo_cancellation_;
+ // Adding a lock here has no effect as it allows any access to the submodule
+ // from the returned pointer.
+ return public_submodules_->echo_cancellation;
}
EchoControlMobile* AudioProcessingImpl::echo_control_mobile() const {
- return echo_control_mobile_;
+ // Adding a lock here has no effect as it allows any access to the submodule
+ // from the returned pointer.
+ return public_submodules_->echo_control_mobile;
}
GainControl* AudioProcessingImpl::gain_control() const {
- if (use_new_agc_) {
- return gain_control_for_new_agc_.get();
+ // Adding a lock here has no effect as it allows any access to the submodule
+ // from the returned pointer.
+ if (constants_.use_new_agc) {
+ return public_submodules_->gain_control_for_new_agc.get();
}
- return gain_control_;
+ return public_submodules_->gain_control;
}
HighPassFilter* AudioProcessingImpl::high_pass_filter() const {
- return high_pass_filter_;
+ // Adding a lock here has no effect as it allows any access to the submodule
+ // from the returned pointer.
+ return public_submodules_->high_pass_filter;
}
LevelEstimator* AudioProcessingImpl::level_estimator() const {
- return level_estimator_;
+ // Adding a lock here has no effect as it allows any access to the submodule
+ // from the returned pointer.
+ return public_submodules_->level_estimator;
}
NoiseSuppression* AudioProcessingImpl::noise_suppression() const {
- return noise_suppression_;
+ // Adding a lock here has no effect as it allows any access to the submodule
+ // from the returned pointer.
+ return public_submodules_->noise_suppression;
}
VoiceDetection* AudioProcessingImpl::voice_detection() const {
- return voice_detection_;
+ // Adding a lock here has no effect as it allows any access to the submodule
+ // from the returned pointer.
+ return public_submodules_->voice_detection;
}
bool AudioProcessingImpl::is_data_processed() const {
- if (beamformer_enabled_) {
+ if (constants_.beamformer_enabled) {
return true;
}
int enabled_count = 0;
- for (auto item : component_list_) {
+ for (auto item : private_submodules_->component_list) {
if (item->is_component_enabled()) {
enabled_count++;
}
}
- // Data is unchanged if no components are enabled, or if only level_estimator_
- // or voice_detection_ is enabled.
+ // Data is unchanged if no components are enabled, or if only
+ // public_submodules_->level_estimator
+ // or public_submodules_->voice_detection is enabled.
if (enabled_count == 0) {
return false;
} else if (enabled_count == 1) {
- if (level_estimator_->is_enabled() || voice_detection_->is_enabled()) {
+ if (public_submodules_->level_estimator->is_enabled() ||
+ public_submodules_->voice_detection->is_enabled()) {
return false;
}
} else if (enabled_count == 2) {
- if (level_estimator_->is_enabled() && voice_detection_->is_enabled()) {
+ if (public_submodules_->level_estimator->is_enabled() &&
+ public_submodules_->voice_detection->is_enabled()) {
return false;
}
}
@@ -1073,32 +1201,39 @@ bool AudioProcessingImpl::is_data_processed() const {
bool AudioProcessingImpl::output_copy_needed(bool is_data_processed) const {
// Check if we've upmixed or downmixed the audio.
- return ((shared_state_.api_format_.output_stream().num_channels() !=
- shared_state_.api_format_.input_stream().num_channels()) ||
- is_data_processed || transient_suppressor_enabled_);
+ return ((formats_.api_format.output_stream().num_channels() !=
+ formats_.api_format.input_stream().num_channels()) ||
+ is_data_processed || capture_.transient_suppressor_enabled);
}
bool AudioProcessingImpl::synthesis_needed(bool is_data_processed) const {
return (is_data_processed &&
- (fwd_proc_format_.sample_rate_hz() == kSampleRate32kHz ||
- fwd_proc_format_.sample_rate_hz() == kSampleRate48kHz));
+ (capture_nonlocked_.fwd_proc_format.sample_rate_hz() ==
+ kSampleRate32kHz ||
+ capture_nonlocked_.fwd_proc_format.sample_rate_hz() ==
+ kSampleRate48kHz));
}
bool AudioProcessingImpl::analysis_needed(bool is_data_processed) const {
- if (!is_data_processed && !voice_detection_->is_enabled() &&
- !transient_suppressor_enabled_) {
- // Only level_estimator_ is enabled.
+ if (!is_data_processed &&
+ !public_submodules_->voice_detection->is_enabled() &&
+ !capture_.transient_suppressor_enabled) {
+ // Only public_submodules_->level_estimator is enabled.
return false;
- } else if (fwd_proc_format_.sample_rate_hz() == kSampleRate32kHz ||
- fwd_proc_format_.sample_rate_hz() == kSampleRate48kHz) {
- // Something besides level_estimator_ is enabled, and we have super-wb.
+ } else if (capture_nonlocked_.fwd_proc_format.sample_rate_hz() ==
+ kSampleRate32kHz ||
+ capture_nonlocked_.fwd_proc_format.sample_rate_hz() ==
+ kSampleRate48kHz) {
+ // Something besides public_submodules_->level_estimator is enabled, and we
+ // have super-wb.
return true;
}
return false;
}
bool AudioProcessingImpl::is_rev_processed() const {
- return intelligibility_enabled_ && intelligibility_enhancer_->active();
+ return constants_.intelligibility_enabled &&
+ public_submodules_->intelligibility_enhancer->active();
}
bool AudioProcessingImpl::render_check_rev_conversion_needed() const {
@@ -1106,55 +1241,55 @@ bool AudioProcessingImpl::render_check_rev_conversion_needed() const {
}
bool AudioProcessingImpl::rev_conversion_needed() const {
- // TODO(peah): Refactor to be allowed to verify using thread annotations.
- return (shared_state_.api_format_.reverse_input_stream() !=
- shared_state_.api_format_.reverse_output_stream());
+ return (formats_.api_format.reverse_input_stream() !=
+ formats_.api_format.reverse_output_stream());
}
void AudioProcessingImpl::InitializeExperimentalAgc() {
- // TODO(peah): Refactor to be allowed to verify using thread annotations.
- if (use_new_agc_) {
- if (!agc_manager_.get()) {
- agc_manager_.reset(new AgcManagerDirect(gain_control_,
- gain_control_for_new_agc_.get(),
- agc_startup_min_volume_));
+ if (constants_.use_new_agc) {
+ if (!private_submodules_->agc_manager.get()) {
+ private_submodules_->agc_manager.reset(new AgcManagerDirect(
+ public_submodules_->gain_control,
+ public_submodules_->gain_control_for_new_agc.get(),
+ constants_.agc_startup_min_volume));
}
- agc_manager_->Initialize();
- agc_manager_->SetCaptureMuted(output_will_be_muted_);
+ private_submodules_->agc_manager->Initialize();
+ private_submodules_->agc_manager->SetCaptureMuted(
+ capture_.output_will_be_muted);
}
}
void AudioProcessingImpl::InitializeTransient() {
- // TODO(peah): Refactor to be allowed to verify using thread annotations.
- if (transient_suppressor_enabled_) {
- if (!transient_suppressor_.get()) {
- transient_suppressor_.reset(new TransientSuppressor());
+ if (capture_.transient_suppressor_enabled) {
+ if (!public_submodules_->transient_suppressor.get()) {
+ public_submodules_->transient_suppressor.reset(new TransientSuppressor());
}
- transient_suppressor_->Initialize(
- fwd_proc_format_.sample_rate_hz(), split_rate_,
- shared_state_.api_format_.output_stream().num_channels());
+ public_submodules_->transient_suppressor->Initialize(
+ capture_nonlocked_.fwd_proc_format.sample_rate_hz(),
+ capture_nonlocked_.split_rate,
+ formats_.api_format.output_stream().num_channels());
}
}
void AudioProcessingImpl::InitializeBeamformer() {
- // TODO(peah): Refactor to be allowed to verify using thread annotations.
- if (beamformer_enabled_) {
- if (!beamformer_) {
- beamformer_.reset(
- new NonlinearBeamformer(array_geometry_, target_direction_));
+ if (constants_.beamformer_enabled) {
+ if (!private_submodules_->beamformer) {
+ private_submodules_->beamformer.reset(new NonlinearBeamformer(
+ constants_.array_geometry, constants_.target_direction));
}
- beamformer_->Initialize(kChunkSizeMs, split_rate_);
+ private_submodules_->beamformer->Initialize(kChunkSizeMs,
+ capture_nonlocked_.split_rate);
}
}
void AudioProcessingImpl::InitializeIntelligibility() {
- // TODO(peah): Refactor to be allowed to verify using thread annotations.
- if (intelligibility_enabled_) {
+ if (constants_.intelligibility_enabled) {
IntelligibilityEnhancer::Config config;
- config.sample_rate_hz = split_rate_;
- config.num_capture_channels = capture_audio_->num_channels();
- config.num_render_channels = render_audio_->num_channels();
- intelligibility_enhancer_.reset(new IntelligibilityEnhancer(config));
+ config.sample_rate_hz = capture_nonlocked_.split_rate;
+ config.num_capture_channels = capture_.capture_audio->num_channels();
+ config.num_render_channels = render_.render_audio->num_channels();
+ public_submodules_->intelligibility_enhancer.reset(
+ new IntelligibilityEnhancer(config));
}
}
@@ -1164,67 +1299,77 @@ void AudioProcessingImpl::MaybeUpdateHistograms() {
if (echo_cancellation()->is_enabled()) {
// Activate delay_jumps_ counters if we know echo_cancellation is runnning.
// If a stream has echo we know that the echo_cancellation is in process.
- if (stream_delay_jumps_ == -1 && echo_cancellation()->stream_has_echo()) {
- stream_delay_jumps_ = 0;
+ if (capture_.stream_delay_jumps == -1 &&
+ echo_cancellation()->stream_has_echo()) {
+ capture_.stream_delay_jumps = 0;
}
- if (aec_system_delay_jumps_ == -1 &&
+ if (capture_.aec_system_delay_jumps == -1 &&
echo_cancellation()->stream_has_echo()) {
- aec_system_delay_jumps_ = 0;
+ capture_.aec_system_delay_jumps = 0;
}
// Detect a jump in platform reported system delay and log the difference.
- const int diff_stream_delay_ms = stream_delay_ms_ - last_stream_delay_ms_;
- if (diff_stream_delay_ms > kMinDiffDelayMs && last_stream_delay_ms_ != 0) {
+ const int diff_stream_delay_ms =
+ capture_nonlocked_.stream_delay_ms - capture_.last_stream_delay_ms;
+ if (diff_stream_delay_ms > kMinDiffDelayMs &&
+ capture_.last_stream_delay_ms != 0) {
RTC_HISTOGRAM_COUNTS("WebRTC.Audio.PlatformReportedStreamDelayJump",
diff_stream_delay_ms, kMinDiffDelayMs, 1000, 100);
- if (stream_delay_jumps_ == -1) {
- stream_delay_jumps_ = 0; // Activate counter if needed.
+ if (capture_.stream_delay_jumps == -1) {
+ capture_.stream_delay_jumps = 0; // Activate counter if needed.
}
- stream_delay_jumps_++;
+ capture_.stream_delay_jumps++;
}
- last_stream_delay_ms_ = stream_delay_ms_;
+ capture_.last_stream_delay_ms = capture_nonlocked_.stream_delay_ms;
// Detect a jump in AEC system delay and log the difference.
- const int frames_per_ms = rtc::CheckedDivExact(split_rate_, 1000);
+ const int frames_per_ms =
+ rtc::CheckedDivExact(capture_nonlocked_.split_rate, 1000);
const int aec_system_delay_ms =
WebRtcAec_system_delay(echo_cancellation()->aec_core()) / frames_per_ms;
const int diff_aec_system_delay_ms =
- aec_system_delay_ms - last_aec_system_delay_ms_;
+ aec_system_delay_ms - capture_.last_aec_system_delay_ms;
if (diff_aec_system_delay_ms > kMinDiffDelayMs &&
- last_aec_system_delay_ms_ != 0) {
+ capture_.last_aec_system_delay_ms != 0) {
RTC_HISTOGRAM_COUNTS("WebRTC.Audio.AecSystemDelayJump",
diff_aec_system_delay_ms, kMinDiffDelayMs, 1000,
100);
- if (aec_system_delay_jumps_ == -1) {
- aec_system_delay_jumps_ = 0; // Activate counter if needed.
+ if (capture_.aec_system_delay_jumps == -1) {
+ capture_.aec_system_delay_jumps = 0; // Activate counter if needed.
}
- aec_system_delay_jumps_++;
+ capture_.aec_system_delay_jumps++;
}
- last_aec_system_delay_ms_ = aec_system_delay_ms;
+ capture_.last_aec_system_delay_ms = aec_system_delay_ms;
}
}
void AudioProcessingImpl::UpdateHistogramsOnCallEnd() {
- CriticalSectionScoped crit_scoped(crit_);
- if (stream_delay_jumps_ > -1) {
+ // Run in a single-threaded manner.
+ rtc::CritScope cs_render(&crit_render_);
+ rtc::CritScope cs_capture(&crit_capture_);
+
+ if (capture_.stream_delay_jumps > -1) {
RTC_HISTOGRAM_ENUMERATION(
"WebRTC.Audio.NumOfPlatformReportedStreamDelayJumps",
- stream_delay_jumps_, 51);
+ capture_.stream_delay_jumps, 51);
}
- stream_delay_jumps_ = -1;
- last_stream_delay_ms_ = 0;
+ capture_.stream_delay_jumps = -1;
+ capture_.last_stream_delay_ms = 0;
- if (aec_system_delay_jumps_ > -1) {
+ if (capture_.aec_system_delay_jumps > -1) {
RTC_HISTOGRAM_ENUMERATION("WebRTC.Audio.NumOfAecSystemDelayJumps",
- aec_system_delay_jumps_, 51);
+ capture_.aec_system_delay_jumps, 51);
}
- aec_system_delay_jumps_ = -1;
- last_aec_system_delay_ms_ = 0;
+ capture_.aec_system_delay_jumps = -1;
+ capture_.last_aec_system_delay_ms = 0;
}
#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
-int AudioProcessingImpl::WriteMessageToDebugFile() {
- int32_t size = event_msg_->ByteSize();
+int AudioProcessingImpl::WriteMessageToDebugFile(
+ FileWrapper* debug_file,
+ rtc::CriticalSection* crit_debug,
+ ApmDebugDumpThreadState* debug_state) {
+ int32_t size = debug_state->event_msg->ByteSize();
if (size <= 0) {
return kUnspecifiedError;
}
@@ -1233,87 +1378,100 @@ int AudioProcessingImpl::WriteMessageToDebugFile() {
// pretty safe in assuming little-endian.
#endif
- if (!event_msg_->SerializeToString(&event_str_)) {
+ if (!debug_state->event_msg->SerializeToString(&debug_state->event_str)) {
return kUnspecifiedError;
}
- // Write message preceded by its size.
- if (!debug_file_->Write(&size, sizeof(int32_t))) {
- return kFileError;
- }
- if (!debug_file_->Write(event_str_.data(), event_str_.length())) {
- return kFileError;
+ {
+ // Ensure atomic writes of the message.
+ rtc::CritScope cs_capture(crit_debug);
+ // Write message preceded by its size.
+ if (!debug_file->Write(&size, sizeof(int32_t))) {
+ return kFileError;
+ }
+ if (!debug_file->Write(debug_state->event_str.data(),
+ debug_state->event_str.length())) {
+ return kFileError;
+ }
}
- event_msg_->Clear();
+ debug_state->event_msg->Clear();
return kNoError;
}
int AudioProcessingImpl::WriteInitMessage() {
- // TODO(peah): Refactor to be allowed to verify using thread annotations.
- event_msg_->set_type(audioproc::Event::INIT);
- audioproc::Init* msg = event_msg_->mutable_init();
- msg->set_sample_rate(
- shared_state_.api_format_.input_stream().sample_rate_hz());
+ debug_dump_.capture.event_msg->set_type(audioproc::Event::INIT);
+ audioproc::Init* msg = debug_dump_.capture.event_msg->mutable_init();
+ msg->set_sample_rate(formats_.api_format.input_stream().sample_rate_hz());
+
msg->set_num_input_channels(
- shared_state_.api_format_.input_stream().num_channels());
+ formats_.api_format.input_stream().num_channels());
msg->set_num_output_channels(
- shared_state_.api_format_.output_stream().num_channels());
+ formats_.api_format.output_stream().num_channels());
msg->set_num_reverse_channels(
- shared_state_.api_format_.reverse_input_stream().num_channels());
+ formats_.api_format.reverse_input_stream().num_channels());
msg->set_reverse_sample_rate(
- shared_state_.api_format_.reverse_input_stream().sample_rate_hz());
+ formats_.api_format.reverse_input_stream().sample_rate_hz());
msg->set_output_sample_rate(
- shared_state_.api_format_.output_stream().sample_rate_hz());
- // TODO(ekmeyerson): Add reverse output fields to event_msg_.
+ formats_.api_format.output_stream().sample_rate_hz());
+ // TODO(ekmeyerson): Add reverse output fields to
+ // debug_dump_.capture.event_msg.
- RETURN_ON_ERR(WriteMessageToDebugFile());
+ RETURN_ON_ERR(WriteMessageToDebugFile(debug_dump_.debug_file.get(),
+ &crit_debug_, &debug_dump_.capture));
return kNoError;
}
int AudioProcessingImpl::WriteConfigMessage(bool forced) {
audioproc::Config config;
- config.set_aec_enabled(echo_cancellation_->is_enabled());
+ config.set_aec_enabled(public_submodules_->echo_cancellation->is_enabled());
config.set_aec_delay_agnostic_enabled(
- echo_cancellation_->is_delay_agnostic_enabled());
+ public_submodules_->echo_cancellation->is_delay_agnostic_enabled());
config.set_aec_drift_compensation_enabled(
- echo_cancellation_->is_drift_compensation_enabled());
+ public_submodules_->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()));
+ public_submodules_->echo_cancellation->is_extended_filter_enabled());
+ config.set_aec_suppression_level(static_cast<int>(
+ public_submodules_->echo_cancellation->suppression_level()));
- config.set_aecm_enabled(echo_control_mobile_->is_enabled());
+ config.set_aecm_enabled(
+ public_submodules_->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()));
+ public_submodules_->echo_control_mobile->is_comfort_noise_enabled());
+ config.set_aecm_routing_mode(static_cast<int>(
+ public_submodules_->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_agc_enabled(public_submodules_->gain_control->is_enabled());
+ config.set_agc_mode(
+ static_cast<int>(public_submodules_->gain_control->mode()));
+ config.set_agc_limiter_enabled(
+ public_submodules_->gain_control->is_limiter_enabled());
+ config.set_noise_robust_agc_enabled(constants_.use_new_agc);
- config.set_hpf_enabled(high_pass_filter_->is_enabled());
+ config.set_hpf_enabled(public_submodules_->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_ns_enabled(public_submodules_->noise_suppression->is_enabled());
+ config.set_ns_level(
+ static_cast<int>(public_submodules_->noise_suppression->level()));
- config.set_transient_suppression_enabled(transient_suppressor_enabled_);
+ config.set_transient_suppression_enabled(
+ capture_.transient_suppressor_enabled);
std::string serialized_config = config.SerializeAsString();
- if (!forced && last_serialized_config_ == serialized_config) {
+ if (!forced &&
+ debug_dump_.capture.last_serialized_config == serialized_config) {
return kNoError;
}
- last_serialized_config_ = serialized_config;
+ debug_dump_.capture.last_serialized_config = serialized_config;
- event_msg_->set_type(audioproc::Event::CONFIG);
- event_msg_->mutable_config()->CopyFrom(config);
+ debug_dump_.capture.event_msg->set_type(audioproc::Event::CONFIG);
+ debug_dump_.capture.event_msg->mutable_config()->CopyFrom(config);
- RETURN_ON_ERR(WriteMessageToDebugFile());
+ RETURN_ON_ERR(WriteMessageToDebugFile(debug_dump_.debug_file.get(),
+ &crit_debug_, &debug_dump_.capture));
return kNoError;
}
#endif // WEBRTC_AUDIOPROC_DEBUG_DUMP

Powered by Google App Engine
This is Rietveld 408576698