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}
This commit is contained in:
Stefan Holmer 2015-04-16 19:55:45 +02:00
parent f49dbfa5c3
commit 3795937920
12 changed files with 375 additions and 92 deletions

View File

@ -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',

View File

@ -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<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 @@ 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<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

View File

@ -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);

View File

@ -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);
}

View File

@ -53,7 +53,8 @@ enum BandwidthEstimatorType {
kNullEstimator,
kNadaEstimator,
kRembEstimator,
kFullSendSideEstimator
kFullSendSideEstimator,
kTcpEstimator
};
int64_t GetAbsSendTimeInMs(uint32_t abs_send_time);

View File

@ -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_) {

View File

@ -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);

View File

@ -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

View File

@ -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_

View File

@ -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<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;

View File

@ -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 @@ 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<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 @@ void PacketSender::ProcessFeedbackAndGeneratePackets(
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 @@ 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<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 @@ 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<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

View File

@ -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<FeedbackPacket*>* feedbacks,
Packets* generated);
std::list<FeedbackPacket*> 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<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 @@ 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<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