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

Side by Side Diff: webrtc/modules/audio_processing/echo_control_mobile_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: Major general updates, completing the locking scheme, and increasing readability Created 5 years, 1 month 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_control_mobile_impl.h" 11 #include "webrtc/modules/audio_processing/echo_control_mobile_impl.h"
12 12
13 #include <assert.h> 13 #include <assert.h>
14 #include <string.h> 14 #include <string.h>
15 15
16 #include "webrtc/base/criticalsection.h"
16 #include "webrtc/modules/audio_processing/aecm/include/echo_control_mobile.h" 17 #include "webrtc/modules/audio_processing/aecm/include/echo_control_mobile.h"
17 #include "webrtc/modules/audio_processing/audio_buffer.h" 18 #include "webrtc/modules/audio_processing/audio_buffer.h"
18 #include "webrtc/system_wrappers/include/critical_section_wrapper.h"
19 #include "webrtc/system_wrappers/include/logging.h" 19 #include "webrtc/system_wrappers/include/logging.h"
20 20
21 namespace webrtc { 21 namespace webrtc {
22 22
23 typedef void Handle; 23 typedef void Handle;
24 24
25 namespace { 25 namespace {
26 int16_t MapSetting(EchoControlMobile::RoutingMode mode) { 26 int16_t MapSetting(EchoControlMobile::RoutingMode mode) {
27 switch (mode) { 27 switch (mode) {
28 case EchoControlMobile::kQuietEarpieceOrHeadset: 28 case EchoControlMobile::kQuietEarpieceOrHeadset:
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 60
61 const size_t EchoControlMobileImpl::kAllowedValuesOfSamplesPerFrame1; 61 const size_t EchoControlMobileImpl::kAllowedValuesOfSamplesPerFrame1;
62 const size_t EchoControlMobileImpl::kAllowedValuesOfSamplesPerFrame2; 62 const size_t EchoControlMobileImpl::kAllowedValuesOfSamplesPerFrame2;
63 63
64 size_t EchoControlMobile::echo_path_size_bytes() { 64 size_t EchoControlMobile::echo_path_size_bytes() {
65 return WebRtcAecm_echo_path_size_bytes(); 65 return WebRtcAecm_echo_path_size_bytes();
66 } 66 }
67 67
68 EchoControlMobileImpl::EchoControlMobileImpl( 68 EchoControlMobileImpl::EchoControlMobileImpl(
69 const AudioProcessing* apm, 69 const AudioProcessing* apm,
70 CriticalSectionWrapper* crit, 70 rtc::CriticalSection* crit_render,
71 rtc::CriticalSection* crit_capture,
71 rtc::ThreadChecker* render_thread_checker) 72 rtc::ThreadChecker* render_thread_checker)
72 : ProcessingComponent(), 73 : ProcessingComponent(),
73 apm_(apm), 74 apm_(apm),
74 crit_(crit), 75 crit_render_(crit_render),
76 crit_capture_(crit_capture),
75 render_thread_checker_(render_thread_checker), 77 render_thread_checker_(render_thread_checker),
76 routing_mode_(kSpeakerphone), 78 routing_mode_(kSpeakerphone),
77 comfort_noise_enabled_(true), 79 comfort_noise_enabled_(true),
78 external_echo_path_(NULL), 80 external_echo_path_(NULL),
79 render_queue_element_max_size_(0) { 81 render_queue_element_max_size_(0) {
80 AllocateRenderQueue(); 82 AllocateRenderQueue();
81 } 83 }
82 84
83 EchoControlMobileImpl::~EchoControlMobileImpl() { 85 EchoControlMobileImpl::~EchoControlMobileImpl() {
84 if (external_echo_path_ != NULL) { 86 if (external_echo_path_ != NULL) {
(...skipping 29 matching lines...) Expand all
114 // Buffer the samples in the render queue. 116 // Buffer the samples in the render queue.
115 render_queue_buffer_.insert(render_queue_buffer_.end(), 117 render_queue_buffer_.insert(render_queue_buffer_.end(),
116 audio->split_bands_const(j)[kBand0To8kHz], 118 audio->split_bands_const(j)[kBand0To8kHz],
117 (audio->split_bands_const(j)[kBand0To8kHz] + 119 (audio->split_bands_const(j)[kBand0To8kHz] +
118 audio->num_frames_per_band())); 120 audio->num_frames_per_band()));
119 121
120 handle_index++; 122 handle_index++;
121 } 123 }
122 } 124 }
123 125
124 // Check of success is temporarily disabled as it breaks a unit test. 126 // Insert the samples into the queue.
125 // TODO(peah): Will be fixed in the next CL. 127 bool success = render_signal_queue_->Insert(&render_queue_buffer_);
126 (void)render_signal_queue_->Insert(&render_queue_buffer_); 128 if (!success) {
hlundin-webrtc 2015/11/05 16:11:22 if (!render_signal_queue_->Insert(&render_queue_bu
peah-webrtc 2015/11/06 09:54:32 Done.
129 // The data queue is full and needs to be emptied.
130 {
131 rtc::CritScope cs_capture(crit_capture_);
132 ReadQueuedRenderData();
133 }
134
135 // Retry the insert (should always work).
136 RTC_DCHECK_EQ(render_signal_queue_->Insert(&render_queue_buffer_), true);
137 }
127 138
128 return apm_->kNoError; 139 return apm_->kNoError;
129 } 140 }
130 141
131 // Read chunks of data that were received and queued on the render side from 142 // Read chunks of data that were received and queued on the render side from
132 // a queue. All the data chunks are buffered into the farend signal of the AEC. 143 // a queue. All the data chunks are buffered into the farend signal of the AEC.
133 void EchoControlMobileImpl::ReadQueuedRenderData() { 144 void EchoControlMobileImpl::ReadQueuedRenderData() {
134 if (!is_component_enabled()) { 145 if (!is_component_enabled()) {
135 return; 146 return;
136 } 147 }
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 return MapError(err); 205 return MapError(err);
195 206
196 handle_index++; 207 handle_index++;
197 } 208 }
198 } 209 }
199 210
200 return apm_->kNoError; 211 return apm_->kNoError;
201 } 212 }
202 213
203 int EchoControlMobileImpl::Enable(bool enable) { 214 int EchoControlMobileImpl::Enable(bool enable) {
204 CriticalSectionScoped crit_scoped(crit_); 215 // Run in a single-threaded manner
216 rtc::CritScope cs_render(crit_render_);
217 rtc::CritScope cs_capture(crit_capture_);
205 // Ensure AEC and AECM are not both enabled. 218 // Ensure AEC and AECM are not both enabled.
206 if (enable && apm_->echo_cancellation()->is_enabled()) { 219 if (enable && apm_->echo_cancellation()->is_enabled()) {
207 return apm_->kBadParameterError; 220 return apm_->kBadParameterError;
208 } 221 }
209 222
210 return EnableComponent(enable); 223 return EnableComponent(enable);
211 } 224 }
212 225
213 bool EchoControlMobileImpl::is_enabled() const { 226 bool EchoControlMobileImpl::is_enabled() const {
227 rtc::CritScope cs(crit_capture_);
214 return is_component_enabled(); 228 return is_component_enabled();
215 } 229 }
216 230
217 int EchoControlMobileImpl::set_routing_mode(RoutingMode mode) { 231 int EchoControlMobileImpl::set_routing_mode(RoutingMode mode) {
218 CriticalSectionScoped crit_scoped(crit_); 232 rtc::CritScope cs(crit_capture_);
219 if (MapSetting(mode) == -1) { 233 if (MapSetting(mode) == -1) {
220 return apm_->kBadParameterError; 234 return apm_->kBadParameterError;
221 } 235 }
222 236
223 routing_mode_ = mode; 237 routing_mode_ = mode;
224 return Configure(); 238 return Configure();
225 } 239 }
226 240
227 EchoControlMobile::RoutingMode EchoControlMobileImpl::routing_mode() 241 EchoControlMobile::RoutingMode EchoControlMobileImpl::routing_mode()
228 const { 242 const {
243 rtc::CritScope cs(crit_capture_);
229 return routing_mode_; 244 return routing_mode_;
230 } 245 }
231 246
232 int EchoControlMobileImpl::enable_comfort_noise(bool enable) { 247 int EchoControlMobileImpl::enable_comfort_noise(bool enable) {
233 CriticalSectionScoped crit_scoped(crit_); 248 rtc::CritScope cs(crit_capture_);
234 comfort_noise_enabled_ = enable; 249 comfort_noise_enabled_ = enable;
235 return Configure(); 250 return Configure();
236 } 251 }
237 252
238 bool EchoControlMobileImpl::is_comfort_noise_enabled() const { 253 bool EchoControlMobileImpl::is_comfort_noise_enabled() const {
254 rtc::CritScope cs(crit_capture_);
239 return comfort_noise_enabled_; 255 return comfort_noise_enabled_;
240 } 256 }
241 257
242 int EchoControlMobileImpl::SetEchoPath(const void* echo_path, 258 int EchoControlMobileImpl::SetEchoPath(const void* echo_path,
243 size_t size_bytes) { 259 size_t size_bytes) {
244 CriticalSectionScoped crit_scoped(crit_); 260 rtc::CritScope cs_render(crit_render_);
261 rtc::CritScope cs_capture(crit_capture_);
245 if (echo_path == NULL) { 262 if (echo_path == NULL) {
246 return apm_->kNullPointerError; 263 return apm_->kNullPointerError;
247 } 264 }
248 if (size_bytes != echo_path_size_bytes()) { 265 if (size_bytes != echo_path_size_bytes()) {
249 // Size mismatch 266 // Size mismatch
250 return apm_->kBadParameterError; 267 return apm_->kBadParameterError;
251 } 268 }
252 269
253 if (external_echo_path_ == NULL) { 270 if (external_echo_path_ == NULL) {
254 external_echo_path_ = new unsigned char[size_bytes]; 271 external_echo_path_ = new unsigned char[size_bytes];
255 } 272 }
256 memcpy(external_echo_path_, echo_path, size_bytes); 273 memcpy(external_echo_path_, echo_path, size_bytes);
257 274
258 return Initialize(); 275 return Initialize();
259 } 276 }
260 277
261 int EchoControlMobileImpl::GetEchoPath(void* echo_path, 278 int EchoControlMobileImpl::GetEchoPath(void* echo_path,
262 size_t size_bytes) const { 279 size_t size_bytes) const {
263 CriticalSectionScoped crit_scoped(crit_); 280 rtc::CritScope cs(crit_capture_);
264 if (echo_path == NULL) { 281 if (echo_path == NULL) {
265 return apm_->kNullPointerError; 282 return apm_->kNullPointerError;
266 } 283 }
267 if (size_bytes != echo_path_size_bytes()) { 284 if (size_bytes != echo_path_size_bytes()) {
268 // Size mismatch 285 // Size mismatch
269 return apm_->kBadParameterError; 286 return apm_->kBadParameterError;
270 } 287 }
271 if (!is_component_enabled()) { 288 if (!is_component_enabled()) {
272 return apm_->kNotEnabledError; 289 return apm_->kNotEnabledError;
273 } 290 }
274 291
275 // Get the echo path from the first channel 292 // Get the echo path from the first channel
276 Handle* my_handle = static_cast<Handle*>(handle(0)); 293 Handle* my_handle = static_cast<Handle*>(handle(0));
277 int32_t err = WebRtcAecm_GetEchoPath(my_handle, echo_path, size_bytes); 294 int32_t err = WebRtcAecm_GetEchoPath(my_handle, echo_path, size_bytes);
278 if (err != 0) 295 if (err != 0)
279 return MapError(err); 296 return MapError(err);
280 297
281 return apm_->kNoError; 298 return apm_->kNoError;
282 } 299 }
283 300
284 int EchoControlMobileImpl::Initialize() { 301 int EchoControlMobileImpl::Initialize() {
302 // Only called from within APM, hence no locking is needed.
285 if (!is_component_enabled()) { 303 if (!is_component_enabled()) {
286 return apm_->kNoError; 304 return apm_->kNoError;
287 } 305 }
288 306
289 if (apm_->proc_sample_rate_hz() > apm_->kSampleRate16kHz) { 307 if (apm_->proc_sample_rate_hz() > apm_->kSampleRate16kHz) {
290 LOG(LS_ERROR) << "AECM only supports 16 kHz or lower sample rates"; 308 LOG(LS_ERROR) << "AECM only supports 16 kHz or lower sample rates";
291 return apm_->kBadSampleRateError; 309 return apm_->kBadSampleRateError;
292 } 310 }
293 311
294 int err = ProcessingComponent::Initialize(); 312 int err = ProcessingComponent::Initialize();
295 if (err != apm_->kNoError) { 313 if (err != apm_->kNoError) {
296 return err; 314 return err;
297 } 315 }
298 316
299 AllocateRenderQueue(); 317 AllocateRenderQueue();
300 318
301 return apm_->kNoError; 319 return apm_->kNoError;
302 } 320 }
303 321
304 void EchoControlMobileImpl::AllocateRenderQueue() { 322 void EchoControlMobileImpl::AllocateRenderQueue() {
323 // Only called from within APM, hence no locking is needed.
305 const size_t max_frame_size = std::max(kAllowedValuesOfSamplesPerFrame1, 324 const size_t max_frame_size = std::max(kAllowedValuesOfSamplesPerFrame1,
306 kAllowedValuesOfSamplesPerFrame2); 325 kAllowedValuesOfSamplesPerFrame2);
307 const size_t new_render_queue_element_max_size = 326 const size_t new_render_queue_element_max_size =
308 std::max(1UL, max_frame_size * num_handles_required()); 327 std::max(1UL, max_frame_size * num_handles_required());
309 328
310 // Reallocate the queue if the queue item size is too small to fit the 329 // Reallocate the queue if the queue item size is too small to fit the
311 // data to put in the queue. 330 // data to put in the queue.
312 if (new_render_queue_element_max_size > render_queue_element_max_size_) { 331 if (new_render_queue_element_max_size > render_queue_element_max_size_) {
313 render_queue_element_max_size_ = new_render_queue_element_max_size; 332 render_queue_element_max_size_ = new_render_queue_element_max_size;
314 333
315 std::vector<int16_t> template_queue_element(render_queue_element_max_size_); 334 std::vector<int16_t> template_queue_element(render_queue_element_max_size_);
316 335
317 render_signal_queue_.reset( 336 render_signal_queue_.reset(
318 new SwapQueue<std::vector<int16_t>, AecmRenderQueueItemVerifier>( 337 new SwapQueue<std::vector<int16_t>, AecmRenderQueueItemVerifier>(
319 kMaxNumFramesToBuffer, 338 kMaxNumFramesToBuffer,
320 AecmRenderQueueItemVerifier(render_queue_element_max_size_), 339 AecmRenderQueueItemVerifier(render_queue_element_max_size_),
321 template_queue_element)); 340 template_queue_element));
322 } else { 341 } else {
323 render_signal_queue_->Clear(); 342 render_signal_queue_->Clear();
324 } 343 }
325 344
326 render_queue_buffer_.resize(new_render_queue_element_max_size); 345 render_queue_buffer_.resize(new_render_queue_element_max_size);
327 capture_queue_buffer_.resize(new_render_queue_element_max_size); 346 capture_queue_buffer_.resize(new_render_queue_element_max_size);
328 } 347 }
329 348
330 void* EchoControlMobileImpl::CreateHandle() const { 349 void* EchoControlMobileImpl::CreateHandle() const {
350 // Only called from within APM, hence no locking is needed.
331 return WebRtcAecm_Create(); 351 return WebRtcAecm_Create();
332 } 352 }
333 353
334 void EchoControlMobileImpl::DestroyHandle(void* handle) const { 354 void EchoControlMobileImpl::DestroyHandle(void* handle) const {
355 // Only called from within APM, hence no locking is needed.
335 WebRtcAecm_Free(static_cast<Handle*>(handle)); 356 WebRtcAecm_Free(static_cast<Handle*>(handle));
336 } 357 }
337 358
338 int EchoControlMobileImpl::InitializeHandle(void* handle) const { 359 int EchoControlMobileImpl::InitializeHandle(void* handle) const {
360 // Only called from within APM, hence no locking is needed.
339 assert(handle != NULL); 361 assert(handle != NULL);
340 Handle* my_handle = static_cast<Handle*>(handle); 362 Handle* my_handle = static_cast<Handle*>(handle);
341 if (WebRtcAecm_Init(my_handle, apm_->proc_sample_rate_hz()) != 0) { 363 if (WebRtcAecm_Init(my_handle, apm_->proc_sample_rate_hz()) != 0) {
342 return GetHandleError(my_handle); 364 return GetHandleError(my_handle);
343 } 365 }
344 if (external_echo_path_ != NULL) { 366 if (external_echo_path_ != NULL) {
345 if (WebRtcAecm_InitEchoPath(my_handle, 367 if (WebRtcAecm_InitEchoPath(my_handle,
346 external_echo_path_, 368 external_echo_path_,
347 echo_path_size_bytes()) != 0) { 369 echo_path_size_bytes()) != 0) {
348 return GetHandleError(my_handle); 370 return GetHandleError(my_handle);
349 } 371 }
350 } 372 }
351 373
352 return apm_->kNoError; 374 return apm_->kNoError;
353 } 375 }
354 376
355 int EchoControlMobileImpl::ConfigureHandle(void* handle) const { 377 int EchoControlMobileImpl::ConfigureHandle(void* handle) const {
378 // Only called from within APM, hence no locking is needed.
356 AecmConfig config; 379 AecmConfig config;
357 config.cngMode = comfort_noise_enabled_; 380 config.cngMode = comfort_noise_enabled_;
358 config.echoMode = MapSetting(routing_mode_); 381 config.echoMode = MapSetting(routing_mode_);
359 382
360 return WebRtcAecm_set_config(static_cast<Handle*>(handle), config); 383 return WebRtcAecm_set_config(static_cast<Handle*>(handle), config);
361 } 384 }
362 385
363 int EchoControlMobileImpl::num_handles_required() const { 386 int EchoControlMobileImpl::num_handles_required() const {
387 // Only called from within APM, hence no locking is needed.
364 return apm_->num_output_channels() * 388 return apm_->num_output_channels() *
365 apm_->num_reverse_channels(); 389 apm_->num_reverse_channels();
366 } 390 }
367 391
368 int EchoControlMobileImpl::GetHandleError(void* handle) const { 392 int EchoControlMobileImpl::GetHandleError(void* handle) const {
393 // Only called from within APM, hence no locking is needed.
369 assert(handle != NULL); 394 assert(handle != NULL);
370 return AudioProcessing::kUnspecifiedError; 395 return AudioProcessing::kUnspecifiedError;
371 } 396 }
372 397
373 } // namespace webrtc 398 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698