Adds feedback only mode to GoogCC.

This CL adds a factory for creating a GoogCC network controller that
can be used without RTCP specific messages. This prepares for enabling
use of other underlying protocols as long as they can provide per
packet feedback.

Bug: None
Change-Id: I6671181949d97abd18843d0f4edf75040cc3f007
Reviewed-on: https://webrtc-review.googlesource.com/84583
Commit-Queue: Sebastian Jansson <srte@webrtc.org>
Reviewed-by: Björn Terelius <terelius@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24198}
This commit is contained in:
Sebastian Jansson 2018-08-06 13:20:36 +02:00 committed by Commit Bot
parent f70bc5eeff
commit 13ef7d25f6
4 changed files with 109 additions and 25 deletions

View File

@ -20,11 +20,26 @@ GoogCcNetworkControllerFactory::GoogCcNetworkControllerFactory(
std::unique_ptr<NetworkControllerInterface>
GoogCcNetworkControllerFactory::Create(NetworkControllerConfig config) {
return absl::make_unique<webrtc_cc::GoogCcNetworkController>(event_log_,
config);
config, false);
}
TimeDelta GoogCcNetworkControllerFactory::GetProcessInterval() const {
const int64_t kUpdateIntervalMs = 25;
return TimeDelta::ms(kUpdateIntervalMs);
}
GoogCcFeedbackNetworkControllerFactory::GoogCcFeedbackNetworkControllerFactory(
RtcEventLog* event_log)
: event_log_(event_log) {}
std::unique_ptr<NetworkControllerInterface>
GoogCcFeedbackNetworkControllerFactory::Create(NetworkControllerConfig config) {
return absl::make_unique<webrtc_cc::GoogCcNetworkController>(event_log_,
config, true);
}
TimeDelta GoogCcFeedbackNetworkControllerFactory::GetProcessInterval() const {
const int64_t kUpdateIntervalMs = 25;
return TimeDelta::ms(kUpdateIntervalMs);
}
} // namespace webrtc

View File

