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

#include "webrtc/base/checks.h"
#include "webrtc/base/format_macros.h"
#include "webrtc/engine_configurations.h"
#include "webrtc/modules/audio_coding/acm2/rent_a_codec.h"
#include "webrtc/system_wrappers/include/trace.h"

namespace webrtc {
namespace acm2 {

namespace {

// Check if the given codec is a valid to be registered as send codec.
int IsValidSendCodec(const CodecInst& send_codec) {
  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 (%" PRIuS ", only mono and stereo "
                 "are supported)",
                 send_codec.channels);
    return -1;
  }

  auto maybe_codec_id = RentACodec::CodecIdByInst(send_codec);
  if (!maybe_codec_id) {
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
                 "Invalid codec setting for the send codec.");
    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 (!RentACodec::IsSupportedNumChannels(*maybe_codec_id, send_codec.channels)
           .value_or(false)) {
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
                 "%" PRIuS " number of channels not supportedn for %s.",
                 send_codec.channels, send_codec.plname);
    return -1;
  }
  return RentACodec::CodecIndexFromId(*maybe_codec_id).value_or(-1);
}

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

}  // namespace

CodecManager::CodecManager() {
  thread_checker_.DetachFromThread();
}

CodecManager::~CodecManager() = default;

bool CodecManager::RegisterEncoder(const CodecInst& send_codec) {
  RTC_DCHECK(thread_checker_.CalledOnValidThread());
  int codec_id = IsValidSendCodec(send_codec);

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

  int dummy_id = 0;
  switch (RentACodec::RegisterRedPayloadType(
      &codec_stack_params_.red_payload_types, send_codec)) {
    case RentACodec::RegistrationResult::kOk:
      return true;
    case RentACodec::RegistrationResult::kBadFreq:
      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
                   "RegisterSendCodec() failed, invalid frequency for RED"
                   " registration");
      return false;
    case RentACodec::RegistrationResult::kSkip:
      break;
  }
  switch (RentACodec::RegisterCngPayloadType(
      &codec_stack_params_.cng_payload_types, send_codec)) {
    case RentACodec::RegistrationResult::kOk:
      return true;
    case RentACodec::RegistrationResult::kBadFreq:
      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
                   "RegisterSendCodec() failed, invalid frequency for CNG"
                   " registration");
      return false;
    case RentACodec::RegistrationResult::kSkip:
      break;
  }

  if (IsOpus(send_codec)) {
    // VAD/DTX not supported.
    codec_stack_params_.use_cng = false;
  }

  send_codec_inst_ = rtc::Optional<CodecInst>(send_codec);
  codec_stack_params_.speech_encoder = nullptr;  // Caller must recreate it.
  return true;
}

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

bool CodecManager::SetCopyRed(bool enable) {
  if (enable && codec_stack_params_.use_codec_fec) {
    WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, 0,
                 "Codec internal FEC and RED cannot be co-enabled.");
    return false;
  }
  if (enable && send_codec_inst_ &&
      codec_stack_params_.red_payload_types.count(send_codec_inst_->plfreq) <
          1) {
    WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, 0,
                 "Cannot enable RED at %i Hz.", send_codec_inst_->plfreq);
    return false;
  }
  codec_stack_params_.use_red = enable;
  return true;
}

bool 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.
  const bool stereo_send =
      codec_stack_params_.speech_encoder
          ? (codec_stack_params_.speech_encoder->NumChannels() != 1)
          : false;
  if (enable && stereo_send) {
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, 0,
                 "VAD/DTX not supported for stereo sending");
    return false;
  }

  // TODO(kwiberg): This doesn't protect Opus when injected as an external
  // encoder.
  if (send_codec_inst_ && IsOpus(*send_codec_inst_)) {
    // VAD/DTX not supported, but don't fail.
    enable = false;
  }

  codec_stack_params_.use_cng = enable;
  codec_stack_params_.vad_mode = mode;
  return true;
}

bool CodecManager::SetCodecFEC(bool enable_codec_fec) {
  if (enable_codec_fec && codec_stack_params_.use_red) {
    WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, 0,
                 "Codec internal FEC and RED cannot be co-enabled.");
    return false;
  }

  codec_stack_params_.use_codec_fec = enable_codec_fec;
  return true;
}

}  // namespace acm2
}  // namespace webrtc
