/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/voice_engine/voe_base_impl.h"

#include "webrtc/base/format_macros.h"
#include "webrtc/base/logging.h"
#include "webrtc/common.h"
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
#include "webrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory.h"
#include "webrtc/modules/audio_coding/include/audio_coding_module.h"
#include "webrtc/modules/audio_device/audio_device_impl.h"
#include "webrtc/modules/audio_processing/include/audio_processing.h"
#include "webrtc/system_wrappers/include/file_wrapper.h"
#include "webrtc/voice_engine/channel.h"
#include "webrtc/voice_engine/include/voe_errors.h"
#include "webrtc/voice_engine/output_mixer.h"
#include "webrtc/voice_engine/transmit_mixer.h"
#include "webrtc/voice_engine/utility.h"
#include "webrtc/voice_engine/voice_engine_impl.h"

namespace webrtc {

VoEBase* VoEBase::GetInterface(VoiceEngine* voiceEngine) {
  if (nullptr == voiceEngine) {
    return nullptr;
  }
  VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
  s->AddRef();
  return s;
}

VoEBaseImpl::VoEBaseImpl(voe::SharedData* shared)
    : voiceEngineObserverPtr_(nullptr),
      shared_(shared) {}

VoEBaseImpl::~VoEBaseImpl() {
  TerminateInternal();
}

void VoEBaseImpl::OnErrorIsReported(const ErrorCode error) {
  rtc::CritScope cs(&callbackCritSect_);
  int errCode = 0;
  if (error == AudioDeviceObserver::kRecordingError) {
    errCode = VE_RUNTIME_REC_ERROR;
    LOG_F(LS_ERROR) << "VE_RUNTIME_REC_ERROR";
  } else if (error == AudioDeviceObserver::kPlayoutError) {
    errCode = VE_RUNTIME_PLAY_ERROR;
    LOG_F(LS_ERROR) << "VE_RUNTIME_PLAY_ERROR";
  }
  if (voiceEngineObserverPtr_) {
    // Deliver callback (-1 <=> no channel dependency)
    voiceEngineObserverPtr_->CallbackOnError(-1, errCode);
  }
}

void VoEBaseImpl::OnWarningIsReported(const WarningCode warning) {
  rtc::CritScope cs(&callbackCritSect_);
  int warningCode = 0;
  if (warning == AudioDeviceObserver::kRecordingWarning) {
    warningCode = VE_RUNTIME_REC_WARNING;
    LOG_F(LS_WARNING) << "VE_RUNTIME_REC_WARNING";
  } else if (warning == AudioDeviceObserver::kPlayoutWarning) {
    warningCode = VE_RUNTIME_PLAY_WARNING;
    LOG_F(LS_WARNING) << "VE_RUNTIME_PLAY_WARNING";
  }
  if (voiceEngineObserverPtr_) {
    // Deliver callback (-1 <=> no channel dependency)
    voiceEngineObserverPtr_->CallbackOnError(-1, warningCode);
  }
}

int32_t VoEBaseImpl::RecordedDataIsAvailable(const void* audioSamples,
                                             const size_t nSamples,
                                             const size_t nBytesPerSample,
                                             const size_t nChannels,
                                             const uint32_t samplesPerSec,
                                             const uint32_t totalDelayMS,
                                             const int32_t clockDrift,
                                             const uint32_t currentMicLevel,
                                             const bool keyPressed,
                                             uint32_t& newMicLevel) {
  newMicLevel = static_cast<uint32_t>(ProcessRecordedDataWithAPM(
      nullptr, 0, audioSamples, samplesPerSec, nChannels, nSamples,
      totalDelayMS, clockDrift, currentMicLevel, keyPressed));
  return 0;
}

int32_t VoEBaseImpl::NeedMorePlayData(const size_t nSamples,
                                      const size_t nBytesPerSample,
                                      const size_t nChannels,
                                      const uint32_t samplesPerSec,
                                      void* audioSamples,
                                      size_t& nSamplesOut,
                                      int64_t* elapsed_time_ms,
                                      int64_t* ntp_time_ms) {
  GetPlayoutData(static_cast<int>(samplesPerSec), nChannels, nSamples, true,
                 audioSamples, elapsed_time_ms, ntp_time_ms);
  nSamplesOut = audioFrame_.samples_per_channel_;
  return 0;
}

int VoEBaseImpl::OnDataAvailable(const int voe_channels[],
                                 size_t number_of_voe_channels,
                                 const int16_t* audio_data, int sample_rate,
                                 size_t number_of_channels,
                                 size_t number_of_frames,
                                 int audio_delay_milliseconds, int volume,
                                 bool key_pressed, bool need_audio_processing) {
  if (number_of_voe_channels == 0) return 0;

  if (need_audio_processing) {
    return ProcessRecordedDataWithAPM(
        voe_channels, number_of_voe_channels, audio_data, sample_rate,
        number_of_channels, number_of_frames, audio_delay_milliseconds, 0,
        volume, key_pressed);
  }

  // No need to go through the APM, demultiplex the data to each VoE channel,
  // encode and send to the network.
  for (size_t i = 0; i < number_of_voe_channels; ++i) {
    // TODO(ajm): In the case where multiple channels are using the same codec
    // rate, this path needlessly does extra conversions. We should convert once
    // and share between channels.
    PushCaptureData(voe_channels[i], audio_data, 16, sample_rate,
                    number_of_channels, number_of_frames);
  }

  // Return 0 to indicate no need to change the volume.
  return 0;
}

void VoEBaseImpl::OnData(int voe_channel, const void* audio_data,
                         int bits_per_sample, int sample_rate,
                         size_t number_of_channels, size_t number_of_frames) {
  PushCaptureData(voe_channel, audio_data, bits_per_sample, sample_rate,
                  number_of_channels, number_of_frames);
}

void VoEBaseImpl::PushCaptureData(int voe_channel, const void* audio_data,
                                  int bits_per_sample, int sample_rate,
                                  size_t number_of_channels,
                                  size_t number_of_frames) {
  voe::ChannelOwner ch = shared_->channel_manager().GetChannel(voe_channel);
  voe::Channel* channel_ptr = ch.channel();
  if (!channel_ptr) return;

  if (channel_ptr->Sending()) {
    channel_ptr->Demultiplex(static_cast<const int16_t*>(audio_data),
                             sample_rate, number_of_frames, number_of_channels);
    channel_ptr->PrepareEncodeAndSend(sample_rate);
    channel_ptr->EncodeAndSend();
  }
}

void VoEBaseImpl::PullRenderData(int bits_per_sample,
                                 int sample_rate,
                                 size_t number_of_channels,
                                 size_t number_of_frames,
                                 void* audio_data, int64_t* elapsed_time_ms,
                                 int64_t* ntp_time_ms) {
  assert(bits_per_sample == 16);
  assert(number_of_frames == static_cast<size_t>(sample_rate / 100));

  GetPlayoutData(sample_rate, number_of_channels, number_of_frames, false,
                 audio_data, elapsed_time_ms, ntp_time_ms);
}

int VoEBaseImpl::RegisterVoiceEngineObserver(VoiceEngineObserver& observer) {
  rtc::CritScope cs(&callbackCritSect_);
  if (voiceEngineObserverPtr_) {
    shared_->SetLastError(
        VE_INVALID_OPERATION, kTraceError,
        "RegisterVoiceEngineObserver() observer already enabled");
    return -1;
  }

  // Register the observer in all active channels
  for (voe::ChannelManager::Iterator it(&shared_->channel_manager());
       it.IsValid(); it.Increment()) {
    it.GetChannel()->RegisterVoiceEngineObserver(observer);
  }

  shared_->transmit_mixer()->RegisterVoiceEngineObserver(observer);
  voiceEngineObserverPtr_ = &observer;
  return 0;
}

int VoEBaseImpl::DeRegisterVoiceEngineObserver() {
  rtc::CritScope cs(&callbackCritSect_);
  if (!voiceEngineObserverPtr_) {
    shared_->SetLastError(
        VE_INVALID_OPERATION, kTraceError,
        "DeRegisterVoiceEngineObserver() observer already disabled");
    return 0;
  }
  voiceEngineObserverPtr_ = nullptr;

  // Deregister the observer in all active channels
  for (voe::ChannelManager::Iterator it(&shared_->channel_manager());
       it.IsValid(); it.Increment()) {
    it.GetChannel()->DeRegisterVoiceEngineObserver();
  }

  return 0;
}

int VoEBaseImpl::Init(
    AudioDeviceModule* external_adm,
    AudioProcessing* audioproc,
    const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory) {
  rtc::CritScope cs(shared_->crit_sec());
  WebRtcSpl_Init();
  if (shared_->statistics().Initialized()) {
    return 0;
  }
  if (shared_->process_thread()) {
    shared_->process_thread()->Start();
  }

  // Create an internal ADM if the user has not added an external
  // ADM implementation as input to Init().
  if (external_adm == nullptr) {
#if !defined(WEBRTC_INCLUDE_INTERNAL_AUDIO_DEVICE)
    return -1;
#else
    // Create the internal ADM implementation.
    shared_->set_audio_device(AudioDeviceModule::Create(
        VoEId(shared_->instance_id(), -1), shared_->audio_device_layer()));

    if (shared_->audio_device() == nullptr) {
      shared_->SetLastError(VE_NO_MEMORY, kTraceCritical,
                            "Init() failed to create the ADM");
      return -1;
    }
#endif  // WEBRTC_INCLUDE_INTERNAL_AUDIO_DEVICE
  } else {
    // Use the already existing external ADM implementation.
    shared_->set_audio_device(external_adm);
    LOG_F(LS_INFO)
        << "An external ADM implementation will be used in VoiceEngine";
  }

  // Register the ADM to the process thread, which will drive the error
  // callback mechanism
  if (shared_->process_thread()) {
    shared_->process_thread()->RegisterModule(shared_->audio_device());
  }

  bool available = false;

  // --------------------
  // Reinitialize the ADM

  // Register the AudioObserver implementation
  if (shared_->audio_device()->RegisterEventObserver(this) != 0) {
    shared_->SetLastError(
        VE_AUDIO_DEVICE_MODULE_ERROR, kTraceWarning,
        "Init() failed to register event observer for the ADM");
  }

  // Register the AudioTransport implementation
  if (shared_->audio_device()->RegisterAudioCallback(this) != 0) {
    shared_->SetLastError(
        VE_AUDIO_DEVICE_MODULE_ERROR, kTraceWarning,
        "Init() failed to register audio callback for the ADM");
  }

  // ADM initialization
  if (shared_->audio_device()->Init() != 0) {
    shared_->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError,
                          "Init() failed to initialize the ADM");
    return -1;
  }

