| OLD | NEW |
| 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/modules/audio_processing/aecm/echo_control_mobile.h" | 16 #include "webrtc/modules/audio_processing/aecm/echo_control_mobile.h" |
| 17 #include "webrtc/modules/audio_processing/audio_buffer.h" | 17 #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" | 18 #include "webrtc/system_wrappers/include/logging.h" |
| 20 | 19 |
| 21 namespace webrtc { | 20 namespace webrtc { |
| 22 | 21 |
| 23 typedef void Handle; | 22 typedef void Handle; |
| 24 | 23 |
| 25 namespace { | 24 namespace { |
| 26 int16_t MapSetting(EchoControlMobile::RoutingMode mode) { | 25 int16_t MapSetting(EchoControlMobile::RoutingMode mode) { |
| 27 switch (mode) { | 26 switch (mode) { |
| 28 case EchoControlMobile::kQuietEarpieceOrHeadset: | 27 case EchoControlMobile::kQuietEarpieceOrHeadset: |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 62 // TODO(peah): Decrease this once we properly handle hugely unbalanced | 61 // TODO(peah): Decrease this once we properly handle hugely unbalanced |
| 63 // reverse and forward call numbers. | 62 // reverse and forward call numbers. |
| 64 static const size_t kMaxNumFramesToBuffer = 100; | 63 static const size_t kMaxNumFramesToBuffer = 100; |
| 65 } // namespace | 64 } // namespace |
| 66 | 65 |
| 67 size_t EchoControlMobile::echo_path_size_bytes() { | 66 size_t EchoControlMobile::echo_path_size_bytes() { |
| 68 return WebRtcAecm_echo_path_size_bytes(); | 67 return WebRtcAecm_echo_path_size_bytes(); |
| 69 } | 68 } |
| 70 | 69 |
| 71 EchoControlMobileImpl::EchoControlMobileImpl(const AudioProcessing* apm, | 70 EchoControlMobileImpl::EchoControlMobileImpl(const AudioProcessing* apm, |
| 72 CriticalSectionWrapper* crit) | 71 rtc::CriticalSection* crit_render, |
| 72 rtc::CriticalSection* crit_capture) |
| 73 : ProcessingComponent(), | 73 : ProcessingComponent(), |
| 74 apm_(apm), | 74 apm_(apm), |
| 75 crit_(crit), | 75 crit_render_(crit_render), |
| 76 crit_capture_(crit_capture), |
| 76 routing_mode_(kSpeakerphone), | 77 routing_mode_(kSpeakerphone), |
| 77 comfort_noise_enabled_(true), | 78 comfort_noise_enabled_(true), |
| 78 external_echo_path_(NULL), | 79 external_echo_path_(NULL), |
| 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 EchoControlMobileImpl::~EchoControlMobileImpl() { | 86 EchoControlMobileImpl::~EchoControlMobileImpl() { |
| 82 if (external_echo_path_ != NULL) { | 87 if (external_echo_path_ != NULL) { |
| 83 delete [] external_echo_path_; | 88 delete [] external_echo_path_; |
| 84 external_echo_path_ = NULL; | 89 external_echo_path_ = NULL; |
| 85 } | 90 } |
| 86 } | 91 } |
| 87 | 92 |
| 88 int EchoControlMobileImpl::ProcessRenderAudio(const AudioBuffer* audio) { | 93 int EchoControlMobileImpl::ProcessRenderAudio(const AudioBuffer* audio) { |
| 94 rtc::CritScope cs_render(crit_render_); |
| 95 |
| 89 if (!is_component_enabled()) { | 96 if (!is_component_enabled()) { |
| 90 return apm_->kNoError; | 97 return AudioProcessing::kNoError; |
| 91 } | 98 } |
| 92 | 99 |
| 93 assert(audio->num_frames_per_band() <= 160); | 100 assert(audio->num_frames_per_band() <= 160); |
| 94 assert(audio->num_channels() == apm_->num_reverse_channels()); | 101 assert(audio->num_channels() == apm_->num_reverse_channels()); |
| 95 | 102 |
| 96 int err = apm_->kNoError; | 103 int err = AudioProcessing::kNoError; |
| 97 | |
| 98 // The ordering convention must be followed to pass to the correct AECM. | 104 // The ordering convention must be followed to pass to the correct AECM. |
| 99 size_t handle_index = 0; | 105 size_t handle_index = 0; |
| 100 render_queue_buffer_.clear(); | 106 render_queue_buffer_.clear(); |
| 101 for (int i = 0; i < apm_->num_output_channels(); i++) { | 107 for (int i = 0; i < apm_->num_output_channels(); i++) { |
| 102 for (int j = 0; j < audio->num_channels(); j++) { | 108 for (int j = 0; j < audio->num_channels(); j++) { |
| 103 Handle* my_handle = static_cast<Handle*>(handle(handle_index)); | 109 Handle* my_handle = static_cast<Handle*>(handle(handle_index)); |
| 104 err = WebRtcAecm_GetBufferFarendError( | 110 err = WebRtcAecm_GetBufferFarendError( |
| 105 my_handle, audio->split_bands_const(j)[kBand0To8kHz], | 111 my_handle, audio->split_bands_const(j)[kBand0To8kHz], |
| 106 audio->num_frames_per_band()); | 112 audio->num_frames_per_band()); |
| 107 | 113 |
| 108 if (err != apm_->kNoError) | 114 if (err != AudioProcessing::kNoError) |
| 109 return MapError(err); // TODO(ajm): warning possible?); | 115 return MapError(err); // TODO(ajm): warning possible?); |
| 110 | 116 |
| 111 // Buffer the samples in the render queue. | 117 // Buffer the samples in the render queue. |
| 112 render_queue_buffer_.insert(render_queue_buffer_.end(), | 118 render_queue_buffer_.insert(render_queue_buffer_.end(), |
| 113 audio->split_bands_const(j)[kBand0To8kHz], | 119 audio->split_bands_const(j)[kBand0To8kHz], |
| 114 (audio->split_bands_const(j)[kBand0To8kHz] + | 120 (audio->split_bands_const(j)[kBand0To8kHz] + |
| 115 audio->num_frames_per_band())); | 121 audio->num_frames_per_band())); |
| 116 | 122 |
| 117 handle_index++; | 123 handle_index++; |
| 118 } | 124 } |
| 119 } | 125 } |
| 120 | 126 |
| 121 // Insert the samples into the queue. | 127 // Insert the samples into the queue. |
| 122 if (!render_signal_queue_->Insert(&render_queue_buffer_)) { | 128 if (!render_signal_queue_->Insert(&render_queue_buffer_)) { |
| 129 // The data queue is full and needs to be emptied. |
| 123 ReadQueuedRenderData(); | 130 ReadQueuedRenderData(); |
| 124 | 131 |
| 125 // Retry the insert (should always work). | 132 // Retry the insert (should always work). |
| 126 RTC_DCHECK_EQ(render_signal_queue_->Insert(&render_queue_buffer_), true); | 133 RTC_DCHECK_EQ(render_signal_queue_->Insert(&render_queue_buffer_), true); |
| 127 } | 134 } |
| 128 | 135 |
| 129 return apm_->kNoError; | 136 return AudioProcessing::kNoError; |
| 130 } | 137 } |
| 131 | 138 |
| 132 // Read chunks of data that were received and queued on the render side from | 139 // 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. | 140 // a queue. All the data chunks are buffered into the farend signal of the AEC. |
| 134 void EchoControlMobileImpl::ReadQueuedRenderData() { | 141 void EchoControlMobileImpl::ReadQueuedRenderData() { |
| 142 rtc::CritScope cs_capture(crit_capture_); |
| 143 |
| 135 if (!is_component_enabled()) { | 144 if (!is_component_enabled()) { |
| 136 return; | 145 return; |
| 137 } | 146 } |
| 138 | 147 |
| 139 while (render_signal_queue_->Remove(&capture_queue_buffer_)) { | 148 while (render_signal_queue_->Remove(&capture_queue_buffer_)) { |
| 140 size_t handle_index = 0; | 149 size_t handle_index = 0; |
| 141 int buffer_index = 0; | 150 int buffer_index = 0; |
| 142 const int num_frames_per_band = | 151 const int num_frames_per_band = |
| 143 capture_queue_buffer_.size() / | 152 capture_queue_buffer_.size() / |
| 144 (apm_->num_output_channels() * apm_->num_reverse_channels()); | 153 (apm_->num_output_channels() * apm_->num_reverse_channels()); |
| 145 for (int i = 0; i < apm_->num_output_channels(); i++) { | 154 for (int i = 0; i < apm_->num_output_channels(); i++) { |
| 146 for (int j = 0; j < apm_->num_reverse_channels(); j++) { | 155 for (int j = 0; j < apm_->num_reverse_channels(); j++) { |
| 147 Handle* my_handle = static_cast<Handle*>(handle(handle_index)); | 156 Handle* my_handle = static_cast<Handle*>(handle(handle_index)); |
| 148 WebRtcAecm_BufferFarend(my_handle, &capture_queue_buffer_[buffer_index], | 157 WebRtcAecm_BufferFarend(my_handle, &capture_queue_buffer_[buffer_index], |
| 149 num_frames_per_band); | 158 num_frames_per_band); |
| 150 | 159 |
| 151 buffer_index += num_frames_per_band; | 160 buffer_index += num_frames_per_band; |
| 152 handle_index++; | 161 handle_index++; |
| 153 } | 162 } |
| 154 } | 163 } |
| 155 } | 164 } |
| 156 } | 165 } |
| 157 | 166 |
| 158 int EchoControlMobileImpl::ProcessCaptureAudio(AudioBuffer* audio) { | 167 int EchoControlMobileImpl::ProcessCaptureAudio(AudioBuffer* audio) { |
| 168 rtc::CritScope cs_capture(crit_capture_); |
| 169 |
| 159 if (!is_component_enabled()) { | 170 if (!is_component_enabled()) { |
| 160 return apm_->kNoError; | 171 return AudioProcessing::kNoError; |
| 161 } | 172 } |
| 162 | 173 |
| 163 if (!apm_->was_stream_delay_set()) { | 174 if (!apm_->was_stream_delay_set()) { |
| 164 return apm_->kStreamParameterNotSetError; | 175 return AudioProcessing::kStreamParameterNotSetError; |
| 165 } | 176 } |
| 166 | 177 |
| 167 assert(audio->num_frames_per_band() <= 160); | 178 assert(audio->num_frames_per_band() <= 160); |
| 168 assert(audio->num_channels() == apm_->num_output_channels()); | 179 assert(audio->num_channels() == apm_->num_output_channels()); |
| 169 | 180 |
| 170 int err = apm_->kNoError; | 181 int err = AudioProcessing::kNoError; |
| 171 | 182 |
| 172 // The ordering convention must be followed to pass to the correct AECM. | 183 // The ordering convention must be followed to pass to the correct AECM. |
| 173 size_t handle_index = 0; | 184 size_t handle_index = 0; |
| 174 for (int i = 0; i < audio->num_channels(); i++) { | 185 for (int i = 0; i < audio->num_channels(); i++) { |
| 175 // TODO(ajm): improve how this works, possibly inside AECM. | 186 // TODO(ajm): improve how this works, possibly inside AECM. |
| 176 // This is kind of hacked up. | 187 // This is kind of hacked up. |
| 177 const int16_t* noisy = audio->low_pass_reference(i); | 188 const int16_t* noisy = audio->low_pass_reference(i); |
| 178 const int16_t* clean = audio->split_bands_const(i)[kBand0To8kHz]; | 189 const int16_t* clean = audio->split_bands_const(i)[kBand0To8kHz]; |
| 179 if (noisy == NULL) { | 190 if (noisy == NULL) { |
| 180 noisy = clean; | 191 noisy = clean; |
| 181 clean = NULL; | 192 clean = NULL; |
| 182 } | 193 } |
| 183 for (int j = 0; j < apm_->num_reverse_channels(); j++) { | 194 for (int j = 0; j < apm_->num_reverse_channels(); j++) { |
| 184 Handle* my_handle = static_cast<Handle*>(handle(handle_index)); | 195 Handle* my_handle = static_cast<Handle*>(handle(handle_index)); |
| 185 err = WebRtcAecm_Process( | 196 err = WebRtcAecm_Process( |
| 186 my_handle, | 197 my_handle, |
| 187 noisy, | 198 noisy, |
| 188 clean, | 199 clean, |
| 189 audio->split_bands(i)[kBand0To8kHz], | 200 audio->split_bands(i)[kBand0To8kHz], |
| 190 audio->num_frames_per_band(), | 201 audio->num_frames_per_band(), |
| 191 apm_->stream_delay_ms()); | 202 apm_->stream_delay_ms()); |
| 192 | 203 |
| 193 if (err != apm_->kNoError) | 204 if (err != AudioProcessing::kNoError) |
| 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 AudioProcessing::kNoError; |
| 201 } | 212 } |
| 202 | 213 |
| 203 int EchoControlMobileImpl::Enable(bool enable) { | 214 int EchoControlMobileImpl::Enable(bool enable) { |
| 204 CriticalSectionScoped crit_scoped(crit_); | |
| 205 // Ensure AEC and AECM are not both enabled. | 215 // Ensure AEC and AECM are not both enabled. |
| 216 rtc::CritScope cs_render(crit_render_); |
| 217 rtc::CritScope cs_capture(crit_capture_); |
| 218 // The is_enabled call is safe from a deadlock perspective |
| 219 // as both locks are allready held in the correct order. |
| 206 if (enable && apm_->echo_cancellation()->is_enabled()) { | 220 if (enable && apm_->echo_cancellation()->is_enabled()) { |
| 207 return apm_->kBadParameterError; | 221 return AudioProcessing::kBadParameterError; |
| 208 } | 222 } |
| 209 | 223 |
| 210 return EnableComponent(enable); | 224 return EnableComponent(enable); |
| 211 } | 225 } |
| 212 | 226 |
| 213 bool EchoControlMobileImpl::is_enabled() const { | 227 bool EchoControlMobileImpl::is_enabled() const { |
| 228 rtc::CritScope cs(crit_capture_); |
| 214 return is_component_enabled(); | 229 return is_component_enabled(); |
| 215 } | 230 } |
| 216 | 231 |
| 217 int EchoControlMobileImpl::set_routing_mode(RoutingMode mode) { | 232 int EchoControlMobileImpl::set_routing_mode(RoutingMode mode) { |
| 218 CriticalSectionScoped crit_scoped(crit_); | |
| 219 if (MapSetting(mode) == -1) { | 233 if (MapSetting(mode) == -1) { |
| 220 return apm_->kBadParameterError; | 234 return AudioProcessing::kBadParameterError; |
| 221 } | 235 } |
| 222 | 236 |
| 223 routing_mode_ = mode; | 237 { |
| 238 rtc::CritScope cs(crit_capture_); |
| 239 routing_mode_ = mode; |
| 240 } |
| 224 return Configure(); | 241 return Configure(); |
| 225 } | 242 } |
| 226 | 243 |
| 227 EchoControlMobile::RoutingMode EchoControlMobileImpl::routing_mode() | 244 EchoControlMobile::RoutingMode EchoControlMobileImpl::routing_mode() |
| 228 const { | 245 const { |
| 246 rtc::CritScope cs(crit_capture_); |
| 229 return routing_mode_; | 247 return routing_mode_; |
| 230 } | 248 } |
| 231 | 249 |
| 232 int EchoControlMobileImpl::enable_comfort_noise(bool enable) { | 250 int EchoControlMobileImpl::enable_comfort_noise(bool enable) { |
| 233 CriticalSectionScoped crit_scoped(crit_); | 251 { |
| 234 comfort_noise_enabled_ = enable; | 252 rtc::CritScope cs(crit_capture_); |
| 253 comfort_noise_enabled_ = enable; |
| 254 } |
| 235 return Configure(); | 255 return Configure(); |
| 236 } | 256 } |
| 237 | 257 |
| 238 bool EchoControlMobileImpl::is_comfort_noise_enabled() const { | 258 bool EchoControlMobileImpl::is_comfort_noise_enabled() const { |
| 259 rtc::CritScope cs(crit_capture_); |
| 239 return comfort_noise_enabled_; | 260 return comfort_noise_enabled_; |
| 240 } | 261 } |
| 241 | 262 |
| 242 int EchoControlMobileImpl::SetEchoPath(const void* echo_path, | 263 int EchoControlMobileImpl::SetEchoPath(const void* echo_path, |
| 243 size_t size_bytes) { | 264 size_t size_bytes) { |
| 244 CriticalSectionScoped crit_scoped(crit_); | 265 { |
| 245 if (echo_path == NULL) { | 266 rtc::CritScope cs_render(crit_render_); |
| 246 return apm_->kNullPointerError; | 267 rtc::CritScope cs_capture(crit_capture_); |
| 268 if (echo_path == NULL) { |
| 269 return AudioProcessing::kNullPointerError; |
| 270 } |
| 271 if (size_bytes != echo_path_size_bytes()) { |
| 272 // Size mismatch |
| 273 return AudioProcessing::kBadParameterError; |
| 274 } |
| 275 |
| 276 if (external_echo_path_ == NULL) { |
| 277 external_echo_path_ = new unsigned char[size_bytes]; |
| 278 } |
| 279 memcpy(external_echo_path_, echo_path, size_bytes); |
| 247 } | 280 } |
| 248 if (size_bytes != echo_path_size_bytes()) { | |
| 249 // Size mismatch | |
| 250 return apm_->kBadParameterError; | |
| 251 } | |
| 252 | |
| 253 if (external_echo_path_ == NULL) { | |
| 254 external_echo_path_ = new unsigned char[size_bytes]; | |
| 255 } | |
| 256 memcpy(external_echo_path_, echo_path, size_bytes); | |
| 257 | 281 |
| 258 return Initialize(); | 282 return Initialize(); |
| 259 } | 283 } |
| 260 | 284 |
| 261 int EchoControlMobileImpl::GetEchoPath(void* echo_path, | 285 int EchoControlMobileImpl::GetEchoPath(void* echo_path, |
| 262 size_t size_bytes) const { | 286 size_t size_bytes) const { |
| 263 CriticalSectionScoped crit_scoped(crit_); | 287 rtc::CritScope cs(crit_capture_); |
| 264 if (echo_path == NULL) { | 288 if (echo_path == NULL) { |
| 265 return apm_->kNullPointerError; | 289 return AudioProcessing::kNullPointerError; |
| 266 } | 290 } |
| 267 if (size_bytes != echo_path_size_bytes()) { | 291 if (size_bytes != echo_path_size_bytes()) { |
| 268 // Size mismatch | 292 // Size mismatch |
| 269 return apm_->kBadParameterError; | 293 return AudioProcessing::kBadParameterError; |
| 270 } | 294 } |
| 271 if (!is_component_enabled()) { | 295 if (!is_component_enabled()) { |
| 272 return apm_->kNotEnabledError; | 296 return AudioProcessing::kNotEnabledError; |
| 273 } | 297 } |
| 274 | 298 |
| 275 // Get the echo path from the first channel | 299 // Get the echo path from the first channel |
| 276 Handle* my_handle = static_cast<Handle*>(handle(0)); | 300 Handle* my_handle = static_cast<Handle*>(handle(0)); |
| 277 int32_t err = WebRtcAecm_GetEchoPath(my_handle, echo_path, size_bytes); | 301 int32_t err = WebRtcAecm_GetEchoPath(my_handle, echo_path, size_bytes); |
| 278 if (err != 0) | 302 if (err != 0) |
| 279 return MapError(err); | 303 return MapError(err); |
| 280 | 304 |
| 281 return apm_->kNoError; | 305 return AudioProcessing::kNoError; |
| 282 } | 306 } |
| 283 | 307 |
| 284 int EchoControlMobileImpl::Initialize() { | 308 int EchoControlMobileImpl::Initialize() { |
| 285 if (!is_component_enabled()) { | 309 { |
| 286 return apm_->kNoError; | 310 rtc::CritScope cs_capture(crit_capture_); |
| 311 if (!is_component_enabled()) { |
| 312 return AudioProcessing::kNoError; |
| 313 } |
| 287 } | 314 } |
| 288 | 315 |
| 289 if (apm_->proc_sample_rate_hz() > apm_->kSampleRate16kHz) { | 316 if (apm_->proc_sample_rate_hz() > AudioProcessing::kSampleRate16kHz) { |
| 290 LOG(LS_ERROR) << "AECM only supports 16 kHz or lower sample rates"; | 317 LOG(LS_ERROR) << "AECM only supports 16 kHz or lower sample rates"; |
| 291 return apm_->kBadSampleRateError; | 318 return AudioProcessing::kBadSampleRateError; |
| 292 } | 319 } |
| 293 | 320 |
| 294 int err = ProcessingComponent::Initialize(); | 321 int err = ProcessingComponent::Initialize(); |
| 295 if (err != apm_->kNoError) { | 322 if (err != AudioProcessing::kNoError) { |
| 296 return err; | 323 return err; |
| 297 } | 324 } |
| 298 | 325 |
| 299 AllocateRenderQueue(); | 326 AllocateRenderQueue(); |
| 300 | 327 |
| 301 return apm_->kNoError; | 328 return AudioProcessing::kNoError; |
| 302 } | 329 } |
| 303 | 330 |
| 304 void EchoControlMobileImpl::AllocateRenderQueue() { | 331 void EchoControlMobileImpl::AllocateRenderQueue() { |
| 305 const size_t new_render_queue_element_max_size = std::max<size_t>( | 332 const size_t new_render_queue_element_max_size = std::max<size_t>( |
| 306 static_cast<size_t>(1), | 333 static_cast<size_t>(1), |
| 307 kMaxAllowedValuesOfSamplesPerFrame * num_handles_required()); | 334 kMaxAllowedValuesOfSamplesPerFrame * num_handles_required()); |
| 308 | 335 |
| 336 rtc::CritScope cs_render(crit_render_); |
| 337 rtc::CritScope cs_capture(crit_capture_); |
| 338 |
| 309 // Reallocate the queue if the queue item size is too small to fit the | 339 // Reallocate the queue if the queue item size is too small to fit the |
| 310 // data to put in the queue. | 340 // data to put in the queue. |
| 311 if (render_queue_element_max_size_ < new_render_queue_element_max_size) { | 341 if (render_queue_element_max_size_ < new_render_queue_element_max_size) { |
| 312 render_queue_element_max_size_ = new_render_queue_element_max_size; | 342 render_queue_element_max_size_ = new_render_queue_element_max_size; |
| 313 | 343 |
| 314 std::vector<int16_t> template_queue_element(render_queue_element_max_size_); | 344 std::vector<int16_t> template_queue_element(render_queue_element_max_size_); |
| 315 | 345 |
| 316 render_signal_queue_.reset( | 346 render_signal_queue_.reset( |
| 317 new SwapQueue<std::vector<int16_t>, RenderQueueItemVerifier<int16_t>>( | 347 new SwapQueue<std::vector<int16_t>, RenderQueueItemVerifier<int16_t>>( |
| 318 kMaxNumFramesToBuffer, template_queue_element, | 348 kMaxNumFramesToBuffer, template_queue_element, |
| 319 RenderQueueItemVerifier<int16_t>(render_queue_element_max_size_))); | 349 RenderQueueItemVerifier<int16_t>(render_queue_element_max_size_))); |
| 320 | 350 |
| 321 render_queue_buffer_.resize(render_queue_element_max_size_); | 351 render_queue_buffer_.resize(render_queue_element_max_size_); |
| 322 capture_queue_buffer_.resize(render_queue_element_max_size_); | 352 capture_queue_buffer_.resize(render_queue_element_max_size_); |
| 323 } else { | 353 } else { |
| 324 render_signal_queue_->Clear(); | 354 render_signal_queue_->Clear(); |
| 325 } | 355 } |
| 326 } | 356 } |
| 327 | 357 |
| 328 void* EchoControlMobileImpl::CreateHandle() const { | 358 void* EchoControlMobileImpl::CreateHandle() const { |
| 329 return WebRtcAecm_Create(); | 359 return WebRtcAecm_Create(); |
| 330 } | 360 } |
| 331 | 361 |
| 332 void EchoControlMobileImpl::DestroyHandle(void* handle) const { | 362 void EchoControlMobileImpl::DestroyHandle(void* handle) const { |
| 363 // This method is only called in a non-concurrent manner during APM |
| 364 // destruction. |
| 333 WebRtcAecm_Free(static_cast<Handle*>(handle)); | 365 WebRtcAecm_Free(static_cast<Handle*>(handle)); |
| 334 } | 366 } |
| 335 | 367 |
| 336 int EchoControlMobileImpl::InitializeHandle(void* handle) const { | 368 int EchoControlMobileImpl::InitializeHandle(void* handle) const { |
| 369 rtc::CritScope cs_render(crit_render_); |
| 370 rtc::CritScope cs_capture(crit_capture_); |
| 337 assert(handle != NULL); | 371 assert(handle != NULL); |
| 338 Handle* my_handle = static_cast<Handle*>(handle); | 372 Handle* my_handle = static_cast<Handle*>(handle); |
| 339 if (WebRtcAecm_Init(my_handle, apm_->proc_sample_rate_hz()) != 0) { | 373 if (WebRtcAecm_Init(my_handle, apm_->proc_sample_rate_hz()) != 0) { |
| 340 return GetHandleError(my_handle); | 374 return GetHandleError(my_handle); |
| 341 } | 375 } |
| 342 if (external_echo_path_ != NULL) { | 376 if (external_echo_path_ != NULL) { |
| 343 if (WebRtcAecm_InitEchoPath(my_handle, | 377 if (WebRtcAecm_InitEchoPath(my_handle, |
| 344 external_echo_path_, | 378 external_echo_path_, |
| 345 echo_path_size_bytes()) != 0) { | 379 echo_path_size_bytes()) != 0) { |
| 346 return GetHandleError(my_handle); | 380 return GetHandleError(my_handle); |
| 347 } | 381 } |
| 348 } | 382 } |
| 349 | 383 |
| 350 return apm_->kNoError; | 384 return AudioProcessing::kNoError; |
| 351 } | 385 } |
| 352 | 386 |
| 353 int EchoControlMobileImpl::ConfigureHandle(void* handle) const { | 387 int EchoControlMobileImpl::ConfigureHandle(void* handle) const { |
| 388 rtc::CritScope cs_render(crit_render_); |
| 389 rtc::CritScope cs_capture(crit_capture_); |
| 354 AecmConfig config; | 390 AecmConfig config; |
| 355 config.cngMode = comfort_noise_enabled_; | 391 config.cngMode = comfort_noise_enabled_; |
| 356 config.echoMode = MapSetting(routing_mode_); | 392 config.echoMode = MapSetting(routing_mode_); |
| 357 | 393 |
| 358 return WebRtcAecm_set_config(static_cast<Handle*>(handle), config); | 394 return WebRtcAecm_set_config(static_cast<Handle*>(handle), config); |
| 359 } | 395 } |
| 360 | 396 |
| 361 int EchoControlMobileImpl::num_handles_required() const { | 397 int EchoControlMobileImpl::num_handles_required() const { |
| 398 // Not locked as it only relies on APM public API which is threadsafe. |
| 362 return apm_->num_output_channels() * | 399 return apm_->num_output_channels() * |
| 363 apm_->num_reverse_channels(); | 400 apm_->num_reverse_channels(); |
| 364 } | 401 } |
| 365 | 402 |
| 366 int EchoControlMobileImpl::GetHandleError(void* handle) const { | 403 int EchoControlMobileImpl::GetHandleError(void* handle) const { |
| 404 // Not locked as it does not rely on anything in the state. |
| 367 assert(handle != NULL); | 405 assert(handle != NULL); |
| 368 return AudioProcessing::kUnspecifiedError; | 406 return AudioProcessing::kUnspecifiedError; |
| 369 } | 407 } |
| 370 } // namespace webrtc | 408 } // namespace webrtc |
| OLD | NEW |