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 44a5a0c7730b80a3744a6ee64bbec3174829528f..a323736a56d32b8e0aed436a3d0d9c2cf12bbda1 100644 |
--- a/webrtc/modules/audio_processing/echo_cancellation_impl.cc |
+++ b/webrtc/modules/audio_processing/echo_cancellation_impl.cc |
@@ -57,6 +57,23 @@ static const size_t kMaxAllowedValuesOfSamplesPerFrame = 160; |
static const size_t kMaxNumFramesToBuffer = 100; |
} // namespace |
+struct EchoCancellationImpl::StreamProperties { |
+ StreamProperties() = delete; |
+ StreamProperties(int sample_rate_hz, |
+ size_t num_reverse_channels, |
+ size_t num_output_channels, |
+ size_t num_proc_channels) |
+ : sample_rate_hz(sample_rate_hz), |
+ num_reverse_channels(num_reverse_channels), |
+ num_output_channels(num_output_channels), |
+ num_proc_channels(num_proc_channels) {} |
+ |
+ const int sample_rate_hz; |
+ const size_t num_reverse_channels; |
+ const size_t num_output_channels; |
+ const size_t num_proc_channels; |
+}; |
+ |
class EchoCancellationImpl::Canceller { |
public: |
Canceller() { |
@@ -83,11 +100,9 @@ class EchoCancellationImpl::Canceller { |
void* state_; |
}; |
-EchoCancellationImpl::EchoCancellationImpl(const AudioProcessing* apm, |
- rtc::CriticalSection* crit_render, |
+EchoCancellationImpl::EchoCancellationImpl(rtc::CriticalSection* crit_render, |
rtc::CriticalSection* crit_capture) |
- : apm_(apm), |
- crit_render_(crit_render), |
+ : crit_render_(crit_render), |
crit_capture_(crit_capture), |
drift_compensation_enabled_(false), |
metrics_enabled_(false), |
@@ -100,7 +115,6 @@ EchoCancellationImpl::EchoCancellationImpl(const AudioProcessing* apm, |
delay_agnostic_enabled_(false), |
aec3_enabled_(false), |
render_queue_element_max_size_(0) { |
- RTC_DCHECK(apm); |
RTC_DCHECK(crit_render); |
RTC_DCHECK(crit_capture); |
} |
@@ -113,17 +127,19 @@ int EchoCancellationImpl::ProcessRenderAudio(const AudioBuffer* audio) { |
return AudioProcessing::kNoError; |
} |
+ RTC_DCHECK(stream_properties_); |
RTC_DCHECK_GE(160u, audio->num_frames_per_band()); |
- RTC_DCHECK_EQ(audio->num_channels(), apm_->num_reverse_channels()); |
- RTC_DCHECK_GE(cancellers_.size(), |
- apm_->num_output_channels() * audio->num_channels()); |
+ RTC_DCHECK_EQ(audio->num_channels(), |
+ stream_properties_->num_reverse_channels); |
+ RTC_DCHECK_GE(cancellers_.size(), stream_properties_->num_output_channels * |
+ audio->num_channels()); |
int err = AudioProcessing::kNoError; |
// The ordering convention must be followed to pass to the correct AEC. |
size_t handle_index = 0; |
render_queue_buffer_.clear(); |
- for (size_t i = 0; i < apm_->num_output_channels(); i++) { |
+ for (size_t i = 0; i < stream_properties_->num_output_channels; i++) { |
for (size_t j = 0; j < audio->num_channels(); j++) { |
// Retrieve any error code produced by the buffering of the farend |
// signal. |
@@ -164,14 +180,16 @@ void EchoCancellationImpl::ReadQueuedRenderData() { |
return; |
} |
+ RTC_DCHECK(stream_properties_); |
while (render_signal_queue_->Remove(&capture_queue_buffer_)) { |
size_t handle_index = 0; |
size_t buffer_index = 0; |
const size_t num_frames_per_band = |
capture_queue_buffer_.size() / |
- (apm_->num_output_channels() * apm_->num_reverse_channels()); |
- for (size_t i = 0; i < apm_->num_output_channels(); i++) { |
- for (size_t j = 0; j < apm_->num_reverse_channels(); j++) { |
+ (stream_properties_->num_output_channels * |
+ stream_properties_->num_reverse_channels); |
+ for (size_t i = 0; i < stream_properties_->num_output_channels; i++) { |
+ for (size_t j = 0; j < stream_properties_->num_reverse_channels; j++) { |
WebRtcAec_BufferFarend(cancellers_[handle_index++]->state(), |
&capture_queue_buffer_[buffer_index], |
num_frames_per_band); |
@@ -182,22 +200,20 @@ void EchoCancellationImpl::ReadQueuedRenderData() { |
} |
} |
-int EchoCancellationImpl::ProcessCaptureAudio(AudioBuffer* audio) { |
+int EchoCancellationImpl::ProcessCaptureAudio(AudioBuffer* audio, |
+ int stream_delay_ms) { |
rtc::CritScope cs_capture(crit_capture_); |
if (!enabled_) { |
return AudioProcessing::kNoError; |
} |
- if (!apm_->was_stream_delay_set()) { |
- return AudioProcessing::kStreamParameterNotSetError; |
- } |
- |
if (drift_compensation_enabled_ && !was_stream_drift_set_) { |
return AudioProcessing::kStreamParameterNotSetError; |
} |
+ RTC_DCHECK(stream_properties_); |
RTC_DCHECK_GE(160u, audio->num_frames_per_band()); |
- RTC_DCHECK_EQ(audio->num_channels(), apm_->num_proc_channels()); |
+ RTC_DCHECK_EQ(audio->num_channels(), stream_properties_->num_proc_channels); |
int err = AudioProcessing::kNoError; |
@@ -205,12 +221,11 @@ int EchoCancellationImpl::ProcessCaptureAudio(AudioBuffer* audio) { |
size_t handle_index = 0; |
stream_has_echo_ = false; |
for (size_t i = 0; i < audio->num_channels(); i++) { |
- for (size_t j = 0; j < apm_->num_reverse_channels(); j++) { |
- err = WebRtcAec_Process(cancellers_[handle_index]->state(), |
- audio->split_bands_const_f(i), audio->num_bands(), |
- audio->split_bands_f(i), |
- audio->num_frames_per_band(), |
- apm_->stream_delay_ms(), stream_drift_samples_); |
+ for (size_t j = 0; j < stream_properties_->num_reverse_channels; j++) { |
+ err = WebRtcAec_Process( |
+ cancellers_[handle_index]->state(), audio->split_bands_const_f(i), |
+ audio->num_bands(), audio->split_bands_f(i), |
+ audio->num_frames_per_band(), stream_delay_ms, stream_drift_samples_); |
if (err != AudioProcessing::kNoError) { |
err = MapError(err); |
@@ -243,16 +258,17 @@ int EchoCancellationImpl::Enable(bool enable) { |
// 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. |
- // The is_enabled call is safe from a deadlock perspective |
- // as both locks are already held in the correct order. |
- if (enable && apm_->echo_control_mobile()->is_enabled()) { |
- return AudioProcessing::kBadParameterError; |
- } |
if (enable && !enabled_) { |
enabled_ = enable; // Must be set before Initialize() is called. |
- Initialize(); |
+ |
+ // TODO(peah): Simplify once the Enable function has been removed from |
+ // the public APM API. |
+ RTC_DCHECK(stream_properties_); |
+ Initialize(stream_properties_->sample_rate_hz, |
+ stream_properties_->num_reverse_channels, |
+ stream_properties_->num_output_channels, |
+ stream_properties_->num_proc_channels); |
} else { |
enabled_ = enable; |
} |
@@ -433,23 +449,30 @@ struct AecCore* EchoCancellationImpl::aec_core() const { |
return WebRtcAec_aec_core(cancellers_[0]->state()); |
} |
-void EchoCancellationImpl::Initialize() { |
+void EchoCancellationImpl::Initialize(int sample_rate_hz, |
+ size_t num_reverse_channels, |
+ size_t num_output_channels, |
+ size_t num_proc_channels) { |
rtc::CritScope cs_render(crit_render_); |
rtc::CritScope cs_capture(crit_capture_); |
+ |
+ stream_properties_.reset( |
+ new StreamProperties(sample_rate_hz, num_reverse_channels, |
+ num_output_channels, num_proc_channels)); |
+ |
if (!enabled_) { |
return; |
} |
- if (num_handles_required() > cancellers_.size()) { |
+ if (NumCancellersRequired() > cancellers_.size()) { |
const size_t cancellers_old_size = cancellers_.size(); |
- cancellers_.resize(num_handles_required()); |
+ cancellers_.resize(NumCancellersRequired()); |
for (size_t i = cancellers_old_size; i < cancellers_.size(); ++i) { |
cancellers_[i].reset(new Canceller()); |
} |
} |
- const int sample_rate_hz = apm_->proc_sample_rate_hz(); |
for (auto& canceller : cancellers_) { |
canceller->Initialize(sample_rate_hz); |
} |
@@ -470,7 +493,7 @@ int EchoCancellationImpl::GetSystemDelayInSamples() const { |
void EchoCancellationImpl::AllocateRenderQueue() { |
const size_t new_render_queue_element_max_size = std::max<size_t>( |
static_cast<size_t>(1), |
- kMaxAllowedValuesOfSamplesPerFrame * num_handles_required()); |
+ kMaxAllowedValuesOfSamplesPerFrame * NumCancellersRequired()); |
rtc::CritScope cs_render(crit_render_); |
rtc::CritScope cs_capture(crit_capture_); |
@@ -529,9 +552,10 @@ int EchoCancellationImpl::Configure() { |
return error; |
} |
-size_t EchoCancellationImpl::num_handles_required() const { |
- // Not locked as it only relies on APM public API which is threadsafe. |
- return apm_->num_output_channels() * apm_->num_reverse_channels(); |
+size_t EchoCancellationImpl::NumCancellersRequired() const { |
+ RTC_DCHECK(stream_properties_); |
+ return stream_properties_->num_output_channels * |
+ stream_properties_->num_reverse_channels; |
} |
} // namespace webrtc |