  // Initialize the default speaker
  if (shared_->audio_device()->SetPlayoutDevice(
          WEBRTC_VOICE_ENGINE_DEFAULT_DEVICE) != 0) {
    shared_->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceInfo,
                          "Init() failed to set the default output device");
  }
  if (shared_->audio_device()->InitSpeaker() != 0) {
    shared_->SetLastError(VE_CANNOT_ACCESS_SPEAKER_VOL, kTraceInfo,
                          "Init() failed to initialize the speaker");
  }

  // Initialize the default microphone
  if (shared_->audio_device()->SetRecordingDevice(
          WEBRTC_VOICE_ENGINE_DEFAULT_DEVICE) != 0) {
    shared_->SetLastError(VE_SOUNDCARD_ERROR, kTraceInfo,
                          "Init() failed to set the default input device");
  }
  if (shared_->audio_device()->InitMicrophone() != 0) {
    shared_->SetLastError(VE_CANNOT_ACCESS_MIC_VOL, kTraceInfo,
                          "Init() failed to initialize the microphone");
  }

  // Set number of channels
  if (shared_->audio_device()->StereoPlayoutIsAvailable(&available) != 0) {
    shared_->SetLastError(VE_SOUNDCARD_ERROR, kTraceWarning,
                          "Init() failed to query stereo playout mode");
  }
  if (shared_->audio_device()->SetStereoPlayout(available) != 0) {
    shared_->SetLastError(VE_SOUNDCARD_ERROR, kTraceWarning,
                          "Init() failed to set mono/stereo playout mode");
  }

  // TODO(andrew): These functions don't tell us whether stereo recording
  // is truly available. We simply set the AudioProcessing input to stereo
  // here, because we have to wait until receiving the first frame to
  // determine the actual number of channels anyway.
  //
  // These functions may be changed; tracked here:
  // http://code.google.com/p/webrtc/issues/detail?id=204
  shared_->audio_device()->StereoRecordingIsAvailable(&available);
  if (shared_->audio_device()->SetStereoRecording(available) != 0) {
    shared_->SetLastError(VE_SOUNDCARD_ERROR, kTraceWarning,
                          "Init() failed to set mono/stereo recording mode");
  }

  if (!audioproc) {
    audioproc = AudioProcessing::Create();
    if (!audioproc) {
      LOG(LS_ERROR) << "Failed to create AudioProcessing.";
      shared_->SetLastError(VE_NO_MEMORY);
      return -1;
    }
  }
  shared_->set_audio_processing(audioproc);

  // Set the error state for any failures in this block.
  shared_->SetLastError(VE_APM_ERROR);
  // Configure AudioProcessing components.
  if (audioproc->high_pass_filter()->Enable(true) != 0) {
    LOG_F(LS_ERROR) << "Failed to enable high pass filter.";
    return -1;
  }
  if (audioproc->echo_cancellation()->enable_drift_compensation(false) != 0) {
    LOG_F(LS_ERROR) << "Failed to disable drift compensation.";
    return -1;
  }
  if (audioproc->noise_suppression()->set_level(kDefaultNsMode) != 0) {
    LOG_F(LS_ERROR) << "Failed to set noise suppression level: "
        << kDefaultNsMode;
    return -1;
  }
  GainControl* agc = audioproc->gain_control();
  if (agc->set_analog_level_limits(kMinVolumeLevel, kMaxVolumeLevel) != 0) {
    LOG_F(LS_ERROR) << "Failed to set analog level limits with minimum: "
        << kMinVolumeLevel << " and maximum: " << kMaxVolumeLevel;
    return -1;
  }
  if (agc->set_mode(kDefaultAgcMode) != 0) {
    LOG_F(LS_ERROR) << "Failed to set mode: " << kDefaultAgcMode;
    return -1;
  }
  if (agc->Enable(kDefaultAgcState) != 0) {
    LOG_F(LS_ERROR) << "Failed to set agc state: " << kDefaultAgcState;
    return -1;
  }
  shared_->SetLastError(0);  // Clear error state.