@ -14,6 +14,7 @@
#include <functional>
#include <limits>
#include <memory>
#include <numeric>
#include <string>
#include <utility>
#include <vector>
@ -38,6 +39,9 @@ namespace {
const char kCwndExperiment[] = "WebRTC-CwndExperiment";
const int64_t kDefaultAcceptedQueueMs = 250;
// From RTCPSender video report interval.
const TimeDelta kLossUpdateInterval = TimeDelta::ms(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.
@ -113,8 +117,10 @@ int64_t GetBpsOrDefault(const absl::optional<DataRate>& rate,
} // namespace
GoogCcNetworkController::GoogCcNetworkController(RtcEventLog* event_log,
NetworkControllerConfig config)
NetworkControllerConfig config,
bool feedback_only)
: event_log_(event_log),
packet_feedback_only_(feedback_only),
probe_controller_(new ProbeController()),
bandwidth_estimation_(
absl::make_unique<SendSideBandwidthEstimation>(event_log_)),
@ -214,6 +220,10 @@ NetworkControlUpdate GoogCcNetworkController::OnProcessInterval(
NetworkControlUpdate GoogCcNetworkController::OnRemoteBitrateReport(
RemoteBitrateReport msg) {
if (packet_feedback_only_) {
RTC_LOG(LS_ERROR) << "Received REMB for packet feedback only GoogCC";
return NetworkControlUpdate();
}
bandwidth_estimation_->UpdateReceiverEstimate(msg.receive_time.ms(),
msg.bandwidth.bps());
BWE_TEST_LOGGING_PLOT(1, "REMB_kbps", msg.receive_time.ms(),
@ -223,6 +233,8 @@ NetworkControlUpdate GoogCcNetworkController::OnRemoteBitrateReport(
NetworkControlUpdate GoogCcNetworkController::OnRoundTripTimeUpdate(
RoundTripTimeUpdate msg) {
if (packet_feedback_only_)
return NetworkControlUpdate();
if (msg.smoothed) {
delay_based_bwe_->OnRttUpdate(msg.round_trip_time.ms());
} else {
@ -301,6 +313,8 @@ GoogCcNetworkController::UpdateBitrateConstraints(
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(
@ -310,24 +324,59 @@ NetworkControlUpdate GoogCcNetworkController::OnTransportLossReport(
NetworkControlUpdate GoogCcNetworkController::OnTransportPacketsFeedback(
TransportPacketsFeedback report) {
int64_t feedback_rtt = -1;
for (const auto& packet_feedback : report.PacketsWithFeedback()) {
if (packet_feedback.sent_packet.has_value() &&
packet_feedback.receive_time.IsFinite()) {
int64_t rtt = report.feedback_time.ms() -
packet_feedback.sent_packet->send_time.ms();
// max() is used to account for feedback being delayed by the
// receiver.
feedback_rtt = std::max(rtt, feedback_rtt);
}
TimeDelta feedback_max_rtt = TimeDelta::MinusInfinity();
Timestamp max_recv_time = Timestamp::ms(0);
for (const auto& packet_feedback : report.ReceivedWithSendInfo()) {
TimeDelta rtt =
report.feedback_time - packet_feedback.sent_packet->send_time;
// max() is used to account for feedback being delayed by the
// receiver.
feedback_max_rtt = std::max(feedback_max_rtt, rtt);
max_recv_time = std::max(max_recv_time, packet_feedback.receive_time);
}
if (feedback_rtt > -1) {
feedback_rtts_.push_back(feedback_rtt);
const size_t kFeedbackRttWindow = 32;
if (feedback_rtts_.size() > kFeedbackRttWindow)
feedback_rtts_.pop_front();
min_feedback_rtt_ms_.emplace(
*std::min_element(feedback_rtts_.begin(), feedback_rtts_.end()));
if (feedback_max_rtt.IsFinite()) {
feedback_max_rtts_.push_back(feedback_max_rtt.ms());
const size_t kMaxFeedbackRttWindow = 32;
if (feedback_max_rtts_.size() > kMaxFeedbackRttWindow)
feedback_max_rtts_.pop_front();
min_feedback_max_rtt_ms_.emplace(*std::min_element(
feedback_max_rtts_.begin(), feedback_max_rtts_.end()));
}
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();
delay_based_bwe_->OnRttUpdate(mean_rtt_ms);
}
TimeDelta feedback_min_rtt = TimeDelta::PlusInfinity();
for (const auto& packet_feedback : report.ReceivedWithSendInfo()) {
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.ms(),
report.feedback_time.ms());
}
expected_packets_since_last_loss_update_ +=
report.PacketsWithFeedback().size();
for (const auto& packet_feedback : report.PacketsWithFeedback()) {
lost_packets_since_last_loss_update_ +=
packet_feedback.receive_time.IsFinite() ? 0 : 1;
}
if (report.feedback_time > next_loss_update_) {
next_loss_update_ += kLossUpdateInterval;
bandwidth_estimation_->UpdatePacketsLost(
expected_packets_since_last_loss_update_,
lost_packets_since_last_loss_update_, report.feedback_time.ms());
expected_packets_since_last_loss_update_ = 0;
lost_packets_since_last_loss_update_ = 0;
}
}
std::vector<PacketFeedback> received_feedback_vector =
@ -396,12 +445,12 @@ GoogCcNetworkController::MaybeUpdateCongestionWindow() {
return absl::nullopt;
// 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 (!min_feedback_rtt_ms_)
if (!min_feedback_max_rtt_ms_)
return absl::nullopt;
const DataSize kMinCwnd = DataSize::bytes(2 * 1500);
TimeDelta time_window =
TimeDelta::ms(*min_feedback_rtt_ms_ + accepted_queue_ms_);
TimeDelta::ms(*min_feedback_max_rtt_ms_ + accepted_queue_ms_);
DataSize data_window = last_bandwidth_ * time_window;
if (current_data_window_) {
data_window =
@ -410,7 +459,7 @@ GoogCcNetworkController::MaybeUpdateCongestionWindow() {
data_window = std::max(kMinCwnd, data_window);
}
current_data_window_ = data_window;
RTC_LOG(LS_INFO) << "Feedback rtt: " << *min_feedback_rtt_ms_
RTC_LOG(LS_INFO) << "Feedback rtt: " << *min_feedback_max_rtt_ms_
<< " Bitrate: " << last_bandwidth_.bps();
return data_window;
}

View File

@ -32,7 +32,8 @@ namespace webrtc_cc {
class GoogCcNetworkController : public NetworkControllerInterface {
public:
GoogCcNetworkController(RtcEventLog* event_log,
NetworkControllerConfig config);
NetworkControllerConfig config,
bool feedback_only);
~GoogCcNetworkController() override;
// NetworkControllerInterface
@ -65,6 +66,7 @@ class GoogCcNetworkController : public NetworkControllerInterface {
PacerConfig GetPacingRates(Timestamp at_time) const;
RtcEventLog* const event_log_;
const bool packet_feedback_only_;
const std::unique_ptr<ProbeController> probe_controller_;
@ -75,8 +77,12 @@ class GoogCcNetworkController : public NetworkControllerInterface {
absl::optional<NetworkControllerConfig> initial_config_;
std::deque<int64_t> feedback_rtts_;
absl::optional<int64_t> min_feedback_rtt_ms_;
Timestamp next_loss_update_ = Timestamp::ms(0);
int lost_packets_since_last_loss_update_ = 0;
int expected_packets_since_last_loss_update_ = 0;
std::deque<int64_t> feedback_max_rtts_;
absl::optional<int64_t> min_feedback_max_rtt_ms_;
DataRate last_bandwidth_;
absl::optional<TargetTransferRate> last_target_rate_;

View File

@ -29,6 +29,20 @@ class GoogCcNetworkControllerFactory
private:
RtcEventLog* const event_log_;
};
// Factory to create packet feedback only GoogCC, this can be used for
// connections providing packet receive time feedback but no other reports.
class GoogCcFeedbackNetworkControllerFactory
: public NetworkControllerFactoryInterface {
public:
explicit GoogCcFeedbackNetworkControllerFactory(RtcEventLog*);
std::unique_ptr<NetworkControllerInterface> Create(
NetworkControllerConfig config) override;
TimeDelta GetProcessInterval() const override;
private:
RtcEventLog* const event_log_;
};
} // namespace webrtc
#endif // MODULES_CONGESTION_CONTROLLER_GOOG_CC_INCLUDE_GOOG_CC_FACTORY_H_