/*
 *  Copyright (c) 2016 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 "webrtc/modules/video_coding/protection_bitrate_calculator.h"

namespace webrtc {

using rtc::CritScope;

struct ProtectionBitrateCalculator::EncodedFrameSample {
  EncodedFrameSample(size_t size_bytes,
                     uint32_t timestamp,
                     int64_t time_complete_ms)
      : size_bytes(size_bytes),
        timestamp(timestamp),
        time_complete_ms(time_complete_ms) {}
  size_t size_bytes;
  uint32_t timestamp;
  int64_t time_complete_ms;
};

ProtectionBitrateCalculator::ProtectionBitrateCalculator(
    Clock* clock,
    VCMProtectionCallback* protection_callback)
    : clock_(clock),
      protection_callback_(protection_callback),
      loss_prot_logic_(new media_optimization::VCMLossProtectionLogic(
          clock_->TimeInMilliseconds())),
      max_payload_size_(1460) {}

ProtectionBitrateCalculator::~ProtectionBitrateCalculator(void) {
  loss_prot_logic_->Release();
}

void ProtectionBitrateCalculator::SetEncodingData(size_t width,
                                                  size_t height,
                                                  size_t num_temporal_layers,
                                                  size_t max_payload_size) {
  CritScope lock(&crit_sect_);
  loss_prot_logic_->UpdateFrameSize(width, height);
  loss_prot_logic_->UpdateNumLayers(num_temporal_layers);
  max_payload_size_ = max_payload_size;
}

uint32_t ProtectionBitrateCalculator::SetTargetRates(
    uint32_t estimated_bitrate_bps,
    int actual_framerate_fps,
    uint8_t fraction_lost,
    int64_t round_trip_time_ms) {
  float target_bitrate_kbps =
      static_cast<float>(estimated_bitrate_bps) / 1000.0f;
  // Sanity check.
  if (actual_framerate_fps < 1.0) {
    actual_framerate_fps = 1.0;
  }

  FecProtectionParams delta_fec_params;
  FecProtectionParams key_fec_params;
  {
    CritScope lock(&crit_sect_);

    loss_prot_logic_->UpdateBitRate(target_bitrate_kbps);
    loss_prot_logic_->UpdateRtt(round_trip_time_ms);

    // Update frame rate for the loss protection logic class: frame rate should
    // be the actual/sent rate.
    loss_prot_logic_->UpdateFrameRate(actual_framerate_fps);

    // Returns the filtered packet loss, used for the protection setting.
    // The filtered loss may be the received loss (no filter), or some
    // filtered value (average or max window filter).
    // Use max window filter for now.
    media_optimization::FilterPacketLossMode filter_mode =
        media_optimization::kMaxFilter;
    uint8_t packet_loss_enc = loss_prot_logic_->FilteredLoss(
        clock_->TimeInMilliseconds(), filter_mode, fraction_lost);

    // For now use the filtered loss for computing the robustness settings.
    loss_prot_logic_->UpdateFilteredLossPr(packet_loss_enc);

    if (loss_prot_logic_->SelectedType() == media_optimization::kNone) {
      return estimated_bitrate_bps;
    }

    // Update method will compute the robustness settings for the given
    // protection method and the overhead cost
    // the protection method is set by the user via SetVideoProtection.
    loss_prot_logic_->UpdateMethod();

    // Get the bit cost of protection method, based on the amount of
    // overhead data actually transmitted (including headers) the last
    // second.

    // Get the FEC code rate for Key frames (set to 0 when NA).
    key_fec_params.fec_rate =
        loss_prot_logic_->SelectedMethod()->RequiredProtectionFactorK();

    // Get the FEC code rate for Delta frames (set to 0 when NA).
    delta_fec_params.fec_rate =
        loss_prot_logic_->SelectedMethod()->RequiredProtectionFactorD();

    // The RTP module currently requires the same |max_fec_frames| for both
    // key and delta frames.
    delta_fec_params.max_fec_frames =
        loss_prot_logic_->SelectedMethod()->MaxFramesFec();
    key_fec_params.max_fec_frames =
        loss_prot_logic_->SelectedMethod()->MaxFramesFec();
  }

  // Set the FEC packet mask type. |kFecMaskBursty| is more effective for
  // consecutive losses and little/no packet re-ordering. As we currently
  // do not have feedback data on the degree of correlated losses and packet
  // re-ordering, we keep default setting to |kFecMaskRandom| for now.
  delta_fec_params.fec_mask_type = kFecMaskRandom;
  key_fec_params.fec_mask_type = kFecMaskRandom;

  // Update protection callback with protection settings.
  uint32_t sent_video_rate_bps = 0;
  uint32_t sent_nack_rate_bps = 0;
  uint32_t sent_fec_rate_bps = 0;
  // Rate cost of the protection methods.
  float protection_overhead_rate = 0.0f;

  // TODO(Marco): Pass FEC protection values per layer.
  protection_callback_->ProtectionRequest(
      &delta_fec_params, &key_fec_params, &sent_video_rate_bps,
      &sent_nack_rate_bps, &sent_fec_rate_bps);

  uint32_t sent_total_rate_bps =
      sent_video_rate_bps + sent_nack_rate_bps + sent_fec_rate_bps;
  // Estimate the overhead costs of the next second as staying the same
  // wrt the source bitrate.
  if (sent_total_rate_bps > 0) {
    protection_overhead_rate =
        static_cast<float>(sent_nack_rate_bps + sent_fec_rate_bps) /
        sent_total_rate_bps;
  }
  // Cap the overhead estimate to 50%.
  if (protection_overhead_rate > 0.5)
    protection_overhead_rate = 0.5;

  // Source coding rate: total rate - protection overhead.
  return estimated_bitrate_bps * (1.0 - protection_overhead_rate);
}

void ProtectionBitrateCalculator::SetProtectionMethod(bool enable_fec,
                                                      bool enable_nack) {
  media_optimization::VCMProtectionMethodEnum method(media_optimization::kNone);
  if (enable_fec && enable_nack) {
    method = media_optimization::kNackFec;
  } else if (enable_nack) {
    method = media_optimization::kNack;
  } else if (enable_fec) {
    method = media_optimization::kFec;
  }
  CritScope lock(&crit_sect_);
  loss_prot_logic_->SetMethod(method);
}

void ProtectionBitrateCalculator::UpdateWithEncodedData(
    const EncodedImage& encoded_image) {
  const size_t encoded_length = encoded_image._length;
  CritScope lock(&crit_sect_);
  if (encoded_length > 0) {
    const bool delta_frame = encoded_image._frameType != kVideoFrameKey;

    if (max_payload_size_ > 0 && encoded_length > 0) {
      const float min_packets_per_frame =
          encoded_length / static_cast<float>(max_payload_size_);
      if (delta_frame) {
        loss_prot_logic_->UpdatePacketsPerFrame(min_packets_per_frame,
                                                clock_->TimeInMilliseconds());
      } else {
        loss_prot_logic_->UpdatePacketsPerFrameKey(
            min_packets_per_frame, clock_->TimeInMilliseconds());
      }
    }
    if (!delta_frame && encoded_length > 0) {
      loss_prot_logic_->UpdateKeyFrameSize(static_cast<float>(encoded_length));
    }
  }
}

}  // namespace webrtc