#ifdef WEBRTC_VOICE_ENGINE_AGC
  bool agc_enabled =
      agc->mode() == GainControl::kAdaptiveAnalog && agc->is_enabled();
  if (shared_->audio_device()->SetAGC(agc_enabled) != 0) {
    LOG_F(LS_ERROR) << "Failed to set agc to enabled: " << agc_enabled;
    shared_->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR);
    // TODO(ajm): No error return here due to
    // https://code.google.com/p/webrtc/issues/detail?id=1464
  }
#endif

  if (decoder_factory)
    decoder_factory_ = decoder_factory;
  else
    decoder_factory_ = CreateBuiltinAudioDecoderFactory();

  return shared_->statistics().SetInitialized();
}

int VoEBaseImpl::Terminate() {
  rtc::CritScope cs(shared_->crit_sec());
  return TerminateInternal();
}

int VoEBaseImpl::CreateChannel() {
  rtc::CritScope cs(shared_->crit_sec());
  if (!shared_->statistics().Initialized()) {
    shared_->SetLastError(VE_NOT_INITED, kTraceError);
    return -1;
  }

  voe::ChannelOwner channel_owner =
      shared_->channel_manager().CreateChannel(decoder_factory_);
  return InitializeChannel(&channel_owner);
}

int VoEBaseImpl::CreateChannel(const Config& config) {
  rtc::CritScope cs(shared_->crit_sec());
  if (!shared_->statistics().Initialized()) {
    shared_->SetLastError(VE_NOT_INITED, kTraceError);
    return -1;
  }
  voe::ChannelOwner channel_owner =
      shared_->channel_manager().CreateChannel(config, decoder_factory_);
  return InitializeChannel(&channel_owner);
}

