/*
 *  Copyright (c) 2019 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 "rtc_tools/rtp_generator/rtp_generator.h"

#include <algorithm>
#include <memory>
#include <utility>

#include "api/task_queue/default_task_queue_factory.h"
#include "api/test/create_frame_generator.h"
#include "api/video_codecs/video_decoder_factory_template.h"
#include "api/video_codecs/video_decoder_factory_template_dav1d_adapter.h"
#include "api/video_codecs/video_decoder_factory_template_libvpx_vp8_adapter.h"
#include "api/video_codecs/video_decoder_factory_template_libvpx_vp9_adapter.h"
#include "api/video_codecs/video_encoder.h"
#include "api/video_codecs/video_encoder_factory.h"
#include "api/video_codecs/video_encoder_factory_template.h"
#include "api/video_codecs/video_encoder_factory_template_libaom_av1_adapter.h"
#include "api/video_codecs/video_encoder_factory_template_libvpx_vp8_adapter.h"
#include "api/video_codecs/video_encoder_factory_template_libvpx_vp9_adapter.h"
#include "media/base/media_constants.h"
#include "rtc_base/strings/json.h"
#include "rtc_base/system/file_wrapper.h"
#include "rtc_base/thread.h"
#include "test/testsupport/file_utils.h"
#include "video/config/encoder_stream_factory.h"
#include "video/config/video_encoder_config.h"

namespace webrtc {
namespace {

// Payload types.
constexpr int kPayloadTypeVp8 = 125;
constexpr int kPayloadTypeVp9 = 124;
constexpr int kPayloadTypeH264 = 123;
constexpr int kFakeVideoSendPayloadType = 122;

// Defaults
constexpr int kDefaultSsrc = 1337;
constexpr int kMaxConfigBufferSize = 8192;

// Utility function to validate a correct codec type has been passed in.
bool IsValidCodecType(const std::string& codec_name) {
  return cricket::kVp8CodecName == codec_name ||
         cricket::kVp9CodecName == codec_name ||
         cricket::kH264CodecName == codec_name;
}

// Utility function to return some base payload type for a codec_name.
int GetDefaultTypeForPayloadName(const std::string& codec_name) {
  if (cricket::kVp8CodecName == codec_name) {
    return kPayloadTypeVp8;
  }
  if (cricket::kVp9CodecName == codec_name) {
    return kPayloadTypeVp9;
  }
  if (cricket::kH264CodecName == codec_name) {
    return kPayloadTypeH264;
  }
  return kFakeVideoSendPayloadType;
}

// Creates a single VideoSendStream configuration.
absl::optional<RtpGeneratorOptions::VideoSendStreamConfig>
ParseVideoSendStreamConfig(const Json::Value& json) {
  RtpGeneratorOptions::VideoSendStreamConfig config;

  // Parse video source settings.
  if (!rtc::GetIntFromJsonObject(json, "duration_ms", &config.duration_ms)) {
    RTC_LOG(LS_WARNING) << "duration_ms not specified using default: "
                        << config.duration_ms;
  }
  if (!rtc::GetIntFromJsonObject(json, "video_width", &config.video_width)) {
    RTC_LOG(LS_WARNING) << "video_width not specified using default: "
                        << config.video_width;
  }
  if (!rtc::GetIntFromJsonObject(json, "video_height", &config.video_height)) {
    RTC_LOG(LS_WARNING) << "video_height not specified using default: "
                        << config.video_height;
  }
  if (!rtc::GetIntFromJsonObject(json, "video_fps", &config.video_fps)) {
    RTC_LOG(LS_WARNING) << "video_fps not specified using default: "
                        << config.video_fps;
  }
  if (!rtc::GetIntFromJsonObject(json, "num_squares", &config.num_squares)) {
    RTC_LOG(LS_WARNING) << "num_squares not specified using default: "
                        << config.num_squares;
  }

  // Parse RTP settings for this configuration.
  config.rtp.ssrcs.push_back(kDefaultSsrc);
  Json::Value rtp_json;
  if (!rtc::GetValueFromJsonObject(json, "rtp", &rtp_json)) {
    RTC_LOG(LS_ERROR) << "video_streams must have an rtp section";
    return absl::nullopt;
  }
  if (!rtc::GetStringFromJsonObject(rtp_json, "payload_name",
                                    &config.rtp.payload_name)) {
    RTC_LOG(LS_ERROR) << "rtp.payload_name must be specified";
    return absl::nullopt;
  }
  if (!IsValidCodecType(config.rtp.payload_name)) {
    RTC_LOG(LS_ERROR) << "rtp.payload_name must be VP8,VP9 or H264";
    return absl::nullopt;
  }

  config.rtp.payload_type =
      GetDefaultTypeForPayloadName(config.rtp.payload_name);
  if (!rtc::GetIntFromJsonObject(rtp_json, "payload_type",
                                 &config.rtp.payload_type)) {
    RTC_LOG(LS_WARNING)
        << "rtp.payload_type not specified using default for codec type"
        << config.rtp.payload_type;
  }

  return config;
}

}  // namespace

absl::optional<RtpGeneratorOptions> ParseRtpGeneratorOptionsFromFile(
    const std::string& options_file) {
  if (!test::FileExists(options_file)) {
    RTC_LOG(LS_ERROR) << " configuration file does not exist";
    return absl::nullopt;
  }

  // Read the configuration file from disk.
  FileWrapper config_file = FileWrapper::OpenReadOnly(options_file);
  std::vector<char> raw_json_buffer(kMaxConfigBufferSize, 0);
  size_t bytes_read =
      config_file.Read(raw_json_buffer.data(), raw_json_buffer.size() - 1);
  if (bytes_read == 0) {
    RTC_LOG(LS_ERROR) << "Unable to read the configuration file.";
    return absl::nullopt;
  }

  // Parse the file as JSON
  Json::CharReaderBuilder builder;
  Json::Value json;
  std::string error_message;
  std::unique_ptr<Json::CharReader> json_reader(builder.newCharReader());
  if (!json_reader->parse(raw_json_buffer.data(),
                          raw_json_buffer.data() + raw_json_buffer.size(),
                          &json, &error_message)) {
    RTC_LOG(LS_ERROR) << "Unable to parse the corpus config json file. Error:"
                      << error_message;
    return absl::nullopt;
  }

  RtpGeneratorOptions gen_options;
  for (const auto& video_stream_json : json["video_streams"]) {
    absl::optional<RtpGeneratorOptions::VideoSendStreamConfig>
        video_stream_config = ParseVideoSendStreamConfig(video_stream_json);
    if (!video_stream_config.has_value()) {
      RTC_LOG(LS_ERROR) << "Unable to parse the corpus config json file";
      return absl::nullopt;
    }
    gen_options.video_streams.push_back(*video_stream_config);
  }
  return gen_options;
}

RtpGenerator::RtpGenerator(const RtpGeneratorOptions& options)
    : options_(options),
      video_encoder_factory_(
          std::make_unique<webrtc::VideoEncoderFactoryTemplate<
              webrtc::LibvpxVp8EncoderTemplateAdapter,
              webrtc::LibvpxVp9EncoderTemplateAdapter,
              webrtc::LibaomAv1EncoderTemplateAdapter>>()),
      video_decoder_factory_(
          std::make_unique<webrtc::VideoDecoderFactoryTemplate<
              webrtc::LibvpxVp8DecoderTemplateAdapter,
              webrtc::LibvpxVp9DecoderTemplateAdapter,
              webrtc::Dav1dDecoderTemplateAdapter>>()),
      video_bitrate_allocator_factory_(
          CreateBuiltinVideoBitrateAllocatorFactory()),
      event_log_(std::make_unique<RtcEventLogNull>()),
      call_(Call::Create(CallConfig(event_log_.get()))),
      task_queue_(CreateDefaultTaskQueueFactory()) {
  constexpr int kMinBitrateBps = 30000;    // 30 Kbps
  constexpr int kMaxBitrateBps = 2500000;  // 2.5 Mbps

  int stream_count = 0;
  webrtc::VideoEncoder::EncoderInfo encoder_info;
  for (const auto& send_config : options.video_streams) {
    webrtc::VideoSendStream::Config video_config(this);
    video_config.encoder_settings.encoder_factory =
        video_encoder_factory_.get();
    video_config.encoder_settings.bitrate_allocator_factory =
        video_bitrate_allocator_factory_.get();
    video_config.rtp = send_config.rtp;
    // Update some required to be unique values.
    stream_count++;
    video_config.rtp.mid = "mid-" + std::to_string(stream_count);

    // Configure the video encoder configuration.
    VideoEncoderConfig encoder_config;
    encoder_config.content_type =
        VideoEncoderConfig::ContentType::kRealtimeVideo;
    encoder_config.codec_type =
        PayloadStringToCodecType(video_config.rtp.payload_name);
    if (video_config.rtp.payload_name == cricket::kVp8CodecName) {
      VideoCodecVP8 settings = VideoEncoder::GetDefaultVp8Settings();
      encoder_config.encoder_specific_settings =
          rtc::make_ref_counted<VideoEncoderConfig::Vp8EncoderSpecificSettings>(
              settings);
    } else if (video_config.rtp.payload_name == cricket::kVp9CodecName) {
      VideoCodecVP9 settings = VideoEncoder::GetDefaultVp9Settings();
      encoder_config.encoder_specific_settings =
          rtc::make_ref_counted<VideoEncoderConfig::Vp9EncoderSpecificSettings>(
              settings);
    } else if (video_config.rtp.payload_name == cricket::kH264CodecName) {
      encoder_config.encoder_specific_settings = nullptr;
    }
    encoder_config.video_format.name = video_config.rtp.payload_name;
    encoder_config.min_transmit_bitrate_bps = 0;
    encoder_config.max_bitrate_bps = kMaxBitrateBps;
    encoder_config.content_type =
        VideoEncoderConfig::ContentType::kRealtimeVideo;

    // Configure the simulcast layers.
    encoder_config.number_of_streams = video_config.rtp.ssrcs.size();
    encoder_config.bitrate_priority = 1.0;
    encoder_config.simulcast_layers.resize(encoder_config.number_of_streams);
    for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
      encoder_config.simulcast_layers[i].active = true;
      encoder_config.simulcast_layers[i].min_bitrate_bps = kMinBitrateBps;
      encoder_config.simulcast_layers[i].max_bitrate_bps = kMaxBitrateBps;
      encoder_config.simulcast_layers[i].max_framerate = send_config.video_fps;
    }

    encoder_config.video_stream_factory =
        rtc::make_ref_counted<cricket::EncoderStreamFactory>(
            video_config.rtp.payload_name, /*max qp*/ 56, /*screencast*/ false,
            /*screenshare enabled*/ false, encoder_info);

    // Setup the fake video stream for this.
    std::unique_ptr<test::FrameGeneratorCapturer> frame_generator =
        std::make_unique<test::FrameGeneratorCapturer>(
            Clock::GetRealTimeClock(),
            test::CreateSquareFrameGenerator(send_config.video_width,
                                             send_config.video_height,
                                             absl::nullopt, absl::nullopt),
            send_config.video_fps, *task_queue_);
    frame_generator->Init();

    VideoSendStream* video_send_stream = call_->CreateVideoSendStream(
        std::move(video_config), std::move(encoder_config));
    video_send_stream->SetSource(
        frame_generator.get(),
        webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
    // Store these objects so we can destropy them at the end.
    frame_generators_.push_back(std::move(frame_generator));
    video_send_streams_.push_back(video_send_stream);
  }
}

