/*
 *  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.
 */

#include "webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h"

#include <algorithm>
#include <limits>
#include "webrtc/common_types.h"
#include "webrtc/modules/audio_coding/codecs/ilbc/ilbc.h"
#include "webrtc/rtc_base/checks.h"
#include "webrtc/rtc_base/safe_conversions.h"
#include "webrtc/rtc_base/string_to_number.h"

namespace webrtc {

namespace {

const int kSampleRateHz = 8000;

AudioEncoderIlbcConfig CreateConfig(const CodecInst& codec_inst) {
  AudioEncoderIlbcConfig config;
  config.frame_size_ms = codec_inst.pacsize / 8;
  return config;
}

int GetIlbcBitrate(int ptime) {
  switch (ptime) {
    case 20:
    case 40:
      // 38 bytes per frame of 20 ms => 15200 bits/s.
      return 15200;
    case 30:
    case 60:
      // 50 bytes per frame of 30 ms => (approx) 13333 bits/s.
      return 13333;
    default:
      FATAL();
  }
}

}  // namespace

rtc::Optional<AudioEncoderIlbcConfig> AudioEncoderIlbcImpl::SdpToConfig(
    const SdpAudioFormat& format) {
  if (STR_CASE_CMP(format.name.c_str(), "ilbc") != 0 ||
      format.clockrate_hz != 8000 || format.num_channels != 1) {
    return rtc::Optional<AudioEncoderIlbcConfig>();
  }

  AudioEncoderIlbcConfig config;
  auto ptime_iter = format.parameters.find("ptime");
  if (ptime_iter != format.parameters.end()) {
    auto ptime = rtc::StringToNumber<int>(ptime_iter->second);
    if (ptime && *ptime > 0) {
      const int whole_packets = *ptime / 10;
      config.frame_size_ms = std::max(20, std::min(whole_packets * 10, 60));
    }
  }
  return config.IsOk() ? rtc::Optional<AudioEncoderIlbcConfig>(config)
                       : rtc::Optional<AudioEncoderIlbcConfig>();
}

AudioEncoderIlbcImpl::AudioEncoderIlbcImpl(const AudioEncoderIlbcConfig& config,
                                           int payload_type)
    : frame_size_ms_(config.frame_size_ms),
      payload_type_(payload_type),
      num_10ms_frames_per_packet_(
          static_cast<size_t>(config.frame_size_ms / 10)),
      encoder_(nullptr) {
  RTC_CHECK(config.IsOk());
  Reset();
}

AudioEncoderIlbcImpl::AudioEncoderIlbcImpl(const CodecInst& codec_inst)
    : AudioEncoderIlbcImpl(CreateConfig(codec_inst), codec_inst.pltype) {}

AudioEncoderIlbcImpl::AudioEncoderIlbcImpl(int payload_type,
                                           const SdpAudioFormat& format)
    : AudioEncoderIlbcImpl(*SdpToConfig(format), payload_type) {}

AudioEncoderIlbcImpl::~AudioEncoderIlbcImpl() {
  RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderFree(encoder_));
}

rtc::Optional<AudioCodecInfo> AudioEncoderIlbcImpl::QueryAudioEncoder(
    const SdpAudioFormat& format) {
  if (STR_CASE_CMP(format.name.c_str(), GetPayloadName()) == 0) {
    const auto config_opt = SdpToConfig(format);
    if (format.clockrate_hz == 8000 && format.num_channels == 1 &&
        config_opt) {
      RTC_DCHECK(config_opt->IsOk());
      return rtc::Optional<AudioCodecInfo>(
          {rtc::dchecked_cast<int>(kSampleRateHz), 1,
           GetIlbcBitrate(config_opt->frame_size_ms)});
    }
  }
  return rtc::Optional<AudioCodecInfo>();
}

int AudioEncoderIlbcImpl::SampleRateHz() const {
  return kSampleRateHz;
}

size_t AudioEncoderIlbcImpl::NumChannels() const {
  return 1;
}

size_t AudioEncoderIlbcImpl::Num10MsFramesInNextPacket() const {
  return num_10ms_frames_per_packet_;
}

size_t AudioEncoderIlbcImpl::Max10MsFramesInAPacket() const {
  return num_10ms_frames_per_packet_;
}

int AudioEncoderIlbcImpl::GetTargetBitrate() const {
  return GetIlbcBitrate(rtc::dchecked_cast<int>(num_10ms_frames_per_packet_) *
                        10);
}

AudioEncoder::EncodedInfo AudioEncoderIlbcImpl::EncodeImpl(
    uint32_t rtp_timestamp,
    rtc::ArrayView<const int16_t> audio,
    rtc::Buffer* encoded) {

  // Save timestamp if starting a new packet.
  if (num_10ms_frames_buffered_ == 0)
    first_timestamp_in_buffer_ = rtp_timestamp;

  // Buffer input.
  std::copy(audio.cbegin(), audio.cend(),
            input_buffer_ + kSampleRateHz / 100 * num_10ms_frames_buffered_);

  // If we don't yet have enough buffered input for a whole packet, we're done
  // for now.
  if (++num_10ms_frames_buffered_ < num_10ms_frames_per_packet_) {
    return EncodedInfo();
  }

  // Encode buffered input.
  RTC_DCHECK_EQ(num_10ms_frames_buffered_, num_10ms_frames_per_packet_);
  num_10ms_frames_buffered_ = 0;
  size_t encoded_bytes =
      encoded->AppendData(
          RequiredOutputSizeBytes(),
          [&] (rtc::ArrayView<uint8_t> encoded) {
            const int r = WebRtcIlbcfix_Encode(
                encoder_,
                input_buffer_,
                kSampleRateHz / 100 * num_10ms_frames_per_packet_,
                encoded.data());
            RTC_CHECK_GE(r, 0);

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

  RTC_DCHECK_EQ(encoded_bytes, RequiredOutputSizeBytes());

  EncodedInfo info;
  info.encoded_bytes = encoded_bytes;
  info.encoded_timestamp = first_timestamp_in_buffer_;
  info.payload_type = payload_type_;
  info.encoder_type = CodecType::kIlbc;
  return info;
}

void AudioEncoderIlbcImpl::Reset() {
  if (encoder_)
    RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderFree(encoder_));
  RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderCreate(&encoder_));
  const int encoder_frame_size_ms = frame_size_ms_ > 30
                                        ? frame_size_ms_ / 2
                                        : frame_size_ms_;
  RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderInit(encoder_, encoder_frame_size_ms));
  num_10ms_frames_buffered_ = 0;
}

size_t AudioEncoderIlbcImpl::RequiredOutputSizeBytes() const {
  switch (num_10ms_frames_per_packet_) {
    case 2:   return 38;
    case 3:   return 50;
    case 4:   return 2 * 38;
    case 6:   return 2 * 50;
    default:  FATAL();
  }
}

}  // namespace webrtc