int VoEBaseImpl::InitializeChannel(voe::ChannelOwner* channel_owner) {
  if (channel_owner->channel()->SetEngineInformation(
          shared_->statistics(), *shared_->output_mixer(),
          *shared_->transmit_mixer(), *shared_->process_thread(),
          *shared_->audio_device(), voiceEngineObserverPtr_,
          &callbackCritSect_) != 0) {
    shared_->SetLastError(
        VE_CHANNEL_NOT_CREATED, kTraceError,
        "CreateChannel() failed to associate engine and channel."
        " Destroying channel.");
    shared_->channel_manager().DestroyChannel(
        channel_owner->channel()->ChannelId());
    return -1;
  } else if (channel_owner->channel()->Init() != 0) {
    shared_->SetLastError(
        VE_CHANNEL_NOT_CREATED, kTraceError,
        "CreateChannel() failed to initialize channel. Destroying"
        " channel.");
    shared_->channel_manager().DestroyChannel(
        channel_owner->channel()->ChannelId());
    return -1;
  }
  return channel_owner->channel()->ChannelId();
}

int VoEBaseImpl::DeleteChannel(int channel) {
  rtc::CritScope cs(shared_->crit_sec());
  if (!shared_->statistics().Initialized()) {
    shared_->SetLastError(VE_NOT_INITED, kTraceError);
    return -1;
  }

  {
    voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
    voe::Channel* channelPtr = ch.channel();
    if (channelPtr == nullptr) {
      shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
                            "DeleteChannel() failed to locate channel");
      return -1;
    }
  }

  shared_->channel_manager().DestroyChannel(channel);
  if (StopSend() != 0) {
    return -1;
  }
  if (StopPlayout() != 0) {
    return -1;
  }
  return 0;
}

