/*
 *  Copyright (c) 2012 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/video_coding/media_opt_util.h"

#include <math.h>

#include <algorithm>

#include "modules/video_coding/fec_rate_table.h"
#include "modules/video_coding/internal_defines.h"
#include "modules/video_coding/utility/simulcast_rate_allocator.h"
#include "rtc_base/checks.h"
#include "rtc_base/experiments/rate_control_settings.h"
#include "rtc_base/numerics/safe_conversions.h"

namespace webrtc {
// Max value of loss rates in off-line model
static const int kPacketLossMax = 129;

namespace media_optimization {

VCMProtectionParameters::VCMProtectionParameters()
    : rtt(0),
      lossPr(0.0f),
      bitRate(0.0f),
      packetsPerFrame(0.0f),
      packetsPerFrameKey(0.0f),
      frameRate(0.0f),
      keyFrameSize(0.0f),
      fecRateDelta(0),
      fecRateKey(0),
      codecWidth(0),
      codecHeight(0),
      numLayers(1) {}

VCMProtectionMethod::VCMProtectionMethod()
    : _effectivePacketLoss(0),
      _protectionFactorK(0),
      _protectionFactorD(0),
      _scaleProtKey(2.0f),
      _maxPayloadSize(1460),
      _corrFecCost(1.0),
      _type(kNone) {}

VCMProtectionMethod::~VCMProtectionMethod() {}

enum VCMProtectionMethodEnum VCMProtectionMethod::Type() const {
  return _type;
}

uint8_t VCMProtectionMethod::RequiredPacketLossER() {
  return _effectivePacketLoss;
}

uint8_t VCMProtectionMethod::RequiredProtectionFactorK() {
  return _protectionFactorK;
}

uint8_t VCMProtectionMethod::RequiredProtectionFactorD() {
  return _protectionFactorD;
}

bool VCMProtectionMethod::RequiredUepProtectionK() {
  return _useUepProtectionK;
}

bool VCMProtectionMethod::RequiredUepProtectionD() {
  return _useUepProtectionD;
}

int VCMProtectionMethod::MaxFramesFec() const {
  return 1;
}

VCMNackFecMethod::VCMNackFecMethod(int64_t lowRttNackThresholdMs,
                                   int64_t highRttNackThresholdMs)
    : VCMFecMethod(),
      _lowRttNackMs(lowRttNackThresholdMs),
      _highRttNackMs(highRttNackThresholdMs),
      _maxFramesFec(1) {
  RTC_DCHECK(lowRttNackThresholdMs >= -1 && highRttNackThresholdMs >= -1);
  RTC_DCHECK(highRttNackThresholdMs == -1 ||
             lowRttNackThresholdMs <= highRttNackThresholdMs);
  RTC_DCHECK(lowRttNackThresholdMs > -1 || highRttNackThresholdMs == -1);
  _type = kNackFec;
}

VCMNackFecMethod::~VCMNackFecMethod() {
  //
}
bool VCMNackFecMethod::ProtectionFactor(
    const VCMProtectionParameters* parameters) {
  // Hybrid Nack FEC has three operational modes:
  // 1. Low RTT (below kLowRttNackMs) - Nack only: Set FEC rate
  //    (_protectionFactorD) to zero. -1 means no FEC.
  // 2. High RTT (above _highRttNackMs) - FEC Only: Keep FEC factors.
  //    -1 means always allow NACK.
  // 3. Medium RTT values - Hybrid mode: We will only nack the
  //    residual following the decoding of the FEC (refer to JB logic). FEC
  //    delta protection factor will be adjusted based on the RTT.

  // Otherwise: we count on FEC; if the RTT is below a threshold, then we
  // nack the residual, based on a decision made in the JB.

  // Compute the protection factors
  VCMFecMethod::ProtectionFactor(parameters);
  if (_lowRttNackMs == -1 || parameters->rtt < _lowRttNackMs) {
    _protectionFactorD = 0;
    VCMFecMethod::UpdateProtectionFactorD(_protectionFactorD);

    // When in Hybrid mode (RTT range), adjust FEC rates based on the
    // RTT (NACK effectiveness) - adjustment factor is in the range [0,1].
  } else if (_highRttNackMs == -1 || parameters->rtt < _highRttNackMs) {
    // TODO(mikhal): Disabling adjustment temporarily.
    // uint16_t rttIndex = (uint16_t) parameters->rtt;
    float adjustRtt = 1.0f;  // (float)VCMNackFecTable[rttIndex] / 100.0f;

    // Adjust FEC with NACK on (for delta frame only)
    // table depends on RTT relative to rttMax (NACK Threshold)
    _protectionFactorD = rtc::saturated_cast<uint8_t>(
        adjustRtt * rtc::saturated_cast<float>(_protectionFactorD));
    // update FEC rates after applying adjustment
    VCMFecMethod::UpdateProtectionFactorD(_protectionFactorD);
  }

  return true;
}

int VCMNackFecMethod::ComputeMaxFramesFec(
    const VCMProtectionParameters* parameters) {
  if (parameters->numLayers > 2) {
    // For more than 2 temporal layers we will only have FEC on the base layer,
    // and the base layers will be pretty far apart. Therefore we force one
    // frame FEC.
    return 1;
  }
  // We set the max number of frames to base the FEC on so that on average
  // we will have complete frames in one RTT. Note that this is an upper
  // bound, and that the actual number of frames used for FEC is decided by the
  // RTP module based on the actual number of packets and the protection factor.
  float base_layer_framerate =
      parameters->frameRate /
      rtc::saturated_cast<float>(1 << (parameters->numLayers - 1));
  int max_frames_fec = std::max(
      rtc::saturated_cast<int>(
          2.0f * base_layer_framerate * parameters->rtt / 1000.0f + 0.5f),
      1);
  // |kUpperLimitFramesFec| is the upper limit on how many frames we
  // allow any FEC to be based on.
  if (max_frames_fec > kUpperLimitFramesFec) {
    max_frames_fec = kUpperLimitFramesFec;
  }
  return max_frames_fec;
}

int VCMNackFecMethod::MaxFramesFec() const {
  return _maxFramesFec;
}

bool VCMNackFecMethod::BitRateTooLowForFec(
    const VCMProtectionParameters* parameters) {
  // Bitrate below which we turn off FEC, regardless of reported packet loss.
  // The condition should depend on resolution and content. For now, use
  // threshold on bytes per frame, with some effect for the frame size.
  // The condition for turning off FEC is also based on other factors,
  // such as |_numLayers|, |_maxFramesFec|, and |_rtt|.
  int estimate_bytes_per_frame = 1000 * BitsPerFrame(parameters) / 8;
  int max_bytes_per_frame = kMaxBytesPerFrameForFec;
  int num_pixels = parameters->codecWidth * parameters->codecHeight;
  if (num_pixels <= 352 * 288) {
    max_bytes_per_frame = kMaxBytesPerFrameForFecLow;
  } else if (num_pixels > 640 * 480) {
    max_bytes_per_frame = kMaxBytesPerFrameForFecHigh;
  }
  // TODO(marpan): add condition based on maximum frames used for FEC,
  // and expand condition based on frame size.
  // Max round trip time threshold in ms.
  const int64_t kMaxRttTurnOffFec = 200;
  if (estimate_bytes_per_frame < max_bytes_per_frame &&
      parameters->numLayers < 3 && parameters->rtt < kMaxRttTurnOffFec) {
    return true;
  }
  return false;
}

bool VCMNackFecMethod::EffectivePacketLoss(
    const VCMProtectionParameters* parameters) {
  // Set the effective packet loss for encoder (based on FEC code).
  // Compute the effective packet loss and residual packet loss due to FEC.
  VCMFecMethod::EffectivePacketLoss(parameters);
  return true;
}

bool VCMNackFecMethod::UpdateParameters(
    const VCMProtectionParameters* parameters) {
  ProtectionFactor(parameters);
  EffectivePacketLoss(parameters);
  _maxFramesFec = ComputeMaxFramesFec(parameters);
  if (BitRateTooLowForFec(parameters)) {
    _protectionFactorK = 0;
    _protectionFactorD = 0;
  }

  // Protection/fec rates obtained above are defined relative to total number
  // of packets (total rate: source + fec) FEC in RTP module assumes
  // protection factor is defined relative to source number of packets so we
  // should convert the factor to reduce mismatch between mediaOpt's rate and
  // the actual one
  _protectionFactorK = VCMFecMethod::ConvertFECRate(_protectionFactorK);
  _protectionFactorD = VCMFecMethod::ConvertFECRate(_protectionFactorD);

  return true;
}

VCMNackMethod::VCMNackMethod() : VCMProtectionMethod() {
  _type = kNack;
}

VCMNackMethod::~VCMNackMethod() {
  //
}

bool VCMNackMethod::EffectivePacketLoss(
    const VCMProtectionParameters* parameter) {
  // Effective Packet Loss, NA in current version.
  _effectivePacketLoss = 0;
  return true;
}

bool VCMNackMethod::UpdateParameters(
    const VCMProtectionParameters* parameters) {
  // Compute the effective packet loss
  EffectivePacketLoss(parameters);

  // nackCost  = (bitRate - nackCost) * (lossPr)
  return true;
}

VCMFecMethod::VCMFecMethod()
    : VCMProtectionMethod(),
      rate_control_settings_(RateControlSettings::ParseFromFieldTrials()) {
  _type = kFec;
}

VCMFecMethod::~VCMFecMethod() = default;

uint8_t VCMFecMethod::BoostCodeRateKey(uint8_t packetFrameDelta,
                                       uint8_t packetFrameKey) const {
  uint8_t boostRateKey = 2;
  // Default: ratio scales the FEC protection up for I frames
  uint8_t ratio = 1;

  if (packetFrameDelta > 0) {
    ratio = (int8_t)(packetFrameKey / packetFrameDelta);
  }
  ratio = VCM_MAX(boostRateKey, ratio);

  return ratio;
}

uint8_t VCMFecMethod::ConvertFECRate(uint8_t codeRateRTP) const {
  return rtc::saturated_cast<uint8_t>(
      VCM_MIN(255, (0.5 + 255.0 * codeRateRTP /
                              rtc::saturated_cast<float>(255 - codeRateRTP))));
}

// Update FEC with protectionFactorD
void VCMFecMethod::UpdateProtectionFactorD(uint8_t protectionFactorD) {
  _protectionFactorD = protectionFactorD;
}

// Update FEC with protectionFactorK
void VCMFecMethod::UpdateProtectionFactorK(uint8_t protectionFactorK) {
  _protectionFactorK = protectionFactorK;
}

bool VCMFecMethod::ProtectionFactor(const VCMProtectionParameters* parameters) {
  // FEC PROTECTION SETTINGS: varies with packet loss and bitrate

  // No protection if (filtered) packetLoss is 0
  uint8_t packetLoss = rtc::saturated_cast<uint8_t>(255 * parameters->lossPr);
  if (packetLoss == 0) {
    _protectionFactorK = 0;
    _protectionFactorD = 0;
    return true;
  }

  // Parameters for FEC setting:
  // first partition size, thresholds, table pars, spatial resoln fac.

  // First partition protection: ~ 20%
  uint8_t firstPartitionProt = rtc::saturated_cast<uint8_t>(255 * 0.20);

  // Minimum protection level needed to generate one FEC packet for one
  // source packet/frame (in RTP sender)
  uint8_t minProtLevelFec = 85;

  // Threshold on packetLoss and bitRrate/frameRate (=average #packets),
  // above which we allocate protection to cover at least first partition.
  uint8_t lossThr = 0;
  uint8_t packetNumThr = 1;

  // Parameters for range of rate index of table.
  const uint8_t ratePar1 = 5;
  const uint8_t ratePar2 = 49;

  // Spatial resolution size, relative to a reference size.
  float spatialSizeToRef = rtc::saturated_cast<float>(parameters->codecWidth *
                                                      parameters->codecHeight) /
                           (rtc::saturated_cast<float>(704 * 576));
  // resolnFac: This parameter will generally increase/decrease the FEC rate
  // (for fixed bitRate and packetLoss) based on system size.
  // Use a smaller exponent (< 1) to control/soften system size effect.
  const float resolnFac = 1.0 / powf(spatialSizeToRef, 0.3f);

  const int bitRatePerFrame = BitsPerFrame(parameters);

  // Average number of packets per frame (source and fec):
  const uint8_t avgTotPackets = rtc::saturated_cast<uint8_t>(
      1.5f + rtc::saturated_cast<float>(bitRatePerFrame) * 1000.0f /
                 rtc::saturated_cast<float>(8.0 * _maxPayloadSize));

  // FEC rate parameters: for P and I frame
  uint8_t codeRateDelta = 0;
  uint8_t codeRateKey = 0;

  // Get index for table: the FEC protection depends on an effective rate.
  // The range on the rate index corresponds to rates (bps)
  // from ~200k to ~8000k, for 30fps
  const uint16_t effRateFecTable =
      rtc::saturated_cast<uint16_t>(resolnFac * bitRatePerFrame);
  uint8_t rateIndexTable = rtc::saturated_cast<uint8_t>(
      VCM_MAX(VCM_MIN((effRateFecTable - ratePar1) / ratePar1, ratePar2), 0));

  // Restrict packet loss range to 50:
  // current tables defined only up to 50%
  if (packetLoss >= kPacketLossMax) {
    packetLoss = kPacketLossMax - 1;
  }
  uint16_t indexTable = rateIndexTable * kPacketLossMax + packetLoss;

  // Check on table index
  RTC_DCHECK_LT(indexTable, kFecRateTableSize);

  // Protection factor for P frame
  codeRateDelta = kFecRateTable[indexTable];

  if (packetLoss > lossThr && avgTotPackets > packetNumThr) {
    // Set a minimum based on first partition size.
    if (codeRateDelta < firstPartitionProt) {
      codeRateDelta = firstPartitionProt;
    }
  }

  // Check limit on amount of protection for P frame; 50% is max.
  if (codeRateDelta >= kPacketLossMax) {
    codeRateDelta = kPacketLossMax - 1;
  }

  // For Key frame:
  // Effectively at a higher rate, so we scale/boost the rate
  // The boost factor may depend on several factors: ratio of packet
  // number of I to P frames, how much protection placed on P frames, etc.
  const uint8_t packetFrameDelta =
      rtc::saturated_cast<uint8_t>(0.5 + parameters->packetsPerFrame);
  const uint8_t packetFrameKey =
      rtc::saturated_cast<uint8_t>(0.5 + parameters->packetsPerFrameKey);
  const uint8_t boostKey = BoostCodeRateKey(packetFrameDelta, packetFrameKey);

  rateIndexTable = rtc::saturated_cast<uint8_t>(VCM_MAX(
      VCM_MIN(1 + (boostKey * effRateFecTable - ratePar1) / ratePar1, ratePar2),
      0));
  uint16_t indexTableKey = rateIndexTable * kPacketLossMax + packetLoss;

  indexTableKey = VCM_MIN(indexTableKey, kFecRateTableSize);

  // Check on table index
  RTC_DCHECK_LT(indexTableKey, kFecRateTableSize);

  // Protection factor for I frame
  codeRateKey = kFecRateTable[indexTableKey];

  // Boosting for Key frame.
  int boostKeyProt = _scaleProtKey * codeRateDelta;
  if (boostKeyProt >= kPacketLossMax) {
    boostKeyProt = kPacketLossMax - 1;
  }

  // Make sure I frame protection is at least larger than P frame protection,
  // and at least as high as filtered packet loss.
  codeRateKey = rtc::saturated_cast<uint8_t>(
      VCM_MAX(packetLoss, VCM_MAX(boostKeyProt, codeRateKey)));

  // Check limit on amount of protection for I frame: 50% is max.
  if (codeRateKey >= kPacketLossMax) {
    codeRateKey = kPacketLossMax - 1;
  }

  _protectionFactorK = codeRateKey;
  _protectionFactorD = codeRateDelta;

  // Generally there is a rate mis-match between the FEC cost estimated
  // in mediaOpt and the actual FEC cost sent out in RTP module.
  // This is more significant at low rates (small # of source packets), where
  // the granularity of the FEC decreases. In this case, non-zero protection
  // in mediaOpt may generate 0 FEC packets in RTP sender (since actual #FEC
  // is based on rounding off protectionFactor on actual source packet number).
  // The correction factor (_corrFecCost) attempts to corrects this, at least
  // for cases of low rates (small #packets) and low protection levels.

  float numPacketsFl =
      1.0f + (rtc::saturated_cast<float>(bitRatePerFrame) * 1000.0 /
                  rtc::saturated_cast<float>(8.0 * _maxPayloadSize) +
              0.5);

  const float estNumFecGen =
      0.5f +
      rtc::saturated_cast<float>(_protectionFactorD * numPacketsFl / 255.0f);

  // We reduce cost factor (which will reduce overhead for FEC and
  // hybrid method) and not the protectionFactor.
  _corrFecCost = 1.0f;
  if (estNumFecGen < 1.1f && _protectionFactorD < minProtLevelFec) {
    _corrFecCost = 0.5f;
  }
  if (estNumFecGen < 0.9f && _protectionFactorD < minProtLevelFec) {
    _corrFecCost = 0.0f;
  }

  // DONE WITH FEC PROTECTION SETTINGS
  return true;
}

int VCMFecMethod::BitsPerFrame(const VCMProtectionParameters* parameters) {
  // When temporal layers are available FEC will only be applied on the base
  // layer.
  const float bitRateRatio =
      webrtc::SimulcastRateAllocator::GetTemporalRateAllocation(
          parameters->numLayers, 0,
          rate_control_settings_.Vp8BaseHeavyTl3RateAllocation());
  float frameRateRatio = powf(1 / 2.0, parameters->numLayers - 1);
  float bitRate = parameters->bitRate * bitRateRatio;
  float frameRate = parameters->frameRate * frameRateRatio;

  // TODO(mikhal): Update factor following testing.
  float adjustmentFactor = 1;

  if (frameRate < 1.0f)
    frameRate = 1.0f;
  // Average bits per frame (units of kbits)
  return rtc::saturated_cast<int>(adjustmentFactor * bitRate / frameRate);
}

bool VCMFecMethod::EffectivePacketLoss(
    const VCMProtectionParameters* parameters) {
  // Effective packet loss to encoder is based on RPL (residual packet loss)
  // this is a soft setting based on degree of FEC protection
  // RPL = received/input packet loss - average_FEC_recovery
  // note: received/input packet loss may be filtered based on FilteredLoss

  // Effective Packet Loss, NA in current version.
  _effectivePacketLoss = 0;

  return true;
}

bool VCMFecMethod::UpdateParameters(const VCMProtectionParameters* parameters) {
  // Compute the protection factor
  ProtectionFactor(parameters);

  // Compute the effective packet loss
  EffectivePacketLoss(parameters);

  // Protection/fec rates obtained above is defined relative to total number
  // of packets (total rate: source+fec) FEC in RTP module assumes protection
  // factor is defined relative to source number of packets so we should
  // convert the factor to reduce mismatch between mediaOpt suggested rate and
  // the actual rate
  _protectionFactorK = ConvertFECRate(_protectionFactorK);
  _protectionFactorD = ConvertFECRate(_protectionFactorD);

  return true;
}
VCMLossProtectionLogic::VCMLossProtectionLogic(int64_t nowMs)
    : _currentParameters(),
      _rtt(0),
      _lossPr(0.0f),
      _bitRate(0.0f),
      _frameRate(0.0f),
      _keyFrameSize(0.0f),
      _fecRateKey(0),
      _fecRateDelta(0),
      _lastPrUpdateT(0),
      _lossPr255(0.9999f),
      _lossPrHistory(),
      _shortMaxLossPr255(0),
      _packetsPerFrame(0.9999f),
      _packetsPerFrameKey(0.9999f),
      _codecWidth(704),
      _codecHeight(576),
      _numLayers(1) {
  Reset(nowMs);
}

VCMLossProtectionLogic::~VCMLossProtectionLogic() {
  Release();
}

void VCMLossProtectionLogic::SetMethod(
    enum VCMProtectionMethodEnum newMethodType) {
  if (_selectedMethod && _selectedMethod->Type() == newMethodType)
    return;

  switch (newMethodType) {
    case kNack:
      _selectedMethod.reset(new VCMNackMethod());
      break;
    case kFec:
      _selectedMethod.reset(new VCMFecMethod());
      break;
    case kNackFec:
      _selectedMethod.reset(new VCMNackFecMethod(kLowRttNackMs, -1));
      break;
    case kNone:
      _selectedMethod.reset();
      break;
  }
  UpdateMethod();
}

void VCMLossProtectionLogic::UpdateRtt(int64_t rtt) {
  _rtt = rtt;
}

void VCMLossProtectionLogic::UpdateMaxLossHistory(uint8_t lossPr255,
                                                  int64_t now) {
  if (_lossPrHistory[0].timeMs >= 0 &&
      now - _lossPrHistory[0].timeMs < kLossPrShortFilterWinMs) {
    if (lossPr255 > _shortMaxLossPr255) {
      _shortMaxLossPr255 = lossPr255;
    }
  } else {
    // Only add a new value to the history once a second
    if (_lossPrHistory[0].timeMs == -1) {
      // First, no shift
      _shortMaxLossPr255 = lossPr255;
    } else {
      // Shift
      for (int32_t i = (kLossPrHistorySize - 2); i >= 0; i--) {
        _lossPrHistory[i + 1].lossPr255 = _lossPrHistory[i].lossPr255;
        _lossPrHistory[i + 1].timeMs = _lossPrHistory[i].timeMs;
      }
    }
    if (_shortMaxLossPr255 == 0) {
      _shortMaxLossPr255 = lossPr255;
    }

    _lossPrHistory[0].lossPr255 = _shortMaxLossPr255;
    _lossPrHistory[0].timeMs = now;
    _shortMaxLossPr255 = 0;
  }
}

uint8_t VCMLossProtectionLogic::MaxFilteredLossPr(int64_t nowMs) const {
  uint8_t maxFound = _shortMaxLossPr255;
  if (_lossPrHistory[0].timeMs == -1) {
    return maxFound;
  }
  for (int32_t i = 0; i < kLossPrHistorySize; i++) {
    if (_lossPrHistory[i].timeMs == -1) {
      break;
    }
    if (nowMs - _lossPrHistory[i].timeMs >
        kLossPrHistorySize * kLossPrShortFilterWinMs) {
      // This sample (and all samples after this) is too old
      break;
    }
    if (_lossPrHistory[i].lossPr255 > maxFound) {
      // This sample is the largest one this far into the history
      maxFound = _lossPrHistory[i].lossPr255;
    }
  }
  return maxFound;
}

uint8_t VCMLossProtectionLogic::FilteredLoss(int64_t nowMs,
                                             FilterPacketLossMode filter_mode,
                                             uint8_t lossPr255) {
  // Update the max window filter.
  UpdateMaxLossHistory(lossPr255, nowMs);

  // Update the recursive average filter.
  _lossPr255.Apply(rtc::saturated_cast<float>(nowMs - _lastPrUpdateT),
                   rtc::saturated_cast<float>(lossPr255));
  _lastPrUpdateT = nowMs;

  // Filtered loss: default is received loss (no filtering).
  uint8_t filtered_loss = lossPr255;

  switch (filter_mode) {
    case kNoFilter:
      break;
    case kAvgFilter:
      filtered_loss = rtc::saturated_cast<uint8_t>(_lossPr255.filtered() + 0.5);
      break;
    case kMaxFilter:
      filtered_loss = MaxFilteredLossPr(nowMs);
      break;
  }

  return filtered_loss;
}

void VCMLossProtectionLogic::UpdateFilteredLossPr(uint8_t packetLossEnc) {
  _lossPr = rtc::saturated_cast<float>(packetLossEnc) / 255.0;
}

void VCMLossProtectionLogic::UpdateBitRate(float bitRate) {
  _bitRate = bitRate;
}

void VCMLossProtectionLogic::UpdatePacketsPerFrame(float nPackets,
                                                   int64_t nowMs) {
  _packetsPerFrame.Apply(
      rtc::saturated_cast<float>(nowMs - _lastPacketPerFrameUpdateT), nPackets);
  _lastPacketPerFrameUpdateT = nowMs;
}

void VCMLossProtectionLogic::UpdatePacketsPerFrameKey(float nPackets,
                                                      int64_t nowMs) {
  _packetsPerFrameKey.Apply(
      rtc::saturated_cast<float>(nowMs - _lastPacketPerFrameUpdateTKey),
      nPackets);
  _lastPacketPerFrameUpdateTKey = nowMs;
}

void VCMLossProtectionLogic::UpdateKeyFrameSize(float keyFrameSize) {
  _keyFrameSize = keyFrameSize;
}

void VCMLossProtectionLogic::UpdateFrameSize(size_t width, size_t height) {
  _codecWidth = width;
  _codecHeight = height;
}

void VCMLossProtectionLogic::UpdateNumLayers(int numLayers) {
  _numLayers = (numLayers == 0) ? 1 : numLayers;
}

bool VCMLossProtectionLogic::UpdateMethod() {
  if (!_selectedMethod)
    return false;
  _currentParameters.rtt = _rtt;
  _currentParameters.lossPr = _lossPr;
  _currentParameters.bitRate = _bitRate;
  _currentParameters.frameRate = _frameRate;  // rename actual frame rate?
  _currentParameters.keyFrameSize = _keyFrameSize;
  _currentParameters.fecRateDelta = _fecRateDelta;
  _currentParameters.fecRateKey = _fecRateKey;
  _currentParameters.packetsPerFrame = _packetsPerFrame.filtered();
  _currentParameters.packetsPerFrameKey = _packetsPerFrameKey.filtered();
  _currentParameters.codecWidth = _codecWidth;
  _currentParameters.codecHeight = _codecHeight;
  _currentParameters.numLayers = _numLayers;
  return _selectedMethod->UpdateParameters(&_currentParameters);
}

VCMProtectionMethod* VCMLossProtectionLogic::SelectedMethod() const {
  return _selectedMethod.get();
}

VCMProtectionMethodEnum VCMLossProtectionLogic::SelectedType() const {
  return _selectedMethod ? _selectedMethod->Type() : kNone;
}

void VCMLossProtectionLogic::Reset(int64_t nowMs) {
  _lastPrUpdateT = nowMs;
  _lastPacketPerFrameUpdateT = nowMs;
  _lastPacketPerFrameUpdateTKey = nowMs;
  _lossPr255.Reset(0.9999f);
  _packetsPerFrame.Reset(0.9999f);
  _fecRateDelta = _fecRateKey = 0;
  for (int32_t i = 0; i < kLossPrHistorySize; i++) {
    _lossPrHistory[i].lossPr255 = 0;
    _lossPrHistory[i].timeMs = -1;
  }
  _shortMaxLossPr255 = 0;
  Release();
}

void VCMLossProtectionLogic::Release() {
  _selectedMethod.reset();
}

}  // namespace media_optimization
}  // namespace webrtc
