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

#include "webrtc/modules/audio_coding/codecs/opus/opus_interface.h"
#include "webrtc/rtc_base/format_macros.h"
#include "webrtc/test/gtest.h"
#include "webrtc/test/testsupport/fileutils.h"

using ::std::string;
using ::std::tr1::tuple;
using ::std::tr1::get;
using ::testing::TestWithParam;

namespace webrtc {

// Define coding parameter as <channels, bit_rate, filename, extension>.
typedef tuple<size_t, int, string, string> coding_param;
typedef struct mode mode;

struct mode {
  bool fec;
  uint8_t target_packet_loss_rate;
};

const int kOpusBlockDurationMs = 20;
const int kOpusSamplingKhz = 48;

class OpusFecTest : public TestWithParam<coding_param> {
 protected:
  OpusFecTest();

  virtual void SetUp();
  virtual void TearDown();

  virtual void EncodeABlock();

  virtual void DecodeABlock(bool lost_previous, bool lost_current);

  int block_duration_ms_;
  int sampling_khz_;
  size_t block_length_sample_;

  size_t channels_;
  int bit_rate_;

  size_t data_pointer_;
  size_t loop_length_samples_;
  size_t max_bytes_;
  size_t encoded_bytes_;

  WebRtcOpusEncInst* opus_encoder_;
  WebRtcOpusDecInst* opus_decoder_;

  string in_filename_;

  std::unique_ptr<int16_t[]> in_data_;
  std::unique_ptr<int16_t[]> out_data_;
  std::unique_ptr<uint8_t[]> bit_stream_;
};

void OpusFecTest::SetUp() {
  channels_ = get<0>(GetParam());
  bit_rate_ = get<1>(GetParam());
  printf("Coding %" PRIuS " channel signal at %d bps.\n", channels_, bit_rate_);

  in_filename_ = test::ResourcePath(get<2>(GetParam()), get<3>(GetParam()));

  FILE* fp = fopen(in_filename_.c_str(), "rb");
  ASSERT_FALSE(fp == NULL);

  // Obtain file size.
  fseek(fp, 0, SEEK_END);
  loop_length_samples_ = ftell(fp) / sizeof(int16_t);
  rewind(fp);

  // Allocate memory to contain the whole file.
  in_data_.reset(new int16_t[loop_length_samples_ +
      block_length_sample_ * channels_]);

  // Copy the file into the buffer.
  ASSERT_EQ(fread(&in_data_[0], sizeof(int16_t), loop_length_samples_, fp),
            loop_length_samples_);
  fclose(fp);

  // The audio will be used in a looped manner. To ease the acquisition of an
  // audio frame that crosses the end of the excerpt, we add an extra block
  // length of samples to the end of the array, starting over again from the
  // beginning of the array. Audio frames cross the end of the excerpt always
  // appear as a continuum of memory.
  memcpy(&in_data_[loop_length_samples_], &in_data_[0],
         block_length_sample_ * channels_ * sizeof(int16_t));

  // Maximum number of bytes in output bitstream.
  max_bytes_ = block_length_sample_ * channels_ * sizeof(int16_t);

  out_data_.reset(new int16_t[2 * block_length_sample_ * channels_]);
  bit_stream_.reset(new uint8_t[max_bytes_]);

  // If channels_ == 1, use Opus VOIP mode, otherwise, audio mode.
  int app = channels_ == 1 ? 0 : 1;

  // Create encoder memory.
  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, app));
  EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
  // Set bitrate.
  EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, bit_rate_));
}

void OpusFecTest::TearDown() {
  // Free memory.
  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
  EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
}

OpusFecTest::OpusFecTest()
    : block_duration_ms_(kOpusBlockDurationMs),
      sampling_khz_(kOpusSamplingKhz),
      block_length_sample_(
          static_cast<size_t>(block_duration_ms_ * sampling_khz_)),
      data_pointer_(0),
      max_bytes_(0),
      encoded_bytes_(0),
      opus_encoder_(NULL),
      opus_decoder_(NULL) {
}