int VoEBaseImpl::StartReceive(int channel) {
  rtc::CritScope cs(shared_->crit_sec());
  if (!shared_->statistics().Initialized()) {
    shared_->SetLastError(VE_NOT_INITED, kTraceError);
    return -1;
  }
  voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
  voe::Channel* channelPtr = ch.channel();
  if (channelPtr == nullptr) {
    shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
                          "StartReceive() failed to locate channel");
    return -1;
  }
  return channelPtr->StartReceiving();
}

int VoEBaseImpl::StopReceive(int channel) {
  rtc::CritScope cs(shared_->crit_sec());
  if (!shared_->statistics().Initialized()) {
    shared_->SetLastError(VE_NOT_INITED, kTraceError);
    return -1;
  }
  voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
  voe::Channel* channelPtr = ch.channel();
  if (channelPtr == nullptr) {
    shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
                          "SetLocalReceiver() failed to locate channel");
    return -1;
  }
  return channelPtr->StopReceiving();
}

int VoEBaseImpl::StartPlayout(int channel) {
  rtc::CritScope cs(shared_->crit_sec());
  if (!shared_->statistics().Initialized()) {
    shared_->SetLastError(VE_NOT_INITED, kTraceError);
    return -1;
  }
  voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
  voe::Channel* channelPtr = ch.channel();
  if (channelPtr == nullptr) {
    shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
                          "StartPlayout() failed to locate channel");
    return -1;
  }
  if (channelPtr->Playing()) {
    return 0;
  }
  if (StartPlayout() != 0) {
    shared_->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError,
                          "StartPlayout() failed to start playout");
    return -1;
  }
  return channelPtr->StartPlayout();
}

