/*
 *  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 !STR_CASE_CMP(codec.plname, "l16");
}

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) {
  RTC_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_);
    RTC_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.
    RTC_DCHECK(CodecSupported(send_codec));
    if (IsOpus(send_codec)) {
      // VAD/DTX not supported.
      dtx_enabled_ = false;
    }
    if (!codec_owner_.SetEncoders(
            send_codec, dtx_enabled_ ? CngPayloadType(send_codec.plfreq) : -1,
            vad_mode_, red_enabled_ ? RedPayloadType(send_codec.plfreq) : -1))
      return -1;
    RTC_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) {
    if (!codec_owner_.SetEncoders(
            send_codec, dtx_enabled_ ? CngPayloadType(send_codec.plfreq) : -1,
            vad_mode_, red_enabled_ ? RedPayloadType(send_codec.plfreq) : -1))
      return -1;
    RTC_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.
  RTC_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;
  }

  RTC_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
