/*
 *  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/remote_bitrate_estimator/test/estimators/bbr.h"

#include <stdlib.h>
#include <algorithm>

#include "webrtc/modules/remote_bitrate_estimator/test/estimators/congestion_window.h"
#include "webrtc/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_filter.h"
#include "webrtc/modules/remote_bitrate_estimator/test/estimators/min_rtt_filter.h"

namespace webrtc {
namespace testing {
namespace bwe {
namespace {
const int kFeedbackIntervalsMs = 5;
// BBR uses this value to double sending rate each round trip. Design document
// suggests using this value.
const float kHighGain = 2.885f;
// BBR uses this value to drain queues created during STARTUP in one round trip
// time.
const float kDrainGain = 1 / kHighGain;
// kStartupGrowthTarget and kMaxRoundsWithoutGrowth are chosen from
// experiments, according to the design document.
const float kStartupGrowthTarget = 1.25f;
const int kMaxRoundsWithoutGrowth = 3;
// Pacing gain values for Probe Bandwidth mode.
const float kPacingGain[] = {1.1f, 0.9f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f};
const size_t kGainCycleLength = sizeof(kPacingGain) / sizeof(kPacingGain[0]);
// Least number of rounds PROBE_RTT should last.
const int kProbeRttDurationRounds = 1;
// The least amount of milliseconds PROBE_RTT mode should last.
const int kProbeRttDurationMs = 200;
// Gain value for congestion window for assuming that network has no queues.
const float kTargetCongestionWindowGain = 1;
// Gain value for congestion window in PROBE_BW mode. In theory it should be
// equal to 1, but in practice because of delayed acks and the way networks
// work, it is nice to have some extra room in congestion window for full link
// utilization. Value chosen by observations on different tests.
const float kCruisingCongestionWindowGain = 2;
// Pacing gain specific for Recovery mode. Chosen by experiments in simulation
// tool.
const float kRecoveryPacingGain = 0.5f;
// Congestion window gain specific for Recovery mode. Chosen by experiments in
// simulation tool.
const float kRecoveryCongestionWindowGain = 1.5f;
// Number of rounds over which average RTT is stored for Recovery mode.
const size_t kPastRttsFilterSize = 1;
// Threshold to assume average RTT has increased for a round. Chosen by
// experiments in simulation tool.
const float kRttIncreaseThreshold = 3;
// Threshold to assume average RTT has decreased for a round. Chosen by
// experiments in simulation tool.
const float kRttDecreaseThreshold = 1.5f;
// If |kCongestionWindowThreshold| of the congestion window is filled up, tell
// encoder to stop, to avoid building sender side queues.
const float kCongestionWindowThreshold = 0.69f;
// Duration we send at |kDefaultRatebps| in order to ensure BBR has data to work
// with.
const int64_t kDefaultDurationMs = 200;
const int64_t kDefaultRatebps = 300000;
// Congestion window gain for PROBE_RTT mode.
const float kProbeRttCongestionWindowGain = 0.65f;
// We need to be sure that data inflight has increased by at least
// |kTargetCongestionWindowGainForHighGain| compared to the congestion window in
// PROBE_BW's high gain phase, to make ramp-up quicker. As high gain value has
// been decreased from 1.25 to 1.1 we need to make
// |kTargetCongestionWindowGainForHighGain| slightly higher than the actual high
// gain value.
const float kTargetCongestionWindowGainForHighGain = 1.15f;
// Encoder rate gain value for PROBE_RTT mode.
const float kEncoderRateGainForProbeRtt = 0.1f;
}  // namespace

BbrBweSender::BbrBweSender(BitrateObserver* observer, Clock* clock)
    : BweSender(0),
      observer_(observer),
      clock_(clock),
      mode_(STARTUP),
      max_bandwidth_filter_(new MaxBandwidthFilter()),
      min_rtt_filter_(new MinRttFilter()),
      congestion_window_(new CongestionWindow()),
      rand_(new Random(time(NULL))),
      round_count_(0),
      round_trip_end_(0),
      full_bandwidth_reached_(false),
      cycle_start_time_ms_(0),
      cycle_index_(0),
      bytes_acked_(0),
      probe_rtt_start_time_ms_(0),
      minimum_congestion_window_start_time_ms_(0),
      minimum_congestion_window_start_round_(0),
      bytes_sent_(0),
      last_packet_sent_sequence_number_(0),
      last_packet_acked_sequence_number_(0),
      last_packet_ack_time_(0),
      last_packet_send_time_(0),
      pacing_rate_bps_(0),
      last_packet_send_time_during_high_gain_ms_(-1),
      data_sent_before_high_gain_started_bytes_(-1),
      data_sent_before_high_gain_ended_bytes_(-1),
      first_packet_ack_time_during_high_gain_ms_(-1),
      last_packet_ack_time_during_high_gain_ms_(-1),
      data_acked_before_high_gain_started_bytes_(-1),
      data_acked_before_high_gain_ended_bytes_(-1),
      first_packet_seq_num_during_high_gain_(0),
      last_packet_seq_num_during_high_gain_(0),
      high_gain_over_(false),
      packet_stats_(),
      past_rtts_() {
  // Initially enter Startup mode.
  EnterStartup();
}

BbrBweSender::~BbrBweSender() {}

int BbrBweSender::GetFeedbackIntervalMs() const {
  return kFeedbackIntervalsMs;
}

void BbrBweSender::CalculatePacingRate() {
  pacing_rate_bps_ =
      max_bandwidth_filter_->max_bandwidth_estimate_bps() * pacing_gain_;
}

// Declare lost packets as acked.
void BbrBweSender::HandleLoss(uint64_t last_acked_packet,
                              uint64_t recently_acked_packet) {
  for (uint16_t i = last_acked_packet + 1;
       AheadOrAt<uint16_t>(recently_acked_packet - 1, i); i++) {
    congestion_window_->AckReceived(packet_stats_[i].payload_size_bytes);
    observer_->OnBytesAcked(packet_stats_[i].payload_size_bytes);
  }
}

void BbrBweSender::AddToPastRtts(int64_t rtt_sample_ms) {
  uint64_t last_round = 0;
  if (!past_rtts_.empty())
    last_round = past_rtts_.back().round;

  // Try to add the sample to the last round.
  if (last_round == round_count_ && !past_rtts_.empty()) {
    past_rtts_.back().sum_of_rtts_ms += rtt_sample_ms;
    past_rtts_.back().num_samples++;
  } else {
    // If the sample belongs to a new round, keep number of rounds in the window
    // equal to |kPastRttsFilterSize|.
    if (past_rtts_.size() == kPastRttsFilterSize)
      past_rtts_.pop_front();
    past_rtts_.push_back(
        BbrBweSender::AverageRtt(rtt_sample_ms, 1, round_count_));
  }
}

void BbrBweSender::GiveFeedback(const FeedbackPacket& feedback) {
  int64_t now_ms = clock_->TimeInMilliseconds();
  last_packet_ack_time_ = now_ms;
  const BbrBweFeedback& fb = static_cast<const BbrBweFeedback&>(feedback);
  // feedback_vector holds values of acknowledged packets' sequence numbers.
  const std::vector<uint16_t>& feedback_vector = fb.packet_feedback_vector();
  // Go through all the packets acked, update variables/containers accordingly.
  for (uint16_t sequence_number : feedback_vector) {
    // Completing packet information with a recently received ack.
    PacketStats* packet = &packet_stats_[sequence_number];
    bytes_acked_ += packet->payload_size_bytes;
    packet->data_sent_bytes = bytes_sent_;
    packet->last_sent_packet_send_time_ms = last_packet_send_time_;
    packet->data_acked_bytes = bytes_acked_;
    packet->ack_time_ms = now_ms;
    // Logic specific to applying "bucket" to high gain, in order to have
    // quicker ramp-up. We check if we started receiving acks for the packets
    // sent during high gain phase.
    if (packet->sequence_number == first_packet_seq_num_during_high_gain_) {
      first_packet_ack_time_during_high_gain_ms_ = now_ms;
      // Substracting half of the packet's size to avoid overestimation.
      data_acked_before_high_gain_started_bytes_ =
          bytes_acked_ - packet->payload_size_bytes / 2;
    }
    // If the last packet of high gain phase has been acked, high gain phase is
    // over.
    if (packet->sequence_number == last_packet_seq_num_during_high_gain_) {
      last_packet_ack_time_during_high_gain_ms_ = now_ms;
      data_acked_before_high_gain_ended_bytes_ =
          bytes_acked_ - packet->payload_size_bytes / 2;
      high_gain_over_ = true;
    }
    observer_->OnBytesAcked(packet->payload_size_bytes);
    congestion_window_->AckReceived(packet->payload_size_bytes);
    HandleLoss(last_packet_acked_sequence_number_, packet->sequence_number);
    last_packet_acked_sequence_number_ = packet->sequence_number;
    // Logic for wrapping sequence numbers. If round started with packet number
    // x, it can never end on y, if x > y. That could happen when sequence
    // numbers are wrapped after some point.
    if (packet->sequence_number == 0)
      round_trip_end_ = 0;
  }
  // Check if new round started for the connection.
  bool new_round_started = false;
  if (!feedback_vector.empty()) {
    if (last_packet_acked_sequence_number_ > round_trip_end_) {
      new_round_started = true;
      round_count_++;
      round_trip_end_ = last_packet_sent_sequence_number_;
    }
  }
  TryEnteringProbeRtt(now_ms);
  UpdateBandwidthAndMinRtt(now_ms, feedback_vector, bytes_acked_);
  if (new_round_started && !full_bandwidth_reached_) {
    full_bandwidth_reached_ = max_bandwidth_filter_->FullBandwidthReached(
        kStartupGrowthTarget, kMaxRoundsWithoutGrowth);
  }
  switch (mode_) {
    break;
    case STARTUP:
      TryExitingStartup();
      break;
    case DRAIN:
      TryExitingDrain(now_ms);
      break;
    case PROBE_BW:
      TryUpdatingCyclePhase(now_ms);
      break;
    case PROBE_RTT:
      TryExitingProbeRtt(now_ms, round_count_);
      break;
    case RECOVERY:
      TryExitingRecovery(new_round_started);
      break;
  }
  TryEnteringRecovery(new_round_started);  // Comment this line to disable
                                           // entering Recovery mode.
  for (uint16_t f : feedback_vector)
    AddToPastRtts(packet_stats_[f].ack_time_ms - packet_stats_[f].send_time_ms);
  CalculatePacingRate();
  size_t cwnd = congestion_window_->GetCongestionWindow(
      mode_, max_bandwidth_filter_->max_bandwidth_estimate_bps(),
      min_rtt_filter_->min_rtt_ms(), congestion_window_gain_);
  // Make sure we don't get stuck when pacing_rate is 0, because of simulation
  // tool specifics.
  if (!pacing_rate_bps_)
    pacing_rate_bps_ = 100;
  BWE_TEST_LOGGING_PLOT(1, "SendRate", now_ms, pacing_rate_bps_ / 1000);
  int64_t rate_for_pacer_bps = pacing_rate_bps_;
  int64_t rate_for_encoder_bps = pacing_rate_bps_;
  if (congestion_window_->data_inflight() >= cwnd * kCongestionWindowThreshold)
    rate_for_encoder_bps = 0;
  // We dont completely stop sending during PROBE_RTT, so we need encoder to
  // produce something, another way of doing this would be telling encoder to
  // stop and send padding instead of actual data.
  if (mode_ == PROBE_RTT)
    rate_for_encoder_bps = rate_for_pacer_bps * kEncoderRateGainForProbeRtt;
  // Send for 300 kbps for first 200 ms, so that BBR has data to work with.
  if (now_ms <= kDefaultDurationMs)
    observer_->OnNetworkChanged(
        kDefaultRatebps, kDefaultRatebps, false,
        clock_->TimeInMicroseconds() + kFeedbackIntervalsMs * 1000, cwnd);
  else
    observer_->OnNetworkChanged(
        rate_for_encoder_bps, rate_for_pacer_bps, mode_ == PROBE_RTT,
        clock_->TimeInMicroseconds() + kFeedbackIntervalsMs * 1000, cwnd);
}

size_t BbrBweSender::TargetCongestionWindow(float gain) {
  size_t target_congestion_window =
      congestion_window_->GetTargetCongestionWindow(
          max_bandwidth_filter_->max_bandwidth_estimate_bps(),
          min_rtt_filter_->min_rtt_ms(), gain);
  return target_congestion_window;
}

rtc::Optional<int64_t> BbrBweSender::CalculateBandwidthSample(
    size_t data_sent_bytes,
    int64_t send_time_delta_ms,
    size_t data_acked_bytes,
    int64_t ack_time_delta_ms) {
  rtc::Optional<int64_t> bandwidth_sample;
  if (send_time_delta_ms > 0)
    bandwidth_sample.emplace(data_sent_bytes * 8000 / send_time_delta_ms);
  rtc::Optional<int64_t> ack_rate;
  if (ack_time_delta_ms > 0)
    ack_rate.emplace(data_acked_bytes * 8000 / ack_time_delta_ms);
  // If send rate couldn't be calculated automaticaly set |bandwidth_sample| to
  // ack_rate.
  if (!bandwidth_sample)
    bandwidth_sample = ack_rate;
  if (bandwidth_sample && ack_rate)
    bandwidth_sample.emplace(std::min(*bandwidth_sample, *ack_rate));
  return bandwidth_sample;
}

void BbrBweSender::AddSampleForHighGain() {
  if (!high_gain_over_)
    return;
  high_gain_over_ = false;
  // Calculate data sent/acked and time elapsed only for packets sent during
  // high gain phase.
  size_t data_sent_bytes = data_sent_before_high_gain_ended_bytes_ -
                           data_sent_before_high_gain_started_bytes_;
  int64_t send_time_delta_ms = last_packet_send_time_during_high_gain_ms_ -
                               *first_packet_send_time_during_high_gain_ms_;
  size_t data_acked_bytes = data_acked_before_high_gain_ended_bytes_ -
                            data_acked_before_high_gain_started_bytes_;
  int64_t ack_time_delta_ms = last_packet_ack_time_during_high_gain_ms_ -
                              first_packet_ack_time_during_high_gain_ms_;
  rtc::Optional<int64_t> bandwidth_sample = CalculateBandwidthSample(
      data_sent_bytes, send_time_delta_ms, data_acked_bytes, ack_time_delta_ms);
  if (bandwidth_sample)
    max_bandwidth_filter_->AddBandwidthSample(*bandwidth_sample, round_count_);
  first_packet_send_time_during_high_gain_ms_.reset();
}

void BbrBweSender::UpdateBandwidthAndMinRtt(
    int64_t now_ms,
    const std::vector<uint16_t>& feedback_vector,
    int64_t bytes_acked) {
  rtc::Optional<int64_t> min_rtt_sample_ms;
  for (uint16_t f : feedback_vector) {
    PacketStats packet = packet_stats_[f];
    size_t data_sent_bytes =
        packet.data_sent_bytes - packet.data_sent_before_last_sent_packet_bytes;
    int64_t send_time_delta_ms =
        packet.last_sent_packet_send_time_ms - packet.send_time_ms;
    size_t data_acked_bytes = packet.data_acked_bytes -
                              packet.data_acked_before_last_acked_packet_bytes;
    int64_t ack_time_delta_ms =
        packet.ack_time_ms - packet.last_acked_packet_ack_time_ms;
    rtc::Optional<int64_t> bandwidth_sample =
        CalculateBandwidthSample(data_sent_bytes, send_time_delta_ms,
                                 data_acked_bytes, ack_time_delta_ms);
    if (bandwidth_sample)
      max_bandwidth_filter_->AddBandwidthSample(*bandwidth_sample,
                                                round_count_);
    // AddSampleForHighGain();  // Comment to disable bucket for high gain.
    if (!min_rtt_sample_ms)
      min_rtt_sample_ms.emplace(packet.ack_time_ms - packet.send_time_ms);
    else
      *min_rtt_sample_ms = std::min(*min_rtt_sample_ms,
                                    packet.ack_time_ms - packet.send_time_ms);
    BWE_TEST_LOGGING_PLOT(1, "MinRtt", now_ms,
                          packet.ack_time_ms - packet.send_time_ms);
  }
  // We only feed RTT samples into the min_rtt filter which were not produced
  // during 1.1 gain phase, to ensure they contain no queueing delay. But if the
  // rtt sample from 1.1 gain phase improves the current estimate then we should
  // make it as a new best estimate.
  if (pacing_gain_ <= 1.0f || !min_rtt_filter_->min_rtt_ms() ||
      *min_rtt_filter_->min_rtt_ms() >= *min_rtt_sample_ms)
    min_rtt_filter_->AddRttSample(*min_rtt_sample_ms, now_ms);
}

void BbrBweSender::EnterStartup() {
  mode_ = STARTUP;
  pacing_gain_ = kHighGain;
  congestion_window_gain_ = kHighGain;
}

void BbrBweSender::TryExitingStartup() {
  if (full_bandwidth_reached_) {
    mode_ = DRAIN;
    pacing_gain_ = kDrainGain;
    congestion_window_gain_ = kHighGain;
  }
}

void BbrBweSender::TryExitingDrain(int64_t now_ms) {
  if (congestion_window_->data_inflight() <=
      TargetCongestionWindow(kTargetCongestionWindowGain))
    EnterProbeBw(now_ms);
}

// Start probing with a random gain value, which is different form 0.75,
// starting with 0.75 doesn't offer any benefits as there are no queues to be
// drained.
void BbrBweSender::EnterProbeBw(int64_t now_ms) {
  mode_ = PROBE_BW;
  congestion_window_gain_ = kCruisingCongestionWindowGain;
  int index = rand_->Rand(kGainCycleLength - 2);
  if (index == 1)
    index = kGainCycleLength - 1;
  pacing_gain_ = kPacingGain[index];
  cycle_start_time_ms_ = now_ms;
  cycle_index_ = index;
}

void BbrBweSender::TryUpdatingCyclePhase(int64_t now_ms) {
  // Each phase should last rougly min_rtt ms time.
  bool advance_cycle_phase = false;
  if (min_rtt_filter_->min_rtt_ms())
    advance_cycle_phase =
        now_ms - cycle_start_time_ms_ > *min_rtt_filter_->min_rtt_ms();
  // If BBR was probing and it couldn't increase data inflight sufficiently in
  // one min_rtt time, continue probing. BBR design doc isn't clear about this,
  // but condition helps in quicker ramp-up and performs better.
  if (pacing_gain_ > 1.0 &&
      congestion_window_->data_inflight() <
          TargetCongestionWindow(kTargetCongestionWindowGainForHighGain))
    advance_cycle_phase = false;
  // If BBR has already drained queues there is no point in continuing draining
  // phase.
  if (pacing_gain_ < 1.0 &&
      congestion_window_->data_inflight() <= TargetCongestionWindow(1))
    advance_cycle_phase = true;
  if (advance_cycle_phase) {
    cycle_index_++;
    cycle_index_ %= kGainCycleLength;
    pacing_gain_ = kPacingGain[cycle_index_];
    cycle_start_time_ms_ = now_ms;
  }
}

void BbrBweSender::TryEnteringProbeRtt(int64_t now_ms) {
  if (min_rtt_filter_->MinRttExpired(now_ms) && mode_ != PROBE_RTT) {
    mode_ = PROBE_RTT;
    pacing_gain_ = 1;
    congestion_window_gain_ = kProbeRttCongestionWindowGain;
    probe_rtt_start_time_ms_ = now_ms;
    minimum_congestion_window_start_time_ms_.reset();
  }
}

// |minimum_congestion_window_start_time_|'s value is set to the first moment
// when data inflight was less then
// |CongestionWindow::kMinimumCongestionWindowBytes|, we should make sure that
// BBR has been in PROBE_RTT mode for at least one round or 200ms.
void BbrBweSender::TryExitingProbeRtt(int64_t now_ms, int64_t round) {
  if (!minimum_congestion_window_start_time_ms_) {
    if (congestion_window_->data_inflight() <=
        TargetCongestionWindow(kProbeRttCongestionWindowGain)) {
      minimum_congestion_window_start_time_ms_.emplace(now_ms);
      minimum_congestion_window_start_round_ = round;
    }
  } else {
    if (now_ms - *minimum_congestion_window_start_time_ms_ >=
            kProbeRttDurationMs &&
        round - minimum_congestion_window_start_round_ >=
            kProbeRttDurationRounds) {
      EnterProbeBw(now_ms);
    }
  }
}

void BbrBweSender::TryEnteringRecovery(bool new_round_started) {
  if (mode_ == RECOVERY || !new_round_started || !full_bandwidth_reached_ ||
      !min_rtt_filter_->min_rtt_ms())
    return;
  uint64_t increased_rtt_round_counter = 0;
  // If average RTT for past |kPastRttsFilterSize| rounds has been more than
  // some multiplier of min_rtt_ms enter Recovery.
  for (BbrBweSender::AverageRtt i : past_rtts_) {
    if (i.sum_of_rtts_ms / (int64_t)i.num_samples >=
        *min_rtt_filter_->min_rtt_ms() * kRttIncreaseThreshold)
      increased_rtt_round_counter++;
  }
  if (increased_rtt_round_counter < kPastRttsFilterSize)
    return;
  mode_ = RECOVERY;
  pacing_gain_ = kRecoveryPacingGain;
  congestion_window_gain_ = kRecoveryCongestionWindowGain;
}

void BbrBweSender::TryExitingRecovery(bool new_round_started) {
  if (mode_ != RECOVERY || !new_round_started || !full_bandwidth_reached_)
    return;
  // If average RTT for the past round has decreased sufficiently exit Recovery.
  if (!past_rtts_.empty()) {
    BbrBweSender::AverageRtt last_round_sample = past_rtts_.back();
    if (last_round_sample.sum_of_rtts_ms / last_round_sample.num_samples <=
        *min_rtt_filter_->min_rtt_ms() * kRttDecreaseThreshold) {
      EnterProbeBw(clock_->TimeInMilliseconds());
    }
  }
}

int64_t BbrBweSender::TimeUntilNextProcess() {
  return 50;
}

void BbrBweSender::OnPacketsSent(const Packets& packets) {
  for (Packet* packet : packets) {
    if (packet->GetPacketType() == Packet::kMedia) {
      MediaPacket* media_packet = static_cast<MediaPacket*>(packet);
      bytes_sent_ += media_packet->payload_size();
      PacketStats packet_stats = PacketStats(
          media_packet->sequence_number(), 0,
          media_packet->sender_timestamp_ms(), 0, last_packet_ack_time_,
          media_packet->payload_size(), 0, bytes_sent_, 0, bytes_acked_);
      packet_stats_[media_packet->sequence_number()] = packet_stats;
      last_packet_send_time_ = media_packet->sender_timestamp_ms();
      last_packet_sent_sequence_number_ = media_packet->sequence_number();
      // If this is the first packet sent for high gain phase, save data for it.
      if (!first_packet_send_time_during_high_gain_ms_ && pacing_gain_ > 1) {
        first_packet_send_time_during_high_gain_ms_.emplace(
            last_packet_send_time_);
        data_sent_before_high_gain_started_bytes_ =
            bytes_sent_ - media_packet->payload_size() / 2;
        first_packet_seq_num_during_high_gain_ =
            media_packet->sequence_number();
      }
      // This condition ensures that |last_packet_seq_num_during_high_gain_|
      // will contain a sequence number of the last packet sent during high gain
      // phase.
      if (pacing_gain_ > 1) {
        last_packet_send_time_during_high_gain_ms_ = last_packet_send_time_;
        data_sent_before_high_gain_ended_bytes_ =
            bytes_sent_ - media_packet->payload_size() / 2;
        last_packet_seq_num_during_high_gain_ = media_packet->sequence_number();
      }
      congestion_window_->PacketSent(media_packet->payload_size());
    }
  }
}

void BbrBweSender::Process() {}

BbrBweReceiver::BbrBweReceiver(int flow_id)
    : BweReceiver(flow_id, kReceivingRateTimeWindowMs),
      clock_(0),
      packet_feedbacks_(),
      last_feedback_ms_(0) {}

BbrBweReceiver::~BbrBweReceiver() {}

void BbrBweReceiver::ReceivePacket(int64_t arrival_time_ms,
                                   const MediaPacket& media_packet) {
  packet_feedbacks_.push_back(media_packet.sequence_number());
  BweReceiver::ReceivePacket(arrival_time_ms, media_packet);
}

FeedbackPacket* BbrBweReceiver::GetFeedback(int64_t now_ms) {
  last_feedback_ms_ = now_ms;
  int64_t corrected_send_time_ms = 0L;
  if (!received_packets_.empty()) {
    PacketIdentifierNode* latest = *(received_packets_.begin());
    corrected_send_time_ms =
        latest->send_time_ms + now_ms - latest->arrival_time_ms;
  }
  FeedbackPacket* fb = new BbrBweFeedback(
      flow_id_, now_ms * 1000, corrected_send_time_ms, packet_feedbacks_);
  packet_feedbacks_.clear();
  return fb;
}
}  // namespace bwe
}  // namespace testing
}  // namespace webrtc