int VoEBaseImpl::StopPlayout(int channel) {
  rtc::CritScope cs(shared_->crit_sec());
  if (!shared_->statistics().Initialized()) {
    shared_->SetLastError(VE_NOT_INITED, kTraceError);
    return -1;
  }
  voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
  voe::Channel* channelPtr = ch.channel();
  if (channelPtr == nullptr) {
    shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
                          "StopPlayout() failed to locate channel");
    return -1;
  }
  if (channelPtr->StopPlayout() != 0) {
    LOG_F(LS_WARNING) << "StopPlayout() failed to stop playout for channel "
                      << channel;
  }
  return StopPlayout();
}

int VoEBaseImpl::StartSend(int channel) {
  rtc::CritScope cs(shared_->crit_sec());
  if (!shared_->statistics().Initialized()) {
    shared_->SetLastError(VE_NOT_INITED, kTraceError);
    return -1;
  }
  voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
  voe::Channel* channelPtr = ch.channel();
  if (channelPtr == nullptr) {
    shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
                          "StartSend() failed to locate channel");
    return -1;
  }
  if (channelPtr->Sending()) {
    return 0;
  }
  if (StartSend() != 0) {
    shared_->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError,
                          "StartSend() failed to start recording");
    return -1;
  }
  return channelPtr->StartSend();
}

int VoEBaseImpl::StopSend(int channel) {
  rtc::CritScope cs(shared_->crit_sec());
  if (!shared_->statistics().Initialized()) {
    shared_->SetLastError(VE_NOT_INITED, kTraceError);
    return -1;
  }
  voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
  voe::Channel* channelPtr = ch.channel();
  if (channelPtr == nullptr) {
    shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
                          "StopSend() failed to locate channel");
    return -1;
  }
  if (channelPtr->StopSend() != 0) {
    LOG_F(LS_WARNING) << "StopSend() failed to stop sending for channel "
                      << channel;
  }
  return StopSend();
}

int VoEBaseImpl::GetVersion(char version[1024]) {
  if (version == nullptr) {
    shared_->SetLastError(VE_INVALID_ARGUMENT, kTraceError);
    return -1;
  }

  std::string versionString = VoiceEngine::GetVersionString();
  RTC_DCHECK_GT(1024u, versionString.size() + 1);
  char* end = std::copy(versionString.cbegin(), versionString.cend(), version);
  end[0] = '\n';
  end[1] = '\0';
  return 0;
}

int VoEBaseImpl::LastError() { return (shared_->statistics().LastError()); }

int32_t VoEBaseImpl::StartPlayout() {
  if (!shared_->audio_device()->Playing()) {
    if (shared_->audio_device()->InitPlayout() != 0) {
      LOG_F(LS_ERROR) << "Failed to initialize playout";
      return -1;
    }
    if (shared_->audio_device()->StartPlayout() != 0) {
      LOG_F(LS_ERROR) << "Failed to start playout";
      return -1;
    }
  }
  return 0;
}

int32_t VoEBaseImpl::StopPlayout() {
  // Stop audio-device playing if no channel is playing out
  if (shared_->NumOfPlayingChannels() == 0) {
    if (shared_->audio_device()->StopPlayout() != 0) {
      shared_->SetLastError(VE_CANNOT_STOP_PLAYOUT, kTraceError,
                            "StopPlayout() failed to stop playout");
      return -1;
    }
  }
  return 0;
}

