/*
 *  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 "webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h"

#include <math.h>  // sqrt()

#include "webrtc/system_wrappers/interface/trace.h"

namespace webrtc {

SendSideBandwidthEstimation::SendSideBandwidthEstimation()
    : critsect_(CriticalSectionWrapper::CreateCriticalSection()),
      accumulate_lost_packets_Q8_(0),
      accumulate_expected_packets_(0),
      bitrate_(0),
      min_bitrate_configured_(0),
      max_bitrate_configured_(0),
      last_fraction_loss_(0),
      last_round_trip_time_(0),
      bwe_incoming_(0),
      time_last_increase_(0),
      time_last_decrease_(0) {
}

SendSideBandwidthEstimation::~SendSideBandwidthEstimation() {
    delete critsect_;
}

void SendSideBandwidthEstimation::SetSendBitrate(const uint32_t bitrate) {
  CriticalSectionScoped cs(critsect_);
  bitrate_ = bitrate;
}

void SendSideBandwidthEstimation::SetMinMaxBitrate(const uint32_t min_bitrate,
                                                   const uint32_t max_bitrate) {
  CriticalSectionScoped cs(critsect_);
  min_bitrate_configured_ = min_bitrate;
  if (max_bitrate == 0) {
    // no max configured use 1Gbit/s
    max_bitrate_configured_ = 1000000000;
  } else {
    max_bitrate_configured_ = max_bitrate;
  }
}

void SendSideBandwidthEstimation::SetMinBitrate(uint32_t min_bitrate) {
  CriticalSectionScoped cs(critsect_);
  min_bitrate_configured_ = min_bitrate;
}

bool SendSideBandwidthEstimation::UpdateBandwidthEstimate(
    const uint32_t bandwidth,
    uint32_t* new_bitrate,
    uint8_t* fraction_lost,
    uint16_t* rtt) {
  *new_bitrate = 0;
  CriticalSectionScoped cs(critsect_);

  bwe_incoming_ = bandwidth;

  if (bitrate_ == 0) {
    // SendSideBandwidthEstimation off
    return false;
  }
  if (bwe_incoming_ > 0 && bitrate_ > bwe_incoming_) {
    bitrate_ = bwe_incoming_;
    *new_bitrate = bitrate_;
    *fraction_lost = last_fraction_loss_;
    *rtt = last_round_trip_time_;
    return true;
  }
  return false;
}

bool SendSideBandwidthEstimation::UpdatePacketLoss(
    const int number_of_packets,
    const uint32_t rtt,
    const uint32_t now_ms,
    uint8_t* loss,
    uint32_t* new_bitrate) {
  CriticalSectionScoped cs(critsect_);

  if (bitrate_ == 0) {
    // SendSideBandwidthEstimation off
    return false;
  }
  // Update RTT.
  last_round_trip_time_ = rtt;

  // Check sequence number diff and weight loss report
  if (number_of_packets > 0) {
    // Calculate number of lost packets.
    const int num_lost_packets_Q8 = *loss * number_of_packets;
    // Accumulate reports.
    accumulate_lost_packets_Q8_ += num_lost_packets_Q8;
    accumulate_expected_packets_ += number_of_packets;

    // Report loss if the total report is based on sufficiently many packets.
    if (accumulate_expected_packets_ >= kLimitNumPackets) {
      *loss = accumulate_lost_packets_Q8_ / accumulate_expected_packets_;

      // Reset accumulators
      accumulate_lost_packets_Q8_ = 0;
      accumulate_expected_packets_ = 0;
    } else {
      // Report zero loss until we have enough data to estimate
      // the loss rate.
      return false;
    }
  }
  // Keep for next time.
  last_fraction_loss_ = *loss;
  uint32_t bitrate = 0;
  if (!ShapeSimple(*loss, rtt, now_ms, &bitrate)) {
    // No change.
    return false;
  }
  bitrate_ = bitrate;
  *new_bitrate = bitrate;
  return true;
}

bool SendSideBandwidthEstimation::AvailableBandwidth(
    uint32_t* bandwidth) const {
  CriticalSectionScoped cs(critsect_);
  if (bitrate_ == 0) {
    return false;
  }
  *bandwidth = bitrate_;
  return true;
}

/*
 * Calculate the rate that TCP-Friendly Rate Control (TFRC) would apply.
 * The formula in RFC 3448, Section 3.1, is used.
 */
