Adds a simplified Reno-type TCP sender.

BUG=4559
R=sprang@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/44189004

Cr-Commit-Position: refs/heads/master@{#9021}
diff --git a/webrtc/modules/modules.gyp b/webrtc/modules/modules.gyp
index c004d5a..1bf8466 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 df82764..201c915 100644
--- a/webrtc/modules/remote_bitrate_estimator/bwe_simulations.cc
+++ b/webrtc/modules/remote_bitrate_estimator/bwe_simulations.cc
@@ -46,7 +46,7 @@
 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, 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 @@
   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 @@
   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, 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, 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, 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 @@
   const int kAllFlowIds[] = {0, 1, 2};
   const size_t kNumFlows = sizeof(kAllFlowIds) / sizeof(kAllFlowIds[0]);
   rtc::scoped_ptr<AdaptiveVideoSource> sources[kNumFlows];
-  rtc::scoped_ptr<PacketSender> senders[kNumFlows];
+  rtc::scoped_ptr<VideoSender> 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 @@
 
   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<PeriodicKeyFrameSource> sources[kNumFlows];
+  rtc::scoped_ptr<PacketSender> 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<RateCounterFilter> 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<PacketReceiver> 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 d1b9ea7..b64033e 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 @@
 
 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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 @@
 
 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, 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, 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 @@
 // 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 3b23370..6edfe3d 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 @@
       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 @@
       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 0bab5a9..a82235f 100644
--- a/webrtc/modules/remote_bitrate_estimator/test/bwe.h
+++ b/webrtc/modules/remote_bitrate_estimator/test/bwe.h
@@ -53,7 +53,8 @@
   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 d179e8e..5608b2a 100644
--- a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc
+++ b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc
@@ -151,13 +151,22 @@
 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,
                          const RTPHeader& header)
     : Packet(flow_id, send_time_us, payload_size), header_(header) {
 }
 
 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 @@
 
 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 c611b07..1b1117d 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 @@
   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 @@
 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_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, 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, 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, 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, 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 @@
 
   // 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, 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_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 0000000..1312fe3
--- /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 <algorithm>
+
+#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 0000000..a5f73a2
--- /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 <vector>
+
+#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<uint16_t> 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 12d4a3e..f4e9c12 100644
--- a/webrtc/modules/remote_bitrate_estimator/test/packet.h
+++ b/webrtc/modules/remote_bitrate_estimator/test/packet.h
@@ -53,6 +53,10 @@
   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,
               const RTPHeader& header);
   MediaPacket(int64_t send_time_us, uint32_t sequence_number);
   virtual ~MediaPacket() {}
@@ -135,6 +139,20 @@
   float derivative_;
 };
 
+class TcpFeedback : public FeedbackPacket {
+ public:
+  TcpFeedback(int flow_id,
+              int64_t send_time_us,
+              const std::vector<uint16_t>& acked_packets)
+      : FeedbackPacket(flow_id, send_time_us), acked_packets_(acked_packets) {}
+  virtual ~TcpFeedback() {}
+
+  const std::vector<uint16_t>& acked_packets() const { return acked_packets_; }
+
+ private:
+  const std::vector<uint16_t> acked_packets_;
+};
+
 typedef std::list<Packet*> Packets;
 typedef std::list<Packet*>::iterator PacketsIt;
 typedef std::list<Packet*>::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 5908f26..3c73d97 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 <list>
 #include <sstream>
 
+#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<FeedbackPacket*> GetFeedbackPackets(Packets* in_out,
+                                              int64_t end_time_ms,
+                                              int flow_id) {
+  std::list<FeedbackPacket*> 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<FeedbackPacket*>(*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 @@
   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<FeedbackPacket*> 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<FeedbackPacket*>* feedbacks,
     Packets* packets) {
@@ -76,42 +96,20 @@
   assert(feedbacks->empty());
 }
 
-int PacketSender::GetFeedbackIntervalMs() const {
+int VideoSender::GetFeedbackIntervalMs() const {
   return bwe_->GetFeedbackIntervalMs();
 }
 
-std::list<FeedbackPacket*> PacketSender::GetFeedbackPackets(
-    Packets* in_out,
-    int64_t end_time_ms) {
-  std::list<FeedbackPacket*> 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<FeedbackPacket*>(*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 @@
   int64_t end_time_ms = clock_.TimeInMilliseconds() + time_ms;
   // Run process periodically to allow the packets to be paced out.
   std::list<FeedbackPacket*> 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 @@
 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<FeedbackPacket*> 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<Packet>);
+  }
+}
+
+void TcpSender::UpdateCongestionControl(const FeedbackPacket* fb) {
+  const TcpFeedback* tcp_fb = static_cast<const TcpFeedback*>(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<uint16_t>& 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 8c13cb1..b3280d5 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 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 @@
   void ProcessFeedbackAndGeneratePackets(int64_t time_ms,
                                          std::list<FeedbackPacket*>* feedbacks,
                                          Packets* generated);
-  std::list<FeedbackPacket*> GetFeedbackPackets(Packets* in_out,
-                                                int64_t end_time_ms);
 
   SimulatedClock clock_;
   VideoSource* source_;
@@ -60,10 +66,10 @@
   std::list<Module*> 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 @@
 
   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<uint16_t>& 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