diff --git a/webrtc/modules/modules.gyp b/webrtc/modules/modules.gyp index c004d5a3f5..1bf8466ecc 100644 --- a/webrtc/modules/modules.gyp +++ b/webrtc/modules/modules.gyp @@ -241,6 +241,8 @@ 'remote_bitrate_estimator/test/estimators/remb.h', 'remote_bitrate_estimator/test/estimators/send_side.cc', 'remote_bitrate_estimator/test/estimators/send_side.h', + 'remote_bitrate_estimator/test/estimators/tcp.cc', + 'remote_bitrate_estimator/test/estimators/tcp.h', 'rtp_rtcp/source/mock/mock_rtp_payload_strategy.h', 'rtp_rtcp/source/byte_io_unittest.cc', 'rtp_rtcp/source/fec_receiver_unittest.cc', diff --git a/webrtc/modules/remote_bitrate_estimator/bwe_simulations.cc b/webrtc/modules/remote_bitrate_estimator/bwe_simulations.cc index df82764a6c..201c91570d 100644 --- a/webrtc/modules/remote_bitrate_estimator/bwe_simulations.cc +++ b/webrtc/modules/remote_bitrate_estimator/bwe_simulations.cc @@ -46,7 +46,7 @@ INSTANTIATE_TEST_CASE_P(VideoSendersTest, TEST_P(BweSimulation, SprintUplinkTest) { VerboseLogging(true); AdaptiveVideoSource source(0, 30, 300, 0, 0); - PacketSender sender(&uplink_, &source, GetParam()); + VideoSender sender(&uplink_, &source, GetParam()); RateCounterFilter counter1(&uplink_, 0, "sender_output"); TraceBasedDeliveryFilter filter(&uplink_, 0, "link_capacity"); RateCounterFilter counter2(&uplink_, 0, "receiver_input"); @@ -58,7 +58,7 @@ TEST_P(BweSimulation, SprintUplinkTest) { TEST_P(BweSimulation, Verizon4gDownlinkTest) { VerboseLogging(true); AdaptiveVideoSource source(0, 30, 300, 0, 0); - PacketSender sender(&downlink_, &source, GetParam()); + VideoSender sender(&downlink_, &source, GetParam()); RateCounterFilter counter1(&downlink_, 0, "sender_output"); TraceBasedDeliveryFilter filter(&downlink_, 0, "link_capacity"); RateCounterFilter counter2(&downlink_, 0, "receiver_input"); @@ -74,13 +74,13 @@ TEST_P(BweSimulation, Choke1000kbps500kbps1000kbpsBiDirectional) { const size_t kNumFlows = sizeof(kFlowIds) / sizeof(kFlowIds[0]); AdaptiveVideoSource source(kFlowIds[0], 30, 300, 0, 0); - PacketSender sender(&uplink_, &source, GetParam()); + VideoSender sender(&uplink_, &source, GetParam()); ChokeFilter choke(&uplink_, kFlowIds[0]); RateCounterFilter counter(&uplink_, kFlowIds[0], "receiver_input_0"); PacketReceiver receiver(&uplink_, kFlowIds[0], GetParam(), true, false); AdaptiveVideoSource source2(kFlowIds[1], 30, 300, 0, 0); - PacketSender sender2(&downlink_, &source2, GetParam()); + VideoSender sender2(&downlink_, &source2, GetParam()); ChokeFilter choke2(&downlink_, kFlowIds[1]); DelayFilter delay(&downlink_, CreateFlowIds(kFlowIds, kNumFlows)); RateCounterFilter counter2(&downlink_, kFlowIds[1], "receiver_input_1"); @@ -102,7 +102,7 @@ TEST_P(BweSimulation, Choke1000kbps500kbps1000kbps) { VerboseLogging(true); AdaptiveVideoSource source(0, 30, 300, 0, 0); - PacketSender sender(&uplink_, &source, GetParam()); + VideoSender sender(&uplink_, &source, GetParam()); ChokeFilter choke(&uplink_, 0); RateCounterFilter counter(&uplink_, 0, "receiver_input"); PacketReceiver receiver(&uplink_, 0, GetParam(), true, false); @@ -163,7 +163,7 @@ TEST_P(BweSimulation, PacerChoke200kbps30kbps200kbps) { TEST_P(BweSimulation, Choke200kbps30kbps200kbps) { VerboseLogging(true); AdaptiveVideoSource source(0, 30, 300, 0, 0); - PacketSender sender(&uplink_, &source, GetParam()); + VideoSender sender(&uplink_, &source, GetParam()); ChokeFilter filter(&uplink_, 0); RateCounterFilter counter(&uplink_, 0, "receiver_input"); PacketReceiver receiver(&uplink_, 0, GetParam(), true, true); @@ -179,7 +179,7 @@ TEST_P(BweSimulation, Choke200kbps30kbps200kbps) { TEST_P(BweSimulation, GoogleWifiTrace3Mbps) { VerboseLogging(true); AdaptiveVideoSource source(0, 30, 300, 0, 0); - PacketSender sender(&uplink_, &source, kRembEstimator); + VideoSender sender(&uplink_, &source, GetParam()); RateCounterFilter counter1(&uplink_, 0, "sender_output"); TraceBasedDeliveryFilter filter(&uplink_, 0, "link_capacity"); filter.SetMaxDelay(500); @@ -192,7 +192,7 @@ TEST_P(BweSimulation, GoogleWifiTrace3Mbps) { TEST_P(BweSimulation, PacerGoogleWifiTrace3Mbps) { VerboseLogging(true); PeriodicKeyFrameSource source(0, 30, 300, 0, 0, 1000); - PacedVideoSender sender(&uplink_, &source, kRembEstimator); + PacedVideoSender sender(&uplink_, &source, GetParam()); RateCounterFilter counter1(&uplink_, 0, "sender_output"); TraceBasedDeliveryFilter filter(&uplink_, 0, "link_capacity"); filter.SetMaxDelay(500); @@ -207,13 +207,13 @@ TEST_P(BweSimulation, SelfFairnessTest) { const int kAllFlowIds[] = {0, 1, 2}; const size_t kNumFlows = sizeof(kAllFlowIds) / sizeof(kAllFlowIds[0]); rtc::scoped_ptr sources[kNumFlows]; - rtc::scoped_ptr senders[kNumFlows]; + rtc::scoped_ptr senders[kNumFlows]; for (size_t i = 0; i < kNumFlows; ++i) { // Streams started 20 seconds apart to give them different advantage when // competing for the bandwidth. sources[i].reset( new AdaptiveVideoSource(kAllFlowIds[i], 30, 300, 0, i * 20000)); - senders[i].reset(new PacketSender(&uplink_, sources[i].get(), GetParam())); + senders[i].reset(new VideoSender(&uplink_, sources[i].get(), GetParam())); } ChokeFilter choke(&uplink_, CreateFlowIds(kAllFlowIds, kNumFlows)); @@ -273,6 +273,64 @@ TEST_P(BweSimulation, PacedSelfFairnessTest) { RunFor(30 * 60 * 1000); } + +TEST_P(BweSimulation, PacedTcpFairnessTest) { + VerboseLogging(true); + + const int kAllFlowIds[] = {0, 1}; + const size_t kNumFlows = sizeof(kAllFlowIds) / sizeof(kAllFlowIds[0]); + + const int kAllMediaFlowIds[] = {0}; + const size_t kNumMediaFlows = + sizeof(kAllMediaFlowIds) / sizeof(kAllMediaFlowIds[0]); + + const int kAllTcpFlowIds[] = {1}; + const size_t kNumTcpFlows = + sizeof(kAllTcpFlowIds) / sizeof(kAllTcpFlowIds[0]); + + rtc::scoped_ptr sources[kNumFlows]; + rtc::scoped_ptr senders[kNumFlows + kNumTcpFlows]; + + for (size_t i = 0; i < kNumMediaFlows; ++i) { + // Streams started 20 seconds apart to give them different advantage when + // competing for the bandwidth. + sources[i].reset(new PeriodicKeyFrameSource(kAllMediaFlowIds[i], 30, 300, 0, + i * 20000, 1000)); + senders[i].reset( + new PacedVideoSender(&uplink_, sources[i].get(), GetParam())); + } + + for (size_t i = 0; i < kNumTcpFlows; ++i) { + senders[kNumMediaFlows + i].reset( + new TcpSender(&uplink_, kAllTcpFlowIds[i])); + } + + ChokeFilter choke(&uplink_, CreateFlowIds(kAllFlowIds, kNumFlows)); + choke.SetCapacity(1000); + choke.SetMaxDelay(1000); + + rtc::scoped_ptr rate_counters[kNumFlows]; + for (size_t i = 0; i < kNumFlows; ++i) { + rate_counters[i].reset(new RateCounterFilter( + &uplink_, CreateFlowIds(&kAllFlowIds[i], 1), "receiver_input")); + } + + RateCounterFilter total_utilization( + &uplink_, CreateFlowIds(kAllFlowIds, kNumFlows), "total_utilization"); + + rtc::scoped_ptr receivers[kNumFlows]; + for (size_t i = 0; i < kNumMediaFlows; ++i) { + receivers[i].reset(new PacketReceiver(&uplink_, kAllMediaFlowIds[i], + GetParam(), i == 0, false)); + } + + for (size_t i = 0; i < kNumTcpFlows; ++i) { + receivers[kNumMediaFlows + i].reset(new PacketReceiver( + &uplink_, kAllTcpFlowIds[i], kTcpEstimator, false, false)); + } + + RunFor(30 * 60 * 1000); +} #endif // BWE_TEST_LOGGING_COMPILE_TIME_ENABLE } // namespace bwe } // namespace testing diff --git a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimators_test.cc b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimators_test.cc index d1b9ea79f7..b64033ee45 100644 --- a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimators_test.cc +++ b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimators_test.cc @@ -36,14 +36,14 @@ INSTANTIATE_TEST_CASE_P(VideoSendersTest, TEST_P(DefaultBweTest, UnlimitedSpeed) { VideoSource source(0, 30, 300, 0, 0); - PacketSender sender(&uplink_, &source, GetParam()); + VideoSender sender(&uplink_, &source, GetParam()); PacketReceiver receiver(&uplink_, 0, GetParam(), false, false); RunFor(10 * 60 * 1000); } TEST_P(DefaultBweTest, SteadyLoss) { VideoSource source(0, 30, 300, 0, 0); - PacketSender sender(&uplink_, &source, GetParam()); + VideoSender sender(&uplink_, &source, GetParam()); LossFilter loss(&uplink_, 0); PacketReceiver receiver(&uplink_, 0, GetParam(), false, false); loss.SetLoss(20.0); @@ -52,7 +52,7 @@ TEST_P(DefaultBweTest, SteadyLoss) { TEST_P(DefaultBweTest, IncreasingLoss1) { VideoSource source(0, 30, 300, 0, 0); - PacketSender sender(&uplink_, &source, GetParam()); + VideoSender sender(&uplink_, &source, GetParam()); LossFilter loss(&uplink_, 0); PacketReceiver receiver(&uplink_, 0, GetParam(), false, false); for (int i = 0; i < 76; ++i) { @@ -63,7 +63,7 @@ TEST_P(DefaultBweTest, IncreasingLoss1) { TEST_P(DefaultBweTest, SteadyDelay) { VideoSource source(0, 30, 300, 0, 0); - PacketSender sender(&uplink_, &source, GetParam()); + VideoSender sender(&uplink_, &source, GetParam()); DelayFilter delay(&uplink_, 0); PacketReceiver receiver(&uplink_, 0, GetParam(), false, false); delay.SetDelay(1000); @@ -72,7 +72,7 @@ TEST_P(DefaultBweTest, SteadyDelay) { TEST_P(DefaultBweTest, IncreasingDelay1) { VideoSource source(0, 30, 300, 0, 0); - PacketSender sender(&uplink_, &source, GetParam()); + VideoSender sender(&uplink_, &source, GetParam()); DelayFilter delay(&uplink_, 0); PacketReceiver receiver(&uplink_, 0, GetParam(), false, false); RunFor(10 * 60 * 1000); @@ -85,7 +85,7 @@ TEST_P(DefaultBweTest, IncreasingDelay1) { TEST_P(DefaultBweTest, IncreasingDelay2) { VideoSource source(0, 30, 300, 0, 0); - PacketSender sender(&uplink_, &source, GetParam()); + VideoSender sender(&uplink_, &source, GetParam()); DelayFilter delay(&uplink_, 0); RateCounterFilter counter(&uplink_, 0, ""); PacketReceiver receiver(&uplink_, 0, GetParam(), false, false); @@ -100,7 +100,7 @@ TEST_P(DefaultBweTest, IncreasingDelay2) { TEST_P(DefaultBweTest, JumpyDelay1) { VideoSource source(0, 30, 300, 0, 0); - PacketSender sender(&uplink_, &source, GetParam()); + VideoSender sender(&uplink_, &source, GetParam()); DelayFilter delay(&uplink_, 0); PacketReceiver receiver(&uplink_, 0, GetParam(), false, false); RunFor(10 * 60 * 1000); @@ -116,7 +116,7 @@ TEST_P(DefaultBweTest, JumpyDelay1) { TEST_P(DefaultBweTest, SteadyJitter) { VideoSource source(0, 30, 300, 0, 0); - PacketSender sender(&uplink_, &source, GetParam()); + VideoSender sender(&uplink_, &source, GetParam()); JitterFilter jitter(&uplink_, 0); RateCounterFilter counter(&uplink_, 0, ""); PacketReceiver receiver(&uplink_, 0, GetParam(), false, false); @@ -126,7 +126,7 @@ TEST_P(DefaultBweTest, SteadyJitter) { TEST_P(DefaultBweTest, IncreasingJitter1) { VideoSource source(0, 30, 300, 0, 0); - PacketSender sender(&uplink_, &source, GetParam()); + VideoSender sender(&uplink_, &source, GetParam()); JitterFilter jitter(&uplink_, 0); PacketReceiver receiver(&uplink_, 0, GetParam(), false, false); for (int i = 0; i < 2 * 60 * 2; ++i) { @@ -138,7 +138,7 @@ TEST_P(DefaultBweTest, IncreasingJitter1) { TEST_P(DefaultBweTest, IncreasingJitter2) { VideoSource source(0, 30, 300, 0, 0); - PacketSender sender(&uplink_, &source, GetParam()); + VideoSender sender(&uplink_, &source, GetParam()); JitterFilter jitter(&uplink_, 0); PacketReceiver receiver(&uplink_, 0, GetParam(), false, false); RunFor(30 * 1000); @@ -152,7 +152,7 @@ TEST_P(DefaultBweTest, IncreasingJitter2) { TEST_P(DefaultBweTest, SteadyReorder) { VideoSource source(0, 30, 300, 0, 0); - PacketSender sender(&uplink_, &source, GetParam()); + VideoSender sender(&uplink_, &source, GetParam()); ReorderFilter reorder(&uplink_, 0); PacketReceiver receiver(&uplink_, 0, GetParam(), false, false); reorder.SetReorder(20.0); @@ -161,7 +161,7 @@ TEST_P(DefaultBweTest, SteadyReorder) { TEST_P(DefaultBweTest, IncreasingReorder1) { VideoSource source(0, 30, 300, 0, 0); - PacketSender sender(&uplink_, &source, GetParam()); + VideoSender sender(&uplink_, &source, GetParam()); ReorderFilter reorder(&uplink_, 0); PacketReceiver receiver(&uplink_, 0, GetParam(), false, false); for (int i = 0; i < 76; ++i) { @@ -172,7 +172,7 @@ TEST_P(DefaultBweTest, IncreasingReorder1) { TEST_P(DefaultBweTest, SteadyChoke) { VideoSource source(0, 30, 300, 0, 0); - PacketSender sender(&uplink_, &source, GetParam()); + VideoSender sender(&uplink_, &source, GetParam()); ChokeFilter choke(&uplink_, 0); PacketReceiver receiver(&uplink_, 0, GetParam(), false, false); choke.SetCapacity(140); @@ -181,7 +181,7 @@ TEST_P(DefaultBweTest, SteadyChoke) { TEST_P(DefaultBweTest, IncreasingChoke1) { VideoSource source(0, 30, 300, 0, 0); - PacketSender sender(&uplink_, &source, GetParam()); + VideoSender sender(&uplink_, &source, GetParam()); ChokeFilter choke(&uplink_, 0); PacketReceiver receiver(&uplink_, 0, GetParam(), false, false); for (int i = 1200; i >= 100; i -= 100) { @@ -192,7 +192,7 @@ TEST_P(DefaultBweTest, IncreasingChoke1) { TEST_P(DefaultBweTest, IncreasingChoke2) { VideoSource source(0, 30, 300, 0, 0); - PacketSender sender(&uplink_, &source, GetParam()); + VideoSender sender(&uplink_, &source, GetParam()); ChokeFilter choke(&uplink_, 0); PacketReceiver receiver(&uplink_, 0, GetParam(), false, false); RunFor(60 * 1000); @@ -204,7 +204,7 @@ TEST_P(DefaultBweTest, IncreasingChoke2) { TEST_P(DefaultBweTest, Multi1) { VideoSource source(0, 30, 300, 0, 0); - PacketSender sender(&uplink_, &source, GetParam()); + VideoSender sender(&uplink_, &source, GetParam()); DelayFilter delay(&uplink_, 0); ChokeFilter choke(&uplink_, 0); RateCounterFilter counter(&uplink_, 0, ""); @@ -222,7 +222,7 @@ TEST_P(DefaultBweTest, Multi1) { TEST_P(DefaultBweTest, Multi2) { VideoSource source(0, 30, 300, 0, 0); - PacketSender sender(&uplink_, &source, GetParam()); + VideoSender sender(&uplink_, &source, GetParam()); ChokeFilter choke(&uplink_, 0); JitterFilter jitter(&uplink_, 0); RateCounterFilter counter(&uplink_, 0, ""); @@ -280,7 +280,7 @@ INSTANTIATE_TEST_CASE_P(VideoSendersTest, TEST_P(BweFeedbackTest, Choke1000kbps500kbps1000kbps) { AdaptiveVideoSource source(0, 30, 300, 0, 0); - PacketSender sender(&uplink_, &source, GetParam()); + VideoSender sender(&uplink_, &source, GetParam()); ChokeFilter filter(&uplink_, 0); RateCounterFilter counter(&uplink_, 0, "receiver_input"); PacketReceiver receiver(&uplink_, 0, GetParam(), false, false); @@ -299,7 +299,7 @@ TEST_P(BweFeedbackTest, Choke1000kbps500kbps1000kbps) { TEST_P(BweFeedbackTest, Choke200kbps30kbps200kbps) { AdaptiveVideoSource source(0, 30, 300, 0, 0); - PacketSender sender(&uplink_, &source, GetParam()); + VideoSender sender(&uplink_, &source, GetParam()); ChokeFilter filter(&uplink_, 0); RateCounterFilter counter(&uplink_, 0, "receiver_input"); PacketReceiver receiver(&uplink_, 0, GetParam(), false, false); @@ -319,7 +319,7 @@ TEST_P(BweFeedbackTest, Choke200kbps30kbps200kbps) { TEST_P(BweFeedbackTest, Verizon4gDownlinkTest) { AdaptiveVideoSource source(0, 30, 300, 0, 0); - PacketSender sender(&uplink_, &source, GetParam()); + VideoSender sender(&uplink_, &source, GetParam()); RateCounterFilter counter1(&uplink_, 0, "sender_output"); TraceBasedDeliveryFilter filter(&uplink_, 0, "link_capacity"); RateCounterFilter counter2(&uplink_, 0, "receiver_input"); @@ -333,7 +333,7 @@ TEST_P(BweFeedbackTest, Verizon4gDownlinkTest) { // webrtc:3277 TEST_P(BweFeedbackTest, DISABLED_GoogleWifiTrace3Mbps) { AdaptiveVideoSource source(0, 30, 300, 0, 0); - PacketSender sender(&uplink_, &source, GetParam()); + VideoSender sender(&uplink_, &source, GetParam()); RateCounterFilter counter1(&uplink_, 0, "sender_output"); TraceBasedDeliveryFilter filter(&uplink_, 0, "link_capacity"); filter.SetMaxDelay(500); diff --git a/webrtc/modules/remote_bitrate_estimator/test/bwe.cc b/webrtc/modules/remote_bitrate_estimator/test/bwe.cc index 3b233709c8..6edfe3d08d 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/bwe.cc +++ b/webrtc/modules/remote_bitrate_estimator/test/bwe.cc @@ -16,6 +16,7 @@ #include "webrtc/modules/remote_bitrate_estimator/test/estimators/nada.h" #include "webrtc/modules/remote_bitrate_estimator/test/estimators/remb.h" #include "webrtc/modules/remote_bitrate_estimator/test/estimators/send_side.h" +#include "webrtc/modules/remote_bitrate_estimator/test/estimators/tcp.h" namespace webrtc { namespace testing { @@ -58,6 +59,8 @@ BweSender* CreateBweSender(BandwidthEstimatorType estimator, return new FullBweSender(kbps, observer, clock); case kNadaEstimator: return new NadaBweSender(kbps, observer, clock); + case kTcpEstimator: + FALLTHROUGH(); case kNullEstimator: return new NullBweSender(); } @@ -75,6 +78,8 @@ BweReceiver* CreateBweReceiver(BandwidthEstimatorType type, return new SendSideBweReceiver(flow_id); case kNadaEstimator: return new NadaBweReceiver(flow_id); + case kTcpEstimator: + return new TcpBweReceiver(flow_id); case kNullEstimator: return new BweReceiver(flow_id); } diff --git a/webrtc/modules/remote_bitrate_estimator/test/bwe.h b/webrtc/modules/remote_bitrate_estimator/test/bwe.h index 0bab5a98a1..a82235f237 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/bwe.h +++ b/webrtc/modules/remote_bitrate_estimator/test/bwe.h @@ -53,7 +53,8 @@ enum BandwidthEstimatorType { kNullEstimator, kNadaEstimator, kRembEstimator, - kFullSendSideEstimator + kFullSendSideEstimator, + kTcpEstimator }; int64_t GetAbsSendTimeInMs(uint32_t abs_send_time); diff --git a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc index d179e8e6ea..5608b2a814 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc +++ b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc @@ -148,6 +148,15 @@ MediaPacket::MediaPacket() { memset(&header_, 0, sizeof(header_)); } +MediaPacket::MediaPacket(int flow_id, + int64_t send_time_us, + size_t payload_size, + uint16_t sequence_number) + : Packet(flow_id, send_time_us, payload_size) { + header_ = RTPHeader(); + header_.sequenceNumber = sequence_number; +} + MediaPacket::MediaPacket(int flow_id, int64_t send_time_us, size_t payload_size, @@ -157,7 +166,7 @@ MediaPacket::MediaPacket(int flow_id, MediaPacket::MediaPacket(int64_t send_time_us, uint32_t sequence_number) : Packet(0, send_time_us, 0) { - memset(&header_, 0, sizeof(header_)); + header_ = RTPHeader(); header_.sequenceNumber = sequence_number; } @@ -636,6 +645,9 @@ uint32_t VideoSource::NextPacketSize(uint32_t frame_size, void VideoSource::RunFor(int64_t time_ms, Packets* in_out) { assert(in_out); + std::stringstream ss; + ss << "SendEstimate_" << flow_id_ << "#1"; + BWE_TEST_LOGGING_PLOT(0, ss.str(), now_ms_, bits_per_second_ / 1000); now_ms_ += time_ms; Packets new_packets; while (now_ms_ >= next_frame_ms_) { diff --git a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework_unittest.cc b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework_unittest.cc index c611b073b6..1b1117d4f8 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework_unittest.cc +++ b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework_unittest.cc @@ -765,7 +765,7 @@ TEST_F(BweTestFramework_ChokeFilterTest, ShortTraceMaxDelay) { TestChoke(&filter, 25, 1, 1); } -void TestVideoSender(PacketSender* sender, +void TestVideoSender(VideoSender* sender, int64_t run_for_ms, uint32_t expected_packets, uint32_t expected_payload_size, @@ -812,7 +812,7 @@ void TestVideoSender(PacketSender* sender, TEST(BweTestFramework_VideoSenderTest, Fps1Kbps80_1s) { // 1 fps, 80 kbps VideoSource source(0, 1.0f, 80, 0x1234, 0); - PacketSender sender(NULL, &source, kNullEstimator); + VideoSender sender(NULL, &source, kNullEstimator); EXPECT_EQ(80000u, source.bits_per_second()); // We're at 1 fps, so all packets should be generated on first call, giving 10 // packets of each 1000 bytes, total 10000 bytes. @@ -830,7 +830,7 @@ TEST(BweTestFramework_VideoSenderTest, Fps1Kbps80_1s) { TEST(BweTestFramework_VideoSenderTest, Fps1Kbps80_1s_Offset) { // 1 fps, 80 kbps, offset 0.5 of a frame period, ==0.5s in this case. VideoSource source(0, 1.0f, 80, 0x1234, 500); - PacketSender sender(NULL, &source, kNullEstimator); + VideoSender sender(NULL, &source, kNullEstimator); EXPECT_EQ(80000u, source.bits_per_second()); // 499ms, no output. TestVideoSender(&sender, 499, 0, 0, 0); @@ -851,7 +851,7 @@ TEST(BweTestFramework_VideoSenderTest, Fps1Kbps80_1s_Offset) { TEST(BweTestFramework_VideoSenderTest, Fps50Kpbs80_11s) { // 50 fps, 80 kbps. VideoSource source(0, 50.0f, 80, 0x1234, 0); - PacketSender sender(NULL, &source, kNullEstimator); + VideoSender sender(NULL, &source, kNullEstimator); EXPECT_EQ(80000u, source.bits_per_second()); // 9998ms, should see 500 frames, 200 byte payloads, total 100000 bytes. TestVideoSender(&sender, 9998, 500, 200, 100000); @@ -868,7 +868,7 @@ TEST(BweTestFramework_VideoSenderTest, Fps50Kpbs80_11s) { TEST(BweTestFramework_VideoSenderTest, Fps10Kpbs120_1s) { // 20 fps, 120 kbps. VideoSource source(0, 20.0f, 120, 0x1234, 0); - PacketSender sender(NULL, &source, kNullEstimator); + VideoSender sender(NULL, &source, kNullEstimator); EXPECT_EQ(120000u, source.bits_per_second()); // 498ms, 10 frames with 750 byte payloads, total 7500 bytes. TestVideoSender(&sender, 498, 10, 750, 7500); @@ -885,7 +885,7 @@ TEST(BweTestFramework_VideoSenderTest, Fps10Kpbs120_1s) { TEST(BweTestFramework_VideoSenderTest, Fps30Kbps800_20s) { // 20 fps, 820 kbps. VideoSource source(0, 25.0f, 820, 0x1234, 0); - PacketSender sender(NULL, &source, kNullEstimator); + VideoSender sender(NULL, &source, kNullEstimator); EXPECT_EQ(820000u, source.bits_per_second()); // 9998ms, 250 frames. 820 kbps = 102500 bytes/s, so total should be 1025000. // Each frame is 102500/25=4100 bytes, or 5 packets (4 @1000 bytes, 1 @100), @@ -907,7 +907,7 @@ TEST(BweTestFramework_VideoSenderTest, Fps30Kbps800_20s) { TEST(BweTestFramework_VideoSenderTest, TestAppendInOrder) { // 1 fps, 80 kbps, 250ms offset. VideoSource source1(0, 1.0f, 80, 0x1234, 250); - PacketSender sender1(NULL, &source1, kNullEstimator); + VideoSender sender1(NULL, &source1, kNullEstimator); EXPECT_EQ(80000u, source1.bits_per_second()); Packets packets; // Generate some packets, verify they are sorted. @@ -923,7 +923,7 @@ TEST(BweTestFramework_VideoSenderTest, TestAppendInOrder) { // Another sender, 2 fps, 160 kbps, 150ms offset VideoSource source2(0, 2.0f, 160, 0x2234, 150); - PacketSender sender2(NULL, &source2, kNullEstimator); + VideoSender sender2(NULL, &source2, kNullEstimator); EXPECT_EQ(160000u, source2.bits_per_second()); // Generate some packets, verify that they are merged with the packets already // on the list. @@ -941,7 +941,7 @@ TEST(BweTestFramework_VideoSenderTest, TestAppendInOrder) { TEST(BweTestFramework_VideoSenderTest, FeedbackIneffective) { VideoSource source(0, 25.0f, 820, 0x1234, 0); - PacketSender sender(NULL, &source, kNullEstimator); + VideoSender sender(NULL, &source, kNullEstimator); EXPECT_EQ(820000u, source.bits_per_second()); TestVideoSender(&sender, 9998, 1000, 500, 1025000); @@ -957,7 +957,7 @@ TEST(BweTestFramework_VideoSenderTest, FeedbackIneffective) { TEST(BweTestFramework_AdaptiveVideoSenderTest, FeedbackChangesBitrate) { AdaptiveVideoSource source(0, 25.0f, 820, 0x1234, 0); - PacketSender sender(NULL, &source, kRembEstimator); + VideoSender sender(NULL, &source, kRembEstimator); EXPECT_EQ(820000u, source.bits_per_second()); TestVideoSender(&sender, 9998, 1000, 500, 1025000); diff --git a/webrtc/modules/remote_bitrate_estimator/test/estimators/tcp.cc b/webrtc/modules/remote_bitrate_estimator/test/estimators/tcp.cc new file mode 100644 index 0000000000..1312fe36d0 --- /dev/null +++ b/webrtc/modules/remote_bitrate_estimator/test/estimators/tcp.cc @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015 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 + +#include "webrtc/modules/remote_bitrate_estimator/test/estimators/tcp.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/common.h" +#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h" +#include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h" +#include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h" + +namespace webrtc { +namespace testing { +namespace bwe { + +TcpBweReceiver::TcpBweReceiver(int flow_id) + : BweReceiver(flow_id), last_feedback_ms_(0) { +} + +TcpBweReceiver::~TcpBweReceiver() { +} + +void TcpBweReceiver::ReceivePacket(int64_t arrival_time_ms, + const MediaPacket& media_packet) { + acks_.push_back(media_packet.header().sequenceNumber); +} + +FeedbackPacket* TcpBweReceiver::GetFeedback(int64_t now_ms) { + // if (now_ms - last_feedback_ms_ < 100) + // return NULL; + last_feedback_ms_ = now_ms; + FeedbackPacket* fb = new TcpFeedback(flow_id_, now_ms * 1000, acks_); + acks_.clear(); + return fb; +} + +} // namespace bwe +} // namespace testing +} // namespace webrtc diff --git a/webrtc/modules/remote_bitrate_estimator/test/estimators/tcp.h b/webrtc/modules/remote_bitrate_estimator/test/estimators/tcp.h new file mode 100644 index 0000000000..a5f73a2b25 --- /dev/null +++ b/webrtc/modules/remote_bitrate_estimator/test/estimators/tcp.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015 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 WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_TCP_H_ +#define WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_TCP_H_ + +#include + +#include "webrtc/modules/remote_bitrate_estimator/test/bwe.h" + +namespace webrtc { +namespace testing { +namespace bwe { +class TcpBweReceiver : public BweReceiver { + public: + explicit TcpBweReceiver(int flow_id); + virtual ~TcpBweReceiver(); + + void ReceivePacket(int64_t arrival_time_ms, + const MediaPacket& media_packet) override; + FeedbackPacket* GetFeedback(int64_t now_ms) override; + + private: + int64_t last_feedback_ms_; + std::vector acks_; +}; +} // namespace bwe +} // namespace testing +} // namespace webrtc +#endif // WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_TCP_H_ diff --git a/webrtc/modules/remote_bitrate_estimator/test/packet.h b/webrtc/modules/remote_bitrate_estimator/test/packet.h index 12d4a3ee93..f4e9c12a17 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/packet.h +++ b/webrtc/modules/remote_bitrate_estimator/test/packet.h @@ -50,6 +50,10 @@ class Packet { class MediaPacket : public Packet { public: MediaPacket(); + MediaPacket(int flow_id, + int64_t send_time_us, + size_t payload_size, + uint16_t sequence_number); MediaPacket(int flow_id, int64_t send_time_us, size_t payload_size, @@ -135,6 +139,20 @@ class NadaFeedback : public FeedbackPacket { float derivative_; }; +class TcpFeedback : public FeedbackPacket { + public: + TcpFeedback(int flow_id, + int64_t send_time_us, + const std::vector& acked_packets) + : FeedbackPacket(flow_id, send_time_us), acked_packets_(acked_packets) {} + virtual ~TcpFeedback() {} + + const std::vector& acked_packets() const { return acked_packets_; } + + private: + const std::vector acked_packets_; +}; + typedef std::list Packets; typedef std::list::iterator PacketsIt; typedef std::list::const_iterator PacketsConstIt; diff --git a/webrtc/modules/remote_bitrate_estimator/test/packet_sender.cc b/webrtc/modules/remote_bitrate_estimator/test/packet_sender.cc index 5908f26748..3c73d97989 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/packet_sender.cc +++ b/webrtc/modules/remote_bitrate_estimator/test/packet_sender.cc @@ -14,18 +14,38 @@ #include #include +#include "webrtc/base/checks.h" +#include "webrtc/modules/interface/module_common_types.h" #include "webrtc/modules/remote_bitrate_estimator/test/bwe.h" namespace webrtc { namespace testing { namespace bwe { -PacketSender::PacketSender(PacketProcessorListener* listener, - VideoSource* source, - BandwidthEstimatorType estimator_type) - : PacketProcessor(listener, source->flow_id(), kSender), +std::list GetFeedbackPackets(Packets* in_out, + int64_t end_time_ms, + int flow_id) { + std::list fb_packets; + for (auto it = in_out->begin(); it != in_out->end();) { + if ((*it)->send_time_us() > 1000 * end_time_ms) + break; + if ((*it)->GetPacketType() == Packet::kFeedback && + flow_id == (*it)->flow_id()) { + fb_packets.push_back(static_cast(*it)); + it = in_out->erase(it); + } else { + ++it; + } + } + return fb_packets; +} + +VideoSender::VideoSender(PacketProcessorListener* listener, + VideoSource* source, + BandwidthEstimatorType estimator_type) + : PacketSender(listener, source->flow_id()), // For Packet::send_time_us() to be comparable with timestamps from - // clock_, the clock of the PacketSender and the Source must be aligned. + // clock_, the clock of the VideoSender and the Source must be aligned. // We assume that both start at time 0. clock_(0), source_(source), @@ -36,17 +56,17 @@ PacketSender::PacketSender(PacketProcessorListener* listener, modules_.push_back(bwe_.get()); } -PacketSender::~PacketSender() { +VideoSender::~VideoSender() { } -void PacketSender::RunFor(int64_t time_ms, Packets* in_out) { +void VideoSender::RunFor(int64_t time_ms, Packets* in_out) { int64_t now_ms = clock_.TimeInMilliseconds(); std::list feedbacks = - GetFeedbackPackets(in_out, now_ms + time_ms); + GetFeedbackPackets(in_out, now_ms + time_ms, source_->flow_id()); ProcessFeedbackAndGeneratePackets(time_ms, &feedbacks, in_out); } -void PacketSender::ProcessFeedbackAndGeneratePackets( +void VideoSender::ProcessFeedbackAndGeneratePackets( int64_t time_ms, std::list* feedbacks, Packets* packets) { @@ -76,42 +96,20 @@ void PacketSender::ProcessFeedbackAndGeneratePackets( assert(feedbacks->empty()); } -int PacketSender::GetFeedbackIntervalMs() const { +int VideoSender::GetFeedbackIntervalMs() const { return bwe_->GetFeedbackIntervalMs(); } -std::list PacketSender::GetFeedbackPackets( - Packets* in_out, - int64_t end_time_ms) { - std::list fb_packets; - for (auto it = in_out->begin(); it != in_out->end();) { - if ((*it)->send_time_us() > 1000 * end_time_ms) - break; - if ((*it)->GetPacketType() == Packet::kFeedback && - source()->flow_id() == (*it)->flow_id()) { - fb_packets.push_back(static_cast(*it)); - it = in_out->erase(it); - } else { - ++it; - } - } - return fb_packets; -} - -void PacketSender::OnNetworkChanged(uint32_t target_bitrate_bps, - uint8_t fraction_lost, - int64_t rtt) { +void VideoSender::OnNetworkChanged(uint32_t target_bitrate_bps, + uint8_t fraction_lost, + int64_t rtt) { source_->SetBitrateBps(target_bitrate_bps); - std::stringstream ss; - ss << "SendEstimate_" << source_->flow_id() << "#1"; - BWE_TEST_LOGGING_PLOT(0, ss.str(), clock_.TimeInMilliseconds(), - target_bitrate_bps / 1000); } PacedVideoSender::PacedVideoSender(PacketProcessorListener* listener, VideoSource* source, BandwidthEstimatorType estimator) - : PacketSender(listener, source, estimator), + : VideoSender(listener, source, estimator), pacer_(&clock_, this, source->bits_per_second() / 1000, @@ -132,7 +130,7 @@ void PacedVideoSender::RunFor(int64_t time_ms, Packets* in_out) { int64_t end_time_ms = clock_.TimeInMilliseconds() + time_ms; // Run process periodically to allow the packets to be paced out. std::list feedbacks = - GetFeedbackPackets(in_out, end_time_ms); + GetFeedbackPackets(in_out, end_time_ms, source_->flow_id()); int64_t last_run_time_ms = -1; BWE_TEST_LOGGING_CONTEXT("Sender"); BWE_TEST_LOGGING_CONTEXT(source_->flow_id()); @@ -260,11 +258,79 @@ size_t PacedVideoSender::TimeToSendPadding(size_t bytes) { void PacedVideoSender::OnNetworkChanged(uint32_t target_bitrate_bps, uint8_t fraction_lost, int64_t rtt) { - PacketSender::OnNetworkChanged(target_bitrate_bps, fraction_lost, rtt); + VideoSender::OnNetworkChanged(target_bitrate_bps, fraction_lost, rtt); pacer_.UpdateBitrate( target_bitrate_bps / 1000, PacedSender::kDefaultPaceMultiplier * target_bitrate_bps / 1000, 0); } + +void TcpSender::RunFor(int64_t time_ms, Packets* in_out) { + BWE_TEST_LOGGING_CONTEXT("Sender"); + BWE_TEST_LOGGING_CONTEXT(*flow_ids().begin()); + std::list feedbacks = + GetFeedbackPackets(in_out, now_ms_ + time_ms, *flow_ids().begin()); + // The number of packets which are sent in during time_ms depends on the + // number of packets in_flight_ and the max number of packets in flight + // (cwnd_). Therefore SendPackets() isn't directly dependent on time_ms. + for (FeedbackPacket* fb : feedbacks) { + UpdateCongestionControl(fb); + SendPackets(in_out); + } + SendPackets(in_out); + now_ms_ += time_ms; +} + +void TcpSender::SendPackets(Packets* in_out) { + int cwnd = ceil(cwnd_); + int packets_to_send = std::max(cwnd - in_flight_, 0); + if (packets_to_send > 0) { + Packets generated = GeneratePackets(packets_to_send); + in_flight_ += generated.size(); + in_out->merge(generated, DereferencingComparator); + } +} + +void TcpSender::UpdateCongestionControl(const FeedbackPacket* fb) { + const TcpFeedback* tcp_fb = static_cast(fb); + DCHECK(!tcp_fb->acked_packets().empty()); + ack_received_ = true; + + in_flight_ -= tcp_fb->acked_packets().size(); + DCHECK_GE(in_flight_, 0); + + if (LossEvent(tcp_fb->acked_packets())) { + cwnd_ /= 2.0f; + in_slow_start_ = false; + } else if (in_slow_start_) { + cwnd_ += tcp_fb->acked_packets().size(); + } else { + cwnd_ += 1.0f / cwnd_; + } + + last_acked_seq_num_ = + LatestSequenceNumber(tcp_fb->acked_packets().back(), last_acked_seq_num_); +} + +bool TcpSender::LossEvent(const std::vector& acked_packets) { + int missing = 0; + for (int i = last_acked_seq_num_ + 1; i <= acked_packets.back(); ++i) { + if (std::find(acked_packets.begin(), acked_packets.end(), i) == + acked_packets.end()) { + ++missing; + } + } + in_flight_ -= missing; + return missing > 0; +} + +Packets TcpSender::GeneratePackets(size_t num_packets) { + Packets generated; + for (size_t i = 0; i < num_packets; ++i) { + generated.push_back(new MediaPacket(*flow_ids().begin(), 1000 * now_ms_, + 1200, next_sequence_number_++)); + } + return generated; +} } // namespace bwe } // namespace testing } // namespace webrtc diff --git a/webrtc/modules/remote_bitrate_estimator/test/packet_sender.h b/webrtc/modules/remote_bitrate_estimator/test/packet_sender.h index 8c13cb16ef..b3280d5b89 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/packet_sender.h +++ b/webrtc/modules/remote_bitrate_estimator/test/packet_sender.h @@ -24,19 +24,27 @@ namespace webrtc { namespace testing { namespace bwe { -class PacketSender : public PacketProcessor, public BitrateObserver { +class PacketSender : public PacketProcessor { public: - PacketSender(PacketProcessorListener* listener, - VideoSource* source, - BandwidthEstimatorType estimator); - virtual ~PacketSender(); - + PacketSender(PacketProcessorListener* listener, int flow_id) + : PacketProcessor(listener, flow_id, kSender) {} + virtual ~PacketSender() {} // Call GiveFeedback() with the returned interval in milliseconds, provided // there is a new estimate available. // Note that changing the feedback interval affects the timing of when the // output of the estimators is sampled and therefore the baseline files may // have to be regenerated. - virtual int GetFeedbackIntervalMs() const; + virtual int GetFeedbackIntervalMs() const = 0; +}; + +class VideoSender : public PacketSender, public BitrateObserver { + public: + VideoSender(PacketProcessorListener* listener, + VideoSource* source, + BandwidthEstimatorType estimator); + virtual ~VideoSender(); + + int GetFeedbackIntervalMs() const override; void RunFor(int64_t time_ms, Packets* in_out) override; virtual VideoSource* source() const { return source_; } @@ -50,8 +58,6 @@ class PacketSender : public PacketProcessor, public BitrateObserver { void ProcessFeedbackAndGeneratePackets(int64_t time_ms, std::list* feedbacks, Packets* generated); - std::list GetFeedbackPackets(Packets* in_out, - int64_t end_time_ms); SimulatedClock clock_; VideoSource* source_; @@ -60,10 +66,10 @@ class PacketSender : public PacketProcessor, public BitrateObserver { std::list modules_; private: - DISALLOW_COPY_AND_ASSIGN(PacketSender); + DISALLOW_COPY_AND_ASSIGN(VideoSender); }; -class PacedVideoSender : public PacketSender, public PacedSender::Callback { +class PacedVideoSender : public VideoSender, public PacedSender::Callback { public: PacedVideoSender(PacketProcessorListener* listener, VideoSource* source, @@ -95,6 +101,36 @@ class PacedVideoSender : public PacketSender, public PacedSender::Callback { DISALLOW_IMPLICIT_CONSTRUCTORS(PacedVideoSender); }; + +class TcpSender : public PacketSender { + public: + TcpSender(PacketProcessorListener* listener, int flow_id) + : PacketSender(listener, flow_id), + now_ms_(0), + in_slow_start_(false), + cwnd_(1), + in_flight_(0), + ack_received_(false), + last_acked_seq_num_(0), + next_sequence_number_(0) {} + + void RunFor(int64_t time_ms, Packets* in_out) override; + int GetFeedbackIntervalMs() const override { return 10; } + + private: + void SendPackets(Packets* in_out); + void UpdateCongestionControl(const FeedbackPacket* fb); + bool LossEvent(const std::vector& acked_packets); + Packets GeneratePackets(size_t num_packets); + + int64_t now_ms_; + bool in_slow_start_; + float cwnd_; + int in_flight_; + bool ack_received_; + uint16_t last_acked_seq_num_; + uint16_t next_sequence_number_; +}; } // namespace bwe } // namespace testing } // namespace webrtc