int32_t VoEBaseImpl::StartSend() {
  if (!shared_->audio_device()->RecordingIsInitialized() &&
      !shared_->audio_device()->Recording()) {
    if (shared_->audio_device()->InitRecording() != 0) {
      LOG_F(LS_ERROR) << "Failed to initialize recording";
      return -1;
    }
  }
  if (!shared_->audio_device()->Recording()) {
    if (shared_->audio_device()->StartRecording() != 0) {
      LOG_F(LS_ERROR) << "Failed to start recording";
      return -1;
    }
  }
  return 0;
}

int32_t VoEBaseImpl::StopSend() {
  if (shared_->NumOfSendingChannels() == 0 &&
      !shared_->transmit_mixer()->IsRecordingMic()) {
    // Stop audio-device recording if no channel is recording
    if (shared_->audio_device()->StopRecording() != 0) {
      shared_->SetLastError(VE_CANNOT_STOP_RECORDING, kTraceError,
                            "StopSend() failed to stop recording");
      return -1;
    }
    shared_->transmit_mixer()->StopSend();
  }

  return 0;
}

int32_t VoEBaseImpl::TerminateInternal() {
  // Delete any remaining channel objects
  shared_->channel_manager().DestroyAllChannels();

  if (shared_->process_thread()) {
    if (shared_->audio_device()) {
      shared_->process_thread()->DeRegisterModule(shared_->audio_device());
    }
    shared_->process_thread()->Stop();
  }

  if (shared_->audio_device()) {
    if (shared_->audio_device()->StopPlayout() != 0) {
      shared_->SetLastError(VE_SOUNDCARD_ERROR, kTraceWarning,
                            "TerminateInternal() failed to stop playout");
    }
    if (shared_->audio_device()->StopRecording() != 0) {
      shared_->SetLastError(VE_SOUNDCARD_ERROR, kTraceWarning,
                            "TerminateInternal() failed to stop recording");
    }
    if (shared_->audio_device()->RegisterEventObserver(nullptr) != 0) {
      shared_->SetLastError(
          VE_AUDIO_DEVICE_MODULE_ERROR, kTraceWarning,
          "TerminateInternal() failed to de-register event observer "
          "for the ADM");
    }
    if (shared_->audio_device()->RegisterAudioCallback(nullptr) != 0) {
      shared_->SetLastError(
          VE_AUDIO_DEVICE_MODULE_ERROR, kTraceWarning,
          "TerminateInternal() failed to de-register audio callback "
          "for the ADM");
    }
    if (shared_->audio_device()->Terminate() != 0) {
      shared_->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError,
                            "TerminateInternal() failed to terminate the ADM");
    }
    shared_->set_audio_device(nullptr);
  }

  if (shared_->audio_processing()) {
    shared_->set_audio_processing(nullptr);
  }

  return shared_->statistics().SetUnInitialized();
}

