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

Side by Side Diff: webrtc/modules/audio_processing/echo_cancellation_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: Merged changes from Lock scheme #9: WIP:Adding lock and thread annotations to the APM submodules in… Created 5 years 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 unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/modules/audio_processing/echo_cancellation_impl.h" 11 #include "webrtc/modules/audio_processing/echo_cancellation_impl.h"
12 12
13 #include <assert.h> 13 #include <assert.h>
14 #include <string.h> 14 #include <string.h>
15 15
16 extern "C" { 16 extern "C" {
17 #include "webrtc/modules/audio_processing/aec/aec_core.h" 17 #include "webrtc/modules/audio_processing/aec/aec_core.h"
18 } 18 }
19 #include "webrtc/modules/audio_processing/aec/echo_cancellation.h" 19 #include "webrtc/modules/audio_processing/aec/echo_cancellation.h"
20 #include "webrtc/modules/audio_processing/audio_buffer.h" 20 #include "webrtc/modules/audio_processing/audio_buffer.h"
21 #include "webrtc/system_wrappers/include/critical_section_wrapper.h"
22 21
23 namespace webrtc { 22 namespace webrtc {
24 23
25 typedef void Handle; 24 typedef void Handle;
26 25
27 namespace { 26 namespace {
28 int16_t MapSetting(EchoCancellation::SuppressionLevel level) { 27 int16_t MapSetting(EchoCancellation::SuppressionLevel level) {
29 switch (level) { 28 switch (level) {
30 case EchoCancellation::kLowSuppression: 29 case EchoCancellation::kLowSuppression:
31 return kAecNlpConservative; 30 return kAecNlpConservative;
(...skipping 23 matching lines...) Expand all
55 } 54 }
56 55
57 // Maximum length that a frame of samples can have. 56 // Maximum length that a frame of samples can have.
58 static const size_t kMaxAllowedValuesOfSamplesPerFrame = 160; 57 static const size_t kMaxAllowedValuesOfSamplesPerFrame = 160;
59 // Maximum number of frames to buffer in the render queue. 58 // Maximum number of frames to buffer in the render queue.
60 // TODO(peah): Decrease this once we properly handle hugely unbalanced 59 // TODO(peah): Decrease this once we properly handle hugely unbalanced
61 // reverse and forward call numbers. 60 // reverse and forward call numbers.
62 static const size_t kMaxNumFramesToBuffer = 100; 61 static const size_t kMaxNumFramesToBuffer = 100;
63 } // namespace 62 } // namespace
64 63
65 EchoCancellationImpl::EchoCancellationImpl(const AudioProcessing* apm, 64 EchoCancellationImpl::EchoCancellationImpl(
66 CriticalSectionWrapper* crit) 65 const AudioProcessing* apm,
66 rtc::CriticalSection* crit_render,
67 rtc::CriticalSection* crit_capture)
67 : ProcessingComponent(), 68 : ProcessingComponent(),
68 apm_(apm), 69 apm_(apm),
69 crit_(crit), 70 crit_render_(crit_render),
71 crit_capture_(crit_capture),
70 drift_compensation_enabled_(false), 72 drift_compensation_enabled_(false),
71 metrics_enabled_(false), 73 metrics_enabled_(false),
72 suppression_level_(kModerateSuppression), 74 suppression_level_(kModerateSuppression),
73 stream_drift_samples_(0), 75 stream_drift_samples_(0),
74 was_stream_drift_set_(false), 76 was_stream_drift_set_(false),
75 stream_has_echo_(false), 77 stream_has_echo_(false),
76 delay_logging_enabled_(false), 78 delay_logging_enabled_(false),
77 extended_filter_enabled_(false), 79 extended_filter_enabled_(false),
78 delay_agnostic_enabled_(false), 80 delay_agnostic_enabled_(false),
79 render_queue_element_max_size_(0) {} 81 render_queue_element_max_size_(0) {
82 RTC_DCHECK(apm);
83 RTC_DCHECK(crit_render);
84 RTC_DCHECK(crit_capture);
85 }
80 86
81 EchoCancellationImpl::~EchoCancellationImpl() {} 87 EchoCancellationImpl::~EchoCancellationImpl() {}
82 88
83 int EchoCancellationImpl::ProcessRenderAudio(const AudioBuffer* audio) { 89 int EchoCancellationImpl::ProcessRenderAudio(const AudioBuffer* audio) {
90 rtc::CritScope cs_render(crit_render_);
84 if (!is_component_enabled()) { 91 if (!is_component_enabled()) {
85 return apm_->kNoError; 92 return AudioProcessing::kNoError;
86 } 93 }
87 94
88 assert(audio->num_frames_per_band() <= 160); 95 assert(audio->num_frames_per_band() <= 160);
89 assert(audio->num_channels() == apm_->num_reverse_channels()); 96 assert(audio->num_channels() == apm_->num_reverse_channels());
90 97
91 int err = apm_->kNoError; 98 int err = AudioProcessing::kNoError;
92 99
93 // The ordering convention must be followed to pass to the correct AEC. 100 // The ordering convention must be followed to pass to the correct AEC.
94 size_t handle_index = 0; 101 size_t handle_index = 0;
95 render_queue_buffer_.clear(); 102 render_queue_buffer_.clear();
96 for (int i = 0; i < apm_->num_output_channels(); i++) { 103 for (int i = 0; i < apm_->num_output_channels(); i++) {
97 for (int j = 0; j < audio->num_channels(); j++) { 104 for (int j = 0; j < audio->num_channels(); j++) {
98 Handle* my_handle = static_cast<Handle*>(handle(handle_index)); 105 Handle* my_handle = static_cast<Handle*>(handle(handle_index));
99 // Retrieve any error code produced by the buffering of the farend 106 // Retrieve any error code produced by the buffering of the farend
100 // signal 107 // signal
101 err = WebRtcAec_GetBufferFarendError( 108 err = WebRtcAec_GetBufferFarendError(
102 my_handle, audio->split_bands_const_f(j)[kBand0To8kHz], 109 my_handle, audio->split_bands_const_f(j)[kBand0To8kHz],
103 audio->num_frames_per_band()); 110 audio->num_frames_per_band());
104 111
105 if (err != apm_->kNoError) { 112 if (err != AudioProcessing::kNoError) {
106 return MapError(err); // TODO(ajm): warning possible? 113 return MapError(err); // TODO(ajm): warning possible?
107 } 114 }
108 115
109 // Buffer the samples in the render queue. 116 // Buffer the samples in the render queue.
110 render_queue_buffer_.insert(render_queue_buffer_.end(), 117 render_queue_buffer_.insert(render_queue_buffer_.end(),
111 audio->split_bands_const_f(j)[kBand0To8kHz], 118 audio->split_bands_const_f(j)[kBand0To8kHz],
112 (audio->split_bands_const_f(j)[kBand0To8kHz] + 119 (audio->split_bands_const_f(j)[kBand0To8kHz] +
113 audio->num_frames_per_band())); 120 audio->num_frames_per_band()));
114 } 121 }
115 } 122 }
116 123
117 // Insert the samples into the queue. 124 // Insert the samples into the queue.
118 if (!render_signal_queue_->Insert(&render_queue_buffer_)) { 125 if (!render_signal_queue_->Insert(&render_queue_buffer_)) {
126 // The data queue is full and needs to be emptied.
119 ReadQueuedRenderData(); 127 ReadQueuedRenderData();
120 128
121 // Retry the insert (should always work). 129 // Retry the insert (should always work).
122 RTC_DCHECK_EQ(render_signal_queue_->Insert(&render_queue_buffer_), true); 130 RTC_DCHECK_EQ(render_signal_queue_->Insert(&render_queue_buffer_), true);
123 } 131 }
124 132
125 return apm_->kNoError; 133 return AudioProcessing::kNoError;
126 } 134 }
127 135
128 // Read chunks of data that were received and queued on the render side from 136 // Read chunks of data that were received and queued on the render side from
129 // a queue. All the data chunks are buffered into the farend signal of the AEC. 137 // a queue. All the data chunks are buffered into the farend signal of the AEC.
130 void EchoCancellationImpl::ReadQueuedRenderData() { 138 void EchoCancellationImpl::ReadQueuedRenderData() {
139 rtc::CritScope cs_capture(crit_capture_);
131 if (!is_component_enabled()) { 140 if (!is_component_enabled()) {
132 return; 141 return;
133 } 142 }
134 143
135 while (render_signal_queue_->Remove(&capture_queue_buffer_)) { 144 while (render_signal_queue_->Remove(&capture_queue_buffer_)) {
136 size_t handle_index = 0; 145 size_t handle_index = 0;
137 int buffer_index = 0; 146 int buffer_index = 0;
138 const int num_frames_per_band = 147 const int num_frames_per_band =
139 capture_queue_buffer_.size() / 148 capture_queue_buffer_.size() /
140 (apm_->num_output_channels() * apm_->num_reverse_channels()); 149 (apm_->num_output_channels() * apm_->num_reverse_channels());
141 for (int i = 0; i < apm_->num_output_channels(); i++) { 150 for (int i = 0; i < apm_->num_output_channels(); i++) {
142 for (int j = 0; j < apm_->num_reverse_channels(); j++) { 151 for (int j = 0; j < apm_->num_reverse_channels(); j++) {
143 Handle* my_handle = static_cast<Handle*>(handle(handle_index)); 152 Handle* my_handle = static_cast<Handle*>(handle(handle_index));
144 WebRtcAec_BufferFarend(my_handle, &capture_queue_buffer_[buffer_index], 153 WebRtcAec_BufferFarend(my_handle, &capture_queue_buffer_[buffer_index],
145 num_frames_per_band); 154 num_frames_per_band);
146 155
147 buffer_index += num_frames_per_band; 156 buffer_index += num_frames_per_band;
148 handle_index++; 157 handle_index++;
149 } 158 }
150 } 159 }
151 } 160 }
152 } 161 }
153 162
154 int EchoCancellationImpl::ProcessCaptureAudio(AudioBuffer* audio) { 163 int EchoCancellationImpl::ProcessCaptureAudio(AudioBuffer* audio) {
164 rtc::CritScope cs_capture(crit_capture_);
155 if (!is_component_enabled()) { 165 if (!is_component_enabled()) {
156 return apm_->kNoError; 166 return AudioProcessing::kNoError;
157 } 167 }
158 168
159 if (!apm_->was_stream_delay_set()) { 169 if (!apm_->was_stream_delay_set()) {
160 return apm_->kStreamParameterNotSetError; 170 return AudioProcessing::kStreamParameterNotSetError;
161 } 171 }
162 172
163 if (drift_compensation_enabled_ && !was_stream_drift_set_) { 173 if (drift_compensation_enabled_ && !was_stream_drift_set_) {
164 return apm_->kStreamParameterNotSetError; 174 return AudioProcessing::kStreamParameterNotSetError;
165 } 175 }
166 176
167 assert(audio->num_frames_per_band() <= 160); 177 assert(audio->num_frames_per_band() <= 160);
168 assert(audio->num_channels() == apm_->num_output_channels()); 178 assert(audio->num_channels() == apm_->num_output_channels());
169 179
170 int err = apm_->kNoError; 180 int err = AudioProcessing::kNoError;
171 181
172 // The ordering convention must be followed to pass to the correct AEC. 182 // The ordering convention must be followed to pass to the correct AEC.
173 size_t handle_index = 0; 183 size_t handle_index = 0;
174 stream_has_echo_ = false; 184 stream_has_echo_ = false;
175 for (int i = 0; i < audio->num_channels(); i++) { 185 for (int i = 0; i < audio->num_channels(); i++) {
176 for (int j = 0; j < apm_->num_reverse_channels(); j++) { 186 for (int j = 0; j < apm_->num_reverse_channels(); j++) {
177 Handle* my_handle = handle(handle_index); 187 Handle* my_handle = handle(handle_index);
178 err = WebRtcAec_Process( 188 err = WebRtcAec_Process(my_handle, audio->split_bands_const_f(i),
179 my_handle, 189 audio->num_bands(), audio->split_bands_f(i),
180 audio->split_bands_const_f(i), 190 audio->num_frames_per_band(),
181 audio->num_bands(), 191 apm_->stream_delay_ms(), stream_drift_samples_);
182 audio->split_bands_f(i),
183 audio->num_frames_per_band(),
184 apm_->stream_delay_ms(),
185 stream_drift_samples_);
186 192
187 if (err != apm_->kNoError) { 193 if (err != AudioProcessing::kNoError) {
188 err = MapError(err); 194 err = MapError(err);
189 // TODO(ajm): Figure out how to return warnings properly. 195 // TODO(ajm): Figure out how to return warnings properly.
190 if (err != apm_->kBadStreamParameterWarning) { 196 if (err != AudioProcessing::kBadStreamParameterWarning) {
191 return err; 197 return err;
192 } 198 }
193 } 199 }
194 200
195 int status = 0; 201 int status = 0;
196 err = WebRtcAec_get_echo_status(my_handle, &status); 202 err = WebRtcAec_get_echo_status(my_handle, &status);
197 if (err != apm_->kNoError) { 203 if (err != AudioProcessing::kNoError) {
198 return MapError(err); 204 return MapError(err);
199 } 205 }
200 206
201 if (status == 1) { 207 if (status == 1) {
202 stream_has_echo_ = true; 208 stream_has_echo_ = true;
203 } 209 }
204 210
205 handle_index++; 211 handle_index++;
206 } 212 }
207 } 213 }
208 214
209 was_stream_drift_set_ = false; 215 was_stream_drift_set_ = false;
210 return apm_->kNoError; 216 return AudioProcessing::kNoError;
211 } 217 }
212 218
213 int EchoCancellationImpl::Enable(bool enable) { 219 int EchoCancellationImpl::Enable(bool enable) {
214 CriticalSectionScoped crit_scoped(crit_); 220 // Run in a single-threaded manner.
221 rtc::CritScope cs_render(crit_render_);
222 rtc::CritScope cs_capture(crit_capture_);
215 // Ensure AEC and AECM are not both enabled. 223 // Ensure AEC and AECM are not both enabled.
224 // The is_enabled call is safe from a deadlock perspective
225 // as both locks are already held in the correct order.
216 if (enable && apm_->echo_control_mobile()->is_enabled()) { 226 if (enable && apm_->echo_control_mobile()->is_enabled()) {
217 return apm_->kBadParameterError; 227 return AudioProcessing::kBadParameterError;
218 } 228 }
219 229
220 return EnableComponent(enable); 230 return EnableComponent(enable);
221 } 231 }
222 232
223 bool EchoCancellationImpl::is_enabled() const { 233 bool EchoCancellationImpl::is_enabled() const {
234 rtc::CritScope cs(crit_capture_);
224 return is_component_enabled(); 235 return is_component_enabled();
225 } 236 }
226 237
227 int EchoCancellationImpl::set_suppression_level(SuppressionLevel level) { 238 int EchoCancellationImpl::set_suppression_level(SuppressionLevel level) {
228 CriticalSectionScoped crit_scoped(crit_); 239 {
229 if (MapSetting(level) == -1) { 240 if (MapSetting(level) == -1) {
230 return apm_->kBadParameterError; 241 return AudioProcessing::kBadParameterError;
242 }
243 rtc::CritScope cs(crit_capture_);
244 suppression_level_ = level;
231 } 245 }
232
233 suppression_level_ = level;
234 return Configure(); 246 return Configure();
235 } 247 }
236 248
237 EchoCancellation::SuppressionLevel EchoCancellationImpl::suppression_level() 249 EchoCancellation::SuppressionLevel EchoCancellationImpl::suppression_level()
238 const { 250 const {
251 rtc::CritScope cs(crit_capture_);
239 return suppression_level_; 252 return suppression_level_;
240 } 253 }
241 254
242 int EchoCancellationImpl::enable_drift_compensation(bool enable) { 255 int EchoCancellationImpl::enable_drift_compensation(bool enable) {
243 CriticalSectionScoped crit_scoped(crit_); 256 {
244 drift_compensation_enabled_ = enable; 257 rtc::CritScope cs(crit_capture_);
258 drift_compensation_enabled_ = enable;
259 }
245 return Configure(); 260 return Configure();
246 } 261 }
247 262
248 bool EchoCancellationImpl::is_drift_compensation_enabled() const { 263 bool EchoCancellationImpl::is_drift_compensation_enabled() const {
264 rtc::CritScope cs(crit_capture_);
249 return drift_compensation_enabled_; 265 return drift_compensation_enabled_;
250 } 266 }
251 267
252 void EchoCancellationImpl::set_stream_drift_samples(int drift) { 268 void EchoCancellationImpl::set_stream_drift_samples(int drift) {
269 rtc::CritScope cs(crit_capture_);
253 was_stream_drift_set_ = true; 270 was_stream_drift_set_ = true;
254 stream_drift_samples_ = drift; 271 stream_drift_samples_ = drift;
255 } 272 }
256 273
257 int EchoCancellationImpl::stream_drift_samples() const { 274 int EchoCancellationImpl::stream_drift_samples() const {
275 rtc::CritScope cs(crit_capture_);
258 return stream_drift_samples_; 276 return stream_drift_samples_;
259 } 277 }
260 278
261 int EchoCancellationImpl::enable_metrics(bool enable) { 279 int EchoCancellationImpl::enable_metrics(bool enable) {
262 CriticalSectionScoped crit_scoped(crit_); 280 {
263 metrics_enabled_ = enable; 281 rtc::CritScope cs(crit_capture_);
282 metrics_enabled_ = enable;
283 }
264 return Configure(); 284 return Configure();
265 } 285 }
266 286
267 bool EchoCancellationImpl::are_metrics_enabled() const { 287 bool EchoCancellationImpl::are_metrics_enabled() const {
288 rtc::CritScope cs(crit_capture_);
268 return metrics_enabled_; 289 return metrics_enabled_;
269 } 290 }
270 291
271 // TODO(ajm): we currently just use the metrics from the first AEC. Think more 292 // TODO(ajm): we currently just use the metrics from the first AEC. Think more
272 // aboue the best way to extend this to multi-channel. 293 // aboue the best way to extend this to multi-channel.
273 int EchoCancellationImpl::GetMetrics(Metrics* metrics) { 294 int EchoCancellationImpl::GetMetrics(Metrics* metrics) {
274 CriticalSectionScoped crit_scoped(crit_); 295 rtc::CritScope cs(crit_capture_);
275 if (metrics == NULL) { 296 if (metrics == NULL) {
276 return apm_->kNullPointerError; 297 return AudioProcessing::kNullPointerError;
277 } 298 }
278 299
279 if (!is_component_enabled() || !metrics_enabled_) { 300 if (!is_component_enabled() || !metrics_enabled_) {
280 return apm_->kNotEnabledError; 301 return AudioProcessing::kNotEnabledError;
281 } 302 }
282 303
283 AecMetrics my_metrics; 304 AecMetrics my_metrics;
284 memset(&my_metrics, 0, sizeof(my_metrics)); 305 memset(&my_metrics, 0, sizeof(my_metrics));
285 memset(metrics, 0, sizeof(Metrics)); 306 memset(metrics, 0, sizeof(Metrics));
286 307
287 Handle* my_handle = static_cast<Handle*>(handle(0)); 308 Handle* my_handle = static_cast<Handle*>(handle(0));
288 int err = WebRtcAec_GetMetrics(my_handle, &my_metrics); 309 int err = WebRtcAec_GetMetrics(my_handle, &my_metrics);
289 if (err != apm_->kNoError) { 310 if (err != AudioProcessing::kNoError) {
290 return MapError(err); 311 return MapError(err);
291 } 312 }
292 313
293 metrics->residual_echo_return_loss.instant = my_metrics.rerl.instant; 314 metrics->residual_echo_return_loss.instant = my_metrics.rerl.instant;
294 metrics->residual_echo_return_loss.average = my_metrics.rerl.average; 315 metrics->residual_echo_return_loss.average = my_metrics.rerl.average;
295 metrics->residual_echo_return_loss.maximum = my_metrics.rerl.max; 316 metrics->residual_echo_return_loss.maximum = my_metrics.rerl.max;
296 metrics->residual_echo_return_loss.minimum = my_metrics.rerl.min; 317 metrics->residual_echo_return_loss.minimum = my_metrics.rerl.min;
297 318
298 metrics->echo_return_loss.instant = my_metrics.erl.instant; 319 metrics->echo_return_loss.instant = my_metrics.erl.instant;
299 metrics->echo_return_loss.average = my_metrics.erl.average; 320 metrics->echo_return_loss.average = my_metrics.erl.average;
300 metrics->echo_return_loss.maximum = my_metrics.erl.max; 321 metrics->echo_return_loss.maximum = my_metrics.erl.max;
301 metrics->echo_return_loss.minimum = my_metrics.erl.min; 322 metrics->echo_return_loss.minimum = my_metrics.erl.min;
302 323
303 metrics->echo_return_loss_enhancement.instant = my_metrics.erle.instant; 324 metrics->echo_return_loss_enhancement.instant = my_metrics.erle.instant;
304 metrics->echo_return_loss_enhancement.average = my_metrics.erle.average; 325 metrics->echo_return_loss_enhancement.average = my_metrics.erle.average;
305 metrics->echo_return_loss_enhancement.maximum = my_metrics.erle.max; 326 metrics->echo_return_loss_enhancement.maximum = my_metrics.erle.max;
306 metrics->echo_return_loss_enhancement.minimum = my_metrics.erle.min; 327 metrics->echo_return_loss_enhancement.minimum = my_metrics.erle.min;
307 328
308 metrics->a_nlp.instant = my_metrics.aNlp.instant; 329 metrics->a_nlp.instant = my_metrics.aNlp.instant;
309 metrics->a_nlp.average = my_metrics.aNlp.average; 330 metrics->a_nlp.average = my_metrics.aNlp.average;
310 metrics->a_nlp.maximum = my_metrics.aNlp.max; 331 metrics->a_nlp.maximum = my_metrics.aNlp.max;
311 metrics->a_nlp.minimum = my_metrics.aNlp.min; 332 metrics->a_nlp.minimum = my_metrics.aNlp.min;
312 333
313 return apm_->kNoError; 334 return AudioProcessing::kNoError;
314 } 335 }
315 336
316 bool EchoCancellationImpl::stream_has_echo() const { 337 bool EchoCancellationImpl::stream_has_echo() const {
338 rtc::CritScope cs(crit_capture_);
317 return stream_has_echo_; 339 return stream_has_echo_;
318 } 340 }
319 341
320 int EchoCancellationImpl::enable_delay_logging(bool enable) { 342 int EchoCancellationImpl::enable_delay_logging(bool enable) {
321 CriticalSectionScoped crit_scoped(crit_); 343 {
322 delay_logging_enabled_ = enable; 344 rtc::CritScope cs(crit_capture_);
345 delay_logging_enabled_ = enable;
346 }
323 return Configure(); 347 return Configure();
324 } 348 }
325 349
326 bool EchoCancellationImpl::is_delay_logging_enabled() const { 350 bool EchoCancellationImpl::is_delay_logging_enabled() const {
351 rtc::CritScope cs(crit_capture_);
327 return delay_logging_enabled_; 352 return delay_logging_enabled_;
328 } 353 }
329 354
330 bool EchoCancellationImpl::is_delay_agnostic_enabled() const { 355 bool EchoCancellationImpl::is_delay_agnostic_enabled() const {
356 rtc::CritScope cs(crit_capture_);
331 return delay_agnostic_enabled_; 357 return delay_agnostic_enabled_;
332 } 358 }
333 359
334 bool EchoCancellationImpl::is_extended_filter_enabled() const { 360 bool EchoCancellationImpl::is_extended_filter_enabled() const {
361 rtc::CritScope cs(crit_capture_);
335 return extended_filter_enabled_; 362 return extended_filter_enabled_;
336 } 363 }
337 364
338 // TODO(bjornv): How should we handle the multi-channel case? 365 // TODO(bjornv): How should we handle the multi-channel case?
339 int EchoCancellationImpl::GetDelayMetrics(int* median, int* std) { 366 int EchoCancellationImpl::GetDelayMetrics(int* median, int* std) {
367 rtc::CritScope cs(crit_capture_);
340 float fraction_poor_delays = 0; 368 float fraction_poor_delays = 0;
341 return GetDelayMetrics(median, std, &fraction_poor_delays); 369 return GetDelayMetrics(median, std, &fraction_poor_delays);
342 } 370 }
343 371
344 int EchoCancellationImpl::GetDelayMetrics(int* median, int* std, 372 int EchoCancellationImpl::GetDelayMetrics(int* median, int* std,
345 float* fraction_poor_delays) { 373 float* fraction_poor_delays) {
346 CriticalSectionScoped crit_scoped(crit_); 374 rtc::CritScope cs(crit_capture_);
347 if (median == NULL) { 375 if (median == NULL) {
348 return apm_->kNullPointerError; 376 return AudioProcessing::kNullPointerError;
349 } 377 }
350 if (std == NULL) { 378 if (std == NULL) {
351 return apm_->kNullPointerError; 379 return AudioProcessing::kNullPointerError;
352 } 380 }
353 381
354 if (!is_component_enabled() || !delay_logging_enabled_) { 382 if (!is_component_enabled() || !delay_logging_enabled_) {
355 return apm_->kNotEnabledError; 383 return AudioProcessing::kNotEnabledError;
356 } 384 }
357 385
358 Handle* my_handle = static_cast<Handle*>(handle(0)); 386 Handle* my_handle = static_cast<Handle*>(handle(0));
359 const int err = 387 const int err =
360 WebRtcAec_GetDelayMetrics(my_handle, median, std, fraction_poor_delays); 388 WebRtcAec_GetDelayMetrics(my_handle, median, std, fraction_poor_delays);
361 if (err != apm_->kNoError) { 389 if (err != AudioProcessing::kNoError) {
362 return MapError(err); 390 return MapError(err);
363 } 391 }
364 392
365 return apm_->kNoError; 393 return AudioProcessing::kNoError;
366 } 394 }
367 395
368 struct AecCore* EchoCancellationImpl::aec_core() const { 396 struct AecCore* EchoCancellationImpl::aec_core() const {
369 CriticalSectionScoped crit_scoped(crit_); 397 rtc::CritScope cs(crit_capture_);
370 if (!is_component_enabled()) { 398 if (!is_component_enabled()) {
371 return NULL; 399 return NULL;
372 } 400 }
373 Handle* my_handle = static_cast<Handle*>(handle(0)); 401 Handle* my_handle = static_cast<Handle*>(handle(0));
374 return WebRtcAec_aec_core(my_handle); 402 return WebRtcAec_aec_core(my_handle);
375 } 403 }
376 404
377 int EchoCancellationImpl::Initialize() { 405 int EchoCancellationImpl::Initialize() {
378 int err = ProcessingComponent::Initialize(); 406 int err = ProcessingComponent::Initialize();
379 if (err != apm_->kNoError || !is_component_enabled()) { 407 {
380 return err; 408 rtc::CritScope cs(crit_capture_);
409 if (err != AudioProcessing::kNoError || !is_component_enabled()) {
410 return err;
411 }
381 } 412 }
382 413
383 AllocateRenderQueue(); 414 AllocateRenderQueue();
384 415
385 return apm_->kNoError; 416 return AudioProcessing::kNoError;
386 } 417 }
387 418
388 void EchoCancellationImpl::AllocateRenderQueue() { 419 void EchoCancellationImpl::AllocateRenderQueue() {
389 const size_t new_render_queue_element_max_size = std::max<size_t>( 420 const size_t new_render_queue_element_max_size = std::max<size_t>(
390 static_cast<size_t>(1), 421 static_cast<size_t>(1),
391 kMaxAllowedValuesOfSamplesPerFrame * num_handles_required()); 422 kMaxAllowedValuesOfSamplesPerFrame * num_handles_required());
392 423
424 rtc::CritScope cs_render(crit_render_);
425 rtc::CritScope cs_capture(crit_capture_);
426
393 // Reallocate the queue if the queue item size is too small to fit the 427 // Reallocate the queue if the queue item size is too small to fit the
394 // data to put in the queue. 428 // data to put in the queue.
395 if (render_queue_element_max_size_ < new_render_queue_element_max_size) { 429 if (render_queue_element_max_size_ < new_render_queue_element_max_size) {
396 render_queue_element_max_size_ = new_render_queue_element_max_size; 430 render_queue_element_max_size_ = new_render_queue_element_max_size;
397 431
398 std::vector<float> template_queue_element(render_queue_element_max_size_); 432 std::vector<float> template_queue_element(render_queue_element_max_size_);
399 433
400 render_signal_queue_.reset( 434 render_signal_queue_.reset(
401 new SwapQueue<std::vector<float>, RenderQueueItemVerifier<float>>( 435 new SwapQueue<std::vector<float>, RenderQueueItemVerifier<float>>(
402 kMaxNumFramesToBuffer, template_queue_element, 436 kMaxNumFramesToBuffer, template_queue_element,
403 RenderQueueItemVerifier<float>(render_queue_element_max_size_))); 437 RenderQueueItemVerifier<float>(render_queue_element_max_size_)));
404 438
405 render_queue_buffer_.resize(render_queue_element_max_size_); 439 render_queue_buffer_.resize(render_queue_element_max_size_);
406 capture_queue_buffer_.resize(render_queue_element_max_size_); 440 capture_queue_buffer_.resize(render_queue_element_max_size_);
407 } else { 441 } else {
408 render_signal_queue_->Clear(); 442 render_signal_queue_->Clear();
409 } 443 }
410 } 444 }
411 445
412 void EchoCancellationImpl::SetExtraOptions(const Config& config) { 446 void EchoCancellationImpl::SetExtraOptions(const Config& config) {
413 extended_filter_enabled_ = config.Get<ExtendedFilter>().enabled; 447 {
414 delay_agnostic_enabled_ = config.Get<DelayAgnostic>().enabled; 448 rtc::CritScope cs(crit_capture_);
449 extended_filter_enabled_ = config.Get<ExtendedFilter>().enabled;
450 delay_agnostic_enabled_ = config.Get<DelayAgnostic>().enabled;
451 }
415 Configure(); 452 Configure();
416 } 453 }
417 454
418 void* EchoCancellationImpl::CreateHandle() const { 455 void* EchoCancellationImpl::CreateHandle() const {
419 return WebRtcAec_Create(); 456 return WebRtcAec_Create();
420 } 457 }
421 458
422 void EchoCancellationImpl::DestroyHandle(void* handle) const { 459 void EchoCancellationImpl::DestroyHandle(void* handle) const {
423 assert(handle != NULL); 460 assert(handle != NULL);
424 WebRtcAec_Free(static_cast<Handle*>(handle)); 461 WebRtcAec_Free(static_cast<Handle*>(handle));
425 } 462 }
426 463
427 int EchoCancellationImpl::InitializeHandle(void* handle) const { 464 int EchoCancellationImpl::InitializeHandle(void* handle) const {
465 // Not locked as it only relies on APM public API which is threadsafe.
466
428 assert(handle != NULL); 467 assert(handle != NULL);
429 // TODO(ajm): Drift compensation is disabled in practice. If restored, it 468 // TODO(ajm): Drift compensation is disabled in practice. If restored, it
430 // should be managed internally and not depend on the hardware sample rate. 469 // should be managed internally and not depend on the hardware sample rate.
431 // For now, just hardcode a 48 kHz value. 470 // For now, just hardcode a 48 kHz value.
432 return WebRtcAec_Init(static_cast<Handle*>(handle), 471 return WebRtcAec_Init(static_cast<Handle*>(handle),
433 apm_->proc_sample_rate_hz(), 472 apm_->proc_sample_rate_hz(), 48000);
434 48000);
435 } 473 }
436 474
437 int EchoCancellationImpl::ConfigureHandle(void* handle) const { 475 int EchoCancellationImpl::ConfigureHandle(void* handle) const {
476 rtc::CritScope cs_render(crit_render_);
477 rtc::CritScope cs_capture(crit_capture_);
438 assert(handle != NULL); 478 assert(handle != NULL);
439 AecConfig config; 479 AecConfig config;
440 config.metricsMode = metrics_enabled_; 480 config.metricsMode = metrics_enabled_;
441 config.nlpMode = MapSetting(suppression_level_); 481 config.nlpMode = MapSetting(suppression_level_);
442 config.skewMode = drift_compensation_enabled_; 482 config.skewMode = drift_compensation_enabled_;
443 config.delay_logging = delay_logging_enabled_; 483 config.delay_logging = delay_logging_enabled_;
444
445 WebRtcAec_enable_extended_filter( 484 WebRtcAec_enable_extended_filter(
446 WebRtcAec_aec_core(static_cast<Handle*>(handle)), 485 WebRtcAec_aec_core(static_cast<Handle*>(handle)),
447 extended_filter_enabled_ ? 1 : 0); 486 extended_filter_enabled_ ? 1 : 0);
448 WebRtcAec_enable_delay_agnostic( 487 WebRtcAec_enable_delay_agnostic(
449 WebRtcAec_aec_core(static_cast<Handle*>(handle)), 488 WebRtcAec_aec_core(static_cast<Handle*>(handle)),
450 delay_agnostic_enabled_ ? 1 : 0); 489 delay_agnostic_enabled_ ? 1 : 0);
451 return WebRtcAec_set_config(static_cast<Handle*>(handle), config); 490 return WebRtcAec_set_config(static_cast<Handle*>(handle), config);
452 } 491 }
453 492
454 int EchoCancellationImpl::num_handles_required() const { 493 int EchoCancellationImpl::num_handles_required() const {
494 // Not locked as it only relies on APM public API which is threadsafe.
455 return apm_->num_output_channels() * 495 return apm_->num_output_channels() *
456 apm_->num_reverse_channels(); 496 apm_->num_reverse_channels();
457 } 497 }
458 498
459 int EchoCancellationImpl::GetHandleError(void* handle) const { 499 int EchoCancellationImpl::GetHandleError(void* handle) const {
500 // Not locked as it does not rely on anything in the state.
460 assert(handle != NULL); 501 assert(handle != NULL);
461 return AudioProcessing::kUnspecifiedError; 502 return AudioProcessing::kUnspecifiedError;
462 } 503 }
463 } // namespace webrtc 504 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698