/*
 *  Copyright (c) 2014 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.
 */

#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_
#define MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_

#include "common_types.h"
#include "rtc_base/checks.h"

namespace webrtc {

template <typename T>
typename AudioEncoderIsacT<T>::Config CreateIsacConfig(
    const CodecInst& codec_inst,
    const rtc::scoped_refptr<LockedIsacBandwidthInfo>& bwinfo) {
  typename AudioEncoderIsacT<T>::Config config;
  config.bwinfo = bwinfo;
  config.payload_type = codec_inst.pltype;
  config.sample_rate_hz = codec_inst.plfreq;
  config.frame_size_ms =
      rtc::CheckedDivExact(1000 * codec_inst.pacsize, config.sample_rate_hz);
  config.adaptive_mode = (codec_inst.rate == -1);
  if (codec_inst.rate != -1)
    config.bit_rate = codec_inst.rate;
  return config;
}

template <typename T>
bool AudioEncoderIsacT<T>::Config::IsOk() const {
  if (max_bit_rate < 32000 && max_bit_rate != -1)
    return false;
  if (max_payload_size_bytes < 120 && max_payload_size_bytes != -1)
    return false;
  if (adaptive_mode && !bwinfo)
    return false;
  switch (sample_rate_hz) {
    case 16000:
      if (max_bit_rate > 53400)
        return false;
      if (max_payload_size_bytes > 400)
        return false;
      return (frame_size_ms == 30 || frame_size_ms == 60) &&
             (bit_rate == 0 || (bit_rate >= 10000 && bit_rate <= 32000));
    case 32000:
      if (max_bit_rate > 160000)
        return false;
      if (max_payload_size_bytes > 600)
        return false;
      return T::has_swb &&
             (frame_size_ms == 30 &&
              (bit_rate == 0 || (bit_rate >= 10000 && bit_rate <= 56000)));
    default:
      return false;
  }
}

template <typename T>
AudioEncoderIsacT<T>::AudioEncoderIsacT(const Config& config) {
  RecreateEncoderInstance(config);
}

template <typename T>
AudioEncoderIsacT<T>::AudioEncoderIsacT(
    const CodecInst& codec_inst,
    const rtc::scoped_refptr<LockedIsacBandwidthInfo>& bwinfo)
    : AudioEncoderIsacT(CreateIsacConfig<T>(codec_inst, bwinfo)) {}

template <typename T>
AudioEncoderIsacT<T>::~AudioEncoderIsacT() {
  RTC_CHECK_EQ(0, T::Free(isac_state_));
}

template <typename T>
int AudioEncoderIsacT<T>::SampleRateHz() const {
  return T::EncSampRate(isac_state_);
}

template <typename T>
size_t AudioEncoderIsacT<T>::NumChannels() const {
  return 1;
}

template <typename T>
size_t AudioEncoderIsacT<T>::Num10MsFramesInNextPacket() const {
  const int samples_in_next_packet = T::GetNewFrameLen(isac_state_);
  return static_cast<size_t>(
      rtc::CheckedDivExact(samples_in_next_packet,
                           rtc::CheckedDivExact(SampleRateHz(), 100)));
}

template <typename T>
size_t AudioEncoderIsacT<T>::Max10MsFramesInAPacket() const {
  return 6;  // iSAC puts at most 60 ms in a packet.
}

template <typename T>
int AudioEncoderIsacT<T>::GetTargetBitrate() const {
  if (config_.adaptive_mode)
    return -1;
  return config_.bit_rate == 0 ? kDefaultBitRate : config_.bit_rate;
}

template <typename T>
AudioEncoder::EncodedInfo AudioEncoderIsacT<T>::EncodeImpl(
    uint32_t rtp_timestamp,
    rtc::ArrayView<const int16_t> audio,
    rtc::Buffer* encoded) {
  if (!packet_in_progress_) {
    // Starting a new packet; remember the timestamp for later.
    packet_in_progress_ = true;
    packet_timestamp_ = rtp_timestamp;
  }
  if (bwinfo_) {
    IsacBandwidthInfo bwinfo = bwinfo_->Get();
    T::SetBandwidthInfo(isac_state_, &bwinfo);
  }

  size_t encoded_bytes = encoded->AppendData(
      kSufficientEncodeBufferSizeBytes,
      [&] (rtc::ArrayView<uint8_t> encoded) {
        int r = T::Encode(isac_state_, audio.data(), encoded.data());

        RTC_CHECK_GE(r, 0) << "Encode failed (error code "
                           << T::GetErrorCode(isac_state_) << ")";

        return static_cast<size_t>(r);
      });

  if (encoded_bytes == 0)
    return EncodedInfo();

  // Got enough input to produce a packet. Return the saved timestamp from
  // the first chunk of input that went into the packet.
  packet_in_progress_ = false;
  EncodedInfo info;
  info.encoded_bytes = encoded_bytes;
  info.encoded_timestamp = packet_timestamp_;
  info.payload_type = config_.payload_type;
  info.encoder_type = CodecType::kIsac;
  return info;
}

template <typename T>
void AudioEncoderIsacT<T>::Reset() {
  RecreateEncoderInstance(config_);
}

template <typename T>
void AudioEncoderIsacT<T>::RecreateEncoderInstance(const Config& config) {
  RTC_CHECK(config.IsOk());
  packet_in_progress_ = false;
  bwinfo_ = config.bwinfo;
  if (isac_state_)
    RTC_CHECK_EQ(0, T::Free(isac_state_));
  RTC_CHECK_EQ(0, T::Create(&isac_state_));
  RTC_CHECK_EQ(0, T::EncoderInit(isac_state_, config.adaptive_mode ? 0 : 1));
  RTC_CHECK_EQ(0, T::SetEncSampRate(isac_state_, config.sample_rate_hz));
  const int bit_rate = config.bit_rate == 0 ? kDefaultBitRate : config.bit_rate;
  if (config.adaptive_mode) {
    RTC_CHECK_EQ(0, T::ControlBwe(isac_state_, bit_rate, config.frame_size_ms,
                                  config.enforce_frame_size));
  } else {
    RTC_CHECK_EQ(0, T::Control(isac_state_, bit_rate, config.frame_size_ms));
  }
  if (config.max_payload_size_bytes != -1)
    RTC_CHECK_EQ(
        0, T::SetMaxPayloadSize(isac_state_, config.max_payload_size_bytes));
  if (config.max_bit_rate != -1)
    RTC_CHECK_EQ(0, T::SetMaxRate(isac_state_, config.max_bit_rate));

  // Set the decoder sample rate even though we just use the encoder. This
  // doesn't appear to be necessary to produce a valid encoding, but without it
  // we get an encoding that isn't bit-for-bit identical with what a combined
  // encoder+decoder object produces.
  RTC_CHECK_EQ(0, T::SetDecSampRate(isac_state_, config.sample_rate_hz));

  config_ = config;
}

}  // namespace webrtc

#endif  // MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_
