/*
 *  Copyright (c) 2015 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/modules/audio_coding/main/acm2/codec_manager.h"

#include "webrtc/base/checks.h"
#include "webrtc/engine_configurations.h"
#include "webrtc/modules/audio_coding/main/acm2/acm_codec_database.h"
#include "webrtc/system_wrappers/interface/trace.h"

namespace webrtc {
namespace acm2 {

namespace {
bool IsCodecRED(const CodecInst& codec) {
  return (STR_CASE_CMP(codec.plname, "RED") == 0);
}

bool IsCodecRED(int index) {
  return (IsCodecRED(ACMCodecDB::database_[index]));
}

bool IsCodecCN(const CodecInst& codec) {
  return (STR_CASE_CMP(codec.plname, "CN") == 0);
}

bool IsCodecCN(int index) {
  return (IsCodecCN(ACMCodecDB::database_[index]));
}

// Check if the given codec is a valid to be registered as send codec.
int IsValidSendCodec(const CodecInst& send_codec, bool is_primary_encoder) {
  int dummy_id = 0;
  if ((send_codec.channels != 1) && (send_codec.channels != 2)) {
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
                 "Wrong number of channels (%d, only mono and stereo are "
                 "supported) for %s encoder",
                 send_codec.channels,
                 is_primary_encoder ? "primary" : "secondary");
    return -1;
  }

  int codec_id = ACMCodecDB::CodecNumber(send_codec);
  if (codec_id < 0) {
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
                 "Invalid codec setting for the send codec.");
    return -1;
  }

  // TODO(tlegrand): Remove this check. Already taken care of in
  // ACMCodecDB::CodecNumber().
  // Check if the payload-type is valid
  if (!ACMCodecDB::ValidPayloadType(send_codec.pltype)) {
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
                 "Invalid payload-type %d for %s.", send_codec.pltype,
                 send_codec.plname);
    return -1;
  }

  // Telephone-event cannot be a send codec.
  if (!STR_CASE_CMP(send_codec.plname, "telephone-event")) {
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
                 "telephone-event cannot be a send codec");
    return -1;
  }

  if (ACMCodecDB::codec_settings_[codec_id].channel_support <
      send_codec.channels) {
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
                 "%d number of channels not supportedn for %s.",
                 send_codec.channels, send_codec.plname);
    return -1;
  }

  if (!is_primary_encoder) {
    // If registering the secondary encoder, then RED and CN are not valid
    // choices as encoder.
    if (IsCodecRED(send_codec)) {
      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
                   "RED cannot be secondary codec");
      return -1;
    }

    if (IsCodecCN(send_codec)) {
      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
                   "DTX cannot be secondary codec");
      return -1;
    }
  }
  return codec_id;
}

bool IsIsac(const CodecInst& codec) {
  return
#if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX))
      !STR_CASE_CMP(codec.plname, "isac") ||
#endif
      false;
}

bool IsOpus(const CodecInst& codec) {
  return
#ifdef WEBRTC_CODEC_OPUS
      !STR_CASE_CMP(codec.plname, "opus") ||
#endif
      false;
}

bool IsPcmU(const CodecInst& codec) {
  return !STR_CASE_CMP(codec.plname, "pcmu");
}

bool IsPcmA(const CodecInst& codec) {
  return !STR_CASE_CMP(codec.plname, "pcma");
}

bool IsPcm16B(const CodecInst& codec) {
  return
#ifdef WEBRTC_CODEC_PCM16
      !STR_CASE_CMP(codec.plname, "l16") ||
#endif
      false;
}

bool IsIlbc(const CodecInst& codec) {
  return
#ifdef WEBRTC_CODEC_ILBC
      !STR_CASE_CMP(codec.plname, "ilbc") ||
#endif
      false;
}

bool IsG722(const CodecInst& codec) {
  return
#ifdef WEBRTC_CODEC_G722
      !STR_CASE_CMP(codec.plname, "g722") ||
#endif
      false;
}

bool CodecSupported(const CodecInst& codec) {
  return IsOpus(codec) || IsPcmU(codec) || IsPcmA(codec) || IsPcm16B(codec) ||
         IsIlbc(codec) || IsG722(codec) || IsIsac(codec);
}

const CodecInst kEmptyCodecInst = {-1, "noCodecRegistered", 0, 0, 0, 0};
}  // namespace

CodecManager::CodecManager()
    : cng_nb_pltype_(255),
      cng_wb_pltype_(255),
      cng_swb_pltype_(255),
      cng_fb_pltype_(255),
      red_nb_pltype_(255),
      stereo_send_(false),
      dtx_enabled_(false),
      vad_mode_(VADNormal),
      send_codec_inst_(kEmptyCodecInst),
      red_enabled_(false),
      codec_fec_enabled_(false),
      encoder_is_opus_(false) {
  // Register the default payload type for RED and for CNG at sampling rates of
  // 8, 16, 32 and 48 kHz.
  for (int i = (ACMCodecDB::kNumCodecs - 1); i >= 0; i--) {
    if (IsCodecRED(i) && ACMCodecDB::database_[i].plfreq == 8000) {
      red_nb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
    } else if (IsCodecCN(i)) {
      if (ACMCodecDB::database_[i].plfreq == 8000) {
        cng_nb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
      } else if (ACMCodecDB::database_[i].plfreq == 16000) {
        cng_wb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
      } else if (ACMCodecDB::database_[i].plfreq == 32000) {
        cng_swb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
      } else if (ACMCodecDB::database_[i].plfreq == 48000) {
        cng_fb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
      }
    }
  }
  thread_checker_.DetachFromThread();
}

CodecManager::~CodecManager() = default;

int CodecManager::RegisterEncoder(const CodecInst& send_codec) {
  DCHECK(thread_checker_.CalledOnValidThread());
  int codec_id = IsValidSendCodec(send_codec, true);

  // Check for reported errors from function IsValidSendCodec().
  if (codec_id < 0) {
    return -1;
  }

  int dummy_id = 0;
  // RED can be registered with other payload type. If not registered a default
  // payload type is used.
  if (IsCodecRED(send_codec)) {
    // TODO(tlegrand): Remove this check. Already taken care of in
    // ACMCodecDB::CodecNumber().
    // Check if the payload-type is valid
    if (!ACMCodecDB::ValidPayloadType(send_codec.pltype)) {
      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
                   "Invalid payload-type %d for %s.", send_codec.pltype,
                   send_codec.plname);
      return -1;
    }
    // Set RED payload type.
    if (send_codec.plfreq == 8000) {
      red_nb_pltype_ = static_cast<uint8_t>(send_codec.pltype);
    } else {
      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
                   "RegisterSendCodec() failed, invalid frequency for RED "
                   "registration");
      return -1;
    }
    return 0;
  }

  // CNG can be registered with other payload type. If not registered the
  // default payload types from codec database will be used.
  if (IsCodecCN(send_codec)) {
    // CNG is registered.
    switch (send_codec.plfreq) {
      case 8000: {
        cng_nb_pltype_ = static_cast<uint8_t>(send_codec.pltype);
        return 0;
      }
      case 16000: {
        cng_wb_pltype_ = static_cast<uint8_t>(send_codec.pltype);
        return 0;
      }
      case 32000: {
        cng_swb_pltype_ = static_cast<uint8_t>(send_codec.pltype);
        return 0;
      }
      case 48000: {
        cng_fb_pltype_ = static_cast<uint8_t>(send_codec.pltype);
        return 0;
      }
      default: {
        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
                     "RegisterSendCodec() failed, invalid frequency for CNG "
                     "registration");
        return -1;
      }
    }
  }

  // Set Stereo, and make sure VAD and DTX is turned off.
  if (send_codec.channels == 2) {
    stereo_send_ = true;
    if (dtx_enabled_) {
      WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, dummy_id,
                   "VAD/DTX is turned off, not supported when sending stereo.");
    }
    dtx_enabled_ = false;
  } else {
    stereo_send_ = false;
  }

  // Check if the codec is already registered as send codec.
  bool new_codec = true;
  if (codec_owner_.Encoder()) {
    int new_codec_id = ACMCodecDB::CodecNumber(send_codec_inst_);
    DCHECK_GE(new_codec_id, 0);
    new_codec = new_codec_id != codec_id;
  }

  if (RedPayloadType(send_codec.plfreq) == -1) {
    red_enabled_ = false;
  }

  encoder_is_opus_ = IsOpus(send_codec);

  if (new_codec) {
    // This is a new codec. Register it and return.
    DCHECK(CodecSupported(send_codec));
    if (IsOpus(send_codec)) {
      // VAD/DTX not supported.
      dtx_enabled_ = false;
    }
    codec_owner_.SetEncoders(
        send_codec, dtx_enabled_ ? CngPayloadType(send_codec.plfreq) : -1,
        vad_mode_, red_enabled_ ? RedPayloadType(send_codec.plfreq) : -1);
    DCHECK(codec_owner_.Encoder());

    codec_fec_enabled_ = codec_fec_enabled_ &&
                         codec_owner_.Encoder()->SetFec(codec_fec_enabled_);

    send_codec_inst_ = send_codec;
    return 0;
  }

  // This is an existing codec; re-create it if any parameters have changed.
  if (send_codec_inst_.plfreq != send_codec.plfreq ||
      send_codec_inst_.pacsize != send_codec.pacsize ||
      send_codec_inst_.channels != send_codec.channels) {
    codec_owner_.SetEncoders(
        send_codec, dtx_enabled_ ? CngPayloadType(send_codec.plfreq) : -1,
        vad_mode_, red_enabled_ ? RedPayloadType(send_codec.plfreq) : -1);
    DCHECK(codec_owner_.Encoder());
  }
  send_codec_inst_.plfreq = send_codec.plfreq;
  send_codec_inst_.pacsize = send_codec.pacsize;
  send_codec_inst_.channels = send_codec.channels;
  send_codec_inst_.pltype = send_codec.pltype;

  // Check if a change in Rate is required.
  if (send_codec.rate != send_codec_inst_.rate) {
    codec_owner_.Encoder()->SetTargetBitrate(send_codec.rate);
    send_codec_inst_.rate = send_codec.rate;
  }

  codec_fec_enabled_ =
      codec_fec_enabled_ && codec_owner_.Encoder()->SetFec(codec_fec_enabled_);

  return 0;
}

void CodecManager::RegisterEncoder(AudioEncoder* external_speech_encoder) {
  // Make up a CodecInst.
  send_codec_inst_.channels = external_speech_encoder->NumChannels();
  send_codec_inst_.plfreq = external_speech_encoder->SampleRateHz();
  send_codec_inst_.pacsize = rtc::CheckedDivExact(
      static_cast<int>(external_speech_encoder->Max10MsFramesInAPacket() *
                       send_codec_inst_.plfreq),
      100);
  send_codec_inst_.pltype = -1;  // Not valid.
  send_codec_inst_.rate = -1;    // Not valid.
  static const char kName[] = "external";
  memcpy(send_codec_inst_.plname, kName, sizeof(kName));

  if (stereo_send_)
    dtx_enabled_ = false;
  codec_fec_enabled_ =
      codec_fec_enabled_ && codec_owner_.Encoder()->SetFec(codec_fec_enabled_);
  int cng_pt = dtx_enabled_
                   ? CngPayloadType(external_speech_encoder->SampleRateHz())
                   : -1;
  int red_pt = red_enabled_ ? RedPayloadType(send_codec_inst_.plfreq) : -1;
  codec_owner_.SetEncoders(external_speech_encoder, cng_pt, vad_mode_, red_pt);
}

int CodecManager::GetCodecInst(CodecInst* current_codec) const {
  int dummy_id = 0;
  WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, dummy_id,
               "SendCodec()");

  if (!codec_owner_.Encoder()) {
    WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, dummy_id,
                 "SendCodec Failed, no codec is registered");
    return -1;
  }
  *current_codec = send_codec_inst_;
  return 0;
}

bool CodecManager::SetCopyRed(bool enable) {
  if (enable && codec_fec_enabled_) {
    WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, 0,
                 "Codec internal FEC and RED cannot be co-enabled.");
    return false;
  }
  if (enable && RedPayloadType(send_codec_inst_.plfreq) == -1) {
    WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, 0,
                 "Cannot enable RED at %i Hz.", send_codec_inst_.plfreq);
    return false;
  }
  if (red_enabled_ != enable) {
    red_enabled_ = enable;
    if (codec_owner_.Encoder()) {
      int cng_pt = dtx_enabled_ ? CngPayloadType(send_codec_inst_.plfreq) : -1;
      int red_pt = red_enabled_ ? RedPayloadType(send_codec_inst_.plfreq) : -1;
      codec_owner_.ChangeCngAndRed(cng_pt, vad_mode_, red_pt);
    }
  }
  return true;
}

int CodecManager::SetVAD(bool enable, ACMVADMode mode) {
  // Sanity check of the mode.
  DCHECK(mode == VADNormal || mode == VADLowBitrate || mode == VADAggr ||
         mode == VADVeryAggr);

  // Check that the send codec is mono. We don't support VAD/DTX for stereo
  // sending.
  if (enable && stereo_send_) {
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, 0,
                 "VAD/DTX not supported for stereo sending");
    dtx_enabled_ = false;
    return -1;
  }

  // If a send codec is registered, set VAD/DTX for the codec.
  if (IsOpus(send_codec_inst_)) {
    // VAD/DTX not supported.
    dtx_enabled_ = false;
    return 0;
  }

  if (dtx_enabled_ != enable || vad_mode_ != mode) {
    dtx_enabled_ = enable;
    vad_mode_ = mode;
    if (codec_owner_.Encoder()) {
      int cng_pt = dtx_enabled_ ? CngPayloadType(send_codec_inst_.plfreq) : -1;
      int red_pt = red_enabled_ ? RedPayloadType(send_codec_inst_.plfreq) : -1;
      codec_owner_.ChangeCngAndRed(cng_pt, vad_mode_, red_pt);
    }
  }
  return 0;
}

void CodecManager::VAD(bool* dtx_enabled,
                       bool* vad_enabled,
                       ACMVADMode* mode) const {
  *dtx_enabled = dtx_enabled_;
  *vad_enabled = dtx_enabled_;
  *mode = vad_mode_;
}

int CodecManager::SetCodecFEC(bool enable_codec_fec) {
  if (enable_codec_fec == true && red_enabled_ == true) {
    WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, 0,
                 "Codec internal FEC and RED cannot be co-enabled.");
    return -1;
  }

  CHECK(codec_owner_.Encoder());
  codec_fec_enabled_ =
      codec_owner_.Encoder()->SetFec(enable_codec_fec) && enable_codec_fec;
  return codec_fec_enabled_ == enable_codec_fec ? 0 : -1;
}

AudioDecoder* CodecManager::GetAudioDecoder(const CodecInst& codec) {
  return IsIsac(codec) ? codec_owner_.GetIsacDecoder() : nullptr;
}

int CodecManager::CngPayloadType(int sample_rate_hz) const {
  switch (sample_rate_hz) {
    case 8000:
      return cng_nb_pltype_;
    case 16000:
      return cng_wb_pltype_;
    case 32000:
      return cng_swb_pltype_;
    case 48000:
      return cng_fb_pltype_;
    default:
      FATAL() << sample_rate_hz << " Hz is not supported";
      return -1;
  }
}

int CodecManager::RedPayloadType(int sample_rate_hz) const {
  switch (sample_rate_hz) {
    case 8000:
      return red_nb_pltype_;
    case 16000:
    case 32000:
    case 48000:
      return -1;
    default:
      FATAL() << sample_rate_hz << " Hz is not supported";
      return -1;
  }
}

}  // namespace acm2
}  // namespace webrtc
