Improve TCP implementation by adding ssthresh and make it possible to start it with an offset.
Add a propagation delay to tests and make the run-time configurable for the fairness tests. Handle losses in-between feedback messages. BUG=4549 R=pbos@webrtc.org Review URL: https://webrtc-codereview.appspot.com/49819004 Cr-Commit-Position: refs/heads/master@{#9099}
This commit is contained in:
		| @@ -87,7 +87,7 @@ TEST_P(BweSimulation, Choke1000kbps500kbps1000kbpsBiDirectional) { | ||||
|   PacketReceiver receiver2(&downlink_, kFlowIds[1], GetParam(), true, false); | ||||
|  | ||||
|   choke2.SetCapacity(500); | ||||
|   delay.SetDelay(0); | ||||
|   delay.SetDelayMs(0); | ||||
|  | ||||
|   choke.SetCapacity(1000); | ||||
|   choke.SetMaxDelay(500); | ||||
| @@ -240,13 +240,33 @@ TEST_P(BweSimulation, SelfFairnessTest) { | ||||
| TEST_P(BweSimulation, PacedSelfFairnessTest) { | ||||
|   VerboseLogging(true); | ||||
|   srand(Clock::GetRealTimeClock()->TimeInMicroseconds()); | ||||
|   RunFairnessTest(GetParam(), 4, 0, 2000); | ||||
|   RunFairnessTest(GetParam(), 4, 0, 1000, 3000, 50); | ||||
| } | ||||
|  | ||||
| TEST_P(BweSimulation, PacedTcpFairnessTest) { | ||||
|   VerboseLogging(true); | ||||
|   srand(Clock::GetRealTimeClock()->TimeInMicroseconds()); | ||||
|   RunFairnessTest(GetParam(), 1, 1, 3000); | ||||
|   RunFairnessTest(GetParam(), 4, 0, 1000, 3000, 500); | ||||
| } | ||||
|  | ||||
| TEST_P(BweSimulation, PacedSelfFairness1000msTest) { | ||||
|   srand(Clock::GetRealTimeClock()->TimeInMicroseconds()); | ||||
|   RunFairnessTest(GetParam(), 4, 0, 1000, 3000, 1000); | ||||
| } | ||||
|  | ||||
| TEST_P(BweSimulation, TcpFairness50msTest) { | ||||
|   srand(Clock::GetRealTimeClock()->TimeInMicroseconds()); | ||||
|   RunFairnessTest(GetParam(), 1, 1, 1000, 2000, 50); | ||||
| } | ||||
|  | ||||
| TEST_P(BweSimulation, TcpFairness500msTest) { | ||||
|   srand(Clock::GetRealTimeClock()->TimeInMicroseconds()); | ||||
|   RunFairnessTest(GetParam(), 1, 1, 1000, 2000, 500); | ||||
| } | ||||
|  | ||||
| TEST_P(BweSimulation, TcpFairness1000msTest) { | ||||
|   srand(Clock::GetRealTimeClock()->TimeInMicroseconds()); | ||||
|   RunFairnessTest(GetParam(), 1, 1, 1000, 2000, 1000); | ||||
| } | ||||
| #endif  // BWE_TEST_LOGGING_COMPILE_TIME_ENABLE | ||||
| }  // namespace bwe | ||||
|   | ||||
| @@ -65,7 +65,7 @@ TEST_P(DefaultBweTest, SteadyDelay) { | ||||
|   VideoSender sender(&uplink_, &source, GetParam()); | ||||
|   DelayFilter delay(&uplink_, 0); | ||||
|   PacketReceiver receiver(&uplink_, 0, GetParam(), false, false); | ||||
|   delay.SetDelay(1000); | ||||
|   delay.SetDelayMs(1000); | ||||
|   RunFor(10 * 60 * 1000); | ||||
| } | ||||
|  | ||||
| @@ -76,7 +76,7 @@ TEST_P(DefaultBweTest, IncreasingDelay1) { | ||||
|   PacketReceiver receiver(&uplink_, 0, GetParam(), false, false); | ||||
|   RunFor(10 * 60 * 1000); | ||||
|   for (int i = 0; i < 30 * 2; ++i) { | ||||
|     delay.SetDelay(i); | ||||
|     delay.SetDelayMs(i); | ||||
|     RunFor(10 * 1000); | ||||
|   } | ||||
|   RunFor(10 * 60 * 1000); | ||||
| @@ -90,10 +90,10 @@ TEST_P(DefaultBweTest, IncreasingDelay2) { | ||||
|   PacketReceiver receiver(&uplink_, 0, GetParam(), false, false); | ||||
|   RunFor(1 * 60 * 1000); | ||||
|   for (int i = 1; i < 51; ++i) { | ||||
|     delay.SetDelay(10.0f * i); | ||||
|     delay.SetDelayMs(10.0f * i); | ||||
|     RunFor(10 * 1000); | ||||
|   } | ||||
|   delay.SetDelay(0.0f); | ||||
|   delay.SetDelayMs(0.0f); | ||||
|   RunFor(10 * 60 * 1000); | ||||
| } | ||||
|  | ||||
| @@ -104,12 +104,12 @@ TEST_P(DefaultBweTest, JumpyDelay1) { | ||||
|   PacketReceiver receiver(&uplink_, 0, GetParam(), false, false); | ||||
|   RunFor(10 * 60 * 1000); | ||||
|   for (int i = 1; i < 200; ++i) { | ||||
|     delay.SetDelay((10 * i) % 500); | ||||
|     delay.SetDelayMs((10 * i) % 500); | ||||
|     RunFor(1000); | ||||
|     delay.SetDelay(1.0f); | ||||
|     delay.SetDelayMs(1.0f); | ||||
|     RunFor(1000); | ||||
|   } | ||||
|   delay.SetDelay(0.0f); | ||||
|   delay.SetDelayMs(0.0f); | ||||
|   RunFor(10 * 60 * 1000); | ||||
| } | ||||
|  | ||||
| @@ -211,11 +211,11 @@ TEST_P(DefaultBweTest, Multi1) { | ||||
|   choke.SetCapacity(1000); | ||||
|   RunFor(1 * 60 * 1000); | ||||
|   for (int i = 1; i < 51; ++i) { | ||||
|     delay.SetDelay(100.0f * i); | ||||
|     delay.SetDelayMs(100.0f * i); | ||||
|     RunFor(10 * 1000); | ||||
|   } | ||||
|   RunFor(500 * 1000); | ||||
|   delay.SetDelay(0.0f); | ||||
|   delay.SetDelayMs(0.0f); | ||||
|   RunFor(5 * 60 * 1000); | ||||
| } | ||||
|  | ||||
| @@ -254,7 +254,7 @@ INSTANTIATE_TEST_CASE_P(VideoSendersTest, | ||||
|  | ||||
| TEST_P(BweFeedbackTest, Choke1000kbps500kbps1000kbps) { | ||||
|   AdaptiveVideoSource source(0, 30, 300, 0, 0); | ||||
|   VideoSender sender(&uplink_, &source, GetParam()); | ||||
|   PacedVideoSender sender(&uplink_, &source, GetParam()); | ||||
|   ChokeFilter filter(&uplink_, 0); | ||||
|   RateCounterFilter counter(&uplink_, 0, "receiver_input"); | ||||
|   PacketReceiver receiver(&uplink_, 0, GetParam(), false, false); | ||||
| @@ -274,7 +274,7 @@ TEST_P(BweFeedbackTest, Choke1000kbps500kbps1000kbps) { | ||||
|  | ||||
| TEST_P(BweFeedbackTest, Choke200kbps30kbps200kbps) { | ||||
|   AdaptiveVideoSource source(0, 30, 300, 0, 0); | ||||
|   VideoSender sender(&uplink_, &source, GetParam()); | ||||
|   PacedVideoSender sender(&uplink_, &source, GetParam()); | ||||
|   ChokeFilter filter(&uplink_, 0); | ||||
|   RateCounterFilter counter(&uplink_, 0, "receiver_input"); | ||||
|   PacketReceiver receiver(&uplink_, 0, GetParam(), false, false); | ||||
| @@ -323,12 +323,27 @@ TEST_P(BweFeedbackTest, DISABLED_GoogleWifiTrace3Mbps) { | ||||
|  | ||||
| TEST_P(BweFeedbackTest, PacedSelfFairnessTest) { | ||||
|   srand(Clock::GetRealTimeClock()->TimeInMicroseconds()); | ||||
|   RunFairnessTest(GetParam(), 4, 0, 3000); | ||||
|   RunFairnessTest(GetParam(), 4, 0, 300, 3000, 50); | ||||
| } | ||||
|  | ||||
| TEST_P(BweFeedbackTest, TcpFairnessTest) { | ||||
| TEST_P(BweFeedbackTest, PacedSelfFairness1000msTest) { | ||||
|   srand(Clock::GetRealTimeClock()->TimeInMicroseconds()); | ||||
|   RunFairnessTest(GetParam(), 1, 1, 2000); | ||||
|   RunFairnessTest(GetParam(), 4, 0, 300, 3000, 1000); | ||||
| } | ||||
|  | ||||
| TEST_P(BweFeedbackTest, TcpFairness50msTest) { | ||||
|   srand(Clock::GetRealTimeClock()->TimeInMicroseconds()); | ||||
|   RunFairnessTest(GetParam(), 1, 1, 300, 2000, 50); | ||||
| } | ||||
|  | ||||
| TEST_P(BweFeedbackTest, TcpFairness500msTest) { | ||||
|   srand(Clock::GetRealTimeClock()->TimeInMicroseconds()); | ||||
|   RunFairnessTest(GetParam(), 1, 1, 300, 2000, 500); | ||||
| } | ||||
|  | ||||
| TEST_P(BweFeedbackTest, TcpFairness1000msTest) { | ||||
|   srand(Clock::GetRealTimeClock()->TimeInMicroseconds()); | ||||
|   RunFairnessTest(GetParam(), 1, 1, 300, 2000, 1000); | ||||
| } | ||||
| }  // namespace bwe | ||||
| }  // namespace testing | ||||
|   | ||||
| @@ -21,7 +21,7 @@ namespace testing { | ||||
| namespace bwe { | ||||
|  | ||||
| const int kMinBitrateKbps = 150; | ||||
| const int kMaxBitrateKbps = 2000; | ||||
| const int kMaxBitrateKbps = 3000; | ||||
|  | ||||
| class BweSender : public Module { | ||||
|  public: | ||||
|   | ||||
| @@ -192,14 +192,16 @@ void BweTest::PrintResults( | ||||
|   webrtc::test::PrintResultMeanAndError("BwePerformance", GetTestName(), | ||||
|                                         "Average delay", delay_ms.AsString(), | ||||
|                                         "ms", false); | ||||
|   double fairness_index = 0.0; | ||||
|   double squared_bitrate_sum = 0.0; | ||||
|   for (Stats<double> flow : flow_throughput_kbps) { | ||||
|     squared_bitrate_sum += flow.GetMean() * flow.GetMean(); | ||||
|     fairness_index += flow.GetMean(); | ||||
|   double fairness_index = 1.0; | ||||
|   if (!flow_throughput_kbps.empty()) { | ||||
|     double squared_bitrate_sum = 0.0; | ||||
|     for (Stats<double> flow : flow_throughput_kbps) { | ||||
|       squared_bitrate_sum += flow.GetMean() * flow.GetMean(); | ||||
|       fairness_index += flow.GetMean(); | ||||
|     } | ||||
|     fairness_index *= fairness_index; | ||||
|     fairness_index /= flow_throughput_kbps.size() * squared_bitrate_sum; | ||||
|   } | ||||
|   fairness_index *= fairness_index; | ||||
|   fairness_index /= flow_throughput_kbps.size() * squared_bitrate_sum; | ||||
|   webrtc::test::PrintResult("BwePerformance", GetTestName(), "Fairness", | ||||
|                             fairness_index * 100, "%", false); | ||||
| } | ||||
| @@ -207,7 +209,9 @@ void BweTest::PrintResults( | ||||
| void BweTest::RunFairnessTest(BandwidthEstimatorType bwe_type, | ||||
|                               size_t num_media_flows, | ||||
|                               size_t num_tcp_flows, | ||||
|                               int capacity_kbps) { | ||||
|                               int64_t run_time_seconds, | ||||
|                               int capacity_kbps, | ||||
|                               int max_delay_ms) { | ||||
|   std::set<int> all_flow_ids; | ||||
|   std::set<int> media_flow_ids; | ||||
|   std::set<int> tcp_flow_ids; | ||||
| @@ -230,17 +234,22 @@ void BweTest::RunFairnessTest(BandwidthEstimatorType bwe_type, | ||||
|   for (int media_flow : media_flow_ids) { | ||||
|     // Streams started 20 seconds apart to give them different advantage when | ||||
|     // competing for the bandwidth. | ||||
|     const int64_t kFlowStartOffsetMs = i++ * (rand() % 40000); | ||||
|     sources.push_back(new AdaptiveVideoSource(media_flow, 30, 300, 0, | ||||
|                                               i++ * (rand() % 40000))); | ||||
|                                               kFlowStartOffsetMs)); | ||||
|     senders.push_back(new PacedVideoSender(&uplink_, sources.back(), bwe_type)); | ||||
|   } | ||||
|  | ||||
|   const int64_t kTcpStartOffsetMs = 20000; | ||||
|   for (int tcp_flow : tcp_flow_ids) | ||||
|     senders.push_back(new TcpSender(&uplink_, tcp_flow)); | ||||
|     senders.push_back(new TcpSender(&uplink_, tcp_flow, kTcpStartOffsetMs)); | ||||
|  | ||||
|   ChokeFilter choke(&uplink_, all_flow_ids); | ||||
|   choke.SetCapacity(capacity_kbps); | ||||
|   choke.SetMaxDelay(1000); | ||||
|   choke.SetMaxDelay(max_delay_ms); | ||||
|  | ||||
|   DelayFilter delay_uplink(&uplink_, all_flow_ids); | ||||
|   delay_uplink.SetDelayMs(25); | ||||
|  | ||||
|   std::vector<RateCounterFilter*> rate_counters; | ||||
|   for (int flow : all_flow_ids) { | ||||
| @@ -262,7 +271,10 @@ void BweTest::RunFairnessTest(BandwidthEstimatorType bwe_type, | ||||
|         new PacketReceiver(&uplink_, tcp_flow, kTcpEstimator, false, false)); | ||||
|   } | ||||
|  | ||||
|   RunFor(15 * 60 * 1000); | ||||
|   DelayFilter delay_downlink(&downlink_, all_flow_ids); | ||||
|   delay_downlink.SetDelayMs(25); | ||||
|  | ||||
|   RunFor(run_time_seconds * 1000); | ||||
|  | ||||
|   std::vector<Stats<double>> flow_throughput_kbps; | ||||
|   for (i = 0; i < all_flow_ids.size(); ++i) | ||||
|   | ||||
| @@ -84,7 +84,9 @@ class BweTest { | ||||
|   void RunFairnessTest(BandwidthEstimatorType bwe_type, | ||||
|                        size_t num_media_flows, | ||||
|                        size_t num_tcp_flows, | ||||
|                        int capacity_kbps); | ||||
|                        int64_t run_time_seconds, | ||||
|                        int capacity_kbps, | ||||
|                        int max_delay_ms); | ||||
|  | ||||
|   Link downlink_; | ||||
|   Link uplink_; | ||||
|   | ||||
| @@ -341,7 +341,7 @@ DelayFilter::DelayFilter(PacketProcessorListener* listener, | ||||
|       last_send_time_us_(0) { | ||||
| } | ||||
|  | ||||
| void DelayFilter::SetDelay(int64_t delay_ms) { | ||||
| void DelayFilter::SetDelayMs(int64_t delay_ms) { | ||||
|   BWE_TEST_LOGGING_ENABLE(false); | ||||
|   BWE_TEST_LOGGING_LOG1("Delay", "%d ms", static_cast<int>(delay_ms)); | ||||
|   assert(delay_ms >= 0); | ||||
|   | ||||
| @@ -254,7 +254,7 @@ class DelayFilter : public PacketProcessor { | ||||
|   DelayFilter(PacketProcessorListener* listener, const FlowIds& flow_ids); | ||||
|   virtual ~DelayFilter() {} | ||||
|  | ||||
|   void SetDelay(int64_t delay_ms); | ||||
|   void SetDelayMs(int64_t delay_ms); | ||||
|   virtual void RunFor(int64_t time_ms, Packets* in_out); | ||||
|  | ||||
|  private: | ||||
|   | ||||
| @@ -333,7 +333,7 @@ class BweTestFramework_DelayFilterTest : public ::testing::Test { | ||||
|   } | ||||
|  | ||||
|   void TestDelayFilter(int64_t delay_ms) { | ||||
|     filter_.SetDelay(delay_ms); | ||||
|     filter_.SetDelayMs(delay_ms); | ||||
|     TestDelayFilter(1, 0, 0);    // No input should yield no output | ||||
|  | ||||
|     // Single packet | ||||
| @@ -341,7 +341,7 @@ class BweTestFramework_DelayFilterTest : public ::testing::Test { | ||||
|     TestDelayFilter(delay_ms, 0, 0); | ||||
|  | ||||
|     for (int i = 0; i < delay_ms; ++i) { | ||||
|       filter_.SetDelay(i); | ||||
|       filter_.SetDelayMs(i); | ||||
|       TestDelayFilter(1, 10, 10); | ||||
|     } | ||||
|     TestDelayFilter(0, 0, 0); | ||||
| @@ -351,11 +351,11 @@ class BweTestFramework_DelayFilterTest : public ::testing::Test { | ||||
|     TestDelayFilter(delay_ms, 0, 0); | ||||
|  | ||||
|     for (int i = 1; i < delay_ms + 1; ++i) { | ||||
|       filter_.SetDelay(i); | ||||
|       filter_.SetDelayMs(i); | ||||
|       TestDelayFilter(1, 5, 5); | ||||
|     } | ||||
|     TestDelayFilter(0, 0, 0); | ||||
|     filter_.SetDelay(2 * delay_ms); | ||||
|     filter_.SetDelayMs(2 * delay_ms); | ||||
|     TestDelayFilter(1, 0, 0); | ||||
|     TestDelayFilter(delay_ms, 13, 13); | ||||
|     TestDelayFilter(delay_ms, 0, 0); | ||||
| @@ -364,11 +364,11 @@ class BweTestFramework_DelayFilterTest : public ::testing::Test { | ||||
|     TestDelayFilter(delay_ms, 0, 0); | ||||
|  | ||||
|     for (int i = 0; i < 2 * delay_ms; ++i) { | ||||
|       filter_.SetDelay(2 * delay_ms - i - 1); | ||||
|       filter_.SetDelayMs(2 * delay_ms - i - 1); | ||||
|       TestDelayFilter(1, 5, 5); | ||||
|     } | ||||
|     TestDelayFilter(0, 0, 0); | ||||
|     filter_.SetDelay(0); | ||||
|     filter_.SetDelayMs(0); | ||||
|     TestDelayFilter(0, 7, 7); | ||||
|  | ||||
|     ASSERT_TRUE(IsTimeSorted(accumulated_packets_)); | ||||
| @@ -389,7 +389,7 @@ TEST_F(BweTestFramework_DelayFilterTest, Delay0) { | ||||
|   TestDelayFilter(1, 0, 0);    // No input should yield no output | ||||
|   TestDelayFilter(1, 10, 10);  // Expect no delay (delay time is zero) | ||||
|   TestDelayFilter(1, 0, 0);    // Check no packets are still in buffer | ||||
|   filter_.SetDelay(0); | ||||
|   filter_.SetDelayMs(0); | ||||
|   TestDelayFilter(1, 5, 5);    // Expect no delay (delay time is zero) | ||||
|   TestDelayFilter(1, 0, 0);    // Check no packets are still in buffer | ||||
| } | ||||
| @@ -416,7 +416,7 @@ TEST_F(BweTestFramework_DelayFilterTest, JumpToZeroDelay) { | ||||
|   Packets packets; | ||||
|  | ||||
|   // Delay a bunch of packets, accumulate them to the 'acc' list. | ||||
|   delay.SetDelay(100.0f); | ||||
|   delay.SetDelayMs(100.0f); | ||||
|   for (uint32_t i = 0; i < 10; ++i) { | ||||
|     packets.push_back(new MediaPacket(i * 100, i)); | ||||
|   } | ||||
| @@ -427,7 +427,7 @@ TEST_F(BweTestFramework_DelayFilterTest, JumpToZeroDelay) { | ||||
|  | ||||
|   // Drop delay to zero, send a few more packets through the delay, append them | ||||
|   // to the 'acc' list and verify that it is all sorted. | ||||
|   delay.SetDelay(0.0f); | ||||
|   delay.SetDelayMs(0.0f); | ||||
|   for (uint32_t i = 10; i < 50; ++i) { | ||||
|     packets.push_back(new MediaPacket(i * 100, i)); | ||||
|   } | ||||
| @@ -446,12 +446,12 @@ TEST_F(BweTestFramework_DelayFilterTest, IncreasingDelay) { | ||||
|     TestDelayFilter(i); | ||||
|   } | ||||
|   // Reach a steady state. | ||||
|   filter_.SetDelay(100); | ||||
|   filter_.SetDelayMs(100); | ||||
|   TestDelayFilter(1, 20, 20); | ||||
|   TestDelayFilter(2, 0, 0); | ||||
|   TestDelayFilter(99, 20, 20); | ||||
|   // Drop delay back down to zero. | ||||
|   filter_.SetDelay(0); | ||||
|   filter_.SetDelayMs(0); | ||||
|   TestDelayFilter(1, 100, 100); | ||||
|   TestDelayFilter(23010, 0, 0); | ||||
|   ASSERT_TRUE(IsTimeSorted(accumulated_packets_)); | ||||
|   | ||||
| @@ -11,6 +11,7 @@ | ||||
| #include "webrtc/modules/remote_bitrate_estimator/test/estimators/send_side.h" | ||||
|  | ||||
| #include "webrtc/base/logging.h" | ||||
| #include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h" | ||||
|  | ||||
| namespace webrtc { | ||||
| namespace testing { | ||||
| @@ -23,7 +24,9 @@ FullBweSender::FullBweSender(int kbps, BitrateObserver* observer, Clock* clock) | ||||
|                .Create(this, clock, kAimdControl, 1000 * kMinBitrateKbps)), | ||||
|       feedback_observer_(bitrate_controller_->CreateRtcpBandwidthObserver()), | ||||
|       clock_(clock), | ||||
|       send_time_history_(10000) { | ||||
|       send_time_history_(10000), | ||||
|       has_received_ack_(false), | ||||
|       last_acked_seq_num_(0) { | ||||
|   assert(kbps >= kMinBitrateKbps); | ||||
|   assert(kbps <= kMaxBitrateKbps); | ||||
|   bitrate_controller_->SetStartBitrate(1000 * kbps); | ||||
| @@ -51,23 +54,32 @@ void FullBweSender::GiveFeedback(const FeedbackPacket& feedback) { | ||||
|       LOG(LS_WARNING) << "Ack arrived too late."; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   rbe_->IncomingPacketFeedbackVector(packet_feedback_vector); | ||||
|   // TODO(holmer): Handle losses in between feedback packets. | ||||
|   int expected_packets = fb.packet_feedback_vector().back().sequence_number - | ||||
|                          fb.packet_feedback_vector().front().sequence_number + | ||||
|                          1; | ||||
|   // Assuming no reordering for now. | ||||
|   if (expected_packets <= 0) | ||||
|     return; | ||||
|   int lost_packets = | ||||
|       expected_packets - static_cast<int>(fb.packet_feedback_vector().size()); | ||||
|   report_block_.fractionLost = (lost_packets << 8) / expected_packets; | ||||
|   report_block_.cumulativeLost += lost_packets; | ||||
|   ReportBlockList report_blocks; | ||||
|   report_blocks.push_back(report_block_); | ||||
|   feedback_observer_->OnReceivedRtcpReceiverReport( | ||||
|       report_blocks, 0, clock_->TimeInMilliseconds()); | ||||
|   bitrate_controller_->Process(); | ||||
|   if (has_received_ack_) { | ||||
|     int expected_packets = fb.packet_feedback_vector().back().sequence_number - | ||||
|                            last_acked_seq_num_; | ||||
|     // Assuming no reordering for now. | ||||
|     if (expected_packets > 0) { | ||||
|       int lost_packets = expected_packets - | ||||
|                          static_cast<int>(fb.packet_feedback_vector().size()); | ||||
|       report_block_.fractionLost = (lost_packets << 8) / expected_packets; | ||||
|       report_block_.cumulativeLost += lost_packets; | ||||
|       report_block_.extendedHighSeqNum = | ||||
|           packet_feedback_vector.back().sequence_number; | ||||
|       ReportBlockList report_blocks; | ||||
|       report_blocks.push_back(report_block_); | ||||
|       feedback_observer_->OnReceivedRtcpReceiverReport( | ||||
|           report_blocks, 0, clock_->TimeInMilliseconds()); | ||||
|     } | ||||
|     bitrate_controller_->Process(); | ||||
|  | ||||
|     last_acked_seq_num_ = LatestSequenceNumber( | ||||
|         packet_feedback_vector.back().sequence_number, last_acked_seq_num_); | ||||
|   } else { | ||||
|     last_acked_seq_num_ = packet_feedback_vector.back().sequence_number; | ||||
|     has_received_ack_ = true; | ||||
|   } | ||||
| } | ||||
|  | ||||
| void FullBweSender::OnPacketsSent(const Packets& packets) { | ||||
|   | ||||
| @@ -42,6 +42,8 @@ class FullBweSender : public BweSender, public RemoteBitrateObserver { | ||||
|   Clock* const clock_; | ||||
|   RTCPReportBlock report_block_; | ||||
|   SendTimeHistory send_time_history_; | ||||
|   bool has_received_ack_; | ||||
|   uint16_t last_acked_seq_num_; | ||||
|  | ||||
|   DISALLOW_IMPLICIT_CONSTRUCTORS(FullBweSender); | ||||
| }; | ||||
|   | ||||
| @@ -138,8 +138,10 @@ void PacedVideoSender::RunFor(int64_t time_ms, Packets* in_out) { | ||||
|     int64_t time_until_process_ms = TimeUntilNextProcess(modules_); | ||||
|     int64_t time_until_feedback_ms = time_ms; | ||||
|     if (!feedbacks.empty()) | ||||
|       time_until_feedback_ms = feedbacks.front()->send_time_us() / 1000 - | ||||
|                                clock_.TimeInMilliseconds(); | ||||
|       time_until_feedback_ms = | ||||
|           std::max<int64_t>(feedbacks.front()->send_time_us() / 1000 - | ||||
|                                 clock_.TimeInMilliseconds(), | ||||
|                             0); | ||||
|  | ||||
|     int64_t time_until_next_event_ms = | ||||
|         std::min(time_until_feedback_ms, time_until_process_ms); | ||||
| @@ -265,6 +267,10 @@ void PacedVideoSender::OnNetworkChanged(uint32_t target_bitrate_bps, | ||||
| } | ||||
|  | ||||
| void TcpSender::RunFor(int64_t time_ms, Packets* in_out) { | ||||
|   if (now_ms_ + time_ms < offset_ms_) { | ||||
|     now_ms_ += time_ms; | ||||
|     return; | ||||
|   } | ||||
|   BWE_TEST_LOGGING_CONTEXT("Sender"); | ||||
|   BWE_TEST_LOGGING_CONTEXT(*flow_ids().begin()); | ||||
|   std::list<FeedbackPacket*> feedbacks = | ||||
| @@ -277,13 +283,6 @@ void TcpSender::RunFor(int64_t time_ms, Packets* in_out) { | ||||
|     SendPackets(in_out); | ||||
|   } | ||||
|  | ||||
|   for (auto it = in_flight_.begin(); it != in_flight_.end();) { | ||||
|     if (it->time_ms < now_ms_ - 1000) | ||||
|       in_flight_.erase(it++); | ||||
|     else | ||||
|       ++it; | ||||
|   } | ||||
|  | ||||
|   SendPackets(in_out); | ||||
|   now_ms_ += time_ms; | ||||
| } | ||||
| @@ -291,6 +290,10 @@ void TcpSender::RunFor(int64_t time_ms, Packets* in_out) { | ||||
| void TcpSender::SendPackets(Packets* in_out) { | ||||
|   int cwnd = ceil(cwnd_); | ||||
|   int packets_to_send = std::max(cwnd - static_cast<int>(in_flight_.size()), 0); | ||||
|   int timed_out = TriggerTimeouts(); | ||||
|   if (timed_out > 0) { | ||||
|     HandleLoss(); | ||||
|   } | ||||
|   if (packets_to_send > 0) { | ||||
|     Packets generated = GeneratePackets(packets_to_send); | ||||
|     for (Packet* packet : generated) | ||||
| @@ -312,9 +315,8 @@ void TcpSender::UpdateCongestionControl(const FeedbackPacket* fb) { | ||||
|     in_flight_.erase(InFlight(ack_seq_num, now_ms_)); | ||||
|  | ||||
|   if (missing > 0) { | ||||
|     cwnd_ /= 2.0f; | ||||
|     in_slow_start_ = false; | ||||
|   } else if (in_slow_start_) { | ||||
|     HandleLoss(); | ||||
|   } else if (cwnd_ <= ssthresh_) { | ||||
|     cwnd_ += tcp_fb->acked_packets().size(); | ||||
|   } else { | ||||
|     cwnd_ += 1.0f / cwnd_; | ||||
| @@ -324,6 +326,24 @@ void TcpSender::UpdateCongestionControl(const FeedbackPacket* fb) { | ||||
|       LatestSequenceNumber(tcp_fb->acked_packets().back(), last_acked_seq_num_); | ||||
| } | ||||
|  | ||||
| int TcpSender::TriggerTimeouts() { | ||||
|   int timed_out = 0; | ||||
|   for (auto it = in_flight_.begin(); it != in_flight_.end();) { | ||||
|     if (it->time_ms < now_ms_ - 1000) { | ||||
|       in_flight_.erase(it++); | ||||
|       ++timed_out; | ||||
|     } else { | ||||
|       ++it; | ||||
|     } | ||||
|   } | ||||
|   return timed_out; | ||||
| } | ||||
|  | ||||
| void TcpSender::HandleLoss() { | ||||
|   ssthresh_ = std::max(static_cast<int>(in_flight_.size() / 2), 2); | ||||
|   cwnd_ = ssthresh_; | ||||
| } | ||||
|  | ||||
| Packets TcpSender::GeneratePackets(size_t num_packets) { | ||||
|   Packets generated; | ||||
|   for (size_t i = 0; i < num_packets; ++i) { | ||||
|   | ||||
| @@ -12,6 +12,7 @@ | ||||
| #define WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_PACKET_SENDER_H_ | ||||
|  | ||||
| #include <list> | ||||
| #include <limits> | ||||
| #include <string> | ||||
|  | ||||
| #include "webrtc/base/constructormagic.h" | ||||
| @@ -104,14 +105,15 @@ class PacedVideoSender : public VideoSender, public PacedSender::Callback { | ||||
|  | ||||
| class TcpSender : public PacketSender { | ||||
|  public: | ||||
|   TcpSender(PacketProcessorListener* listener, int flow_id) | ||||
|   TcpSender(PacketProcessorListener* listener, int flow_id, int64_t offset_ms) | ||||
|       : PacketSender(listener, flow_id), | ||||
|         now_ms_(0), | ||||
|         in_slow_start_(false), | ||||
|         cwnd_(10), | ||||
|         ssthresh_(std::numeric_limits<int>::max()), | ||||
|         ack_received_(false), | ||||
|         last_acked_seq_num_(0), | ||||
|         next_sequence_number_(0) {} | ||||
|         next_sequence_number_(0), | ||||
|         offset_ms_(offset_ms) {} | ||||
|  | ||||
|   virtual ~TcpSender() {} | ||||
|  | ||||
| @@ -140,15 +142,18 @@ class TcpSender : public PacketSender { | ||||
|  | ||||
|   void SendPackets(Packets* in_out); | ||||
|   void UpdateCongestionControl(const FeedbackPacket* fb); | ||||
|   int TriggerTimeouts(); | ||||
|   void HandleLoss(); | ||||
|   Packets GeneratePackets(size_t num_packets); | ||||
|  | ||||
|   int64_t now_ms_; | ||||
|   bool in_slow_start_; | ||||
|   float cwnd_; | ||||
|   int ssthresh_; | ||||
|   std::set<InFlight> in_flight_; | ||||
|   bool ack_received_; | ||||
|   uint16_t last_acked_seq_num_; | ||||
|   uint16_t next_sequence_number_; | ||||
|   int64_t offset_ms_; | ||||
| }; | ||||
| }  // namespace bwe | ||||
| }  // namespace testing | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Stefan Holmer
					Stefan Holmer