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

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: Changes in response to reviewer comments 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 25 matching lines...) Expand all
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( 64 EchoCancellationImpl::EchoCancellationImpl(
66 const AudioProcessing* apm, 65 const AudioProcessing* apm,
67 CriticalSectionWrapper* crit, 66 rtc::CriticalSection* crit_render,
67 rtc::CriticalSection* crit_capture,
68 const rtc::ThreadChecker* render_thread_checker) 68 const rtc::ThreadChecker* render_thread_checker)
69 : ProcessingComponent(), 69 : ProcessingComponent(),
70 apm_(apm), 70 apm_(apm),
71 crit_(crit), 71 crit_render_(crit_render),
72 crit_capture_(crit_capture),
72 render_thread_checker_(render_thread_checker), 73 render_thread_checker_(render_thread_checker),
73 drift_compensation_enabled_(false), 74 drift_compensation_enabled_(false),
74 metrics_enabled_(false), 75 metrics_enabled_(false),
75 suppression_level_(kModerateSuppression), 76 suppression_level_(kModerateSuppression),
76 stream_drift_samples_(0), 77 stream_drift_samples_(0),
77 was_stream_drift_set_(false), 78 was_stream_drift_set_(false),
78 stream_has_echo_(false), 79 stream_has_echo_(false),
79 delay_logging_enabled_(false), 80 delay_logging_enabled_(false),
80 extended_filter_enabled_(false), 81 extended_filter_enabled_(false),
81 delay_agnostic_enabled_(false), 82 delay_agnostic_enabled_(false),
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 // Buffer the samples in the render queue. 114 // Buffer the samples in the render queue.
114 render_queue_buffer_.insert(render_queue_buffer_.end(), 115 render_queue_buffer_.insert(render_queue_buffer_.end(),
115 audio->split_bands_const_f(j)[kBand0To8kHz], 116 audio->split_bands_const_f(j)[kBand0To8kHz],
116 (audio->split_bands_const_f(j)[kBand0To8kHz] + 117 (audio->split_bands_const_f(j)[kBand0To8kHz] +
117 audio->num_frames_per_band())); 118 audio->num_frames_per_band()));
118 } 119 }
119 } 120 }
120 121
121 // Insert the samples into the queue. 122 // Insert the samples into the queue.
122 if (!render_signal_queue_->Insert(&render_queue_buffer_)) { 123 if (!render_signal_queue_->Insert(&render_queue_buffer_)) {
123 ReadQueuedRenderData(); 124 // The data queue is full and needs to be emptied.
125 {
126 rtc::CritScope cs_capture(crit_capture_);
127 ReadQueuedRenderData();
128 }
124 129
125 // Retry the insert (should always work). 130 // Retry the insert (should always work).
126 RTC_DCHECK_EQ(render_signal_queue_->Insert(&render_queue_buffer_), true); 131 RTC_DCHECK_EQ(render_signal_queue_->Insert(&render_queue_buffer_), true);
127 } 132 }
128 133
129 return apm_->kNoError; 134 return apm_->kNoError;
130 } 135 }
131 136
132 // Read chunks of data that were received and queued on the render side from 137 // Read chunks of data that were received and queued on the render side from
133 // a queue. All the data chunks are buffered into the farend signal of the AEC. 138 // a queue. All the data chunks are buffered into the farend signal of the AEC.
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 213
209 handle_index++; 214 handle_index++;
210 } 215 }
211 } 216 }
212 217
213 was_stream_drift_set_ = false; 218 was_stream_drift_set_ = false;
214 return apm_->kNoError; 219 return apm_->kNoError;
215 } 220 }
216 221
217 int EchoCancellationImpl::Enable(bool enable) { 222 int EchoCancellationImpl::Enable(bool enable) {
218 CriticalSectionScoped crit_scoped(crit_); 223 // Run in a single-threaded manner.
224 rtc::CritScope cs_render(crit_render_);
225 rtc::CritScope cs_capture(crit_capture_);
219 // Ensure AEC and AECM are not both enabled. 226 // Ensure AEC and AECM are not both enabled.
220 if (enable && apm_->echo_control_mobile()->is_enabled()) { 227 if (enable && apm_->echo_control_mobile()->is_enabled()) {
221 return apm_->kBadParameterError; 228 return apm_->kBadParameterError;
222 } 229 }
223 230
224 return EnableComponent(enable); 231 return EnableComponent(enable);
225 } 232 }
226 233
227 bool EchoCancellationImpl::is_enabled() const { 234 bool EchoCancellationImpl::is_enabled() const {
235 rtc::CritScope cs(crit_capture_);
228 return is_component_enabled(); 236 return is_component_enabled();
229 } 237 }
230 238
231 int EchoCancellationImpl::set_suppression_level(SuppressionLevel level) { 239 int EchoCancellationImpl::set_suppression_level(SuppressionLevel level) {
232 CriticalSectionScoped crit_scoped(crit_); 240 rtc::CritScope cs(crit_capture_);
233 if (MapSetting(level) == -1) { 241 if (MapSetting(level) == -1) {
234 return apm_->kBadParameterError; 242 return apm_->kBadParameterError;
235 } 243 }
236 244
237 suppression_level_ = level; 245 suppression_level_ = level;
238 return Configure(); 246 return Configure();
239 } 247 }
240 248
241 EchoCancellation::SuppressionLevel EchoCancellationImpl::suppression_level() 249 EchoCancellation::SuppressionLevel EchoCancellationImpl::suppression_level()
242 const { 250 const {
251 rtc::CritScope cs(crit_capture_);
243 return suppression_level_; 252 return suppression_level_;
244 } 253 }
245 254
246 int EchoCancellationImpl::enable_drift_compensation(bool enable) { 255 int EchoCancellationImpl::enable_drift_compensation(bool enable) {
247 CriticalSectionScoped crit_scoped(crit_); 256 rtc::CritScope cs(crit_capture_);
248 drift_compensation_enabled_ = enable; 257 drift_compensation_enabled_ = enable;
249 return Configure(); 258 return Configure();
250 } 259 }
251 260
252 bool EchoCancellationImpl::is_drift_compensation_enabled() const { 261 bool EchoCancellationImpl::is_drift_compensation_enabled() const {
262 rtc::CritScope cs(crit_capture_);
253 return drift_compensation_enabled_; 263 return drift_compensation_enabled_;
254 } 264 }
255 265
256 void EchoCancellationImpl::set_stream_drift_samples(int drift) { 266 void EchoCancellationImpl::set_stream_drift_samples(int drift) {
267 rtc::CritScope cs(crit_capture_);
257 was_stream_drift_set_ = true; 268 was_stream_drift_set_ = true;
258 stream_drift_samples_ = drift; 269 stream_drift_samples_ = drift;
259 } 270 }
260 271
261 int EchoCancellationImpl::stream_drift_samples() const { 272 int EchoCancellationImpl::stream_drift_samples() const {
273 rtc::CritScope cs(crit_capture_);
262 return stream_drift_samples_; 274 return stream_drift_samples_;
263 } 275 }
264 276
265 int EchoCancellationImpl::enable_metrics(bool enable) { 277 int EchoCancellationImpl::enable_metrics(bool enable) {
266 CriticalSectionScoped crit_scoped(crit_); 278 rtc::CritScope cs(crit_capture_);
267 metrics_enabled_ = enable; 279 metrics_enabled_ = enable;
268 return Configure(); 280 return Configure();
269 } 281 }
270 282
271 bool EchoCancellationImpl::are_metrics_enabled() const { 283 bool EchoCancellationImpl::are_metrics_enabled() const {
284 rtc::CritScope cs(crit_capture_);
272 return metrics_enabled_; 285 return metrics_enabled_;
273 } 286 }
274 287
275 // TODO(ajm): we currently just use the metrics from the first AEC. Think more 288 // TODO(ajm): we currently just use the metrics from the first AEC. Think more
276 // aboue the best way to extend this to multi-channel. 289 // aboue the best way to extend this to multi-channel.
277 int EchoCancellationImpl::GetMetrics(Metrics* metrics) { 290 int EchoCancellationImpl::GetMetrics(Metrics* metrics) {
278 CriticalSectionScoped crit_scoped(crit_); 291 rtc::CritScope cs(crit_capture_);
279 if (metrics == NULL) { 292 if (metrics == NULL) {
280 return apm_->kNullPointerError; 293 return apm_->kNullPointerError;
281 } 294 }
282 295
283 if (!is_component_enabled() || !metrics_enabled_) { 296 if (!is_component_enabled() || !metrics_enabled_) {
284 return apm_->kNotEnabledError; 297 return apm_->kNotEnabledError;
285 } 298 }
286 299
287 AecMetrics my_metrics; 300 AecMetrics my_metrics;
288 memset(&my_metrics, 0, sizeof(my_metrics)); 301 memset(&my_metrics, 0, sizeof(my_metrics));
(...skipping 22 matching lines...) Expand all
311 324
312 metrics->a_nlp.instant = my_metrics.aNlp.instant; 325 metrics->a_nlp.instant = my_metrics.aNlp.instant;
313 metrics->a_nlp.average = my_metrics.aNlp.average; 326 metrics->a_nlp.average = my_metrics.aNlp.average;
314 metrics->a_nlp.maximum = my_metrics.aNlp.max; 327 metrics->a_nlp.maximum = my_metrics.aNlp.max;
315 metrics->a_nlp.minimum = my_metrics.aNlp.min; 328 metrics->a_nlp.minimum = my_metrics.aNlp.min;
316 329
317 return apm_->kNoError; 330 return apm_->kNoError;
318 } 331 }
319 332
320 bool EchoCancellationImpl::stream_has_echo() const { 333 bool EchoCancellationImpl::stream_has_echo() const {
334 // This is called both from within and from outside of APM, with and
335 // without locks set. The lock acquisition below is hence possible
336 // reentrant.
kwiberg-webrtc 2015/11/25 10:17:14 possibly
peah-webrtc 2015/11/25 12:33:53 Done.
337 rtc::CritScope cs(crit_capture_);
338
321 return stream_has_echo_; 339 return stream_has_echo_;
322 } 340 }
323 341
324 int EchoCancellationImpl::enable_delay_logging(bool enable) { 342 int EchoCancellationImpl::enable_delay_logging(bool enable) {
325 CriticalSectionScoped crit_scoped(crit_); 343 // This is called both from within and from outside of APM, with and
344 // without locks set. The lock acquisition below is hence possible
345 // reentrant.
kwiberg-webrtc 2015/11/25 10:17:14 possibly
peah-webrtc 2015/11/25 12:33:53 Done.
346 rtc::CritScope cs(crit_capture_);
347
326 delay_logging_enabled_ = enable; 348 delay_logging_enabled_ = enable;
327 return Configure(); 349 return Configure();
328 } 350 }
329 351
330 bool EchoCancellationImpl::is_delay_logging_enabled() const { 352 bool EchoCancellationImpl::is_delay_logging_enabled() const {
353 rtc::CritScope cs(crit_capture_);
331 return delay_logging_enabled_; 354 return delay_logging_enabled_;
332 } 355 }
333 356
334 bool EchoCancellationImpl::is_delay_agnostic_enabled() const { 357 bool EchoCancellationImpl::is_delay_agnostic_enabled() const {
358 // Only called from within APM, hence no locking is needed.
335 return delay_agnostic_enabled_; 359 return delay_agnostic_enabled_;
336 } 360 }
337 361
338 bool EchoCancellationImpl::is_extended_filter_enabled() const { 362 bool EchoCancellationImpl::is_extended_filter_enabled() const {
363 // Only called from within APM, hence no locking is needed.
339 return extended_filter_enabled_; 364 return extended_filter_enabled_;
340 } 365 }
341 366
342 // TODO(bjornv): How should we handle the multi-channel case? 367 // TODO(bjornv): How should we handle the multi-channel case?
343 int EchoCancellationImpl::GetDelayMetrics(int* median, int* std) { 368 int EchoCancellationImpl::GetDelayMetrics(int* median, int* std) {
369 rtc::CritScope cs(crit_capture_);
344 float fraction_poor_delays = 0; 370 float fraction_poor_delays = 0;
345 return GetDelayMetrics(median, std, &fraction_poor_delays); 371 return GetDelayMetrics(median, std, &fraction_poor_delays);
346 } 372 }
347 373
348 int EchoCancellationImpl::GetDelayMetrics(int* median, int* std, 374 int EchoCancellationImpl::GetDelayMetrics(int* median, int* std,
349 float* fraction_poor_delays) { 375 float* fraction_poor_delays) {
350 CriticalSectionScoped crit_scoped(crit_); 376 rtc::CritScope cs(crit_capture_);
351 if (median == NULL) { 377 if (median == NULL) {
352 return apm_->kNullPointerError; 378 return apm_->kNullPointerError;
353 } 379 }
354 if (std == NULL) { 380 if (std == NULL) {
355 return apm_->kNullPointerError; 381 return apm_->kNullPointerError;
356 } 382 }
357 383
358 if (!is_component_enabled() || !delay_logging_enabled_) { 384 if (!is_component_enabled() || !delay_logging_enabled_) {
359 return apm_->kNotEnabledError; 385 return apm_->kNotEnabledError;
360 } 386 }
361 387
362 Handle* my_handle = static_cast<Handle*>(handle(0)); 388 Handle* my_handle = static_cast<Handle*>(handle(0));
363 const int err = 389 const int err =
364 WebRtcAec_GetDelayMetrics(my_handle, median, std, fraction_poor_delays); 390 WebRtcAec_GetDelayMetrics(my_handle, median, std, fraction_poor_delays);
365 if (err != apm_->kNoError) { 391 if (err != apm_->kNoError) {
366 return MapError(err); 392 return MapError(err);
367 } 393 }
368 394
369 return apm_->kNoError; 395 return apm_->kNoError;
370 } 396 }
371 397
372 struct AecCore* EchoCancellationImpl::aec_core() const { 398 struct AecCore* EchoCancellationImpl::aec_core() const {
373 CriticalSectionScoped crit_scoped(crit_); 399 // Only called from within APM, hence no locking is needed.
374 if (!is_component_enabled()) { 400 if (!is_component_enabled()) {
375 return NULL; 401 return NULL;
376 } 402 }
377 Handle* my_handle = static_cast<Handle*>(handle(0)); 403 Handle* my_handle = static_cast<Handle*>(handle(0));
378 return WebRtcAec_aec_core(my_handle); 404 return WebRtcAec_aec_core(my_handle);
379 } 405 }
380 406
381 int EchoCancellationImpl::Initialize() { 407 int EchoCancellationImpl::Initialize() {
408 // Only called from within APM, hence no locking is needed.
382 int err = ProcessingComponent::Initialize(); 409 int err = ProcessingComponent::Initialize();
383 if (err != apm_->kNoError || !is_component_enabled()) { 410 if (err != apm_->kNoError || !is_component_enabled()) {
384 return err; 411 return err;
385 } 412 }
386 413
387 AllocateRenderQueue(); 414 AllocateRenderQueue();
388 415
389 return apm_->kNoError; 416 return apm_->kNoError;
390 } 417 }
391 418
(...skipping 15 matching lines...) Expand all
407 RenderQueueItemVerifier<float>(render_queue_element_max_size_))); 434 RenderQueueItemVerifier<float>(render_queue_element_max_size_)));
408 435
409 render_queue_buffer_.resize(render_queue_element_max_size_); 436 render_queue_buffer_.resize(render_queue_element_max_size_);
410 capture_queue_buffer_.resize(render_queue_element_max_size_); 437 capture_queue_buffer_.resize(render_queue_element_max_size_);
411 } else { 438 } else {
412 render_signal_queue_->Clear(); 439 render_signal_queue_->Clear();
413 } 440 }
414 } 441 }
415 442
416 void EchoCancellationImpl::SetExtraOptions(const Config& config) { 443 void EchoCancellationImpl::SetExtraOptions(const Config& config) {
444 // This is called both from within and from outside of APM, with and
445 // without locks set. The lock acquisition below is hence possible
446 // reentrant.
kwiberg-webrtc 2015/11/25 10:17:14 possibly
peah-webrtc 2015/11/25 12:33:53 Done.
447 rtc::CritScope cs(crit_capture_);
417 extended_filter_enabled_ = config.Get<ExtendedFilter>().enabled; 448 extended_filter_enabled_ = config.Get<ExtendedFilter>().enabled;
418 delay_agnostic_enabled_ = config.Get<DelayAgnostic>().enabled; 449 delay_agnostic_enabled_ = config.Get<DelayAgnostic>().enabled;
419 Configure(); 450 Configure();
420 } 451 }
421 452
422 void* EchoCancellationImpl::CreateHandle() const { 453 void* EchoCancellationImpl::CreateHandle() const {
454 // Only called from within APM, hence no locking is needed.
423 return WebRtcAec_Create(); 455 return WebRtcAec_Create();
424 } 456 }
425 457
426 void EchoCancellationImpl::DestroyHandle(void* handle) const { 458 void EchoCancellationImpl::DestroyHandle(void* handle) const {
459 // Only called from within APM, hence no locking is needed.
427 assert(handle != NULL); 460 assert(handle != NULL);
428 WebRtcAec_Free(static_cast<Handle*>(handle)); 461 WebRtcAec_Free(static_cast<Handle*>(handle));
429 } 462 }
430 463
431 int EchoCancellationImpl::InitializeHandle(void* handle) const { 464 int EchoCancellationImpl::InitializeHandle(void* handle) const {
465 // Only called from within APM, hence no locking is needed.
432 assert(handle != NULL); 466 assert(handle != NULL);
433 // TODO(ajm): Drift compensation is disabled in practice. If restored, it 467 // TODO(ajm): Drift compensation is disabled in practice. If restored, it
434 // should be managed internally and not depend on the hardware sample rate. 468 // should be managed internally and not depend on the hardware sample rate.
435 // For now, just hardcode a 48 kHz value. 469 // For now, just hardcode a 48 kHz value.
436 return WebRtcAec_Init(static_cast<Handle*>(handle), 470 return WebRtcAec_Init(static_cast<Handle*>(handle),
437 apm_->proc_sample_rate_hz(), 471 apm_->proc_sample_rate_hz(),
438 48000); 472 48000);
439 } 473 }
440 474
441 int EchoCancellationImpl::ConfigureHandle(void* handle) const { 475 int EchoCancellationImpl::ConfigureHandle(void* handle) const {
476 // Only called from within APM, hence no locking is needed.
442 assert(handle != NULL); 477 assert(handle != NULL);
443 AecConfig config; 478 AecConfig config;
444 config.metricsMode = metrics_enabled_; 479 config.metricsMode = metrics_enabled_;
445 config.nlpMode = MapSetting(suppression_level_); 480 config.nlpMode = MapSetting(suppression_level_);
446 config.skewMode = drift_compensation_enabled_; 481 config.skewMode = drift_compensation_enabled_;
447 config.delay_logging = delay_logging_enabled_; 482 config.delay_logging = delay_logging_enabled_;
448 WebRtcAec_enable_extended_filter( 483 WebRtcAec_enable_extended_filter(
449 WebRtcAec_aec_core(static_cast<Handle*>(handle)), 484 WebRtcAec_aec_core(static_cast<Handle*>(handle)),
450 extended_filter_enabled_ ? 1 : 0); 485 extended_filter_enabled_ ? 1 : 0);
451 WebRtcAec_enable_delay_agnostic( 486 WebRtcAec_enable_delay_agnostic(
452 WebRtcAec_aec_core(static_cast<Handle*>(handle)), 487 WebRtcAec_aec_core(static_cast<Handle*>(handle)),
453 delay_agnostic_enabled_ ? 1 : 0); 488 delay_agnostic_enabled_ ? 1 : 0);
454 return WebRtcAec_set_config(static_cast<Handle*>(handle), config); 489 return WebRtcAec_set_config(static_cast<Handle*>(handle), config);
455 } 490 }
456 491
457 int EchoCancellationImpl::num_handles_required() const { 492 int EchoCancellationImpl::num_handles_required() const {
493 // Only called from within APM, hence no locking is needed.
458 return apm_->num_output_channels() * 494 return apm_->num_output_channels() *
459 apm_->num_reverse_channels(); 495 apm_->num_reverse_channels();
460 } 496 }
461 497
462 int EchoCancellationImpl::GetHandleError(void* handle) const { 498 int EchoCancellationImpl::GetHandleError(void* handle) const {
499 // Only called from within APM, hence no locking is needed.
463 assert(handle != NULL); 500 assert(handle != NULL);
464 return AudioProcessing::kUnspecifiedError; 501 return AudioProcessing::kUnspecifiedError;
465 } 502 }
466 } // namespace webrtc 503 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/audio_processing/echo_cancellation_impl.h ('k') | webrtc/modules/audio_processing/echo_control_mobile_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698