/*
 *  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 "modules/audio_coding/test/PacketLossTest.h"

#include <memory>

#include "api/audio_codecs/builtin_audio_decoder_factory.h"
#include "rtc_base/strings/string_builder.h"
#include "test/gtest.h"
#include "test/testsupport/fileutils.h"

namespace webrtc {

ReceiverWithPacketLoss::ReceiverWithPacketLoss()
    : loss_rate_(0),
      burst_length_(1),
      packet_counter_(0),
      lost_packet_counter_(0),
      burst_lost_counter_(burst_length_) {}

void ReceiverWithPacketLoss::Setup(AudioCodingModule* acm,
                                   RTPStream* rtpStream,
                                   std::string out_file_name,
                                   int channels,
                                   int loss_rate,
                                   int burst_length) {
  loss_rate_ = loss_rate;
  burst_length_ = burst_length;
  burst_lost_counter_ = burst_length_;  // To prevent first packet gets lost.
  rtc::StringBuilder ss;
  ss << out_file_name << "_" << loss_rate_ << "_" << burst_length_ << "_";
  Receiver::Setup(acm, rtpStream, ss.str(), channels);
}

bool ReceiverWithPacketLoss::IncomingPacket() {
  if (!_rtpStream->EndOfFile()) {
    if (packet_counter_ == 0) {
      _realPayloadSizeBytes = _rtpStream->Read(&_rtpInfo, _incomingPayload,
                                               _payloadSizeBytes, &_nextTime);
      if (_realPayloadSizeBytes == 0) {
        if (_rtpStream->EndOfFile()) {
          packet_counter_ = 0;
          return true;
        } else {
          return false;
        }
      }
    }

    if (!PacketLost()) {
      _acm->IncomingPacket(_incomingPayload, _realPayloadSizeBytes, _rtpInfo);
    }
    packet_counter_++;
    _realPayloadSizeBytes = _rtpStream->Read(&_rtpInfo, _incomingPayload,
                                             _payloadSizeBytes, &_nextTime);
    if (_realPayloadSizeBytes == 0 && _rtpStream->EndOfFile()) {
      packet_counter_ = 0;
      lost_packet_counter_ = 0;
    }
  }
  return true;
}

bool ReceiverWithPacketLoss::PacketLost() {
  if (burst_lost_counter_ < burst_length_) {
    lost_packet_counter_++;
    burst_lost_counter_++;
    return true;
  }

  if (lost_packet_counter_ * 100 < loss_rate_ * packet_counter_) {
    lost_packet_counter_++;
    burst_lost_counter_ = 1;
    return true;
  }
  return false;
}

SenderWithFEC::SenderWithFEC() : expected_loss_rate_(0) {}

void SenderWithFEC::Setup(AudioCodingModule* acm,
                          RTPStream* rtpStream,
                          std::string in_file_name,
                          int sample_rate,
                          int channels,
                          int expected_loss_rate) {
  Sender::Setup(acm, rtpStream, in_file_name, sample_rate, channels);
  EXPECT_TRUE(SetFEC(true));
  EXPECT_TRUE(SetPacketLossRate(expected_loss_rate));
}

bool SenderWithFEC::SetFEC(bool enable_fec) {
  bool success = false;
  _acm->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* enc) {
    if (*enc && (*enc)->SetFec(enable_fec)) {
      success = true;
    }
  });
  return success;
}

bool SenderWithFEC::SetPacketLossRate(int expected_loss_rate) {
  if (_acm->SetPacketLossRate(expected_loss_rate) == 0) {
    expected_loss_rate_ = expected_loss_rate;
    return true;
  }
  return false;
}

PacketLossTest::PacketLossTest(int channels,
                               int expected_loss_rate,
                               int actual_loss_rate,
                               int burst_length)
    : channels_(channels),
      in_file_name_(channels_ == 1 ? "audio_coding/testfile32kHz"
                                   : "audio_coding/teststereo32kHz"),
      sample_rate_hz_(32000),
      sender_(new SenderWithFEC),
      receiver_(new ReceiverWithPacketLoss),
      expected_loss_rate_(expected_loss_rate),
      actual_loss_rate_(actual_loss_rate),
      burst_length_(burst_length) {}

void PacketLossTest::Perform() {
#ifndef WEBRTC_CODEC_OPUS
  return;
#else
  AudioCodingModule::Config config;
  config.decoder_factory = CreateBuiltinAudioDecoderFactory();
  std::unique_ptr<AudioCodingModule> acm(AudioCodingModule::Create(config));

  int codec_id = acm->Codec("opus", 48000, channels_);

  RTPFile rtpFile;
  std::string fileName = webrtc::test::TempFilename(webrtc::test::OutputPath(),
                                                    "packet_loss_test");

  // Encode to file
  rtpFile.Open(fileName.c_str(), "wb+");
  rtpFile.WriteHeader();

  sender_->codeId = codec_id;

  sender_->Setup(acm.get(), &rtpFile, in_file_name_, sample_rate_hz_, channels_,
                 expected_loss_rate_);
  if (acm->SendCodec()) {
    sender_->Run();
  }
  sender_->Teardown();
  rtpFile.Close();

  // Decode to file
  rtpFile.Open(fileName.c_str(), "rb");
  rtpFile.ReadHeader();

  receiver_->codeId = codec_id;

  receiver_->Setup(acm.get(), &rtpFile, "packetLoss_out", channels_,
                   actual_loss_rate_, burst_length_);
  receiver_->Run();
  receiver_->Teardown();
  rtpFile.Close();
#endif
}

}  // namespace webrtc
