webrtc/modules/congestion_controller/goog_cc/probe_bitrate_estimator.cc
Mirko Bonadei 317a1f09ed Use std::make_unique instead of absl::make_unique.
WebRTC is now using C++14 so there is no need to use the Abseil version
of std::make_unique.

This CL has been created with the following steps:

git grep -l absl::make_unique | sort | uniq > /tmp/make_unique.txt
git grep -l absl::WrapUnique | sort | uniq > /tmp/wrap_unique.txt
git grep -l "#include <memory>" | sort | uniq > /tmp/memory.txt

diff --new-line-format="" --unchanged-line-format="" \
  /tmp/make_unique.txt /tmp/wrap_unique.txt | sort | \
  uniq > /tmp/only_make_unique.txt
diff --new-line-format="" --unchanged-line-format="" \
  /tmp/only_make_unique.txt /tmp/memory.txt | \
  xargs grep -l "absl/memory" > /tmp/add-memory.txt

git grep -l "\babsl::make_unique\b" | \
  xargs sed -i "s/\babsl::make_unique\b/std::make_unique/g"

git checkout PRESUBMIT.py abseil-in-webrtc.md

cat /tmp/add-memory.txt | \
  xargs sed -i \
  's/#include "absl\/memory\/memory.h"/#include <memory>/g'
git cl format
# Manual fix order of the new inserted #include <memory>

cat /tmp/only_make_unique | xargs grep -l "#include <memory>" | \
  xargs sed -i '/#include "absl\/memory\/memory.h"/d'

git ls-files | grep BUILD.gn | \
  xargs sed -i '/\/\/third_party\/abseil-cpp\/absl\/memory/d'

python tools_webrtc/gn_check_autofix.py \
  -m tryserver.webrtc -b linux_rel

# Repead the gn_check_autofix step for other platforms

git ls-files | grep BUILD.gn | \
  xargs sed -i 's/absl\/memory:memory/absl\/memory/g'
git cl format

Bug: webrtc:10945
Change-Id: I3fe28ea80f4dd3ba3cf28effd151d5e1f19aff89
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/153221
Commit-Queue: Mirko Bonadei <mbonadei@webrtc.org>
Reviewed-by: Alessio Bazzica <alessiob@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29209}
2019-09-17 15:47:29 +00:00

199 lines
8.2 KiB
C++