RtpGenerator::~RtpGenerator() {
  for (VideoSendStream* send_stream : video_send_streams_) {
    call_->DestroyVideoSendStream(send_stream);
  }
}

void RtpGenerator::GenerateRtpDump(const std::string& rtp_dump_path) {
  rtp_dump_writer_.reset(test::RtpFileWriter::Create(
      test::RtpFileWriter::kRtpDump, rtp_dump_path));

  call_->SignalChannelNetworkState(webrtc::MediaType::VIDEO,
                                   webrtc::kNetworkUp);
  for (VideoSendStream* send_stream : video_send_streams_) {
    send_stream->Start();
  }

  // Spinlock until all the durations end.
  WaitUntilAllVideoStreamsFinish();

  call_->SignalChannelNetworkState(webrtc::MediaType::VIDEO,
                                   webrtc::kNetworkDown);
}

bool RtpGenerator::SendRtp(rtc::ArrayView<const uint8_t> packet,
                           const webrtc::PacketOptions& options) {
  test::RtpPacket rtp_packet = DataToRtpPacket(packet.data(), packet.size());
  rtp_dump_writer_->WritePacket(&rtp_packet);
  return true;
}

bool RtpGenerator::SendRtcp(rtc::ArrayView<const uint8_t> packet) {
  test::RtpPacket rtcp_packet = DataToRtpPacket(packet.data(), packet.size());
  rtp_dump_writer_->WritePacket(&rtcp_packet);
  return true;
}

