| Index: webrtc/modules/congestion_controller/delay_based_bwe.cc
|
| diff --git a/webrtc/modules/congestion_controller/delay_based_bwe.cc b/webrtc/modules/congestion_controller/delay_based_bwe.cc
|
| index bb13aba37a5eef68b399b13c39c274890dce46c9..a7d2788ff862d56ad874ee4b4c77e162f0bd565f 100644
|
| --- a/webrtc/modules/congestion_controller/delay_based_bwe.cc
|
| +++ b/webrtc/modules/congestion_controller/delay_based_bwe.cc
|
| @@ -25,50 +25,21 @@
|
| #include "webrtc/typedefs.h"
|
|
|
| namespace {
|
| -enum {
|
| - kTimestampGroupLengthMs = 5,
|
| - kAbsSendTimeFraction = 18,
|
| - kAbsSendTimeInterArrivalUpshift = 8,
|
| - kInterArrivalShift = kAbsSendTimeFraction + kAbsSendTimeInterArrivalUpshift,
|
| - kInitialProbingIntervalMs = 2000,
|
| - kMinClusterSize = 4,
|
| - kMaxProbePackets = 15,
|
| - kExpectedNumberOfProbes = 3
|
| -};
|
| -
|
| -static const double kTimestampToMs =
|
| +constexpr int kTimestampGroupLengthMs = 5;
|
| +constexpr int kAbsSendTimeFraction = 18;
|
| +constexpr int kAbsSendTimeInterArrivalUpshift = 8;
|
| +constexpr int kInterArrivalShift =
|
| + kAbsSendTimeFraction + kAbsSendTimeInterArrivalUpshift;
|
| +constexpr double kTimestampToMs =
|
| 1000.0 / static_cast<double>(1 << kInterArrivalShift);
|
|
|
| -template <typename K, typename V>
|
| -std::vector<K> Keys(const std::map<K, V>& map) {
|
| - std::vector<K> keys;
|
| - keys.reserve(map.size());
|
| - for (typename std::map<K, V>::const_iterator it = map.begin();
|
| - it != map.end(); ++it) {
|
| - keys.push_back(it->first);
|
| - }
|
| - return keys;
|
| -}
|
| -
|
| -uint32_t ConvertMsTo24Bits(int64_t time_ms) {
|
| - uint32_t time_24_bits =
|
| - static_cast<uint32_t>(
|
| - ((static_cast<uint64_t>(time_ms) << kAbsSendTimeFraction) + 500) /
|
| - 1000) &
|
| - 0x00FFFFFF;
|
| - return time_24_bits;
|
| -}
|
| +// This ssrc is used to fulfill the current API but will be removed
|
| +// after the API has been changed.
|
| +constexpr uint32_t kFixedSsrc = 0;
|
| } // namespace
|
|
|
| namespace webrtc {
|
|
|
| -void DelayBasedBwe::AddCluster(std::list<Cluster>* clusters, Cluster* cluster) {
|
| - cluster->send_mean_ms /= static_cast<float>(cluster->count);
|
| - cluster->recv_mean_ms /= static_cast<float>(cluster->count);
|
| - cluster->mean_size /= cluster->count;
|
| - clusters->push_back(*cluster);
|
| -}
|
| -
|
| DelayBasedBwe::DelayBasedBwe(RemoteBitrateObserver* observer, Clock* clock)
|
| : clock_(clock),
|
| observer_(observer),
|
| @@ -76,124 +47,14 @@ DelayBasedBwe::DelayBasedBwe(RemoteBitrateObserver* observer, Clock* clock)
|
| estimator_(),
|
| detector_(OverUseDetectorOptions()),
|
| incoming_bitrate_(kBitrateWindowMs, 8000),
|
| - total_probes_received_(0),
|
| first_packet_time_ms_(-1),
|
| last_update_ms_(-1),
|
| + last_seen_packet_ms_(-1),
|
| uma_recorded_(false) {
|
| RTC_DCHECK(observer_);
|
| - // NOTE! The BitrateEstimatorTest relies on this EXACT log line.
|
| - LOG(LS_INFO) << "RemoteBitrateEstimatorAbsSendTime: Instantiating.";
|
| network_thread_.DetachFromThread();
|
| }
|
|
|
| -void DelayBasedBwe::ComputeClusters(std::list<Cluster>* clusters) const {
|
| - Cluster current;
|
| - int64_t prev_send_time = -1;
|
| - int64_t prev_recv_time = -1;
|
| - int last_probe_cluster_id = -1;
|
| - for (std::list<Probe>::const_iterator it = probes_.begin();
|
| - it != probes_.end(); ++it) {
|
| - if (last_probe_cluster_id == -1)
|
| - last_probe_cluster_id = it->cluster_id;
|
| - if (prev_send_time >= 0) {
|
| - int send_delta_ms = it->send_time_ms - prev_send_time;
|
| - int recv_delta_ms = it->recv_time_ms - prev_recv_time;
|
| - if (send_delta_ms >= 1 && recv_delta_ms >= 1) {
|
| - ++current.num_above_min_delta;
|
| - }
|
| - if (it->cluster_id != last_probe_cluster_id) {
|
| - if (current.count >= kMinClusterSize)
|
| - AddCluster(clusters, ¤t);
|
| - current = Cluster();
|
| - }
|
| - current.send_mean_ms += send_delta_ms;
|
| - current.recv_mean_ms += recv_delta_ms;
|
| - current.mean_size += it->payload_size;
|
| - ++current.count;
|
| - last_probe_cluster_id = it->cluster_id;
|
| - }
|
| - prev_send_time = it->send_time_ms;
|
| - prev_recv_time = it->recv_time_ms;
|
| - }
|
| - if (current.count >= kMinClusterSize)
|
| - AddCluster(clusters, ¤t);
|
| -}
|
| -
|
| -std::list<DelayBasedBwe::Cluster>::const_iterator DelayBasedBwe::FindBestProbe(
|
| - const std::list<Cluster>& clusters) const {
|
| - int highest_probe_bitrate_bps = 0;
|
| - std::list<Cluster>::const_iterator best_it = clusters.end();
|
| - for (std::list<Cluster>::const_iterator it = clusters.begin();
|
| - it != clusters.end(); ++it) {
|
| - if (it->send_mean_ms == 0 || it->recv_mean_ms == 0)
|
| - continue;
|
| - int send_bitrate_bps = it->mean_size * 8 * 1000 / it->send_mean_ms;
|
| - int recv_bitrate_bps = it->mean_size * 8 * 1000 / it->recv_mean_ms;
|
| - if (it->num_above_min_delta > it->count / 2 &&
|
| - (it->recv_mean_ms - it->send_mean_ms <= 2.0f &&
|
| - it->send_mean_ms - it->recv_mean_ms <= 5.0f)) {
|
| - int probe_bitrate_bps =
|
| - std::min(it->GetSendBitrateBps(), it->GetRecvBitrateBps());
|
| - if (probe_bitrate_bps > highest_probe_bitrate_bps) {
|
| - highest_probe_bitrate_bps = probe_bitrate_bps;
|
| - best_it = it;
|
| - }
|
| - } else {
|
| - LOG(LS_INFO) << "Probe failed, sent at " << send_bitrate_bps
|
| - << " bps, received at " << recv_bitrate_bps
|
| - << " bps. Mean send delta: " << it->send_mean_ms
|
| - << " ms, mean recv delta: " << it->recv_mean_ms
|
| - << " ms, num probes: " << it->count;
|
| - break;
|
| - }
|
| - }
|
| - return best_it;
|
| -}
|
| -
|
| -DelayBasedBwe::ProbeResult DelayBasedBwe::ProcessClusters(int64_t now_ms) {
|
| - std::list<Cluster> clusters;
|
| - ComputeClusters(&clusters);
|
| - if (clusters.empty()) {
|
| - // If we reach the max number of probe packets and still have no clusters,
|
| - // we will remove the oldest one.
|
| - if (probes_.size() >= kMaxProbePackets)
|
| - probes_.pop_front();
|
| - return ProbeResult::kNoUpdate;
|
| - }
|
| -
|
| - std::list<Cluster>::const_iterator best_it = FindBestProbe(clusters);
|
| - if (best_it != clusters.end()) {
|
| - int probe_bitrate_bps =
|
| - std::min(best_it->GetSendBitrateBps(), best_it->GetRecvBitrateBps());
|
| - // Make sure that a probe sent on a lower bitrate than our estimate can't
|
| - // reduce the estimate.
|
| - if (IsBitrateImproving(probe_bitrate_bps)) {
|
| - LOG(LS_INFO) << "Probe successful, sent at "
|
| - << best_it->GetSendBitrateBps() << " bps, received at "
|
| - << best_it->GetRecvBitrateBps()
|
| - << " bps. Mean send delta: " << best_it->send_mean_ms
|
| - << " ms, mean recv delta: " << best_it->recv_mean_ms
|
| - << " ms, num probes: " << best_it->count;
|
| - remote_rate_.SetEstimate(probe_bitrate_bps, now_ms);
|
| - return ProbeResult::kBitrateUpdated;
|
| - }
|
| - }
|
| -
|
| - // Not probing and received non-probe packet, or finished with current set
|
| - // of probes.
|
| - if (clusters.size() >= kExpectedNumberOfProbes)
|
| - probes_.clear();
|
| - return ProbeResult::kNoUpdate;
|
| -}
|
| -
|
| -bool DelayBasedBwe::IsBitrateImproving(int new_bitrate_bps) const {
|
| - bool initial_probe = !remote_rate_.ValidEstimate() && new_bitrate_bps > 0;
|
| - bool bitrate_above_estimate =
|
| - remote_rate_.ValidEstimate() &&
|
| - new_bitrate_bps > static_cast<int>(remote_rate_.LatestEstimate());
|
| - return initial_probe || bitrate_above_estimate;
|
| -}
|
| -
|
| void DelayBasedBwe::IncomingPacketFeedbackVector(
|
| const std::vector<PacketInfo>& packet_feedback_vector) {
|
| RTC_DCHECK(network_thread_.CalledOnValidThread());
|
| @@ -204,82 +65,61 @@ void DelayBasedBwe::IncomingPacketFeedbackVector(
|
| uma_recorded_ = true;
|
| }
|
| for (const auto& packet_info : packet_feedback_vector) {
|
| - IncomingPacketInfo(packet_info.arrival_time_ms,
|
| - ConvertMsTo24Bits(packet_info.send_time_ms),
|
| - packet_info.payload_size, 0,
|
| - packet_info.probe_cluster_id);
|
| + IncomingPacketInfo(packet_info);
|
| }
|
| }
|
|
|
| -void DelayBasedBwe::IncomingPacketInfo(int64_t arrival_time_ms,
|
| - uint32_t send_time_24bits,
|
| - size_t payload_size,
|
| - uint32_t ssrc,
|
| - int probe_cluster_id) {
|
| - assert(send_time_24bits < (1ul << 24));
|
| - // Shift up send time to use the full 32 bits that inter_arrival works with,
|
| - // so wrapping works properly.
|
| - uint32_t timestamp = send_time_24bits << kAbsSendTimeInterArrivalUpshift;
|
| - int64_t send_time_ms = static_cast<int64_t>(timestamp) * kTimestampToMs;
|
| -
|
| +void DelayBasedBwe::IncomingPacketInfo(const PacketInfo& info) {
|
| int64_t now_ms = clock_->TimeInMilliseconds();
|
| - // TODO(holmer): SSRCs are only needed for REMB, should be broken out from
|
| - // here.
|
| - incoming_bitrate_.Update(payload_size, arrival_time_ms);
|
|
|
| if (first_packet_time_ms_ == -1)
|
| first_packet_time_ms_ = now_ms;
|
|
|
| - uint32_t ts_delta = 0;
|
| - int64_t t_delta = 0;
|
| - int size_delta = 0;
|
| -
|
| + incoming_bitrate_.Update(info.payload_size, info.arrival_time_ms);
|
| bool update_estimate = false;
|
| uint32_t target_bitrate_bps = 0;
|
| - std::vector<uint32_t> ssrcs;
|
| {
|
| rtc::CritScope lock(&crit_);
|
|
|
| - TimeoutStreams(now_ms);
|
| - RTC_DCHECK(inter_arrival_.get());
|
| - RTC_DCHECK(estimator_.get());
|
| - ssrcs_[ssrc] = now_ms;
|
| + // Reset if the stream has timed out.
|
| + if (last_seen_packet_ms_ == -1 ||
|
| + now_ms - last_seen_packet_ms_ > kStreamTimeOutMs) {
|
| + inter_arrival_.reset(new InterArrival(
|
| + (kTimestampGroupLengthMs << kInterArrivalShift) / 1000,
|
| + kTimestampToMs, true));
|
| + estimator_.reset(new OveruseEstimator(OverUseDetectorOptions()));
|
| + }
|
| + last_seen_packet_ms_ = now_ms;
|
|
|
| - // For now only try to detect probes while we don't have a valid estimate,
|
| - // and make sure the packet was paced. We currently assume that only packets
|
| - // larger than 200 bytes are paced by the sender.
|
| - if (probe_cluster_id != PacketInfo::kNotAProbe &&
|
| - payload_size > PacedSender::kMinProbePacketSize &&
|
| - (!remote_rate_.ValidEstimate() ||
|
| - now_ms - first_packet_time_ms_ < kInitialProbingIntervalMs)) {
|
| - // TODO(holmer): Use a map instead to get correct order?
|
| - if (total_probes_received_ < kMaxProbePackets) {
|
| - int send_delta_ms = -1;
|
| - int recv_delta_ms = -1;
|
| - if (!probes_.empty()) {
|
| - send_delta_ms = send_time_ms - probes_.back().send_time_ms;
|
| - recv_delta_ms = arrival_time_ms - probes_.back().recv_time_ms;
|
| - }
|
| - LOG(LS_INFO) << "Probe packet received: send time=" << send_time_ms
|
| - << " ms, recv time=" << arrival_time_ms
|
| - << " ms, send delta=" << send_delta_ms
|
| - << " ms, recv delta=" << recv_delta_ms << " ms.";
|
| - }
|
| - probes_.push_back(
|
| - Probe(send_time_ms, arrival_time_ms, payload_size, probe_cluster_id));
|
| - ++total_probes_received_;
|
| - // Make sure that a probe which updated the bitrate immediately has an
|
| - // effect by calling the OnReceiveBitrateChanged callback.
|
| - if (ProcessClusters(now_ms) == ProbeResult::kBitrateUpdated)
|
| + if (info.probe_cluster_id != PacketInfo::kNotAProbe) {
|
| + ProbingResult probe_result =
|
| + probe_bitrate_estimator_.PacketFeedback(info);
|
| + if (probe_result.valid()) {
|
| + remote_rate_.SetEstimate(probe_result.bps, probe_result.timestamp);
|
| update_estimate = true;
|
| + }
|
| }
|
| - if (inter_arrival_->ComputeDeltas(timestamp, arrival_time_ms, now_ms,
|
| - payload_size, &ts_delta, &t_delta,
|
| +
|
| + uint32_t send_time_24bits =
|
| + static_cast<uint32_t>(((static_cast<uint64_t>(info.send_time_ms)
|
| + << kAbsSendTimeFraction) +
|
| + 500) /
|
| + 1000) &
|
| + 0x00FFFFFF;
|
| + // Shift up send time to use the full 32 bits that inter_arrival works with,
|
| + // so wrapping works properly.
|
| + uint32_t timestamp = send_time_24bits << kAbsSendTimeInterArrivalUpshift;
|
| +
|
| + uint32_t ts_delta = 0;
|
| + int64_t t_delta = 0;
|
| + int size_delta = 0;
|
| + if (inter_arrival_->ComputeDeltas(timestamp, info.arrival_time_ms, now_ms,
|
| + info.payload_size, &ts_delta, &t_delta,
|
| &size_delta)) {
|
| double ts_delta_ms = (1000.0 * ts_delta) / (1 << kInterArrivalShift);
|
| estimator_->Update(t_delta, ts_delta_ms, size_delta, detector_.State());
|
| detector_.Detect(estimator_->offset(), ts_delta_ms,
|
| - estimator_->num_of_deltas(), arrival_time_ms);
|
| + estimator_->num_of_deltas(), info.arrival_time_ms);
|
| }
|
|
|
| if (!update_estimate) {
|
| @@ -290,7 +130,7 @@ void DelayBasedBwe::IncomingPacketInfo(int64_t arrival_time_ms,
|
| update_estimate = true;
|
| } else if (detector_.State() == kBwOverusing) {
|
| rtc::Optional<uint32_t> incoming_rate =
|
| - incoming_bitrate_.Rate(arrival_time_ms);
|
| + incoming_bitrate_.Rate(info.arrival_time_ms);
|
| if (incoming_rate &&
|
| remote_rate_.TimeToReduceFurther(now_ms, *incoming_rate)) {
|
| update_estimate = true;
|
| @@ -303,17 +143,17 @@ void DelayBasedBwe::IncomingPacketInfo(int64_t arrival_time_ms,
|
| // We also have to update the estimate immediately if we are overusing
|
| // and the target bitrate is too high compared to what we are receiving.
|
| const RateControlInput input(detector_.State(),
|
| - incoming_bitrate_.Rate(arrival_time_ms),
|
| + incoming_bitrate_.Rate(info.arrival_time_ms),
|
| estimator_->var_noise());
|
| remote_rate_.Update(&input, now_ms);
|
| target_bitrate_bps = remote_rate_.UpdateBandwidthEstimate(now_ms);
|
| update_estimate = remote_rate_.ValidEstimate();
|
| - ssrcs = Keys(ssrcs_);
|
| }
|
| }
|
| +
|
| if (update_estimate) {
|
| last_update_ms_ = now_ms;
|
| - observer_->OnReceiveBitrateChanged(ssrcs, target_bitrate_bps);
|
| + observer_->OnReceiveBitrateChanged({kFixedSsrc}, target_bitrate_bps);
|
| }
|
| }
|
|
|
| @@ -324,34 +164,12 @@ int64_t DelayBasedBwe::TimeUntilNextProcess() {
|
| return kDisabledModuleTime;
|
| }
|
|
|
| -void DelayBasedBwe::TimeoutStreams(int64_t now_ms) {
|
| - for (Ssrcs::iterator it = ssrcs_.begin(); it != ssrcs_.end();) {
|
| - if ((now_ms - it->second) > kStreamTimeOutMs) {
|
| - ssrcs_.erase(it++);
|
| - } else {
|
| - ++it;
|
| - }
|
| - }
|
| - if (ssrcs_.empty()) {
|
| - // We can't update the estimate if we don't have any active streams.
|
| - inter_arrival_.reset(
|
| - new InterArrival((kTimestampGroupLengthMs << kInterArrivalShift) / 1000,
|
| - kTimestampToMs, true));
|
| - estimator_.reset(new OveruseEstimator(OverUseDetectorOptions()));
|
| - // We deliberately don't reset the first_packet_time_ms_ here for now since
|
| - // we only probe for bandwidth in the beginning of a call right now.
|
| - }
|
| -}
|
| -
|
| void DelayBasedBwe::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) {
|
| rtc::CritScope lock(&crit_);
|
| remote_rate_.SetRtt(avg_rtt_ms);
|
| }
|
|
|
| -void DelayBasedBwe::RemoveStream(uint32_t ssrc) {
|
| - rtc::CritScope lock(&crit_);
|
| - ssrcs_.erase(ssrc);
|
| -}
|
| +void DelayBasedBwe::RemoveStream(uint32_t ssrc) {}
|
|
|
| bool DelayBasedBwe::LatestEstimate(std::vector<uint32_t>* ssrcs,
|
| uint32_t* bitrate_bps) const {
|
| @@ -362,15 +180,11 @@ bool DelayBasedBwe::LatestEstimate(std::vector<uint32_t>* ssrcs,
|
| RTC_DCHECK(ssrcs);
|
| RTC_DCHECK(bitrate_bps);
|
| rtc::CritScope lock(&crit_);
|
| - if (!remote_rate_.ValidEstimate()) {
|
| + if (!remote_rate_.ValidEstimate())
|
| return false;
|
| - }
|
| - *ssrcs = Keys(ssrcs_);
|
| - if (ssrcs_.empty()) {
|
| - *bitrate_bps = 0;
|
| - } else {
|
| - *bitrate_bps = remote_rate_.LatestEstimate();
|
| - }
|
| +
|
| + *ssrcs = {kFixedSsrc};
|
| + *bitrate_bps = remote_rate_.LatestEstimate();
|
| return true;
|
| }
|
|
|
|
|