Chromium Code Reviews| Index: webrtc/modules/audio_processing/echo_cancellation_impl.cc |
| diff --git a/webrtc/modules/audio_processing/echo_cancellation_impl.cc b/webrtc/modules/audio_processing/echo_cancellation_impl.cc |
| index e75930ef76c9c2fa919fb5661ca17615929d25d2..460803a3e91a435bd429450b1aa36a1f0ae31007 100644 |
| --- a/webrtc/modules/audio_processing/echo_cancellation_impl.cc |
| +++ b/webrtc/modules/audio_processing/echo_cancellation_impl.cc |
| @@ -18,7 +18,6 @@ extern "C" { |
| } |
| #include "webrtc/modules/audio_processing/aec/echo_cancellation.h" |
| #include "webrtc/modules/audio_processing/audio_buffer.h" |
| -#include "webrtc/system_wrappers/include/critical_section_wrapper.h" |
| namespace webrtc { |
| @@ -64,11 +63,13 @@ static const size_t kMaxNumFramesToBuffer = 100; |
| EchoCancellationImpl::EchoCancellationImpl( |
| const AudioProcessing* apm, |
| - CriticalSectionWrapper* crit, |
| + rtc::CriticalSection* crit_render, |
| + rtc::CriticalSection* crit_capture, |
| const rtc::ThreadChecker* render_thread_checker) |
| : ProcessingComponent(), |
| apm_(apm), |
| - crit_(crit), |
| + crit_render_(crit_render), |
| + crit_capture_(crit_capture), |
| render_thread_checker_(render_thread_checker), |
| drift_compensation_enabled_(false), |
| metrics_enabled_(false), |
| @@ -120,7 +121,11 @@ int EchoCancellationImpl::ProcessRenderAudio(const AudioBuffer* audio) { |
| // Insert the samples into the queue. |
| if (!render_signal_queue_->Insert(&render_queue_buffer_)) { |
| - ReadQueuedRenderData(); |
| + // The data queue is full and needs to be emptied. |
| + { |
| + rtc::CritScope cs_capture(crit_capture_); |
| + ReadQueuedRenderData(); |
| + } |
| // Retry the insert (should always work). |
| RTC_DCHECK_EQ(render_signal_queue_->Insert(&render_queue_buffer_), true); |
| @@ -215,7 +220,9 @@ int EchoCancellationImpl::ProcessCaptureAudio(AudioBuffer* audio) { |
| } |
| int EchoCancellationImpl::Enable(bool enable) { |
| - CriticalSectionScoped crit_scoped(crit_); |
| + // Run in a single-threaded manner. |
| + rtc::CritScope cs_render(crit_render_); |
| + rtc::CritScope cs_capture(crit_capture_); |
| // Ensure AEC and AECM are not both enabled. |
| if (enable && apm_->echo_control_mobile()->is_enabled()) { |
| return apm_->kBadParameterError; |
| @@ -225,11 +232,12 @@ int EchoCancellationImpl::Enable(bool enable) { |
| } |
| bool EchoCancellationImpl::is_enabled() const { |
| + rtc::CritScope cs(crit_capture_); |
| return is_component_enabled(); |
| } |
| int EchoCancellationImpl::set_suppression_level(SuppressionLevel level) { |
| - CriticalSectionScoped crit_scoped(crit_); |
| + rtc::CritScope cs(crit_capture_); |
| if (MapSetting(level) == -1) { |
| return apm_->kBadParameterError; |
| } |
| @@ -240,42 +248,47 @@ int EchoCancellationImpl::set_suppression_level(SuppressionLevel level) { |
| EchoCancellation::SuppressionLevel EchoCancellationImpl::suppression_level() |
| const { |
| + rtc::CritScope cs(crit_capture_); |
| return suppression_level_; |
| } |
| int EchoCancellationImpl::enable_drift_compensation(bool enable) { |
| - CriticalSectionScoped crit_scoped(crit_); |
| + rtc::CritScope cs(crit_capture_); |
|
the sun
2015/11/23 21:36:05
It's great that you have added these. Thank you!
peah-webrtc
2015/11/24 21:42:23
You are welcome! :-)
Acknowledged.
|
| drift_compensation_enabled_ = enable; |
| return Configure(); |
| } |
| bool EchoCancellationImpl::is_drift_compensation_enabled() const { |
| + rtc::CritScope cs(crit_capture_); |
| return drift_compensation_enabled_; |
| } |
| void EchoCancellationImpl::set_stream_drift_samples(int drift) { |
| + rtc::CritScope cs(crit_capture_); |
| was_stream_drift_set_ = true; |
| stream_drift_samples_ = drift; |
| } |
| int EchoCancellationImpl::stream_drift_samples() const { |
| + rtc::CritScope cs(crit_capture_); |
| return stream_drift_samples_; |
| } |
| int EchoCancellationImpl::enable_metrics(bool enable) { |
| - CriticalSectionScoped crit_scoped(crit_); |
| + rtc::CritScope cs(crit_capture_); |
| metrics_enabled_ = enable; |
| return Configure(); |
| } |
| bool EchoCancellationImpl::are_metrics_enabled() const { |
| + rtc::CritScope cs(crit_capture_); |
| return metrics_enabled_; |
| } |
| // TODO(ajm): we currently just use the metrics from the first AEC. Think more |
| // aboue the best way to extend this to multi-channel. |
| int EchoCancellationImpl::GetMetrics(Metrics* metrics) { |
| - CriticalSectionScoped crit_scoped(crit_); |
| + rtc::CritScope cs(crit_capture_); |
| if (metrics == NULL) { |
| return apm_->kNullPointerError; |
| } |
| @@ -318,36 +331,53 @@ int EchoCancellationImpl::GetMetrics(Metrics* metrics) { |
| } |
| bool EchoCancellationImpl::stream_has_echo() const { |
| + // This is called both from within and from outside of APM, with and |
| + // without locks set. Hence the conditional lock handling below. |
| + rtc::TryCritScope cs(crit_capture_); |
|
the sun
2015/11/23 21:36:05
I don't understand why you are using TryCritScope
peah-webrtc
2015/11/24 21:42:23
Agree, something is wrong with this. I'll revise.
|
| + |
| + // Call the lock function (without this call TryCritScope will DCHECK). |
|
the sun
2015/11/23 21:36:05
TryCritScope::locked() does *not* call any lock fu
peah-webrtc
2015/11/24 21:42:23
Of course you are correct, I'll revise. Please re-
|
| + (void)cs.locked(); |
| + |
|
kwiberg-webrtc
2015/11/23 22:15:11
This doesn't look right. The effect here is to tak
peah-webrtc
2015/11/24 21:42:23
I agree on both, it was not correct, but I revised
|
| return stream_has_echo_; |
| } |
| int EchoCancellationImpl::enable_delay_logging(bool enable) { |
| - CriticalSectionScoped crit_scoped(crit_); |
| + // This is called both from within and from outside of APM, with and |
| + // without locks set. Hence the conditional lock handling below. |
| + rtc::TryCritScope cs(crit_capture_); |
| + |
| + // Call the lock function (without this call TryCritScope will DCHECK). |
| + (void)cs.locked(); |
| + |
|
kwiberg-webrtc
2015/11/23 22:15:11
Same.
peah-webrtc
2015/11/24 21:42:24
Agree, please look at the revised solution.
|
| delay_logging_enabled_ = enable; |
| return Configure(); |
|
the sun
2015/11/23 21:36:05
You may be setting delay_logging_enabled_ and call
peah-webrtc
2015/11/24 21:42:24
Agree, that was a bad design, but the revised code
|
| } |
| bool EchoCancellationImpl::is_delay_logging_enabled() const { |
| + rtc::CritScope cs(crit_capture_); |
| return delay_logging_enabled_; |
| } |
| bool EchoCancellationImpl::is_delay_agnostic_enabled() const { |
| + // Only called from within APM, hence no locking is needed. |
| return delay_agnostic_enabled_; |
| } |
| bool EchoCancellationImpl::is_extended_filter_enabled() const { |
| + // Only called from within APM, hence no locking is needed. |
| return extended_filter_enabled_; |
| } |
| // TODO(bjornv): How should we handle the multi-channel case? |
| int EchoCancellationImpl::GetDelayMetrics(int* median, int* std) { |
| + rtc::CritScope cs(crit_capture_); |
| float fraction_poor_delays = 0; |
| return GetDelayMetrics(median, std, &fraction_poor_delays); |
| } |
| int EchoCancellationImpl::GetDelayMetrics(int* median, int* std, |
| float* fraction_poor_delays) { |
| - CriticalSectionScoped crit_scoped(crit_); |
| + rtc::CritScope cs(crit_capture_); |
| if (median == NULL) { |
| return apm_->kNullPointerError; |
| } |
| @@ -370,7 +400,7 @@ int EchoCancellationImpl::GetDelayMetrics(int* median, int* std, |
| } |
| struct AecCore* EchoCancellationImpl::aec_core() const { |
| - CriticalSectionScoped crit_scoped(crit_); |
| + // Only called from within APM, hence no locking is needed. |
| if (!is_component_enabled()) { |
| return NULL; |
| } |
| @@ -379,6 +409,7 @@ struct AecCore* EchoCancellationImpl::aec_core() const { |
| } |
| int EchoCancellationImpl::Initialize() { |
| + // Only called from within APM, hence no locking is needed. |
|
the sun
2015/11/23 21:36:05
What do you mean with "called from within APM"? Al
peah-webrtc
2015/11/24 21:42:24
No, it is actually not, although I think I see you
|
| int err = ProcessingComponent::Initialize(); |
| if (err != apm_->kNoError || !is_component_enabled()) { |
| return err; |
| @@ -414,21 +445,31 @@ void EchoCancellationImpl::AllocateRenderQueue() { |
| } |
| void EchoCancellationImpl::SetExtraOptions(const Config& config) { |
| + // This is called both from within and from outside of APM, with and |
| + // without locks set. Hence the conditional lock handling below. |
| + rtc::TryCritScope cs(crit_capture_); |
| + |
| + // Call the lock function (without this call TryCritScope will DCHECK). |
| + (void)cs.locked(); |
| + |
|
kwiberg-webrtc
2015/11/23 22:15:11
Same.
peah-webrtc
2015/11/24 21:42:23
Agree. Please see the revised version.
|
| extended_filter_enabled_ = config.Get<ExtendedFilter>().enabled; |
| delay_agnostic_enabled_ = config.Get<DelayAgnostic>().enabled; |
| Configure(); |
| } |
| void* EchoCancellationImpl::CreateHandle() const { |
| + // Only called from within APM, hence no locking is needed. |
| return WebRtcAec_Create(); |
| } |
| void EchoCancellationImpl::DestroyHandle(void* handle) const { |
| + // Only called from within APM, hence no locking is needed. |
| assert(handle != NULL); |
| WebRtcAec_Free(static_cast<Handle*>(handle)); |
| } |
| int EchoCancellationImpl::InitializeHandle(void* handle) const { |
| + // Only called from within APM, hence no locking is needed. |
| assert(handle != NULL); |
| // TODO(ajm): Drift compensation is disabled in practice. If restored, it |
| // should be managed internally and not depend on the hardware sample rate. |
| @@ -439,6 +480,7 @@ int EchoCancellationImpl::InitializeHandle(void* handle) const { |
| } |
| int EchoCancellationImpl::ConfigureHandle(void* handle) const { |
| + // Only called from within APM, hence no locking is needed. |
|
the sun
2015/11/23 21:36:05
This function is called from ProcessingComponent::
peah-webrtc
2015/11/24 21:42:23
You are right in that the lock was not properly ac
|
| assert(handle != NULL); |
| AecConfig config; |
| config.metricsMode = metrics_enabled_; |
| @@ -455,11 +497,13 @@ int EchoCancellationImpl::ConfigureHandle(void* handle) const { |
| } |
| int EchoCancellationImpl::num_handles_required() const { |
| + // Only called from within APM, hence no locking is needed. |
| return apm_->num_output_channels() * |
| apm_->num_reverse_channels(); |
| } |
| int EchoCancellationImpl::GetHandleError(void* handle) const { |
| + // Only called from within APM, hence no locking is needed. |
| assert(handle != NULL); |
| return AudioProcessing::kUnspecifiedError; |
| } |