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:
parent
f70bc5eeff
commit
13ef7d25f6
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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_;
|
||||
|
||||
@ -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_
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user