diff --git a/call/rtp_transport_controller_send.cc b/call/rtp_transport_controller_send.cc index abb3ad05e4e..090c261e4e5 100644 --- a/call/rtp_transport_controller_send.cc +++ b/call/rtp_transport_controller_send.cc @@ -46,8 +46,7 @@ const RtpKeepAliveConfig& RtpTransportControllerSend::keepalive_config() const { void RtpTransportControllerSend::SetAllocatedSendBitrateLimits( int min_send_bitrate_bps, int max_padding_bitrate_bps) { - send_side_cc_.SetSendBitrateLimits(min_send_bitrate_bps, - max_padding_bitrate_bps); + pacer_.SetSendBitrateLimits(min_send_bitrate_bps, max_padding_bitrate_bps); } void RtpTransportControllerSend::SetKeepAliveConfig( diff --git a/modules/bitrate_controller/bitrate_controller_unittest.cc b/modules/bitrate_controller/bitrate_controller_unittest.cc index 8bd7800ee7d..66ca5b9558d 100644 --- a/modules/bitrate_controller/bitrate_controller_unittest.cc +++ b/modules/bitrate_controller/bitrate_controller_unittest.cc @@ -340,11 +340,11 @@ TEST_F(BitrateControllerTest, OneBitrateObserverMultipleReportBlocks) { report_blocks.clear(); // All packets lost on stream with few packets, no back-off. - report_blocks.push_back(CreateReportBlock(1, 2, 0, sequence_number[0])); + report_blocks.push_back(CreateReportBlock(1, 2, 1, sequence_number[0])); report_blocks.push_back(CreateReportBlock(1, 3, 255, sequence_number[1])); bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, 50, time_ms); EXPECT_EQ(bitrate_observer_.last_bitrate_, last_bitrate); - EXPECT_EQ(WeightedLoss(20, 0, 1, 255), bitrate_observer_.last_fraction_loss_); + EXPECT_EQ(WeightedLoss(20, 1, 1, 255), bitrate_observer_.last_fraction_loss_); EXPECT_EQ(50, bitrate_observer_.last_rtt_); last_bitrate = bitrate_observer_.last_bitrate_; sequence_number[0] += 20; diff --git a/modules/bitrate_controller/send_side_bandwidth_estimation.cc b/modules/bitrate_controller/send_side_bandwidth_estimation.cc index 323c210a545..d3bce593f36 100644 --- a/modules/bitrate_controller/send_side_bandwidth_estimation.cc +++ b/modules/bitrate_controller/send_side_bandwidth_estimation.cc @@ -105,7 +105,7 @@ bool ReadBweLossExperimentParameters(float* low_loss_threshold, } // namespace SendSideBandwidthEstimation::SendSideBandwidthEstimation(RtcEventLog* event_log) - : lost_packets_since_last_loss_update_(0), + : lost_packets_since_last_loss_update_Q8_(0), expected_packets_since_last_loss_update_(0), current_bitrate_bps_(0), min_bitrate_configured_(congestion_controller::GetMinBitrateBps()), @@ -125,7 +125,6 @@ SendSideBandwidthEstimation::SendSideBandwidthEstimation(RtcEventLog* event_log) initially_lost_packets_(0), bitrate_at_2_seconds_kbps_(0), uma_update_state_(kNoUpdate), - uma_rtt_state_(kNoUpdate), rampup_uma_stats_updated_(kNumUmaRampupMetrics, false), event_log_(event_log), last_rtc_event_log_ms_(-1), @@ -207,28 +206,24 @@ void SendSideBandwidthEstimation::UpdateDelayBasedEstimate( } void SendSideBandwidthEstimation::UpdateReceiverBlock(uint8_t fraction_loss, - int64_t rtt_ms, + int64_t rtt, int number_of_packets, int64_t now_ms) { - const int kRoundingConstant = 128; - int packets_lost = (static_cast(fraction_loss) * number_of_packets + - kRoundingConstant) >> - 8; - UpdatePacketsLost(packets_lost, number_of_packets, now_ms); - UpdateRtt(rtt_ms, now_ms); -} - -void SendSideBandwidthEstimation::UpdatePacketsLost(int packets_lost, - int number_of_packets, - int64_t now_ms) { last_feedback_ms_ = now_ms; if (first_report_time_ms_ == -1) first_report_time_ms_ = now_ms; + // Update RTT if we were able to compute an RTT based on this RTCP. + // FlexFEC doesn't send RTCP SR, which means we won't be able to compute RTT. + if (rtt > 0) + last_round_trip_time_ms_ = rtt; + // Check sequence number diff and weight loss report if (number_of_packets > 0) { + // Calculate number of lost packets. + const int num_lost_packets_Q8 = fraction_loss * number_of_packets; // Accumulate reports. - lost_packets_since_last_loss_update_ += packets_lost; + lost_packets_since_last_loss_update_Q8_ += num_lost_packets_Q8; expected_packets_since_last_loss_update_ += number_of_packets; // Don't generate a loss rate until it can be based on enough packets. @@ -236,22 +231,21 @@ void SendSideBandwidthEstimation::UpdatePacketsLost(int packets_lost, return; has_decreased_since_last_fraction_loss_ = false; - int64_t lost_q8 = lost_packets_since_last_loss_update_ << 8; - int64_t expected = expected_packets_since_last_loss_update_; - last_fraction_loss_ = std::min(lost_q8 / expected, 255); + last_fraction_loss_ = lost_packets_since_last_loss_update_Q8_ / + expected_packets_since_last_loss_update_; // Reset accumulators. - - lost_packets_since_last_loss_update_ = 0; + lost_packets_since_last_loss_update_Q8_ = 0; expected_packets_since_last_loss_update_ = 0; last_packet_report_ms_ = now_ms; UpdateEstimate(now_ms); } - UpdateUmaStatsPacketsLost(now_ms, packets_lost); + UpdateUmaStats(now_ms, rtt, (fraction_loss * number_of_packets) >> 8); } -void SendSideBandwidthEstimation::UpdateUmaStatsPacketsLost(int64_t now_ms, - int packets_lost) { +void SendSideBandwidthEstimation::UpdateUmaStats(int64_t now_ms, + int64_t rtt, + int lost_packets) { int bitrate_kbps = static_cast((current_bitrate_bps_ + 500) / 1000); for (size_t i = 0; i < kNumUmaRampupMetrics; ++i) { if (!rampup_uma_stats_updated_[i] && @@ -262,12 +256,14 @@ void SendSideBandwidthEstimation::UpdateUmaStatsPacketsLost(int64_t now_ms, } } if (IsInStartPhase(now_ms)) { - initially_lost_packets_ += packets_lost; + initially_lost_packets_ += lost_packets; } else if (uma_update_state_ == kNoUpdate) { uma_update_state_ = kFirstDone; bitrate_at_2_seconds_kbps_ = bitrate_kbps; RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitiallyLostPackets", initially_lost_packets_, 0, 100, 50); + RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitialRtt", static_cast(rtt), 0, + 2000, 50); RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitialBandwidthEstimate", bitrate_at_2_seconds_kbps_, 0, 2000, 50); } else if (uma_update_state_ == kFirstDone && @@ -280,19 +276,6 @@ void SendSideBandwidthEstimation::UpdateUmaStatsPacketsLost(int64_t now_ms, } } -void SendSideBandwidthEstimation::UpdateRtt(int64_t rtt_ms, int64_t now_ms) { - // Update RTT if we were able to compute an RTT based on this RTCP. - // FlexFEC doesn't send RTCP SR, which means we won't be able to compute RTT. - if (rtt_ms > 0) - last_round_trip_time_ms_ = rtt_ms; - - if (!IsInStartPhase(now_ms) && uma_rtt_state_ == kNoUpdate) { - uma_rtt_state_ = kDone; - RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitialRtt", static_cast(rtt_ms), 0, - 2000, 50); - } -} - void SendSideBandwidthEstimation::UpdateEstimate(int64_t now_ms) { uint32_t new_bitrate = current_bitrate_bps_; // We trust the REMB and/or delay-based estimate during the first 2 seconds if @@ -374,7 +357,7 @@ void SendSideBandwidthEstimation::UpdateEstimate(int64_t now_ms) { new_bitrate *= 0.8; // Reset accumulators since we've already acted on missing feedback and // shouldn't to act again on these old lost packets. - lost_packets_since_last_loss_update_ = 0; + lost_packets_since_last_loss_update_Q8_ = 0; expected_packets_since_last_loss_update_ = 0; last_timeout_ms_ = now_ms; } diff --git a/modules/bitrate_controller/send_side_bandwidth_estimation.h b/modules/bitrate_controller/send_side_bandwidth_estimation.h index d09184c0bf2..59d1c3280d2 100644 --- a/modules/bitrate_controller/send_side_bandwidth_estimation.h +++ b/modules/bitrate_controller/send_side_bandwidth_estimation.h @@ -42,18 +42,10 @@ class SendSideBandwidthEstimation { // Call when we receive a RTCP message with a ReceiveBlock. void UpdateReceiverBlock(uint8_t fraction_loss, - int64_t rtt_ms, + int64_t rtt, int number_of_packets, int64_t now_ms); - // Call when we receive a RTCP message with a ReceiveBlock. - void UpdatePacketsLost(int packets_lost, - int number_of_packets, - int64_t now_ms); - - // Call when we receive a RTCP message with a ReceiveBlock. - void UpdateRtt(int64_t rtt, int64_t now_ms); - void SetBitrates(int send_bitrate, int min_bitrate, int max_bitrate); @@ -66,7 +58,7 @@ class SendSideBandwidthEstimation { bool IsInStartPhase(int64_t now_ms) const; - void UpdateUmaStatsPacketsLost(int64_t now_ms, int packets_lost); + void UpdateUmaStats(int64_t now_ms, int64_t rtt, int lost_packets); // Updates history of min bitrates. // After this method returns min_bitrate_history_.front().second contains the @@ -80,7 +72,7 @@ class SendSideBandwidthEstimation { std::deque > min_bitrate_history_; // incoming filters - int lost_packets_since_last_loss_update_; + int lost_packets_since_last_loss_update_Q8_; int expected_packets_since_last_loss_update_; uint32_t current_bitrate_bps_; @@ -103,7 +95,6 @@ class SendSideBandwidthEstimation { int initially_lost_packets_; int bitrate_at_2_seconds_kbps_; UmaState uma_update_state_; - UmaState uma_rtt_state_; std::vector rampup_uma_stats_updated_; RtcEventLog* event_log_; int64_t last_rtc_event_log_ms_; diff --git a/modules/congestion_controller/BUILD.gn b/modules/congestion_controller/BUILD.gn index eee190dde9f..23f5333dd93 100644 --- a/modules/congestion_controller/BUILD.gn +++ b/modules/congestion_controller/BUILD.gn @@ -22,8 +22,8 @@ rtc_static_library("congestion_controller") { sources = [ "include/receive_side_congestion_controller.h", "include/send_side_congestion_controller.h", - "pacer_controller.cc", - "pacer_controller.h", + "probe_controller.cc", + "probe_controller.h", "receive_side_congestion_controller.cc", "send_side_congestion_controller.cc", ] @@ -37,14 +37,13 @@ rtc_static_library("congestion_controller") { } deps = [ - ":goog_cc", + ":delay_based_bwe", + ":estimators", ":transport_feedback", "..:module_api", "../..:webrtc_common", "../../rtc_base:checks", "../../rtc_base:rate_limiter", - "../../rtc_base:rtc_task_queue_api", - "../../rtc_base:sequenced_task_checker", "../../system_wrappers", "../../system_wrappers:field_trial_api", "../../system_wrappers:metrics_api", @@ -53,7 +52,6 @@ rtc_static_library("congestion_controller") { "../pacing", "../remote_bitrate_estimator", "../rtp_rtcp:rtp_rtcp_format", - "./network_control", ] if (!build_with_mozilla) { @@ -71,54 +69,11 @@ rtc_static_library("transport_feedback") { ] deps = [ - "..:module_api", - "../../rtc_base:checks", - "../../rtc_base:rtc_base_approved", - "../../system_wrappers", - "../rtp_rtcp:rtp_rtcp_format", - ] -} - -rtc_static_library("goog_cc") { - configs += [ ":bwe_test_logging" ] - sources = [ - "alr_detector.cc", - "alr_detector.h", - "goog_cc_network_control.cc", - "goog_cc_network_control.h", - "include/goog_cc_factory.h", - "probe_controller.cc", - "probe_controller.h", - ] - - # TODO(jschuh): Bug 1348: fix this warning. - configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] - - if (!build_with_chromium && is_clang) { - # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163). - suppressed_configs += [ "//build/config/clang:find_bad_constructs" ] - } - - deps = [ - ":delay_based_bwe", - ":estimators", - "..:module_api", - "../..:webrtc_common", - "../../:typedefs", - "../../api:optional", - "../../logging:rtc_event_log_api", - "../../logging:rtc_event_pacing", + "../../modules:module_api", "../../rtc_base:checks", "../../rtc_base:rtc_base_approved", - "../../rtc_base/experiments:alr_experiment", - "../../system_wrappers", - "../../system_wrappers:field_trial_api", - "../../system_wrappers:metrics_api", - "../bitrate_controller", - "../pacing", - "../remote_bitrate_estimator", + "../../system_wrappers:system_wrappers", "../rtp_rtcp:rtp_rtcp_format", - "./network_control", ] } @@ -155,7 +110,7 @@ rtc_source_set("estimators") { "../../rtc_base:rtc_numerics", "../../system_wrappers:field_trial_api", "../../system_wrappers:metrics_api", - "../remote_bitrate_estimator", + "../remote_bitrate_estimator:remote_bitrate_estimator", "../rtp_rtcp:rtp_rtcp_format", ] } @@ -190,16 +145,25 @@ if (rtc_include_tests) { testonly = true sources = [ + "acknowledged_bitrate_estimator_unittest.cc", "congestion_controller_unittests_helper.cc", "congestion_controller_unittests_helper.h", + "delay_based_bwe_unittest.cc", + "delay_based_bwe_unittest_helper.cc", + "delay_based_bwe_unittest_helper.h", + "median_slope_estimator_unittest.cc", + "probe_bitrate_estimator_unittest.cc", + "probe_controller_unittest.cc", "receive_side_congestion_controller_unittest.cc", "send_side_congestion_controller_unittest.cc", "send_time_history_unittest.cc", "transport_feedback_adapter_unittest.cc", + "trendline_estimator_unittest.cc", ] deps = [ ":congestion_controller", - ":goog_cc_unittests", + ":delay_based_bwe", + ":estimators", ":mock_congestion_controller", ":transport_feedback", "../../logging:mocks", @@ -210,51 +174,12 @@ if (rtc_include_tests) { "../../system_wrappers", "../../test:field_trial", "../../test:test_support", + "../bitrate_controller:bitrate_controller", "../bitrate_controller:mocks", "../pacing:mock_paced_sender", "../pacing:pacing", "../remote_bitrate_estimator:remote_bitrate_estimator", "../rtp_rtcp:rtp_rtcp_format", - "./network_control", - "//testing/gmock", - ] - if (!build_with_chromium && is_clang) { - # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163). - suppressed_configs += [ "//build/config/clang:find_bad_constructs" ] - } - } - - rtc_source_set("goog_cc_unittests") { - testonly = true - - sources = [ - "acknowledged_bitrate_estimator_unittest.cc", - "alr_detector_unittest.cc", - "delay_based_bwe_unittest.cc", - "delay_based_bwe_unittest_helper.cc", - "delay_based_bwe_unittest_helper.h", - "median_slope_estimator_unittest.cc", - "probe_bitrate_estimator_unittest.cc", - "probe_controller_unittest.cc", - "trendline_estimator_unittest.cc", - ] - deps = [ - ":delay_based_bwe", - ":estimators", - ":goog_cc", - "../../rtc_base:checks", - "../../rtc_base:rtc_base_approved", - "../../rtc_base:rtc_base_tests_utils", - "../../rtc_base/experiments:alr_experiment", - "../../system_wrappers", - "../../test:field_trial", - "../../test:test_support", - "../pacing", - "../remote_bitrate_estimator", - "../rtp_rtcp:rtp_rtcp_format", - "./network_control", - "./network_control:network_control_unittests", - "//testing/gmock", ] if (!build_with_chromium && is_clang) { # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163). diff --git a/modules/congestion_controller/acknowledged_bitrate_estimator.cc b/modules/congestion_controller/acknowledged_bitrate_estimator.cc index ec1a6f278ea..1e75ee6e925 100644 --- a/modules/congestion_controller/acknowledged_bitrate_estimator.cc +++ b/modules/congestion_controller/acknowledged_bitrate_estimator.cc @@ -27,8 +27,6 @@ bool IsInSendTimeHistory(const PacketFeedback& packet) { AcknowledgedBitrateEstimator::AcknowledgedBitrateEstimator() : AcknowledgedBitrateEstimator(rtc::MakeUnique()) {} -AcknowledgedBitrateEstimator::~AcknowledgedBitrateEstimator() {} - AcknowledgedBitrateEstimator::AcknowledgedBitrateEstimator( std::unique_ptr bitrate_estimator) : bitrate_estimator_(std::move(bitrate_estimator)) {} diff --git a/modules/congestion_controller/acknowledged_bitrate_estimator.h b/modules/congestion_controller/acknowledged_bitrate_estimator.h index c009e8682f7..72c1023044c 100644 --- a/modules/congestion_controller/acknowledged_bitrate_estimator.h +++ b/modules/congestion_controller/acknowledged_bitrate_estimator.h @@ -27,7 +27,6 @@ class AcknowledgedBitrateEstimator { std::unique_ptr bitrate_estimator); AcknowledgedBitrateEstimator(); - ~AcknowledgedBitrateEstimator(); void IncomingPacketFeedbackVector( const std::vector& packet_feedback_vector); diff --git a/modules/congestion_controller/delay_based_bwe.cc b/modules/congestion_controller/delay_based_bwe.cc index b053ef42af0..9f0e01dc2d6 100644 --- a/modules/congestion_controller/delay_based_bwe.cc +++ b/modules/congestion_controller/delay_based_bwe.cc @@ -85,8 +85,9 @@ DelayBasedBwe::Result::Result(bool probe, uint32_t target_bitrate_bps) DelayBasedBwe::Result::~Result() {} -DelayBasedBwe::DelayBasedBwe(RtcEventLog* event_log) +DelayBasedBwe::DelayBasedBwe(RtcEventLog* event_log, const Clock* clock) : event_log_(event_log), + clock_(clock), inter_arrival_(), delay_detector_(), last_seen_packet_ms_(-1), @@ -113,8 +114,7 @@ DelayBasedBwe::~DelayBasedBwe() {} DelayBasedBwe::Result DelayBasedBwe::IncomingPacketFeedbackVector( const std::vector& packet_feedback_vector, - rtc::Optional acked_bitrate_bps, - int64_t at_time_ms) { + rtc::Optional acked_bitrate_bps) { RTC_DCHECK(std::is_sorted(packet_feedback_vector.begin(), packet_feedback_vector.end(), PacketFeedbackComparator())); @@ -141,7 +141,7 @@ DelayBasedBwe::Result DelayBasedBwe::IncomingPacketFeedbackVector( if (packet_feedback.send_time_ms < 0) continue; delayed_feedback = false; - IncomingPacketFeedback(packet_feedback, at_time_ms); + IncomingPacketFeedback(packet_feedback); if (prev_detector_state == BandwidthUsage::kBwUnderusing && delay_detector_->State() == BandwidthUsage::kBwNormal) { recovered_from_overuse = true; @@ -157,8 +157,7 @@ DelayBasedBwe::Result DelayBasedBwe::IncomingPacketFeedbackVector( } } else { consecutive_delayed_feedbacks_ = 0; - return MaybeUpdateEstimate(acked_bitrate_bps, recovered_from_overuse, - at_time_ms); + return MaybeUpdateEstimate(acked_bitrate_bps, recovered_from_overuse); } return Result(); } @@ -181,9 +180,8 @@ DelayBasedBwe::Result DelayBasedBwe::OnLongFeedbackDelay( } void DelayBasedBwe::IncomingPacketFeedback( - const PacketFeedback& packet_feedback, - int64_t at_time_ms) { - int64_t now_ms = at_time_ms; + const PacketFeedback& packet_feedback) { + int64_t now_ms = clock_->TimeInMilliseconds(); // Reset if the stream has timed out. if (last_seen_packet_ms_ == -1 || now_ms - last_seen_packet_ms_ > kStreamTimeOutMs) { @@ -225,10 +223,9 @@ void DelayBasedBwe::IncomingPacketFeedback( DelayBasedBwe::Result DelayBasedBwe::MaybeUpdateEstimate( rtc::Optional acked_bitrate_bps, - bool recovered_from_overuse, - int64_t at_time_ms) { + bool recovered_from_overuse) { Result result; - int64_t now_ms = at_time_ms; + int64_t now_ms = clock_->TimeInMilliseconds(); rtc::Optional probe_bitrate_bps = probe_bitrate_estimator_.FetchAndResetLastEstimatedBitrateBps(); @@ -292,7 +289,7 @@ bool DelayBasedBwe::UpdateEstimate(int64_t now_ms, return rate_control_.ValidEstimate(); } -void DelayBasedBwe::OnRttUpdate(int64_t avg_rtt_ms) { +void DelayBasedBwe::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) { rate_control_.SetRtt(avg_rtt_ms); } diff --git a/modules/congestion_controller/delay_based_bwe.h b/modules/congestion_controller/delay_based_bwe.h index 654fe54719d..dbe759ebf5f 100644 --- a/modules/congestion_controller/delay_based_bwe.h +++ b/modules/congestion_controller/delay_based_bwe.h @@ -42,14 +42,13 @@ class DelayBasedBwe { bool recovered_from_overuse; }; - explicit DelayBasedBwe(RtcEventLog* event_log); + DelayBasedBwe(RtcEventLog* event_log, const Clock* clock); virtual ~DelayBasedBwe(); Result IncomingPacketFeedbackVector( const std::vector& packet_feedback_vector, - rtc::Optional acked_bitrate_bps, - int64_t at_time_ms); - void OnRttUpdate(int64_t avg_rtt_ms); + rtc::Optional acked_bitrate_bps); + void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms); bool LatestEstimate(std::vector* ssrcs, uint32_t* bitrate_bps) const; void SetStartBitrate(int start_bitrate_bps); @@ -57,12 +56,10 @@ class DelayBasedBwe { int64_t GetExpectedBwePeriodMs() const; private: - void IncomingPacketFeedback(const PacketFeedback& packet_feedback, - int64_t at_time_ms); + void IncomingPacketFeedback(const PacketFeedback& packet_feedback); Result OnLongFeedbackDelay(int64_t arrival_time_ms); Result MaybeUpdateEstimate(rtc::Optional acked_bitrate_bps, - bool request_probe, - int64_t at_time_ms); + bool request_probe); // Updates the current remote rate estimate and returns true if a valid // estimate exists. bool UpdateEstimate(int64_t now_ms, @@ -71,6 +68,7 @@ class DelayBasedBwe { rtc::RaceChecker network_race_; RtcEventLog* const event_log_; + const Clock* const clock_; std::unique_ptr inter_arrival_; std::unique_ptr delay_detector_; int64_t last_seen_packet_ms_; diff --git a/modules/congestion_controller/delay_based_bwe_unittest.cc b/modules/congestion_controller/delay_based_bwe_unittest.cc index d5fb8bfc3c2..250cb036a32 100644 --- a/modules/congestion_controller/delay_based_bwe_unittest.cc +++ b/modules/congestion_controller/delay_based_bwe_unittest.cc @@ -24,13 +24,12 @@ constexpr int kNumProbesCluster1 = 8; const PacedPacketInfo kPacingInfo0(0, kNumProbesCluster0, 2000); const PacedPacketInfo kPacingInfo1(1, kNumProbesCluster1, 4000); constexpr float kTargetUtilizationFraction = 0.95f; -constexpr int64_t kDummyTimestamp = 1000; } // namespace TEST_F(DelayBasedBweTest, NoCrashEmptyFeedback) { std::vector packet_feedback_vector; - bitrate_estimator_->IncomingPacketFeedbackVector( - packet_feedback_vector, rtc::nullopt, kDummyTimestamp); + bitrate_estimator_->IncomingPacketFeedbackVector(packet_feedback_vector, + rtc::nullopt); } TEST_F(DelayBasedBweTest, NoCrashOnlyLostFeedback) { @@ -41,8 +40,8 @@ TEST_F(DelayBasedBweTest, NoCrashOnlyLostFeedback) { packet_feedback_vector.push_back(PacketFeedback(PacketFeedback::kNotReceived, PacketFeedback::kNoSendTime, 1, 1500, PacedPacketInfo())); - bitrate_estimator_->IncomingPacketFeedbackVector( - packet_feedback_vector, rtc::nullopt, kDummyTimestamp); + bitrate_estimator_->IncomingPacketFeedbackVector(packet_feedback_vector, + rtc::nullopt); } TEST_F(DelayBasedBweTest, ProbeDetection) { diff --git a/modules/congestion_controller/delay_based_bwe_unittest_helper.cc b/modules/congestion_controller/delay_based_bwe_unittest_helper.cc index 0b005b58e80..b441e998cde 100644 --- a/modules/congestion_controller/delay_based_bwe_unittest_helper.cc +++ b/modules/congestion_controller/delay_based_bwe_unittest_helper.cc @@ -152,7 +152,7 @@ DelayBasedBweTest::DelayBasedBweTest() : clock_(100000000), acknowledged_bitrate_estimator_( rtc::MakeUnique()), - bitrate_estimator_(new DelayBasedBwe(nullptr)), + bitrate_estimator_(new DelayBasedBwe(nullptr, &clock_)), stream_generator_(new test::StreamGenerator(1e6, // Capacity. clock_.TimeInMicroseconds())), arrival_time_offset_ms_(0), @@ -187,8 +187,7 @@ void DelayBasedBweTest::IncomingFeedback(int64_t arrival_time_ms, acknowledged_bitrate_estimator_->IncomingPacketFeedbackVector(packets); DelayBasedBwe::Result result = bitrate_estimator_->IncomingPacketFeedbackVector( - packets, acknowledged_bitrate_estimator_->bitrate_bps(), - clock_.TimeInMilliseconds()); + packets, acknowledged_bitrate_estimator_->bitrate_bps()); const uint32_t kDummySsrc = 0; if (result.updated) { bitrate_observer_.OnReceiveBitrateChanged({kDummySsrc}, @@ -223,8 +222,7 @@ bool DelayBasedBweTest::GenerateAndProcessFrame(uint32_t ssrc, acknowledged_bitrate_estimator_->IncomingPacketFeedbackVector(packets); DelayBasedBwe::Result result = bitrate_estimator_->IncomingPacketFeedbackVector( - packets, acknowledged_bitrate_estimator_->bitrate_bps(), - clock_.TimeInMilliseconds()); + packets, acknowledged_bitrate_estimator_->bitrate_bps()); const uint32_t kDummySsrc = 0; if (result.updated) { bitrate_observer_.OnReceiveBitrateChanged({kDummySsrc}, diff --git a/modules/congestion_controller/goog_cc_network_control.cc b/modules/congestion_controller/goog_cc_network_control.cc deleted file mode 100644 index b6e473d68ac..00000000000 --- a/modules/congestion_controller/goog_cc_network_control.cc +++ /dev/null @@ -1,425 +0,0 @@ -/* - * Copyright (c) 2018 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_network_control.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "modules/congestion_controller/acknowledged_bitrate_estimator.h" -#include "modules/congestion_controller/alr_detector.h" -#include "modules/congestion_controller/include/goog_cc_factory.h" -#include "modules/congestion_controller/probe_controller.h" -#include "modules/remote_bitrate_estimator/include/bwe_defines.h" -#include "modules/remote_bitrate_estimator/test/bwe_test_logging.h" -#include "rtc_base/checks.h" -#include "rtc_base/format_macros.h" -#include "rtc_base/logging.h" -#include "rtc_base/ptr_util.h" -#include "rtc_base/timeutils.h" -#include "system_wrappers/include/field_trial.h" - -namespace webrtc { -namespace { - -const char kCwndExperiment[] = "WebRTC-CwndExperiment"; -const int64_t kDefaultAcceptedQueueMs = 250; - -// 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. -// Increasing this factor will result in lower delays in cases of bitrate -// overshoots from the encoder. -const float kDefaultPaceMultiplier = 2.5f; - -bool CwndExperimentEnabled() { - std::string experiment_string = - webrtc::field_trial::FindFullName(kCwndExperiment); - // The experiment is enabled iff the field trial string begins with "Enabled". - return experiment_string.find("Enabled") == 0; -} - -bool ReadCwndExperimentParameter(int64_t* accepted_queue_ms) { - RTC_DCHECK(accepted_queue_ms); - std::string experiment_string = - webrtc::field_trial::FindFullName(kCwndExperiment); - int parsed_values = - sscanf(experiment_string.c_str(), "Enabled-%" PRId64, accepted_queue_ms); - if (parsed_values == 1) { - RTC_CHECK_GE(*accepted_queue_ms, 0) - << "Accepted must be greater than or equal to 0."; - return true; - } - return false; -} - -// Makes sure that the bitrate and the min, max values are in valid range. -static void ClampBitrates(int64_t* bitrate_bps, - int64_t* min_bitrate_bps, - int64_t* max_bitrate_bps) { - // TODO(holmer): We should make sure the default bitrates are set to 10 kbps, - // and that we don't try to set the min bitrate to 0 from any applications. - // The congestion controller should allow a min bitrate of 0. - if (*min_bitrate_bps < congestion_controller::GetMinBitrateBps()) - *min_bitrate_bps = congestion_controller::GetMinBitrateBps(); - if (*max_bitrate_bps > 0) - *max_bitrate_bps = std::max(*min_bitrate_bps, *max_bitrate_bps); - if (*bitrate_bps > 0) - *bitrate_bps = std::max(*min_bitrate_bps, *bitrate_bps); -} - -std::vector ReceivedPacketsFeedbackAsRtp( - const TransportPacketsFeedback report) { - std::vector packet_feedback_vector; - for (auto& fb : report.PacketsWithFeedback()) { - if (fb.receive_time.IsFinite()) { - PacketFeedback pf(fb.receive_time.ms(), 0); - pf.creation_time_ms = report.feedback_time.ms(); - if (fb.sent_packet.has_value()) { - pf.payload_size = fb.sent_packet->size.bytes(); - pf.pacing_info = fb.sent_packet->pacing_info; - pf.send_time_ms = fb.sent_packet->send_time.ms(); - } else { - pf.send_time_ms = PacketFeedback::kNoSendTime; - } - packet_feedback_vector.push_back(pf); - } - } - return packet_feedback_vector; -} - -} // namespace - -GoogCcNetworkControllerFactory::GoogCcNetworkControllerFactory( - RtcEventLog* event_log) - : event_log_(event_log) {} - -NetworkControllerInterface::uptr GoogCcNetworkControllerFactory::Create( - NetworkControllerObserver* observer) { - return rtc::MakeUnique(event_log_, observer); -} - -TimeDelta GoogCcNetworkControllerFactory::GetProcessInterval() const { - const int64_t kUpdateIntervalMs = 25; - return TimeDelta::ms(kUpdateIntervalMs); -} - -GoogCcNetworkController::GoogCcNetworkController( - RtcEventLog* event_log, - NetworkControllerObserver* observer) - : event_log_(event_log), - observer_(observer), - probe_controller_(new ProbeController(observer_)), - bandwidth_estimation_( - rtc::MakeUnique(event_log_)), - alr_detector_(rtc::MakeUnique()), - delay_based_bwe_(new DelayBasedBwe(event_log_)), - acknowledged_bitrate_estimator_( - rtc::MakeUnique()), - pacing_factor_(kDefaultPaceMultiplier), - min_pacing_rate_(DataRate::Zero()), - max_padding_rate_(DataRate::Zero()), - in_cwnd_experiment_(CwndExperimentEnabled()), - accepted_queue_ms_(kDefaultAcceptedQueueMs) { - delay_based_bwe_->SetMinBitrate(congestion_controller::GetMinBitrateBps()); - if (in_cwnd_experiment_ && - !ReadCwndExperimentParameter(&accepted_queue_ms_)) { - RTC_LOG(LS_WARNING) << "Failed to parse parameters for CwndExperiment " - "from field trial string. Experiment disabled."; - in_cwnd_experiment_ = false; - } -} - -GoogCcNetworkController::~GoogCcNetworkController() {} - -void GoogCcNetworkController::OnNetworkAvailability(NetworkAvailability msg) { - probe_controller_->OnNetworkAvailability(msg); -} - -void GoogCcNetworkController::OnNetworkRouteChange(NetworkRouteChange msg) { - int64_t min_bitrate_bps = msg.constraints.min_data_rate.bps(); - int64_t max_bitrate_bps = -1; - int64_t start_bitrate_bps = -1; - - if (msg.constraints.max_data_rate.IsFinite()) - max_bitrate_bps = msg.constraints.max_data_rate.bps(); - if (msg.constraints.starting_rate.IsFinite()) - start_bitrate_bps = msg.constraints.starting_rate.bps(); - - ClampBitrates(&start_bitrate_bps, &min_bitrate_bps, &max_bitrate_bps); - - bandwidth_estimation_ = - rtc::MakeUnique(event_log_); - bandwidth_estimation_->SetBitrates(start_bitrate_bps, min_bitrate_bps, - max_bitrate_bps); - delay_based_bwe_.reset(new DelayBasedBwe(event_log_)); - acknowledged_bitrate_estimator_.reset(new AcknowledgedBitrateEstimator()); - delay_based_bwe_->SetStartBitrate(start_bitrate_bps); - delay_based_bwe_->SetMinBitrate(min_bitrate_bps); - - probe_controller_->Reset(msg.at_time.ms()); - probe_controller_->SetBitrates(min_bitrate_bps, start_bitrate_bps, - max_bitrate_bps, msg.at_time.ms()); - - MaybeTriggerOnNetworkChanged(msg.at_time); -} - -void GoogCcNetworkController::OnProcessInterval(ProcessInterval msg) { - bandwidth_estimation_->UpdateEstimate(msg.at_time.ms()); - rtc::Optional start_time_ms = - alr_detector_->GetApplicationLimitedRegionStartTime(); - probe_controller_->SetAlrStartTimeMs(start_time_ms); - probe_controller_->Process(msg.at_time.ms()); - MaybeTriggerOnNetworkChanged(msg.at_time); -} - -void GoogCcNetworkController::OnRemoteBitrateReport(RemoteBitrateReport msg) { - bandwidth_estimation_->UpdateReceiverEstimate(msg.receive_time.ms(), - msg.bandwidth.bps()); - BWE_TEST_LOGGING_PLOT(1, "REMB_kbps", msg.receive_time.ms(), - msg.bandwidth.bps() / 1000); -} - -void GoogCcNetworkController::OnRoundTripTimeUpdate(RoundTripTimeUpdate msg) { - if (msg.smoothed) { - delay_based_bwe_->OnRttUpdate(msg.round_trip_time.ms()); - } else { - bandwidth_estimation_->UpdateRtt(msg.round_trip_time.ms(), - msg.receive_time.ms()); - } -} - -void GoogCcNetworkController::OnSentPacket(SentPacket sent_packet) { - alr_detector_->OnBytesSent(sent_packet.size.bytes(), - sent_packet.send_time.ms()); -} - -void GoogCcNetworkController::OnStreamsConfig(StreamsConfig msg) { - probe_controller_->EnablePeriodicAlrProbing(msg.requests_alr_probing); - - bool pacing_changed = false; - if (msg.pacing_factor && *msg.pacing_factor != pacing_factor_) { - pacing_factor_ = *msg.pacing_factor; - pacing_changed = true; - } - if (msg.min_pacing_rate && *msg.min_pacing_rate != min_pacing_rate_) { - min_pacing_rate_ = *msg.min_pacing_rate; - pacing_changed = true; - } - if (msg.max_padding_rate && *msg.max_padding_rate != max_padding_rate_) { - max_padding_rate_ = *msg.max_padding_rate; - pacing_changed = true; - } - if (pacing_changed) - UpdatePacingRates(msg.at_time); -} - -void GoogCcNetworkController::OnTargetRateConstraints( - TargetRateConstraints constraints) { - int64_t min_bitrate_bps = constraints.min_data_rate.bps(); - int64_t max_bitrate_bps = -1; - int64_t start_bitrate_bps = -1; - - if (constraints.max_data_rate.IsFinite()) - max_bitrate_bps = constraints.max_data_rate.bps(); - if (constraints.starting_rate.IsFinite()) - start_bitrate_bps = constraints.starting_rate.bps(); - - ClampBitrates(&start_bitrate_bps, &min_bitrate_bps, &max_bitrate_bps); - - probe_controller_->SetBitrates(min_bitrate_bps, start_bitrate_bps, - max_bitrate_bps, constraints.at_time.ms()); - - bandwidth_estimation_->SetBitrates(start_bitrate_bps, min_bitrate_bps, - max_bitrate_bps); - if (start_bitrate_bps > 0) - delay_based_bwe_->SetStartBitrate(start_bitrate_bps); - delay_based_bwe_->SetMinBitrate(min_bitrate_bps); - - MaybeTriggerOnNetworkChanged(constraints.at_time); -} - -void GoogCcNetworkController::OnTransportLossReport(TransportLossReport msg) { - int64_t total_packets_delta = - msg.packets_received_delta + msg.packets_lost_delta; - bandwidth_estimation_->UpdatePacketsLost( - msg.packets_lost_delta, total_packets_delta, msg.receive_time.ms()); -} - -void 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); - } - } - 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())); - } - - std::vector received_feedback_vector = - ReceivedPacketsFeedbackAsRtp(report); - - rtc::Optional alr_start_time = - alr_detector_->GetApplicationLimitedRegionStartTime(); - - if (previously_in_alr && !alr_start_time.has_value()) { - int64_t now_ms = report.feedback_time.ms(); - acknowledged_bitrate_estimator_->SetAlrEndedTimeMs(now_ms); - probe_controller_->SetAlrEndedTimeMs(now_ms); - } - previously_in_alr = alr_start_time.has_value(); - acknowledged_bitrate_estimator_->IncomingPacketFeedbackVector( - received_feedback_vector); - DelayBasedBwe::Result result; - result = delay_based_bwe_->IncomingPacketFeedbackVector( - received_feedback_vector, acknowledged_bitrate_estimator_->bitrate_bps(), - report.feedback_time.ms()); - if (result.updated) { - if (result.probe) { - bandwidth_estimation_->SetSendBitrate(result.target_bitrate_bps); - } - // Since SetSendBitrate now resets the delay-based estimate, we have to call - // UpdateDelayBasedEstimate after SetSendBitrate. - bandwidth_estimation_->UpdateDelayBasedEstimate(report.feedback_time.ms(), - result.target_bitrate_bps); - // Update the estimate in the ProbeController, in case we want to probe. - MaybeTriggerOnNetworkChanged(report.feedback_time); - } - if (result.recovered_from_overuse) { - probe_controller_->SetAlrStartTimeMs(alr_start_time); - probe_controller_->RequestProbe(report.feedback_time.ms()); - } - MaybeUpdateCongestionWindow(); -} - -void GoogCcNetworkController::MaybeUpdateCongestionWindow() { - if (!in_cwnd_experiment_) - return; - // 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_) - return; - if (!last_estimate_.has_value()) - return; - const DataSize kMinCwnd = DataSize::bytes(2 * 1500); - TimeDelta time_window = - TimeDelta::ms(*min_feedback_rtt_ms_ + accepted_queue_ms_); - DataSize data_window = last_estimate_->bandwidth * time_window; - CongestionWindow msg; - msg.enabled = true; - msg.data_window = std::max(kMinCwnd, data_window); - observer_->OnCongestionWindow(msg); - RTC_LOG(LS_INFO) << "Feedback rtt: " << *min_feedback_rtt_ms_ - << " Bitrate: " << last_estimate_->bandwidth.bps(); -} - -void GoogCcNetworkController::MaybeTriggerOnNetworkChanged(Timestamp at_time) { - int32_t estimated_bitrate_bps; - uint8_t fraction_loss; - int64_t rtt_ms; - - bool estimate_changed = GetNetworkParameters( - &estimated_bitrate_bps, &fraction_loss, &rtt_ms, at_time); - if (estimate_changed) { - TimeDelta bwe_period = - TimeDelta::ms(delay_based_bwe_->GetExpectedBwePeriodMs()); - - NetworkEstimate new_estimate; - new_estimate.at_time = at_time; - new_estimate.round_trip_time = TimeDelta::ms(rtt_ms); - new_estimate.bandwidth = DataRate::bps(estimated_bitrate_bps); - new_estimate.loss_rate_ratio = fraction_loss / 255.0f; - new_estimate.bwe_period = bwe_period; - new_estimate.changed = true; - last_estimate_ = new_estimate; - OnNetworkEstimate(new_estimate); - } -} - -bool GoogCcNetworkController::GetNetworkParameters( - int32_t* estimated_bitrate_bps, - uint8_t* fraction_loss, - int64_t* rtt_ms, - Timestamp at_time) { - bandwidth_estimation_->CurrentEstimate(estimated_bitrate_bps, fraction_loss, - rtt_ms); - *estimated_bitrate_bps = std::max( - *estimated_bitrate_bps, bandwidth_estimation_->GetMinBitrate()); - - bool estimate_changed = false; - if ((*estimated_bitrate_bps != last_estimated_bitrate_bps_) || - (*fraction_loss != last_estimated_fraction_loss_) || - (*rtt_ms != last_estimated_rtt_ms_)) { - last_estimated_bitrate_bps_ = *estimated_bitrate_bps; - last_estimated_fraction_loss_ = *fraction_loss; - last_estimated_rtt_ms_ = *rtt_ms; - estimate_changed = true; - } - - BWE_TEST_LOGGING_PLOT(1, "fraction_loss_%", at_time.ms(), - (*fraction_loss * 100) / 256); - BWE_TEST_LOGGING_PLOT(1, "rtt_ms", at_time.ms(), *rtt_ms); - BWE_TEST_LOGGING_PLOT(1, "Target_bitrate_kbps", at_time.ms(), - *estimated_bitrate_bps / 1000); - - return estimate_changed; -} - -void GoogCcNetworkController::OnNetworkEstimate(NetworkEstimate estimate) { - if (!estimate.changed) - return; - - UpdatePacingRates(estimate.at_time); - alr_detector_->SetEstimatedBitrate(estimate.bandwidth.bps()); - probe_controller_->SetEstimatedBitrate(estimate.bandwidth.bps(), - estimate.at_time.ms()); - - TargetTransferRate target_rate; - target_rate.at_time = estimate.at_time; - // Set the target rate to the full estimated bandwidth since the estimation - // for legacy reasons includes target rate constraints. - target_rate.target_rate = estimate.bandwidth; - target_rate.network_estimate = estimate; - observer_->OnTargetTransferRate(target_rate); -} - -void GoogCcNetworkController::UpdatePacingRates(Timestamp at_time) { - if (!last_estimate_) - return; - DataRate pacing_rate = - std::max(min_pacing_rate_, last_estimate_->bandwidth) * pacing_factor_; - DataRate padding_rate = - std::min(max_padding_rate_, last_estimate_->bandwidth); - PacerConfig msg; - msg.at_time = at_time; - msg.time_window = TimeDelta::s(1); - msg.data_window = pacing_rate * msg.time_window; - msg.pad_window = padding_rate * msg.time_window; - observer_->OnPacerConfig(msg); -} - -} // namespace webrtc diff --git a/modules/congestion_controller/goog_cc_network_control.h b/modules/congestion_controller/goog_cc_network_control.h deleted file mode 100644 index 4360aac3e47..00000000000 --- a/modules/congestion_controller/goog_cc_network_control.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#ifndef MODULES_CONGESTION_CONTROLLER_GOOG_CC_NETWORK_CONTROL_H_ -#define MODULES_CONGESTION_CONTROLLER_GOOG_CC_NETWORK_CONTROL_H_ - -#include -#include -#include -#include - -#include "api/optional.h" -#include "logging/rtc_event_log/rtc_event_log.h" -#include "modules/bitrate_controller/send_side_bandwidth_estimation.h" -#include "modules/congestion_controller/acknowledged_bitrate_estimator.h" -#include "modules/congestion_controller/alr_detector.h" -#include "modules/congestion_controller/delay_based_bwe.h" -#include "modules/congestion_controller/network_control/include/network_control.h" -#include "modules/congestion_controller/probe_controller.h" -#include "rtc_base/constructormagic.h" - -namespace webrtc { - -class GoogCcNetworkController : public NetworkControllerInterface { - public: - GoogCcNetworkController(RtcEventLog* event_log, - NetworkControllerObserver* observer); - ~GoogCcNetworkController() override; - - // NetworkControllerInterface - void OnNetworkAvailability(NetworkAvailability msg) override; - void OnNetworkRouteChange(NetworkRouteChange msg) override; - void OnProcessInterval(ProcessInterval msg) override; - void OnRemoteBitrateReport(RemoteBitrateReport msg) override; - void OnRoundTripTimeUpdate(RoundTripTimeUpdate msg) override; - void OnSentPacket(SentPacket msg) override; - void OnStreamsConfig(StreamsConfig msg) override; - void OnTargetRateConstraints(TargetRateConstraints msg) override; - void OnTransportLossReport(TransportLossReport msg) override; - void OnTransportPacketsFeedback(TransportPacketsFeedback msg) override; - - private: - void MaybeUpdateCongestionWindow(); - void MaybeTriggerOnNetworkChanged(Timestamp at_time); - bool GetNetworkParameters(int32_t* estimated_bitrate_bps, - uint8_t* fraction_loss, - int64_t* rtt_ms, - Timestamp at_time); - void OnNetworkEstimate(NetworkEstimate msg); - void UpdatePacingRates(Timestamp at_time); - - RtcEventLog* const event_log_; - NetworkControllerObserver* const observer_; - - const std::unique_ptr probe_controller_; - - std::unique_ptr bandwidth_estimation_; - std::unique_ptr alr_detector_; - std::unique_ptr delay_based_bwe_; - std::unique_ptr acknowledged_bitrate_estimator_; - - std::deque feedback_rtts_; - rtc::Optional min_feedback_rtt_ms_; - - rtc::Optional last_estimate_; - rtc::Optional last_target_rate_; - - int32_t last_estimated_bitrate_bps_ = 0; - uint8_t last_estimated_fraction_loss_ = 0; - int64_t last_estimated_rtt_ms_ = 0; - - double pacing_factor_; - DataRate min_pacing_rate_; - DataRate max_padding_rate_; - - bool in_cwnd_experiment_; - int64_t accepted_queue_ms_; - bool previously_in_alr = false; - - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(GoogCcNetworkController); -}; - -} // namespace webrtc - -#endif // MODULES_CONGESTION_CONTROLLER_GOOG_CC_NETWORK_CONTROL_H_ diff --git a/modules/congestion_controller/include/goog_cc_factory.h b/modules/congestion_controller/include/goog_cc_factory.h deleted file mode 100644 index 10dddd27153..00000000000 --- a/modules/congestion_controller/include/goog_cc_factory.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#ifndef MODULES_CONGESTION_CONTROLLER_INCLUDE_GOOG_CC_FACTORY_H_ -#define MODULES_CONGESTION_CONTROLLER_INCLUDE_GOOG_CC_FACTORY_H_ -#include "modules/congestion_controller/network_control/include/network_control.h" - -namespace webrtc { -class Clock; -class RtcEventLog; - -class GoogCcNetworkControllerFactory - : public NetworkControllerFactoryInterface { - public: - explicit GoogCcNetworkControllerFactory(RtcEventLog*); - NetworkControllerInterface::uptr Create( - NetworkControllerObserver* observer) override; - TimeDelta GetProcessInterval() const override; - - private: - RtcEventLog* const event_log_; -}; -} // namespace webrtc - -#endif // MODULES_CONGESTION_CONTROLLER_INCLUDE_GOOG_CC_FACTORY_H_ diff --git a/modules/congestion_controller/include/send_side_congestion_controller.h b/modules/congestion_controller/include/send_side_congestion_controller.h index 86f59e573c9..2707cc340d8 100644 --- a/modules/congestion_controller/include/send_side_congestion_controller.h +++ b/modules/congestion_controller/include/send_side_congestion_controller.h @@ -11,26 +11,19 @@ #ifndef MODULES_CONGESTION_CONTROLLER_INCLUDE_SEND_SIDE_CONGESTION_CONTROLLER_H_ #define MODULES_CONGESTION_CONTROLLER_INCLUDE_SEND_SIDE_CONGESTION_CONTROLLER_H_ -#include -#include -#include #include #include #include "common_types.h" // NOLINT(build/include) -#include "modules/congestion_controller/network_control/include/network_control.h" -#include "modules/congestion_controller/network_control/include/network_types.h" -#include "modules/congestion_controller/pacer_controller.h" +#include "modules/congestion_controller/delay_based_bwe.h" #include "modules/congestion_controller/transport_feedback_adapter.h" #include "modules/include/module.h" #include "modules/include/module_common_types.h" #include "modules/pacing/paced_sender.h" -#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "rtc_base/constructormagic.h" #include "rtc_base/criticalsection.h" #include "rtc_base/networkroute.h" #include "rtc_base/race_checker.h" -#include "rtc_base/task_queue.h" namespace rtc { struct SentPacket; @@ -38,23 +31,16 @@ struct SentPacket; namespace webrtc { +class BitrateController; class Clock; +class AcknowledgedBitrateEstimator; +class ProbeController; class RateLimiter; class RtcEventLog; -namespace send_side_cc_internal { -// This is used to observe the network controller state and route calls to -// the proper handler. It also keeps cached values for safe asynchronous use. -// This makes sure that things running on the worker queue can't access state -// in SendSideCongestionController, which would risk causing data race on -// destruction unless members are properly ordered. -class ControlHandler; -} // namespace send_side_cc_internal - class SendSideCongestionController : public CallStatsObserver, public Module, - public TransportFeedbackObserver, - public RtcpBandwidthObserver { + public TransportFeedbackObserver { public: // Observer class for bitrate changes announced due to change in bandwidth // estimate or due to that the send pacer is full. Fraction loss and rtt is @@ -100,7 +86,10 @@ class SendSideCongestionController : public CallStatsObserver, virtual void SignalNetworkState(NetworkState state); virtual void SetTransportOverhead(size_t transport_overhead_bytes_per_packet); - virtual RtcpBandwidthObserver* GetBandwidthObserver(); + // Deprecated: Use GetBandwidthObserver instead. + RTC_DEPRECATED virtual BitrateController* GetBitrateController() const; + + virtual RtcpBandwidthObserver* GetBandwidthObserver() const; virtual bool AvailableBandwidth(uint32_t* bandwidth) const; virtual int64_t GetPacerQueuingDelayMs() const; @@ -113,11 +102,6 @@ class SendSideCongestionController : public CallStatsObserver, virtual void OnSentPacket(const rtc::SentPacket& sent_packet); - // Implements RtcpBandwidthObserver - void OnReceivedEstimatedBitrate(uint32_t bitrate) override; - void OnReceivedRtcpReceiverReport(const ReportBlockList& report_blocks, - int64_t rtt, - int64_t now_ms) override; // Implements CallStatsObserver. void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) override; @@ -133,64 +117,52 @@ class SendSideCongestionController : public CallStatsObserver, void OnTransportFeedback(const rtcp::TransportFeedback& feedback) override; std::vector GetTransportFeedbackVector() const override; - // Sets the minimum send bitrate and maximum padding bitrate requested by send - // streams. - // |min_send_bitrate_bps| might be higher that the estimated available network - // bitrate and if so, the pacer will send with |min_send_bitrate_bps|. - // |max_padding_bitrate_bps| might be higher than the estimate available - // network bitrate and if so, the pacer will send padding packets to reach - // the min of the estimated available bitrate and |max_padding_bitrate_bps|. - void SetSendBitrateLimits(int64_t min_send_bitrate_bps, - int64_t max_padding_bitrate_bps); - void SetPacingFactor(float pacing_factor); - - protected: - // Waits long enough that any outstanding tasks should be finished. - void WaitOnTasks(); - private: - SendSideCongestionController( - const Clock* clock, - RtcEventLog* event_log, - PacedSender* pacer, - NetworkControllerFactoryInterface::uptr controller_factory); - - void UpdateStreamsConfig(); - void WaitOnTask(std::function closure); - void MaybeUpdateOutstandingData(); - void OnReceivedRtcpReceiverReportBlocks(const ReportBlockList& report_blocks, - int64_t now_ms); - + void MaybeTriggerOnNetworkChanged(); + + bool IsSendQueueFull() const; + bool IsNetworkDown() const; + bool HasNetworkParametersToReportChanged(uint32_t bitrate_bps, + uint8_t fraction_loss, + int64_t rtt); + void LimitOutstandingBytes(size_t num_outstanding_bytes); const Clock* const clock_; + rtc::CriticalSection observer_lock_; + Observer* observer_ RTC_GUARDED_BY(observer_lock_); + RtcEventLog* const event_log_; PacedSender* const pacer_; + const std::unique_ptr bitrate_controller_; + std::unique_ptr acknowledged_bitrate_estimator_; + const std::unique_ptr probe_controller_; + const std::unique_ptr retransmission_rate_limiter_; TransportFeedbackAdapter transport_feedback_adapter_; - - const std::unique_ptr pacer_controller_; - const std::unique_ptr control_handler; - const std::unique_ptr controller_; - - TimeDelta process_interval_; - int64_t last_process_update_ms_ = 0; - - std::map last_report_blocks_; - Timestamp last_report_block_time_; - - StreamsConfig streams_config_; + rtc::CriticalSection network_state_lock_; + uint32_t last_reported_bitrate_bps_ RTC_GUARDED_BY(network_state_lock_); + uint8_t last_reported_fraction_loss_ RTC_GUARDED_BY(network_state_lock_); + int64_t last_reported_rtt_ RTC_GUARDED_BY(network_state_lock_); + NetworkState network_state_ RTC_GUARDED_BY(network_state_lock_); + bool pause_pacer_ RTC_GUARDED_BY(network_state_lock_); + // Duplicate the pacer paused state to avoid grabbing a lock when + // pausing the pacer. This can be removed when we move this class + // over to the task queue. + bool pacer_paused_; + rtc::CriticalSection bwe_lock_; + int min_bitrate_bps_ RTC_GUARDED_BY(bwe_lock_); + std::unique_ptr delay_based_bwe_ RTC_GUARDED_BY(bwe_lock_); + bool in_cwnd_experiment_; + int64_t accepted_queue_ms_; + bool was_in_alr_; const bool send_side_bwe_with_overhead_; - std::atomic transport_overhead_bytes_per_packet_; - std::atomic network_available_; + size_t transport_overhead_bytes_per_packet_ RTC_GUARDED_BY(bwe_lock_); rtc::RaceChecker worker_race_; - // Note that moving ownership of the task queue makes it neccessary to make - // sure that there is no outstanding tasks on it using destructed objects. - // This is currently guranteed by using explicit reset in the destructor of - // this class. It is declared last to indicate that it's lifetime is shorter - // than all other members. - std::unique_ptr task_queue_; + bool pacer_pushback_experiment_ = false; + float encoding_rate_ = 1.0; RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(SendSideCongestionController); }; + } // namespace webrtc #endif // MODULES_CONGESTION_CONTROLLER_INCLUDE_SEND_SIDE_CONGESTION_CONTROLLER_H_ diff --git a/modules/congestion_controller/network_control/BUILD.gn b/modules/congestion_controller/network_control/BUILD.gn deleted file mode 100644 index 369d9a315a6..00000000000 --- a/modules/congestion_controller/network_control/BUILD.gn +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright (c) 2018 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. - -import("../../../webrtc.gni") - -rtc_static_library("network_control") { - sources = [ - "include/network_control.h", - "include/network_types.h", - "include/network_units.h", - "network_types.cc", - "network_units.cc", - ] - - deps = [ - "../../:module_api", - "../../../api:optional", - "../../../rtc_base:checks", - "../../../rtc_base:rtc_base_approved", - ] -} - -if (rtc_include_tests) { - rtc_source_set("network_control_unittests") { - testonly = true - sources = [ - "network_units_unittest.cc", - ] - - deps = [ - ":network_control", - "../../../test:test_support", - ] - } -} diff --git a/modules/congestion_controller/network_control/include/network_control.h b/modules/congestion_controller/network_control/include/network_control.h deleted file mode 100644 index d87acbf649b..00000000000 --- a/modules/congestion_controller/network_control/include/network_control.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#ifndef MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_INCLUDE_NETWORK_CONTROL_H_ -#define MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_INCLUDE_NETWORK_CONTROL_H_ -#include -#include - -#include "modules/congestion_controller/network_control/include/network_types.h" -#include "modules/congestion_controller/network_control/include/network_units.h" - -namespace webrtc { - -// NetworkControllerObserver is an interface implemented by observers of network -// controllers. It contains declarations of the possible configuration messages -// that can be sent from a network controller implementation. -class NetworkControllerObserver { - public: - // Called when congestion window configutation is changed. - virtual void OnCongestionWindow(CongestionWindow) = 0; - // Called when pacer configuration has changed. - virtual void OnPacerConfig(PacerConfig) = 0; - // Called to indicate that a new probe should be sent. - virtual void OnProbeClusterConfig(ProbeClusterConfig) = 0; - // Called to indicate target transfer rate as well as giving information about - // the current estimate of network parameters. - virtual void OnTargetTransferRate(TargetTransferRate) = 0; - - protected: - virtual ~NetworkControllerObserver() = default; -}; - -// NetworkControllerInterface is implemented by network controllers. A network -// controller is a class that uses information about network state and traffic -// to estimate network parameters such as round trip time and bandwidth. Network -// controllers does not guarantee thread safety, the interface must be used in a -// non-concurrent fashion. -class NetworkControllerInterface { - public: - using uptr = std::unique_ptr; - virtual ~NetworkControllerInterface() = default; - - // Called when network availabilty changes. - virtual void OnNetworkAvailability(NetworkAvailability) = 0; - // Called when the receiving or sending endpoint changes address. - virtual void OnNetworkRouteChange(NetworkRouteChange) = 0; - // Called periodically with a periodicy as specified by - // NetworkControllerFactoryInterface::GetProcessInterval. - virtual void OnProcessInterval(ProcessInterval) = 0; - // Called when remotely calculated bitrate is received. - virtual void OnRemoteBitrateReport(RemoteBitrateReport) = 0; - // Called round trip time has been calculated by protocol specific mechanisms. - virtual void OnRoundTripTimeUpdate(RoundTripTimeUpdate) = 0; - // Called when a packet is sent on the network. - virtual void OnSentPacket(SentPacket) = 0; - // Called when the stream specific configuration has been updated. - virtual void OnStreamsConfig(StreamsConfig) = 0; - // Called when target transfer rate constraints has been changed. - virtual void OnTargetRateConstraints(TargetRateConstraints) = 0; - // Called when a protocol specific calculation of packet loss has been made. - virtual void OnTransportLossReport(TransportLossReport) = 0; - // Called with per packet feedback regarding receive time. - virtual void OnTransportPacketsFeedback(TransportPacketsFeedback) = 0; -}; - -// NetworkControllerFactoryInterface is an interface for creating a network -// controller. -class NetworkControllerFactoryInterface { - public: - using uptr = std::unique_ptr; - // Used to create a new network controller, requires an observer to be - // provided to handle callbacks. - virtual NetworkControllerInterface::uptr Create( - NetworkControllerObserver* observer) = 0; - // Returns the interval by which the network controller expects - // OnProcessInterval calls. - virtual TimeDelta GetProcessInterval() const = 0; - virtual ~NetworkControllerFactoryInterface() = default; -}; -} // namespace webrtc - -#endif // MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_INCLUDE_NETWORK_CONTROL_H_ diff --git a/modules/congestion_controller/network_control/include/network_types.h b/modules/congestion_controller/network_control/include/network_types.h deleted file mode 100644 index 1df3c4e8567..00000000000 --- a/modules/congestion_controller/network_control/include/network_types.h +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#ifndef MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_INCLUDE_NETWORK_TYPES_H_ -#define MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_INCLUDE_NETWORK_TYPES_H_ -#include -#include -#include -#include "modules/congestion_controller/network_control/include/network_units.h" -#include "modules/include/module_common_types.h" -#include "rtc_base/constructormagic.h" - -namespace webrtc { - -// Configuration - -// Use StreamsConfig for information about streams that is required for specific -// adjustments to the algorithms in network controllers. Especially useful -// for experiments. -struct StreamsConfig { - StreamsConfig(); - StreamsConfig(const StreamsConfig&); - ~StreamsConfig(); - Timestamp at_time; - bool requests_alr_probing = false; - rtc::Optional pacing_factor; - rtc::Optional min_pacing_rate; - rtc::Optional max_padding_rate; -}; - -struct TargetRateConstraints { - Timestamp at_time; - DataRate starting_rate; - DataRate min_data_rate; - DataRate max_data_rate; -}; - -// Send side information - -struct NetworkAvailability { - Timestamp at_time; - bool network_available = false; -}; - -struct NetworkRouteChange { - Timestamp at_time; - // The TargetRateConstraints are set here so they can be changed synchronously - // when network route changes. - TargetRateConstraints constraints; -}; - -struct SentPacket { - Timestamp send_time; - DataSize size; - PacedPacketInfo pacing_info; -}; - -struct PacerQueueUpdate { - TimeDelta expected_queue_time; -}; - -// Transport level feedback - -struct RemoteBitrateReport { - Timestamp receive_time; - DataRate bandwidth; -}; - -struct RoundTripTimeUpdate { - Timestamp receive_time; - TimeDelta round_trip_time; - bool smoothed = false; -}; - -struct TransportLossReport { - Timestamp receive_time; - Timestamp start_time; - Timestamp end_time; - uint64_t packets_lost_delta = 0; - uint64_t packets_received_delta = 0; -}; - -struct OutstandingData { - DataSize in_flight_data; -}; - -// Packet level feedback - -struct PacketResult { - PacketResult(); - PacketResult(const PacketResult&); - ~PacketResult(); - - rtc::Optional sent_packet; - Timestamp receive_time; -}; - -struct TransportPacketsFeedback { - TransportPacketsFeedback(); - TransportPacketsFeedback(const TransportPacketsFeedback& other); - ~TransportPacketsFeedback(); - - Timestamp feedback_time; - DataSize data_in_flight; - DataSize prior_in_flight; - std::vector packet_feedbacks; - - std::vector ReceivedWithSendInfo() const; - std::vector LostWithSendInfo() const; - std::vector PacketsWithFeedback() const; -}; - -// Network estimation - -struct NetworkEstimate { - Timestamp at_time; - DataRate bandwidth; - TimeDelta round_trip_time; - TimeDelta bwe_period; - - float loss_rate_ratio = 0; - bool changed = true; -}; - -// Network control -struct CongestionWindow { - bool enabled = true; - DataSize data_window; -}; - -struct PacerConfig { - Timestamp at_time; - // Pacer should send at most data_window data over time_window duration. - DataSize data_window; - TimeDelta time_window; - // Pacer should send at least pad_window data over time_window duration. - DataSize pad_window; - DataRate data_rate() const { return data_window / time_window; } -}; - -struct ProbeClusterConfig { - Timestamp at_time; - DataRate target_data_rate; - TimeDelta target_duration; - uint32_t target_probe_count; -}; - -struct TargetTransferRate { - Timestamp at_time; - DataRate target_rate; - // The estimate on which the target rate is based on. - NetworkEstimate network_estimate; -}; - -// Process control -struct ProcessInterval { - Timestamp at_time; -}; - -::std::ostream& operator<<(::std::ostream& os, - const ProbeClusterConfig& config); -::std::ostream& operator<<(::std::ostream& os, const PacerConfig& config); -} // namespace webrtc - -#endif // MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_INCLUDE_NETWORK_TYPES_H_ diff --git a/modules/congestion_controller/network_control/include/network_units.h b/modules/congestion_controller/network_control/include/network_units.h deleted file mode 100644 index ab7b4b25f34..00000000000 --- a/modules/congestion_controller/network_control/include/network_units.h +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#ifndef MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_INCLUDE_NETWORK_UNITS_H_ -#define MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_INCLUDE_NETWORK_UNITS_H_ -#include -#include -#include -#include "rtc_base/checks.h" - -namespace webrtc { -namespace units_internal { -inline int64_t DivideAndRound(int64_t numerator, int64_t denominators) { - if (numerator >= 0) { - return (numerator + (denominators / 2)) / denominators; - } else { - return (numerator + (denominators / 2)) / denominators - 1; - } -} -} // namespace units_internal - -// TimeDelta represents the difference between two timestamps. Connomly this can -// be a duration. However since two Timestamps are not guaranteed to have the -// same epoch (they might come from different computers, making exact -// synchronisation infeasible), the duration covered by a TimeDelta can be -// undefined. To simplify usage, it can be constructed and converted to -// different units, specifically seconds (s), milliseconds (ms) and -// microseconds (us). -class TimeDelta { - public: - static const TimeDelta kPlusInfinity; - static const TimeDelta kMinusInfinity; - static const TimeDelta kNotInitialized; - static const TimeDelta kZero; - TimeDelta() : TimeDelta(kNotInitialized) {} - static TimeDelta Zero() { return kZero; } - static TimeDelta Infinity() { return kPlusInfinity; } - static TimeDelta seconds(int64_t seconds) { return TimeDelta::s(seconds); } - static TimeDelta s(int64_t seconds) { - return TimeDelta::us(seconds * 1000000); - } - static TimeDelta ms(int64_t milliseconds) { - return TimeDelta::us(milliseconds * 1000); - } - static TimeDelta us(int64_t microseconds) { - // Infinities only allowed via use of explicit constants. - RTC_DCHECK(microseconds > std::numeric_limits::min()); - RTC_DCHECK(microseconds < std::numeric_limits::max()); - return TimeDelta(microseconds); - } - int64_t s() const { return units_internal::DivideAndRound(us(), 1000000); } - int64_t ms() const { return units_internal::DivideAndRound(us(), 1000); } - int64_t us() const { - RTC_DCHECK(IsFinite()); - return microseconds_; - } - TimeDelta Abs() const { return TimeDelta::us(std::abs(us())); } - bool IsZero() const { return microseconds_ == 0; } - bool IsFinite() const { return IsInitialized() && !IsInfinite(); } - bool IsInitialized() const { - return microseconds_ != kNotInitialized.microseconds_; - } - bool IsInfinite() const { - return *this == kPlusInfinity || *this == kMinusInfinity; - } - TimeDelta operator+(const TimeDelta& other) const { - return TimeDelta::us(us() + other.us()); - } - TimeDelta operator-(const TimeDelta& other) const { - return TimeDelta::us(us() - other.us()); - } - TimeDelta operator*(double scalar) const { - return TimeDelta::us(us() * scalar); - } - TimeDelta operator*(int64_t scalar) const { - return TimeDelta::us(us() * scalar); - } - TimeDelta operator*(int32_t scalar) const { - return TimeDelta::us(us() * scalar); - } - bool operator==(const TimeDelta& other) const { - return microseconds_ == other.microseconds_; - } - bool operator!=(const TimeDelta& other) const { - return microseconds_ != other.microseconds_; - } - bool operator<=(const TimeDelta& other) const { - return microseconds_ <= other.microseconds_; - } - bool operator>=(const TimeDelta& other) const { - return microseconds_ >= other.microseconds_; - } - bool operator>(const TimeDelta& other) const { - return microseconds_ > other.microseconds_; - } - bool operator<(const TimeDelta& other) const { - return microseconds_ < other.microseconds_; - } - - private: - explicit TimeDelta(int64_t us) : microseconds_(us) {} - int64_t microseconds_; -}; -inline TimeDelta operator*(const double& scalar, const TimeDelta& delta) { - return delta * scalar; -} -inline TimeDelta operator*(const int64_t& scalar, const TimeDelta& delta) { - return delta * scalar; -} -inline TimeDelta operator*(const int32_t& scalar, const TimeDelta& delta) { - return delta * scalar; -} - -// Timestamp represents the time that has passed since some unspecified epoch. -// The epoch is assumed to be before any represented timestamps, this means that -// negative values are not valid. The most notable feature is that the -// difference of of two Timestamps results in a TimeDelta. -class Timestamp { - public: - static const Timestamp kPlusInfinity; - static const Timestamp kNotInitialized; - Timestamp() : Timestamp(kNotInitialized) {} - static Timestamp Infinity() { return kPlusInfinity; } - static Timestamp s(int64_t seconds) { return Timestamp(seconds * 1000000); } - static Timestamp ms(int64_t millis) { return Timestamp(millis * 1000); } - static Timestamp us(int64_t micros) { return Timestamp(micros); } - int64_t s() const { return units_internal::DivideAndRound(us(), 1000000); } - int64_t ms() const { return units_internal::DivideAndRound(us(), 1000); } - int64_t us() const { - RTC_DCHECK(IsFinite()); - return microseconds_; - } - bool IsInfinite() const { - return microseconds_ == kPlusInfinity.microseconds_; - } - bool IsInitialized() const { - return microseconds_ != kNotInitialized.microseconds_; - } - bool IsFinite() const { return IsInitialized() && !IsInfinite(); } - TimeDelta operator-(const Timestamp& other) const { - return TimeDelta::us(us() - other.us()); - } - Timestamp operator-(const TimeDelta& delta) const { - return Timestamp::us(us() - delta.us()); - } - Timestamp operator+(const TimeDelta& delta) const { - return Timestamp::us(us() + delta.us()); - } - bool operator==(const Timestamp& other) const { - return microseconds_ == other.microseconds_; - } - bool operator!=(const Timestamp& other) const { - return microseconds_ != other.microseconds_; - } - bool operator<=(const Timestamp& other) const { return us() <= other.us(); } - bool operator>=(const Timestamp& other) const { return us() >= other.us(); } - bool operator>(const Timestamp& other) const { return us() > other.us(); } - bool operator<(const Timestamp& other) const { return us() < other.us(); } - - private: - explicit Timestamp(int64_t us) : microseconds_(us) {} - int64_t microseconds_; -}; - -// DataSize is a class represeting a count of bytes. Note that while it can be -// initialized by a number of bits, it does not guarantee that the resolution is -// kept and the internal storage is in bytes. The number of bits will be -// truncated to fit. -class DataSize { - public: - static const DataSize kZero; - static const DataSize kPlusInfinity; - static const DataSize kNotInitialized; - DataSize() : DataSize(kNotInitialized) {} - static DataSize Zero() { return kZero; } - static DataSize Infinity() { return kPlusInfinity; } - static DataSize bytes(int64_t bytes) { return DataSize(bytes); } - static DataSize bits(int64_t bits) { return DataSize(bits / 8); } - int64_t bytes() const { - RTC_DCHECK(IsFinite()); - return bytes_; - } - int64_t kilobytes() const { - return units_internal::DivideAndRound(bytes(), 1000); - } - int64_t bits() const { return bytes() * 8; } - int64_t kilobits() const { - return units_internal::DivideAndRound(bits(), 1000); - } - bool IsZero() const { return bytes_ == 0; } - bool IsInfinite() const { return bytes_ == kPlusInfinity.bytes_; } - bool IsInitialized() const { return bytes_ != kNotInitialized.bytes_; } - bool IsFinite() const { return IsInitialized() && !IsInfinite(); } - DataSize operator-(const DataSize& other) const { - return DataSize::bytes(bytes() - other.bytes()); - } - DataSize operator+(const DataSize& other) const { - return DataSize::bytes(bytes() + other.bytes()); - } - DataSize operator*(double scalar) const { - return DataSize::bytes(bytes() * scalar); - } - DataSize operator*(int64_t scalar) const { - return DataSize::bytes(bytes() * scalar); - } - DataSize operator*(int32_t scalar) const { - return DataSize::bytes(bytes() * scalar); - } - DataSize operator/(int64_t scalar) const { - return DataSize::bytes(bytes() / scalar); - } - DataSize& operator-=(const DataSize& other) { - bytes_ -= other.bytes(); - return *this; - } - DataSize& operator+=(const DataSize& other) { - bytes_ += other.bytes(); - return *this; - } - bool operator==(const DataSize& other) const { - return bytes_ == other.bytes_; - } - bool operator!=(const DataSize& other) const { - return bytes_ != other.bytes_; - } - bool operator<=(const DataSize& other) const { - return bytes_ <= other.bytes_; - } - bool operator>=(const DataSize& other) const { - return bytes_ >= other.bytes_; - } - bool operator>(const DataSize& other) const { return bytes_ > other.bytes_; } - bool operator<(const DataSize& other) const { return bytes_ < other.bytes_; } - - private: - explicit DataSize(int64_t bytes) : bytes_(bytes) {} - int64_t bytes_; -}; -inline DataSize operator*(const double& scalar, const DataSize& size) { - return size * scalar; -} -inline DataSize operator*(const int64_t& scalar, const DataSize& size) { - return size * scalar; -} -inline DataSize operator*(const int32_t& scalar, const DataSize& size) { - return size * scalar; -} - -// DataRate is a class that represents a given data rate. This can be used to -// represent bandwidth, encoding bitrate, etc. The internal storage is currently -// bits per second (bps) since this makes it easier to intepret the raw value -// when debugging. The promised precision, however is only that it will -// represent bytes per second accurately. Any implementation depending on bps -// resolution should document this by changing this comment. -class DataRate { - public: - static const DataRate kZero; - static const DataRate kPlusInfinity; - static const DataRate kNotInitialized; - DataRate() : DataRate(kNotInitialized) {} - static DataRate Zero() { return kZero; } - static DataRate Infinity() { return kPlusInfinity; } - static DataRate bytes_per_second(int64_t bytes_per_sec) { - return DataRate(bytes_per_sec * 8); - } - static DataRate bits_per_second(int64_t bits_per_sec) { - return DataRate(bits_per_sec); - } - static DataRate bps(int64_t bits_per_sec) { - return DataRate::bits_per_second(bits_per_sec); - } - static DataRate kbps(int64_t kilobits_per_sec) { - return DataRate::bits_per_second(kilobits_per_sec * 1000); - } - int64_t bits_per_second() const { - RTC_DCHECK(IsFinite()); - return bits_per_sec_; - } - int64_t bytes_per_second() const { return bits_per_second() / 8; } - int64_t bps() const { return bits_per_second(); } - int64_t kbps() const { return units_internal::DivideAndRound(bps(), 1000); } - bool IsZero() const { return bits_per_sec_ == 0; } - bool IsInfinite() const { - return bits_per_sec_ == kPlusInfinity.bits_per_sec_; - } - bool IsInitialized() const { - return bits_per_sec_ != kNotInitialized.bits_per_sec_; - } - bool IsFinite() const { return IsInitialized() && !IsInfinite(); } - DataRate operator*(double scalar) const { - return DataRate::bytes_per_second(bytes_per_second() * scalar); - } - DataRate operator*(int64_t scalar) const { - return DataRate::bytes_per_second(bytes_per_second() * scalar); - } - DataRate operator*(int32_t scalar) const { - return DataRate::bytes_per_second(bytes_per_second() * scalar); - } - bool operator==(const DataRate& other) const { - return bits_per_sec_ == other.bits_per_sec_; - } - bool operator!=(const DataRate& other) const { - return bits_per_sec_ != other.bits_per_sec_; - } - bool operator<=(const DataRate& other) const { - return bits_per_sec_ <= other.bits_per_sec_; - } - bool operator>=(const DataRate& other) const { - return bits_per_sec_ >= other.bits_per_sec_; - } - bool operator>(const DataRate& other) const { - return bits_per_sec_ > other.bits_per_sec_; - } - bool operator<(const DataRate& other) const { - return bits_per_sec_ < other.bits_per_sec_; - } - - private: - // Bits per second used internally to simplify debugging by making the value - // more recognizable. - explicit DataRate(int64_t bits_per_second) : bits_per_sec_(bits_per_second) {} - int64_t bits_per_sec_; -}; -inline DataRate operator*(const double& scalar, const DataRate& rate) { - return rate * scalar; -} -inline DataRate operator*(const int64_t& scalar, const DataRate& rate) { - return rate * scalar; -} -inline DataRate operator*(const int32_t& scalar, const DataRate& rate) { - return rate * scalar; -} - -DataRate operator/(const DataSize& size, const TimeDelta& duration); -TimeDelta operator/(const DataSize& size, const DataRate& rate); -DataSize operator*(const DataRate& rate, const TimeDelta& duration); -DataSize operator*(const TimeDelta& duration, const DataRate& rate); - -::std::ostream& operator<<(::std::ostream& os, const DataRate& datarate); -::std::ostream& operator<<(::std::ostream& os, const DataSize& datasize); -::std::ostream& operator<<(::std::ostream& os, const Timestamp& timestamp); -::std::ostream& operator<<(::std::ostream& os, const TimeDelta& delta); - -} // namespace webrtc - -#endif // MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_INCLUDE_NETWORK_UNITS_H_ diff --git a/modules/congestion_controller/network_control/network_types.cc b/modules/congestion_controller/network_control/network_types.cc deleted file mode 100644 index e5355598d66..00000000000 --- a/modules/congestion_controller/network_control/network_types.cc +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2018 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/network_control/include/network_types.h" - -namespace webrtc { - -StreamsConfig::StreamsConfig() = default; -StreamsConfig::StreamsConfig(const StreamsConfig&) = default; -StreamsConfig::~StreamsConfig() = default; - -PacketResult::PacketResult() = default; -PacketResult::PacketResult(const PacketResult& other) = default; -PacketResult::~PacketResult() = default; - -TransportPacketsFeedback::TransportPacketsFeedback() = default; -TransportPacketsFeedback::TransportPacketsFeedback( - const TransportPacketsFeedback& other) = default; -TransportPacketsFeedback::~TransportPacketsFeedback() = default; - -std::vector TransportPacketsFeedback::ReceivedWithSendInfo() - const { - std::vector res; - for (const PacketResult& fb : packet_feedbacks) { - if (fb.receive_time.IsFinite() && fb.sent_packet.has_value()) { - res.push_back(fb); - } - } - return res; -} - -std::vector TransportPacketsFeedback::LostWithSendInfo() const { - std::vector res; - for (const PacketResult& fb : packet_feedbacks) { - if (fb.receive_time.IsInfinite() && fb.sent_packet.has_value()) { - res.push_back(fb); - } - } - return res; -} - -std::vector TransportPacketsFeedback::PacketsWithFeedback() - const { - return packet_feedbacks; -} - -::std::ostream& operator<<(::std::ostream& os, - const ProbeClusterConfig& config) { - return os << "ProbeClusterConfig(...)"; -} - -::std::ostream& operator<<(::std::ostream& os, const PacerConfig& config) { - return os << "PacerConfig(...)"; -} - -} // namespace webrtc diff --git a/modules/congestion_controller/network_control/network_units.cc b/modules/congestion_controller/network_control/network_units.cc deleted file mode 100644 index fd4a30150ff..00000000000 --- a/modules/congestion_controller/network_control/network_units.cc +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2018 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/network_control/include/network_units.h" - -namespace webrtc { -namespace { -int64_t kPlusInfinityVal = std::numeric_limits::max(); -int64_t kMinusInfinityVal = std::numeric_limits::min(); -int64_t kSignedNotInitializedVal = kMinusInfinityVal + 1; -int64_t kNotInitializedVal = -1; -} // namespace -const TimeDelta TimeDelta::kZero = TimeDelta(0); -const TimeDelta TimeDelta::kMinusInfinity = TimeDelta(kMinusInfinityVal); -const TimeDelta TimeDelta::kPlusInfinity = TimeDelta(kPlusInfinityVal); -const TimeDelta TimeDelta::kNotInitialized = - TimeDelta(kSignedNotInitializedVal); - -const Timestamp Timestamp::kPlusInfinity = Timestamp(kPlusInfinityVal); -const Timestamp Timestamp::kNotInitialized = Timestamp(kNotInitializedVal); - -const DataRate DataRate::kZero = DataRate(0); -const DataRate DataRate::kPlusInfinity = DataRate(kPlusInfinityVal); -const DataRate DataRate::kNotInitialized = DataRate(kNotInitializedVal); - -const DataSize DataSize::kZero = DataSize(0); -const DataSize DataSize::kPlusInfinity = DataSize(kPlusInfinityVal); -const DataSize DataSize::kNotInitialized = DataSize(kNotInitializedVal); - -DataRate operator/(const DataSize& size, const TimeDelta& duration) { - RTC_DCHECK(size.bytes() < std::numeric_limits::max() / 1000000) - << "size is too large, size: " << size.bytes() << " is not less than " - << std::numeric_limits::max() / 1000000; - auto bytes_per_sec = size.bytes() * 1000000 / duration.us(); - return DataRate::bytes_per_second(bytes_per_sec); -} - -TimeDelta operator/(const DataSize& size, const DataRate& rate) { - RTC_DCHECK(size.bytes() < std::numeric_limits::max() / 1000000) - << "size is too large, size: " << size.bytes() << " is not less than " - << std::numeric_limits::max() / 1000000; - auto microseconds = size.bytes() * 1000000 / rate.bytes_per_second(); - return TimeDelta::us(microseconds); -} - -DataSize operator*(const DataRate& rate, const TimeDelta& duration) { - auto micro_bytes = rate.bytes_per_second() * duration.us(); - auto bytes = units_internal::DivideAndRound(micro_bytes, 1000000); - return DataSize::bytes(bytes); -} - -DataSize operator*(const TimeDelta& duration, const DataRate& rate) { - return rate * duration; -} - -::std::ostream& operator<<(::std::ostream& os, const DataRate& value) { - if (value == DataRate::kPlusInfinity) { - return os << "inf bps"; - } else if (value == DataRate::kNotInitialized) { - return os << "? bps"; - } else { - return os << value.bps() << " bps"; - } -} -::std::ostream& operator<<(::std::ostream& os, const DataSize& value) { - if (value == DataSize::kPlusInfinity) { - return os << "inf bytes"; - } else if (value == DataSize::kNotInitialized) { - return os << "? bytes"; - } else { - return os << value.bytes() << " bytes"; - } -} -::std::ostream& operator<<(::std::ostream& os, const Timestamp& value) { - if (value == Timestamp::kPlusInfinity) { - return os << "inf ms"; - } else if (value == Timestamp::kNotInitialized) { - return os << "? ms"; - } else { - return os << value.ms() << " ms"; - } -} -::std::ostream& operator<<(::std::ostream& os, const TimeDelta& value) { - if (value == TimeDelta::kPlusInfinity) { - return os << "+inf ms"; - } else if (value == TimeDelta::kMinusInfinity) { - return os << "-inf ms"; - } else if (value == TimeDelta::kNotInitialized) { - return os << "? ms"; - } else { - return os << value.ms() << " ms"; - } -} -} // namespace webrtc diff --git a/modules/congestion_controller/network_control/network_units_unittest.cc b/modules/congestion_controller/network_control/network_units_unittest.cc deleted file mode 100644 index 5c7fa871127..00000000000 --- a/modules/congestion_controller/network_control/network_units_unittest.cc +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Copyright (c) 2018 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/network_control/include/network_units.h" -#include "test/gtest.h" - -namespace webrtc { -namespace test { - -TEST(TimeDeltaTest, GetBackSameValues) { - const int64_t kValue = 499; - for (int sign = -1; sign <= 1; ++sign) { - int64_t value = kValue * sign; - EXPECT_EQ(TimeDelta::ms(value).ms(), value); - EXPECT_EQ(TimeDelta::us(value).us(), value); - EXPECT_EQ(TimeDelta::s(value).s(), value); - EXPECT_EQ(TimeDelta::seconds(value).s(), value); - } - EXPECT_EQ(TimeDelta::Zero().us(), 0); -} - -TEST(TimeDeltaTest, GetDifferentPrefix) { - const int64_t kValue = 3000000; - EXPECT_EQ(TimeDelta::us(kValue).s(), kValue / 1000000); - EXPECT_EQ(TimeDelta::ms(kValue).s(), kValue / 1000); - EXPECT_EQ(TimeDelta::us(kValue).ms(), kValue / 1000); - - EXPECT_EQ(TimeDelta::ms(kValue).us(), kValue * 1000); - EXPECT_EQ(TimeDelta::s(kValue).ms(), kValue * 1000); - EXPECT_EQ(TimeDelta::s(kValue).us(), kValue * 1000000); -} - -TEST(TimeDeltaTest, IdentityChecks) { - const int64_t kValue = 3000; - EXPECT_TRUE(TimeDelta::Zero().IsZero()); - EXPECT_FALSE(TimeDelta::ms(kValue).IsZero()); - - EXPECT_TRUE(TimeDelta::Infinity().IsInfinite()); - EXPECT_TRUE(TimeDelta::kPlusInfinity.IsInfinite()); - EXPECT_TRUE(TimeDelta::kMinusInfinity.IsInfinite()); - EXPECT_FALSE(TimeDelta::Zero().IsInfinite()); - EXPECT_FALSE(TimeDelta::ms(-kValue).IsInfinite()); - EXPECT_FALSE(TimeDelta::ms(kValue).IsInfinite()); - - EXPECT_FALSE(TimeDelta::Infinity().IsFinite()); - EXPECT_FALSE(TimeDelta::kPlusInfinity.IsFinite()); - EXPECT_FALSE(TimeDelta::kMinusInfinity.IsFinite()); - EXPECT_TRUE(TimeDelta::ms(-kValue).IsFinite()); - EXPECT_TRUE(TimeDelta::ms(kValue).IsFinite()); - EXPECT_TRUE(TimeDelta::Zero().IsFinite()); -} - -TEST(TimeDeltaTest, ComparisonOperators) { - const int64_t kSmall = 450; - const int64_t kLarge = 451; - const TimeDelta small = TimeDelta::ms(kSmall); - const TimeDelta large = TimeDelta::ms(kLarge); - - EXPECT_EQ(TimeDelta::Zero(), TimeDelta::Zero()); - EXPECT_EQ(TimeDelta::Infinity(), TimeDelta::Infinity()); - EXPECT_EQ(small, TimeDelta::ms(kSmall)); - EXPECT_LE(small, TimeDelta::ms(kSmall)); - EXPECT_GE(small, TimeDelta::ms(kSmall)); - EXPECT_NE(small, TimeDelta::ms(kLarge)); - EXPECT_LE(small, TimeDelta::ms(kLarge)); - EXPECT_LT(small, TimeDelta::ms(kLarge)); - EXPECT_GE(large, TimeDelta::ms(kSmall)); - EXPECT_GT(large, TimeDelta::ms(kSmall)); - EXPECT_LT(TimeDelta::kZero, small); - EXPECT_GT(TimeDelta::kZero, TimeDelta::ms(-kSmall)); - EXPECT_GT(TimeDelta::kZero, TimeDelta::ms(-kSmall)); - - EXPECT_GT(TimeDelta::kPlusInfinity, large); - EXPECT_LT(TimeDelta::kMinusInfinity, TimeDelta::kZero); -} - -TEST(TimeDeltaTest, MathOperations) { - const int64_t kValueA = 267; - const int64_t kValueB = 450; - const TimeDelta delta_a = TimeDelta::ms(kValueA); - const TimeDelta delta_b = TimeDelta::ms(kValueB); - EXPECT_EQ((delta_a + delta_b).ms(), kValueA + kValueB); - EXPECT_EQ((delta_a - delta_b).ms(), kValueA - kValueB); - - const int32_t kInt32Value = 123; - const double kFloatValue = 123.0; - EXPECT_EQ((TimeDelta::us(kValueA) * kValueB).us(), kValueA * kValueB); - EXPECT_EQ((TimeDelta::us(kValueA) * kInt32Value).us(), kValueA * kInt32Value); - EXPECT_EQ((TimeDelta::us(kValueA) * kFloatValue).us(), kValueA * kFloatValue); - - EXPECT_EQ(TimeDelta::us(-kValueA).Abs().us(), kValueA); - EXPECT_EQ(TimeDelta::us(kValueA).Abs().us(), kValueA); -} - -TEST(TimestampTest, GetBackSameValues) { - const int64_t kValue = 499; - EXPECT_EQ(Timestamp::ms(kValue).ms(), kValue); - EXPECT_EQ(Timestamp::us(kValue).us(), kValue); - EXPECT_EQ(Timestamp::s(kValue).s(), kValue); -} - -TEST(TimestampTest, GetDifferentPrefix) { - const int64_t kValue = 3000000; - EXPECT_EQ(Timestamp::us(kValue).s(), kValue / 1000000); - EXPECT_EQ(Timestamp::ms(kValue).s(), kValue / 1000); - EXPECT_EQ(Timestamp::us(kValue).ms(), kValue / 1000); - - EXPECT_EQ(Timestamp::ms(kValue).us(), kValue * 1000); - EXPECT_EQ(Timestamp::s(kValue).ms(), kValue * 1000); - EXPECT_EQ(Timestamp::s(kValue).us(), kValue * 1000000); -} - -TEST(TimestampTest, IdentityChecks) { - const int64_t kValue = 3000; - - EXPECT_TRUE(Timestamp::Infinity().IsInfinite()); - EXPECT_FALSE(Timestamp::ms(kValue).IsInfinite()); - - EXPECT_FALSE(Timestamp::kNotInitialized.IsFinite()); - EXPECT_FALSE(Timestamp::Infinity().IsFinite()); - EXPECT_TRUE(Timestamp::ms(kValue).IsFinite()); -} - -TEST(TimestampTest, ComparisonOperators) { - const int64_t kSmall = 450; - const int64_t kLarge = 451; - - EXPECT_EQ(Timestamp::Infinity(), Timestamp::Infinity()); - EXPECT_EQ(Timestamp::ms(kSmall), Timestamp::ms(kSmall)); - EXPECT_LE(Timestamp::ms(kSmall), Timestamp::ms(kSmall)); - EXPECT_GE(Timestamp::ms(kSmall), Timestamp::ms(kSmall)); - EXPECT_NE(Timestamp::ms(kSmall), Timestamp::ms(kLarge)); - EXPECT_LE(Timestamp::ms(kSmall), Timestamp::ms(kLarge)); - EXPECT_LT(Timestamp::ms(kSmall), Timestamp::ms(kLarge)); - EXPECT_GE(Timestamp::ms(kLarge), Timestamp::ms(kSmall)); - EXPECT_GT(Timestamp::ms(kLarge), Timestamp::ms(kSmall)); -} - -TEST(UnitConversionTest, TimestampAndTimeDeltaMath) { - const int64_t kValueA = 267; - const int64_t kValueB = 450; - const Timestamp time_a = Timestamp::ms(kValueA); - const Timestamp time_b = Timestamp::ms(kValueB); - const TimeDelta delta_a = TimeDelta::ms(kValueA); - - EXPECT_EQ((time_a - time_b), TimeDelta::ms(kValueA - kValueB)); - EXPECT_EQ((time_b - delta_a), Timestamp::ms(kValueB - kValueA)); - EXPECT_EQ((time_b + delta_a), Timestamp::ms(kValueB + kValueA)); -} - -TEST(DataSizeTest, GetBackSameValues) { - const int64_t kValue = 123 * 8; - EXPECT_EQ(DataSize::bytes(kValue).bytes(), kValue); - EXPECT_EQ(DataSize::bits(kValue).bits(), kValue); -} - -TEST(DataSizeTest, GetDifferentPrefix) { - const int64_t kValue = 123 * 8000; - EXPECT_EQ(DataSize::bytes(kValue).bits(), kValue * 8); - EXPECT_EQ(DataSize::bits(kValue).bytes(), kValue / 8); - EXPECT_EQ(DataSize::bits(kValue).kilobits(), kValue / 1000); - EXPECT_EQ(DataSize::bytes(kValue).kilobytes(), kValue / 1000); -} - -TEST(DataSizeTest, IdentityChecks) { - const int64_t kValue = 3000; - EXPECT_TRUE(DataSize::Zero().IsZero()); - EXPECT_FALSE(DataSize::bytes(kValue).IsZero()); - - EXPECT_TRUE(DataSize::Infinity().IsInfinite()); - EXPECT_TRUE(DataSize::kPlusInfinity.IsInfinite()); - EXPECT_FALSE(DataSize::Zero().IsInfinite()); - EXPECT_FALSE(DataSize::bytes(kValue).IsInfinite()); - - EXPECT_FALSE(DataSize::Infinity().IsFinite()); - EXPECT_FALSE(DataSize::kPlusInfinity.IsFinite()); - EXPECT_TRUE(DataSize::bytes(kValue).IsFinite()); - EXPECT_TRUE(DataSize::Zero().IsFinite()); -} - -TEST(DataSizeTest, ComparisonOperators) { - const int64_t kSmall = 450; - const int64_t kLarge = 451; - const DataSize small = DataSize::bytes(kSmall); - const DataSize large = DataSize::bytes(kLarge); - - EXPECT_EQ(DataSize::Zero(), DataSize::Zero()); - EXPECT_EQ(DataSize::Infinity(), DataSize::Infinity()); - EXPECT_EQ(small, small); - EXPECT_LE(small, small); - EXPECT_GE(small, small); - EXPECT_NE(small, large); - EXPECT_LE(small, large); - EXPECT_LT(small, large); - EXPECT_GE(large, small); - EXPECT_GT(large, small); - EXPECT_LT(DataSize::kZero, small); - - EXPECT_GT(DataSize::kPlusInfinity, large); -} - -TEST(DataSizeTest, MathOperations) { - const int64_t kValueA = 450; - const int64_t kValueB = 267; - const DataSize size_a = DataSize::bytes(kValueA); - const DataSize size_b = DataSize::bytes(kValueB); - EXPECT_EQ((size_a + size_b).bytes(), kValueA + kValueB); - EXPECT_EQ((size_a - size_b).bytes(), kValueA - kValueB); - - const int32_t kInt32Value = 123; - const double kFloatValue = 123.0; - EXPECT_EQ((size_a * kValueB).bytes(), kValueA * kValueB); - EXPECT_EQ((size_a * kInt32Value).bytes(), kValueA * kInt32Value); - EXPECT_EQ((size_a * kFloatValue).bytes(), kValueA * kFloatValue); - - EXPECT_EQ((size_a / 10).bytes(), kValueA / 10); - - DataSize mutable_size = DataSize::bytes(kValueA); - mutable_size += size_b; - EXPECT_EQ(mutable_size.bytes(), kValueA + kValueB); - mutable_size -= size_a; - EXPECT_EQ(mutable_size.bytes(), kValueB); -} - -TEST(DataRateTest, GetBackSameValues) { - const int64_t kValue = 123 * 8; - EXPECT_EQ(DataRate::bytes_per_second(kValue).bytes_per_second(), kValue); - EXPECT_EQ(DataRate::bits_per_second(kValue).bits_per_second(), kValue); - EXPECT_EQ(DataRate::bps(kValue).bps(), kValue); - EXPECT_EQ(DataRate::kbps(kValue).kbps(), kValue); -} - -TEST(DataRateTest, GetDifferentPrefix) { - const int64_t kValue = 123 * 8000; - EXPECT_EQ(DataRate::bytes_per_second(kValue).bps(), kValue * 8); - EXPECT_EQ(DataRate::bits_per_second(kValue).bytes_per_second(), kValue / 8); - EXPECT_EQ(DataRate::bps(kValue).kbps(), kValue / 1000); -} - -TEST(DataRateTest, IdentityChecks) { - const int64_t kValue = 3000; - EXPECT_TRUE(DataRate::Zero().IsZero()); - EXPECT_FALSE(DataRate::bytes_per_second(kValue).IsZero()); - - EXPECT_TRUE(DataRate::Infinity().IsInfinite()); - EXPECT_TRUE(DataRate::kPlusInfinity.IsInfinite()); - EXPECT_FALSE(DataRate::Zero().IsInfinite()); - EXPECT_FALSE(DataRate::bytes_per_second(kValue).IsInfinite()); - - EXPECT_FALSE(DataRate::Infinity().IsFinite()); - EXPECT_FALSE(DataRate::kPlusInfinity.IsFinite()); - EXPECT_TRUE(DataRate::bytes_per_second(kValue).IsFinite()); - EXPECT_TRUE(DataRate::Zero().IsFinite()); -} - -TEST(DataRateTest, ComparisonOperators) { - const int64_t kSmall = 450; - const int64_t kLarge = 451; - const DataRate small = DataRate::bytes_per_second(kSmall); - const DataRate large = DataRate::bytes_per_second(kLarge); - - EXPECT_EQ(DataRate::Zero(), DataRate::Zero()); - EXPECT_EQ(DataRate::Infinity(), DataRate::Infinity()); - EXPECT_EQ(small, small); - EXPECT_LE(small, small); - EXPECT_GE(small, small); - EXPECT_NE(small, large); - EXPECT_LE(small, large); - EXPECT_LT(small, large); - EXPECT_GE(large, small); - EXPECT_GT(large, small); - EXPECT_LT(DataRate::kZero, small); - EXPECT_GT(DataRate::kPlusInfinity, large); -} - -TEST(DataRateTest, MathOperations) { - const int64_t kValueA = 450; - const int64_t kValueB = 267; - const DataRate size_a = DataRate::bytes_per_second(kValueA); - const int32_t kInt32Value = 123; - const double kFloatValue = 123.0; - EXPECT_EQ((size_a * kValueB).bytes_per_second(), kValueA * kValueB); - EXPECT_EQ((size_a * kInt32Value).bytes_per_second(), kValueA * kInt32Value); - EXPECT_EQ((size_a * kFloatValue).bytes_per_second(), kValueA * kFloatValue); -} - -TEST(UnitConversionTest, DataRateAndDataSizeAndTimeDelta) { - const int64_t kValueA = 5; - const int64_t kValueB = 450; - const int64_t kValueC = 45000; - const TimeDelta delta_a = TimeDelta::seconds(kValueA); - const DataRate rate_b = DataRate::bytes_per_second(kValueB); - const DataSize size_c = DataSize::bytes(kValueC); - EXPECT_EQ((delta_a * rate_b).bytes(), kValueA * kValueB); - EXPECT_EQ((size_c / delta_a).bytes_per_second(), kValueC / kValueA); - EXPECT_EQ((size_c / rate_b).s(), kValueC / kValueB); -} - -} // namespace test -} // namespace webrtc diff --git a/modules/congestion_controller/pacer_controller.cc b/modules/congestion_controller/pacer_controller.cc deleted file mode 100644 index 556448bcc87..00000000000 --- a/modules/congestion_controller/pacer_controller.cc +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2018 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/pacer_controller.h" - -#include "modules/congestion_controller/network_control/include/network_units.h" -#include "rtc_base/checks.h" -#include "rtc_base/logging.h" - -namespace webrtc { - -PacerController::PacerController(PacedSender* pacer) : pacer_(pacer) { - sequenced_checker_.Detach(); -} - -PacerController::~PacerController() = default; - -void PacerController::OnCongestionWindow(CongestionWindow congestion_window) { - RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_); - if (congestion_window.enabled) { - congestion_window_ = congestion_window; - } else { - congestion_window_ = rtc::nullopt; - congested_ = false; - UpdatePacerState(); - } -} - -void PacerController::OnNetworkAvailability(NetworkAvailability msg) { - RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_); - network_available_ = msg.network_available; - congested_ = false; - UpdatePacerState(); -} - -void PacerController::OnNetworkRouteChange(NetworkRouteChange) { - RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_); - congested_ = false; - UpdatePacerState(); -} - -void PacerController::OnPacerConfig(PacerConfig msg) { - RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_); - DataRate pacing_rate = msg.data_window / msg.time_window; - DataRate padding_rate = msg.pad_window / msg.time_window; - pacer_->SetPacingRates(pacing_rate.bps(), padding_rate.bps()); -} - -void PacerController::OnProbeClusterConfig(ProbeClusterConfig config) { - RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_); - int64_t bitrate_bps = config.target_data_rate.bps(); - pacer_->CreateProbeCluster(bitrate_bps); -} - -void PacerController::OnOutstandingData(OutstandingData msg) { - RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_); - if (congestion_window_.has_value()) { - congested_ = msg.in_flight_data > congestion_window_->data_window; - } - UpdatePacerState(); -} - -void PacerController::UpdatePacerState() { - bool pause = congested_ || !network_available_; - SetPacerState(pause); -} - -void PacerController::SetPacerState(bool paused) { - if (paused && !pacer_paused_) - pacer_->Pause(); - else if (!paused && pacer_paused_) - pacer_->Resume(); - pacer_paused_ = paused; -} - -} // namespace webrtc diff --git a/modules/congestion_controller/pacer_controller.h b/modules/congestion_controller/pacer_controller.h deleted file mode 100644 index 2679894a136..00000000000 --- a/modules/congestion_controller/pacer_controller.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#ifndef MODULES_CONGESTION_CONTROLLER_PACER_CONTROLLER_H_ -#define MODULES_CONGESTION_CONTROLLER_PACER_CONTROLLER_H_ - -#include - -#include "modules/congestion_controller/network_control/include/network_types.h" -#include "modules/pacing/paced_sender.h" -#include "rtc_base/sequenced_task_checker.h" - -namespace webrtc { -class Clock; - -// Wrapper class to control pacer using task queues. Note that this class is -// only designed to be used from a single task queue and has no built in -// concurrency safety. -// TODO(srte): Integrate this interface directly into PacedSender. -class PacerController { - public: - explicit PacerController(PacedSender* pacer); - ~PacerController(); - void OnCongestionWindow(CongestionWindow msg); - void OnNetworkAvailability(NetworkAvailability msg); - void OnNetworkRouteChange(NetworkRouteChange msg); - void OnOutstandingData(OutstandingData msg); - void OnPacerConfig(PacerConfig msg); - void OnProbeClusterConfig(ProbeClusterConfig msg); - - private: - void UpdatePacerState(); - void SetPacerState(bool paused); - PacedSender* const pacer_; - - rtc::Optional current_pacer_config_; - rtc::Optional congestion_window_; - bool congested_ = false; - bool pacer_paused_ = false; - bool network_available_ = true; - - rtc::SequencedTaskChecker sequenced_checker_; - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(PacerController); -}; -} // namespace webrtc -#endif // MODULES_CONGESTION_CONTROLLER_PACER_CONTROLLER_H_ diff --git a/modules/congestion_controller/probe_bitrate_estimator.cc b/modules/congestion_controller/probe_bitrate_estimator.cc index 34f489178dd..8c754d789cd 100644 --- a/modules/congestion_controller/probe_bitrate_estimator.cc +++ b/modules/congestion_controller/probe_bitrate_estimator.cc @@ -66,8 +66,8 @@ int ProbeBitrateEstimator::HandleProbeAndEstimateBitrate( EraseOldClusters(packet_feedback.arrival_time_ms - kMaxClusterHistoryMs); - int payload_size_bits = - rtc::dchecked_cast(packet_feedback.payload_size * 8); + int payload_size_bits = rtc::dchecked_cast( + packet_feedback.payload_size * 8); AggregatedCluster* cluster = &clusters_[cluster_id]; if (packet_feedback.send_time_ms < cluster->first_send_ms) { diff --git a/modules/congestion_controller/probe_bitrate_estimator.h b/modules/congestion_controller/probe_bitrate_estimator.h index cb10a6fa316..bb8a7ed534e 100644 --- a/modules/congestion_controller/probe_bitrate_estimator.h +++ b/modules/congestion_controller/probe_bitrate_estimator.h @@ -11,8 +11,8 @@ #ifndef MODULES_CONGESTION_CONTROLLER_PROBE_BITRATE_ESTIMATOR_H_ #define MODULES_CONGESTION_CONTROLLER_PROBE_BITRATE_ESTIMATOR_H_ -#include #include +#include #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" diff --git a/modules/congestion_controller/probe_bitrate_estimator_unittest.cc b/modules/congestion_controller/probe_bitrate_estimator_unittest.cc index df4f24be90f..6d21de449de 100644 --- a/modules/congestion_controller/probe_bitrate_estimator_unittest.cc +++ b/modules/congestion_controller/probe_bitrate_estimator_unittest.cc @@ -10,8 +10,8 @@ #include "modules/congestion_controller/probe_bitrate_estimator.h" -#include #include +#include #include "modules/remote_bitrate_estimator/aimd_rate_control.h" #include "test/gmock.h" diff --git a/modules/congestion_controller/probe_controller.cc b/modules/congestion_controller/probe_controller.cc index b0fca7b3c88..8e6ae7cca14 100644 --- a/modules/congestion_controller/probe_controller.cc +++ b/modules/congestion_controller/probe_controller.cc @@ -21,12 +21,6 @@ namespace webrtc { namespace { -// The minimum number probing packets used. -constexpr int kMinProbePacketsSent = 5; - -// The minimum probing duration in ms. -constexpr int kMinProbeDurationMs = 15; - // Maximum waiting time from the time of initiating probing to getting // the measured results back. constexpr int64_t kMaxWaitingTimeForProbingResultMs = 1000; @@ -75,20 +69,19 @@ constexpr char kBweRapidRecoveryExperiment[] = } // namespace -ProbeController::ProbeController(NetworkControllerObserver* observer) - : observer_(observer), enable_periodic_alr_probing_(false) { - Reset(0); +ProbeController::ProbeController(PacedSender* pacer, const Clock* clock) + : pacer_(pacer), clock_(clock), enable_periodic_alr_probing_(false) { + Reset(); in_rapid_recovery_experiment_ = webrtc::field_trial::FindFullName( kBweRapidRecoveryExperiment) == "Enabled"; } -ProbeController::~ProbeController() {} - void ProbeController::SetBitrates(int64_t min_bitrate_bps, int64_t start_bitrate_bps, - int64_t max_bitrate_bps, - int64_t at_time_ms) { - if (start_bitrate_bps > 0) { + int64_t max_bitrate_bps) { + rtc::CritScope cs(&critsect_); + + if (start_bitrate_bps > 0) { start_bitrate_bps_ = start_bitrate_bps; estimated_bitrate_bps_ = start_bitrate_bps; } else if (start_bitrate_bps_ == 0) { @@ -102,8 +95,8 @@ void ProbeController::SetBitrates(int64_t min_bitrate_bps, switch (state_) { case State::kInit: - if (network_available_) - InitiateExponentialProbing(at_time_ms); + if (network_state_ == kNetworkUp) + InitiateExponentialProbing(); break; case State::kWaitingForProbingResult: @@ -126,32 +119,33 @@ void ProbeController::SetBitrates(int64_t min_bitrate_bps, RTC_HISTOGRAM_COUNTS_10000("WebRTC.BWE.MidCallProbing.Initiated", max_bitrate_bps_ / 1000); - InitiateProbing(at_time_ms, {max_bitrate_bps}, false); + InitiateProbing(clock_->TimeInMilliseconds(), {max_bitrate_bps}, false); } break; } } -void ProbeController::OnNetworkAvailability(NetworkAvailability msg) { - network_available_ = msg.network_available; - if (network_available_ && state_ == State::kInit && start_bitrate_bps_ > 0) - InitiateExponentialProbing(msg.at_time.ms()); +void ProbeController::OnNetworkStateChanged(NetworkState network_state) { + rtc::CritScope cs(&critsect_); + network_state_ = network_state; + if (network_state_ == kNetworkUp && state_ == State::kInit) + InitiateExponentialProbing(); } -void ProbeController::InitiateExponentialProbing(int64_t at_time_ms) { - RTC_DCHECK(network_available_); +void ProbeController::InitiateExponentialProbing() { + RTC_DCHECK(network_state_ == kNetworkUp); RTC_DCHECK(state_ == State::kInit); RTC_DCHECK_GT(start_bitrate_bps_, 0); // When probing at 1.8 Mbps ( 6x 300), this represents a threshold of // 1.2 Mbps to continue probing. - InitiateProbing(at_time_ms, {3 * start_bitrate_bps_, 6 * start_bitrate_bps_}, - true); + InitiateProbing(clock_->TimeInMilliseconds(), + {3 * start_bitrate_bps_, 6 * start_bitrate_bps_}, true); } -void ProbeController::SetEstimatedBitrate(int64_t bitrate_bps, - int64_t at_time_ms) { - int64_t now_ms = at_time_ms; +void ProbeController::SetEstimatedBitrate(int64_t bitrate_bps) { + rtc::CritScope cs(&critsect_); + int64_t now_ms = clock_->TimeInMilliseconds(); if (mid_call_probing_waiting_for_result_ && bitrate_bps >= mid_call_probing_succcess_threshold_) { @@ -185,36 +179,36 @@ void ProbeController::SetEstimatedBitrate(int64_t bitrate_bps, } void ProbeController::EnablePeriodicAlrProbing(bool enable) { + rtc::CritScope cs(&critsect_); enable_periodic_alr_probing_ = enable; } -void ProbeController::SetAlrStartTimeMs( - rtc::Optional alr_start_time_ms) { - alr_start_time_ms_ = alr_start_time_ms; -} void ProbeController::SetAlrEndedTimeMs(int64_t alr_end_time_ms) { + rtc::CritScope cs(&critsect_); alr_end_time_ms_.emplace(alr_end_time_ms); } -void ProbeController::RequestProbe(int64_t at_time_ms) { +void ProbeController::RequestProbe() { + int64_t now_ms = clock_->TimeInMilliseconds(); + rtc::CritScope cs(&critsect_); // Called once we have returned to normal state after a large drop in // estimated bandwidth. The current response is to initiate a single probe // session (if not already probing) at the previous bitrate. // // If the probe session fails, the assumption is that this drop was a // real one from a competing flow or a network change. - bool in_alr = alr_start_time_ms_.has_value(); + bool in_alr = pacer_->GetApplicationLimitedRegionStartTime().has_value(); bool alr_ended_recently = (alr_end_time_ms_.has_value() && - at_time_ms - alr_end_time_ms_.value() < kAlrEndedTimeoutMs); + now_ms - alr_end_time_ms_.value() < kAlrEndedTimeoutMs); if (in_alr || alr_ended_recently || in_rapid_recovery_experiment_) { if (state_ == State::kProbingComplete) { uint32_t suggested_probe_bps = kProbeFractionAfterDrop * bitrate_before_last_large_drop_bps_; uint32_t min_expected_probe_result_bps = (1 - kProbeUncertainty) * suggested_probe_bps; - int64_t time_since_drop_ms = at_time_ms - time_of_last_large_drop_ms_; - int64_t time_since_probe_ms = at_time_ms - last_bwe_drop_probing_time_ms_; + int64_t time_since_drop_ms = now_ms - time_of_last_large_drop_ms_; + int64_t time_since_probe_ms = now_ms - last_bwe_drop_probing_time_ms_; if (min_expected_probe_result_bps > estimated_bitrate_bps_ && time_since_drop_ms < kBitrateDropTimeoutMs && time_since_probe_ms > kMinTimeBetweenAlrProbesMs) { @@ -222,23 +216,24 @@ void ProbeController::RequestProbe(int64_t at_time_ms) { // Track how often we probe in response to bandwidth drop in ALR. RTC_HISTOGRAM_COUNTS_10000( "WebRTC.BWE.BweDropProbingIntervalInS", - (at_time_ms - last_bwe_drop_probing_time_ms_) / 1000); - InitiateProbing(at_time_ms, {suggested_probe_bps}, false); - last_bwe_drop_probing_time_ms_ = at_time_ms; + (now_ms - last_bwe_drop_probing_time_ms_) / 1000); + InitiateProbing(now_ms, {suggested_probe_bps}, false); + last_bwe_drop_probing_time_ms_ = now_ms; } } } } -void ProbeController::Reset(int64_t at_time_ms) { - network_available_ = true; +void ProbeController::Reset() { + rtc::CritScope cs(&critsect_); + network_state_ = kNetworkUp; state_ = State::kInit; min_bitrate_to_probe_further_bps_ = kExponentialProbingDisabled; time_last_probing_initiated_ms_ = 0; estimated_bitrate_bps_ = 0; start_bitrate_bps_ = 0; max_bitrate_bps_ = 0; - int64_t now_ms = at_time_ms; + int64_t now_ms = clock_->TimeInMilliseconds(); last_bwe_drop_probing_time_ms_ = now_ms; alr_end_time_ms_.reset(); mid_call_probing_waiting_for_result_ = false; @@ -246,8 +241,10 @@ void ProbeController::Reset(int64_t at_time_ms) { bitrate_before_last_large_drop_bps_ = 0; } -void ProbeController::Process(int64_t at_time_ms) { - int64_t now_ms = at_time_ms; +void ProbeController::Process() { + rtc::CritScope cs(&critsect_); + + int64_t now_ms = clock_->TimeInMilliseconds(); if (now_ms - time_last_probing_initiated_ms_ > kMaxWaitingTimeForProbingResultMs) { @@ -264,9 +261,11 @@ void ProbeController::Process(int64_t at_time_ms) { return; // Probe bandwidth periodically when in ALR state. - if (alr_start_time_ms_ && estimated_bitrate_bps_ > 0) { + rtc::Optional alr_start_time = + pacer_->GetApplicationLimitedRegionStartTime(); + if (alr_start_time && estimated_bitrate_bps_ > 0) { int64_t next_probe_time_ms = - std::max(*alr_start_time_ms_, time_last_probing_initiated_ms_) + + std::max(*alr_start_time, time_last_probing_initiated_ms_) + kAlrPeriodicProbingIntervalMs; if (now_ms >= next_probe_time_ms) { InitiateProbing(now_ms, {estimated_bitrate_bps_ * 2}, true); @@ -286,13 +285,7 @@ void ProbeController::InitiateProbing( bitrate = max_probe_bitrate_bps; probe_further = false; } - - ProbeClusterConfig config; - config.at_time = Timestamp::ms(now_ms); - config.target_data_rate = DataRate::bps(rtc::dchecked_cast(bitrate)); - config.target_duration = TimeDelta::ms(kMinProbeDurationMs); - config.target_probe_count = kMinProbePacketsSent; - observer_->OnProbeClusterConfig(config); + pacer_->CreateProbeCluster(rtc::dchecked_cast(bitrate)); } time_last_probing_initiated_ms_ = now_ms; if (probe_further) { diff --git a/modules/congestion_controller/probe_controller.h b/modules/congestion_controller/probe_controller.h index 187a274507e..cd0e9b1b572 100644 --- a/modules/congestion_controller/probe_controller.h +++ b/modules/congestion_controller/probe_controller.h @@ -11,12 +11,11 @@ #ifndef MODULES_CONGESTION_CONTROLLER_PROBE_CONTROLLER_H_ #define MODULES_CONGESTION_CONTROLLER_PROBE_CONTROLLER_H_ -#include - #include -#include "api/optional.h" -#include "modules/congestion_controller/network_control/include/network_control.h" +#include "common_types.h" // NOLINT(build/include) +#include "modules/pacing/paced_sender.h" +#include "rtc_base/criticalsection.h" namespace webrtc { @@ -27,30 +26,27 @@ class Clock; // bitrate is adjusted by an application. class ProbeController { public: - explicit ProbeController(NetworkControllerObserver* observer); - ~ProbeController(); + ProbeController(PacedSender* pacer, const Clock* clock); void SetBitrates(int64_t min_bitrate_bps, int64_t start_bitrate_bps, - int64_t max_bitrate_bps, - int64_t at_time_ms); + int64_t max_bitrate_bps); - void OnNetworkAvailability(NetworkAvailability msg); + void OnNetworkStateChanged(NetworkState state); - void SetEstimatedBitrate(int64_t bitrate_bps, int64_t at_time_ms); + void SetEstimatedBitrate(int64_t bitrate_bps); void EnablePeriodicAlrProbing(bool enable); - void SetAlrStartTimeMs(rtc::Optional alr_start_time); void SetAlrEndedTimeMs(int64_t alr_end_time); - void RequestProbe(int64_t at_time_ms); + void RequestProbe(); // Resets the ProbeController to a state equivalent to as if it was just // created EXCEPT for |enable_periodic_alr_probing_|. - void Reset(int64_t at_time_ms); + void Reset(); - void Process(int64_t at_time_ms); + void Process(); private: enum class State { @@ -62,32 +58,33 @@ class ProbeController { kProbingComplete, }; - void InitiateExponentialProbing(int64_t at_time_ms); + void InitiateExponentialProbing() RTC_EXCLUSIVE_LOCKS_REQUIRED(critsect_); void InitiateProbing(int64_t now_ms, std::initializer_list bitrates_to_probe, - bool probe_further); - - NetworkControllerObserver* const observer_; - - bool network_available_; - State state_; - int64_t min_bitrate_to_probe_further_bps_; - int64_t time_last_probing_initiated_ms_; - int64_t estimated_bitrate_bps_; - int64_t start_bitrate_bps_; - int64_t max_bitrate_bps_; - int64_t last_bwe_drop_probing_time_ms_; - rtc::Optional alr_start_time_ms_; - rtc::Optional alr_end_time_ms_; - bool enable_periodic_alr_probing_; - int64_t time_of_last_large_drop_ms_; - int64_t bitrate_before_last_large_drop_bps_; - - bool in_rapid_recovery_experiment_; + bool probe_further) + RTC_EXCLUSIVE_LOCKS_REQUIRED(critsect_); + + rtc::CriticalSection critsect_; + PacedSender* const pacer_; + const Clock* const clock_; + NetworkState network_state_ RTC_GUARDED_BY(critsect_); + State state_ RTC_GUARDED_BY(critsect_); + int64_t min_bitrate_to_probe_further_bps_ RTC_GUARDED_BY(critsect_); + int64_t time_last_probing_initiated_ms_ RTC_GUARDED_BY(critsect_); + int64_t estimated_bitrate_bps_ RTC_GUARDED_BY(critsect_); + int64_t start_bitrate_bps_ RTC_GUARDED_BY(critsect_); + int64_t max_bitrate_bps_ RTC_GUARDED_BY(critsect_); + int64_t last_bwe_drop_probing_time_ms_ RTC_GUARDED_BY(critsect_); + rtc::Optional alr_end_time_ms_ RTC_GUARDED_BY(critsect_); + bool enable_periodic_alr_probing_ RTC_GUARDED_BY(critsect_); + int64_t time_of_last_large_drop_ms_ RTC_GUARDED_BY(critsect_); + int64_t bitrate_before_last_large_drop_bps_ RTC_GUARDED_BY(critsect_); + + bool in_rapid_recovery_experiment_ RTC_GUARDED_BY(critsect_); // For WebRTC.BWE.MidCallProbing.* metric. - bool mid_call_probing_waiting_for_result_; - int64_t mid_call_probing_bitrate_bps_; - int64_t mid_call_probing_succcess_threshold_; + bool mid_call_probing_waiting_for_result_ RTC_GUARDED_BY(&critsect_); + int64_t mid_call_probing_bitrate_bps_ RTC_GUARDED_BY(&critsect_); + int64_t mid_call_probing_succcess_threshold_ RTC_GUARDED_BY(&critsect_); RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(ProbeController); }; diff --git a/modules/congestion_controller/probe_controller_unittest.cc b/modules/congestion_controller/probe_controller_unittest.cc index ac889dcd7cd..3477c87a26f 100644 --- a/modules/congestion_controller/probe_controller_unittest.cc +++ b/modules/congestion_controller/probe_controller_unittest.cc @@ -9,8 +9,8 @@ */ #include -#include "modules/congestion_controller/network_control/include/network_types.h" #include "modules/congestion_controller/probe_controller.h" +#include "modules/pacing/mock/mock_paced_sender.h" #include "rtc_base/logging.h" #include "system_wrappers/include/clock.h" #include "test/gmock.h" @@ -18,13 +18,9 @@ using testing::_; using testing::AtLeast; -using testing::Field; -using testing::Matcher; using testing::NiceMock; using testing::Return; -using webrtc::ProbeClusterConfig; - namespace webrtc { namespace test { @@ -40,252 +36,234 @@ constexpr int kAlrProbeInterval = 5000; constexpr int kAlrEndedTimeoutMs = 3000; constexpr int kBitrateDropTimeoutMs = 5000; -inline Matcher DataRateEqBps(int bps) { - return Field(&ProbeClusterConfig::target_data_rate, DataRate::bps(bps)); -} -class MockNetworkControllerObserver : public NetworkControllerObserver { - public: - MOCK_METHOD1(OnCongestionWindow, void(CongestionWindow)); - MOCK_METHOD1(OnPacerConfig, void(PacerConfig)); - MOCK_METHOD1(OnProbeClusterConfig, void(ProbeClusterConfig)); - MOCK_METHOD1(OnTargetTransferRate, void(TargetTransferRate)); -}; } // namespace class ProbeControllerTest : public ::testing::Test { protected: ProbeControllerTest() : clock_(100000000L) { - probe_controller_.reset(new ProbeController(&cluster_handler_)); + probe_controller_.reset(new ProbeController(&pacer_, &clock_)); } ~ProbeControllerTest() override {} - void SetNetworkAvailable(bool available) { - NetworkAvailability msg; - msg.at_time = Timestamp::ms(NowMs()); - msg.network_available = available; - probe_controller_->OnNetworkAvailability(msg); - } - - int64_t NowMs() { return clock_.TimeInMilliseconds(); } - SimulatedClock clock_; - NiceMock cluster_handler_; + NiceMock pacer_; std::unique_ptr probe_controller_; }; TEST_F(ProbeControllerTest, InitiatesProbingAtStart) { - EXPECT_CALL(cluster_handler_, OnProbeClusterConfig(_)).Times(AtLeast(2)); + EXPECT_CALL(pacer_, CreateProbeCluster(_)).Times(AtLeast(2)); probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps, - kMaxBitrateBps, NowMs()); + kMaxBitrateBps); } TEST_F(ProbeControllerTest, ProbeOnlyWhenNetworkIsUp) { - SetNetworkAvailable(false); - EXPECT_CALL(cluster_handler_, OnProbeClusterConfig(_)).Times(0); + probe_controller_->OnNetworkStateChanged(kNetworkDown); + EXPECT_CALL(pacer_, CreateProbeCluster(_)).Times(0); probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps, - kMaxBitrateBps, NowMs()); + kMaxBitrateBps); - testing::Mock::VerifyAndClearExpectations(&cluster_handler_); - EXPECT_CALL(cluster_handler_, OnProbeClusterConfig(_)).Times(AtLeast(2)); - SetNetworkAvailable(true); + testing::Mock::VerifyAndClearExpectations(&pacer_); + EXPECT_CALL(pacer_, CreateProbeCluster(_)).Times(AtLeast(2)); + probe_controller_->OnNetworkStateChanged(kNetworkUp); } TEST_F(ProbeControllerTest, InitiatesProbingOnMaxBitrateIncrease) { - EXPECT_CALL(cluster_handler_, OnProbeClusterConfig(_)).Times(AtLeast(2)); + EXPECT_CALL(pacer_, CreateProbeCluster(_)).Times(AtLeast(2)); probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps, - kMaxBitrateBps, NowMs()); + kMaxBitrateBps); // Long enough to time out exponential probing. clock_.AdvanceTimeMilliseconds(kExponentialProbingTimeoutMs); - probe_controller_->SetEstimatedBitrate(kStartBitrateBps, NowMs()); - probe_controller_->Process(NowMs()); + probe_controller_->SetEstimatedBitrate(kStartBitrateBps); + probe_controller_->Process(); - EXPECT_CALL(cluster_handler_, - OnProbeClusterConfig(DataRateEqBps(kMaxBitrateBps + 100))); + EXPECT_CALL(pacer_, CreateProbeCluster(kMaxBitrateBps + 100)); probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps, - kMaxBitrateBps + 100, NowMs()); + kMaxBitrateBps + 100); } TEST_F(ProbeControllerTest, InitiatesProbingOnMaxBitrateIncreaseAtMaxBitrate) { - EXPECT_CALL(cluster_handler_, OnProbeClusterConfig(_)).Times(AtLeast(2)); + EXPECT_CALL(pacer_, CreateProbeCluster(_)).Times(AtLeast(2)); probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps, - kMaxBitrateBps, NowMs()); + kMaxBitrateBps); // Long enough to time out exponential probing. clock_.AdvanceTimeMilliseconds(kExponentialProbingTimeoutMs); - probe_controller_->SetEstimatedBitrate(kStartBitrateBps, NowMs()); - probe_controller_->Process(NowMs()); + probe_controller_->SetEstimatedBitrate(kStartBitrateBps); + probe_controller_->Process(); - probe_controller_->SetEstimatedBitrate(kMaxBitrateBps, NowMs()); - EXPECT_CALL(cluster_handler_, - OnProbeClusterConfig(DataRateEqBps(kMaxBitrateBps + 100))); + probe_controller_->SetEstimatedBitrate(kMaxBitrateBps); + EXPECT_CALL(pacer_, CreateProbeCluster(kMaxBitrateBps + 100)); probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps, - kMaxBitrateBps + 100, NowMs()); + kMaxBitrateBps + 100); } TEST_F(ProbeControllerTest, TestExponentialProbing) { probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps, - kMaxBitrateBps, NowMs()); + kMaxBitrateBps); // Repeated probe should only be sent when estimated bitrate climbs above // 0.7 * 6 * kStartBitrateBps = 1260. - EXPECT_CALL(cluster_handler_, OnProbeClusterConfig(_)).Times(0); - probe_controller_->SetEstimatedBitrate(1000, NowMs()); - testing::Mock::VerifyAndClearExpectations(&cluster_handler_); + EXPECT_CALL(pacer_, CreateProbeCluster(_)).Times(0); + probe_controller_->SetEstimatedBitrate(1000); + testing::Mock::VerifyAndClearExpectations(&pacer_); - EXPECT_CALL(cluster_handler_, OnProbeClusterConfig(DataRateEqBps(2 * 1800))); - probe_controller_->SetEstimatedBitrate(1800, NowMs()); + EXPECT_CALL(pacer_, CreateProbeCluster(2 * 1800)); + probe_controller_->SetEstimatedBitrate(1800); } TEST_F(ProbeControllerTest, TestExponentialProbingTimeout) { probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps, - kMaxBitrateBps, NowMs()); + kMaxBitrateBps); // Advance far enough to cause a time out in waiting for probing result. clock_.AdvanceTimeMilliseconds(kExponentialProbingTimeoutMs); - probe_controller_->Process(NowMs()); + probe_controller_->Process(); - EXPECT_CALL(cluster_handler_, OnProbeClusterConfig(_)).Times(0); - probe_controller_->SetEstimatedBitrate(1800, NowMs()); + EXPECT_CALL(pacer_, CreateProbeCluster(_)).Times(0); + probe_controller_->SetEstimatedBitrate(1800); } TEST_F(ProbeControllerTest, RequestProbeInAlr) { - EXPECT_CALL(cluster_handler_, OnProbeClusterConfig(_)).Times(2); + EXPECT_CALL(pacer_, CreateProbeCluster(_)).Times(2); probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps, - kMaxBitrateBps, NowMs()); - probe_controller_->SetEstimatedBitrate(500, NowMs()); - testing::Mock::VerifyAndClearExpectations(&cluster_handler_); - EXPECT_CALL(cluster_handler_, OnProbeClusterConfig(DataRateEqBps(0.85 * 500))) - .Times(1); - probe_controller_->SetAlrStartTimeMs(clock_.TimeInMilliseconds()); + kMaxBitrateBps); + probe_controller_->SetEstimatedBitrate(500); + testing::Mock::VerifyAndClearExpectations(&pacer_); + EXPECT_CALL(pacer_, CreateProbeCluster(0.85 * 500)).Times(1); + EXPECT_CALL(pacer_, GetApplicationLimitedRegionStartTime()) + .WillRepeatedly(Return(clock_.TimeInMilliseconds())); clock_.AdvanceTimeMilliseconds(kAlrProbeInterval + 1); - probe_controller_->Process(NowMs()); - probe_controller_->SetEstimatedBitrate(250, NowMs()); - probe_controller_->RequestProbe(NowMs()); + probe_controller_->Process(); + probe_controller_->SetEstimatedBitrate(250); + probe_controller_->RequestProbe(); } TEST_F(ProbeControllerTest, RequestProbeWhenAlrEndedRecently) { - EXPECT_CALL(cluster_handler_, OnProbeClusterConfig(_)).Times(2); + EXPECT_CALL(pacer_, CreateProbeCluster(_)).Times(2); probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps, - kMaxBitrateBps, NowMs()); - probe_controller_->SetEstimatedBitrate(500, NowMs()); - testing::Mock::VerifyAndClearExpectations(&cluster_handler_); - EXPECT_CALL(cluster_handler_, OnProbeClusterConfig(DataRateEqBps(0.85 * 500))) - .Times(1); - probe_controller_->SetAlrStartTimeMs(rtc::nullopt); + kMaxBitrateBps); + probe_controller_->SetEstimatedBitrate(500); + testing::Mock::VerifyAndClearExpectations(&pacer_); + EXPECT_CALL(pacer_, CreateProbeCluster(0.85 * 500)).Times(1); + EXPECT_CALL(pacer_, GetApplicationLimitedRegionStartTime()) + .WillRepeatedly(Return(rtc::nullopt)); clock_.AdvanceTimeMilliseconds(kAlrProbeInterval + 1); - probe_controller_->Process(NowMs()); - probe_controller_->SetEstimatedBitrate(250, NowMs()); + probe_controller_->Process(); + probe_controller_->SetEstimatedBitrate(250); probe_controller_->SetAlrEndedTimeMs(clock_.TimeInMilliseconds()); clock_.AdvanceTimeMilliseconds(kAlrEndedTimeoutMs - 1); - probe_controller_->RequestProbe(NowMs()); + probe_controller_->RequestProbe(); } TEST_F(ProbeControllerTest, RequestProbeWhenAlrNotEndedRecently) { - EXPECT_CALL(cluster_handler_, OnProbeClusterConfig(_)).Times(2); + EXPECT_CALL(pacer_, CreateProbeCluster(_)).Times(2); probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps, - kMaxBitrateBps, NowMs()); - probe_controller_->SetEstimatedBitrate(500, NowMs()); - testing::Mock::VerifyAndClearExpectations(&cluster_handler_); - EXPECT_CALL(cluster_handler_, OnProbeClusterConfig(_)).Times(0); - probe_controller_->SetAlrStartTimeMs(rtc::nullopt); + kMaxBitrateBps); + probe_controller_->SetEstimatedBitrate(500); + testing::Mock::VerifyAndClearExpectations(&pacer_); + EXPECT_CALL(pacer_, CreateProbeCluster(_)).Times(0); + EXPECT_CALL(pacer_, GetApplicationLimitedRegionStartTime()) + .WillRepeatedly(Return(rtc::nullopt)); clock_.AdvanceTimeMilliseconds(kAlrProbeInterval + 1); - probe_controller_->Process(NowMs()); - probe_controller_->SetEstimatedBitrate(250, NowMs()); + probe_controller_->Process(); + probe_controller_->SetEstimatedBitrate(250); probe_controller_->SetAlrEndedTimeMs(clock_.TimeInMilliseconds()); clock_.AdvanceTimeMilliseconds(kAlrEndedTimeoutMs + 1); - probe_controller_->RequestProbe(NowMs()); + probe_controller_->RequestProbe(); } TEST_F(ProbeControllerTest, RequestProbeWhenBweDropNotRecent) { - EXPECT_CALL(cluster_handler_, OnProbeClusterConfig(_)).Times(2); + EXPECT_CALL(pacer_, CreateProbeCluster(_)).Times(2); probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps, - kMaxBitrateBps, NowMs()); - probe_controller_->SetEstimatedBitrate(500, NowMs()); - testing::Mock::VerifyAndClearExpectations(&cluster_handler_); - EXPECT_CALL(cluster_handler_, OnProbeClusterConfig(_)).Times(0); - probe_controller_->SetAlrStartTimeMs(clock_.TimeInMilliseconds()); + kMaxBitrateBps); + probe_controller_->SetEstimatedBitrate(500); + testing::Mock::VerifyAndClearExpectations(&pacer_); + EXPECT_CALL(pacer_, CreateProbeCluster(_)).Times(0); + EXPECT_CALL(pacer_, GetApplicationLimitedRegionStartTime()) + .WillRepeatedly(Return(clock_.TimeInMilliseconds())); clock_.AdvanceTimeMilliseconds(kAlrProbeInterval + 1); - probe_controller_->Process(NowMs()); - probe_controller_->SetEstimatedBitrate(250, NowMs()); + probe_controller_->Process(); + probe_controller_->SetEstimatedBitrate(250); clock_.AdvanceTimeMilliseconds(kBitrateDropTimeoutMs + 1); - probe_controller_->RequestProbe(NowMs()); + probe_controller_->RequestProbe(); } TEST_F(ProbeControllerTest, PeriodicProbing) { - EXPECT_CALL(cluster_handler_, OnProbeClusterConfig(_)).Times(2); + EXPECT_CALL(pacer_, CreateProbeCluster(_)).Times(2); probe_controller_->EnablePeriodicAlrProbing(true); probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps, - kMaxBitrateBps, NowMs()); - probe_controller_->SetEstimatedBitrate(500, NowMs()); - testing::Mock::VerifyAndClearExpectations(&cluster_handler_); + kMaxBitrateBps); + probe_controller_->SetEstimatedBitrate(500); + testing::Mock::VerifyAndClearExpectations(&pacer_); int64_t start_time = clock_.TimeInMilliseconds(); // Expect the controller to send a new probe after 5s has passed. - EXPECT_CALL(cluster_handler_, OnProbeClusterConfig(DataRateEqBps(1000))) - .Times(1); - probe_controller_->SetAlrStartTimeMs(start_time); + EXPECT_CALL(pacer_, CreateProbeCluster(1000)).Times(1); + EXPECT_CALL(pacer_, GetApplicationLimitedRegionStartTime()) + .WillRepeatedly(Return(start_time)); clock_.AdvanceTimeMilliseconds(5000); - probe_controller_->Process(NowMs()); - probe_controller_->SetEstimatedBitrate(500, NowMs()); - testing::Mock::VerifyAndClearExpectations(&cluster_handler_); + probe_controller_->Process(); + probe_controller_->SetEstimatedBitrate(500); + testing::Mock::VerifyAndClearExpectations(&pacer_); // The following probe should be sent at 10s into ALR. - EXPECT_CALL(cluster_handler_, OnProbeClusterConfig(_)).Times(0); - probe_controller_->SetAlrStartTimeMs(start_time); + EXPECT_CALL(pacer_, CreateProbeCluster(_)).Times(0); + EXPECT_CALL(pacer_, GetApplicationLimitedRegionStartTime()) + .WillRepeatedly(Return(start_time)); clock_.AdvanceTimeMilliseconds(4000); - probe_controller_->Process(NowMs()); - probe_controller_->SetEstimatedBitrate(500, NowMs()); - testing::Mock::VerifyAndClearExpectations(&cluster_handler_); + probe_controller_->Process(); + probe_controller_->SetEstimatedBitrate(500); + testing::Mock::VerifyAndClearExpectations(&pacer_); - EXPECT_CALL(cluster_handler_, OnProbeClusterConfig(_)).Times(1); - probe_controller_->SetAlrStartTimeMs(start_time); + EXPECT_CALL(pacer_, CreateProbeCluster(_)).Times(1); + EXPECT_CALL(pacer_, GetApplicationLimitedRegionStartTime()) + .WillRepeatedly(Return(start_time)); clock_.AdvanceTimeMilliseconds(1000); - probe_controller_->Process(NowMs()); - probe_controller_->SetEstimatedBitrate(500, NowMs()); - testing::Mock::VerifyAndClearExpectations(&cluster_handler_); + probe_controller_->Process(); + probe_controller_->SetEstimatedBitrate(500); + testing::Mock::VerifyAndClearExpectations(&pacer_); } TEST_F(ProbeControllerTest, PeriodicProbingAfterReset) { - NiceMock local_handler; - probe_controller_.reset(new ProbeController(&local_handler)); + testing::StrictMock local_pacer; + probe_controller_.reset(new ProbeController(&local_pacer, &clock_)); int64_t alr_start_time = clock_.TimeInMilliseconds(); + EXPECT_CALL(local_pacer, GetApplicationLimitedRegionStartTime()) + .WillRepeatedly(Return(alr_start_time)); - probe_controller_->SetAlrStartTimeMs(alr_start_time); - EXPECT_CALL(local_handler, OnProbeClusterConfig(_)).Times(2); + EXPECT_CALL(local_pacer, CreateProbeCluster(_)).Times(2); probe_controller_->EnablePeriodicAlrProbing(true); probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps, - kMaxBitrateBps, NowMs()); - probe_controller_->Reset(NowMs()); + kMaxBitrateBps); + probe_controller_->Reset(); clock_.AdvanceTimeMilliseconds(10000); - probe_controller_->Process(NowMs()); + probe_controller_->Process(); - EXPECT_CALL(local_handler, OnProbeClusterConfig(_)).Times(2); + EXPECT_CALL(local_pacer, CreateProbeCluster(_)).Times(2); probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps, - kMaxBitrateBps, NowMs()); + kMaxBitrateBps); // Make sure we use |kStartBitrateBps| as the estimated bitrate // until SetEstimatedBitrate is called with an updated estimate. clock_.AdvanceTimeMilliseconds(10000); - EXPECT_CALL(local_handler, - OnProbeClusterConfig(DataRateEqBps(kStartBitrateBps * 2))); - probe_controller_->Process(NowMs()); + EXPECT_CALL(local_pacer, CreateProbeCluster(kStartBitrateBps*2)); + probe_controller_->Process(); } TEST_F(ProbeControllerTest, TestExponentialProbingOverflow) { const int64_t kMbpsMultiplier = 1000000; probe_controller_->SetBitrates(kMinBitrateBps, 10 * kMbpsMultiplier, - 100 * kMbpsMultiplier, NowMs()); + 100 * kMbpsMultiplier); - // Verify that probe bitrate is capped at the specified max bitrate. - EXPECT_CALL(cluster_handler_, - OnProbeClusterConfig(DataRateEqBps(100 * kMbpsMultiplier))); - probe_controller_->SetEstimatedBitrate(60 * kMbpsMultiplier, NowMs()); - testing::Mock::VerifyAndClearExpectations(&cluster_handler_); + // Verify that probe bitrate is capped at the specified max bitrate + EXPECT_CALL(pacer_, CreateProbeCluster(100 * kMbpsMultiplier)); + probe_controller_->SetEstimatedBitrate(60 * kMbpsMultiplier); + testing::Mock::VerifyAndClearExpectations(&pacer_); // Verify that repeated probes aren't sent. - EXPECT_CALL(cluster_handler_, OnProbeClusterConfig(_)).Times(0); - probe_controller_->SetEstimatedBitrate(100 * kMbpsMultiplier, NowMs()); + EXPECT_CALL(pacer_, CreateProbeCluster(_)).Times(0); + probe_controller_->SetEstimatedBitrate(100 * kMbpsMultiplier); } } // namespace test diff --git a/modules/congestion_controller/send_side_congestion_controller.cc b/modules/congestion_controller/send_side_congestion_controller.cc index fa81f247623..2a675786583 100644 --- a/modules/congestion_controller/send_side_congestion_controller.cc +++ b/modules/congestion_controller/send_side_congestion_controller.cc @@ -11,331 +11,142 @@ #include "modules/congestion_controller/include/send_side_congestion_controller.h" #include -#include +#include #include #include -#include "modules/congestion_controller/include/goog_cc_factory.h" -#include "modules/congestion_controller/network_control/include/network_types.h" -#include "modules/congestion_controller/network_control/include/network_units.h" + +#include "modules/bitrate_controller/include/bitrate_controller.h" +#include "modules/congestion_controller/acknowledged_bitrate_estimator.h" +#include "modules/congestion_controller/probe_controller.h" +#include "modules/pacing/alr_detector.h" #include "modules/remote_bitrate_estimator/include/bwe_defines.h" #include "rtc_base/checks.h" #include "rtc_base/format_macros.h" #include "rtc_base/logging.h" #include "rtc_base/numerics/safe_conversions.h" -#include "rtc_base/numerics/safe_minmax.h" #include "rtc_base/ptr_util.h" #include "rtc_base/rate_limiter.h" -#include "rtc_base/sequenced_task_checker.h" #include "rtc_base/socket.h" #include "rtc_base/timeutils.h" #include "system_wrappers/include/field_trial.h" #include "system_wrappers/include/runtime_enabled_features.h" -using rtc::MakeUnique; - namespace webrtc { namespace { -static const int64_t kRetransmitWindowSizeMs = 500; - +const char kCwndExperiment[] = "WebRTC-CwndExperiment"; const char kPacerPushbackExperiment[] = "WebRTC-PacerPushbackExperiment"; - -bool IsPacerPushbackExperimentEnabled() { - return webrtc::field_trial::IsEnabled(kPacerPushbackExperiment) || - (!webrtc::field_trial::IsDisabled(kPacerPushbackExperiment) && - webrtc::runtime_enabled_features::IsFeatureEnabled( - webrtc::runtime_enabled_features::kDualStreamModeFeatureName)); +const int64_t kDefaultAcceptedQueueMs = 250; + +bool CwndExperimentEnabled() { + std::string experiment_string = + webrtc::field_trial::FindFullName(kCwndExperiment); + // The experiment is enabled iff the field trial string begins with "Enabled". + return experiment_string.find("Enabled") == 0; +} + +bool ReadCwndExperimentParameter(int64_t* accepted_queue_ms) { + RTC_DCHECK(accepted_queue_ms); + std::string experiment_string = + webrtc::field_trial::FindFullName(kCwndExperiment); + int parsed_values = + sscanf(experiment_string.c_str(), "Enabled-%" PRId64, accepted_queue_ms); + if (parsed_values == 1) { + RTC_CHECK_GE(*accepted_queue_ms, 0) + << "Accepted must be greater than or equal to 0."; + return true; + } + return false; } -NetworkControllerFactoryInterface::uptr ControllerFactory( - RtcEventLog* event_log) { - return rtc::MakeUnique(event_log); -} +static const int64_t kRetransmitWindowSizeMs = 500; -void SortPacketFeedbackVector(std::vector* input) { +// Makes sure that the bitrate and the min, max values are in valid range. +static void ClampBitrates(int* bitrate_bps, + int* min_bitrate_bps, + int* max_bitrate_bps) { + // TODO(holmer): We should make sure the default bitrates are set to 10 kbps, + // and that we don't try to set the min bitrate to 0 from any applications. + // The congestion controller should allow a min bitrate of 0. + if (*min_bitrate_bps < congestion_controller::GetMinBitrateBps()) + *min_bitrate_bps = congestion_controller::GetMinBitrateBps(); + if (*max_bitrate_bps > 0) + *max_bitrate_bps = std::max(*min_bitrate_bps, *max_bitrate_bps); + if (*bitrate_bps > 0) + *bitrate_bps = std::max(*min_bitrate_bps, *bitrate_bps); +} + +std::vector ReceivedPacketFeedbackVector( + const std::vector& input) { + std::vector received_packet_feedback_vector; + auto is_received = [](const webrtc::PacketFeedback& packet_feedback) { + return packet_feedback.arrival_time_ms != + webrtc::PacketFeedback::kNotReceived; + }; + std::copy_if(input.begin(), input.end(), + std::back_inserter(received_packet_feedback_vector), + is_received); + return received_packet_feedback_vector; +} + +void SortPacketFeedbackVector( + std::vector* const input) { + RTC_DCHECK(input); std::sort(input->begin(), input->end(), PacketFeedbackComparator()); } -PacketResult NetworkPacketFeedbackFromRtpPacketFeedback( - const webrtc::PacketFeedback& pf) { - PacketResult feedback; - if (pf.arrival_time_ms == webrtc::PacketFeedback::kNotReceived) - feedback.receive_time = Timestamp::Infinity(); - else - feedback.receive_time = Timestamp::ms(pf.arrival_time_ms); - if (pf.send_time_ms != webrtc::PacketFeedback::kNoSendTime) { - feedback.sent_packet = SentPacket(); - feedback.sent_packet->send_time = Timestamp::ms(pf.send_time_ms); - feedback.sent_packet->size = DataSize::bytes(pf.payload_size); - feedback.sent_packet->pacing_info = pf.pacing_info; - } - return feedback; +bool IsPacerPushbackExperimentEnabled() { + return webrtc::field_trial::IsEnabled(kPacerPushbackExperiment) || ( + !webrtc::field_trial::IsDisabled(kPacerPushbackExperiment) && + webrtc::runtime_enabled_features::IsFeatureEnabled( + webrtc::runtime_enabled_features::kDualStreamModeFeatureName)); } -std::vector PacketResultsFromRtpFeedbackVector( - const std::vector& feedback_vector) { - RTC_DCHECK(std::is_sorted(feedback_vector.begin(), feedback_vector.end(), - PacketFeedbackComparator())); - - std::vector packet_feedbacks; - packet_feedbacks.reserve(feedback_vector.size()); - for (const PacketFeedback& rtp_feedback : feedback_vector) { - auto feedback = NetworkPacketFeedbackFromRtpPacketFeedback(rtp_feedback); - packet_feedbacks.push_back(feedback); - } - return packet_feedbacks; -} - -TargetRateConstraints ConvertConstraints(int min_bitrate_bps, - int max_bitrate_bps, - int start_bitrate_bps, - const Clock* clock) { - TargetRateConstraints msg; - msg.at_time = Timestamp::ms(clock->TimeInMilliseconds()); - msg.min_data_rate = - min_bitrate_bps >= 0 ? DataRate::bps(min_bitrate_bps) : DataRate::Zero(); - msg.starting_rate = start_bitrate_bps > 0 ? DataRate::bps(start_bitrate_bps) - : DataRate::kNotInitialized; - msg.max_data_rate = max_bitrate_bps > 0 ? DataRate::bps(max_bitrate_bps) - : DataRate::Infinity(); - return msg; -} } // namespace -namespace send_side_cc_internal { -class ControlHandler : public NetworkControllerObserver { - public: - ControlHandler(PacerController* pacer_controller, const Clock* clock); - - void OnCongestionWindow(CongestionWindow window) override; - void OnPacerConfig(PacerConfig config) override; - void OnProbeClusterConfig(ProbeClusterConfig config) override; - void OnTargetTransferRate(TargetTransferRate target_rate) override; - - void OnNetworkAvailability(NetworkAvailability msg); - void OnPacerQueueUpdate(PacerQueueUpdate msg); - - void RegisterNetworkObserver( - SendSideCongestionController::Observer* observer); - void DeRegisterNetworkObserver( - SendSideCongestionController::Observer* observer); - - rtc::Optional last_transfer_rate(); - bool pacer_configured(); - RateLimiter* retransmission_rate_limiter(); - - private: - void OnNetworkInvalidation(); - bool GetNetworkParameters(int32_t* estimated_bitrate_bps, - uint8_t* fraction_loss, - int64_t* rtt_ms); - bool IsSendQueueFull() const; - bool HasNetworkParametersToReportChanged(int64_t bitrate_bps, - uint8_t fraction_loss, - int64_t rtt); - PacerController* pacer_controller_; - RateLimiter retransmission_rate_limiter_; - - rtc::CriticalSection state_lock_; - rtc::Optional last_target_rate_ - RTC_GUARDED_BY(state_lock_); - bool pacer_configured_ RTC_GUARDED_BY(state_lock_) = false; - - SendSideCongestionController::Observer* observer_ = nullptr; - rtc::Optional current_target_rate_msg_; - bool network_available_ = true; - int64_t last_reported_target_bitrate_bps_ = 0; - uint8_t last_reported_fraction_loss_ = 0; - int64_t last_reported_rtt_ms_ = 0; - const bool pacer_pushback_experiment_ = false; - int64_t pacer_expected_queue_ms_ = 0; - float encoding_rate_ratio_ = 1.0; - - rtc::SequencedTaskChecker sequenced_checker_; - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(ControlHandler); -}; - -ControlHandler::ControlHandler(PacerController* pacer_controller, - const Clock* clock) - : pacer_controller_(pacer_controller), - retransmission_rate_limiter_(clock, kRetransmitWindowSizeMs), - pacer_pushback_experiment_(IsPacerPushbackExperimentEnabled()) { - sequenced_checker_.Detach(); -} - -void ControlHandler::OnCongestionWindow(CongestionWindow window) { - RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_); - pacer_controller_->OnCongestionWindow(window); -} - -void ControlHandler::OnPacerConfig(PacerConfig config) { - RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_); - pacer_controller_->OnPacerConfig(config); - rtc::CritScope cs(&state_lock_); - pacer_configured_ = true; -} - -void ControlHandler::OnProbeClusterConfig(ProbeClusterConfig config) { - RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_); - pacer_controller_->OnProbeClusterConfig(config); -} - -void ControlHandler::OnTargetTransferRate(TargetTransferRate target_rate) { - RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_); - retransmission_rate_limiter_.SetMaxRate( - target_rate.network_estimate.bandwidth.bps()); - - current_target_rate_msg_ = target_rate; - OnNetworkInvalidation(); - rtc::CritScope cs(&state_lock_); - last_target_rate_ = target_rate; -} - -void ControlHandler::OnNetworkAvailability(NetworkAvailability msg) { - RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_); - network_available_ = msg.network_available; - OnNetworkInvalidation(); -} - -void ControlHandler::OnPacerQueueUpdate(PacerQueueUpdate msg) { - RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_); - pacer_expected_queue_ms_ = msg.expected_queue_time.ms(); - OnNetworkInvalidation(); -} - -void ControlHandler::RegisterNetworkObserver( - SendSideCongestionController::Observer* observer) { - RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_); - RTC_DCHECK(observer_ == nullptr); - observer_ = observer; -} - -void ControlHandler::DeRegisterNetworkObserver( - SendSideCongestionController::Observer* observer) { - RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_); - RTC_DCHECK_EQ(observer_, observer); - observer_ = nullptr; -} - -void ControlHandler::OnNetworkInvalidation() { - if (!current_target_rate_msg_.has_value()) - return; - - uint32_t target_bitrate_bps = current_target_rate_msg_->target_rate.bps(); - int64_t rtt_ms = - current_target_rate_msg_->network_estimate.round_trip_time.ms(); - float loss_rate_ratio = - current_target_rate_msg_->network_estimate.loss_rate_ratio; - - int loss_ratio_255 = loss_rate_ratio * 255; - uint8_t fraction_loss = - rtc::dchecked_cast(rtc::SafeClamp(loss_ratio_255, 0, 255)); - - int64_t probing_interval_ms = - current_target_rate_msg_->network_estimate.bwe_period.ms(); - - if (!network_available_) { - target_bitrate_bps = 0; - } else if (!pacer_pushback_experiment_) { - target_bitrate_bps = IsSendQueueFull() ? 0 : target_bitrate_bps; - } else { - int64_t queue_length_ms = pacer_expected_queue_ms_; - - if (queue_length_ms == 0) { - encoding_rate_ratio_ = 1.0; - } else if (queue_length_ms > 50) { - float encoding_ratio = 1.0 - queue_length_ms / 1000.0; - encoding_rate_ratio_ = std::min(encoding_rate_ratio_, encoding_ratio); - encoding_rate_ratio_ = std::max(encoding_rate_ratio_, 0.0f); - } - - target_bitrate_bps *= encoding_rate_ratio_; - target_bitrate_bps = target_bitrate_bps < 50000 ? 0 : target_bitrate_bps; - } - if (HasNetworkParametersToReportChanged(target_bitrate_bps, fraction_loss, - rtt_ms)) { - if (observer_) { - observer_->OnNetworkChanged(target_bitrate_bps, fraction_loss, rtt_ms, - probing_interval_ms); - } - } -} -bool ControlHandler::HasNetworkParametersToReportChanged( - int64_t target_bitrate_bps, - uint8_t fraction_loss, - int64_t rtt_ms) { - bool changed = last_reported_target_bitrate_bps_ != target_bitrate_bps || - (target_bitrate_bps > 0 && - (last_reported_fraction_loss_ != fraction_loss || - last_reported_rtt_ms_ != rtt_ms)); - if (changed && - (last_reported_target_bitrate_bps_ == 0 || target_bitrate_bps == 0)) { - RTC_LOG(LS_INFO) << "Bitrate estimate state changed, BWE: " - << target_bitrate_bps << " bps."; - } - last_reported_target_bitrate_bps_ = target_bitrate_bps; - last_reported_fraction_loss_ = fraction_loss; - last_reported_rtt_ms_ = rtt_ms; - return changed; -} - -bool ControlHandler::IsSendQueueFull() const { - return pacer_expected_queue_ms_ > PacedSender::kMaxQueueLengthMs; -} - -rtc::Optional ControlHandler::last_transfer_rate() { - rtc::CritScope cs(&state_lock_); - return last_target_rate_; -} - -bool ControlHandler::pacer_configured() { - rtc::CritScope cs(&state_lock_); - return pacer_configured_; -} - -RateLimiter* ControlHandler::retransmission_rate_limiter() { - return &retransmission_rate_limiter_; -} -} // namespace send_side_cc_internal - SendSideCongestionController::SendSideCongestionController( const Clock* clock, Observer* observer, RtcEventLog* event_log, PacedSender* pacer) - : SendSideCongestionController(clock, - event_log, - pacer, - ControllerFactory(event_log)) { - if (observer != nullptr) - RegisterNetworkObserver(observer); -} - -SendSideCongestionController::SendSideCongestionController( - const Clock* clock, - RtcEventLog* event_log, - PacedSender* pacer, - NetworkControllerFactoryInterface::uptr controller_factory) : clock_(clock), + observer_(observer), + event_log_(event_log), pacer_(pacer), + bitrate_controller_( + BitrateController::CreateBitrateController(clock_, event_log)), + acknowledged_bitrate_estimator_( + rtc::MakeUnique()), + probe_controller_(new ProbeController(pacer_, clock_)), + retransmission_rate_limiter_( + new RateLimiter(clock, kRetransmitWindowSizeMs)), transport_feedback_adapter_(clock_), - pacer_controller_(MakeUnique(pacer_)), - control_handler(MakeUnique( - pacer_controller_.get(), - clock_)), - controller_(controller_factory->Create(control_handler.get())), - process_interval_(controller_factory->GetProcessInterval()), + last_reported_bitrate_bps_(0), + last_reported_fraction_loss_(0), + last_reported_rtt_(0), + network_state_(kNetworkUp), + pause_pacer_(false), + pacer_paused_(false), + min_bitrate_bps_(congestion_controller::GetMinBitrateBps()), + delay_based_bwe_(new DelayBasedBwe(event_log_, clock_)), + in_cwnd_experiment_(CwndExperimentEnabled()), + accepted_queue_ms_(kDefaultAcceptedQueueMs), + was_in_alr_(false), send_side_bwe_with_overhead_( webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")), transport_overhead_bytes_per_packet_(0), - network_available_(true), - task_queue_(MakeUnique("SendSideCCQueue")) {} - -SendSideCongestionController::~SendSideCongestionController() { - // Must be destructed before any objects used by calls on the task queue. - task_queue_.reset(); + pacer_pushback_experiment_(IsPacerPushbackExperimentEnabled()) { + delay_based_bwe_->SetMinBitrate(min_bitrate_bps_); + if (in_cwnd_experiment_ && + !ReadCwndExperimentParameter(&accepted_queue_ms_)) { + RTC_LOG(LS_WARNING) << "Failed to parse parameters for CwndExperiment " + "from field trial string. Experiment disabled."; + in_cwnd_experiment_ = false; + } } +SendSideCongestionController::~SendSideCongestionController() {} + void SendSideCongestionController::RegisterPacketFeedbackObserver( PacketFeedbackObserver* observer) { transport_feedback_adapter_.RegisterPacketFeedbackObserver(observer); @@ -347,84 +158,92 @@ void SendSideCongestionController::DeRegisterPacketFeedbackObserver( } void SendSideCongestionController::RegisterNetworkObserver(Observer* observer) { - WaitOnTask([this, observer]() { - control_handler->RegisterNetworkObserver(observer); - }); + rtc::CritScope cs(&observer_lock_); + RTC_DCHECK(observer_ == nullptr); + observer_ = observer; } void SendSideCongestionController::DeRegisterNetworkObserver( Observer* observer) { - WaitOnTask([this, observer]() { - control_handler->DeRegisterNetworkObserver(observer); - }); + rtc::CritScope cs(&observer_lock_); + RTC_DCHECK_EQ(observer_, observer); + observer_ = nullptr; } void SendSideCongestionController::SetBweBitrates(int min_bitrate_bps, int start_bitrate_bps, int max_bitrate_bps) { - TargetRateConstraints msg = ConvertConstraints( - min_bitrate_bps, max_bitrate_bps, start_bitrate_bps, clock_); - WaitOnTask([this, msg]() { controller_->OnTargetRateConstraints(msg); }); + ClampBitrates(&start_bitrate_bps, &min_bitrate_bps, &max_bitrate_bps); + bitrate_controller_->SetBitrates(start_bitrate_bps, min_bitrate_bps, + max_bitrate_bps); + + probe_controller_->SetBitrates(min_bitrate_bps, start_bitrate_bps, + max_bitrate_bps); + + { + rtc::CritScope cs(&bwe_lock_); + if (start_bitrate_bps > 0) + delay_based_bwe_->SetStartBitrate(start_bitrate_bps); + min_bitrate_bps_ = min_bitrate_bps; + delay_based_bwe_->SetMinBitrate(min_bitrate_bps_); + } + MaybeTriggerOnNetworkChanged(); } // TODO(holmer): Split this up and use SetBweBitrates in combination with // OnNetworkRouteChanged. void SendSideCongestionController::OnNetworkRouteChanged( const rtc::NetworkRoute& network_route, - int start_bitrate_bps, + int bitrate_bps, int min_bitrate_bps, int max_bitrate_bps) { + ClampBitrates(&bitrate_bps, &min_bitrate_bps, &max_bitrate_bps); + // TODO(honghaiz): Recreate this object once the bitrate controller is + // no longer exposed outside SendSideCongestionController. + bitrate_controller_->ResetBitrates(bitrate_bps, min_bitrate_bps, + max_bitrate_bps); + transport_feedback_adapter_.SetNetworkIds(network_route.local_network_id, network_route.remote_network_id); + { + rtc::CritScope cs(&bwe_lock_); + min_bitrate_bps_ = min_bitrate_bps; + delay_based_bwe_.reset(new DelayBasedBwe(event_log_, clock_)); + acknowledged_bitrate_estimator_.reset(new AcknowledgedBitrateEstimator()); + delay_based_bwe_->SetStartBitrate(bitrate_bps); + delay_based_bwe_->SetMinBitrate(min_bitrate_bps); + } + + probe_controller_->Reset(); + probe_controller_->SetBitrates(min_bitrate_bps, bitrate_bps, max_bitrate_bps); + + MaybeTriggerOnNetworkChanged(); +} - NetworkRouteChange msg; - msg.at_time = Timestamp::ms(clock_->TimeInMilliseconds()); - msg.constraints = ConvertConstraints(min_bitrate_bps, max_bitrate_bps, - start_bitrate_bps, clock_); - WaitOnTask([this, msg]() { - controller_->OnNetworkRouteChange(msg); - pacer_controller_->OnNetworkRouteChange(msg); - }); +BitrateController* SendSideCongestionController::GetBitrateController() const { + return bitrate_controller_.get(); } bool SendSideCongestionController::AvailableBandwidth( uint32_t* bandwidth) const { - // TODO(srte): Remove this interface and push information about bandwidth - // estimation to users of this class, thereby reducing synchronous calls. - if (control_handler->last_transfer_rate().has_value()) { - *bandwidth = - control_handler->last_transfer_rate()->network_estimate.bandwidth.bps(); - return true; - } - return false; + return bitrate_controller_->AvailableBandwidth(bandwidth); } -RtcpBandwidthObserver* SendSideCongestionController::GetBandwidthObserver() { - return this; +RtcpBandwidthObserver* SendSideCongestionController::GetBandwidthObserver() + const { + return bitrate_controller_.get(); } RateLimiter* SendSideCongestionController::GetRetransmissionRateLimiter() { - return control_handler->retransmission_rate_limiter(); + return retransmission_rate_limiter_.get(); } void SendSideCongestionController::EnablePeriodicAlrProbing(bool enable) { - WaitOnTask([this, enable]() { - streams_config_.requests_alr_probing = enable; - UpdateStreamsConfig(); - }); -} - -void SendSideCongestionController::UpdateStreamsConfig() { - RTC_DCHECK(task_queue_->IsCurrent()); - streams_config_.at_time = Timestamp::ms(clock_->TimeInMilliseconds()); - controller_->OnStreamsConfig(streams_config_); + probe_controller_->EnablePeriodicAlrProbing(enable); } int64_t SendSideCongestionController::GetPacerQueuingDelayMs() const { - // TODO(srte): This should be made less synchronous. Now it grabs a lock in - // the pacer just for stats usage. Some kind of push interface might make - // sense. - return network_available_ ? pacer_->QueueInMs() : 0; + return IsNetworkDown() ? 0 : pacer_->QueueInMs(); } int64_t SendSideCongestionController::GetFirstPacketTimeMs() const { @@ -439,19 +258,18 @@ SendSideCongestionController::GetTransportFeedbackObserver() { void SendSideCongestionController::SignalNetworkState(NetworkState state) { RTC_LOG(LS_INFO) << "SignalNetworkState " << (state == kNetworkUp ? "Up" : "Down"); - NetworkAvailability msg; - msg.at_time = Timestamp::ms(clock_->TimeInMilliseconds()); - msg.network_available = state == kNetworkUp; - network_available_ = msg.network_available; - WaitOnTask([this, msg]() { - controller_->OnNetworkAvailability(msg); - pacer_controller_->OnNetworkAvailability(msg); - control_handler->OnNetworkAvailability(msg); - }); + { + rtc::CritScope cs(&network_state_lock_); + pause_pacer_ = state == kNetworkDown; + network_state_ = state; + } + probe_controller_->OnNetworkStateChanged(state); + MaybeTriggerOnNetworkChanged(); } void SendSideCongestionController::SetTransportOverhead( size_t transport_overhead_bytes_per_packet) { + rtc::CritScope cs(&bwe_lock_); transport_overhead_bytes_per_packet_ = transport_overhead_bytes_per_packet; } @@ -463,52 +281,38 @@ void SendSideCongestionController::OnSentPacket( return; transport_feedback_adapter_.OnSentPacket(sent_packet.packet_id, sent_packet.send_time_ms); - MaybeUpdateOutstandingData(); - auto packet = transport_feedback_adapter_.GetPacket(sent_packet.packet_id); - if (packet.has_value()) { - SentPacket msg; - msg.size = DataSize::bytes(packet->payload_size); - msg.send_time = Timestamp::ms(packet->send_time_ms); - task_queue_->PostTask([this, msg]() { controller_->OnSentPacket(msg); }); - } + if (in_cwnd_experiment_) + LimitOutstandingBytes(transport_feedback_adapter_.GetOutstandingBytes()); } void SendSideCongestionController::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) { - int64_t now_ms = clock_->TimeInMilliseconds(); - RoundTripTimeUpdate report; - report.receive_time = Timestamp::ms(now_ms); - report.round_trip_time = TimeDelta::ms(avg_rtt_ms); - report.smoothed = true; - task_queue_->PostTask( - [this, report]() { controller_->OnRoundTripTimeUpdate(report); }); + rtc::CritScope cs(&bwe_lock_); + delay_based_bwe_->OnRttUpdate(avg_rtt_ms, max_rtt_ms); } int64_t SendSideCongestionController::TimeUntilNextProcess() { - const int kMaxProcessInterval = 60 * 1000; - if (process_interval_.IsInfinite()) - return kMaxProcessInterval; - int64_t next_process_ms = last_process_update_ms_ + process_interval_.ms(); - int64_t time_until_next_process = - next_process_ms - clock_->TimeInMilliseconds(); - return std::max(time_until_next_process, 0); + return bitrate_controller_->TimeUntilNextProcess(); } void SendSideCongestionController::Process() { - int64_t now_ms = clock_->TimeInMilliseconds(); - last_process_update_ms_ = now_ms; + bool pause_pacer; + // TODO(holmer): Once this class is running on a task queue we should + // replace this with a task instead. { - ProcessInterval msg; - msg.at_time = Timestamp::ms(now_ms); - task_queue_->PostTask( - [this, msg]() { controller_->OnProcessInterval(msg); }); + rtc::CritScope lock(&network_state_lock_); + pause_pacer = pause_pacer_; } - if (control_handler->pacer_configured()) { - PacerQueueUpdate msg; - msg.expected_queue_time = TimeDelta::ms(pacer_->ExpectedQueueTimeMs()); - task_queue_->PostTask( - [this, msg]() { control_handler->OnPacerQueueUpdate(msg); }); + if (pause_pacer && !pacer_paused_) { + pacer_->Pause(); + pacer_paused_ = true; + } else if (!pause_pacer && pacer_paused_) { + pacer_->Resume(); + pacer_paused_ = false; } + bitrate_controller_->Process(); + probe_controller_->Process(); + MaybeTriggerOnNetworkChanged(); } void SendSideCongestionController::AddPacket( @@ -517,6 +321,7 @@ void SendSideCongestionController::AddPacket( size_t length, const PacedPacketInfo& pacing_info) { if (send_side_bwe_with_overhead_) { + rtc::CritScope cs(&bwe_lock_); length += transport_overhead_bytes_per_packet_; } transport_feedback_adapter_.AddPacket(ssrc, sequence_number, length, @@ -526,35 +331,61 @@ void SendSideCongestionController::AddPacket( void SendSideCongestionController::OnTransportFeedback( const rtcp::TransportFeedback& feedback) { RTC_DCHECK_RUNS_SERIALIZED(&worker_race_); - int64_t feedback_time_ms = clock_->TimeInMilliseconds(); - - DataSize prior_in_flight = - DataSize::bytes(transport_feedback_adapter_.GetOutstandingBytes()); transport_feedback_adapter_.OnTransportFeedback(feedback); - MaybeUpdateOutstandingData(); - - std::vector feedback_vector = - transport_feedback_adapter_.GetTransportFeedbackVector(); + std::vector feedback_vector = ReceivedPacketFeedbackVector( + transport_feedback_adapter_.GetTransportFeedbackVector()); SortPacketFeedbackVector(&feedback_vector); - if (!feedback_vector.empty()) { - TransportPacketsFeedback msg; - msg.packet_feedbacks = PacketResultsFromRtpFeedbackVector(feedback_vector); - msg.feedback_time = Timestamp::ms(feedback_time_ms); - msg.prior_in_flight = prior_in_flight; - msg.data_in_flight = - DataSize::bytes(transport_feedback_adapter_.GetOutstandingBytes()); - task_queue_->PostTask( - [this, msg]() { controller_->OnTransportPacketsFeedback(msg); }); + bool currently_in_alr = + pacer_->GetApplicationLimitedRegionStartTime().has_value(); + if (was_in_alr_ && !currently_in_alr) { + int64_t now_ms = rtc::TimeMillis(); + acknowledged_bitrate_estimator_->SetAlrEndedTimeMs(now_ms); + probe_controller_->SetAlrEndedTimeMs(now_ms); } -} + was_in_alr_ = currently_in_alr; -void SendSideCongestionController::MaybeUpdateOutstandingData() { - OutstandingData msg; - msg.in_flight_data = - DataSize::bytes(transport_feedback_adapter_.GetOutstandingBytes()); - task_queue_->PostTask( - [this, msg]() { pacer_controller_->OnOutstandingData(msg); }); + acknowledged_bitrate_estimator_->IncomingPacketFeedbackVector( + feedback_vector); + DelayBasedBwe::Result result; + { + rtc::CritScope cs(&bwe_lock_); + result = delay_based_bwe_->IncomingPacketFeedbackVector( + feedback_vector, acknowledged_bitrate_estimator_->bitrate_bps()); + } + if (result.updated) { + bitrate_controller_->OnDelayBasedBweResult(result); + // Update the estimate in the ProbeController, in case we want to probe. + MaybeTriggerOnNetworkChanged(); + } + if (result.recovered_from_overuse) + probe_controller_->RequestProbe(); + if (in_cwnd_experiment_) + LimitOutstandingBytes(transport_feedback_adapter_.GetOutstandingBytes()); +} + +void SendSideCongestionController::LimitOutstandingBytes( + size_t num_outstanding_bytes) { + RTC_DCHECK(in_cwnd_experiment_); + rtc::CritScope lock(&network_state_lock_); + rtc::Optional min_rtt_ms = + transport_feedback_adapter_.GetMinFeedbackLoopRtt(); + // 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_rtt_ms) + return; + const size_t kMinCwndBytes = 2 * 1500; + size_t max_outstanding_bytes = + std::max((*min_rtt_ms + accepted_queue_ms_) * + last_reported_bitrate_bps_ / 1000 / 8, + kMinCwndBytes); + RTC_LOG(LS_INFO) << clock_->TimeInMilliseconds() + << " Outstanding bytes: " << num_outstanding_bytes + << " pacer queue: " << pacer_->QueueInMs() + << " max outstanding: " << max_outstanding_bytes; + RTC_LOG(LS_INFO) << "Feedback rtt: " << *min_rtt_ms + << " Bitrate: " << last_reported_bitrate_bps_; + pause_pacer_ = num_outstanding_bytes > max_outstanding_bytes; } std::vector @@ -563,99 +394,81 @@ SendSideCongestionController::GetTransportFeedbackVector() const { return transport_feedback_adapter_.GetTransportFeedbackVector(); } -void SendSideCongestionController::WaitOnTasks() { - rtc::Event event(false, false); - task_queue_->PostTask([&event]() { event.Set(); }); - event.Wait(rtc::Event::kForever); -} +void SendSideCongestionController::MaybeTriggerOnNetworkChanged() { + uint32_t bitrate_bps; + uint8_t fraction_loss; + int64_t rtt; + bool estimate_changed = bitrate_controller_->GetNetworkParameters( + &bitrate_bps, &fraction_loss, &rtt); + if (estimate_changed) { + pacer_->SetEstimatedBitrate(bitrate_bps); + probe_controller_->SetEstimatedBitrate(bitrate_bps); + retransmission_rate_limiter_->SetMaxRate(bitrate_bps); + } -void SendSideCongestionController::WaitOnTask(std::function closure) { - rtc::Event done(false, false); - task_queue_->PostTask(rtc::NewClosure(closure, [&done] { done.Set(); })); - done.Wait(rtc::Event::kForever); -} + if (!pacer_pushback_experiment_) { + bitrate_bps = IsNetworkDown() || IsSendQueueFull() ? 0 : bitrate_bps; + } else { + if (IsNetworkDown()) { + bitrate_bps = 0; + } else { + int64_t queue_length_ms = pacer_->ExpectedQueueTimeMs(); + + if (queue_length_ms == 0) { + encoding_rate_ = 1.0; + } else if (queue_length_ms > 50) { + float encoding_rate = 1.0 - queue_length_ms / 1000.0; + encoding_rate_ = std::min(encoding_rate_, encoding_rate); + encoding_rate_ = std::max(encoding_rate_, 0.0f); + } + + bitrate_bps *= encoding_rate_; + bitrate_bps = bitrate_bps < 50000 ? 0 : bitrate_bps; + } + } -void SendSideCongestionController::SetSendBitrateLimits( - int64_t min_send_bitrate_bps, - int64_t max_padding_bitrate_bps) { - WaitOnTask([this, min_send_bitrate_bps, max_padding_bitrate_bps]() { - streams_config_.min_pacing_rate = DataRate::bps(min_send_bitrate_bps); - streams_config_.max_padding_rate = DataRate::bps(max_padding_bitrate_bps); - UpdateStreamsConfig(); - }); + if (HasNetworkParametersToReportChanged(bitrate_bps, fraction_loss, rtt)) { + int64_t probing_interval_ms; + { + rtc::CritScope cs(&bwe_lock_); + probing_interval_ms = delay_based_bwe_->GetExpectedBwePeriodMs(); + } + { + rtc::CritScope cs(&observer_lock_); + if (observer_) { + observer_->OnNetworkChanged(bitrate_bps, fraction_loss, rtt, + probing_interval_ms); + } + } + } } -void SendSideCongestionController::SetPacingFactor(float pacing_factor) { - WaitOnTask([this, pacing_factor]() { - streams_config_.pacing_factor = pacing_factor; - UpdateStreamsConfig(); - }); +bool SendSideCongestionController::HasNetworkParametersToReportChanged( + uint32_t bitrate_bps, + uint8_t fraction_loss, + int64_t rtt) { + rtc::CritScope cs(&network_state_lock_); + bool changed = + last_reported_bitrate_bps_ != bitrate_bps || + (bitrate_bps > 0 && (last_reported_fraction_loss_ != fraction_loss || + last_reported_rtt_ != rtt)); + if (changed && (last_reported_bitrate_bps_ == 0 || bitrate_bps == 0)) { + RTC_LOG(LS_INFO) << "Bitrate estimate state changed, BWE: " << bitrate_bps + << " bps."; + } + last_reported_bitrate_bps_ = bitrate_bps; + last_reported_fraction_loss_ = fraction_loss; + last_reported_rtt_ = rtt; + return changed; } -void SendSideCongestionController::OnReceivedEstimatedBitrate( - uint32_t bitrate) { - RemoteBitrateReport msg; - msg.receive_time = Timestamp::ms(clock_->TimeInMilliseconds()); - msg.bandwidth = DataRate::bps(bitrate); - task_queue_->PostTask( - [this, msg]() { controller_->OnRemoteBitrateReport(msg); }); +bool SendSideCongestionController::IsSendQueueFull() const { + return pacer_->ExpectedQueueTimeMs() > PacedSender::kMaxQueueLengthMs; } -void SendSideCongestionController::OnReceivedRtcpReceiverReport( - const webrtc::ReportBlockList& report_blocks, - int64_t rtt_ms, - int64_t now_ms) { - OnReceivedRtcpReceiverReportBlocks(report_blocks, now_ms); - - RoundTripTimeUpdate report; - report.receive_time = Timestamp::ms(now_ms); - report.round_trip_time = TimeDelta::ms(rtt_ms); - report.smoothed = false; - task_queue_->PostTask( - [this, report]() { controller_->OnRoundTripTimeUpdate(report); }); +bool SendSideCongestionController::IsNetworkDown() const { + rtc::CritScope cs(&network_state_lock_); + return network_state_ == kNetworkDown; } -void SendSideCongestionController::OnReceivedRtcpReceiverReportBlocks( - const ReportBlockList& report_blocks, - int64_t now_ms) { - if (report_blocks.empty()) - return; - - int total_packets_lost_delta = 0; - int total_packets_delta = 0; - - // Compute the packet loss from all report blocks. - for (const RTCPReportBlock& report_block : report_blocks) { - auto it = last_report_blocks_.find(report_block.source_ssrc); - if (it != last_report_blocks_.end()) { - auto number_of_packets = report_block.extended_highest_sequence_number - - it->second.extended_highest_sequence_number; - total_packets_delta += number_of_packets; - auto lost_delta = report_block.packets_lost - it->second.packets_lost; - total_packets_lost_delta += lost_delta; - } - last_report_blocks_[report_block.source_ssrc] = report_block; - } - // Can only compute delta if there has been previous blocks to compare to. If - // not, total_packets_delta will be unchanged and there's nothing more to do. - if (!total_packets_delta) - return; - int packets_received_delta = total_packets_delta - total_packets_lost_delta; - // To detect lost packets, at least one packet has to be received. This check - // is needed to avoid bandwith detection update in - // VideoSendStreamTest.SuspendBelowMinBitrate - - if (packets_received_delta < 1) - return; - Timestamp now = Timestamp::ms(now_ms); - TransportLossReport msg; - msg.packets_lost_delta = total_packets_lost_delta; - msg.packets_received_delta = packets_received_delta; - msg.receive_time = now; - msg.start_time = last_report_block_time_; - msg.end_time = now; - task_queue_->PostTask( - [this, msg]() { controller_->OnTransportLossReport(msg); }); - last_report_block_time_ = now; -} } // namespace webrtc diff --git a/modules/congestion_controller/send_side_congestion_controller_unittest.cc b/modules/congestion_controller/send_side_congestion_controller_unittest.cc index 809526ff2f3..67d2c402c4f 100644 --- a/modules/congestion_controller/send_side_congestion_controller_unittest.cc +++ b/modules/congestion_controller/send_side_congestion_controller_unittest.cc @@ -8,10 +8,11 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "modules/congestion_controller/include/send_side_congestion_controller.h" #include "logging/rtc_event_log/mock/mock_rtc_event_log.h" +#include "modules/bitrate_controller/include/bitrate_controller.h" #include "modules/congestion_controller/congestion_controller_unittests_helper.h" #include "modules/congestion_controller/include/mock/mock_congestion_observer.h" +#include "modules/congestion_controller/include/send_side_congestion_controller.h" #include "modules/pacing/mock/mock_paced_sender.h" #include "modules/pacing/packet_router.h" #include "modules/remote_bitrate_estimator/include/bwe_defines.h" @@ -32,31 +33,16 @@ using testing::SaveArg; using testing::StrictMock; namespace webrtc { -namespace test { namespace { const webrtc::PacedPacketInfo kPacingInfo0(0, 5, 2000); const webrtc::PacedPacketInfo kPacingInfo1(1, 8, 4000); const uint32_t kInitialBitrateBps = 60000; -const float kDefaultPacingRate = 2.5f; - -class SendSideCongestionControllerForTest - : public SendSideCongestionController { - public: - SendSideCongestionControllerForTest(const Clock* clock, - Observer* observer, - RtcEventLog* event_log, - PacedSender* pacer) - : SendSideCongestionController(clock, observer, event_log, pacer) {} - ~SendSideCongestionControllerForTest() {} - void Process() override { - SendSideCongestionController::Process(); - SendSideCongestionController::WaitOnTasks(); - } -}; + } // namespace +namespace test { class SendSideCongestionControllerTest : public ::testing::Test { protected: @@ -66,15 +52,14 @@ class SendSideCongestionControllerTest : public ::testing::Test { void SetUp() override { pacer_.reset(new NiceMock()); - controller_.reset(new SendSideCongestionControllerForTest( + controller_.reset(new SendSideCongestionController( &clock_, &observer_, &event_log_, pacer_.get())); bandwidth_observer_ = controller_->GetBandwidthObserver(); // Set the initial bitrate estimate and expect the |observer| and |pacer_| // to be updated. EXPECT_CALL(observer_, OnNetworkChanged(kInitialBitrateBps, _, _, _)); - EXPECT_CALL(*pacer_, - SetPacingRates(kInitialBitrateBps * kDefaultPacingRate, _)); + EXPECT_CALL(*pacer_, SetEstimatedBitrate(kInitialBitrateBps)); EXPECT_CALL(*pacer_, CreateProbeCluster(kInitialBitrateBps * 3)); EXPECT_CALL(*pacer_, CreateProbeCluster(kInitialBitrateBps * 5)); controller_->SetBweBitrates(0, kInitialBitrateBps, 5 * kInitialBitrateBps); @@ -83,9 +68,8 @@ class SendSideCongestionControllerTest : public ::testing::Test { // Custom setup - use an observer that tracks the target bitrate, without // prescribing on which iterations it must change (like a mock would). void TargetBitrateTrackingSetup() { - bandwidth_observer_ = nullptr; pacer_.reset(new NiceMock()); - controller_.reset(new SendSideCongestionControllerForTest( + controller_.reset(new SendSideCongestionController( &clock_, &target_bitrate_observer_, &event_log_, pacer_.get())); controller_->SetBweBitrates(0, kInitialBitrateBps, 5 * kInitialBitrateBps); } @@ -153,7 +137,7 @@ class SendSideCongestionControllerTest : public ::testing::Test { RtcpBandwidthObserver* bandwidth_observer_; PacketRouter packet_router_; std::unique_ptr> pacer_; - std::unique_ptr controller_; + std::unique_ptr controller_; rtc::Optional target_bitrate_bps_; }; @@ -164,15 +148,13 @@ TEST_F(SendSideCongestionControllerTest, OnNetworkChanged) { controller_->Process(); EXPECT_CALL(observer_, OnNetworkChanged(kInitialBitrateBps * 2, _, _, _)); - EXPECT_CALL(*pacer_, - SetPacingRates(kInitialBitrateBps * 2 * kDefaultPacingRate, _)); + EXPECT_CALL(*pacer_, SetEstimatedBitrate(kInitialBitrateBps * 2)); bandwidth_observer_->OnReceivedEstimatedBitrate(kInitialBitrateBps * 2); clock_.AdvanceTimeMilliseconds(25); controller_->Process(); EXPECT_CALL(observer_, OnNetworkChanged(kInitialBitrateBps, _, _, _)); - EXPECT_CALL(*pacer_, - SetPacingRates(kInitialBitrateBps * kDefaultPacingRate, _)); + EXPECT_CALL(*pacer_, SetEstimatedBitrate(kInitialBitrateBps)); bandwidth_observer_->OnReceivedEstimatedBitrate(kInitialBitrateBps); clock_.AdvanceTimeMilliseconds(25); controller_->Process(); @@ -180,14 +162,14 @@ TEST_F(SendSideCongestionControllerTest, OnNetworkChanged) { TEST_F(SendSideCongestionControllerTest, OnSendQueueFull) { EXPECT_CALL(*pacer_, ExpectedQueueTimeMs()) - .WillRepeatedly(Return(PacedSender::kMaxQueueLengthMs + 1)); + .WillOnce(Return(PacedSender::kMaxQueueLengthMs + 1)); EXPECT_CALL(observer_, OnNetworkChanged(0, _, _, _)); controller_->Process(); // Let the pacer not be full next time the controller checks. EXPECT_CALL(*pacer_, ExpectedQueueTimeMs()) - .WillRepeatedly(Return(PacedSender::kMaxQueueLengthMs - 1)); + .WillOnce(Return(PacedSender::kMaxQueueLengthMs - 1)); EXPECT_CALL(observer_, OnNetworkChanged(kInitialBitrateBps, _, _, _)); controller_->Process(); @@ -195,24 +177,23 @@ TEST_F(SendSideCongestionControllerTest, OnSendQueueFull) { TEST_F(SendSideCongestionControllerTest, OnSendQueueFullAndEstimateChange) { EXPECT_CALL(*pacer_, ExpectedQueueTimeMs()) - .WillRepeatedly(Return(PacedSender::kMaxQueueLengthMs + 1)); + .WillOnce(Return(PacedSender::kMaxQueueLengthMs + 1)); EXPECT_CALL(observer_, OnNetworkChanged(0, _, _, _)); controller_->Process(); // Receive new estimate but let the queue still be full. bandwidth_observer_->OnReceivedEstimatedBitrate(kInitialBitrateBps * 2); EXPECT_CALL(*pacer_, ExpectedQueueTimeMs()) - .WillRepeatedly(Return(PacedSender::kMaxQueueLengthMs + 1)); + .WillOnce(Return(PacedSender::kMaxQueueLengthMs + 1)); // The send pacer should get the new estimate though. - EXPECT_CALL(*pacer_, - SetPacingRates(kInitialBitrateBps * 2 * kDefaultPacingRate, _)); + EXPECT_CALL(*pacer_, SetEstimatedBitrate(kInitialBitrateBps * 2)); clock_.AdvanceTimeMilliseconds(25); controller_->Process(); // Let the pacer not be full next time the controller checks. // |OnNetworkChanged| should be called with the new estimate. EXPECT_CALL(*pacer_, ExpectedQueueTimeMs()) - .WillRepeatedly(Return(PacedSender::kMaxQueueLengthMs - 1)); + .WillOnce(Return(PacedSender::kMaxQueueLengthMs - 1)); EXPECT_CALL(observer_, OnNetworkChanged(kInitialBitrateBps * 2, _, _, _)); clock_.AdvanceTimeMilliseconds(25); controller_->Process(); @@ -233,7 +214,7 @@ TEST_F(SendSideCongestionControllerTest, OnNetworkRouteChanged) { int new_bitrate = 200000; testing::Mock::VerifyAndClearExpectations(pacer_.get()); EXPECT_CALL(observer_, OnNetworkChanged(new_bitrate, _, _, _)); - EXPECT_CALL(*pacer_, SetPacingRates(new_bitrate * kDefaultPacingRate, _)); + EXPECT_CALL(*pacer_, SetEstimatedBitrate(new_bitrate)); rtc::NetworkRoute route; route.local_network_id = 1; controller_->OnNetworkRouteChanged(route, new_bitrate, -1, -1); @@ -243,10 +224,8 @@ TEST_F(SendSideCongestionControllerTest, OnNetworkRouteChanged) { EXPECT_CALL( observer_, OnNetworkChanged(congestion_controller::GetMinBitrateBps(), _, _, _)); - EXPECT_CALL( - *pacer_, - SetPacingRates( - congestion_controller::GetMinBitrateBps() * kDefaultPacingRate, _)); + EXPECT_CALL(*pacer_, + SetEstimatedBitrate(congestion_controller::GetMinBitrateBps())); route.local_network_id = 2; controller_->OnNetworkRouteChanged(route, -1, -1, -1); } @@ -255,7 +234,7 @@ TEST_F(SendSideCongestionControllerTest, OldFeedback) { int new_bitrate = 200000; testing::Mock::VerifyAndClearExpectations(pacer_.get()); EXPECT_CALL(observer_, OnNetworkChanged(new_bitrate, _, _, _)); - EXPECT_CALL(*pacer_, SetPacingRates(new_bitrate * kDefaultPacingRate, _)); + EXPECT_CALL(*pacer_, SetEstimatedBitrate(new_bitrate)); // Send a few packets on the first network route. std::vector packets; @@ -288,17 +267,15 @@ TEST_F(SendSideCongestionControllerTest, OldFeedback) { EXPECT_CALL( observer_, OnNetworkChanged(congestion_controller::GetMinBitrateBps(), _, _, _)); - EXPECT_CALL( - *pacer_, - SetPacingRates( - congestion_controller::GetMinBitrateBps() * kDefaultPacingRate, _)); + EXPECT_CALL(*pacer_, + SetEstimatedBitrate(congestion_controller::GetMinBitrateBps())); route.local_network_id = 2; controller_->OnNetworkRouteChanged(route, -1, -1, -1); } TEST_F(SendSideCongestionControllerTest, SignalNetworkStateAndQueueIsFullAndEstimateChange) { - // Send queue is full. + // Send queue is full EXPECT_CALL(*pacer_, ExpectedQueueTimeMs()) .WillRepeatedly(Return(PacedSender::kMaxQueueLengthMs + 1)); EXPECT_CALL(observer_, OnNetworkChanged(0, _, _, _)); @@ -313,15 +290,14 @@ TEST_F(SendSideCongestionControllerTest, controller_->Process(); // Receive new estimate but let the queue still be full. - EXPECT_CALL(*pacer_, - SetPacingRates(kInitialBitrateBps * 2 * kDefaultPacingRate, _)); + EXPECT_CALL(*pacer_, SetEstimatedBitrate(kInitialBitrateBps * 2)); bandwidth_observer_->OnReceivedEstimatedBitrate(kInitialBitrateBps * 2); clock_.AdvanceTimeMilliseconds(25); controller_->Process(); // Let the pacer not be full next time the controller checks. EXPECT_CALL(*pacer_, ExpectedQueueTimeMs()) - .WillRepeatedly(Return(PacedSender::kMaxQueueLengthMs - 1)); + .WillOnce(Return(PacedSender::kMaxQueueLengthMs - 1)); EXPECT_CALL(observer_, OnNetworkChanged(kInitialBitrateBps * 2, _, _, _)); controller_->Process(); } @@ -347,7 +323,7 @@ TEST_F(SendSideCongestionControllerTest, GetProbingInterval) { controller_->Process(); EXPECT_CALL(observer_, OnNetworkChanged(_, _, _, testing::Ne(0))); - EXPECT_CALL(*pacer_, SetPacingRates(_, _)); + EXPECT_CALL(*pacer_, SetEstimatedBitrate(_)); bandwidth_observer_->OnReceivedEstimatedBitrate(kInitialBitrateBps * 2); clock_.AdvanceTimeMilliseconds(25); controller_->Process(); diff --git a/modules/congestion_controller/send_time_history.cc b/modules/congestion_controller/send_time_history.cc index 45d81c8434d..e5bc4162861 100644 --- a/modules/congestion_controller/send_time_history.cc +++ b/modules/congestion_controller/send_time_history.cc @@ -50,17 +50,6 @@ bool SendTimeHistory::OnSentPacket(uint16_t sequence_number, return true; } -rtc::Optional SendTimeHistory::GetPacket( - uint16_t sequence_number) const { - int64_t unwrapped_seq_num = - seq_num_unwrapper_.UnwrapWithoutUpdate(sequence_number); - rtc::Optional optional_feedback; - auto it = history_.find(unwrapped_seq_num); - if (it != history_.end()) - optional_feedback.emplace(it->second); - return optional_feedback; -} - bool SendTimeHistory::GetFeedback(PacketFeedback* packet_feedback, bool remove) { RTC_DCHECK(packet_feedback); diff --git a/modules/congestion_controller/send_time_history.h b/modules/congestion_controller/send_time_history.h index 649ef6a6d25..366fec9d2cd 100644 --- a/modules/congestion_controller/send_time_history.h +++ b/modules/congestion_controller/send_time_history.h @@ -33,9 +33,6 @@ class SendTimeHistory { // Return false if not found. bool OnSentPacket(uint16_t sequence_number, int64_t send_time_ms); - // Retrieves packet info identified by |sequence_number|. - rtc::Optional GetPacket(uint16_t sequence_number) const; - // Look up PacketFeedback for a sent packet, based on the sequence number, and // populate all fields except for arrival_time. The packet parameter must // thus be non-null and have the sequence_number field set. diff --git a/modules/congestion_controller/send_time_history_unittest.cc b/modules/congestion_controller/send_time_history_unittest.cc index 15907cc51fb..64f30c0375a 100644 --- a/modules/congestion_controller/send_time_history_unittest.cc +++ b/modules/congestion_controller/send_time_history_unittest.cc @@ -52,7 +52,8 @@ TEST_F(SendTimeHistoryTest, SaveAndRestoreNetworkId) { uint16_t sequence_number = 0; int64_t now_ms = clock_.TimeInMilliseconds(); for (int i = 1; i < 5; ++i) { - PacketFeedback packet(now_ms, sequence_number, 1000, i, i - 1, kPacingInfo); + PacketFeedback packet(now_ms, sequence_number, 1000, i, i - 1, + kPacingInfo); history_.AddAndRemoveOld(packet); history_.OnSentPacket(sequence_number, now_ms); PacketFeedback restored(now_ms, sequence_number); @@ -81,26 +82,6 @@ TEST_F(SendTimeHistoryTest, AddRemoveOne) { EXPECT_FALSE(history_.GetFeedback(&received_packet3, true)); } -TEST_F(SendTimeHistoryTest, GetPacketReturnsSentPacket) { - const uint16_t kSeqNo = 10; - const PacedPacketInfo kPacingInfo(0, 5, 1200); - const PacketFeedback kSentPacket(0, -1, 1, kSeqNo, 123, 0, 0, kPacingInfo); - AddPacketWithSendTime(kSeqNo, 123, 1, kPacingInfo); - auto sent_packet = history_.GetPacket(kSeqNo); - EXPECT_EQ(kSentPacket, *sent_packet); -} - -TEST_F(SendTimeHistoryTest, GetPacketEmptyForRemovedPacket) { - const uint16_t kSeqNo = 10; - const PacedPacketInfo kPacingInfo(0, 5, 1200); - AddPacketWithSendTime(kSeqNo, 123, 1, kPacingInfo); - auto sent_packet = history_.GetPacket(kSeqNo); - PacketFeedback received_packet(0, 0, kSeqNo, 0, kPacingInfo); - EXPECT_TRUE(history_.GetFeedback(&received_packet, true)); - sent_packet = history_.GetPacket(kSeqNo); - EXPECT_FALSE(sent_packet.has_value()); -} - TEST_F(SendTimeHistoryTest, PopulatesExpectedFields) { const uint16_t kSeqNo = 10; const int64_t kSendTime = 1000; diff --git a/modules/congestion_controller/transport_feedback_adapter.cc b/modules/congestion_controller/transport_feedback_adapter.cc index 8973ecaada9..7a5f7c4ee3f 100644 --- a/modules/congestion_controller/transport_feedback_adapter.cc +++ b/modules/congestion_controller/transport_feedback_adapter.cc @@ -82,12 +82,6 @@ void TransportFeedbackAdapter::OnSentPacket(uint16_t sequence_number, send_time_history_.OnSentPacket(sequence_number, send_time_ms); } -rtc::Optional TransportFeedbackAdapter::GetPacket( - uint16_t sequence_number) const { - rtc::CritScope cs(&lock_); - return send_time_history_.GetPacket(sequence_number); -} - void TransportFeedbackAdapter::SetNetworkIds(uint16_t local_id, uint16_t remote_id) { rtc::CritScope cs(&lock_); @@ -124,6 +118,7 @@ std::vector TransportFeedbackAdapter::GetPacketFeedbackVector( return packet_feedback_vector; } packet_feedback_vector.reserve(feedback.GetPacketStatusCount()); + int64_t feedback_rtt = -1; { rtc::CritScope cs(&lock_); size_t failed_lookups = 0; @@ -153,6 +148,12 @@ std::vector TransportFeedbackAdapter::GetPacketFeedbackVector( ++failed_lookups; if (packet_feedback.local_net_id == local_net_id_ && packet_feedback.remote_net_id == remote_net_id_) { + if (packet_feedback.send_time_ms >= 0) { + int64_t rtt = now_ms - packet_feedback.send_time_ms; + // max() is used to account for feedback being delayed by the + // receiver. + feedback_rtt = std::max(rtt, feedback_rtt); + } packet_feedback_vector.push_back(packet_feedback); } @@ -164,6 +165,14 @@ std::vector TransportFeedbackAdapter::GetPacketFeedbackVector( << " packet" << (failed_lookups > 1 ? "s" : "") << ". Send time history too small?"; } + 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_.emplace( + *std::min_element(feedback_rtts_.begin(), feedback_rtts_.end())); + } } return packet_feedback_vector; } @@ -184,6 +193,11 @@ TransportFeedbackAdapter::GetTransportFeedbackVector() const { return last_packet_feedback_vector_; } +rtc::Optional TransportFeedbackAdapter::GetMinFeedbackLoopRtt() const { + rtc::CritScope cs(&lock_); + return min_feedback_rtt_; +} + size_t TransportFeedbackAdapter::GetOutstandingBytes() const { rtc::CritScope cs(&lock_); return send_time_history_.GetOutstandingBytes(local_net_id_, remote_net_id_); diff --git a/modules/congestion_controller/transport_feedback_adapter.h b/modules/congestion_controller/transport_feedback_adapter.h index 26592548813..2e9bf7ced22 100644 --- a/modules/congestion_controller/transport_feedback_adapter.h +++ b/modules/congestion_controller/transport_feedback_adapter.h @@ -47,7 +47,7 @@ class TransportFeedbackAdapter { // to the CongestionController interface. void OnTransportFeedback(const rtcp::TransportFeedback& feedback); std::vector GetTransportFeedbackVector() const; - rtc::Optional GetPacket(uint16_t sequence_number) const; + rtc::Optional GetMinFeedbackLoopRtt() const; void SetTransportOverhead(int transport_overhead_bytes_per_packet); @@ -67,6 +67,8 @@ class TransportFeedbackAdapter { std::vector last_packet_feedback_vector_; uint16_t local_net_id_ RTC_GUARDED_BY(&lock_); uint16_t remote_net_id_ RTC_GUARDED_BY(&lock_); + std::deque feedback_rtts_ RTC_GUARDED_BY(&lock_); + rtc::Optional min_feedback_rtt_ RTC_GUARDED_BY(&lock_); rtc::CriticalSection observers_lock_; std::vector observers_ diff --git a/modules/pacing/BUILD.gn b/modules/pacing/BUILD.gn index fdfa3b271c3..4ac56d253e7 100644 --- a/modules/pacing/BUILD.gn +++ b/modules/pacing/BUILD.gn @@ -10,6 +10,8 @@ import("../../webrtc.gni") rtc_static_library("pacing") { sources = [ + "alr_detector.cc", + "alr_detector.h", "bitrate_prober.cc", "bitrate_prober.h", "interval_budget.cc", @@ -58,6 +60,7 @@ if (rtc_include_tests) { testonly = true sources = [ + "alr_detector_unittest.cc", "bitrate_prober_unittest.cc", "interval_budget_unittest.cc", "paced_sender_unittest.cc", diff --git a/modules/congestion_controller/alr_detector.cc b/modules/pacing/alr_detector.cc similarity index 87% rename from modules/congestion_controller/alr_detector.cc rename to modules/pacing/alr_detector.cc index 249aa18b1b3..9ba6e32770d 100644 --- a/modules/congestion_controller/alr_detector.cc +++ b/modules/pacing/alr_detector.cc @@ -8,11 +8,11 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "modules/congestion_controller/alr_detector.h" +#include "modules/pacing/alr_detector.h" #include -#include #include +#include #include "logging/rtc_event_log/events/rtc_event_alr_state.h" #include "logging/rtc_event_log/rtc_event_log.h" @@ -52,16 +52,7 @@ AlrDetector::AlrDetector(RtcEventLog* event_log) AlrDetector::~AlrDetector() {} -void AlrDetector::OnBytesSent(size_t bytes_sent, int64_t send_time_ms) { - if (!last_send_time_ms_.has_value()) { - last_send_time_ms_ = send_time_ms; - // Since the duration for sending the bytes is unknwon, return without - // updating alr state. - return; - } - int64_t delta_time_ms = send_time_ms - *last_send_time_ms_; - last_send_time_ms_ = send_time_ms; - +void AlrDetector::OnBytesSent(size_t bytes_sent, int64_t delta_time_ms) { alr_budget_.UseBudget(bytes_sent); alr_budget_.IncreaseBudget(delta_time_ms); bool state_changed = false; diff --git a/modules/congestion_controller/alr_detector.h b/modules/pacing/alr_detector.h similarity index 89% rename from modules/congestion_controller/alr_detector.h rename to modules/pacing/alr_detector.h index 5cb90430141..f73bc17b3db 100644 --- a/modules/congestion_controller/alr_detector.h +++ b/modules/pacing/alr_detector.h @@ -8,8 +8,8 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef MODULES_CONGESTION_CONTROLLER_ALR_DETECTOR_H_ -#define MODULES_CONGESTION_CONTROLLER_ALR_DETECTOR_H_ +#ifndef MODULES_PACING_ALR_DETECTOR_H_ +#define MODULES_PACING_ALR_DETECTOR_H_ #include "api/optional.h" #include "common_types.h" // NOLINT(build/include) @@ -35,7 +35,7 @@ class AlrDetector { explicit AlrDetector(RtcEventLog* event_log); ~AlrDetector(); - void OnBytesSent(size_t bytes_sent, int64_t send_time_ms); + void OnBytesSent(size_t bytes_sent, int64_t delta_time_ms); // Set current estimated bandwidth. void SetEstimatedBitrate(int bitrate_bps); @@ -61,8 +61,6 @@ class AlrDetector { int alr_start_budget_level_percent_; int alr_stop_budget_level_percent_; - rtc::Optional last_send_time_ms_; - IntervalBudget alr_budget_; rtc::Optional alr_started_time_ms_; @@ -71,4 +69,4 @@ class AlrDetector { } // namespace webrtc -#endif // MODULES_CONGESTION_CONTROLLER_ALR_DETECTOR_H_ +#endif // MODULES_PACING_ALR_DETECTOR_H_ diff --git a/modules/congestion_controller/alr_detector_unittest.cc b/modules/pacing/alr_detector_unittest.cc similarity index 84% rename from modules/congestion_controller/alr_detector_unittest.cc rename to modules/pacing/alr_detector_unittest.cc index a7f55413fd0..356e14e4699 100644 --- a/modules/congestion_controller/alr_detector_unittest.cc +++ b/modules/pacing/alr_detector_unittest.cc @@ -8,7 +8,7 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "modules/congestion_controller/alr_detector.h" +#include "modules/pacing/alr_detector.h" #include "rtc_base/experiments/alr_experiment.h" #include "test/field_trial.h" @@ -25,9 +25,8 @@ namespace webrtc { namespace { class SimulateOutgoingTrafficIn { public: - explicit SimulateOutgoingTrafficIn(AlrDetector* alr_detector, - int64_t* timestamp_ms) - : alr_detector_(alr_detector), timestamp_ms_(timestamp_ms) { + explicit SimulateOutgoingTrafficIn(AlrDetector* alr_detector) + : alr_detector_(alr_detector) { RTC_CHECK(alr_detector_); } @@ -49,21 +48,18 @@ class SimulateOutgoingTrafficIn { return; const int kTimeStepMs = 10; for (int t = 0; t < *interval_ms_; t += kTimeStepMs) { - *timestamp_ms_ += kTimeStepMs; alr_detector_->OnBytesSent(kEstimatedBitrateBps * *usage_percentage_ * kTimeStepMs / (8 * 100 * 1000), - *timestamp_ms_); + kTimeStepMs); } int remainder_ms = *interval_ms_ % kTimeStepMs; if (remainder_ms > 0) { - *timestamp_ms_ += kTimeStepMs; alr_detector_->OnBytesSent(kEstimatedBitrateBps * *usage_percentage_ * remainder_ms / (8 * 100 * 1000), - *timestamp_ms_); + kTimeStepMs); } } AlrDetector* const alr_detector_; - int64_t* timestamp_ms_; rtc::Optional interval_ms_; rtc::Optional usage_percentage_; }; @@ -77,7 +73,6 @@ class AlrDetectorTest : public testing::Test { protected: AlrDetector alr_detector_; - int64_t timestamp_ms_ = 1000; }; TEST_F(AlrDetectorTest, AlrDetection) { @@ -85,19 +80,19 @@ TEST_F(AlrDetectorTest, AlrDetection) { EXPECT_FALSE(alr_detector_.GetApplicationLimitedRegionStartTime()); // Stay in non-ALR state when usage is close to 100%. - SimulateOutgoingTrafficIn(&alr_detector_, ×tamp_ms_) + SimulateOutgoingTrafficIn(&alr_detector_) .ForTimeMs(1000) .AtPercentOfEstimatedBitrate(90); EXPECT_FALSE(alr_detector_.GetApplicationLimitedRegionStartTime()); // Verify that we ALR starts when bitrate drops below 20%. - SimulateOutgoingTrafficIn(&alr_detector_, ×tamp_ms_) + SimulateOutgoingTrafficIn(&alr_detector_) .ForTimeMs(1500) .AtPercentOfEstimatedBitrate(20); EXPECT_TRUE(alr_detector_.GetApplicationLimitedRegionStartTime()); // Verify that ALR ends when usage is above 65%. - SimulateOutgoingTrafficIn(&alr_detector_, ×tamp_ms_) + SimulateOutgoingTrafficIn(&alr_detector_) .ForTimeMs(4000) .AtPercentOfEstimatedBitrate(100); EXPECT_FALSE(alr_detector_.GetApplicationLimitedRegionStartTime()); @@ -108,19 +103,19 @@ TEST_F(AlrDetectorTest, ShortSpike) { EXPECT_FALSE(alr_detector_.GetApplicationLimitedRegionStartTime()); // Verify that we ALR starts when bitrate drops below 20%. - SimulateOutgoingTrafficIn(&alr_detector_, ×tamp_ms_) + SimulateOutgoingTrafficIn(&alr_detector_) .ForTimeMs(1000) .AtPercentOfEstimatedBitrate(20); EXPECT_TRUE(alr_detector_.GetApplicationLimitedRegionStartTime()); // Verify that we stay in ALR region even after a short bitrate spike. - SimulateOutgoingTrafficIn(&alr_detector_, ×tamp_ms_) + SimulateOutgoingTrafficIn(&alr_detector_) .ForTimeMs(100) .AtPercentOfEstimatedBitrate(150); EXPECT_TRUE(alr_detector_.GetApplicationLimitedRegionStartTime()); // ALR ends when usage is above 65%. - SimulateOutgoingTrafficIn(&alr_detector_, ×tamp_ms_) + SimulateOutgoingTrafficIn(&alr_detector_) .ForTimeMs(3000) .AtPercentOfEstimatedBitrate(100); EXPECT_FALSE(alr_detector_.GetApplicationLimitedRegionStartTime()); @@ -131,7 +126,7 @@ TEST_F(AlrDetectorTest, BandwidthEstimateChanges) { EXPECT_FALSE(alr_detector_.GetApplicationLimitedRegionStartTime()); // ALR starts when bitrate drops below 20%. - SimulateOutgoingTrafficIn(&alr_detector_, ×tamp_ms_) + SimulateOutgoingTrafficIn(&alr_detector_) .ForTimeMs(1000) .AtPercentOfEstimatedBitrate(20); EXPECT_TRUE(alr_detector_.GetApplicationLimitedRegionStartTime()); @@ -142,7 +137,7 @@ TEST_F(AlrDetectorTest, BandwidthEstimateChanges) { // to the BWE drop by initiating a new probe. alr_detector_.SetEstimatedBitrate(kEstimatedBitrateBps / 5); EXPECT_TRUE(alr_detector_.GetApplicationLimitedRegionStartTime()); - SimulateOutgoingTrafficIn(&alr_detector_, ×tamp_ms_) + SimulateOutgoingTrafficIn(&alr_detector_) .ForTimeMs(1000) .AtPercentOfEstimatedBitrate(50); EXPECT_FALSE(alr_detector_.GetApplicationLimitedRegionStartTime()); diff --git a/modules/pacing/interval_budget.cc b/modules/pacing/interval_budget.cc index f739a984584..b63bc37149e 100644 --- a/modules/pacing/interval_budget.cc +++ b/modules/pacing/interval_budget.cc @@ -15,6 +15,7 @@ namespace webrtc { namespace { constexpr int kWindowMs = 500; +constexpr int kDeltaTimeMs = 2000; } IntervalBudget::IntervalBudget(int initial_target_rate_kbps) @@ -34,6 +35,7 @@ void IntervalBudget::set_target_rate_kbps(int target_rate_kbps) { } void IntervalBudget::IncreaseBudget(int64_t delta_time_ms) { + RTC_DCHECK_LT(delta_time_ms, kDeltaTimeMs); int bytes = target_rate_kbps_ * delta_time_ms / 8; if (bytes_remaining_ < 0 || can_build_up_underuse_) { // We overused last interval, compensate this interval. @@ -54,8 +56,6 @@ size_t IntervalBudget::bytes_remaining() const { } int IntervalBudget::budget_level_percent() const { - if (max_bytes_in_budget_ == 0) - return 0; return bytes_remaining_ * 100 / max_bytes_in_budget_; } diff --git a/modules/pacing/mock/mock_paced_sender.h b/modules/pacing/mock/mock_paced_sender.h index cf9899671fb..3366aa85ed1 100644 --- a/modules/pacing/mock/mock_paced_sender.h +++ b/modules/pacing/mock/mock_paced_sender.h @@ -30,10 +30,12 @@ class MockPacedSender : public PacedSender { size_t bytes, bool retransmission)); MOCK_METHOD1(CreateProbeCluster, void(int)); - MOCK_METHOD2(SetPacingRates, void(uint32_t, uint32_t)); + MOCK_METHOD1(SetEstimatedBitrate, void(uint32_t)); MOCK_CONST_METHOD0(QueueInMs, int64_t()); MOCK_CONST_METHOD0(QueueInPackets, int()); MOCK_CONST_METHOD0(ExpectedQueueTimeMs, int64_t()); + MOCK_CONST_METHOD0(GetApplicationLimitedRegionStartTime, + rtc::Optional()); MOCK_METHOD0(Process, void()); }; diff --git a/modules/pacing/paced_sender.cc b/modules/pacing/paced_sender.cc index 862f4e189f7..4bccb000c2f 100644 --- a/modules/pacing/paced_sender.cc +++ b/modules/pacing/paced_sender.cc @@ -18,6 +18,7 @@ #include #include "modules/include/module_common_types.h" +#include "modules/pacing/alr_detector.h" #include "modules/pacing/bitrate_prober.h" #include "modules/pacing/interval_budget.h" #include "modules/pacing/packet_queue.h" @@ -53,6 +54,7 @@ bool IsRoundRobinPacingEnabled() { namespace webrtc { const int64_t PacedSender::kMaxQueueLengthMs = 2000; +const float PacedSender::kDefaultPaceMultiplier = 2.5f; namespace { std::unique_ptr CreatePacketQueue(const Clock* clock, @@ -79,16 +81,21 @@ PacedSender::PacedSender(const Clock* clock, std::unique_ptr packets) : clock_(clock), packet_sender_(packet_sender), + alr_detector_(rtc::MakeUnique(event_log)), paused_(false), media_budget_(rtc::MakeUnique(0)), padding_budget_(rtc::MakeUnique(0)), prober_(rtc::MakeUnique(event_log)), probing_send_failure_(false), + estimated_bitrate_bps_(0), + min_send_bitrate_kbps_(0u), + max_padding_bitrate_kbps_(0u), pacing_bitrate_kbps_(0), time_last_update_us_(clock->TimeInMicroseconds()), first_sent_packet_ms_(-1), packets_(std::move(packets)), packet_counter_(0), + pacing_factor_(kDefaultPaceMultiplier), queue_time_limit(kMaxQueueLengthMs), account_for_audio_(false) { UpdateBudgetWithElapsedTime(kMinPacketLimitMs); @@ -109,7 +116,6 @@ void PacedSender::Pause() { paused_ = true; packets_->SetPauseState(true, clock_->TimeInMilliseconds()); } - rtc::CritScope cs(&process_thread_lock_); // Tell the process thread to call our TimeUntilNextProcess() method to get // a new (longer) estimate for when to call Process(). if (process_thread_) @@ -124,7 +130,6 @@ void PacedSender::Resume() { paused_ = false; packets_->SetPauseState(false, clock_->TimeInMilliseconds()); } - rtc::CritScope cs(&process_thread_lock_); // Tell the process thread to call our TimeUntilNextProcess() method to // refresh the estimate for when to call Process(). if (process_thread_) @@ -137,12 +142,29 @@ void PacedSender::SetProbingEnabled(bool enabled) { prober_->SetEnabled(enabled); } -void PacedSender::SetPacingRates(uint32_t pacing_rate_bps, - uint32_t padding_rate_bps) { +void PacedSender::SetEstimatedBitrate(uint32_t bitrate_bps) { + if (bitrate_bps == 0) + RTC_LOG(LS_ERROR) << "PacedSender is not designed to handle 0 bitrate."; rtc::CritScope cs(&critsect_); - RTC_DCHECK(pacing_rate_bps > 0); - pacing_bitrate_kbps_ = pacing_rate_bps / 1000; - padding_budget_->set_target_rate_kbps(padding_rate_bps / 1000); + estimated_bitrate_bps_ = bitrate_bps; + padding_budget_->set_target_rate_kbps( + std::min(estimated_bitrate_bps_ / 1000, max_padding_bitrate_kbps_)); + pacing_bitrate_kbps_ = + std::max(min_send_bitrate_kbps_, estimated_bitrate_bps_ / 1000) * + pacing_factor_; + alr_detector_->SetEstimatedBitrate(bitrate_bps); +} + +void PacedSender::SetSendBitrateLimits(int min_send_bitrate_bps, + int padding_bitrate) { + rtc::CritScope cs(&critsect_); + min_send_bitrate_kbps_ = min_send_bitrate_bps / 1000; + pacing_bitrate_kbps_ = + std::max(min_send_bitrate_kbps_, estimated_bitrate_bps_ / 1000) * + pacing_factor_; + max_padding_bitrate_kbps_ = padding_bitrate / 1000; + padding_budget_->set_target_rate_kbps( + std::min(estimated_bitrate_bps_ / 1000, max_padding_bitrate_kbps_)); } void PacedSender::InsertPacket(RtpPacketSender::Priority priority, @@ -152,8 +174,8 @@ void PacedSender::InsertPacket(RtpPacketSender::Priority priority, size_t bytes, bool retransmission) { rtc::CritScope cs(&critsect_); - RTC_DCHECK(pacing_bitrate_kbps_ > 0) - << "SetPacingRate must be called before InsertPacket."; + RTC_DCHECK(estimated_bitrate_bps_ > 0) + << "SetEstimatedBitrate must be called before InsertPacket."; int64_t now_ms = clock_->TimeInMilliseconds(); prober_->OnIncomingPacket(bytes); @@ -178,6 +200,12 @@ int64_t PacedSender::ExpectedQueueTimeMs() const { pacing_bitrate_kbps_); } +rtc::Optional PacedSender::GetApplicationLimitedRegionStartTime() + const { + rtc::CritScope cs(&critsect_); + return alr_detector_->GetApplicationLimitedRegionStartTime(); +} + size_t PacedSender::QueueSizePackets() const { rtc::CritScope cs(&critsect_); return packets_->SizeInPackets(); @@ -229,7 +257,8 @@ void PacedSender::Process() { // do, timestamps get messed up. if (packet_counter_ == 0) return; - SendPadding(1, pacing_info); + size_t bytes_sent = SendPadding(1, pacing_info); + alr_detector_->OnBytesSent(bytes_sent, elapsed_time_ms); return; } @@ -262,7 +291,7 @@ void PacedSender::Process() { pacing_info = prober_->CurrentCluster(); recommended_probe_size = prober_->RecommendedMinProbeSize(); } - while (!packets_->Empty() && !paused_) { + while (!packets_->Empty()) { // Since we need to release the lock in order to send, we first pop the // element from the priority queue but keep it in storage, so that we can // reinsert it if send fails. @@ -290,9 +319,8 @@ void PacedSender::Process() { int padding_needed = static_cast(is_probing ? (recommended_probe_size - bytes_sent) : padding_budget_->bytes_remaining()); - if (padding_needed > 0) { + if (padding_needed > 0) bytes_sent += SendPadding(padding_needed, pacing_info); - } } } if (is_probing) { @@ -300,11 +328,11 @@ void PacedSender::Process() { if (!probing_send_failure_) prober_->ProbeSent(clock_->TimeInMilliseconds(), bytes_sent); } + alr_detector_->OnBytesSent(bytes_sent, elapsed_time_ms); } void PacedSender::ProcessThreadAttached(ProcessThread* process_thread) { RTC_LOG(LS_INFO) << "ProcessThreadAttached 0x" << std::hex << process_thread; - rtc::CritScope cs(&process_thread_lock_); process_thread_ = process_thread; } @@ -360,6 +388,14 @@ void PacedSender::UpdateBudgetWithBytesSent(size_t bytes_sent) { padding_budget_->UseBudget(bytes_sent); } +void PacedSender::SetPacingFactor(float pacing_factor) { + rtc::CritScope cs(&critsect_); + pacing_factor_ = pacing_factor; + // Make sure new padding factor is applied immediately, otherwise we need to + // wait for the send bitrate estimate to be updated before this takes effect. + SetEstimatedBitrate(estimated_bitrate_bps_); +} + void PacedSender::SetQueueTimeLimit(int limit_ms) { rtc::CritScope cs(&critsect_); queue_time_limit = limit_ms; diff --git a/modules/pacing/paced_sender.h b/modules/pacing/paced_sender.h index 0501bbb6914..02ebdcd6325 100644 --- a/modules/pacing/paced_sender.h +++ b/modules/pacing/paced_sender.h @@ -21,6 +21,7 @@ #include "typedefs.h" // NOLINT(build/include) namespace webrtc { +class AlrDetector; class BitrateProber; class Clock; class ProbeClusterCreatedObserver; @@ -54,6 +55,12 @@ class PacedSender : public Pacer { // encoding them). Bitrate sent may temporarily exceed target set by // UpdateBitrate() so that this limit will be upheld. static const int64_t kMaxQueueLengthMs; + // 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. + // Increasing this factor will result in lower delays in cases of bitrate + // overshoots from the encoder. + static const float kDefaultPaceMultiplier; PacedSender(const Clock* clock, PacketSender* packet_sender, @@ -79,9 +86,22 @@ class PacedSender : public Pacer { // effect. void SetProbingEnabled(bool enabled); - // Sets the pacing rates. Must be called once before packets can be sent. - void SetPacingRates(uint32_t pacing_rate_bps, - uint32_t padding_rate_bps) override; + // Sets the estimated capacity of the network. Must be called once before + // packets can be sent. + // |bitrate_bps| is our estimate of what we are allowed to send on average. + // We will pace out bursts of packets at a bitrate of + // |bitrate_bps| * kDefaultPaceMultiplier. + void SetEstimatedBitrate(uint32_t bitrate_bps) override; + + // Sets the minimum send bitrate and maximum padding bitrate requested by send + // streams. + // |min_send_bitrate_bps| might be higher that the estimated available network + // bitrate and if so, the pacer will send with |min_send_bitrate_bps|. + // |max_padding_bitrate_bps| might be higher than the estimate available + // network bitrate and if so, the pacer will send padding packets to reach + // the min of the estimated available bitrate and |max_padding_bitrate_bps|. + void SetSendBitrateLimits(int min_send_bitrate_bps, + int max_padding_bitrate_bps); // Returns true if we send the packet now, else it will add the packet // information to the queue and call TimeToSendPacket when it's time to send. @@ -111,6 +131,14 @@ class PacedSender : public Pacer { // packets in the queue, given the current size and bitrate, ignoring prio. virtual int64_t ExpectedQueueTimeMs() const; + // Returns time in milliseconds when the current application-limited region + // started or empty result if the sender is currently not application-limited. + // + // Application Limited Region (ALR) refers to operating in a state where the + // traffic on network is limited due to application not having enough + // traffic to meet the current channel capacity. + virtual rtc::Optional GetApplicationLimitedRegionStartTime() const; + // Returns the number of milliseconds until the module want a worker thread // to call Process. int64_t TimeUntilNextProcess() override; @@ -120,6 +148,7 @@ class PacedSender : public Pacer { // Called when the prober is associated with a process thread. void ProcessThreadAttached(ProcessThread* process_thread) override; + void SetPacingFactor(float pacing_factor); void SetQueueTimeLimit(int limit_ms); private: @@ -137,6 +166,7 @@ class PacedSender : public Pacer { const Clock* const clock_; PacketSender* const packet_sender_; + const std::unique_ptr alr_detector_ RTC_PT_GUARDED_BY(critsect_); rtc::CriticalSection critsect_; bool paused_ RTC_GUARDED_BY(critsect_); @@ -154,6 +184,9 @@ class PacedSender : public Pacer { bool probing_send_failure_ RTC_GUARDED_BY(critsect_); // Actual configured bitrates (media_budget_ may temporarily be higher in // order to meet pace time constraint). + uint32_t estimated_bitrate_bps_ RTC_GUARDED_BY(critsect_); + uint32_t min_send_bitrate_kbps_ RTC_GUARDED_BY(critsect_); + uint32_t max_padding_bitrate_kbps_ RTC_GUARDED_BY(critsect_); uint32_t pacing_bitrate_kbps_ RTC_GUARDED_BY(critsect_); int64_t time_last_update_us_ RTC_GUARDED_BY(critsect_); @@ -162,15 +195,9 @@ class PacedSender : public Pacer { const std::unique_ptr packets_ RTC_PT_GUARDED_BY(critsect_); uint64_t packet_counter_ RTC_GUARDED_BY(critsect_); + ProcessThread* process_thread_ = nullptr; - // Lock to avoid race when attaching process thread. This can happen due to - // the Call class setting network state on SendSideCongestionController, which - // in turn calls Pause/Resume on Pacedsender, before actually starting the - // pacer process thread. If SendSideCongestionController is running on a task - // queue separate from the thread used by Call, this causes a race. - rtc::CriticalSection process_thread_lock_; - ProcessThread* process_thread_ RTC_GUARDED_BY(process_thread_lock_) = nullptr; - + float pacing_factor_ RTC_GUARDED_BY(critsect_); int64_t queue_time_limit RTC_GUARDED_BY(critsect_); bool account_for_audio_ RTC_GUARDED_BY(critsect_); }; diff --git a/modules/pacing/paced_sender_unittest.cc b/modules/pacing/paced_sender_unittest.cc index 4507f3f9297..4281ec220aa 100644 --- a/modules/pacing/paced_sender_unittest.cc +++ b/modules/pacing/paced_sender_unittest.cc @@ -31,8 +31,6 @@ constexpr unsigned kSecondClusterBps = 1800000; // values. This results in probing slightly higher than the target bitrate. // For 1.8 Mbps, this comes to be about 120 kbps with 1200 probe packets. constexpr int kBitrateProbingError = 150000; - -const float kPaceMultiplier = 2.5f; } // namespace namespace webrtc { @@ -118,7 +116,7 @@ class PacedSenderTest : public testing::TestWithParam { // have to enable probing, either by creating a new PacedSender instance or // by calling SetProbingEnabled(true). send_bucket_->SetProbingEnabled(false); - send_bucket_->SetPacingRates(kTargetBitrateBps * kPaceMultiplier, 0); + send_bucket_->SetEstimatedBitrate(kTargetBitrateBps); clock_.AdvanceTimeMilliseconds(send_bucket_->TimeUntilNextProcess()); } @@ -173,7 +171,7 @@ TEST_P(PacedSenderTest, QueuePacket) { // interval. (network capacity * multiplier / (8 bits per byte * // (packet size * #send intervals per second) const size_t packets_to_send = - kTargetBitrateBps * kPaceMultiplier / (8 * 250 * 200); + kTargetBitrateBps * PacedSender::kDefaultPaceMultiplier / (8 * 250 * 200); for (size_t i = 0; i < packets_to_send; ++i) { SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++, clock_.TimeInMilliseconds(), 250, false); @@ -222,7 +220,7 @@ TEST_P(PacedSenderTest, PaceQueuedPackets) { // interval. (network capacity * multiplier / (8 bits per byte * // (packet size * #send intervals per second) const size_t packets_to_send_per_interval = - kTargetBitrateBps * kPaceMultiplier / (8 * 250 * 200); + kTargetBitrateBps * PacedSender::kDefaultPaceMultiplier / (8 * 250 * 200); for (size_t i = 0; i < packets_to_send_per_interval; ++i) { SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++, clock_.TimeInMilliseconds(), 250, false); @@ -307,14 +305,14 @@ TEST_P(PacedSenderTest, Padding) { uint32_t ssrc = 12345; uint16_t sequence_number = 1234; - send_bucket_->SetPacingRates(kTargetBitrateBps * kPaceMultiplier, - kTargetBitrateBps); + send_bucket_->SetEstimatedBitrate(kTargetBitrateBps); + send_bucket_->SetSendBitrateLimits(kTargetBitrateBps, kTargetBitrateBps); // Due to the multiplicative factor we can send 5 packets during a send // interval. (network capacity * multiplier / (8 bits per byte * // (packet size * #send intervals per second) const size_t packets_to_send_per_interval = - kTargetBitrateBps * kPaceMultiplier / (8 * 250 * 200); + kTargetBitrateBps * PacedSender::kDefaultPaceMultiplier / (8 * 250 * 200); for (size_t i = 0; i < packets_to_send_per_interval; ++i) { SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++, clock_.TimeInMilliseconds(), 250, false); @@ -344,8 +342,8 @@ TEST_P(PacedSenderTest, Padding) { } TEST_P(PacedSenderTest, NoPaddingBeforeNormalPacket) { - send_bucket_->SetPacingRates(kTargetBitrateBps * kPaceMultiplier, - kTargetBitrateBps); + send_bucket_->SetEstimatedBitrate(kTargetBitrateBps); + send_bucket_->SetSendBitrateLimits(kTargetBitrateBps, kTargetBitrateBps); EXPECT_CALL(callback_, TimeToSendPadding(_, _)).Times(0); send_bucket_->Process(); @@ -372,8 +370,8 @@ TEST_P(PacedSenderTest, VerifyPaddingUpToBitrate) { int64_t capture_time_ms = 56789; const int kTimeStep = 5; const int64_t kBitrateWindow = 100; - send_bucket_->SetPacingRates(kTargetBitrateBps * kPaceMultiplier, - kTargetBitrateBps); + send_bucket_->SetEstimatedBitrate(kTargetBitrateBps); + send_bucket_->SetSendBitrateLimits(kTargetBitrateBps, kTargetBitrateBps); int64_t start_time = clock_.TimeInMilliseconds(); while (clock_.TimeInMilliseconds() - start_time < kBitrateWindow) { @@ -400,8 +398,11 @@ TEST_P(PacedSenderTest, VerifyAverageBitrateVaryingMediaPayload) { PacedSenderPadding callback; send_bucket_.reset(new PacedSender(&clock_, &callback, nullptr)); send_bucket_->SetProbingEnabled(false); - send_bucket_->SetPacingRates(kTargetBitrateBps * kPaceMultiplier, - kTargetBitrateBps); + send_bucket_->SetEstimatedBitrate(kTargetBitrateBps); + + send_bucket_->SetSendBitrateLimits( + 0 /*allocated_bitrate_bps*/, + kTargetBitrateBps * 2 /* max_padding_bitrate_bps */); int64_t start_time = clock_.TimeInMilliseconds(); size_t media_bytes = 0; @@ -432,7 +433,7 @@ TEST_P(PacedSenderTest, Priority) { // interval. (network capacity * multiplier / (8 bits per byte * // (packet size * #send intervals per second) const size_t packets_to_send_per_interval = - kTargetBitrateBps * kPaceMultiplier / (8 * 250 * 200); + kTargetBitrateBps * PacedSender::kDefaultPaceMultiplier / (8 * 250 * 200); for (size_t i = 0; i < packets_to_send_per_interval; ++i) { SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++, clock_.TimeInMilliseconds(), 250, false); @@ -486,7 +487,7 @@ TEST_P(PacedSenderTest, RetransmissionPriority) { // interval. (network capacity * multiplier / (8 bits per byte * // (packet size * #send intervals per second) const size_t packets_to_send_per_interval = - kTargetBitrateBps * kPaceMultiplier / (8 * 250 * 200); + kTargetBitrateBps * PacedSender::kDefaultPaceMultiplier / (8 * 250 * 200); send_bucket_->Process(); EXPECT_EQ(0u, send_bucket_->QueueSizePackets()); @@ -547,7 +548,7 @@ TEST_P(PacedSenderTest, HighPrioDoesntAffectBudget) { // interval. (network capacity * multiplier / (8 bits per byte * // (packet size * #send intervals per second) const size_t packets_to_send_per_interval = - kTargetBitrateBps * kPaceMultiplier / (8 * 250 * 200); + kTargetBitrateBps * PacedSender::kDefaultPaceMultiplier / (8 * 250 * 200); for (size_t i = 0; i < packets_to_send_per_interval; ++i) { SendAndExpectPacket(PacedSender::kLowPriority, ssrc, sequence_number++, clock_.TimeInMilliseconds(), 250, false); @@ -581,7 +582,7 @@ TEST_P(PacedSenderTest, Pause) { // interval. (network capacity * multiplier / (8 bits per byte * // (packet size * #send intervals per second) const size_t packets_to_send_per_interval = - kTargetBitrateBps * kPaceMultiplier / (8 * 250 * 200); + kTargetBitrateBps * PacedSender::kDefaultPaceMultiplier / (8 * 250 * 200); for (size_t i = 0; i < packets_to_send_per_interval; ++i) { SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++, clock_.TimeInMilliseconds(), 250, false); @@ -740,10 +741,10 @@ TEST_P(PacedSenderTest, ExpectedQueueTimeMs) { uint16_t sequence_number = 1234; const size_t kNumPackets = 60; const size_t kPacketSize = 1200; - const int32_t kMaxBitrate = kPaceMultiplier * 30000; + const int32_t kMaxBitrate = PacedSender::kDefaultPaceMultiplier * 30000; EXPECT_EQ(0, send_bucket_->ExpectedQueueTimeMs()); - send_bucket_->SetPacingRates(30000 * kPaceMultiplier, 0); + send_bucket_->SetEstimatedBitrate(30000); for (size_t i = 0; i < kNumPackets; ++i) { SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++, clock_.TimeInMilliseconds(), kPacketSize, false); @@ -777,7 +778,7 @@ TEST_P(PacedSenderTest, QueueTimeGrowsOverTime) { uint16_t sequence_number = 1234; EXPECT_EQ(0, send_bucket_->QueueInMs()); - send_bucket_->SetPacingRates(30000 * kPaceMultiplier, 0); + send_bucket_->SetEstimatedBitrate(30000); SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number, @@ -801,7 +802,7 @@ TEST_P(PacedSenderTest, ProbingWithInsertedPackets) { send_bucket_.reset(new PacedSender(&clock_, &packet_sender, nullptr)); send_bucket_->CreateProbeCluster(kFirstClusterBps); send_bucket_->CreateProbeCluster(kSecondClusterBps); - send_bucket_->SetPacingRates(kInitialBitrateBps * kPaceMultiplier, 0); + send_bucket_->SetEstimatedBitrate(kInitialBitrateBps); for (int i = 0; i < 10; ++i) { send_bucket_->InsertPacket(PacedSender::kNormalPriority, ssrc, @@ -846,7 +847,7 @@ TEST_P(PacedSenderTest, ProbingWithPaddingSupport) { PacedSenderProbing packet_sender; send_bucket_.reset(new PacedSender(&clock_, &packet_sender, nullptr)); send_bucket_->CreateProbeCluster(kFirstClusterBps); - send_bucket_->SetPacingRates(kInitialBitrateBps * kPaceMultiplier, 0); + send_bucket_->SetEstimatedBitrate(kInitialBitrateBps); for (int i = 0; i < 3; ++i) { send_bucket_->InsertPacket(PacedSender::kNormalPriority, ssrc, @@ -934,7 +935,8 @@ TEST_P(PacedSenderTest, PaddingOveruse) { const size_t kPacketSize = 1200; send_bucket_->Process(); - send_bucket_->SetPacingRates(60000 * kPaceMultiplier, 0); + send_bucket_->SetEstimatedBitrate(60000); + send_bucket_->SetSendBitrateLimits(60000, 0); SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++, clock_.TimeInMilliseconds(), kPacketSize, false); @@ -943,7 +945,7 @@ TEST_P(PacedSenderTest, PaddingOveruse) { // Add 30kbit padding. When increasing budget, media budget will increase from // negative (overuse) while padding budget will increase from 0. clock_.AdvanceTimeMilliseconds(5); - send_bucket_->SetPacingRates(60000 * kPaceMultiplier, 30000); + send_bucket_->SetSendBitrateLimits(60000, 30000); SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++, clock_.TimeInMilliseconds(), kPacketSize, false); @@ -961,7 +963,7 @@ TEST_F(PacedSenderTest, AverageQueueTime) { const size_t kPacketSize = 1200; const int kBitrateBps = 10 * kPacketSize * 8; // 10 packets per second. - send_bucket_->SetPacingRates(kBitrateBps * kPaceMultiplier, 0); + send_bucket_->SetEstimatedBitrate(kBitrateBps); EXPECT_EQ(0, send_bucket_->AverageQueueTimeMs()); @@ -1006,8 +1008,7 @@ TEST_P(PacedSenderTest, ProbeClusterId) { uint16_t sequence_number = 1234; const size_t kPacketSize = 1200; - send_bucket_->SetPacingRates(kTargetBitrateBps * kPaceMultiplier, - kTargetBitrateBps); + send_bucket_->SetSendBitrateLimits(kTargetBitrateBps, kTargetBitrateBps); send_bucket_->SetProbingEnabled(true); for (int i = 0; i < 10; ++i) { send_bucket_->InsertPacket(PacedSender::kNormalPriority, ssrc, @@ -1053,8 +1054,7 @@ TEST_P(PacedSenderTest, AvoidBusyLoopOnSendFailure) { uint16_t sequence_number = 1234; const size_t kPacketSize = kFirstClusterBps / (8000 / 10); - send_bucket_->SetPacingRates(kTargetBitrateBps * kPaceMultiplier, - kTargetBitrateBps); + send_bucket_->SetSendBitrateLimits(kTargetBitrateBps, kTargetBitrateBps); send_bucket_->SetProbingEnabled(true); send_bucket_->InsertPacket(PacedSender::kNormalPriority, ssrc, sequence_number, clock_.TimeInMilliseconds(), diff --git a/modules/pacing/pacer.h b/modules/pacing/pacer.h index 4941e157ee1..8b43e1851ed 100644 --- a/modules/pacing/pacer.h +++ b/modules/pacing/pacer.h @@ -17,8 +17,7 @@ namespace webrtc { class Pacer : public Module, public RtpPacketSender { public: - virtual void SetPacingRates(uint32_t pacing_rate_bps, - uint32_t padding_rate_bps) {} + virtual void SetEstimatedBitrate(uint32_t bitrate_bps) {} virtual void SetEstimatedBitrateAndCongestionWindow( uint32_t bitrate_bps, bool in_probe_rtt, diff --git a/modules/pacing/packet_queue.cc b/modules/pacing/packet_queue.cc index eb0f822d506..5e4e58cb18a 100644 --- a/modules/pacing/packet_queue.cc +++ b/modules/pacing/packet_queue.cc @@ -15,6 +15,7 @@ #include #include "modules/include/module_common_types.h" +#include "modules/pacing/alr_detector.h" #include "modules/pacing/bitrate_prober.h" #include "modules/pacing/interval_budget.h" #include "modules/utility/include/process_thread.h" diff --git a/modules/pacing/packet_router.cc b/modules/pacing/packet_router.cc index ef9d10ae552..e3d935e65c8 100644 --- a/modules/pacing/packet_router.cc +++ b/modules/pacing/packet_router.cc @@ -98,6 +98,7 @@ bool PacketRouter::TimeToSendPacket(uint32_t ssrc, int64_t capture_timestamp, bool retransmission, const PacedPacketInfo& pacing_info) { + RTC_DCHECK_RUNS_SERIALIZED(&pacer_race_); rtc::CritScope cs(&modules_crit_); for (auto* rtp_module : rtp_send_modules_) { if (!rtp_module->SendingMedia()) @@ -113,6 +114,7 @@ bool PacketRouter::TimeToSendPacket(uint32_t ssrc, size_t PacketRouter::TimeToSendPadding(size_t bytes_to_send, const PacedPacketInfo& pacing_info) { + RTC_DCHECK_RUNS_SERIALIZED(&pacer_race_); size_t total_bytes_sent = 0; rtc::CritScope cs(&modules_crit_); // Rtp modules are ordered by which stream can most benefit from padding. @@ -221,6 +223,7 @@ bool PacketRouter::SendRemb(int64_t bitrate_bps, } bool PacketRouter::SendTransportFeedback(rtcp::TransportFeedback* packet) { + RTC_DCHECK_RUNS_SERIALIZED(&pacer_race_); rtc::CritScope cs(&modules_crit_); // Prefer send modules. for (auto* rtp_module : rtp_send_modules_) { diff --git a/modules/pacing/packet_router.h b/modules/pacing/packet_router.h index 22a578c0bf8..9597896353f 100644 --- a/modules/pacing/packet_router.h +++ b/modules/pacing/packet_router.h @@ -91,6 +91,7 @@ class PacketRouter : public PacedSender::PacketSender, void UnsetActiveRembModule() RTC_EXCLUSIVE_LOCKS_REQUIRED(modules_crit_); void DetermineActiveRembModule() RTC_EXCLUSIVE_LOCKS_REQUIRED(modules_crit_); + rtc::RaceChecker pacer_race_; rtc::CriticalSection modules_crit_; // Rtp and Rtcp modules of the rtp senders. std::list rtp_send_modules_ RTC_GUARDED_BY(modules_crit_); diff --git a/modules/remote_bitrate_estimator/bwe_simulations.cc b/modules/remote_bitrate_estimator/bwe_simulations.cc index 87106f173af..f8866d81cb1 100644 --- a/modules/remote_bitrate_estimator/bwe_simulations.cc +++ b/modules/remote_bitrate_estimator/bwe_simulations.cc @@ -477,47 +477,47 @@ TEST_P(BweSimulation, Evaluation8) { RunPauseResumeFlows(GetParam()); } -// Following test cases begin with "GoogCcComparison" run the -// evaluation test cases for both GoogCc and other calling RMCAT. +// Following test cases begin with "GccComparison" run the +// evaluation test cases for both GCC and other calling RMCAT. -TEST_P(BweSimulation, GoogCcComparison1) { +TEST_P(BweSimulation, GccComparison1) { RunVariableCapacity1SingleFlow(GetParam()); - BweTest goog_cc_test(false); - goog_cc_test.RunVariableCapacity1SingleFlow(kSendSideEstimator); + BweTest gcc_test(false); + gcc_test.RunVariableCapacity1SingleFlow(kSendSideEstimator); } -TEST_P(BweSimulation, GoogCcComparison2) { +TEST_P(BweSimulation, GccComparison2) { const size_t kNumFlows = 2; RunVariableCapacity2MultipleFlows(GetParam(), kNumFlows); - BweTest goog_cc_test(false); - goog_cc_test.RunVariableCapacity2MultipleFlows(kSendSideEstimator, kNumFlows); + BweTest gcc_test(false); + gcc_test.RunVariableCapacity2MultipleFlows(kSendSideEstimator, kNumFlows); } -TEST_P(BweSimulation, GoogCcComparison3) { +TEST_P(BweSimulation, GccComparison3) { RunBidirectionalFlow(GetParam()); - BweTest goog_cc_test(false); - goog_cc_test.RunBidirectionalFlow(kSendSideEstimator); + BweTest gcc_test(false); + gcc_test.RunBidirectionalFlow(kSendSideEstimator); } -TEST_P(BweSimulation, GoogCcComparison4) { +TEST_P(BweSimulation, GccComparison4) { RunSelfFairness(GetParam()); - BweTest goog_cc_test(false); - goog_cc_test.RunSelfFairness(GetParam()); + BweTest gcc_test(false); + gcc_test.RunSelfFairness(GetParam()); } -TEST_P(BweSimulation, GoogCcComparison5) { +TEST_P(BweSimulation, GccComparison5) { RunRoundTripTimeFairness(GetParam()); - BweTest goog_cc_test(false); - goog_cc_test.RunRoundTripTimeFairness(kSendSideEstimator); + BweTest gcc_test(false); + gcc_test.RunRoundTripTimeFairness(kSendSideEstimator); } -TEST_P(BweSimulation, GoogCcComparison6) { +TEST_P(BweSimulation, GccComparison6) { RunLongTcpFairness(GetParam()); - BweTest goog_cc_test(false); - goog_cc_test.RunLongTcpFairness(kSendSideEstimator); + BweTest gcc_test(false); + gcc_test.RunLongTcpFairness(kSendSideEstimator); } -TEST_P(BweSimulation, GoogCcComparison7) { +TEST_P(BweSimulation, GccComparison7) { const int kNumTcpFiles = 10; std::vector tcp_file_sizes_bytes = @@ -528,24 +528,24 @@ TEST_P(BweSimulation, GoogCcComparison7) { RunMultipleShortTcpFairness(GetParam(), tcp_file_sizes_bytes, tcp_starting_times_ms); - BweTest goog_cc_test(false); - goog_cc_test.RunMultipleShortTcpFairness( - kSendSideEstimator, tcp_file_sizes_bytes, tcp_starting_times_ms); + BweTest gcc_test(false); + gcc_test.RunMultipleShortTcpFairness(kSendSideEstimator, tcp_file_sizes_bytes, + tcp_starting_times_ms); } -TEST_P(BweSimulation, GoogCcComparison8) { +TEST_P(BweSimulation, GccComparison8) { RunPauseResumeFlows(GetParam()); - BweTest goog_cc_test(false); - goog_cc_test.RunPauseResumeFlows(kSendSideEstimator); + BweTest gcc_test(false); + gcc_test.RunPauseResumeFlows(kSendSideEstimator); } -TEST_P(BweSimulation, GoogCcComparisonChoke) { +TEST_P(BweSimulation, GccComparisonChoke) { int array[] = {1000, 500, 1000}; std::vector capacities_kbps(array, array + 3); RunChoke(GetParam(), capacities_kbps); - BweTest goog_cc_test(false); - goog_cc_test.RunChoke(kSendSideEstimator, capacities_kbps); + BweTest gcc_test(false); + gcc_test.RunChoke(kSendSideEstimator, capacities_kbps); } } // namespace bwe diff --git a/modules/remote_bitrate_estimator/test/bwe.h b/modules/remote_bitrate_estimator/test/bwe.h index 9cc5063dc90..96aed21c6b4 100644 --- a/modules/remote_bitrate_estimator/test/bwe.h +++ b/modules/remote_bitrate_estimator/test/bwe.h @@ -181,8 +181,7 @@ enum BandwidthEstimatorType { kBbrEstimator }; -const char* const bwe_names[] = {"Null", "NADA", "REMB", - "GoogCc", "TCP", "BBR"}; +const char* const bwe_names[] = {"Null", "NADA", "REMB", "GCC", "TCP", "BBR"}; int64_t GetAbsSendTimeInMs(uint32_t abs_send_time); diff --git a/modules/remote_bitrate_estimator/test/estimators/send_side.cc b/modules/remote_bitrate_estimator/test/estimators/send_side.cc index 123def92ceb..6e03eee942d 100644 --- a/modules/remote_bitrate_estimator/test/estimators/send_side.cc +++ b/modules/remote_bitrate_estimator/test/estimators/send_side.cc @@ -32,7 +32,7 @@ SendSideBweSender::SendSideBweSender(int kbps, &event_log_)), acknowledged_bitrate_estimator_( rtc::MakeUnique()), - bwe_(new DelayBasedBwe(nullptr)), + bwe_(new DelayBasedBwe(nullptr, clock)), feedback_observer_(bitrate_controller_.get()), clock_(clock), send_time_history_(clock_, 10000), @@ -72,7 +72,7 @@ void SendSideBweSender::GiveFeedback(const FeedbackPacket& feedback) { int64_t rtt_ms = clock_->TimeInMilliseconds() - feedback.latest_send_time_ms(); - bwe_->OnRttUpdate(rtt_ms); + bwe_->OnRttUpdate(rtt_ms, rtt_ms); BWE_TEST_LOGGING_PLOT(1, "RTT", clock_->TimeInMilliseconds(), rtt_ms); std::sort(packet_feedback_vector.begin(), packet_feedback_vector.end(), @@ -80,8 +80,7 @@ void SendSideBweSender::GiveFeedback(const FeedbackPacket& feedback) { acknowledged_bitrate_estimator_->IncomingPacketFeedbackVector( packet_feedback_vector); DelayBasedBwe::Result result = bwe_->IncomingPacketFeedbackVector( - packet_feedback_vector, acknowledged_bitrate_estimator_->bitrate_bps(), - clock_->TimeInMilliseconds()); + packet_feedback_vector, acknowledged_bitrate_estimator_->bitrate_bps()); if (result.updated) bitrate_controller_->OnDelayBasedBweResult(result); diff --git a/modules/remote_bitrate_estimator/test/packet_sender.cc b/modules/remote_bitrate_estimator/test/packet_sender.cc index d45f363491d..08db1a3f551 100644 --- a/modules/remote_bitrate_estimator/test/packet_sender.cc +++ b/modules/remote_bitrate_estimator/test/packet_sender.cc @@ -24,9 +24,6 @@ namespace webrtc { namespace testing { namespace bwe { -namespace { -const float kPaceMultiplier = 2.5f; -} void PacketSender::Pause() { running_ = false; @@ -167,7 +164,7 @@ PacedVideoSender::PacedVideoSender(PacketProcessorListener* listener, ? static_cast(new BbrPacedSender(&clock_, this, nullptr)) : static_cast(new PacedSender(&clock_, this, nullptr))) { modules_.push_back(pacer_.get()); - pacer_->SetPacingRates(source->bits_per_second() * kPaceMultiplier, 0); + pacer_->SetEstimatedBitrate(source->bits_per_second()); } PacedVideoSender::~PacedVideoSender() { @@ -315,7 +312,7 @@ void PacedVideoSender::OnNetworkChanged(uint32_t target_bitrate_bps, uint8_t fraction_lost, int64_t rtt) { VideoSender::OnNetworkChanged(target_bitrate_bps, fraction_lost, rtt); - pacer_->SetPacingRates(target_bitrate_bps * kPaceMultiplier, 0); + pacer_->SetEstimatedBitrate(target_bitrate_bps); } void PacedVideoSender::OnNetworkChanged(uint32_t bitrate_for_encoder_bps, diff --git a/rtc_tools/BUILD.gn b/rtc_tools/BUILD.gn index 32a594b3dca..f04bd2dc3b7 100644 --- a/rtc_tools/BUILD.gn +++ b/rtc_tools/BUILD.gn @@ -231,6 +231,7 @@ if (!build_with_chromium) { "../modules/audio_coding:ana_debug_dump_proto", "../modules/audio_coding:audio_network_adaptor", "../modules/audio_coding:neteq_tools", + "../modules/congestion_controller:estimators", "../modules/rtp_rtcp:rtp_rtcp_format", "../rtc_base:checks", "../rtc_base:rtc_base_approved", @@ -239,8 +240,6 @@ if (!build_with_chromium) { # TODO(kwiberg): Remove this dependency. "../api/audio_codecs:audio_codecs_api", "../modules/congestion_controller", - "../modules/congestion_controller:delay_based_bwe", - "../modules/congestion_controller:estimators", "../modules/pacing", "../modules/rtp_rtcp", "../system_wrappers:system_wrappers_default", diff --git a/rtc_tools/event_log_visualizer/analyzer.cc b/rtc_tools/event_log_visualizer/analyzer.cc index 0310cd2769a..c32c676b380 100644 --- a/rtc_tools/event_log_visualizer/analyzer.cc +++ b/rtc_tools/event_log_visualizer/analyzer.cc @@ -33,7 +33,6 @@ #include "modules/audio_coding/neteq/tools/resample_input_audio_file.h" #include "modules/congestion_controller/acknowledged_bitrate_estimator.h" #include "modules/congestion_controller/bitrate_estimator.h" -#include "modules/congestion_controller/delay_based_bwe.h" #include "modules/congestion_controller/include/receive_side_congestion_controller.h" #include "modules/congestion_controller/include/send_side_congestion_controller.h" #include "modules/include/module_common_types.h" diff --git a/video/video_send_stream.cc b/video/video_send_stream.cc index 765ec424e0c..3d59bc25b97 100644 --- a/video/video_send_stream.cc +++ b/video/video_send_stream.cc @@ -839,7 +839,7 @@ VideoSendStreamImpl::VideoSendStreamImpl( } if (alr_settings) { transport->send_side_cc()->EnablePeriodicAlrProbing(true); - transport->send_side_cc()->SetPacingFactor(alr_settings->pacing_factor); + transport->pacer()->SetPacingFactor(alr_settings->pacing_factor); configured_pacing_factor_ = alr_settings->pacing_factor; transport->pacer()->SetQueueTimeLimit(alr_settings->max_paced_queue_time); }