/*
 *  Copyright (c) 2017 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 "api/video_codecs/video_encoder.h"

#include <algorithm>
#include <cstdint>
#include <cstring>
#include <optional>
#include <string>
#include <tuple>
#include <vector>

#include "absl/container/inlined_vector.h"
#include "api/fec_controller_override.h"
#include "api/units/data_rate.h"
#include "api/video/video_bitrate_allocation.h"
#include "api/video/video_codec_constants.h"
#include "api/video/video_frame_buffer.h"
#include "api/video_codecs/video_codec.h"
#include "rtc_base/checks.h"
#include "rtc_base/strings/string_builder.h"

namespace webrtc {

// TODO(mflodman): Add default complexity for VP9 and VP9.
VideoCodecVP8 VideoEncoder::GetDefaultVp8Settings() {
  VideoCodecVP8 vp8_settings;
  memset(&vp8_settings, 0, sizeof(vp8_settings));

  vp8_settings.numberOfTemporalLayers = 1;
  vp8_settings.denoisingOn = true;
  vp8_settings.automaticResizeOn = false;
  vp8_settings.keyFrameInterval = 3000;

  return vp8_settings;
}

VideoCodecVP9 VideoEncoder::GetDefaultVp9Settings() {
  VideoCodecVP9 vp9_settings;
  memset(&vp9_settings, 0, sizeof(vp9_settings));

  vp9_settings.numberOfTemporalLayers = 1;
  vp9_settings.denoisingOn = true;
  vp9_settings.keyFrameInterval = 3000;
  vp9_settings.adaptiveQpMode = true;
  vp9_settings.automaticResizeOn = true;
  vp9_settings.numberOfSpatialLayers = 1;
  vp9_settings.flexibleMode = false;
  vp9_settings.interLayerPred = InterLayerPredMode::kOn;

  return vp9_settings;
}

VideoCodecH264 VideoEncoder::GetDefaultH264Settings() {
  VideoCodecH264 h264_settings;
  memset(&h264_settings, 0, sizeof(h264_settings));

  h264_settings.keyFrameInterval = 3000;
  h264_settings.numberOfTemporalLayers = 1;

  return h264_settings;
}

VideoEncoder::ScalingSettings::ScalingSettings() = default;

VideoEncoder::ScalingSettings::ScalingSettings(KOff) : ScalingSettings() {}

VideoEncoder::ScalingSettings::ScalingSettings(int low, int high)
    : thresholds(QpThresholds(low, high)) {}

VideoEncoder::ScalingSettings::ScalingSettings(int low,
                                               int high,
                                               int min_pixels)
    : thresholds(QpThresholds(low, high)), min_pixels_per_frame(min_pixels) {}

VideoEncoder::ScalingSettings::ScalingSettings(const ScalingSettings&) =
    default;

VideoEncoder::ScalingSettings::~ScalingSettings() {}

bool VideoEncoder::ResolutionBitrateLimits::operator==(
    const ResolutionBitrateLimits& rhs) const {
  return frame_size_pixels == rhs.frame_size_pixels &&
         min_start_bitrate_bps == rhs.min_start_bitrate_bps &&
         min_bitrate_bps == rhs.min_bitrate_bps &&
         max_bitrate_bps == rhs.max_bitrate_bps;
}

VideoEncoder::EncoderInfo::EncoderInfo()
    : scaling_settings(VideoEncoder::ScalingSettings::kOff),
      requested_resolution_alignment(1),
      apply_alignment_to_all_simulcast_layers(false),
      supports_native_handle(false),
      implementation_name("unknown"),
      has_trusted_rate_controller(false),
      is_hardware_accelerated(true),
      enable_cpu_overuse_detection(true),
      fps_allocation{absl::InlinedVector<uint8_t, kMaxTemporalStreams>(
          1,
          kMaxFramerateFraction)},
      supports_simulcast(false),
      preferred_pixel_formats{VideoFrameBuffer::Type::kI420} {}

VideoEncoder::EncoderInfo::EncoderInfo(const EncoderInfo&) = default;

VideoEncoder::EncoderInfo::~EncoderInfo() = default;

std::string VideoEncoder::EncoderInfo::ToString() const {
  StringBuilder oss;
  oss << "EncoderInfo { "
         "ScalingSettings { ";
  if (scaling_settings.thresholds) {
    oss << "Thresholds { "
           "low = "
        << scaling_settings.thresholds->low
        << ", high = " << scaling_settings.thresholds->high << "}, ";
  }
  oss << "min_pixels_per_frame = " << scaling_settings.min_pixels_per_frame
      << " }";
  oss << ", requested_resolution_alignment = " << requested_resolution_alignment
      << ", apply_alignment_to_all_simulcast_layers = "
      << apply_alignment_to_all_simulcast_layers
      << ", supports_native_handle = " << supports_native_handle
      << ", implementation_name = '" << implementation_name
      << "'"
         ", has_trusted_rate_controller = "
      << has_trusted_rate_controller
      << ", is_hardware_accelerated = " << is_hardware_accelerated
      << ", enable_cpu_overuse_detection = " << enable_cpu_overuse_detection
      << ", fps_allocation = [";
  size_t num_spatial_layer_with_fps_allocation = 0;
  for (size_t i = 0; i < kMaxSpatialLayers; ++i) {
    if (!fps_allocation[i].empty()) {
      num_spatial_layer_with_fps_allocation = i + 1;
    }
  }
  bool first = true;
  for (size_t i = 0; i < num_spatial_layer_with_fps_allocation; ++i) {
    if (fps_allocation[i].empty()) {
      break;
    }
    if (!first) {
      oss << ", ";
    }
    const absl::InlinedVector<uint8_t, kMaxTemporalStreams>& fractions =
        fps_allocation[i];
    if (!fractions.empty()) {
      first = false;
      oss << "[ ";
      for (size_t j = 0; j < fractions.size(); ++j) {
        if (j > 0) {
          oss << ", ";
        }
        oss << (static_cast<double>(fractions[j]) / kMaxFramerateFraction);
      }
      oss << "] ";
    }
  }
  oss << "]";
  oss << ", resolution_bitrate_limits = [";
  for (size_t i = 0; i < resolution_bitrate_limits.size(); ++i) {
    if (i > 0) {
      oss << ", ";
    }
    ResolutionBitrateLimits l = resolution_bitrate_limits[i];
    oss << "Limits { "
           "frame_size_pixels = "
        << l.frame_size_pixels
        << ", min_start_bitrate_bps = " << l.min_start_bitrate_bps
        << ", min_bitrate_bps = " << l.min_bitrate_bps
        << ", max_bitrate_bps = " << l.max_bitrate_bps << "} ";
  }
  oss << "] "
         ", supports_simulcast = "
      << supports_simulcast;
  oss << ", preferred_pixel_formats = [";
  for (size_t i = 0; i < preferred_pixel_formats.size(); ++i) {
    if (i > 0)
      oss << ", ";
    oss << VideoFrameBufferTypeToString(preferred_pixel_formats.at(i));
  }
  oss << "]";
  if (is_qp_trusted.has_value()) {
    oss << ", is_qp_trusted = " << is_qp_trusted.value();
  }
  if (max_pixels_per_frame.has_value()) {
    oss << ", max_pixels_per_frame = " << max_pixels_per_frame.value();
  }
  if (mapped_resolution.has_value()) {
    oss << ", mapped_resolution = " << mapped_resolution->width << " x "
        << mapped_resolution->height;
  }
  oss << "}";
  return oss.str();
}

bool VideoEncoder::EncoderInfo::operator==(const EncoderInfo& rhs) const {
  if (scaling_settings.thresholds.has_value() !=
      rhs.scaling_settings.thresholds.has_value()) {
    return false;
  }
  if (scaling_settings.thresholds.has_value()) {
    QpThresholds l = *scaling_settings.thresholds;
    QpThresholds r = *rhs.scaling_settings.thresholds;
    if (l.low != r.low || l.high != r.high) {
      return false;
    }
  }
  if (scaling_settings.min_pixels_per_frame !=
      rhs.scaling_settings.min_pixels_per_frame) {
    return false;
  }

  if (supports_native_handle != rhs.supports_native_handle ||
      implementation_name != rhs.implementation_name ||
      has_trusted_rate_controller != rhs.has_trusted_rate_controller ||
      is_hardware_accelerated != rhs.is_hardware_accelerated ||
      enable_cpu_overuse_detection != rhs.enable_cpu_overuse_detection ||
      max_pixels_per_frame != rhs.max_pixels_per_frame) {
    return false;
  }

  for (size_t i = 0; i < kMaxSpatialLayers; ++i) {
    if (fps_allocation[i] != rhs.fps_allocation[i]) {
      return false;
    }
  }

  if (resolution_bitrate_limits != rhs.resolution_bitrate_limits ||
      supports_simulcast != rhs.supports_simulcast) {
    return false;
  }

  return true;
}

std::optional<VideoEncoder::ResolutionBitrateLimits>
VideoEncoder::EncoderInfo::GetEncoderBitrateLimitsForResolution(
    int frame_size_pixels) const {
  std::vector<ResolutionBitrateLimits> bitrate_limits =
      resolution_bitrate_limits;

  // Sort the list of bitrate limits by resolution.
  sort(bitrate_limits.begin(), bitrate_limits.end(),
       [](const ResolutionBitrateLimits& lhs,
          const ResolutionBitrateLimits& rhs) {
         return lhs.frame_size_pixels < rhs.frame_size_pixels;
       });

  for (size_t i = 0; i < bitrate_limits.size(); ++i) {
    RTC_DCHECK_GE(bitrate_limits[i].min_bitrate_bps, 0);
    RTC_DCHECK_GE(bitrate_limits[i].min_start_bitrate_bps, 0);
    RTC_DCHECK_GE(bitrate_limits[i].max_bitrate_bps,
                  bitrate_limits[i].min_bitrate_bps);
    if (i > 0) {
      // The bitrate limits aren't expected to decrease with resolution.
      RTC_DCHECK_GE(bitrate_limits[i].min_bitrate_bps,
                    bitrate_limits[i - 1].min_bitrate_bps);
      RTC_DCHECK_GE(bitrate_limits[i].min_start_bitrate_bps,
                    bitrate_limits[i - 1].min_start_bitrate_bps);
      RTC_DCHECK_GE(bitrate_limits[i].max_bitrate_bps,
                    bitrate_limits[i - 1].max_bitrate_bps);
    }

    if (bitrate_limits[i].frame_size_pixels >= frame_size_pixels) {
      return std::optional<ResolutionBitrateLimits>(bitrate_limits[i]);
    }
  }

  return std::nullopt;
}

VideoEncoder::RateControlParameters::RateControlParameters()
    : bitrate(VideoBitrateAllocation()),
      framerate_fps(0.0),
      bandwidth_allocation(DataRate::Zero()) {}

VideoEncoder::RateControlParameters::RateControlParameters(
    const VideoBitrateAllocation& bitrate,
    double framerate_fps)
    : bitrate(bitrate),
      framerate_fps(framerate_fps),
      bandwidth_allocation(DataRate::BitsPerSec(bitrate.get_sum_bps())) {}

VideoEncoder::RateControlParameters::RateControlParameters(
    const VideoBitrateAllocation& bitrate,
    double framerate_fps,
    DataRate bandwidth_allocation)
    : bitrate(bitrate),
      framerate_fps(framerate_fps),
      bandwidth_allocation(bandwidth_allocation) {}

bool VideoEncoder::RateControlParameters::operator==(
    const VideoEncoder::RateControlParameters& rhs) const {
  return std::tie(bitrate, framerate_fps, bandwidth_allocation) ==
         std::tie(rhs.bitrate, rhs.framerate_fps, rhs.bandwidth_allocation);
}

bool VideoEncoder::RateControlParameters::operator!=(
    const VideoEncoder::RateControlParameters& rhs) const {
  return !(rhs == *this);
}

VideoEncoder::RateControlParameters::~RateControlParameters() = default;

void VideoEncoder::SetFecControllerOverride(
    FecControllerOverride* /* fec_controller_override */) {}

