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