/*
 *  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 "webrtc/modules/congestion_controller/include/receive_side_congestion_controller.h"

#include "webrtc/modules/pacing/packet_router.h"
#include "webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.h"
#include "webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.h"
#include "webrtc/rtc_base/logging.h"

namespace webrtc {

namespace {
static const uint32_t kTimeOffsetSwitchThreshold = 30;
}  // namespace

ReceiveSideCongestionController::WrappingBitrateEstimator::
    WrappingBitrateEstimator(RemoteBitrateObserver* observer,
                             const Clock* clock)
    : observer_(observer),
      clock_(clock),
      rbe_(new RemoteBitrateEstimatorSingleStream(observer_, clock_)),
      using_absolute_send_time_(false),
      packets_since_absolute_send_time_(0),
      min_bitrate_bps_(congestion_controller::GetMinBitrateBps()) {}

void ReceiveSideCongestionController::WrappingBitrateEstimator::IncomingPacket(
    int64_t arrival_time_ms,
    size_t payload_size,
    const RTPHeader& header) {
  rtc::CritScope cs(&crit_sect_);
  PickEstimatorFromHeader(header);
  rbe_->IncomingPacket(arrival_time_ms, payload_size, header);
}

void ReceiveSideCongestionController::WrappingBitrateEstimator::Process() {
  rtc::CritScope cs(&crit_sect_);
  rbe_->Process();
}

int64_t ReceiveSideCongestionController::WrappingBitrateEstimator::
    TimeUntilNextProcess() {
  rtc::CritScope cs(&crit_sect_);
  return rbe_->TimeUntilNextProcess();
}

void ReceiveSideCongestionController::WrappingBitrateEstimator::OnRttUpdate(
    int64_t avg_rtt_ms,
    int64_t max_rtt_ms) {
  rtc::CritScope cs(&crit_sect_);
  rbe_->OnRttUpdate(avg_rtt_ms, max_rtt_ms);
}

void ReceiveSideCongestionController::WrappingBitrateEstimator::RemoveStream(
    unsigned int ssrc) {
  rtc::CritScope cs(&crit_sect_);
  rbe_->RemoveStream(ssrc);
}

bool ReceiveSideCongestionController::WrappingBitrateEstimator::LatestEstimate(
    std::vector<unsigned int>* ssrcs,
    unsigned int* bitrate_bps) const {
  rtc::CritScope cs(&crit_sect_);
  return rbe_->LatestEstimate(ssrcs, bitrate_bps);
}

void ReceiveSideCongestionController::WrappingBitrateEstimator::SetMinBitrate(
    int min_bitrate_bps) {
  rtc::CritScope cs(&crit_sect_);
  rbe_->SetMinBitrate(min_bitrate_bps);
  min_bitrate_bps_ = min_bitrate_bps;
}

void ReceiveSideCongestionController::WrappingBitrateEstimator::
    PickEstimatorFromHeader(const RTPHeader& header) {
  if (header.extension.hasAbsoluteSendTime) {
    // If we see AST in header, switch RBE strategy immediately.
    if (!using_absolute_send_time_) {
      LOG(LS_INFO)
          << "WrappingBitrateEstimator: Switching to absolute send time RBE.";
      using_absolute_send_time_ = true;
      PickEstimator();
    }
    packets_since_absolute_send_time_ = 0;
  } else {
    // When we don't see AST, wait for a few packets before going back to TOF.
    if (using_absolute_send_time_) {
      ++packets_since_absolute_send_time_;
      if (packets_since_absolute_send_time_ >= kTimeOffsetSwitchThreshold) {
        LOG(LS_INFO) << "WrappingBitrateEstimator: Switching to transmission "
                     << "time offset RBE.";
        using_absolute_send_time_ = false;
        PickEstimator();
      }
    }
  }
}

// Instantiate RBE for Time Offset or Absolute Send Time extensions.
void ReceiveSideCongestionController::WrappingBitrateEstimator::
    PickEstimator() {
  if (using_absolute_send_time_) {
    rbe_.reset(new RemoteBitrateEstimatorAbsSendTime(observer_, clock_));
  } else {
    rbe_.reset(new RemoteBitrateEstimatorSingleStream(observer_, clock_));
  }
  rbe_->SetMinBitrate(min_bitrate_bps_);
}

ReceiveSideCongestionController::ReceiveSideCongestionController(
    const Clock* clock,
    PacketRouter* packet_router)
    : remote_bitrate_estimator_(packet_router, clock),
      remote_estimator_proxy_(clock, packet_router) {}

void ReceiveSideCongestionController::OnReceivedPacket(
    int64_t arrival_time_ms,
    size_t payload_size,
    const RTPHeader& header) {
  // Send-side BWE.
  if (header.extension.hasTransportSequenceNumber) {
    remote_estimator_proxy_.IncomingPacket(arrival_time_ms, payload_size,
                                           header);
  } else {
    // Receive-side BWE.
    remote_bitrate_estimator_.IncomingPacket(arrival_time_ms, payload_size,
                                             header);
  }
}

RemoteBitrateEstimator*
ReceiveSideCongestionController::GetRemoteBitrateEstimator(bool send_side_bwe) {
  if (send_side_bwe) {
    return &remote_estimator_proxy_;
  } else {
    return &remote_bitrate_estimator_;
  }
}

const RemoteBitrateEstimator*
ReceiveSideCongestionController::GetRemoteBitrateEstimator(
    bool send_side_bwe) const {
  if (send_side_bwe) {
    return &remote_estimator_proxy_;
  } else {
    return &remote_bitrate_estimator_;
  }
}

void ReceiveSideCongestionController::OnRttUpdate(int64_t avg_rtt_ms,
                                                  int64_t max_rtt_ms) {
  remote_bitrate_estimator_.OnRttUpdate(avg_rtt_ms, max_rtt_ms);
}

void ReceiveSideCongestionController::OnBitrateChanged(int bitrate_bps) {
  remote_estimator_proxy_.OnBitrateChanged(bitrate_bps);
}

int64_t ReceiveSideCongestionController::TimeUntilNextProcess() {
  return remote_bitrate_estimator_.TimeUntilNextProcess();
}

void ReceiveSideCongestionController::Process() {
  remote_bitrate_estimator_.Process();
}

}  // namespace webrtc