int RtpGenerator::GetMaxDuration() const {
  int max_end_ms = 0;
  for (const auto& video_stream : options_.video_streams) {
    max_end_ms = std::max(video_stream.duration_ms, max_end_ms);
  }
  return max_end_ms;
}

void RtpGenerator::WaitUntilAllVideoStreamsFinish() {
  // Find the maximum duration required by the streams.
  start_ms_ = Clock::GetRealTimeClock()->TimeInMilliseconds();
  int64_t max_end_ms = start_ms_ + GetMaxDuration();

  int64_t current_time = 0;
  do {
    int64_t min_wait_time = 0;
    current_time = Clock::GetRealTimeClock()->TimeInMilliseconds();
    // Stop any streams that are no longer active.
    for (size_t i = 0; i < options_.video_streams.size(); ++i) {
      const int64_t end_ms = start_ms_ + options_.video_streams[i].duration_ms;
      if (current_time > end_ms) {
        video_send_streams_[i]->Stop();
      } else {
        min_wait_time = std::min(min_wait_time, end_ms - current_time);
      }
    }
    rtc::Thread::Current()->SleepMs(min_wait_time);
  } while (current_time < max_end_ms);
}

test::RtpPacket RtpGenerator::DataToRtpPacket(const uint8_t* packet,
                                              size_t packet_len) {
  webrtc::test::RtpPacket rtp_packet;
  memcpy(rtp_packet.data, packet, packet_len);
  rtp_packet.length = packet_len;
  rtp_packet.original_length = packet_len;
  rtp_packet.time_ms =
      webrtc::Clock::GetRealTimeClock()->TimeInMilliseconds() - start_ms_;
  return rtp_packet;
}

}  // namespace webrtc
