/*
 *  Copyright (c) 2018 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/neteq/tools/neteq_test_factory.h"

#include <errno.h>
#include <limits.h>  // For ULONG_MAX returned by strtoul.
#include <stdio.h>
#include <stdlib.h>  // For strtoul.

#include <fstream>
#include <iostream>
#include <memory>
#include <set>
#include <string>
#include <utility>

#include "absl/memory/memory.h"
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
#include "modules/audio_coding/neteq/include/neteq.h"
#include "modules/audio_coding/neteq/tools/audio_sink.h"
#include "modules/audio_coding/neteq/tools/fake_decode_from_file.h"
#include "modules/audio_coding/neteq/tools/input_audio_file.h"
#include "modules/audio_coding/neteq/tools/neteq_delay_analyzer.h"
#include "modules/audio_coding/neteq/tools/neteq_event_log_input.h"
#include "modules/audio_coding/neteq/tools/neteq_packet_source_input.h"
#include "modules/audio_coding/neteq/tools/neteq_replacement_input.h"
#include "modules/audio_coding/neteq/tools/neteq_stats_getter.h"
#include "modules/audio_coding/neteq/tools/neteq_stats_plotter.h"
#include "modules/audio_coding/neteq/tools/neteq_test.h"
#include "modules/audio_coding/neteq/tools/output_audio_file.h"
#include "modules/audio_coding/neteq/tools/output_wav_file.h"
#include "modules/audio_coding/neteq/tools/rtp_file_source.h"
#include "rtc_base/checks.h"
#include "rtc_base/ref_counted_object.h"
#include "test/function_audio_decoder_factory.h"
#include "test/testsupport/file_utils.h"

namespace webrtc {
namespace test {
namespace {

absl::optional<int> CodecSampleRate(
    uint8_t payload_type,
    webrtc::test::NetEqTestFactory::Config config) {
  if (payload_type == config.pcmu || payload_type == config.pcma ||
      payload_type == config.ilbc || payload_type == config.pcm16b ||
      payload_type == config.cn_nb || payload_type == config.avt)
    return 8000;
  if (payload_type == config.isac || payload_type == config.pcm16b_wb ||
      payload_type == config.g722 || payload_type == config.cn_wb ||
      payload_type == config.avt_16)
    return 16000;
  if (payload_type == config.isac_swb || payload_type == config.pcm16b_swb32 ||
      payload_type == config.cn_swb32 || payload_type == config.avt_32)
    return 32000;
  if (payload_type == config.opus || payload_type == config.pcm16b_swb48 ||
      payload_type == config.cn_swb48 || payload_type == config.avt_48)
    return 48000;
  if (payload_type == config.red)
    return 0;
  return absl::nullopt;
}

}  // namespace

// A callback class which prints whenver the inserted packet stream changes
// the SSRC.
class SsrcSwitchDetector : public NetEqPostInsertPacket {
 public:
  // Takes a pointer to another callback object, which will be invoked after
  // this object finishes. This does not transfer ownership, and null is a
  // valid value.
  explicit SsrcSwitchDetector(NetEqPostInsertPacket* other_callback)
      : other_callback_(other_callback) {}

  void AfterInsertPacket(const NetEqInput::PacketData& packet,
                         NetEq* neteq) override {
    if (last_ssrc_ && packet.header.ssrc != *last_ssrc_) {
      std::cout << "Changing streams from 0x" << std::hex << *last_ssrc_
                << " to 0x" << std::hex << packet.header.ssrc << std::dec
                << " (payload type "
                << static_cast<int>(packet.header.payloadType) << ")"
                << std::endl;
    }
    last_ssrc_ = packet.header.ssrc;
    if (other_callback_) {
      other_callback_->AfterInsertPacket(packet, neteq);
    }
  }

 private:
  NetEqPostInsertPacket* other_callback_;
  absl::optional<uint32_t> last_ssrc_;
};

NetEqTestFactory::NetEqTestFactory() = default;
NetEqTestFactory::~NetEqTestFactory() = default;

NetEqTestFactory::Config::Config() = default;
NetEqTestFactory::Config::Config(const Config& other) = default;
NetEqTestFactory::Config::~Config() = default;

std::unique_ptr<NetEqTest> NetEqTestFactory::InitializeTestFromString(
    const std::string& input_string,
    const Config& config) {
  std::unique_ptr<NetEqInput> input(
      NetEqEventLogInput::CreateFromString(input_string, config.ssrc_filter));
  if (!input) {
    std::cerr << "Error: Cannot parse input string" << std::endl;
    return nullptr;
  }
  return InitializeTest(std::move(input), config);
}

std::unique_ptr<NetEqTest> NetEqTestFactory::InitializeTestFromFile(
    const std::string& input_file_name,
    const Config& config) {
  // Gather RTP header extensions in a map.
  NetEqPacketSourceInput::RtpHeaderExtensionMap rtp_ext_map = {
      {config.audio_level, kRtpExtensionAudioLevel},
      {config.abs_send_time, kRtpExtensionAbsoluteSendTime},
      {config.transport_seq_no, kRtpExtensionTransportSequenceNumber},
      {config.video_content_type, kRtpExtensionVideoContentType},
      {config.video_timing, kRtpExtensionVideoTiming}};

  std::unique_ptr<NetEqInput> input;
  if (RtpFileSource::ValidRtpDump(input_file_name) ||
      RtpFileSource::ValidPcap(input_file_name)) {
    input.reset(new NetEqRtpDumpInput(input_file_name, rtp_ext_map,
                                      config.ssrc_filter));
  } else {
    input.reset(NetEqEventLogInput::CreateFromFile(input_file_name,
                                                   config.ssrc_filter));
  }

  std::cout << "Input file: " << input_file_name << std::endl;
  if (!input) {
    std::cerr << "Error: Cannot open input file" << std::endl;
    return nullptr;
  }
  return InitializeTest(std::move(input), config);
}

std::unique_ptr<NetEqTest> NetEqTestFactory::InitializeTest(
    std::unique_ptr<NetEqInput> input,
    const Config& config) {
  if (input->ended()) {
    std::cerr << "Error: Input is empty" << std::endl;
    return nullptr;
  }

  // Check the sample rate.
  absl::optional<int> sample_rate_hz;
  std::set<std::pair<int, uint32_t>> discarded_pt_and_ssrc;
  while (absl::optional<RTPHeader> first_rtp_header = input->NextHeader()) {
    RTC_DCHECK(first_rtp_header);
    sample_rate_hz = CodecSampleRate(first_rtp_header->payloadType, config);
    if (sample_rate_hz) {
      std::cout << "Found valid packet with payload type "
                << static_cast<int>(first_rtp_header->payloadType)
                << " and SSRC 0x" << std::hex << first_rtp_header->ssrc
                << std::dec << std::endl;
      break;
    }
    // Discard this packet and move to the next. Keep track of discarded payload
    // types and SSRCs.
    discarded_pt_and_ssrc.emplace(first_rtp_header->payloadType,
                                  first_rtp_header->ssrc);
    input->PopPacket();
  }
  if (!discarded_pt_and_ssrc.empty()) {
    std::cout << "Discarded initial packets with the following payload types "
                 "and SSRCs:"
              << std::endl;
    for (const auto& d : discarded_pt_and_ssrc) {
      std::cout << "PT " << d.first << "; SSRC 0x" << std::hex
                << static_cast<int>(d.second) << std::dec << std::endl;
    }
  }
  if (!sample_rate_hz) {
    std::cerr << "Cannot find any packets with known payload types"
              << std::endl;
    return nullptr;
  }

  // If an output file is requested, open it.
  std::unique_ptr<AudioSink> output;
  if (!config.output_audio_filename.has_value()) {
    output = absl::make_unique<VoidAudioSink>();
    std::cout << "No output audio file" << std::endl;
  } else if (config.output_audio_filename->size() >= 4 &&
             config.output_audio_filename->substr(
                 config.output_audio_filename->size() - 4) == ".wav") {
    // Open a wav file with the known sample rate.
    output = absl::make_unique<OutputWavFile>(*config.output_audio_filename,
                                              *sample_rate_hz);
    std::cout << "Output WAV file: " << *config.output_audio_filename
              << std::endl;
  } else {
    // Open a pcm file.
    output = absl::make_unique<OutputAudioFile>(*config.output_audio_filename);
    std::cout << "Output PCM file: " << *config.output_audio_filename
              << std::endl;
  }

  NetEqTest::DecoderMap codecs = NetEqTest::StandardDecoderMap();

  rtc::scoped_refptr<AudioDecoderFactory> decoder_factory =
      CreateBuiltinAudioDecoderFactory();

  // Check if a replacement audio file was provided.
  if (config.replacement_audio_file.size() > 0) {
    // Find largest unused payload type.
    int replacement_pt = 127;
    while (codecs.find(replacement_pt) != codecs.end()) {
      --replacement_pt;
      if (replacement_pt <= 0) {
        std::cerr << "Error: Unable to find available replacement payload type"
                  << std::endl;
        return nullptr;
      }
    }

    auto std_set_int32_to_uint8 = [](const std::set<int32_t>& a) {
      std::set<uint8_t> b;
      for (auto& x : a) {
        b.insert(static_cast<uint8_t>(x));
      }
      return b;
    };

    std::set<uint8_t> cn_types = std_set_int32_to_uint8(
        {config.cn_nb, config.cn_wb, config.cn_swb32, config.cn_swb48});
    std::set<uint8_t> forbidden_types =
        std_set_int32_to_uint8({config.g722, config.red, config.avt,
                                config.avt_16, config.avt_32, config.avt_48});
    input.reset(new NetEqReplacementInput(std::move(input), replacement_pt,
                                          cn_types, forbidden_types));

    // Note that capture-by-copy implies that the lambda captures the value of
    // decoder_factory before it's reassigned on the left-hand side.
    decoder_factory = new rtc::RefCountedObject<FunctionAudioDecoderFactory>(
        [decoder_factory, config](
            const SdpAudioFormat& format,
            absl::optional<AudioCodecPairId> codec_pair_id) {
          std::unique_ptr<AudioDecoder> decoder =
              decoder_factory->MakeAudioDecoder(format, codec_pair_id);
          if (!decoder && format.name == "replacement") {
            decoder = absl::make_unique<FakeDecodeFromFile>(
                absl::make_unique<InputAudioFile>(
                    config.replacement_audio_file),
                format.clockrate_hz, format.num_channels > 1);
          }
          return decoder;
        });

    if (!codecs
             .insert({replacement_pt, SdpAudioFormat("replacement", 48000, 1)})
             .second) {
      std::cerr << "Error: Unable to insert replacement audio codec"
                << std::endl;
      return nullptr;
    }
  }

  // Create a text log file if needed.
  std::unique_ptr<std::ofstream> text_log;
  if (config.textlog_filename.has_value()) {
    text_log = absl::make_unique<std::ofstream>(*config.textlog_filename);
  }

  NetEqTest::Callbacks callbacks;
  stats_plotter_ = absl::make_unique<NetEqStatsPlotter>(
      config.matlabplot, config.pythonplot, config.concealment_events,
      config.plot_scripts_basename.value_or(""));

  ssrc_switch_detector_.reset(
      new SsrcSwitchDetector(stats_plotter_->stats_getter()->delay_analyzer()));
  callbacks.post_insert_packet = ssrc_switch_detector_.get();
  callbacks.get_audio_callback = stats_plotter_->stats_getter();
  callbacks.simulation_ended_callback = stats_plotter_.get();
  NetEq::Config neteq_config;
  neteq_config.sample_rate_hz = *sample_rate_hz;
  neteq_config.max_packets_in_buffer = config.max_nr_packets_in_buffer;
  neteq_config.enable_fast_accelerate = config.enable_fast_accelerate;
  return absl::make_unique<NetEqTest>(neteq_config, decoder_factory, codecs,
                                      std::move(text_log), std::move(input),
                                      std::move(output), callbacks);
}

}  // namespace test
}  // namespace webrtc
