Index: webrtc/modules/audio_processing/gain_control_impl.cc |
diff --git a/webrtc/modules/audio_processing/gain_control_impl.cc b/webrtc/modules/audio_processing/gain_control_impl.cc |
index 0eacd28686382c2bd8cffb17b340495915d47eb8..c8175dc01f22685246af7255c3ddafe917db5b84 100644 |
--- a/webrtc/modules/audio_processing/gain_control_impl.cc |
+++ b/webrtc/modules/audio_processing/gain_control_impl.cc |
@@ -14,7 +14,6 @@ |
#include "webrtc/modules/audio_processing/audio_buffer.h" |
#include "webrtc/modules/audio_processing/agc/legacy/gain_control.h" |
-#include "webrtc/system_wrappers/include/critical_section_wrapper.h" |
namespace webrtc { |
@@ -44,10 +43,12 @@ static const size_t kMaxNumFramesToBuffer = 100; |
} // namespace |
GainControlImpl::GainControlImpl(const AudioProcessing* apm, |
- CriticalSectionWrapper* crit) |
+ rtc::CriticalSection* crit_render, |
+ rtc::CriticalSection* crit_capture) |
: ProcessingComponent(), |
apm_(apm), |
- crit_(crit), |
+ crit_render_(crit_render), |
+ crit_capture_(crit_capture), |
mode_(kAdaptiveAnalog), |
minimum_capture_level_(0), |
maximum_capture_level_(255), |
@@ -57,13 +58,18 @@ GainControlImpl::GainControlImpl(const AudioProcessing* apm, |
analog_capture_level_(0), |
was_analog_level_set_(false), |
stream_is_saturated_(false), |
- render_queue_element_max_size_(0) {} |
+ render_queue_element_max_size_(0) { |
+ RTC_DCHECK(apm); |
+ RTC_DCHECK(crit_render); |
+ RTC_DCHECK(crit_capture); |
+} |
GainControlImpl::~GainControlImpl() {} |
int GainControlImpl::ProcessRenderAudio(AudioBuffer* audio) { |
+ rtc::CritScope cs(crit_render_); |
if (!is_component_enabled()) { |
- return apm_->kNoError; |
+ return AudioProcessing::kNoError; |
} |
assert(audio->num_frames_per_band() <= 160); |
@@ -74,7 +80,7 @@ int GainControlImpl::ProcessRenderAudio(AudioBuffer* audio) { |
int err = |
WebRtcAgc_GetAddFarendError(my_handle, audio->num_frames_per_band()); |
- if (err != apm_->kNoError) |
+ if (err != AudioProcessing::kNoError) |
return GetHandleError(my_handle); |
// Buffer the samples in the render queue. |
@@ -85,18 +91,21 @@ int GainControlImpl::ProcessRenderAudio(AudioBuffer* audio) { |
// Insert the samples into the queue. |
if (!render_signal_queue_->Insert(&render_queue_buffer_)) { |
+ // The data queue is full and needs to be emptied. |
ReadQueuedRenderData(); |
// Retry the insert (should always work). |
RTC_DCHECK_EQ(render_signal_queue_->Insert(&render_queue_buffer_), true); |
} |
- return apm_->kNoError; |
+ return AudioProcessing::kNoError; |
} |
// Read chunks of data that were received and queued on the render side from |
// a queue. All the data chunks are buffered into the farend signal of the AGC. |
void GainControlImpl::ReadQueuedRenderData() { |
+ rtc::CritScope cs(crit_capture_); |
+ |
if (!is_component_enabled()) { |
return; |
} |
@@ -116,14 +125,16 @@ void GainControlImpl::ReadQueuedRenderData() { |
} |
int GainControlImpl::AnalyzeCaptureAudio(AudioBuffer* audio) { |
+ rtc::CritScope cs(crit_capture_); |
+ |
if (!is_component_enabled()) { |
- return apm_->kNoError; |
+ return AudioProcessing::kNoError; |
} |
assert(audio->num_frames_per_band() <= 160); |
assert(audio->num_channels() == num_handles()); |
- int err = apm_->kNoError; |
+ int err = AudioProcessing::kNoError; |
if (mode_ == kAdaptiveAnalog) { |
capture_levels_.assign(num_handles(), analog_capture_level_); |
@@ -135,7 +146,7 @@ int GainControlImpl::AnalyzeCaptureAudio(AudioBuffer* audio) { |
audio->num_bands(), |
audio->num_frames_per_band()); |
- if (err != apm_->kNoError) { |
+ if (err != AudioProcessing::kNoError) { |
return GetHandleError(my_handle); |
} |
} |
@@ -155,23 +166,25 @@ int GainControlImpl::AnalyzeCaptureAudio(AudioBuffer* audio) { |
capture_levels_[i] = capture_level_out; |
- if (err != apm_->kNoError) { |
+ if (err != AudioProcessing::kNoError) { |
return GetHandleError(my_handle); |
} |
} |
} |
- return apm_->kNoError; |
+ return AudioProcessing::kNoError; |
} |
int GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio) { |
+ rtc::CritScope cs(crit_capture_); |
+ |
if (!is_component_enabled()) { |
- return apm_->kNoError; |
+ return AudioProcessing::kNoError; |
} |
if (mode_ == kAdaptiveAnalog && !was_analog_level_set_) { |
- return apm_->kStreamParameterNotSetError; |
+ return AudioProcessing::kStreamParameterNotSetError; |
} |
assert(audio->num_frames_per_band() <= 160); |
@@ -183,6 +196,8 @@ int GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio) { |
int32_t capture_level_out = 0; |
uint8_t saturation_warning = 0; |
+ // The call to stream_has_echo() is ok from a deadlock perspective |
+ // as the capture lock is allready held. |
int err = WebRtcAgc_Process( |
my_handle, |
audio->split_bands_const(i), |
@@ -194,7 +209,7 @@ int GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio) { |
apm_->echo_cancellation()->stream_has_echo(), |
&saturation_warning); |
- if (err != apm_->kNoError) { |
+ if (err != AudioProcessing::kNoError) { |
return GetHandleError(my_handle); |
} |
@@ -215,22 +230,24 @@ int GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio) { |
} |
was_analog_level_set_ = false; |
- return apm_->kNoError; |
+ return AudioProcessing::kNoError; |
} |
// TODO(ajm): ensure this is called under kAdaptiveAnalog. |
int GainControlImpl::set_stream_analog_level(int level) { |
- CriticalSectionScoped crit_scoped(crit_); |
+ rtc::CritScope cs(crit_capture_); |
+ |
was_analog_level_set_ = true; |
if (level < minimum_capture_level_ || level > maximum_capture_level_) { |
- return apm_->kBadParameterError; |
+ return AudioProcessing::kBadParameterError; |
} |
analog_capture_level_ = level; |
- return apm_->kNoError; |
+ return AudioProcessing::kNoError; |
} |
int GainControlImpl::stream_analog_level() { |
+ rtc::CritScope cs(crit_capture_); |
// TODO(ajm): enable this assertion? |
//assert(mode_ == kAdaptiveAnalog); |
@@ -238,18 +255,21 @@ int GainControlImpl::stream_analog_level() { |
} |
int GainControlImpl::Enable(bool enable) { |
- CriticalSectionScoped crit_scoped(crit_); |
+ rtc::CritScope cs_render(crit_render_); |
+ rtc::CritScope cs_capture(crit_capture_); |
return EnableComponent(enable); |
} |
bool GainControlImpl::is_enabled() const { |
+ rtc::CritScope cs(crit_capture_); |
return is_component_enabled(); |
} |
int GainControlImpl::set_mode(Mode mode) { |
- CriticalSectionScoped crit_scoped(crit_); |
+ rtc::CritScope cs_render(crit_render_); |
+ rtc::CritScope cs_capture(crit_capture_); |
if (MapSetting(mode) == -1) { |
- return apm_->kBadParameterError; |
+ return AudioProcessing::kBadParameterError; |
} |
mode_ = mode; |
@@ -257,22 +277,23 @@ int GainControlImpl::set_mode(Mode mode) { |
} |
GainControl::Mode GainControlImpl::mode() const { |
+ rtc::CritScope cs(crit_capture_); |
return mode_; |
} |
int GainControlImpl::set_analog_level_limits(int minimum, |
int maximum) { |
- CriticalSectionScoped crit_scoped(crit_); |
+ rtc::CritScope cs(crit_capture_); |
if (minimum < 0) { |
- return apm_->kBadParameterError; |
+ return AudioProcessing::kBadParameterError; |
} |
if (maximum > 65535) { |
- return apm_->kBadParameterError; |
+ return AudioProcessing::kBadParameterError; |
} |
if (maximum < minimum) { |
- return apm_->kBadParameterError; |
+ return AudioProcessing::kBadParameterError; |
} |
minimum_capture_level_ = minimum; |
@@ -282,21 +303,24 @@ int GainControlImpl::set_analog_level_limits(int minimum, |
} |
int GainControlImpl::analog_level_minimum() const { |
+ rtc::CritScope cs(crit_capture_); |
return minimum_capture_level_; |
} |
int GainControlImpl::analog_level_maximum() const { |
+ rtc::CritScope cs(crit_capture_); |
return maximum_capture_level_; |
} |
bool GainControlImpl::stream_is_saturated() const { |
+ rtc::CritScope cs(crit_capture_); |
return stream_is_saturated_; |
} |
int GainControlImpl::set_target_level_dbfs(int level) { |
- CriticalSectionScoped crit_scoped(crit_); |
+ rtc::CritScope cs(crit_capture_); |
if (level > 31 || level < 0) { |
- return apm_->kBadParameterError; |
+ return AudioProcessing::kBadParameterError; |
} |
target_level_dbfs_ = level; |
@@ -304,13 +328,14 @@ int GainControlImpl::set_target_level_dbfs(int level) { |
} |
int GainControlImpl::target_level_dbfs() const { |
+ rtc::CritScope cs(crit_capture_); |
return target_level_dbfs_; |
} |
int GainControlImpl::set_compression_gain_db(int gain) { |
- CriticalSectionScoped crit_scoped(crit_); |
+ rtc::CritScope cs(crit_capture_); |
if (gain < 0 || gain > 90) { |
- return apm_->kBadParameterError; |
+ return AudioProcessing::kBadParameterError; |
} |
compression_gain_db_ = gain; |
@@ -318,31 +343,35 @@ int GainControlImpl::set_compression_gain_db(int gain) { |
} |
int GainControlImpl::compression_gain_db() const { |
+ rtc::CritScope cs(crit_capture_); |
return compression_gain_db_; |
} |
int GainControlImpl::enable_limiter(bool enable) { |
- CriticalSectionScoped crit_scoped(crit_); |
+ rtc::CritScope cs(crit_capture_); |
limiter_enabled_ = enable; |
return Configure(); |
} |
bool GainControlImpl::is_limiter_enabled() const { |
+ rtc::CritScope cs(crit_capture_); |
return limiter_enabled_; |
} |
int GainControlImpl::Initialize() { |
int err = ProcessingComponent::Initialize(); |
- if (err != apm_->kNoError || !is_component_enabled()) { |
+ if (err != AudioProcessing::kNoError || !is_component_enabled()) { |
return err; |
} |
AllocateRenderQueue(); |
+ rtc::CritScope cs_capture(crit_capture_); |
const int n = num_handles(); |
RTC_CHECK_GE(n, 0) << "Bad number of handles: " << n; |
+ |
capture_levels_.assign(n, analog_capture_level_); |
- return apm_->kNoError; |
+ return AudioProcessing::kNoError; |
} |
void GainControlImpl::AllocateRenderQueue() { |
@@ -350,6 +379,9 @@ void GainControlImpl::AllocateRenderQueue() { |
std::max<size_t>(static_cast<size_t>(1), |
kMaxAllowedValuesOfSamplesPerFrame * num_handles()); |
+ rtc::CritScope cs_render(crit_render_); |
+ rtc::CritScope cs_capture(crit_capture_); |
+ |
if (render_queue_element_max_size_ < new_render_queue_element_max_size) { |
render_queue_element_max_size_ = new_render_queue_element_max_size; |
std::vector<int16_t> template_queue_element(render_queue_element_max_size_); |
@@ -375,6 +407,9 @@ void GainControlImpl::DestroyHandle(void* handle) const { |
} |
int GainControlImpl::InitializeHandle(void* handle) const { |
+ rtc::CritScope cs_render(crit_render_); |
+ rtc::CritScope cs_capture(crit_capture_); |
+ |
return WebRtcAgc_Init(static_cast<Handle*>(handle), |
minimum_capture_level_, |
maximum_capture_level_, |
@@ -383,6 +418,8 @@ int GainControlImpl::InitializeHandle(void* handle) const { |
} |
int GainControlImpl::ConfigureHandle(void* handle) const { |
+ rtc::CritScope cs_render(crit_render_); |
+ rtc::CritScope cs_capture(crit_capture_); |
WebRtcAgcConfig config; |
// TODO(ajm): Flip the sign here (since AGC expects a positive value) if we |
// change the interface. |
@@ -397,6 +434,7 @@ int GainControlImpl::ConfigureHandle(void* handle) const { |
} |
int GainControlImpl::num_handles_required() const { |
+ // Not locked as it only relies on APM public API which is threadsafe. |
return apm_->num_output_channels(); |
} |
@@ -404,6 +442,6 @@ int GainControlImpl::GetHandleError(void* handle) const { |
// The AGC has no get_error() function. |
// (Despite listing errors in its interface...) |
assert(handle != NULL); |
- return apm_->kUnspecifiedError; |
+ return AudioProcessing::kUnspecifiedError; |
} |
} // namespace webrtc |