int VoEBaseImpl::ProcessRecordedDataWithAPM(
    const int voe_channels[], size_t number_of_voe_channels,
    const void* audio_data, uint32_t sample_rate, size_t number_of_channels,
    size_t number_of_frames, uint32_t audio_delay_milliseconds,
    int32_t clock_drift, uint32_t volume, bool key_pressed) {
  assert(shared_->transmit_mixer() != nullptr);
  assert(shared_->audio_device() != nullptr);

  uint32_t max_volume = 0;
  uint16_t voe_mic_level = 0;
  // Check for zero to skip this calculation; the consumer may use this to
  // indicate no volume is available.
  if (volume != 0) {
    // Scale from ADM to VoE level range
    if (shared_->audio_device()->MaxMicrophoneVolume(&max_volume) == 0) {
      if (max_volume) {
        voe_mic_level = static_cast<uint16_t>(
            (volume * kMaxVolumeLevel + static_cast<int>(max_volume / 2)) /
            max_volume);
      }
    }
    // We learned that on certain systems (e.g Linux) the voe_mic_level
    // can be greater than the maxVolumeLevel therefore
    // we are going to cap the voe_mic_level to the maxVolumeLevel
    // and change the maxVolume to volume if it turns out that
    // the voe_mic_level is indeed greater than the maxVolumeLevel.
    if (voe_mic_level > kMaxVolumeLevel) {
      voe_mic_level = kMaxVolumeLevel;
      max_volume = volume;
    }
  }

  // Perform channel-independent operations
  // (APM, mix with file, record to file, mute, etc.)
  shared_->transmit_mixer()->PrepareDemux(
      audio_data, number_of_frames, number_of_channels, sample_rate,
      static_cast<uint16_t>(audio_delay_milliseconds), clock_drift,
      voe_mic_level, key_pressed);

  // Copy the audio frame to each sending channel and perform
  // channel-dependent operations (file mixing, mute, etc.), encode and
  // packetize+transmit the RTP packet. When |number_of_voe_channels| == 0,
  // do the operations on all the existing VoE channels; otherwise the
  // operations will be done on specific channels.
  if (number_of_voe_channels == 0) {
    shared_->transmit_mixer()->DemuxAndMix();
    shared_->transmit_mixer()->EncodeAndSend();
  } else {
    shared_->transmit_mixer()->DemuxAndMix(voe_channels,
                                           number_of_voe_channels);
    shared_->transmit_mixer()->EncodeAndSend(voe_channels,
                                             number_of_voe_channels);
  }

  // Scale from VoE to ADM level range.
  uint32_t new_voe_mic_level = shared_->transmit_mixer()->CaptureLevel();
  if (new_voe_mic_level != voe_mic_level) {
    // Return the new volume if AGC has changed the volume.
    return static_cast<int>((new_voe_mic_level * max_volume +
                             static_cast<int>(kMaxVolumeLevel / 2)) /
                            kMaxVolumeLevel);
  }

  // Return 0 to indicate no change on the volume.
  return 0;
}

void VoEBaseImpl::GetPlayoutData(int sample_rate, size_t number_of_channels,
                                 size_t number_of_frames, bool feed_data_to_apm,
                                 void* audio_data, int64_t* elapsed_time_ms,
                                 int64_t* ntp_time_ms) {
  assert(shared_->output_mixer() != nullptr);

  // TODO(andrew): if the device is running in mono, we should tell the mixer
  // here so that it will only request mono from AudioCodingModule.
  // Perform mixing of all active participants (channel-based mixing)
  shared_->output_mixer()->MixActiveChannels();

  // Additional operations on the combined signal
  shared_->output_mixer()->DoOperationsOnCombinedSignal(feed_data_to_apm);

  // Retrieve the final output mix (resampled to match the ADM)
  shared_->output_mixer()->GetMixedAudio(sample_rate, number_of_channels,
                                         &audioFrame_);

  assert(number_of_frames == audioFrame_.samples_per_channel_);
  assert(sample_rate == audioFrame_.sample_rate_hz_);

  // Deliver audio (PCM) samples to the ADM
  memcpy(audio_data, audioFrame_.data_,
         sizeof(int16_t) * number_of_frames * number_of_channels);

  *elapsed_time_ms = audioFrame_.elapsed_time_ms_;
  *ntp_time_ms = audioFrame_.ntp_time_ms_;
}

int VoEBaseImpl::AssociateSendChannel(int channel,
                                      int accociate_send_channel) {
  rtc::CritScope cs(shared_->crit_sec());

  if (!shared_->statistics().Initialized()) {
      shared_->SetLastError(VE_NOT_INITED, kTraceError);
      return -1;
  }

  voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
  voe::Channel* channel_ptr = ch.channel();
  if (channel_ptr == NULL) {
    shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
        "AssociateSendChannel() failed to locate channel");
    return -1;
  }

  ch = shared_->channel_manager().GetChannel(accociate_send_channel);
  voe::Channel* accociate_send_channel_ptr = ch.channel();
  if (accociate_send_channel_ptr == NULL) {
    shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
        "AssociateSendChannel() failed to locate accociate_send_channel");
    return -1;
  }

  channel_ptr->set_associate_send_channel(ch);
  return 0;
}

}  // namespace webrtc
