Chromium Code Reviews

Side by Side Diff: webrtc/modules/audio_processing/echo_control_mobile_impl.cc

Issue 1772453002: Removing dependency of the EchoControlMobileImpl class on ProcessingComponent. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Fixed a couple of implementation errors Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
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
(...skipping 46 matching lines...)
57 } 57 }
58 // Maximum length that a frame of samples can have. 58 // Maximum length that a frame of samples can have.
59 static const size_t kMaxAllowedValuesOfSamplesPerFrame = 160; 59 static const size_t kMaxAllowedValuesOfSamplesPerFrame = 160;
60 // Maximum number of frames to buffer in the render queue. 60 // Maximum number of frames to buffer in the render queue.
61 // TODO(peah): Decrease this once we properly handle hugely unbalanced 61 // TODO(peah): Decrease this once we properly handle hugely unbalanced
62 // reverse and forward call numbers. 62 // reverse and forward call numbers.
63 static const size_t kMaxNumFramesToBuffer = 100; 63 static const size_t kMaxNumFramesToBuffer = 100;
64 } // namespace 64 } // namespace
65 65
66 size_t EchoControlMobile::echo_path_size_bytes() { 66 size_t EchoControlMobile::echo_path_size_bytes() {
67 return WebRtcAecm_echo_path_size_bytes(); 67 return WebRtcAecm_echo_path_size_bytes();
68 } 68 }
69 69
70 class EchoControlMobileImpl::Canceller {
71 public:
72 Canceller() {
73 state_ = WebRtcAecm_Create();
74 RTC_DCHECK(state_);
the sun 2016/03/07 14:43:12 RTC_CHECK
peah-webrtc 2016/03/08 07:53:32 Done.
75 }
76
77 ~Canceller() {
78 RTC_CHECK(state_);
the sun 2016/03/07 14:43:12 RTC_DCHECK, or just don't check - as per the ctor
peah-webrtc 2016/03/08 07:53:32 Done.
79 WebRtcAecm_Free(state_);
80 }
81
82 Handle* state() { return state_; }
83
84 void Initialize(int sample_rate_hz,
85 unsigned char* external_echo_path,
86 size_t echo_path_size_bytes) {
87 int error = WebRtcAecm_Init(state_, sample_rate_hz);
88 RTC_DCHECK_EQ(AudioProcessing::kNoError, error);
the sun 2016/03/07 14:43:12 DCHECK or CHECK? Can this ever fail? To we realloc
peah-webrtc 2016/03/08 07:53:32 Afaics, there is only buffer creation inside the W
89 if (external_echo_path != NULL) {
90 error = WebRtcAecm_InitEchoPath(state_, external_echo_path,
91 echo_path_size_bytes);
92 RTC_DCHECK_EQ(AudioProcessing::kNoError, error);
the sun 2016/03/07 14:43:12 Likewise - DCHECK or CHECK?
peah-webrtc 2016/03/08 07:53:32 I'd say DCHECK, since no memory allocation takes p
the sun 2016/03/09 09:23:14 Same as above, runtime or logic? If the arguments
peah-webrtc 2016/03/09 12:34:53 Acknowledged.
93 }
94 }
95
96 private:
97 Handle* state_;
the sun 2016/03/07 14:43:13 RTC_DISALLOW_COPY_AND_ASSIGN(EchoControlMobileImpl
peah-webrtc 2016/03/08 07:53:32 Done.
98 };
99
70 EchoControlMobileImpl::EchoControlMobileImpl(const AudioProcessing* apm, 100 EchoControlMobileImpl::EchoControlMobileImpl(const AudioProcessing* apm,
71 rtc::CriticalSection* crit_render, 101 rtc::CriticalSection* crit_render,
72 rtc::CriticalSection* crit_capture) 102 rtc::CriticalSection* crit_capture)
73 : ProcessingComponent(), 103 : apm_(apm),
74 apm_(apm),
75 crit_render_(crit_render), 104 crit_render_(crit_render),
76 crit_capture_(crit_capture), 105 crit_capture_(crit_capture),
77 routing_mode_(kSpeakerphone), 106 routing_mode_(kSpeakerphone),
78 comfort_noise_enabled_(true), 107 comfort_noise_enabled_(true),
79 external_echo_path_(NULL), 108 external_echo_path_(NULL),
80 render_queue_element_max_size_(0) { 109 render_queue_element_max_size_(0) {
81 RTC_DCHECK(apm); 110 RTC_DCHECK(apm);
82 RTC_DCHECK(crit_render); 111 RTC_DCHECK(crit_render);
83 RTC_DCHECK(crit_capture); 112 RTC_DCHECK(crit_capture);
84 } 113 }
85 114
86 EchoControlMobileImpl::~EchoControlMobileImpl() { 115 EchoControlMobileImpl::~EchoControlMobileImpl() {
87 if (external_echo_path_ != NULL) { 116 if (external_echo_path_ != NULL) {
88 delete [] external_echo_path_; 117 delete [] external_echo_path_;
89 external_echo_path_ = NULL; 118 external_echo_path_ = NULL;
90 } 119 }
91 } 120 }
92 121
93 int EchoControlMobileImpl::ProcessRenderAudio(const AudioBuffer* audio) { 122 int EchoControlMobileImpl::ProcessRenderAudio(const AudioBuffer* audio) {
94 rtc::CritScope cs_render(crit_render_); 123 rtc::CritScope cs_render(crit_render_);
95 124 if (!enabled_) {
96 if (!is_component_enabled()) {
97 return AudioProcessing::kNoError; 125 return AudioProcessing::kNoError;
98 } 126 }
99 127
100 assert(audio->num_frames_per_band() <= 160); 128 RTC_DCHECK_GE(160u, audio->num_frames_per_band());
101 assert(audio->num_channels() == apm_->num_reverse_channels()); 129 RTC_DCHECK_EQ(audio->num_channels(), apm_->num_reverse_channels());
130 RTC_DCHECK_GE(cancellers_.size(),
131 apm_->num_output_channels() * audio->num_channels());
102 132
103 int err = AudioProcessing::kNoError; 133 int err = AudioProcessing::kNoError;
104 // The ordering convention must be followed to pass to the correct AECM. 134 // The ordering convention must be followed to pass to the correct AECM.
105 size_t handle_index = 0; 135 size_t handle_index = 0;
106 render_queue_buffer_.clear(); 136 render_queue_buffer_.clear();
107 for (size_t i = 0; i < apm_->num_output_channels(); i++) { 137 for (size_t i = 0; i < apm_->num_output_channels(); i++) {
108 for (size_t j = 0; j < audio->num_channels(); j++) { 138 for (size_t j = 0; j < audio->num_channels(); j++) {
109 Handle* my_handle = static_cast<Handle*>(handle(handle_index)); 139 Handle* my_handle = cancellers_[handle_index++]->state();
the sun 2016/03/07 14:43:13 fyi: while neat, doing multiple things in the same
peah-webrtc 2016/03/08 07:53:32 True, but I think it is kind of an edge case since
the sun 2016/03/09 09:23:14 Never mind.
peah-webrtc 2016/03/09 12:34:53 Acknowledged.
peah-webrtc 2016/03/09 12:34:53 :-)
110 err = WebRtcAecm_GetBufferFarendError( 140 err = WebRtcAecm_GetBufferFarendError(
111 my_handle, audio->split_bands_const(j)[kBand0To8kHz], 141 my_handle, audio->split_bands_const(j)[kBand0To8kHz],
112 audio->num_frames_per_band()); 142 audio->num_frames_per_band());
113 143
114 if (err != AudioProcessing::kNoError) 144 if (err != AudioProcessing::kNoError)
115 return MapError(err); // TODO(ajm): warning possible?); 145 return MapError(err); // TODO(ajm): warning possible?);
116 146
117 // Buffer the samples in the render queue. 147 // Buffer the samples in the render queue.
118 render_queue_buffer_.insert(render_queue_buffer_.end(), 148 render_queue_buffer_.insert(render_queue_buffer_.end(),
119 audio->split_bands_const(j)[kBand0To8kHz], 149 audio->split_bands_const(j)[kBand0To8kHz],
120 (audio->split_bands_const(j)[kBand0To8kHz] + 150 (audio->split_bands_const(j)[kBand0To8kHz] +
121 audio->num_frames_per_band())); 151 audio->num_frames_per_band()));
122
123 handle_index++;
124 } 152 }
125 } 153 }
126 154
127 // Insert the samples into the queue. 155 // Insert the samples into the queue.
128 if (!render_signal_queue_->Insert(&render_queue_buffer_)) { 156 if (!render_signal_queue_->Insert(&render_queue_buffer_)) {
129 // The data queue is full and needs to be emptied. 157 // The data queue is full and needs to be emptied.
130 ReadQueuedRenderData(); 158 ReadQueuedRenderData();
131 159
132 // Retry the insert (should always work). 160 // Retry the insert (should always work).
133 RTC_DCHECK_EQ(render_signal_queue_->Insert(&render_queue_buffer_), true); 161 RTC_DCHECK_EQ(render_signal_queue_->Insert(&render_queue_buffer_), true);
134 } 162 }
135 163
136 return AudioProcessing::kNoError; 164 return AudioProcessing::kNoError;
137 } 165 }
138 166
139 // Read chunks of data that were received and queued on the render side from 167 // Read chunks of data that were received and queued on the render side from
140 // a queue. All the data chunks are buffered into the farend signal of the AEC. 168 // a queue. All the data chunks are buffered into the farend signal of the AEC.
141 void EchoControlMobileImpl::ReadQueuedRenderData() { 169 void EchoControlMobileImpl::ReadQueuedRenderData() {
142 rtc::CritScope cs_capture(crit_capture_); 170 rtc::CritScope cs_capture(crit_capture_);
143 171
144 if (!is_component_enabled()) { 172 if (!enabled_) {
145 return; 173 return;
146 } 174 }
147 175
148 while (render_signal_queue_->Remove(&capture_queue_buffer_)) { 176 while (render_signal_queue_->Remove(&capture_queue_buffer_)) {
149 size_t handle_index = 0; 177 size_t handle_index = 0;
150 size_t buffer_index = 0; 178 size_t buffer_index = 0;
151 const size_t num_frames_per_band = 179 const size_t num_frames_per_band =
152 capture_queue_buffer_.size() / 180 capture_queue_buffer_.size() /
153 (apm_->num_output_channels() * apm_->num_reverse_channels()); 181 (apm_->num_output_channels() * apm_->num_reverse_channels());
154 for (size_t i = 0; i < apm_->num_output_channels(); i++) { 182 for (size_t i = 0; i < apm_->num_output_channels(); i++) {
155 for (size_t j = 0; j < apm_->num_reverse_channels(); j++) { 183 for (size_t j = 0; j < apm_->num_reverse_channels(); j++) {
156 Handle* my_handle = static_cast<Handle*>(handle(handle_index)); 184 Handle* my_handle = cancellers_[handle_index++]->state();
157 WebRtcAecm_BufferFarend(my_handle, &capture_queue_buffer_[buffer_index], 185 WebRtcAecm_BufferFarend(my_handle, &capture_queue_buffer_[buffer_index],
158 num_frames_per_band); 186 num_frames_per_band);
159 187
160 buffer_index += num_frames_per_band; 188 buffer_index += num_frames_per_band;
161 handle_index++;
162 } 189 }
163 } 190 }
164 } 191 }
165 } 192 }
166 193
167 int EchoControlMobileImpl::ProcessCaptureAudio(AudioBuffer* audio) { 194 int EchoControlMobileImpl::ProcessCaptureAudio(AudioBuffer* audio) {
168 rtc::CritScope cs_capture(crit_capture_); 195 rtc::CritScope cs_capture(crit_capture_);
169 196 if (!enabled_) {
170 if (!is_component_enabled()) {
171 return AudioProcessing::kNoError; 197 return AudioProcessing::kNoError;
172 } 198 }
173 199
174 if (!apm_->was_stream_delay_set()) { 200 if (!apm_->was_stream_delay_set()) {
175 return AudioProcessing::kStreamParameterNotSetError; 201 return AudioProcessing::kStreamParameterNotSetError;
176 } 202 }
177 203
178 assert(audio->num_frames_per_band() <= 160); 204 RTC_DCHECK_GE(160u, audio->num_frames_per_band());
179 assert(audio->num_channels() == apm_->num_output_channels()); 205 RTC_DCHECK_EQ(audio->num_channels(), apm_->num_output_channels());
180 206
181 int err = AudioProcessing::kNoError; 207 int err = AudioProcessing::kNoError;
182 208
183 // The ordering convention must be followed to pass to the correct AECM. 209 // The ordering convention must be followed to pass to the correct AECM.
184 size_t handle_index = 0; 210 size_t handle_index = 0;
185 for (size_t i = 0; i < audio->num_channels(); i++) { 211 for (size_t i = 0; i < audio->num_channels(); i++) {
186 // TODO(ajm): improve how this works, possibly inside AECM. 212 // TODO(ajm): improve how this works, possibly inside AECM.
187 // This is kind of hacked up. 213 // This is kind of hacked up.
188 const int16_t* noisy = audio->low_pass_reference(i); 214 const int16_t* noisy = audio->low_pass_reference(i);
189 const int16_t* clean = audio->split_bands_const(i)[kBand0To8kHz]; 215 const int16_t* clean = audio->split_bands_const(i)[kBand0To8kHz];
190 if (noisy == NULL) { 216 if (noisy == NULL) {
191 noisy = clean; 217 noisy = clean;
192 clean = NULL; 218 clean = NULL;
193 } 219 }
194 for (size_t j = 0; j < apm_->num_reverse_channels(); j++) { 220 for (size_t j = 0; j < apm_->num_reverse_channels(); j++) {
195 Handle* my_handle = static_cast<Handle*>(handle(handle_index)); 221 Handle* my_handle = cancellers_[handle_index++]->state();
196 err = WebRtcAecm_Process( 222 err = WebRtcAecm_Process(
197 my_handle, 223 my_handle,
198 noisy, 224 noisy,
199 clean, 225 clean,
200 audio->split_bands(i)[kBand0To8kHz], 226 audio->split_bands(i)[kBand0To8kHz],
201 audio->num_frames_per_band(), 227 audio->num_frames_per_band(),
202 apm_->stream_delay_ms()); 228 apm_->stream_delay_ms());
203 229
204 if (err != AudioProcessing::kNoError) 230 if (err != AudioProcessing::kNoError)
205 return MapError(err); 231 return MapError(err);
206
207 handle_index++;
208 } 232 }
209 } 233 }
210 234
211 return AudioProcessing::kNoError; 235 return AudioProcessing::kNoError;
212 } 236 }
213 237
214 int EchoControlMobileImpl::Enable(bool enable) { 238 int EchoControlMobileImpl::Enable(bool enable) {
215 // Ensure AEC and AECM are not both enabled. 239 // Ensure AEC and AECM are not both enabled.
216 rtc::CritScope cs_render(crit_render_); 240 rtc::CritScope cs_render(crit_render_);
217 rtc::CritScope cs_capture(crit_capture_); 241 rtc::CritScope cs_capture(crit_capture_);
218 // The is_enabled call is safe from a deadlock perspective 242 // The is_enabled call is safe from a deadlock perspective
219 // as both locks are allready held in the correct order. 243 // as both locks are allready held in the correct order.
220 if (enable && apm_->echo_cancellation()->is_enabled()) { 244 if (enable && apm_->echo_cancellation()->is_enabled()) {
221 return AudioProcessing::kBadParameterError; 245 return AudioProcessing::kBadParameterError;
222 } 246 }
223 247
224 return EnableComponent(enable); 248 if (enable && !enabled_) {
249 enabled_ = enable; // Must be set before Initialize() is called.
250 Initialize();
251 } else {
252 enabled_ = enable;
253 }
254 return AudioProcessing::kNoError;
225 } 255 }
226 256
227 bool EchoControlMobileImpl::is_enabled() const { 257 bool EchoControlMobileImpl::is_enabled() const {
228 rtc::CritScope cs(crit_capture_); 258 rtc::CritScope cs(crit_capture_);
229 return is_component_enabled(); 259 return enabled_;
230 } 260 }
231 261
232 int EchoControlMobileImpl::set_routing_mode(RoutingMode mode) { 262 int EchoControlMobileImpl::set_routing_mode(RoutingMode mode) {
233 if (MapSetting(mode) == -1) { 263 if (MapSetting(mode) == -1) {
234 return AudioProcessing::kBadParameterError; 264 return AudioProcessing::kBadParameterError;
235 } 265 }
236 266
237 { 267 {
238 rtc::CritScope cs(crit_capture_); 268 rtc::CritScope cs(crit_capture_);
239 routing_mode_ = mode; 269 routing_mode_ = mode;
(...skipping 32 matching lines...)
272 // Size mismatch 302 // Size mismatch
273 return AudioProcessing::kBadParameterError; 303 return AudioProcessing::kBadParameterError;
274 } 304 }
275 305
276 if (external_echo_path_ == NULL) { 306 if (external_echo_path_ == NULL) {
277 external_echo_path_ = new unsigned char[size_bytes]; 307 external_echo_path_ = new unsigned char[size_bytes];
278 } 308 }
279 memcpy(external_echo_path_, echo_path, size_bytes); 309 memcpy(external_echo_path_, echo_path, size_bytes);
280 } 310 }
281 311
282 return Initialize(); 312 Initialize();
313 return AudioProcessing::kNoError;
283 } 314 }
284 315
285 int EchoControlMobileImpl::GetEchoPath(void* echo_path, 316 int EchoControlMobileImpl::GetEchoPath(void* echo_path,
286 size_t size_bytes) const { 317 size_t size_bytes) const {
287 rtc::CritScope cs(crit_capture_); 318 rtc::CritScope cs(crit_capture_);
288 if (echo_path == NULL) { 319 if (echo_path == NULL) {
289 return AudioProcessing::kNullPointerError; 320 return AudioProcessing::kNullPointerError;
290 } 321 }
291 if (size_bytes != echo_path_size_bytes()) { 322 if (size_bytes != echo_path_size_bytes()) {
292 // Size mismatch 323 // Size mismatch
293 return AudioProcessing::kBadParameterError; 324 return AudioProcessing::kBadParameterError;
294 } 325 }
295 if (!is_component_enabled()) { 326 if (!enabled_) {
296 return AudioProcessing::kNotEnabledError; 327 return AudioProcessing::kNotEnabledError;
297 } 328 }
298 329
299 // Get the echo path from the first channel 330 // Get the echo path from the first channel
300 Handle* my_handle = static_cast<Handle*>(handle(0)); 331 const int32_t err =
the sun 2016/03/07 14:43:13 I don't think you should const declare this local.
peah-webrtc 2016/03/08 07:53:32 Not really sure what you mean here. Even though no
the sun 2016/03/09 09:23:14 Discussed offline.
peah-webrtc 2016/03/09 12:34:53 Acknowledged.
301 int32_t err = WebRtcAecm_GetEchoPath(my_handle, echo_path, size_bytes); 332 WebRtcAecm_GetEchoPath(cancellers_[0]->state(), echo_path, size_bytes);
302 if (err != 0) 333 if (err != 0) {
303 return MapError(err); 334 return MapError(err);
335 }
304 336
305 return AudioProcessing::kNoError; 337 return AudioProcessing::kNoError;
306 } 338 }
307 339
308 int EchoControlMobileImpl::Initialize() { 340 void EchoControlMobileImpl::Initialize() {
309 { 341 rtc::CritScope cs_render(crit_render_);
310 rtc::CritScope cs_capture(crit_capture_); 342 rtc::CritScope cs_capture(crit_capture_);
311 if (!is_component_enabled()) { 343 if (!enabled_) {
312 return AudioProcessing::kNoError; 344 return;
313 }
314 } 345 }
315 346
316 if (apm_->proc_sample_rate_hz() > AudioProcessing::kSampleRate16kHz) { 347 if (apm_->proc_sample_rate_hz() > AudioProcessing::kSampleRate16kHz) {
317 LOG(LS_ERROR) << "AECM only supports 16 kHz or lower sample rates"; 348 LOG(LS_ERROR) << "AECM only supports 16 kHz or lower sample rates";
318 return AudioProcessing::kBadSampleRateError; 349 RTC_DCHECK_GE(AudioProcessing::kSampleRate16kHz,
the sun 2016/03/07 14:43:13 What is the DCHECK for? You're already logging. Be
peah-webrtc 2016/03/08 07:53:32 You are correct in that the condition is wrong. I'
350 apm_->proc_sample_rate_hz());
319 } 351 }
320 352
321 int err = ProcessingComponent::Initialize(); 353 const int sample_rate_hz = apm_->proc_sample_rate_hz();
322 if (err != AudioProcessing::kNoError) { 354
323 return err; 355 if (num_handles_required() > cancellers_.size()) {
356 const size_t cancellers_old_size = cancellers_.size();
357 cancellers_.resize(num_handles_required());
358
359 for (size_t i = cancellers_old_size; i < cancellers_.size(); ++i) {
360 cancellers_[i].reset(new Canceller());
361 }
324 } 362 }
325 363
364 for (size_t i = 0; i < cancellers_.size(); ++i) {
the sun 2016/03/07 14:43:12 nit: for (auto canceller : cancellers_) { ...
peah-webrtc 2016/03/08 07:53:32 Done.
365 cancellers_[i]->Initialize(sample_rate_hz, external_echo_path_,
366 echo_path_size_bytes());
367 }
368
369 Configure();
370
326 AllocateRenderQueue(); 371 AllocateRenderQueue();
327
328 return AudioProcessing::kNoError;
329 } 372 }
330 373
331 void EchoControlMobileImpl::AllocateRenderQueue() { 374 void EchoControlMobileImpl::AllocateRenderQueue() {
332 const size_t new_render_queue_element_max_size = std::max<size_t>( 375 const size_t new_render_queue_element_max_size = std::max<size_t>(
333 static_cast<size_t>(1), 376 static_cast<size_t>(1),
334 kMaxAllowedValuesOfSamplesPerFrame * num_handles_required()); 377 kMaxAllowedValuesOfSamplesPerFrame * num_handles_required());
335 378
336 rtc::CritScope cs_render(crit_render_); 379 rtc::CritScope cs_render(crit_render_);
337 rtc::CritScope cs_capture(crit_capture_); 380 rtc::CritScope cs_capture(crit_capture_);
338 381
339 // Reallocate the queue if the queue item size is too small to fit the 382 // Reallocate the queue if the queue item size is too small to fit the
340 // data to put in the queue. 383 // data to put in the queue.
341 if (render_queue_element_max_size_ < new_render_queue_element_max_size) { 384 if (render_queue_element_max_size_ < new_render_queue_element_max_size) {
342 render_queue_element_max_size_ = new_render_queue_element_max_size; 385 render_queue_element_max_size_ = new_render_queue_element_max_size;
343 386
344 std::vector<int16_t> template_queue_element(render_queue_element_max_size_); 387 std::vector<int16_t> template_queue_element(render_queue_element_max_size_);
345 388
346 render_signal_queue_.reset( 389 render_signal_queue_.reset(
347 new SwapQueue<std::vector<int16_t>, RenderQueueItemVerifier<int16_t>>( 390 new SwapQueue<std::vector<int16_t>, RenderQueueItemVerifier<int16_t>>(
348 kMaxNumFramesToBuffer, template_queue_element, 391 kMaxNumFramesToBuffer, template_queue_element,
349 RenderQueueItemVerifier<int16_t>(render_queue_element_max_size_))); 392 RenderQueueItemVerifier<int16_t>(render_queue_element_max_size_)));
350 393
351 render_queue_buffer_.resize(render_queue_element_max_size_); 394 render_queue_buffer_.resize(render_queue_element_max_size_);
352 capture_queue_buffer_.resize(render_queue_element_max_size_); 395 capture_queue_buffer_.resize(render_queue_element_max_size_);
353 } else { 396 } else {
354 render_signal_queue_->Clear(); 397 render_signal_queue_->Clear();
355 } 398 }
356 } 399 }
357 400
358 void* EchoControlMobileImpl::CreateHandle() const { 401 int EchoControlMobileImpl::Configure() {
359 return WebRtcAecm_Create();
360 }
361
362 void EchoControlMobileImpl::DestroyHandle(void* handle) const {
363 // This method is only called in a non-concurrent manner during APM
364 // destruction.
365 WebRtcAecm_Free(static_cast<Handle*>(handle));
366 }
367
368 int EchoControlMobileImpl::InitializeHandle(void* handle) const {
369 rtc::CritScope cs_render(crit_render_);
370 rtc::CritScope cs_capture(crit_capture_);
371 assert(handle != NULL);
372 Handle* my_handle = static_cast<Handle*>(handle);
373 if (WebRtcAecm_Init(my_handle, apm_->proc_sample_rate_hz()) != 0) {
374 return GetHandleError(my_handle);
375 }
376 if (external_echo_path_ != NULL) {
377 if (WebRtcAecm_InitEchoPath(my_handle,
378 external_echo_path_,
379 echo_path_size_bytes()) != 0) {
380 return GetHandleError(my_handle);
381 }
382 }
383
384 return AudioProcessing::kNoError;
385 }
386
387 int EchoControlMobileImpl::ConfigureHandle(void* handle) const {
388 rtc::CritScope cs_render(crit_render_); 402 rtc::CritScope cs_render(crit_render_);
389 rtc::CritScope cs_capture(crit_capture_); 403 rtc::CritScope cs_capture(crit_capture_);
390 AecmConfig config; 404 AecmConfig config;
391 config.cngMode = comfort_noise_enabled_; 405 config.cngMode = comfort_noise_enabled_;
392 config.echoMode = MapSetting(routing_mode_); 406 config.echoMode = MapSetting(routing_mode_);
393 407 int error = AudioProcessing::kNoError;
394 return WebRtcAecm_set_config(static_cast<Handle*>(handle), config); 408 for (size_t i = 0; i < cancellers_.size(); i++) {
the sun 2016/03/07 14:43:13 ditto
peah-webrtc 2016/03/08 07:53:32 Done.
409 Handle* my_handle = cancellers_[i]->state();
410 const int handle_error = WebRtcAecm_set_config(my_handle, config);
411 if (handle_error != AudioProcessing::kNoError) {
412 error = AudioProcessing::kNoError;
413 }
414 }
415 return error;
395 } 416 }
396 417
397 size_t EchoControlMobileImpl::num_handles_required() const { 418 size_t EchoControlMobileImpl::num_handles_required() const {
398 // Not locked as it only relies on APM public API which is threadsafe. 419 // Not locked as it only relies on APM public API which is threadsafe.
399 return apm_->num_output_channels() * apm_->num_reverse_channels(); 420 return apm_->num_output_channels() * apm_->num_reverse_channels();
400 } 421 }
401
402 int EchoControlMobileImpl::GetHandleError(void* handle) const {
403 // Not locked as it does not rely on anything in the state.
404 assert(handle != NULL);
405 return AudioProcessing::kUnspecifiedError;
406 }
407 } // namespace webrtc 422 } // namespace webrtc
OLDNEW

Powered by Google App Engine