/*
 *  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_codec_impl.h"

#include "webrtc/modules/audio_coding/include/audio_coding_module.h"
#include "webrtc/rtc_base/format_macros.h"
#include "webrtc/system_wrappers/include/trace.h"
#include "webrtc/voice_engine/channel.h"
#include "webrtc/voice_engine/include/voe_errors.h"
#include "webrtc/voice_engine/voice_engine_impl.h"

namespace webrtc {

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

VoECodecImpl::VoECodecImpl(voe::SharedData* shared) : _shared(shared) {
  WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
               "VoECodecImpl() - ctor");
}

VoECodecImpl::~VoECodecImpl() {
  WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
               "~VoECodecImpl() - dtor");
}

int VoECodecImpl::NumOfCodecs() {
  // Number of supported codecs in the ACM
  uint8_t nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
  return (nSupportedCodecs);
}

int VoECodecImpl::GetCodec(int index, CodecInst& codec) {
  if (AudioCodingModule::Codec(index, &codec) == -1) {
    _shared->SetLastError(VE_INVALID_LISTNR, kTraceError,
                          "GetCodec() invalid index");
    return -1;
  }
  return 0;
}

int VoECodecImpl::SetSendCodec(int channel, const CodecInst& codec) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
               "SetSendCodec(channel=%d, codec)", channel);
  WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
               "codec: plname=%s, pacsize=%d, plfreq=%d, pltype=%d, "
               "channels=%" PRIuS ", rate=%d",
               codec.plname, codec.pacsize, codec.plfreq, codec.pltype,
               codec.channels, codec.rate);
  if (!_shared->statistics().Initialized()) {
    _shared->SetLastError(VE_NOT_INITED, kTraceError);
    return -1;
  }
  // External sanity checks performed outside the ACM
  if ((STR_CASE_CMP(codec.plname, "L16") == 0) && (codec.pacsize >= 960)) {
    _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
                          "SetSendCodec() invalid L16 packet size");
    return -1;
  }
  if (!STR_CASE_CMP(codec.plname, "CN") ||
      !STR_CASE_CMP(codec.plname, "TELEPHONE-EVENT") ||
      !STR_CASE_CMP(codec.plname, "RED")) {
    _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
                          "SetSendCodec() invalid codec name");
    return -1;
  }
  if ((codec.channels != 1) && (codec.channels != 2)) {
    _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
                          "SetSendCodec() invalid number of channels");
    return -1;
  }
  voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
  voe::Channel* channelPtr = ch.channel();
  if (channelPtr == NULL) {
    _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
                          "GetSendCodec() failed to locate channel");
    return -1;
  }
  if (!AudioCodingModule::IsCodecValid(codec)) {
    _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
                          "SetSendCodec() invalid codec");
    return -1;
  }
  if (channelPtr->SetSendCodec(codec) != 0) {
    _shared->SetLastError(VE_CANNOT_SET_SEND_CODEC, kTraceError,
                          "SetSendCodec() failed to set send codec");
    return -1;
  }

  return 0;
}

int VoECodecImpl::GetSendCodec(int channel, CodecInst& codec) {
  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 == NULL) {
    _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
                          "GetSendCodec() failed to locate channel");
    return -1;
  }
  if (channelPtr->GetSendCodec(codec) != 0) {
    _shared->SetLastError(VE_CANNOT_GET_SEND_CODEC, kTraceError,
                          "GetSendCodec() failed to get send codec");
    return -1;
  }
  return 0;
}

int VoECodecImpl::SetBitRate(int channel, int bitrate_bps) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
               "SetBitRate(bitrate_bps=%d)", bitrate_bps);
  if (!_shared->statistics().Initialized()) {
    _shared->SetLastError(VE_NOT_INITED, kTraceError);
    return -1;
  }
  constexpr int64_t kDefaultProbingIntervalMs = 3000;
  _shared->channel_manager().GetChannel(channel).channel()->SetBitRate(
      bitrate_bps, kDefaultProbingIntervalMs);
  return 0;
}

int VoECodecImpl::GetRecCodec(int channel, CodecInst& codec) {
  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 == NULL) {
    _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
                          "GetRecCodec() failed to locate channel");
    return -1;
  }
  return channelPtr->GetRecCodec(codec);
}

int VoECodecImpl::SetRecPayloadType(int channel, const CodecInst& codec) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
               "SetRecPayloadType(channel=%d, codec)", channel);
  WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
               "codec: plname=%s, plfreq=%d, pltype=%d, channels=%" PRIuS ", "
               "pacsize=%d, rate=%d",
               codec.plname, codec.plfreq, codec.pltype, codec.channels,
               codec.pacsize, codec.rate);
  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 == NULL) {
    _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
                          "GetRecPayloadType() failed to locate channel");
    return -1;
  }
  return channelPtr->SetRecPayloadType(codec);
}

int VoECodecImpl::GetRecPayloadType(int channel, CodecInst& codec) {
  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 == NULL) {
    _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
                          "GetRecPayloadType() failed to locate channel");
    return -1;
  }
  return channelPtr->GetRecPayloadType(codec);
}

int VoECodecImpl::SetSendCNPayloadType(int channel,
                                       int type,
                                       PayloadFrequencies frequency) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
               "SetSendCNPayloadType(channel=%d, type=%d, frequency=%d)",
               channel, type, frequency);
  if (!_shared->statistics().Initialized()) {
    _shared->SetLastError(VE_NOT_INITED, kTraceError);
    return -1;
  }
  if (type < 96 || type > 127) {
    // Only allow dynamic range: 96 to 127
    _shared->SetLastError(VE_INVALID_PLTYPE, kTraceError,
                          "SetSendCNPayloadType() invalid payload type");
    return -1;
  }
  if ((frequency != kFreq16000Hz) && (frequency != kFreq32000Hz)) {
    // It is not possible to modify the payload type for CN/8000.
    // We only allow modification of the CN payload type for CN/16000
    // and CN/32000.
    _shared->SetLastError(VE_INVALID_PLFREQ, kTraceError,
                          "SetSendCNPayloadType() invalid payload frequency");
    return -1;
  }
  voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
  voe::Channel* channelPtr = ch.channel();
  if (channelPtr == NULL) {
    _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
                          "SetSendCNPayloadType() failed to locate channel");
    return -1;
  }
  return channelPtr->SetSendCNPayloadType(type, frequency);
}

int VoECodecImpl::SetFECStatus(int channel, bool enable) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
               "SetCodecFECStatus(channel=%d, enable=%d)", channel, enable);
  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 == NULL) {
    _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
                          "SetCodecFECStatus() failed to locate channel");
    return -1;
  }
  return channelPtr->SetCodecFECStatus(enable);
}

int VoECodecImpl::GetFECStatus(int channel, bool& enabled) {
  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 == NULL) {
    _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
                          "GetFECStatus() failed to locate channel");
    return -1;
  }
  enabled = channelPtr->GetCodecFECStatus();
  return 0;
}

int VoECodecImpl::SetVADStatus(int channel,
                               bool enable,
                               VadModes mode,
                               bool disableDTX) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
               "SetVADStatus(channel=%i, enable=%i, mode=%i, disableDTX=%i)",
               channel, enable, mode, disableDTX);

  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 == NULL) {
    _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
                          "SetVADStatus failed to locate channel");
    return -1;
  }

  ACMVADMode vadMode(VADNormal);
  switch (mode) {
    case kVadConventional:
      vadMode = VADNormal;
      break;
    case kVadAggressiveLow:
      vadMode = VADLowBitrate;
      break;
    case kVadAggressiveMid:
      vadMode = VADAggr;
      break;
    case kVadAggressiveHigh:
      vadMode = VADVeryAggr;
      break;
  }
  return channelPtr->SetVADStatus(enable, vadMode, disableDTX);
}

int VoECodecImpl::GetVADStatus(int channel,
                               bool& enabled,
                               VadModes& mode,
                               bool& disabledDTX) {
  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 == NULL) {
    _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
                          "GetVADStatus failed to locate channel");
    return -1;
  }

  ACMVADMode vadMode;
  int ret = channelPtr->GetVADStatus(enabled, vadMode, disabledDTX);

  if (ret != 0) {
    _shared->SetLastError(VE_INVALID_OPERATION, kTraceError,
                          "GetVADStatus failed to get VAD mode");
    return -1;
  }
  switch (vadMode) {
    case VADNormal:
      mode = kVadConventional;
      break;
    case VADLowBitrate:
      mode = kVadAggressiveLow;
      break;
    case VADAggr:
      mode = kVadAggressiveMid;
      break;
    case VADVeryAggr:
      mode = kVadAggressiveHigh;
      break;
  }

  return 0;
}

int VoECodecImpl::SetOpusMaxPlaybackRate(int channel, int frequency_hz) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
               "SetOpusMaxPlaybackRate(channel=%d, frequency_hz=%d)", channel,
               frequency_hz);
  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 == NULL) {
    _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
                          "SetOpusMaxPlaybackRate failed to locate channel");
    return -1;
  }
  return channelPtr->SetOpusMaxPlaybackRate(frequency_hz);
}

int VoECodecImpl::SetOpusDtx(int channel, bool enable_dtx) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
               "SetOpusDtx(channel=%d, enable_dtx=%d)", channel, enable_dtx);
  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 == NULL) {
    _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
                          "SetOpusDtx failed to locate channel");
    return -1;
  }
  return channelPtr->SetOpusDtx(enable_dtx);
}

int VoECodecImpl::GetOpusDtxStatus(int channel, bool* enabled) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
               "GetOpusDtx(channel=%d)", channel);
  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 == NULL) {
    _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
                          "GetOpusDtx failed to locate channel");
    return -1;
  }
  return channelPtr->GetOpusDtx(enabled);
}

}  // namespace webrtc
