1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 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 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "webrtc/voice_engine/voe_base_impl.h" 12 13 #include "webrtc/base/format_macros.h" 14 #include "webrtc/base/logging.h" 15 #include "webrtc/common.h" 16 #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h" 17 #include "webrtc/modules/audio_coding/include/audio_coding_module.h" 18 #include "webrtc/modules/audio_device/audio_device_impl.h" 19 #include "webrtc/modules/audio_processing/include/audio_processing.h" 20 #include "webrtc/system_wrappers/include/critical_section_wrapper.h" 21 #include "webrtc/system_wrappers/include/file_wrapper.h" 22 #include "webrtc/voice_engine/channel.h" 23 #include "webrtc/voice_engine/include/voe_errors.h" 24 #include "webrtc/voice_engine/output_mixer.h" 25 #include "webrtc/voice_engine/transmit_mixer.h" 26 #include "webrtc/voice_engine/utility.h" 27 #include "webrtc/voice_engine/voice_engine_impl.h" 28 29 namespace webrtc { 30 31 VoEBase* VoEBase::GetInterface(VoiceEngine* voiceEngine) { 32 if (nullptr == voiceEngine) { 33 return nullptr; 34 } 35 VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine); 36 s->AddRef(); 37 return s; 38 } 39 40 VoEBaseImpl::VoEBaseImpl(voe::SharedData* shared) 41 : voiceEngineObserverPtr_(nullptr), 42 callbackCritSect_(*CriticalSectionWrapper::CreateCriticalSection()), 43 shared_(shared) {} 44 45 VoEBaseImpl::~VoEBaseImpl() { 46 TerminateInternal(); 47 delete &callbackCritSect_; 48 } 49 50 void VoEBaseImpl::OnErrorIsReported(const ErrorCode error) { 51 CriticalSectionScoped cs(&callbackCritSect_); 52 int errCode = 0; 53 if (error == AudioDeviceObserver::kRecordingError) { 54 errCode = VE_RUNTIME_REC_ERROR; 55 LOG_F(LS_ERROR) << "VE_RUNTIME_REC_ERROR"; 56 } else if (error == AudioDeviceObserver::kPlayoutError) { 57 errCode = VE_RUNTIME_PLAY_ERROR; 58 LOG_F(LS_ERROR) << "VE_RUNTIME_PLAY_ERROR"; 59 } 60 if (voiceEngineObserverPtr_) { 61 // Deliver callback (-1 <=> no channel dependency) 62 voiceEngineObserverPtr_->CallbackOnError(-1, errCode); 63 } 64 } 65 66 void VoEBaseImpl::OnWarningIsReported(const WarningCode warning) { 67 CriticalSectionScoped cs(&callbackCritSect_); 68 int warningCode = 0; 69 if (warning == AudioDeviceObserver::kRecordingWarning) { 70 warningCode = VE_RUNTIME_REC_WARNING; 71 LOG_F(LS_WARNING) << "VE_RUNTIME_REC_WARNING"; 72 } else if (warning == AudioDeviceObserver::kPlayoutWarning) { 73 warningCode = VE_RUNTIME_PLAY_WARNING; 74 LOG_F(LS_WARNING) << "VE_RUNTIME_PLAY_WARNING"; 75 } 76 if (voiceEngineObserverPtr_) { 77 // Deliver callback (-1 <=> no channel dependency) 78 voiceEngineObserverPtr_->CallbackOnError(-1, warningCode); 79 } 80 } 81 82 int32_t VoEBaseImpl::RecordedDataIsAvailable(const void* audioSamples, 83 const size_t nSamples, 84 const size_t nBytesPerSample, 85 const size_t nChannels, 86 const uint32_t samplesPerSec, 87 const uint32_t totalDelayMS, 88 const int32_t clockDrift, 89 const uint32_t currentMicLevel, 90 const bool keyPressed, 91 uint32_t& newMicLevel) { 92 newMicLevel = static_cast<uint32_t>(ProcessRecordedDataWithAPM( 93 nullptr, 0, audioSamples, samplesPerSec, nChannels, nSamples, 94 totalDelayMS, clockDrift, currentMicLevel, keyPressed)); 95 return 0; 96 } 97 98 int32_t VoEBaseImpl::NeedMorePlayData(const size_t nSamples, 99 const size_t nBytesPerSample, 100 const size_t nChannels, 101 const uint32_t samplesPerSec, 102 void* audioSamples, 103 size_t& nSamplesOut, 104 int64_t* elapsed_time_ms, 105 int64_t* ntp_time_ms) { 106 GetPlayoutData(static_cast<int>(samplesPerSec), nChannels, nSamples, true, 107 audioSamples, elapsed_time_ms, ntp_time_ms); 108 nSamplesOut = audioFrame_.samples_per_channel_; 109 return 0; 110 } 111 112 int VoEBaseImpl::OnDataAvailable(const int voe_channels[], 113 size_t number_of_voe_channels, 114 const int16_t* audio_data, int sample_rate, 115 size_t number_of_channels, 116 size_t number_of_frames, 117 int audio_delay_milliseconds, int volume, 118 bool key_pressed, bool need_audio_processing) { 119 if (number_of_voe_channels == 0) return 0; 120 121 if (need_audio_processing) { 122 return ProcessRecordedDataWithAPM( 123 voe_channels, number_of_voe_channels, audio_data, sample_rate, 124 number_of_channels, number_of_frames, audio_delay_milliseconds, 0, 125 volume, key_pressed); 126 } 127 128 // No need to go through the APM, demultiplex the data to each VoE channel, 129 // encode and send to the network. 130 for (size_t i = 0; i < number_of_voe_channels; ++i) { 131 // TODO(ajm): In the case where multiple channels are using the same codec 132 // rate, this path needlessly does extra conversions. We should convert once 133 // and share between channels. 134 PushCaptureData(voe_channels[i], audio_data, 16, sample_rate, 135 number_of_channels, number_of_frames); 136 } 137 138 // Return 0 to indicate no need to change the volume. 139 return 0; 140 } 141 142 void VoEBaseImpl::OnData(int voe_channel, const void* audio_data, 143 int bits_per_sample, int sample_rate, 144 size_t number_of_channels, size_t number_of_frames) { 145 PushCaptureData(voe_channel, audio_data, bits_per_sample, sample_rate, 146 number_of_channels, number_of_frames); 147 } 148 149 void VoEBaseImpl::PushCaptureData(int voe_channel, const void* audio_data, 150 int bits_per_sample, int sample_rate, 151 size_t number_of_channels, 152 size_t number_of_frames) { 153 voe::ChannelOwner ch = shared_->channel_manager().GetChannel(voe_channel); 154 voe::Channel* channel_ptr = ch.channel(); 155 if (!channel_ptr) return; 156 157 if (channel_ptr->Sending()) { 158 channel_ptr->Demultiplex(static_cast<const int16_t*>(audio_data), 159 sample_rate, number_of_frames, number_of_channels); 160 channel_ptr->PrepareEncodeAndSend(sample_rate); 161 channel_ptr->EncodeAndSend(); 162 } 163 } 164 165 void VoEBaseImpl::PullRenderData(int bits_per_sample, 166 int sample_rate, 167 size_t number_of_channels, 168 size_t number_of_frames, 169 void* audio_data, int64_t* elapsed_time_ms, 170 int64_t* ntp_time_ms) { 171 assert(bits_per_sample == 16); 172 assert(number_of_frames == static_cast<size_t>(sample_rate / 100)); 173 174 GetPlayoutData(sample_rate, number_of_channels, number_of_frames, false, 175 audio_data, elapsed_time_ms, ntp_time_ms); 176 } 177 178 int VoEBaseImpl::RegisterVoiceEngineObserver(VoiceEngineObserver& observer) { 179 CriticalSectionScoped cs(&callbackCritSect_); 180 if (voiceEngineObserverPtr_) { 181 shared_->SetLastError( 182 VE_INVALID_OPERATION, kTraceError, 183 "RegisterVoiceEngineObserver() observer already enabled"); 184 return -1; 185 } 186 187 // Register the observer in all active channels 188 for (voe::ChannelManager::Iterator it(&shared_->channel_manager()); 189 it.IsValid(); it.Increment()) { 190 it.GetChannel()->RegisterVoiceEngineObserver(observer); 191 } 192 193 shared_->transmit_mixer()->RegisterVoiceEngineObserver(observer); 194 voiceEngineObserverPtr_ = &observer; 195 return 0; 196 } 197 198 int VoEBaseImpl::DeRegisterVoiceEngineObserver() { 199 CriticalSectionScoped cs(&callbackCritSect_); 200 if (!voiceEngineObserverPtr_) { 201 shared_->SetLastError( 202 VE_INVALID_OPERATION, kTraceError, 203 "DeRegisterVoiceEngineObserver() observer already disabled"); 204 return 0; 205 } 206 voiceEngineObserverPtr_ = nullptr; 207 208 // Deregister the observer in all active channels 209 for (voe::ChannelManager::Iterator it(&shared_->channel_manager()); 210 it.IsValid(); it.Increment()) { 211 it.GetChannel()->DeRegisterVoiceEngineObserver(); 212 } 213 214 return 0; 215 } 216 217 int VoEBaseImpl::Init(AudioDeviceModule* external_adm, 218 AudioProcessing* audioproc) { 219 CriticalSectionScoped cs(shared_->crit_sec()); 220 WebRtcSpl_Init(); 221 if (shared_->statistics().Initialized()) { 222 return 0; 223 } 224 if (shared_->process_thread()) { 225 shared_->process_thread()->Start(); 226 } 227 228 // Create an internal ADM if the user has not added an external 229 // ADM implementation as input to Init(). 230 if (external_adm == nullptr) { 231 #if !defined(WEBRTC_INCLUDE_INTERNAL_AUDIO_DEVICE) 232 return -1; 233 #else 234 // Create the internal ADM implementation. 235 shared_->set_audio_device(AudioDeviceModuleImpl::Create( 236 VoEId(shared_->instance_id(), -1), shared_->audio_device_layer())); 237 238 if (shared_->audio_device() == nullptr) { 239 shared_->SetLastError(VE_NO_MEMORY, kTraceCritical, 240 "Init() failed to create the ADM"); 241 return -1; 242 } 243 #endif // WEBRTC_INCLUDE_INTERNAL_AUDIO_DEVICE 244 } else { 245 // Use the already existing external ADM implementation. 246 shared_->set_audio_device(external_adm); 247 LOG_F(LS_INFO) 248 << "An external ADM implementation will be used in VoiceEngine"; 249 } 250 251 // Register the ADM to the process thread, which will drive the error 252 // callback mechanism 253 if (shared_->process_thread()) { 254 shared_->process_thread()->RegisterModule(shared_->audio_device()); 255 } 256 257 bool available = false; 258 259 // -------------------- 260 // Reinitialize the ADM 261 262 // Register the AudioObserver implementation 263 if (shared_->audio_device()->RegisterEventObserver(this) != 0) { 264 shared_->SetLastError( 265 VE_AUDIO_DEVICE_MODULE_ERROR, kTraceWarning, 266 "Init() failed to register event observer for the ADM"); 267 } 268 269 // Register the AudioTransport implementation 270 if (shared_->audio_device()->RegisterAudioCallback(this) != 0) { 271 shared_->SetLastError( 272 VE_AUDIO_DEVICE_MODULE_ERROR, kTraceWarning, 273 "Init() failed to register audio callback for the ADM"); 274 } 275 276 // ADM initialization 277 if (shared_->audio_device()->Init() != 0) { 278 shared_->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError, 279 "Init() failed to initialize the ADM"); 280 return -1; 281 } 282 283 // Initialize the default speaker 284 if (shared_->audio_device()->SetPlayoutDevice( 285 WEBRTC_VOICE_ENGINE_DEFAULT_DEVICE) != 0) { 286 shared_->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceInfo, 287 "Init() failed to set the default output device"); 288 } 289 if (shared_->audio_device()->InitSpeaker() != 0) { 290 shared_->SetLastError(VE_CANNOT_ACCESS_SPEAKER_VOL, kTraceInfo, 291 "Init() failed to initialize the speaker"); 292 } 293 294 // Initialize the default microphone 295 if (shared_->audio_device()->SetRecordingDevice( 296 WEBRTC_VOICE_ENGINE_DEFAULT_DEVICE) != 0) { 297 shared_->SetLastError(VE_SOUNDCARD_ERROR, kTraceInfo, 298 "Init() failed to set the default input device"); 299 } 300 if (shared_->audio_device()->InitMicrophone() != 0) { 301 shared_->SetLastError(VE_CANNOT_ACCESS_MIC_VOL, kTraceInfo, 302 "Init() failed to initialize the microphone"); 303 } 304 305 // Set number of channels 306 if (shared_->audio_device()->StereoPlayoutIsAvailable(&available) != 0) { 307 shared_->SetLastError(VE_SOUNDCARD_ERROR, kTraceWarning, 308 "Init() failed to query stereo playout mode"); 309 } 310 if (shared_->audio_device()->SetStereoPlayout(available) != 0) { 311 shared_->SetLastError(VE_SOUNDCARD_ERROR, kTraceWarning, 312 "Init() failed to set mono/stereo playout mode"); 313 } 314 315 // TODO(andrew): These functions don't tell us whether stereo recording 316 // is truly available. We simply set the AudioProcessing input to stereo 317 // here, because we have to wait until receiving the first frame to 318 // determine the actual number of channels anyway. 319 // 320 // These functions may be changed; tracked here: 321 // http://code.google.com/p/webrtc/issues/detail?id=204 322 shared_->audio_device()->StereoRecordingIsAvailable(&available); 323 if (shared_->audio_device()->SetStereoRecording(available) != 0) { 324 shared_->SetLastError(VE_SOUNDCARD_ERROR, kTraceWarning, 325 "Init() failed to set mono/stereo recording mode"); 326 } 327 328 if (!audioproc) { 329 audioproc = AudioProcessing::Create(); 330 if (!audioproc) { 331 LOG(LS_ERROR) << "Failed to create AudioProcessing."; 332 shared_->SetLastError(VE_NO_MEMORY); 333 return -1; 334 } 335 } 336 shared_->set_audio_processing(audioproc); 337 338 // Set the error state for any failures in this block. 339 shared_->SetLastError(VE_APM_ERROR); 340 // Configure AudioProcessing components. 341 if (audioproc->high_pass_filter()->Enable(true) != 0) { 342 LOG_F(LS_ERROR) << "Failed to enable high pass filter."; 343 return -1; 344 } 345 if (audioproc->echo_cancellation()->enable_drift_compensation(false) != 0) { 346 LOG_F(LS_ERROR) << "Failed to disable drift compensation."; 347 return -1; 348 } 349 if (audioproc->noise_suppression()->set_level(kDefaultNsMode) != 0) { 350 LOG_F(LS_ERROR) << "Failed to set noise suppression level: " 351 << kDefaultNsMode; 352 return -1; 353 } 354 GainControl* agc = audioproc->gain_control(); 355 if (agc->set_analog_level_limits(kMinVolumeLevel, kMaxVolumeLevel) != 0) { 356 LOG_F(LS_ERROR) << "Failed to set analog level limits with minimum: " 357 << kMinVolumeLevel << " and maximum: " << kMaxVolumeLevel; 358 return -1; 359 } 360 if (agc->set_mode(kDefaultAgcMode) != 0) { 361 LOG_F(LS_ERROR) << "Failed to set mode: " << kDefaultAgcMode; 362 return -1; 363 } 364 if (agc->Enable(kDefaultAgcState) != 0) { 365 LOG_F(LS_ERROR) << "Failed to set agc state: " << kDefaultAgcState; 366 return -1; 367 } 368 shared_->SetLastError(0); // Clear error state. 369 370 #ifdef WEBRTC_VOICE_ENGINE_AGC 371 bool agc_enabled = 372 agc->mode() == GainControl::kAdaptiveAnalog && agc->is_enabled(); 373 if (shared_->audio_device()->SetAGC(agc_enabled) != 0) { 374 LOG_F(LS_ERROR) << "Failed to set agc to enabled: " << agc_enabled; 375 shared_->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR); 376 // TODO(ajm): No error return here due to 377 // https://code.google.com/p/webrtc/issues/detail?id=1464 378 } 379 #endif 380 381 return shared_->statistics().SetInitialized(); 382 } 383 384 int VoEBaseImpl::Terminate() { 385 CriticalSectionScoped cs(shared_->crit_sec()); 386 return TerminateInternal(); 387 } 388 389 int VoEBaseImpl::CreateChannel() { 390 CriticalSectionScoped cs(shared_->crit_sec()); 391 if (!shared_->statistics().Initialized()) { 392 shared_->SetLastError(VE_NOT_INITED, kTraceError); 393 return -1; 394 } 395 396 voe::ChannelOwner channel_owner = shared_->channel_manager().CreateChannel(); 397 return InitializeChannel(&channel_owner); 398 } 399 400 int VoEBaseImpl::CreateChannel(const Config& config) { 401 CriticalSectionScoped cs(shared_->crit_sec()); 402 if (!shared_->statistics().Initialized()) { 403 shared_->SetLastError(VE_NOT_INITED, kTraceError); 404 return -1; 405 } 406 voe::ChannelOwner channel_owner = 407 shared_->channel_manager().CreateChannel(config); 408 return InitializeChannel(&channel_owner); 409 } 410 411 int VoEBaseImpl::InitializeChannel(voe::ChannelOwner* channel_owner) { 412 if (channel_owner->channel()->SetEngineInformation( 413 shared_->statistics(), *shared_->output_mixer(), 414 *shared_->transmit_mixer(), *shared_->process_thread(), 415 *shared_->audio_device(), voiceEngineObserverPtr_, 416 &callbackCritSect_) != 0) { 417 shared_->SetLastError( 418 VE_CHANNEL_NOT_CREATED, kTraceError, 419 "CreateChannel() failed to associate engine and channel." 420 " Destroying channel."); 421 shared_->channel_manager().DestroyChannel( 422 channel_owner->channel()->ChannelId()); 423 return -1; 424 } else if (channel_owner->channel()->Init() != 0) { 425 shared_->SetLastError( 426 VE_CHANNEL_NOT_CREATED, kTraceError, 427 "CreateChannel() failed to initialize channel. Destroying" 428 " channel."); 429 shared_->channel_manager().DestroyChannel( 430 channel_owner->channel()->ChannelId()); 431 return -1; 432 } 433 return channel_owner->channel()->ChannelId(); 434 } 435 436 int VoEBaseImpl::DeleteChannel(int channel) { 437 CriticalSectionScoped cs(shared_->crit_sec()); 438 if (!shared_->statistics().Initialized()) { 439 shared_->SetLastError(VE_NOT_INITED, kTraceError); 440 return -1; 441 } 442 443 { 444 voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel); 445 voe::Channel* channelPtr = ch.channel(); 446 if (channelPtr == nullptr) { 447 shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, 448 "DeleteChannel() failed to locate channel"); 449 return -1; 450 } 451 } 452 453 shared_->channel_manager().DestroyChannel(channel); 454 if (StopSend() != 0) { 455 return -1; 456 } 457 if (StopPlayout() != 0) { 458 return -1; 459 } 460 return 0; 461 } 462 463 int VoEBaseImpl::StartReceive(int channel) { 464 CriticalSectionScoped cs(shared_->crit_sec()); 465 if (!shared_->statistics().Initialized()) { 466 shared_->SetLastError(VE_NOT_INITED, kTraceError); 467 return -1; 468 } 469 voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel); 470 voe::Channel* channelPtr = ch.channel(); 471 if (channelPtr == nullptr) { 472 shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, 473 "StartReceive() failed to locate channel"); 474 return -1; 475 } 476 return channelPtr->StartReceiving(); 477 } 478 479 int VoEBaseImpl::StopReceive(int channel) { 480 CriticalSectionScoped cs(shared_->crit_sec()); 481 if (!shared_->statistics().Initialized()) { 482 shared_->SetLastError(VE_NOT_INITED, kTraceError); 483 return -1; 484 } 485 voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel); 486 voe::Channel* channelPtr = ch.channel(); 487 if (channelPtr == nullptr) { 488 shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, 489 "SetLocalReceiver() failed to locate channel"); 490 return -1; 491 } 492 return channelPtr->StopReceiving(); 493 } 494 495 int VoEBaseImpl::StartPlayout(int channel) { 496 CriticalSectionScoped cs(shared_->crit_sec()); 497 if (!shared_->statistics().Initialized()) { 498 shared_->SetLastError(VE_NOT_INITED, kTraceError); 499 return -1; 500 } 501 voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel); 502 voe::Channel* channelPtr = ch.channel(); 503 if (channelPtr == nullptr) { 504 shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, 505 "StartPlayout() failed to locate channel"); 506 return -1; 507 } 508 if (channelPtr->Playing()) { 509 return 0; 510 } 511 if (StartPlayout() != 0) { 512 shared_->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError, 513 "StartPlayout() failed to start playout"); 514 return -1; 515 } 516 return channelPtr->StartPlayout(); 517 } 518 519 int VoEBaseImpl::StopPlayout(int channel) { 520 CriticalSectionScoped cs(shared_->crit_sec()); 521 if (!shared_->statistics().Initialized()) { 522 shared_->SetLastError(VE_NOT_INITED, kTraceError); 523 return -1; 524 } 525 voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel); 526 voe::Channel* channelPtr = ch.channel(); 527 if (channelPtr == nullptr) { 528 shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, 529 "StopPlayout() failed to locate channel"); 530 return -1; 531 } 532 if (channelPtr->StopPlayout() != 0) { 533 LOG_F(LS_WARNING) << "StopPlayout() failed to stop playout for channel " 534 << channel; 535 } 536 return StopPlayout(); 537 } 538 539 int VoEBaseImpl::StartSend(int channel) { 540 CriticalSectionScoped cs(shared_->crit_sec()); 541 if (!shared_->statistics().Initialized()) { 542 shared_->SetLastError(VE_NOT_INITED, kTraceError); 543 return -1; 544 } 545 voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel); 546 voe::Channel* channelPtr = ch.channel(); 547 if (channelPtr == nullptr) { 548 shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, 549 "StartSend() failed to locate channel"); 550 return -1; 551 } 552 if (channelPtr->Sending()) { 553 return 0; 554 } 555 if (StartSend() != 0) { 556 shared_->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError, 557 "StartSend() failed to start recording"); 558 return -1; 559 } 560 return channelPtr->StartSend(); 561 } 562 563 int VoEBaseImpl::StopSend(int channel) { 564 CriticalSectionScoped cs(shared_->crit_sec()); 565 if (!shared_->statistics().Initialized()) { 566 shared_->SetLastError(VE_NOT_INITED, kTraceError); 567 return -1; 568 } 569 voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel); 570 voe::Channel* channelPtr = ch.channel(); 571 if (channelPtr == nullptr) { 572 shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, 573 "StopSend() failed to locate channel"); 574 return -1; 575 } 576 if (channelPtr->StopSend() != 0) { 577 LOG_F(LS_WARNING) << "StopSend() failed to stop sending for channel " 578 << channel; 579 } 580 return StopSend(); 581 } 582 583 int VoEBaseImpl::GetVersion(char version[1024]) { 584 if (version == nullptr) { 585 shared_->SetLastError(VE_INVALID_ARGUMENT, kTraceError); 586 return -1; 587 } 588 589 std::string versionString = VoiceEngine::GetVersionString(); 590 RTC_DCHECK_GT(1024u, versionString.size() + 1); 591 char* end = std::copy(versionString.cbegin(), versionString.cend(), version); 592 end[0] = '\n'; 593 end[1] = '\0'; 594 return 0; 595 } 596 597 int VoEBaseImpl::LastError() { return (shared_->statistics().LastError()); } 598 599 int32_t VoEBaseImpl::StartPlayout() { 600 if (!shared_->audio_device()->Playing()) { 601 if (shared_->audio_device()->InitPlayout() != 0) { 602 LOG_F(LS_ERROR) << "Failed to initialize playout"; 603 return -1; 604 } 605 if (shared_->audio_device()->StartPlayout() != 0) { 606 LOG_F(LS_ERROR) << "Failed to start playout"; 607 return -1; 608 } 609 } 610 return 0; 611 } 612 613 int32_t VoEBaseImpl::StopPlayout() { 614 // Stop audio-device playing if no channel is playing out 615 if (shared_->NumOfPlayingChannels() == 0) { 616 if (shared_->audio_device()->StopPlayout() != 0) { 617 shared_->SetLastError(VE_CANNOT_STOP_PLAYOUT, kTraceError, 618 "StopPlayout() failed to stop playout"); 619 return -1; 620 } 621 } 622 return 0; 623 } 624 625 int32_t VoEBaseImpl::StartSend() { 626 if (!shared_->audio_device()->Recording()) { 627 if (shared_->audio_device()->InitRecording() != 0) { 628 LOG_F(LS_ERROR) << "Failed to initialize recording"; 629 return -1; 630 } 631 if (shared_->audio_device()->StartRecording() != 0) { 632 LOG_F(LS_ERROR) << "Failed to start recording"; 633 return -1; 634 } 635 } 636 return 0; 637 } 638 639 int32_t VoEBaseImpl::StopSend() { 640 if (shared_->NumOfSendingChannels() == 0 && 641 !shared_->transmit_mixer()->IsRecordingMic()) { 642 // Stop audio-device recording if no channel is recording 643 if (shared_->audio_device()->StopRecording() != 0) { 644 shared_->SetLastError(VE_CANNOT_STOP_RECORDING, kTraceError, 645 "StopSend() failed to stop recording"); 646 return -1; 647 } 648 shared_->transmit_mixer()->StopSend(); 649 } 650 651 return 0; 652 } 653 654 int32_t VoEBaseImpl::TerminateInternal() { 655 // Delete any remaining channel objects 656 shared_->channel_manager().DestroyAllChannels(); 657 658 if (shared_->process_thread()) { 659 if (shared_->audio_device()) { 660 shared_->process_thread()->DeRegisterModule(shared_->audio_device()); 661 } 662 shared_->process_thread()->Stop(); 663 } 664 665 if (shared_->audio_device()) { 666 if (shared_->audio_device()->StopPlayout() != 0) { 667 shared_->SetLastError(VE_SOUNDCARD_ERROR, kTraceWarning, 668 "TerminateInternal() failed to stop playout"); 669 } 670 if (shared_->audio_device()->StopRecording() != 0) { 671 shared_->SetLastError(VE_SOUNDCARD_ERROR, kTraceWarning, 672 "TerminateInternal() failed to stop recording"); 673 } 674 if (shared_->audio_device()->RegisterEventObserver(nullptr) != 0) { 675 shared_->SetLastError( 676 VE_AUDIO_DEVICE_MODULE_ERROR, kTraceWarning, 677 "TerminateInternal() failed to de-register event observer " 678 "for the ADM"); 679 } 680 if (shared_->audio_device()->RegisterAudioCallback(nullptr) != 0) { 681 shared_->SetLastError( 682 VE_AUDIO_DEVICE_MODULE_ERROR, kTraceWarning, 683 "TerminateInternal() failed to de-register audio callback " 684 "for the ADM"); 685 } 686 if (shared_->audio_device()->Terminate() != 0) { 687 shared_->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError, 688 "TerminateInternal() failed to terminate the ADM"); 689 } 690 shared_->set_audio_device(nullptr); 691 } 692 693 if (shared_->audio_processing()) { 694 shared_->set_audio_processing(nullptr); 695 } 696 697 return shared_->statistics().SetUnInitialized(); 698 } 699 700 int VoEBaseImpl::ProcessRecordedDataWithAPM( 701 const int voe_channels[], size_t number_of_voe_channels, 702 const void* audio_data, uint32_t sample_rate, size_t number_of_channels, 703 size_t number_of_frames, uint32_t audio_delay_milliseconds, 704 int32_t clock_drift, uint32_t volume, bool key_pressed) { 705 assert(shared_->transmit_mixer() != nullptr); 706 assert(shared_->audio_device() != nullptr); 707 708 uint32_t max_volume = 0; 709 uint16_t voe_mic_level = 0; 710 // Check for zero to skip this calculation; the consumer may use this to 711 // indicate no volume is available. 712 if (volume != 0) { 713 // Scale from ADM to VoE level range 714 if (shared_->audio_device()->MaxMicrophoneVolume(&max_volume) == 0) { 715 if (max_volume) { 716 voe_mic_level = static_cast<uint16_t>( 717 (volume * kMaxVolumeLevel + static_cast<int>(max_volume / 2)) / 718 max_volume); 719 } 720 } 721 // We learned that on certain systems (e.g Linux) the voe_mic_level 722 // can be greater than the maxVolumeLevel therefore 723 // we are going to cap the voe_mic_level to the maxVolumeLevel 724 // and change the maxVolume to volume if it turns out that 725 // the voe_mic_level is indeed greater than the maxVolumeLevel. 726 if (voe_mic_level > kMaxVolumeLevel) { 727 voe_mic_level = kMaxVolumeLevel; 728 max_volume = volume; 729 } 730 } 731 732 // Perform channel-independent operations 733 // (APM, mix with file, record to file, mute, etc.) 734 shared_->transmit_mixer()->PrepareDemux( 735 audio_data, number_of_frames, number_of_channels, sample_rate, 736 static_cast<uint16_t>(audio_delay_milliseconds), clock_drift, 737 voe_mic_level, key_pressed); 738 739 // Copy the audio frame to each sending channel and perform 740 // channel-dependent operations (file mixing, mute, etc.), encode and 741 // packetize+transmit the RTP packet. When |number_of_voe_channels| == 0, 742 // do the operations on all the existing VoE channels; otherwise the 743 // operations will be done on specific channels. 744 if (number_of_voe_channels == 0) { 745 shared_->transmit_mixer()->DemuxAndMix(); 746 shared_->transmit_mixer()->EncodeAndSend(); 747 } else { 748 shared_->transmit_mixer()->DemuxAndMix(voe_channels, 749 number_of_voe_channels); 750 shared_->transmit_mixer()->EncodeAndSend(voe_channels, 751 number_of_voe_channels); 752 } 753 754 // Scale from VoE to ADM level range. 755 uint32_t new_voe_mic_level = shared_->transmit_mixer()->CaptureLevel(); 756 if (new_voe_mic_level != voe_mic_level) { 757 // Return the new volume if AGC has changed the volume. 758 return static_cast<int>((new_voe_mic_level * max_volume + 759 static_cast<int>(kMaxVolumeLevel / 2)) / 760 kMaxVolumeLevel); 761 } 762 763 // Return 0 to indicate no change on the volume. 764 return 0; 765 } 766 767 void VoEBaseImpl::GetPlayoutData(int sample_rate, size_t number_of_channels, 768 size_t number_of_frames, bool feed_data_to_apm, 769 void* audio_data, int64_t* elapsed_time_ms, 770 int64_t* ntp_time_ms) { 771 assert(shared_->output_mixer() != nullptr); 772 773 // TODO(andrew): if the device is running in mono, we should tell the mixer 774 // here so that it will only request mono from AudioCodingModule. 775 // Perform mixing of all active participants (channel-based mixing) 776 shared_->output_mixer()->MixActiveChannels(); 777 778 // Additional operations on the combined signal 779 shared_->output_mixer()->DoOperationsOnCombinedSignal(feed_data_to_apm); 780 781 // Retrieve the final output mix (resampled to match the ADM) 782 shared_->output_mixer()->GetMixedAudio(sample_rate, number_of_channels, 783 &audioFrame_); 784 785 assert(number_of_frames == audioFrame_.samples_per_channel_); 786 assert(sample_rate == audioFrame_.sample_rate_hz_); 787 788 // Deliver audio (PCM) samples to the ADM 789 memcpy(audio_data, audioFrame_.data_, 790 sizeof(int16_t) * number_of_frames * number_of_channels); 791 792 *elapsed_time_ms = audioFrame_.elapsed_time_ms_; 793 *ntp_time_ms = audioFrame_.ntp_time_ms_; 794 } 795 796 int VoEBaseImpl::AssociateSendChannel(int channel, 797 int accociate_send_channel) { 798 CriticalSectionScoped cs(shared_->crit_sec()); 799 800 if (!shared_->statistics().Initialized()) { 801 shared_->SetLastError(VE_NOT_INITED, kTraceError); 802 return -1; 803 } 804 805 voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel); 806 voe::Channel* channel_ptr = ch.channel(); 807 if (channel_ptr == NULL) { 808 shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, 809 "AssociateSendChannel() failed to locate channel"); 810 return -1; 811 } 812 813 ch = shared_->channel_manager().GetChannel(accociate_send_channel); 814 voe::Channel* accociate_send_channel_ptr = ch.channel(); 815 if (accociate_send_channel_ptr == NULL) { 816 shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, 817 "AssociateSendChannel() failed to locate accociate_send_channel"); 818 return -1; 819 } 820 821 channel_ptr->set_associate_send_channel(ch); 822 return 0; 823 } 824 825 } // namespace webrtc 826