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

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