uint32_t SendSideBandwidthEstimation::CalcTFRCbps(uint16_t rtt, uint8_t loss) {
  if (rtt == 0 || loss == 0) {
    // input variables out of range
    return 0;
  }
  double R = static_cast<double>(rtt) / 1000;  // RTT in seconds
  int b = 1;  // number of packets acknowledged by a single TCP acknowledgement;
              // recommended = 1
  double t_RTO = 4.0 * R;  // TCP retransmission timeout value in seconds
                           // recommended = 4*R
  double p = static_cast<double>(loss) / 255;  // packet loss rate in [0, 1)
  double s = static_cast<double>(kAvgPacketSizeBytes);

  // calculate send rate in bytes/second
  double X = s / (R * sqrt(2 * b * p / 3) +
      (t_RTO * (3 * sqrt(3 * b * p / 8) * p * (1 + 32 * p * p))));

  return (static_cast<uint32_t>(X * 8));  // bits/second
}

bool SendSideBandwidthEstimation::ShapeSimple(const uint8_t loss,
                                              const uint32_t rtt,
                                              const uint32_t now_ms,
                                              uint32_t* bitrate) {
  uint32_t new_bitrate = 0;
  bool reducing = false;

  // Limit the rate increases to once a kBWEIncreaseIntervalMs.
  if (loss <= 5) {
    if ((now_ms - time_last_increase_) < kBWEIncreaseIntervalMs) {
      return false;
    }
    time_last_increase_ = now_ms;
  }
  // Limit the rate decreases to once a kBWEDecreaseIntervalMs + rtt.
  if (loss > 26) {
    if ((now_ms - time_last_decrease_) < kBWEDecreaseIntervalMs + rtt) {
      return false;
    }
    time_last_decrease_ = now_ms;
  }

  if (loss > 5 && loss <= 26) {
    // 2% - 10%
    new_bitrate = bitrate_;
  } else if (loss > 26) {
    // 26/256 ~= 10%
    // reduce rate: newRate = rate * (1 - 0.5*lossRate)
    // packetLoss = 256*lossRate
    new_bitrate = static_cast<uint32_t>((bitrate_ *
        static_cast<double>(512 - loss)) / 512.0);
    reducing = true;
  } else {
    // increase rate by 8%
    new_bitrate = static_cast<uint32_t>(bitrate_ * 1.08 + 0.5);

    // add 1 kbps extra, just to make sure that we do not get stuck
    // (gives a little extra increase at low rates, negligible at higher rates)
    new_bitrate += 1000;
  }
  if (reducing) {
    // Calculate what rate TFRC would apply in this situation
    // scale loss to Q0 (back to [0, 255])
    uint32_t tfrc_bitrate = CalcTFRCbps(rtt, loss);
    if (tfrc_bitrate > new_bitrate) {
      // do not reduce further if rate is below TFRC rate
      new_bitrate = tfrc_bitrate;
    }
  }
  if (bwe_incoming_ > 0 && new_bitrate > bwe_incoming_) {
    new_bitrate = bwe_incoming_;
  }
  if (new_bitrate > max_bitrate_configured_) {
    new_bitrate = max_bitrate_configured_;
  }
  if (new_bitrate < min_bitrate_configured_) {
    WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, -1,
                 "The configured min bitrate (%u kbps) is greater than the "
                 "estimated available bandwidth (%u kbps).\n",
                 min_bitrate_configured_ / 1000, new_bitrate / 1000);
    new_bitrate = min_bitrate_configured_;
  }
  *bitrate = new_bitrate;
  return true;
}
}  // namespace webrtc