void OpusFecTest::EncodeABlock() {
  int value = WebRtcOpus_Encode(opus_encoder_,
                                &in_data_[data_pointer_],
                                block_length_sample_,
                                max_bytes_, &bit_stream_[0]);
  EXPECT_GT(value, 0);

  encoded_bytes_ = static_cast<size_t>(value);
}

void OpusFecTest::DecodeABlock(bool lost_previous, bool lost_current) {
  int16_t audio_type;
  int value_1 = 0, value_2 = 0;

  if (lost_previous) {
    // Decode previous frame.
    if (!lost_current &&
        WebRtcOpus_PacketHasFec(&bit_stream_[0], encoded_bytes_) == 1) {
      value_1 = WebRtcOpus_DecodeFec(opus_decoder_, &bit_stream_[0],
                                     encoded_bytes_, &out_data_[0],
                                     &audio_type);
    } else {
      value_1 = WebRtcOpus_DecodePlc(opus_decoder_, &out_data_[0], 1);
    }
    EXPECT_EQ(static_cast<int>(block_length_sample_), value_1);
  }

  if (!lost_current) {
    // Decode current frame.
    value_2 = WebRtcOpus_Decode(opus_decoder_, &bit_stream_[0], encoded_bytes_,
                                &out_data_[value_1 * channels_], &audio_type);
    EXPECT_EQ(static_cast<int>(block_length_sample_), value_2);
  }
}

TEST_P(OpusFecTest, RandomPacketLossTest) {
  const int kDurationMs = 200000;
  int time_now_ms, fec_frames;
  int actual_packet_loss_rate;
  bool lost_current, lost_previous;
  mode mode_set[3] = {{true, 0},
                      {false, 0},
                      {true, 50}};

  lost_current = false;
  for (int i = 0; i < 3; i++) {
    if (mode_set[i].fec) {
      EXPECT_EQ(0, WebRtcOpus_EnableFec(opus_encoder_));
      EXPECT_EQ(0, WebRtcOpus_SetPacketLossRate(opus_encoder_,
          mode_set[i].target_packet_loss_rate));
      printf("FEC is ON, target at packet loss rate %d percent.\n",
             mode_set[i].target_packet_loss_rate);
    } else {
      EXPECT_EQ(0, WebRtcOpus_DisableFec(opus_encoder_));
      printf("FEC is OFF.\n");
    }
    // In this test, we let the target packet loss rate match the actual rate.
    actual_packet_loss_rate = mode_set[i].target_packet_loss_rate;
    // Run every mode a certain time.
    time_now_ms = 0;
    fec_frames = 0;
    while (time_now_ms < kDurationMs) {
      // Encode & decode.
      EncodeABlock();

      // Check if payload has FEC.
      int fec = WebRtcOpus_PacketHasFec(&bit_stream_[0], encoded_bytes_);

      // If FEC is disabled or the target packet loss rate is set to 0, there
      // should be no FEC in the bit stream.
      if (!mode_set[i].fec || mode_set[i].target_packet_loss_rate == 0) {
        EXPECT_EQ(fec, 0);
      } else if (fec == 1) {
        fec_frames++;
      }

      lost_previous = lost_current;
      lost_current = rand() < actual_packet_loss_rate * (RAND_MAX / 100);
      DecodeABlock(lost_previous, lost_current);

      time_now_ms += block_duration_ms_;

      // |data_pointer_| is incremented and wrapped across
      // |loop_length_samples_|.
      data_pointer_ = (data_pointer_ + block_length_sample_ * channels_) %
        loop_length_samples_;
    }
    if (mode_set[i].fec) {
      printf("%.2f percent frames has FEC.\n",
             static_cast<float>(fec_frames) * block_duration_ms_ / 2000);
    }
  }
}

const coding_param param_set[] =
    {::std::tr1::make_tuple(1, 64000, string("audio_coding/testfile32kHz"),
                            string("pcm")),
     ::std::tr1::make_tuple(1, 32000, string("audio_coding/testfile32kHz"),
                            string("pcm")),
     ::std::tr1::make_tuple(2, 64000, string("audio_coding/teststereo32kHz"),
                            string("pcm"))};

// 64 kbps, stereo
INSTANTIATE_TEST_CASE_P(AllTest, OpusFecTest,
                        ::testing::ValuesIn(param_set));

}  // namespace webrtc
