/*
 *  Copyright (c) 2018 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/congestion_controller/goog_cc/goog_cc_network_control.h"

#include <inttypes.h>
#include <stdio.h>
#include <algorithm>
#include <cstdint>
#include <memory>
#include <numeric>
#include <string>
#include <vector>

#include "absl/memory/memory.h"
#include "api/units/time_delta.h"
#include "modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator.h"
#include "modules/congestion_controller/goog_cc/alr_detector.h"
#include "modules/congestion_controller/goog_cc/probe_controller.h"
#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
#include "modules/remote_bitrate_estimator/test/bwe_test_logging.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"

namespace webrtc {
namespace {

const char kCwndExperiment[] = "WebRTC-CwndExperiment";
// When CongestionWindowPushback is enabled, the pacer is oblivious to
// the congestion window. The relation between outstanding data and
// the congestion window affects encoder allocations directly.
const char kCongestionPushbackExperiment[] = "WebRTC-CongestionWindowPushback";

const int64_t kDefaultAcceptedQueueMs = 250;

// From RTCPSender video report interval.
constexpr TimeDelta kLossUpdateInterval = TimeDelta::Millis<1000>();

// Pacing-rate relative to our target send rate.
// Multiplicative factor that is applied to the target bitrate to calculate
// the number of bytes that can be transmitted per interval.
// Increasing this factor will result in lower delays in cases of bitrate
// overshoots from the encoder.
const float kDefaultPaceMultiplier = 2.5f;

std::unique_ptr<CongestionWindowPushbackController>
MaybeCreateCongestionWindowPushbackController(
    const WebRtcKeyValueConfig* const key_value_config) {
  if (key_value_config->Lookup(kCongestionPushbackExperiment).find("Enabled") ==
          0 &&
      key_value_config->Lookup(kCwndExperiment).find("Enabled") == 0)
    return absl::make_unique<CongestionWindowPushbackController>(
        key_value_config);
  return nullptr;
}

bool CwndExperimentEnabled(const WebRtcKeyValueConfig* const key_value_config) {
  std::string experiment_string = key_value_config->Lookup(kCwndExperiment);
  // The experiment is enabled iff the field trial string begins with "Enabled".
  return experiment_string.find("Enabled") == 0;
}
bool ReadCwndExperimentParameter(
    const WebRtcKeyValueConfig* const key_value_config,
    int64_t* accepted_queue_ms) {
  RTC_DCHECK(accepted_queue_ms);
  std::string experiment_string = key_value_config->Lookup(kCwndExperiment);
  int parsed_values =
      sscanf(experiment_string.c_str(), "Enabled-%" PRId64, accepted_queue_ms);
  if (parsed_values == 1) {
    RTC_CHECK_GE(*accepted_queue_ms, 0)
        << "Accepted must be greater than or equal to 0.";
    return true;
  }
  return false;
}

// Makes sure that the bitrate and the min, max values are in valid range.
static void ClampBitrates(int64_t* bitrate_bps,
                          int64_t* min_bitrate_bps,
                          int64_t* max_bitrate_bps) {
  // TODO(holmer): We should make sure the default bitrates are set to 10 kbps,
  // and that we don't try to set the min bitrate to 0 from any applications.
  // The congestion controller should allow a min bitrate of 0.
  if (*min_bitrate_bps < congestion_controller::GetMinBitrateBps())
    *min_bitrate_bps = congestion_controller::GetMinBitrateBps();
  if (*max_bitrate_bps > 0)
    *max_bitrate_bps = std::max(*min_bitrate_bps, *max_bitrate_bps);
  if (*bitrate_bps > 0)
    *bitrate_bps = std::max(*min_bitrate_bps, *bitrate_bps);
}

std::vector<PacketFeedback> ReceivedPacketsFeedbackAsRtp(
    const TransportPacketsFeedback report) {
  std::vector<PacketFeedback> packet_feedback_vector;
  for (auto& fb : report.PacketsWithFeedback()) {
    if (fb.receive_time.IsFinite()) {
      PacketFeedback pf(fb.receive_time.ms(), 0);
      pf.creation_time_ms = report.feedback_time.ms();
      pf.payload_size = fb.sent_packet.size.bytes();
      pf.pacing_info = fb.sent_packet.pacing_info;
      pf.send_time_ms = fb.sent_packet.send_time.ms();
      pf.unacknowledged_data = fb.sent_packet.prior_unacked_data.bytes();
      packet_feedback_vector.push_back(pf);
    }
  }
  return packet_feedback_vector;
}

int64_t GetBpsOrDefault(const absl::optional<DataRate>& rate,
                        int64_t fallback_bps) {
  if (rate && rate->IsFinite()) {
    return rate->bps();
  } else {
    return fallback_bps;
  }
}

}  // namespace

GoogCcNetworkController::GoogCcNetworkController(RtcEventLog* event_log,
                                                 NetworkControllerConfig config,
                                                 bool feedback_only)
    : key_value_config_(config.key_value_config ? config.key_value_config
                                                : &trial_based_config_),
      event_log_(event_log),
      packet_feedback_only_(feedback_only),
      safe_reset_on_route_change_("Enabled"),
      safe_reset_acknowledged_rate_("ack"),
      use_stable_bandwidth_estimate_(
          key_value_config_->Lookup("WebRTC-Bwe-StableBandwidthEstimate")
              .find("Enabled") == 0),
      fall_back_to_probe_rate_(
          key_value_config_->Lookup("WebRTC-Bwe-ProbeRateFallback")
              .find("Enabled") == 0),
      probe_controller_(new ProbeController(key_value_config_)),
      congestion_window_pushback_controller_(
          MaybeCreateCongestionWindowPushbackController(key_value_config_)),
      bandwidth_estimation_(
          absl::make_unique<SendSideBandwidthEstimation>(event_log_)),
      alr_detector_(absl::make_unique<AlrDetector>()),
      probe_bitrate_estimator_(new ProbeBitrateEstimator(event_log)),
      use_new_delay_based_controller_(
          key_value_config_->Lookup("WebRTC-Bwe-DelayBasedRateController")
              .find("Enabled") == 0),
      delay_based_bwe_(use_new_delay_based_controller_
                           ? nullptr
                           : new DelayBasedBwe(key_value_config_, event_log_)),
      delay_based_controller_(
          use_new_delay_based_controller_
              ? new DelayBasedRateController(key_value_config_,
                                             event_log_,
                                             config.constraints)
              : nullptr),
      acknowledged_bitrate_estimator_(
          absl::make_unique<AcknowledgedBitrateEstimator>(key_value_config_)),
      initial_config_(config),
      last_raw_target_rate_(*config.constraints.starting_rate),
      last_pushback_target_rate_(last_raw_target_rate_),
      pacing_factor_(config.stream_based_config.pacing_factor.value_or(
          kDefaultPaceMultiplier)),
      min_pacing_rate_(config.stream_based_config.min_pacing_rate.value_or(
          DataRate::Zero())),
      max_padding_rate_(config.stream_based_config.max_padding_rate.value_or(
          DataRate::Zero())),
      max_total_allocated_bitrate_(DataRate::Zero()),
      in_cwnd_experiment_(CwndExperimentEnabled(key_value_config_)),
      accepted_queue_ms_(kDefaultAcceptedQueueMs) {
  RTC_DCHECK(config.constraints.at_time.IsFinite());
  ParseFieldTrial(
      {&safe_reset_on_route_change_, &safe_reset_acknowledged_rate_},
      key_value_config_->Lookup("WebRTC-Bwe-SafeResetOnRouteChange"));
  if (delay_based_bwe_)
    delay_based_bwe_->SetMinBitrate(congestion_controller::GetMinBitrate());
  if (in_cwnd_experiment_ &&
      !ReadCwndExperimentParameter(key_value_config_, &accepted_queue_ms_)) {
    RTC_LOG(LS_WARNING) << "Failed to parse parameters for CwndExperiment "
                           "from field trial string. Experiment disabled.";
    in_cwnd_experiment_ = false;
  }
}

GoogCcNetworkController::~GoogCcNetworkController() {}

NetworkControlUpdate GoogCcNetworkController::OnNetworkAvailability(
    NetworkAvailability msg) {
  NetworkControlUpdate update;
  update.probe_cluster_configs = probe_controller_->OnNetworkAvailability(msg);
  return update;
}

NetworkControlUpdate GoogCcNetworkController::OnNetworkRouteChange(
    NetworkRouteChange msg) {
  int64_t min_bitrate_bps = GetBpsOrDefault(msg.constraints.min_data_rate, 0);
  int64_t max_bitrate_bps = GetBpsOrDefault(msg.constraints.max_data_rate, -1);
  int64_t start_bitrate_bps =
      GetBpsOrDefault(msg.constraints.starting_rate, -1);

  ClampBitrates(&start_bitrate_bps, &min_bitrate_bps, &max_bitrate_bps);

  if (safe_reset_on_route_change_) {
    absl::optional<uint32_t> estimated_bitrate_bps;
    if (safe_reset_acknowledged_rate_) {
      estimated_bitrate_bps = acknowledged_bitrate_estimator_->bitrate_bps();
      if (!estimated_bitrate_bps)
        estimated_bitrate_bps = acknowledged_bitrate_estimator_->PeekBps();
    } else {
      int32_t target_bitrate_bps;
      uint8_t fraction_loss;
      int64_t rtt_ms;
      bandwidth_estimation_->CurrentEstimate(&target_bitrate_bps,
                                             &fraction_loss, &rtt_ms);
      estimated_bitrate_bps = target_bitrate_bps;
    }
    if (estimated_bitrate_bps && (!msg.constraints.starting_rate ||
                                  estimated_bitrate_bps < start_bitrate_bps)) {
      start_bitrate_bps = *estimated_bitrate_bps;
      msg.constraints.starting_rate = DataRate::bps(start_bitrate_bps);
    }
  }

  acknowledged_bitrate_estimator_.reset(
      new AcknowledgedBitrateEstimator(key_value_config_));
  probe_bitrate_estimator_.reset(new ProbeBitrateEstimator(event_log_));
  if (delay_based_bwe_) {
    delay_based_bwe_.reset(new DelayBasedBwe(key_value_config_, event_log_));
    if (msg.constraints.starting_rate)
      delay_based_bwe_->SetStartBitrate(*msg.constraints.starting_rate);
    // TODO(srte): Use original values instead of converted.
    delay_based_bwe_->SetMinBitrate(DataRate::bps(min_bitrate_bps));
  } else {
    delay_based_controller_->UpdateConstraints(msg.constraints);
    delay_based_controller_->OnRouteChange();
  }
  bandwidth_estimation_->OnRouteChange();
  bandwidth_estimation_->SetBitrates(
      msg.constraints.starting_rate, DataRate::bps(min_bitrate_bps),
      msg.constraints.max_data_rate.value_or(DataRate::Infinity()),
      msg.at_time);

  probe_controller_->Reset(msg.at_time.ms());
  NetworkControlUpdate update;
  update.probe_cluster_configs = probe_controller_->SetBitrates(
      min_bitrate_bps, start_bitrate_bps, max_bitrate_bps, msg.at_time.ms());
  MaybeTriggerOnNetworkChanged(&update, msg.at_time);
  return update;
}

NetworkControlUpdate GoogCcNetworkController::OnProcessInterval(
    ProcessInterval msg) {
  NetworkControlUpdate update;
  if (initial_config_) {
    update.probe_cluster_configs =
        UpdateBitrateConstraints(initial_config_->constraints,
                                 initial_config_->constraints.starting_rate);
    update.pacer_config = GetPacingRates(msg.at_time);

    if (initial_config_->stream_based_config.requests_alr_probing) {
      probe_controller_->EnablePeriodicAlrProbing(
          *initial_config_->stream_based_config.requests_alr_probing);
    }
    absl::optional<DataRate> total_bitrate =
        initial_config_->stream_based_config.max_total_allocated_bitrate;
    if (total_bitrate) {
      auto probes = probe_controller_->OnMaxTotalAllocatedBitrate(
          total_bitrate->bps(), msg.at_time.ms());
      update.probe_cluster_configs.insert(update.probe_cluster_configs.end(),
                                          probes.begin(), probes.end());

      max_total_allocated_bitrate_ = *total_bitrate;
    }
    initial_config_.reset();
  }
  if (delay_based_controller_) {
    delay_based_controller_->OnTimeUpdate(msg.at_time);
    bandwidth_estimation_->UpdateDelayBasedEstimate(
        msg.at_time, delay_based_controller_->target_rate());
  }
  if (congestion_window_pushback_controller_ && msg.pacer_queue) {
    congestion_window_pushback_controller_->UpdatePacingQueue(
        msg.pacer_queue->bytes());
  }
  bandwidth_estimation_->UpdateEstimate(msg.at_time);
  absl::optional<int64_t> start_time_ms =
      alr_detector_->GetApplicationLimitedRegionStartTime();
  probe_controller_->SetAlrStartTimeMs(start_time_ms);

  auto probes = probe_controller_->Process(msg.at_time.ms());
  update.probe_cluster_configs.insert(update.probe_cluster_configs.end(),
                                      probes.begin(), probes.end());

  MaybeTriggerOnNetworkChanged(&update, msg.at_time);
  return update;
}

NetworkControlUpdate GoogCcNetworkController::OnRemoteBitrateReport(
    RemoteBitrateReport msg) {
  if (packet_feedback_only_) {
    RTC_LOG(LS_ERROR) << "Received REMB for packet feedback only GoogCC";
    return NetworkControlUpdate();
  }
  if (delay_based_controller_)
    delay_based_controller_->OnRemoteBitrateControl(msg);
  bandwidth_estimation_->UpdateReceiverEstimate(msg.receive_time,
                                                msg.bandwidth);
  BWE_TEST_LOGGING_PLOT(1, "REMB_kbps", msg.receive_time.ms(),
                        msg.bandwidth.bps() / 1000);
  return NetworkControlUpdate();
}

NetworkControlUpdate GoogCcNetworkController::OnRoundTripTimeUpdate(
    RoundTripTimeUpdate msg) {
  if (packet_feedback_only_)
    return NetworkControlUpdate();
  if (msg.smoothed) {
    if (delay_based_bwe_)
      delay_based_bwe_->OnRttUpdate(msg.round_trip_time);
  } else {
    bandwidth_estimation_->UpdateRtt(msg.round_trip_time, msg.receive_time);
  }
  return NetworkControlUpdate();
}

NetworkControlUpdate GoogCcNetworkController::OnSentPacket(
    SentPacket sent_packet) {
  alr_detector_->OnBytesSent(sent_packet.size.bytes(),
                             sent_packet.send_time.ms());
  if (!first_packet_sent_) {
    first_packet_sent_ = true;
    // Initialize feedback time to send time to allow estimation of RTT until
    // first feedback is received.
    bandwidth_estimation_->UpdatePropagationRtt(sent_packet.send_time,
                                                TimeDelta::Zero());
  }
  if (congestion_window_pushback_controller_) {
    congestion_window_pushback_controller_->UpdateOutstandingData(
        sent_packet.data_in_flight.bytes());
    NetworkControlUpdate update;
    MaybeTriggerOnNetworkChanged(&update, sent_packet.send_time);
    return update;
  } else {
    return NetworkControlUpdate();
  }
}

NetworkControlUpdate GoogCcNetworkController::OnStreamsConfig(
    StreamsConfig msg) {
  NetworkControlUpdate update;
  if (msg.requests_alr_probing) {
    probe_controller_->EnablePeriodicAlrProbing(*msg.requests_alr_probing);
  }
  if (msg.max_total_allocated_bitrate &&
      *msg.max_total_allocated_bitrate != max_total_allocated_bitrate_) {
    update.probe_cluster_configs =
        probe_controller_->OnMaxTotalAllocatedBitrate(
            msg.max_total_allocated_bitrate->bps(), msg.at_time.ms());
    max_total_allocated_bitrate_ = *msg.max_total_allocated_bitrate;
  }
  bool pacing_changed = false;
  if (msg.pacing_factor && *msg.pacing_factor != pacing_factor_) {
    pacing_factor_ = *msg.pacing_factor;
    pacing_changed = true;
  }
  if (msg.min_pacing_rate && *msg.min_pacing_rate != min_pacing_rate_) {
    min_pacing_rate_ = *msg.min_pacing_rate;
    pacing_changed = true;
  }
  if (msg.max_padding_rate && *msg.max_padding_rate != max_padding_rate_) {
    max_padding_rate_ = *msg.max_padding_rate;
    pacing_changed = true;
  }
  acknowledged_bitrate_estimator_->SetAllocatedBitrateWithoutFeedback(
      msg.unacknowledged_rate_allocation.bps());

  if (pacing_changed)
    update.pacer_config = GetPacingRates(msg.at_time);
  return update;
}

NetworkControlUpdate GoogCcNetworkController::OnTargetRateConstraints(
    TargetRateConstraints constraints) {
  NetworkControlUpdate update;
  update.probe_cluster_configs =
      UpdateBitrateConstraints(constraints, constraints.starting_rate);
  MaybeTriggerOnNetworkChanged(&update, constraints.at_time);
  return update;
}

std::vector<ProbeClusterConfig>
GoogCcNetworkController::UpdateBitrateConstraints(
    TargetRateConstraints constraints,
    absl::optional<DataRate> starting_rate) {
  int64_t min_bitrate_bps = GetBpsOrDefault(constraints.min_data_rate, 0);
  int64_t max_bitrate_bps = GetBpsOrDefault(constraints.max_data_rate, -1);
  int64_t start_bitrate_bps = GetBpsOrDefault(starting_rate, -1);

  ClampBitrates(&start_bitrate_bps, &min_bitrate_bps, &max_bitrate_bps);

  std::vector<ProbeClusterConfig> probes(probe_controller_->SetBitrates(
      min_bitrate_bps, start_bitrate_bps, max_bitrate_bps,
      constraints.at_time.ms()));

  bandwidth_estimation_->SetBitrates(
      starting_rate, DataRate::bps(min_bitrate_bps),
      constraints.max_data_rate.value_or(DataRate::Infinity()),
      constraints.at_time);
  if (delay_based_bwe_) {
    if (starting_rate)
      delay_based_bwe_->SetStartBitrate(*starting_rate);
    delay_based_bwe_->SetMinBitrate(DataRate::bps(min_bitrate_bps));
  } else {
    delay_based_controller_->UpdateConstraints(constraints);
  }
  return probes;
}

NetworkControlUpdate GoogCcNetworkController::OnTransportLossReport(
    TransportLossReport msg) {
  if (packet_feedback_only_)
    return NetworkControlUpdate();
  int64_t total_packets_delta =
      msg.packets_received_delta + msg.packets_lost_delta;
  bandwidth_estimation_->UpdatePacketsLost(
      msg.packets_lost_delta, total_packets_delta, msg.receive_time);
  return NetworkControlUpdate();
}

NetworkControlUpdate GoogCcNetworkController::OnTransportPacketsFeedback(
    TransportPacketsFeedback report) {
  if (report.packet_feedbacks.empty()) {
    // TODO(bugs.webrtc.org/10125): Design a better mechanism to safe-guard
    // against building very large network queues.
    return NetworkControlUpdate();
  }

  if (congestion_window_pushback_controller_) {
    congestion_window_pushback_controller_->UpdateOutstandingData(
        report.data_in_flight.bytes());
  }
  TimeDelta max_feedback_rtt = TimeDelta::MinusInfinity();
  TimeDelta min_propagation_rtt = TimeDelta::PlusInfinity();
  Timestamp max_recv_time = Timestamp::MinusInfinity();

  std::vector<PacketResult> feedbacks = report.ReceivedWithSendInfo();
  for (const auto& feedback : feedbacks)
    max_recv_time = std::max(max_recv_time, feedback.receive_time);

  for (const auto& feedback : feedbacks) {
    TimeDelta feedback_rtt =
        report.feedback_time - feedback.sent_packet.send_time;
    TimeDelta min_pending_time = feedback.receive_time - max_recv_time;
    TimeDelta propagation_rtt = feedback_rtt - min_pending_time;
    max_feedback_rtt = std::max(max_feedback_rtt, feedback_rtt);
    min_propagation_rtt = std::min(min_propagation_rtt, propagation_rtt);
  }

  if (max_feedback_rtt.IsFinite()) {
    feedback_max_rtts_.push_back(max_feedback_rtt.ms());
    const size_t kMaxFeedbackRttWindow = 32;
    if (feedback_max_rtts_.size() > kMaxFeedbackRttWindow)
      feedback_max_rtts_.pop_front();
    // TODO(srte): Use time since last unacknowledged packet.
    bandwidth_estimation_->UpdatePropagationRtt(report.feedback_time,
                                                min_propagation_rtt);
  }
  if (packet_feedback_only_) {
    if (!feedback_max_rtts_.empty()) {
      int64_t sum_rtt_ms = std::accumulate(feedback_max_rtts_.begin(),
                                           feedback_max_rtts_.end(), 0);
      int64_t mean_rtt_ms = sum_rtt_ms / feedback_max_rtts_.size();
      if (delay_based_bwe_)
        delay_based_bwe_->OnRttUpdate(TimeDelta::ms(mean_rtt_ms));
    }

    TimeDelta feedback_min_rtt = TimeDelta::PlusInfinity();
    for (const auto& packet_feedback : feedbacks) {
      TimeDelta pending_time = packet_feedback.receive_time - max_recv_time;
      TimeDelta rtt = report.feedback_time -
                      packet_feedback.sent_packet.send_time - pending_time;
      // Value used for predicting NACK round trip time in FEC controller.
      feedback_min_rtt = std::min(rtt, feedback_min_rtt);
    }
    if (feedback_min_rtt.IsFinite()) {
      bandwidth_estimation_->UpdateRtt(feedback_min_rtt, report.feedback_time);
    }

    expected_packets_since_last_loss_update_ +=
        report.PacketsWithFeedback().size();
    for (const auto& packet_feedback : report.PacketsWithFeedback()) {
      if (packet_feedback.receive_time.IsInfinite())
        lost_packets_since_last_loss_update_ += 1;
    }
    if (report.feedback_time > next_loss_update_) {
      next_loss_update_ = report.feedback_time + kLossUpdateInterval;
      bandwidth_estimation_->UpdatePacketsLost(
          lost_packets_since_last_loss_update_,
          expected_packets_since_last_loss_update_, report.feedback_time);
      expected_packets_since_last_loss_update_ = 0;
      lost_packets_since_last_loss_update_ = 0;
    }
  }

  std::vector<PacketFeedback> received_feedback_vector =
      ReceivedPacketsFeedbackAsRtp(report);

  absl::optional<int64_t> alr_start_time =
      alr_detector_->GetApplicationLimitedRegionStartTime();

  if (previously_in_alr && !alr_start_time.has_value()) {
    int64_t now_ms = report.feedback_time.ms();
    acknowledged_bitrate_estimator_->SetAlrEndedTimeMs(now_ms);
    probe_controller_->SetAlrEndedTimeMs(now_ms);
  }
  previously_in_alr = alr_start_time.has_value();
  acknowledged_bitrate_estimator_->IncomingPacketFeedbackVector(
      received_feedback_vector);
  auto acknowledged_bitrate = acknowledged_bitrate_estimator_->bitrate();
  for (const auto& feedback : received_feedback_vector) {
    if (feedback.pacing_info.probe_cluster_id != PacedPacketInfo::kNotAProbe) {
      probe_bitrate_estimator_->HandleProbeAndEstimateBitrate(feedback);
    }
  }

  absl::optional<DataRate> probe_bitrate =
      probe_bitrate_estimator_->FetchAndResetLastEstimatedBitrate();
  if (fall_back_to_probe_rate_ && !acknowledged_bitrate)
    acknowledged_bitrate = probe_bitrate_estimator_->last_estimate();
  bandwidth_estimation_->SetAcknowledgedRate(acknowledged_bitrate,
                                             report.feedback_time);
  bandwidth_estimation_->IncomingPacketFeedbackVector(report);

  NetworkControlUpdate update;
  bool recovered_from_overuse = false;
  bool backoff_in_alr = false;
  // TODO(srte): Add support for ALR backoff trial in the new rate controller.
  if (delay_based_controller_) {
    if (acknowledged_bitrate)
      delay_based_controller_->SetAcknowledgedRate(*acknowledged_bitrate);
    bool prior_underuse = delay_based_controller_->in_underuse();
    delay_based_controller_->OnTransportPacketsFeedback(report, probe_bitrate);
    recovered_from_overuse =
        prior_underuse && !delay_based_controller_->in_underuse();
    if (probe_bitrate) {
      bandwidth_estimation_->SetSendBitrate(
          delay_based_controller_->target_rate(), report.feedback_time);
    }
    bandwidth_estimation_->UpdateDelayBasedEstimate(
        report.feedback_time, delay_based_controller_->target_rate());
    MaybeTriggerOnNetworkChanged(&update, report.feedback_time);
  } else {
    DelayBasedBwe::Result result;
    result = delay_based_bwe_->IncomingPacketFeedbackVector(
        received_feedback_vector, acknowledged_bitrate, probe_bitrate,
        alr_start_time.has_value(), report.feedback_time);

    if (result.updated) {
      if (result.probe) {
        bandwidth_estimation_->SetSendBitrate(result.target_bitrate,
                                              report.feedback_time);
      }
      // Since SetSendBitrate now resets the delay-based estimate, we have to
      // call UpdateDelayBasedEstimate after SetSendBitrate.
      bandwidth_estimation_->UpdateDelayBasedEstimate(report.feedback_time,
                                                      result.target_bitrate);
      // Update the estimate in the ProbeController, in case we want to probe.
      MaybeTriggerOnNetworkChanged(&update, report.feedback_time);
    }
    recovered_from_overuse = result.recovered_from_overuse;
    backoff_in_alr = result.backoff_in_alr;
  }
  if (recovered_from_overuse) {
    probe_controller_->SetAlrStartTimeMs(alr_start_time);
    auto probes = probe_controller_->RequestProbe(report.feedback_time.ms());
    update.probe_cluster_configs.insert(update.probe_cluster_configs.end(),
                                        probes.begin(), probes.end());
  } else if (backoff_in_alr) {
    // If we just backed off during ALR, request a new probe.
    auto probes = probe_controller_->RequestProbe(report.feedback_time.ms());
    update.probe_cluster_configs.insert(update.probe_cluster_configs.end(),
                                        probes.begin(), probes.end());
  }

  // No valid RTT could be because send-side BWE isn't used, in which case
  // we don't try to limit the outstanding packets.
  if (in_cwnd_experiment_ && max_feedback_rtt.IsFinite()) {
    int64_t min_feedback_max_rtt_ms =
        *std::min_element(feedback_max_rtts_.begin(), feedback_max_rtts_.end());

    const DataSize kMinCwnd = DataSize::bytes(2 * 1500);
    TimeDelta time_window =
        TimeDelta::ms(min_feedback_max_rtt_ms + accepted_queue_ms_);
    DataSize data_window = last_raw_target_rate_ * time_window;
    if (current_data_window_) {
      data_window =
          std::max(kMinCwnd, (data_window + current_data_window_.value()) / 2);
    } else {
      data_window = std::max(kMinCwnd, data_window);
    }
    current_data_window_ = data_window;
  }
  if (congestion_window_pushback_controller_ && current_data_window_) {
    congestion_window_pushback_controller_->SetDataWindow(
        *current_data_window_);
  } else {
    update.congestion_window = current_data_window_;
  }

  return update;
}

NetworkControlUpdate GoogCcNetworkController::GetNetworkState(
    Timestamp at_time) const {
  DataRate bandwidth = DataRate::bps(last_estimated_bitrate_bps_);
  TimeDelta rtt = TimeDelta::ms(last_estimated_rtt_ms_);
  NetworkControlUpdate update;
  update.target_rate = TargetTransferRate();
  update.target_rate->network_estimate.at_time = at_time;
  update.target_rate->network_estimate.bandwidth = bandwidth;
  update.target_rate->network_estimate.loss_rate_ratio =
      last_estimated_fraction_loss_ / 255.0;
  update.target_rate->network_estimate.round_trip_time = rtt;
  update.target_rate->network_estimate.bwe_period =
      delay_based_bwe_ ? delay_based_bwe_->GetExpectedBwePeriod()
                       : delay_based_controller_->GetExpectedBandwidthPeriod();

  update.target_rate->at_time = at_time;
  update.target_rate->target_rate = bandwidth;
  update.pacer_config = GetPacingRates(at_time);
  update.congestion_window = current_data_window_;
  return update;
}


void GoogCcNetworkController::MaybeTriggerOnNetworkChanged(
    NetworkControlUpdate* update,
    Timestamp at_time) {
  int32_t estimated_bitrate_bps;
  uint8_t fraction_loss;
  int64_t rtt_ms;
  bandwidth_estimation_->CurrentEstimate(&estimated_bitrate_bps, &fraction_loss,
                                         &rtt_ms);

  estimated_bitrate_bps = std::max<int32_t>(
      estimated_bitrate_bps, bandwidth_estimation_->GetMinBitrate());

  BWE_TEST_LOGGING_PLOT(1, "fraction_loss_%", at_time.ms(),
                        (fraction_loss * 100) / 256);
  BWE_TEST_LOGGING_PLOT(1, "rtt_ms", at_time.ms(), rtt_ms);
  BWE_TEST_LOGGING_PLOT(1, "Target_bitrate_kbps", at_time.ms(),
                        estimated_bitrate_bps / 1000);

  DataRate target_rate = DataRate::bps(estimated_bitrate_bps);
  if (congestion_window_pushback_controller_) {
    int64_t pushback_rate =
        congestion_window_pushback_controller_->UpdateTargetBitrate(
            target_rate.bps());
    pushback_rate = std::max<int64_t>(bandwidth_estimation_->GetMinBitrate(),
                                      pushback_rate);
    target_rate = DataRate::bps(pushback_rate);
  }

  if ((estimated_bitrate_bps != last_estimated_bitrate_bps_) ||
      (fraction_loss != last_estimated_fraction_loss_) ||
      (rtt_ms != last_estimated_rtt_ms_) ||
      (target_rate != last_pushback_target_rate_)) {
    last_pushback_target_rate_ = target_rate;
    last_estimated_bitrate_bps_ = estimated_bitrate_bps;
    last_estimated_fraction_loss_ = fraction_loss;
    last_estimated_rtt_ms_ = rtt_ms;

    alr_detector_->SetEstimatedBitrate(estimated_bitrate_bps);

    last_raw_target_rate_ = DataRate::bps(estimated_bitrate_bps);
    DataRate bandwidth = use_stable_bandwidth_estimate_
                             ? bandwidth_estimation_->GetEstimatedLinkCapacity()
                             : last_raw_target_rate_;

    TimeDelta bwe_period =
        delay_based_bwe_
            ? delay_based_bwe_->GetExpectedBwePeriod()
            : delay_based_controller_->GetExpectedBandwidthPeriod();

    TargetTransferRate target_rate_msg;
    target_rate_msg.at_time = at_time;
    target_rate_msg.target_rate = target_rate;
    target_rate_msg.network_estimate.at_time = at_time;
    target_rate_msg.network_estimate.round_trip_time = TimeDelta::ms(rtt_ms);
    target_rate_msg.network_estimate.bandwidth = bandwidth;
    target_rate_msg.network_estimate.loss_rate_ratio = fraction_loss / 255.0f;
    target_rate_msg.network_estimate.bwe_period = bwe_period;

    update->target_rate = target_rate_msg;

    auto probes = probe_controller_->SetEstimatedBitrate(
        last_raw_target_rate_.bps(), at_time.ms());
    update->probe_cluster_configs.insert(update->probe_cluster_configs.end(),
                                         probes.begin(), probes.end());
    update->pacer_config = GetPacingRates(at_time);
  }
}

PacerConfig GoogCcNetworkController::GetPacingRates(Timestamp at_time) const {
  DataRate pacing_rate =
      std::max(min_pacing_rate_, last_raw_target_rate_) * pacing_factor_;
  DataRate padding_rate =
      std::min(max_padding_rate_, last_pushback_target_rate_);
  PacerConfig msg;
  msg.at_time = at_time;
  msg.time_window = TimeDelta::seconds(1);
  msg.data_window = pacing_rate * msg.time_window;
  msg.pad_window = padding_rate * msg.time_window;
  return msg;
}

}  // namespace webrtc