/*
* Copyright (c) 2016 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/probe_bitrate_estimator.h"
#include <algorithm>
#include <memory>
#include "api/rtc_event_log/rtc_event_log.h"
#include "logging/rtc_event_log/events/rtc_event_probe_result_failure.h"
#include "logging/rtc_event_log/events/rtc_event_probe_result_success.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/numerics/safe_conversions.h"
namespace webrtc {
namespace {
// The minumum number of probes we need to receive feedback about in percent
// in order to have a valid estimate.
constexpr double kMinReceivedProbesRatio = .80;
// The minumum number of bytes we need to receive feedback about in percent
// in order to have a valid estimate.
constexpr double kMinReceivedBytesRatio = .80;
// The maximum |receive rate| / |send rate| ratio for a valid estimate.
constexpr float kMaxValidRatio = 2.0f;
// The minimum |receive rate| / |send rate| ratio assuming that the link is
// not saturated, i.e. we assume that we will receive at least
// kMinRatioForUnsaturatedLink * |send rate| if |send rate| is less than the
// link capacity.
constexpr float kMinRatioForUnsaturatedLink = 0.9f;
// The target utilization of the link. If we know true link capacity
// we'd like to send at 95% of that rate.
constexpr float kTargetUtilizationFraction = 0.95f;
// The maximum time period over which the cluster history is retained.
// This is also the maximum time period beyond which a probing burst is not
// expected to last.
constexpr TimeDelta kMaxClusterHistory = TimeDelta::Seconds<1>();
// The maximum time interval between first and the last probe on a cluster
// on the sender side as well as the receive side.
constexpr TimeDelta kMaxProbeInterval = TimeDelta::Seconds<1>();
} // namespace
ProbeBitrateEstimator::ProbeBitrateEstimator(RtcEventLog* event_log)
: event_log_(event_log) {}
ProbeBitrateEstimator::~ProbeBitrateEstimator() = default;
absl::optional<DataRate> ProbeBitrateEstimator::HandleProbeAndEstimateBitrate(
const PacketResult& packet_feedback) {
int cluster_id = packet_feedback.sent_packet.pacing_info.probe_cluster_id;
RTC_DCHECK_NE(cluster_id, PacedPacketInfo::kNotAProbe);
EraseOldClusters(packet_feedback.receive_time);
AggregatedCluster* cluster = &clusters_[cluster_id];
if (packet_feedback.sent_packet.send_time < cluster->first_send) {
cluster->first_send = packet_feedback.sent_packet.send_time;
}
if (packet_feedback.sent_packet.send_time > cluster->last_send) {
cluster->last_send = packet_feedback.sent_packet.send_time;
cluster->size_last_send = packet_feedback.sent_packet.size;
}
if (packet_feedback.receive_time < cluster->first_receive) {
cluster->first_receive = packet_feedback.receive_time;
cluster->size_first_receive = packet_feedback.sent_packet.size;
}
if (packet_feedback.receive_time > cluster->last_receive) {
cluster->last_receive = packet_feedback.receive_time;
}
cluster->size_total += packet_feedback.sent_packet.size;
cluster->num_probes += 1;
RTC_DCHECK_GT(
packet_feedback.sent_packet.pacing_info.probe_cluster_min_probes, 0);
RTC_DCHECK_GT(packet_feedback.sent_packet.pacing_info.probe_cluster_min_bytes,
0);
int min_probes =
packet_feedback.sent_packet.pacing_info.probe_cluster_min_probes *
kMinReceivedProbesRatio;
DataSize min_size =
DataSize::bytes(
packet_feedback.sent_packet.pacing_info.probe_cluster_min_bytes) *
kMinReceivedBytesRatio;
if (cluster->num_probes < min_probes || cluster->size_total < min_size)
return absl::nullopt;
TimeDelta send_interval = cluster->last_send - cluster->first_send;
TimeDelta receive_interval = cluster->last_receive - cluster->first_receive;
if (send_interval <= TimeDelta::Zero() || send_interval > kMaxProbeInterval ||
receive_interval <= TimeDelta::Zero() ||
receive_interval > kMaxProbeInterval) {
RTC_LOG(LS_INFO) << "Probing unsuccessful, invalid send/receive interval"
<< " [cluster id: " << cluster_id
<< "] [send interval: " << ToString(send_interval) << "]"
<< " [receive interval: " << ToString(receive_interval)
<< "]";
if (event_log_) {
event_log_->Log(std::make_unique<RtcEventProbeResultFailure>(
cluster_id, ProbeFailureReason::kInvalidSendReceiveInterval));
}
return absl::nullopt;
}
// Since the |send_interval| does not include the time it takes to actually
// send the last packet the size of the last sent packet should not be
// included when calculating the send bitrate.
RTC_DCHECK_GT(cluster->size_total, cluster->size_last_send);
DataSize send_size = cluster->size_total - cluster->size_last_send;
DataRate send_rate = send_size / send_interval;
// Since the |receive_interval| does not include the time it takes to
// actually receive the first packet the size of the first received packet
// should not be included when calculating the receive bitrate.
RTC_DCHECK_GT(cluster->size_total, cluster->size_first_receive);
DataSize receive_size = cluster->size_total - cluster->size_first_receive;
DataRate receive_rate = receive_size / receive_interval;
double ratio = receive_rate / send_rate;
if (ratio > kMaxValidRatio) {
RTC_LOG(LS_INFO) << "Probing unsuccessful, receive/send ratio too high"
<< " [cluster id: " << cluster_id
<< "] [send: " << ToString(send_size) << " / "
<< ToString(send_interval) << " = " << ToString(send_rate)
<< "]"
<< " [receive: " << ToString(receive_size) << " / "
<< ToString(receive_interval) << " = "
<< ToString(receive_rate) << " ]"
<< " [ratio: " << ToString(receive_rate) << " / "
<< ToString(send_rate) << " = " << ratio
<< " > kMaxValidRatio (" << kMaxValidRatio << ")]";
if (event_log_) {
event_log_->Log(std::make_unique<RtcEventProbeResultFailure>(
cluster_id, ProbeFailureReason::kInvalidSendReceiveRatio));
}
return absl::nullopt;
}
RTC_LOG(LS_INFO) << "Probing successful"
<< " [cluster id: " << cluster_id
<< "] [send: " << ToString(send_size) << " / "
<< ToString(send_interval) << " = " << ToString(send_rate)
<< " ]"
<< " [receive: " << ToString(receive_size) << " / "
<< ToString(receive_interval) << " = "
<< ToString(receive_rate) << "]";
DataRate res = std::min(send_rate, receive_rate);
// If we're receiving at significantly lower bitrate than we were sending at,
// it suggests that we've found the true capacity of the link. In this case,
// set the target bitrate slightly lower to not immediately overuse.
if (receive_rate < kMinRatioForUnsaturatedLink * send_rate) {
RTC_DCHECK_GT(send_rate, receive_rate);
res = kTargetUtilizationFraction * receive_rate;
}
if (event_log_) {
event_log_->Log(
std::make_unique<RtcEventProbeResultSuccess>(cluster_id, res.bps()));
}
last_estimate_ = res;
estimated_data_rate_ = res;
return res;
}
absl::optional<DataRate>
ProbeBitrateEstimator::FetchAndResetLastEstimatedBitrate() {
absl::optional<DataRate> estimated_data_rate = estimated_data_rate_;
estimated_data_rate_.reset();
return estimated_data_rate;
}
absl::optional<DataRate> ProbeBitrateEstimator::last_estimate() const {
return last_estimate_;
}
void ProbeBitrateEstimator::EraseOldClusters(Timestamp timestamp) {
for (auto it = clusters_.begin(); it != clusters_.end();) {
if (it->second.last_receive + kMaxClusterHistory < timestamp) {
it = clusters_.erase(it);
} else {
++it;
}
}
}
} // namespace webrtc