int32_t VideoEncoder::InitEncode(const VideoCodec* codec_settings,
                                 int32_t number_of_cores,
                                 size_t max_payload_size) {
  const VideoEncoder::Capabilities capabilities(/* loss_notification= */ false);
  const VideoEncoder::Settings settings(capabilities, number_of_cores,
                                        max_payload_size);
  // In theory, this and the other version of InitEncode() could end up calling
  // each other in a loop until we get a stack overflow.
  // In practice, any subclass of VideoEncoder would overload at least one
  // of these, and we have a TODO in the header file to make this pure virtual.
  return InitEncode(codec_settings, settings);
}

int VideoEncoder::InitEncode(const VideoCodec* codec_settings,
                             const VideoEncoder::Settings& settings) {
  // In theory, this and the other version of InitEncode() could end up calling
  // each other in a loop until we get a stack overflow.
  // In practice, any subclass of VideoEncoder would overload at least one
  // of these, and we have a TODO in the header file to make this pure virtual.
  return InitEncode(codec_settings, settings.number_of_cores,
                    settings.max_payload_size);
}

void VideoEncoder::OnPacketLossRateUpdate(float /* packet_loss_rate */) {}

void VideoEncoder::OnRttUpdate(int64_t /* rtt_ms */) {}

void VideoEncoder::OnLossNotification(
    const LossNotification& /* loss_notification */) {}

}  // namespace webrtc
