Home | History | Annotate | Download | only in voice_engine
      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