Introduce PacketReceiver and remove configuration of simulations via the BweTestConfig.

This makes it possible to build more flexible simulations, and makes it easier to implement bi-directional simulations. This also removes support for generating baseline files and comparing against a baseline, which hasn't turned out to be particuarly useful.

BUG=4173
R=pbos@webrtc.org

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

Cr-Commit-Position: refs/heads/master@{#8311}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8311 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
stefan@webrtc.org
2015-02-10 09:48:35 +00:00
parent 30015e3180
commit 027e113209
6 changed files with 311 additions and 391 deletions

View File

@ -19,57 +19,34 @@ namespace webrtc {
namespace testing { namespace testing {
namespace bwe { namespace bwe {
#if BWE_TEST_LOGGING_COMPILE_TIME_ENABLE #if BWE_TEST_LOGGING_COMPILE_TIME_ENABLE
BweTestConfig::EstimatorConfig CreateEstimatorConfig(
int flow_id, bool plot_delay, bool plot_estimate) {
static const AbsoluteSendTimeRemoteBitrateEstimatorFactory factory =
AbsoluteSendTimeRemoteBitrateEstimatorFactory();
return BweTestConfig::EstimatorConfig("AST", flow_id, &factory, kAimdControl,
kRembEstimator, plot_delay,
plot_estimate);
}
BweTestConfig MakeAdaptiveBweTestConfig() {
BweTestConfig result;
result.estimator_configs.push_back(CreateEstimatorConfig(0, true, true));
return result;
}
BweTestConfig MakeMultiFlowBweTestConfig(int flow_count) {
BweTestConfig result;
for (int i = 0; i < flow_count; ++i) {
result.estimator_configs.push_back(CreateEstimatorConfig(i, false, true));
}
return result;
}
// This test fixture is used to instantiate tests running with adaptive video // This test fixture is used to instantiate tests running with adaptive video
// senders. // senders.
class BweSimulation : public BweTest, class BweSimulation : public BweTest,
public ::testing::TestWithParam<BweTestConfig> { public ::testing::TestWithParam<BandwidthEstimatorType> {
public: public:
BweSimulation() : BweTest() {} BweSimulation() : BweTest() {}
virtual ~BweSimulation() {} virtual ~BweSimulation() {}
virtual void SetUp() { protected:
const BweTestConfig& config = GetParam(); virtual void SetUp() OVERRIDE { BweTest::SetUp(); }
SetupTestFromConfig(config);
}
private: private:
DISALLOW_COPY_AND_ASSIGN(BweSimulation); DISALLOW_COPY_AND_ASSIGN(BweSimulation);
}; };
INSTANTIATE_TEST_CASE_P(VideoSendersTest, BweSimulation, INSTANTIATE_TEST_CASE_P(VideoSendersTest,
::testing::Values(MakeAdaptiveBweTestConfig())); BweSimulation,
::testing::Values(kRembEstimator,
kFullSendSideEstimator));
TEST_P(BweSimulation, SprintUplinkTest) { TEST_P(BweSimulation, SprintUplinkTest) {
VerboseLogging(true); VerboseLogging(true);
AdaptiveVideoSource source(0, 30, 300, 0, 0); AdaptiveVideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, kRembEstimator); PacketSender sender(this, &source, GetParam());
RateCounterFilter counter1(this, "sender_output"); RateCounterFilter counter1(this, "sender_output");
TraceBasedDeliveryFilter filter(this, "link_capacity"); TraceBasedDeliveryFilter filter(this, "link_capacity");
RateCounterFilter counter2(this, "receiver_input"); RateCounterFilter counter2(this, "receiver_input");
PacketReceiver receiver(this, 0, GetParam(), true, true);
ASSERT_TRUE(filter.Init(test::ResourcePath("sprint-uplink", "rx"))); ASSERT_TRUE(filter.Init(test::ResourcePath("sprint-uplink", "rx")));
RunFor(60 * 1000); RunFor(60 * 1000);
} }
@ -77,10 +54,11 @@ TEST_P(BweSimulation, SprintUplinkTest) {
TEST_P(BweSimulation, Verizon4gDownlinkTest) { TEST_P(BweSimulation, Verizon4gDownlinkTest) {
VerboseLogging(true); VerboseLogging(true);
AdaptiveVideoSource source(0, 30, 300, 0, 0); AdaptiveVideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, kRembEstimator); PacketSender sender(this, &source, GetParam());
RateCounterFilter counter1(this, "sender_output"); RateCounterFilter counter1(this, "sender_output");
TraceBasedDeliveryFilter filter(this, "link_capacity"); TraceBasedDeliveryFilter filter(this, "link_capacity");
RateCounterFilter counter2(this, "receiver_input"); RateCounterFilter counter2(this, "receiver_input");
PacketReceiver receiver(this, 0, GetParam(), true, true);
ASSERT_TRUE(filter.Init(test::ResourcePath("verizon4g-downlink", "rx"))); ASSERT_TRUE(filter.Init(test::ResourcePath("verizon4g-downlink", "rx")));
RunFor(22 * 60 * 1000); RunFor(22 * 60 * 1000);
} }
@ -88,9 +66,10 @@ TEST_P(BweSimulation, Verizon4gDownlinkTest) {
TEST_P(BweSimulation, Choke1000kbps500kbps1000kbps) { TEST_P(BweSimulation, Choke1000kbps500kbps1000kbps) {
VerboseLogging(true); VerboseLogging(true);
AdaptiveVideoSource source(0, 30, 300, 0, 0); AdaptiveVideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, kRembEstimator); PacketSender sender(this, &source, GetParam());
ChokeFilter filter(this); ChokeFilter filter(this);
RateCounterFilter counter(this, "receiver_input"); RateCounterFilter counter(this, "receiver_input");
PacketReceiver receiver(this, 0, GetParam(), true, true);
filter.SetCapacity(1000); filter.SetCapacity(1000);
filter.SetMaxDelay(500); filter.SetMaxDelay(500);
RunFor(60 * 1000); RunFor(60 * 1000);
@ -103,9 +82,10 @@ TEST_P(BweSimulation, Choke1000kbps500kbps1000kbps) {
TEST_P(BweSimulation, PacerChoke1000kbps500kbps1000kbps) { TEST_P(BweSimulation, PacerChoke1000kbps500kbps1000kbps) {
VerboseLogging(true); VerboseLogging(true);
PeriodicKeyFrameSource source(0, 30, 300, 0, 0, 1000); PeriodicKeyFrameSource source(0, 30, 300, 0, 0, 1000);
PacedVideoSender sender(this, &source, kRembEstimator); PacedVideoSender sender(this, &source, GetParam());
ChokeFilter filter(this); ChokeFilter filter(this);
RateCounterFilter counter(this, "receiver_input"); RateCounterFilter counter(this, "receiver_input");
PacketReceiver receiver(this, 0, GetParam(), true, true);
filter.SetCapacity(1000); filter.SetCapacity(1000);
filter.SetMaxDelay(500); filter.SetMaxDelay(500);
RunFor(60 * 1000); RunFor(60 * 1000);
@ -118,9 +98,10 @@ TEST_P(BweSimulation, PacerChoke1000kbps500kbps1000kbps) {
TEST_P(BweSimulation, PacerChoke10000kbps) { TEST_P(BweSimulation, PacerChoke10000kbps) {
VerboseLogging(true); VerboseLogging(true);
PeriodicKeyFrameSource source(0, 30, 300, 0, 0, 1000); PeriodicKeyFrameSource source(0, 30, 300, 0, 0, 1000);
PacedVideoSender sender(this, &source, kRembEstimator); PacedVideoSender sender(this, &source, GetParam());
ChokeFilter filter(this); ChokeFilter filter(this);
RateCounterFilter counter(this, "receiver_input"); RateCounterFilter counter(this, "receiver_input");
PacketReceiver receiver(this, 0, GetParam(), true, true);
filter.SetCapacity(10000); filter.SetCapacity(10000);
filter.SetMaxDelay(500); filter.SetMaxDelay(500);
RunFor(60 * 1000); RunFor(60 * 1000);
@ -129,9 +110,10 @@ TEST_P(BweSimulation, PacerChoke10000kbps) {
TEST_P(BweSimulation, PacerChoke200kbps30kbps200kbps) { TEST_P(BweSimulation, PacerChoke200kbps30kbps200kbps) {
VerboseLogging(true); VerboseLogging(true);
PeriodicKeyFrameSource source(0, 30, 300, 0, 0, 1000); PeriodicKeyFrameSource source(0, 30, 300, 0, 0, 1000);
PacedVideoSender sender(this, &source, kRembEstimator); PacedVideoSender sender(this, &source, GetParam());
ChokeFilter filter(this); ChokeFilter filter(this);
RateCounterFilter counter(this, "receiver_input"); RateCounterFilter counter(this, "receiver_input");
PacketReceiver receiver(this, 0, GetParam(), true, true);
filter.SetCapacity(200); filter.SetCapacity(200);
filter.SetMaxDelay(500); filter.SetMaxDelay(500);
RunFor(60 * 1000); RunFor(60 * 1000);
@ -144,9 +126,10 @@ TEST_P(BweSimulation, PacerChoke200kbps30kbps200kbps) {
TEST_P(BweSimulation, Choke200kbps30kbps200kbps) { TEST_P(BweSimulation, Choke200kbps30kbps200kbps) {
VerboseLogging(true); VerboseLogging(true);
AdaptiveVideoSource source(0, 30, 300, 0, 0); AdaptiveVideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, kRembEstimator); PacketSender sender(this, &source, GetParam());
ChokeFilter filter(this); ChokeFilter filter(this);
RateCounterFilter counter(this, "receiver_input"); RateCounterFilter counter(this, "receiver_input");
PacketReceiver receiver(this, 0, GetParam(), true, true);
filter.SetCapacity(200); filter.SetCapacity(200);
filter.SetMaxDelay(500); filter.SetMaxDelay(500);
RunFor(60 * 1000); RunFor(60 * 1000);
@ -164,6 +147,7 @@ TEST_P(BweSimulation, GoogleWifiTrace3Mbps) {
TraceBasedDeliveryFilter filter(this, "link_capacity"); TraceBasedDeliveryFilter filter(this, "link_capacity");
filter.SetMaxDelay(500); filter.SetMaxDelay(500);
RateCounterFilter counter2(this, "receiver_input"); RateCounterFilter counter2(this, "receiver_input");
PacketReceiver receiver(this, 0, GetParam(), true, true);
ASSERT_TRUE(filter.Init(test::ResourcePath("google-wifi-3mbps", "rx"))); ASSERT_TRUE(filter.Init(test::ResourcePath("google-wifi-3mbps", "rx")));
RunFor(300 * 1000); RunFor(300 * 1000);
} }
@ -176,23 +160,12 @@ TEST_P(BweSimulation, PacerGoogleWifiTrace3Mbps) {
TraceBasedDeliveryFilter filter(this, "link_capacity"); TraceBasedDeliveryFilter filter(this, "link_capacity");
filter.SetMaxDelay(500); filter.SetMaxDelay(500);
RateCounterFilter counter2(this, "receiver_input"); RateCounterFilter counter2(this, "receiver_input");
PacketReceiver receiver(this, 0, GetParam(), true, true);
ASSERT_TRUE(filter.Init(test::ResourcePath("google-wifi-3mbps", "rx"))); ASSERT_TRUE(filter.Init(test::ResourcePath("google-wifi-3mbps", "rx")));
RunFor(300 * 1000); RunFor(300 * 1000);
} }
class MultiFlowBweSimulation : public BweSimulation { TEST_P(BweSimulation, SelfFairnessTest) {
public:
MultiFlowBweSimulation() : BweSimulation() {}
virtual ~MultiFlowBweSimulation() {}
private:
DISALLOW_COPY_AND_ASSIGN(MultiFlowBweSimulation);
};
INSTANTIATE_TEST_CASE_P(VideoSendersTest, MultiFlowBweSimulation,
::testing::Values(MakeMultiFlowBweTestConfig(3)));
TEST_P(MultiFlowBweSimulation, SelfFairnessTest) {
VerboseLogging(true); VerboseLogging(true);
const int kAllFlowIds[] = {0, 1, 2}; const int kAllFlowIds[] = {0, 1, 2};
const size_t kNumFlows = sizeof(kAllFlowIds) / sizeof(kAllFlowIds[0]); const size_t kNumFlows = sizeof(kAllFlowIds) / sizeof(kAllFlowIds[0]);
@ -203,7 +176,7 @@ TEST_P(MultiFlowBweSimulation, SelfFairnessTest) {
// competing for the bandwidth. // competing for the bandwidth.
sources[i].reset( sources[i].reset(
new AdaptiveVideoSource(kAllFlowIds[i], 30, 300, 0, i * 20000)); new AdaptiveVideoSource(kAllFlowIds[i], 30, 300, 0, i * 20000));
senders[i].reset(new PacketSender(this, sources[i].get(), kRembEstimator)); senders[i].reset(new PacketSender(this, sources[i].get(), GetParam()));
} }
ChokeFilter choke(this, CreateFlowIds(kAllFlowIds, kNumFlows)); ChokeFilter choke(this, CreateFlowIds(kAllFlowIds, kNumFlows));
@ -218,10 +191,16 @@ TEST_P(MultiFlowBweSimulation, SelfFairnessTest) {
RateCounterFilter total_utilization( RateCounterFilter total_utilization(
this, CreateFlowIds(kAllFlowIds, kNumFlows), "total_utilization"); this, CreateFlowIds(kAllFlowIds, kNumFlows), "total_utilization");
scoped_ptr<PacketReceiver> receivers[kNumFlows];
for (size_t i = 0; i < kNumFlows; ++i) {
receivers[i].reset(
new PacketReceiver(this, kAllFlowIds[i], GetParam(), i == 0, false));
}
RunFor(30 * 60 * 1000); RunFor(30 * 60 * 1000);
} }
TEST_P(MultiFlowBweSimulation, PacedSelfFairnessTest) { TEST_P(BweSimulation, PacedSelfFairnessTest) {
VerboseLogging(true); VerboseLogging(true);
const int kAllFlowIds[] = {0, 1, 2}; const int kAllFlowIds[] = {0, 1, 2};
const size_t kNumFlows = sizeof(kAllFlowIds) / sizeof(kAllFlowIds[0]); const size_t kNumFlows = sizeof(kAllFlowIds) / sizeof(kAllFlowIds[0]);
@ -233,8 +212,7 @@ TEST_P(MultiFlowBweSimulation, PacedSelfFairnessTest) {
// competing for the bandwidth. // competing for the bandwidth.
sources[i].reset(new PeriodicKeyFrameSource(kAllFlowIds[i], 30, 300, 0, sources[i].reset(new PeriodicKeyFrameSource(kAllFlowIds[i], 30, 300, 0,
i * 20000, 1000)); i * 20000, 1000));
senders[i].reset( senders[i].reset(new PacedVideoSender(this, sources[i].get(), GetParam()));
new PacedVideoSender(this, sources[i].get(), kRembEstimator));
} }
ChokeFilter choke(this, CreateFlowIds(kAllFlowIds, kNumFlows)); ChokeFilter choke(this, CreateFlowIds(kAllFlowIds, kNumFlows));
@ -249,6 +227,12 @@ TEST_P(MultiFlowBweSimulation, PacedSelfFairnessTest) {
RateCounterFilter total_utilization( RateCounterFilter total_utilization(
this, CreateFlowIds(kAllFlowIds, kNumFlows), "total_utilization"); this, CreateFlowIds(kAllFlowIds, kNumFlows), "total_utilization");
scoped_ptr<PacketReceiver> receivers[kNumFlows];
for (size_t i = 0; i < kNumFlows; ++i) {
receivers[i].reset(
new PacketReceiver(this, kAllFlowIds[i], GetParam(), i == 0, false));
}
RunFor(30 * 60 * 1000); RunFor(30 * 60 * 1000);
} }
#endif // BWE_TEST_LOGGING_COMPILE_TIME_ENABLE #endif // BWE_TEST_LOGGING_COMPILE_TIME_ENABLE

View File

@ -20,92 +20,39 @@ using std::string;
namespace webrtc { namespace webrtc {
namespace testing { namespace testing {
namespace bwe { namespace bwe {
enum Estimator { kAbsSendTime, kTransmissionOffset };
BweTestConfig::EstimatorConfig EstimatorConfigs(Estimator estimator,
int flow_id) {
static const RemoteBitrateEstimatorFactory factories[] = {
RemoteBitrateEstimatorFactory(),
AbsoluteSendTimeRemoteBitrateEstimatorFactory()
};
switch (estimator) {
case kTransmissionOffset:
return BweTestConfig::EstimatorConfig("TOF", flow_id, &factories[0],
kAimdControl, kRembEstimator, false,
false);
case kAbsSendTime:
return BweTestConfig::EstimatorConfig("AST", flow_id, &factories[1],
kAimdControl, kRembEstimator, false,
false);
}
assert(false);
return BweTestConfig::EstimatorConfig();
}
struct DefaultBweTestConfig {
BweTestConfig bwe_test_config;
size_t number_of_senders;
};
DefaultBweTestConfig MakeBweTestConfig(uint32_t sender_count,
Estimator estimator) {
DefaultBweTestConfig result;
result.bwe_test_config.estimator_configs.push_back(
EstimatorConfigs(estimator, 0));
result.number_of_senders = sender_count;
return result;
}
class DefaultBweTest : public BweTest, class DefaultBweTest : public BweTest,
public ::testing::TestWithParam<DefaultBweTestConfig> { public ::testing::TestWithParam<BandwidthEstimatorType> {
public: public:
virtual ~DefaultBweTest() {} virtual ~DefaultBweTest() {}
virtual void SetUp() {
const DefaultBweTestConfig& config = GetParam();
SetupTestFromConfig(config.bwe_test_config);
for (size_t i = 0; i < config.number_of_senders; ++i) {
sources_.push_back(new VideoSource(0, 30, 300, 0, 0));
packet_senders_.push_back(
new PacketSender(this, sources_.back(), kNullEstimator));
}
}
virtual void TearDown() {
while (!packet_senders_.empty()) {
delete packet_senders_.front();
packet_senders_.pop_front();
}
while (!sources_.empty()) {
delete sources_.front();
sources_.pop_front();
}
}
protected:
std::list<VideoSource*> sources_;
std::list<PacketSender*> packet_senders_;
}; };
INSTANTIATE_TEST_CASE_P(VideoSendersTest, DefaultBweTest, INSTANTIATE_TEST_CASE_P(VideoSendersTest,
::testing::Values(MakeBweTestConfig(1, kAbsSendTime), DefaultBweTest,
MakeBweTestConfig(3, kAbsSendTime), ::testing::Values(kRembEstimator,
MakeBweTestConfig(1, kTransmissionOffset), kFullSendSideEstimator));
MakeBweTestConfig(3, kTransmissionOffset)));
TEST_P(DefaultBweTest, UnlimitedSpeed) { TEST_P(DefaultBweTest, UnlimitedSpeed) {
VerboseLogging(false); VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
PacketReceiver receiver(this, 0, GetParam(), false, false);
RunFor(10 * 60 * 1000); RunFor(10 * 60 * 1000);
} }
TEST_P(DefaultBweTest, DISABLED_SteadyLoss) { TEST_P(DefaultBweTest, DISABLED_SteadyLoss) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
LossFilter loss(this); LossFilter loss(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
loss.SetLoss(20.0); loss.SetLoss(20.0);
RunFor(10 * 60 * 1000); RunFor(10 * 60 * 1000);
} }
TEST_P(DefaultBweTest, IncreasingLoss1) { TEST_P(DefaultBweTest, IncreasingLoss1) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
LossFilter loss(this); LossFilter loss(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
for (int i = 0; i < 76; ++i) { for (int i = 0; i < 76; ++i) {
loss.SetLoss(i); loss.SetLoss(i);
RunFor(5000); RunFor(5000);
@ -113,13 +60,19 @@ TEST_P(DefaultBweTest, IncreasingLoss1) {
} }
TEST_P(DefaultBweTest, SteadyDelay) { TEST_P(DefaultBweTest, SteadyDelay) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
DelayFilter delay(this); DelayFilter delay(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
delay.SetDelay(1000); delay.SetDelay(1000);
RunFor(10 * 60 * 1000); RunFor(10 * 60 * 1000);
} }
TEST_P(DefaultBweTest, DISABLED_IncreasingDelay1) { TEST_P(DefaultBweTest, DISABLED_IncreasingDelay1) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
DelayFilter delay(this); DelayFilter delay(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
RunFor(10 * 60 * 1000); RunFor(10 * 60 * 1000);
for (int i = 0; i < 30 * 2; ++i) { for (int i = 0; i < 30 * 2; ++i) {
delay.SetDelay(i); delay.SetDelay(i);
@ -129,8 +82,11 @@ TEST_P(DefaultBweTest, DISABLED_IncreasingDelay1) {
} }
TEST_P(DefaultBweTest, IncreasingDelay2) { TEST_P(DefaultBweTest, IncreasingDelay2) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
DelayFilter delay(this); DelayFilter delay(this);
RateCounterFilter counter(this); RateCounterFilter counter(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
RunFor(1 * 60 * 1000); RunFor(1 * 60 * 1000);
for (int i = 1; i < 51; ++i) { for (int i = 1; i < 51; ++i) {
delay.SetDelay(10.0f * i); delay.SetDelay(10.0f * i);
@ -141,7 +97,10 @@ TEST_P(DefaultBweTest, IncreasingDelay2) {
} }
TEST_P(DefaultBweTest, JumpyDelay1) { TEST_P(DefaultBweTest, JumpyDelay1) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
DelayFilter delay(this); DelayFilter delay(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
RunFor(10 * 60 * 1000); RunFor(10 * 60 * 1000);
for (int i = 1; i < 200; ++i) { for (int i = 1; i < 200; ++i) {
delay.SetDelay((10 * i) % 500); delay.SetDelay((10 * i) % 500);
@ -154,14 +113,20 @@ TEST_P(DefaultBweTest, JumpyDelay1) {
} }
TEST_P(DefaultBweTest, SteadyJitter) { TEST_P(DefaultBweTest, SteadyJitter) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
JitterFilter jitter(this); JitterFilter jitter(this);
RateCounterFilter counter(this); RateCounterFilter counter(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
jitter.SetJitter(20); jitter.SetJitter(20);
RunFor(2 * 60 * 1000); RunFor(2 * 60 * 1000);
} }
TEST_P(DefaultBweTest, IncreasingJitter1) { TEST_P(DefaultBweTest, IncreasingJitter1) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
JitterFilter jitter(this); JitterFilter jitter(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
for (int i = 0; i < 2 * 60 * 2; ++i) { for (int i = 0; i < 2 * 60 * 2; ++i) {
jitter.SetJitter(i); jitter.SetJitter(i);
RunFor(10 * 1000); RunFor(10 * 1000);
@ -170,7 +135,10 @@ TEST_P(DefaultBweTest, IncreasingJitter1) {
} }
TEST_P(DefaultBweTest, IncreasingJitter2) { TEST_P(DefaultBweTest, IncreasingJitter2) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
JitterFilter jitter(this); JitterFilter jitter(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
RunFor(30 * 1000); RunFor(30 * 1000);
for (int i = 1; i < 51; ++i) { for (int i = 1; i < 51; ++i) {
jitter.SetJitter(10.0f * i); jitter.SetJitter(10.0f * i);
@ -181,13 +149,19 @@ TEST_P(DefaultBweTest, IncreasingJitter2) {
} }
TEST_P(DefaultBweTest, SteadyReorder) { TEST_P(DefaultBweTest, SteadyReorder) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
ReorderFilter reorder(this); ReorderFilter reorder(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
reorder.SetReorder(20.0); reorder.SetReorder(20.0);
RunFor(10 * 60 * 1000); RunFor(10 * 60 * 1000);
} }
TEST_P(DefaultBweTest, IncreasingReorder1) { TEST_P(DefaultBweTest, IncreasingReorder1) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
ReorderFilter reorder(this); ReorderFilter reorder(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
for (int i = 0; i < 76; ++i) { for (int i = 0; i < 76; ++i) {
reorder.SetReorder(i); reorder.SetReorder(i);
RunFor(5000); RunFor(5000);
@ -195,13 +169,19 @@ TEST_P(DefaultBweTest, IncreasingReorder1) {
} }
TEST_P(DefaultBweTest, DISABLED_SteadyChoke) { TEST_P(DefaultBweTest, DISABLED_SteadyChoke) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
ChokeFilter choke(this); ChokeFilter choke(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
choke.SetCapacity(140); choke.SetCapacity(140);
RunFor(10 * 60 * 1000); RunFor(10 * 60 * 1000);
} }
TEST_P(DefaultBweTest, DISABLED_IncreasingChoke1) { TEST_P(DefaultBweTest, DISABLED_IncreasingChoke1) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
ChokeFilter choke(this); ChokeFilter choke(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
for (int i = 1200; i >= 100; i -= 100) { for (int i = 1200; i >= 100; i -= 100) {
choke.SetCapacity(i); choke.SetCapacity(i);
RunFor(5000); RunFor(5000);
@ -209,7 +189,10 @@ TEST_P(DefaultBweTest, DISABLED_IncreasingChoke1) {
} }
TEST_P(DefaultBweTest, DISABLED_IncreasingChoke2) { TEST_P(DefaultBweTest, DISABLED_IncreasingChoke2) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
ChokeFilter choke(this); ChokeFilter choke(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
RunFor(60 * 1000); RunFor(60 * 1000);
for (int i = 1200; i >= 100; i -= 20) { for (int i = 1200; i >= 100; i -= 20) {
choke.SetCapacity(i); choke.SetCapacity(i);
@ -218,9 +201,12 @@ TEST_P(DefaultBweTest, DISABLED_IncreasingChoke2) {
} }
TEST_P(DefaultBweTest, DISABLED_Multi1) { TEST_P(DefaultBweTest, DISABLED_Multi1) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
DelayFilter delay(this); DelayFilter delay(this);
ChokeFilter choke(this); ChokeFilter choke(this);
RateCounterFilter counter(this); RateCounterFilter counter(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
choke.SetCapacity(1000); choke.SetCapacity(1000);
RunFor(1 * 60 * 1000); RunFor(1 * 60 * 1000);
for (int i = 1; i < 51; ++i) { for (int i = 1; i < 51; ++i) {
@ -233,9 +219,12 @@ TEST_P(DefaultBweTest, DISABLED_Multi1) {
} }
TEST_P(DefaultBweTest, Multi2) { TEST_P(DefaultBweTest, Multi2) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
ChokeFilter choke(this); ChokeFilter choke(this);
JitterFilter jitter(this); JitterFilter jitter(this);
RateCounterFilter counter(this); RateCounterFilter counter(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
choke.SetCapacity(2000); choke.SetCapacity(2000);
jitter.SetJitter(120); jitter.SetJitter(120);
RunFor(5 * 60 * 1000); RunFor(5 * 60 * 1000);
@ -243,18 +232,13 @@ TEST_P(DefaultBweTest, Multi2) {
// This test fixture is used to instantiate tests running with adaptive video // This test fixture is used to instantiate tests running with adaptive video
// senders. // senders.
class BweFeedbackTest : public BweTest, class BweFeedbackTest
public ::testing::TestWithParam<BweTestConfig> { : public BweTest,
public ::testing::TestWithParam<BandwidthEstimatorType> {
public: public:
BweFeedbackTest() : BweTest() {} BweFeedbackTest() : BweTest() {}
virtual ~BweFeedbackTest() {} virtual ~BweFeedbackTest() {}
virtual void SetUp() {
BweTestConfig config;
config.estimator_configs.push_back(EstimatorConfigs(kAbsSendTime, 0));
SetupTestFromConfig(config);
}
void PrintResults(double max_throughput_kbps, Stats<double> throughput_kbps, void PrintResults(double max_throughput_kbps, Stats<double> throughput_kbps,
Stats<double> delay_ms) { Stats<double> delay_ms) {
double utilization = throughput_kbps.GetMean() / max_throughput_kbps; double utilization = throughput_kbps.GetMean() / max_throughput_kbps;
@ -280,15 +264,24 @@ class BweFeedbackTest : public BweTest,
false); false);
} }
protected:
virtual void SetUp() OVERRIDE { BweTest::SetUp(); }
private: private:
DISALLOW_COPY_AND_ASSIGN(BweFeedbackTest); DISALLOW_COPY_AND_ASSIGN(BweFeedbackTest);
}; };
TEST_F(BweFeedbackTest, Choke1000kbps500kbps1000kbps) { INSTANTIATE_TEST_CASE_P(VideoSendersTest,
BweFeedbackTest,
::testing::Values(kRembEstimator,
kFullSendSideEstimator));
TEST_P(BweFeedbackTest, Choke1000kbps500kbps1000kbps) {
AdaptiveVideoSource source(0, 30, 300, 0, 0); AdaptiveVideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, kRembEstimator); PacketSender sender(this, &source, GetParam());
ChokeFilter filter(this); ChokeFilter filter(this);
RateCounterFilter counter(this, "receiver_input"); RateCounterFilter counter(this, "receiver_input");
PacketReceiver receiver(this, 0, GetParam(), false, false);
const int kHighCapacityKbps = 1000; const int kHighCapacityKbps = 1000;
const int kLowCapacityKbps = 500; const int kLowCapacityKbps = 500;
filter.SetCapacity(kHighCapacityKbps); filter.SetCapacity(kHighCapacityKbps);
@ -302,11 +295,12 @@ TEST_F(BweFeedbackTest, Choke1000kbps500kbps1000kbps) {
counter.GetBitrateStats(), filter.GetDelayStats()); counter.GetBitrateStats(), filter.GetDelayStats());
} }
TEST_F(BweFeedbackTest, Choke200kbps30kbps200kbps) { TEST_P(BweFeedbackTest, Choke200kbps30kbps200kbps) {
AdaptiveVideoSource source(0, 30, 300, 0, 0); AdaptiveVideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, kRembEstimator); PacketSender sender(this, &source, GetParam());
ChokeFilter filter(this); ChokeFilter filter(this);
RateCounterFilter counter(this, "receiver_input"); RateCounterFilter counter(this, "receiver_input");
PacketReceiver receiver(this, 0, GetParam(), false, false);
const int kHighCapacityKbps = 200; const int kHighCapacityKbps = 200;
const int kLowCapacityKbps = 30; const int kLowCapacityKbps = 30;
filter.SetCapacity(kHighCapacityKbps); filter.SetCapacity(kHighCapacityKbps);
@ -321,12 +315,13 @@ TEST_F(BweFeedbackTest, Choke200kbps30kbps200kbps) {
counter.GetBitrateStats(), filter.GetDelayStats()); counter.GetBitrateStats(), filter.GetDelayStats());
} }
TEST_F(BweFeedbackTest, Verizon4gDownlinkTest) { TEST_P(BweFeedbackTest, Verizon4gDownlinkTest) {
AdaptiveVideoSource source(0, 30, 300, 0, 0); AdaptiveVideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, kRembEstimator); PacketSender sender(this, &source, GetParam());
RateCounterFilter counter1(this, "sender_output"); RateCounterFilter counter1(this, "sender_output");
TraceBasedDeliveryFilter filter(this, "link_capacity"); TraceBasedDeliveryFilter filter(this, "link_capacity");
RateCounterFilter counter2(this, "receiver_input"); RateCounterFilter counter2(this, "receiver_input");
PacketReceiver receiver(this, 0, GetParam(), false, false);
ASSERT_TRUE(filter.Init(test::ResourcePath("verizon4g-downlink", "rx"))); ASSERT_TRUE(filter.Init(test::ResourcePath("verizon4g-downlink", "rx")));
RunFor(22 * 60 * 1000); RunFor(22 * 60 * 1000);
PrintResults(filter.GetBitrateStats().GetMean(), counter2.GetBitrateStats(), PrintResults(filter.GetBitrateStats().GetMean(), counter2.GetBitrateStats(),
@ -334,13 +329,14 @@ TEST_F(BweFeedbackTest, Verizon4gDownlinkTest) {
} }
// webrtc:3277 // webrtc:3277
TEST_F(BweFeedbackTest, DISABLED_GoogleWifiTrace3Mbps) { TEST_P(BweFeedbackTest, DISABLED_GoogleWifiTrace3Mbps) {
AdaptiveVideoSource source(0, 30, 300, 0, 0); AdaptiveVideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, kRembEstimator); PacketSender sender(this, &source, GetParam());
RateCounterFilter counter1(this, "sender_output"); RateCounterFilter counter1(this, "sender_output");
TraceBasedDeliveryFilter filter(this, "link_capacity"); TraceBasedDeliveryFilter filter(this, "link_capacity");
filter.SetMaxDelay(500); filter.SetMaxDelay(500);
RateCounterFilter counter2(this, "receiver_input"); RateCounterFilter counter2(this, "receiver_input");
PacketReceiver receiver(this, 0, GetParam(), false, false);
ASSERT_TRUE(filter.Init(test::ResourcePath("google-wifi-3mbps", "rx"))); ASSERT_TRUE(filter.Init(test::ResourcePath("google-wifi-3mbps", "rx")));
RunFor(300 * 1000); RunFor(300 * 1000);
PrintResults(filter.GetBitrateStats().GetMean(), counter2.GetBitrateStats(), PrintResults(filter.GetBitrateStats().GetMean(), counter2.GetBitrateStats(),

View File

@ -25,81 +25,41 @@ using std::vector;
namespace webrtc { namespace webrtc {
namespace testing { namespace testing {
namespace bwe { namespace bwe {
class BweReceiver {
class PacketReceiver {
public: public:
PacketReceiver(const string& test_name, explicit BweReceiver(int flow_id) : flow_id_(flow_id) {}
const BweTestConfig::EstimatorConfig& config) virtual ~BweReceiver() {}
: flow_id_(config.flow_id),
debug_name_(config.debug_name),
delay_log_prefix_(),
last_delay_plot_ms_(0),
plot_delay_(config.plot_delay),
baseline_(BaseLineFileInterface::Create(test_name + "_" + debug_name_,
config.update_baseline)) {
// Setup the prefix strings used when logging.
std::stringstream ss;
ss << "Delay_" << config.flow_id << "#2";
delay_log_prefix_ = ss.str();
}
virtual ~PacketReceiver() {}
virtual void ReceivePacket(const Packet& packet) {}
virtual void ReceivePacket(int64_t arrival_time_ms,
size_t payload_size,
const RTPHeader& header) {}
virtual FeedbackPacket* GetFeedback() { return NULL; } virtual FeedbackPacket* GetFeedback() { return NULL; }
void LogStats() {
BWE_TEST_LOGGING_CONTEXT(debug_name_);
BWE_TEST_LOGGING_CONTEXT("Mean");
stats_.Log("kbps");
}
void VerifyOrWriteBaseline() { EXPECT_TRUE(baseline_->VerifyOrWrite()); }
protected: protected:
static const int kDelayPlotIntervalMs = 100; int flow_id_;
void LogDelay(int64_t arrival_time_ms, int64_t send_time_ms) {
if (plot_delay_) {
if (arrival_time_ms - last_delay_plot_ms_ > kDelayPlotIntervalMs) {
BWE_TEST_LOGGING_PLOT(delay_log_prefix_, arrival_time_ms,
arrival_time_ms - send_time_ms);
last_delay_plot_ms_ = arrival_time_ms;
}
}
}
const int flow_id_;
const string debug_name_;
string delay_log_prefix_;
int64_t last_delay_plot_ms_;
bool plot_delay_;
scoped_ptr<BaseLineFileInterface> baseline_;
Stats<double> stats_;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PacketReceiver);
}; };
class SendSideBweReceiver : public PacketReceiver { int64_t GetAbsSendTimeInMs(uint32_t abs_send_time) {
public: const int kInterArrivalShift = 26;
SendSideBweReceiver(const string& test_name, const int kAbsSendTimeInterArrivalUpshift = 8;
const BweTestConfig::EstimatorConfig& config) const double kTimestampToMs =
: PacketReceiver(test_name, config) {} 1000.0 / static_cast<double>(1 << kInterArrivalShift);
uint32_t timestamp = abs_send_time << kAbsSendTimeInterArrivalUpshift;
return static_cast<int64_t>(timestamp) * kTimestampToMs;
}
virtual void EatPacket(const Packet& packet) { class SendSideBweReceiver : public BweReceiver {
const MediaPacket& media_packet = static_cast<const MediaPacket&>(packet); public:
// We're treating the send time (from previous filter) as the arrival explicit SendSideBweReceiver(int flow_id) : BweReceiver(flow_id) {}
// time once packet reaches the estimator. virtual void ReceivePacket(int64_t arrival_time_ms,
int64_t arrival_time_ms = (media_packet.send_time_us() + 500) / 1000; size_t payload_size,
BWE_TEST_LOGGING_TIME(arrival_time_ms); const RTPHeader& header) OVERRIDE {
LogDelay(arrival_time_ms, (media_packet.creation_time_us() + 500) / 1000);
packet_feedback_vector_.push_back(PacketInfo( packet_feedback_vector_.push_back(PacketInfo(
arrival_time_ms, media_packet.GetAbsSendTimeInMs(), arrival_time_ms, GetAbsSendTimeInMs(header.extension.absoluteSendTime),
media_packet.header().sequenceNumber, media_packet.payload_size())); header.sequenceNumber, payload_size));
} }
virtual FeedbackPacket* GetFeedback() { virtual FeedbackPacket* GetFeedback() OVERRIDE {
FeedbackPacket* fb = FeedbackPacket* fb =
new SendSideBweFeedback(flow_id_, 0, packet_feedback_vector_); new SendSideBweFeedback(flow_id_, 0, packet_feedback_vector_);
packet_feedback_vector_.clear(); packet_feedback_vector_.clear();
@ -110,44 +70,33 @@ class SendSideBweReceiver : public PacketReceiver {
std::vector<PacketInfo> packet_feedback_vector_; std::vector<PacketInfo> packet_feedback_vector_;
}; };
class RembReceiver : public PacketReceiver, public RemoteBitrateObserver { class RembReceiver : public BweReceiver, public RemoteBitrateObserver {
public: public:
static const uint32_t kRemoteBitrateEstimatorMinBitrateBps = 30000; static const uint32_t kRemoteBitrateEstimatorMinBitrateBps = 30000;
RembReceiver(const string& test_name, RembReceiver(int flow_id, bool plot)
const BweTestConfig::EstimatorConfig& config) : BweReceiver(flow_id),
: PacketReceiver(test_name, config),
estimate_log_prefix_(), estimate_log_prefix_(),
plot_estimate_(config.plot_estimate), plot_estimate_(plot),
clock_(0), clock_(0),
recv_stats_(ReceiveStatistics::Create(&clock_)), recv_stats_(ReceiveStatistics::Create(&clock_)),
latest_estimate_bps_(-1), latest_estimate_bps_(-1),
estimator_(config.estimator_factory->Create( estimator_(AbsoluteSendTimeRemoteBitrateEstimatorFactory().Create(
this, this,
&clock_, &clock_,
config.control_type, kAimdControl,
kRemoteBitrateEstimatorMinBitrateBps)) { kRemoteBitrateEstimatorMinBitrateBps)) {
assert(estimator_.get());
assert(baseline_.get());
std::stringstream ss; std::stringstream ss;
ss.str(""); ss << "Estimate_" << flow_id_ << "#1";
ss << "Estimate_" << config.flow_id << "#1";
estimate_log_prefix_ = ss.str(); estimate_log_prefix_ = ss.str();
// Default RTT in RemoteRateControl is 200 ms ; 50 ms is more realistic. // Default RTT in RemoteRateControl is 200 ms ; 50 ms is more realistic.
estimator_->OnRttUpdate(50); estimator_->OnRttUpdate(50);
} }
virtual void ReceivePacket(const Packet& packet) { virtual void ReceivePacket(int64_t arrival_time_ms,
BWE_TEST_LOGGING_CONTEXT(debug_name_); size_t payload_size,
assert(packet.GetPacketType() == Packet::kMediaPacket); const RTPHeader& header) {
const MediaPacket& media_packet = static_cast<const MediaPacket&>(packet); recv_stats_->IncomingPacket(header, payload_size, false);
// We're treating the send time (from previous filter) as the arrival
// time once packet reaches the estimator.
int64_t arrival_time_ms = (media_packet.send_time_us() + 500) / 1000;
BWE_TEST_LOGGING_TIME(arrival_time_ms);
LogDelay(arrival_time_ms, (media_packet.creation_time_us() + 500) / 1000);
recv_stats_->IncomingPacket(media_packet.header(),
media_packet.payload_size(), false);
latest_estimate_bps_ = -1; latest_estimate_bps_ = -1;
@ -157,15 +106,14 @@ class RembReceiver : public PacketReceiver, public RemoteBitrateObserver {
estimator_->Process(); estimator_->Process();
step_ms = std::max<int64_t>(estimator_->TimeUntilNextProcess(), 0); step_ms = std::max<int64_t>(estimator_->TimeUntilNextProcess(), 0);
} }
estimator_->IncomingPacket(arrival_time_ms, media_packet.payload_size(), estimator_->IncomingPacket(arrival_time_ms, payload_size, header);
media_packet.header());
clock_.AdvanceTimeMilliseconds(arrival_time_ms - clock_.AdvanceTimeMilliseconds(arrival_time_ms -
clock_.TimeInMilliseconds()); clock_.TimeInMilliseconds());
ASSERT_TRUE(arrival_time_ms == clock_.TimeInMilliseconds()); ASSERT_TRUE(arrival_time_ms == clock_.TimeInMilliseconds());
} }
virtual FeedbackPacket* GetFeedback() { virtual FeedbackPacket* GetFeedback() {
BWE_TEST_LOGGING_CONTEXT(debug_name_); BWE_TEST_LOGGING_CONTEXT("Remb");
uint32_t estimated_bps = 0; uint32_t estimated_bps = 0;
RembFeedback* feedback = NULL; RembFeedback* feedback = NULL;
if (LatestEstimate(&estimated_bps)) { if (LatestEstimate(&estimated_bps)) {
@ -176,10 +124,9 @@ class RembReceiver : public PacketReceiver, public RemoteBitrateObserver {
} }
feedback = new RembFeedback(flow_id_, clock_.TimeInMilliseconds(), feedback = new RembFeedback(flow_id_, clock_.TimeInMilliseconds(),
estimated_bps, report_block); estimated_bps, report_block);
baseline_->Estimate(clock_.TimeInMilliseconds(), estimated_bps);
double estimated_kbps = static_cast<double>(estimated_bps) / 1000.0; double estimated_kbps = static_cast<double>(estimated_bps) / 1000.0;
stats_.Push(estimated_kbps); RTC_UNUSED(estimated_kbps);
if (plot_estimate_) { if (plot_estimate_) {
BWE_TEST_LOGGING_PLOT(estimate_log_prefix_, clock_.TimeInMilliseconds(), BWE_TEST_LOGGING_PLOT(estimate_log_prefix_, clock_.TimeInMilliseconds(),
estimated_kbps); estimated_kbps);
@ -228,22 +175,77 @@ class RembReceiver : public PacketReceiver, public RemoteBitrateObserver {
DISALLOW_IMPLICIT_CONSTRUCTORS(RembReceiver); DISALLOW_IMPLICIT_CONSTRUCTORS(RembReceiver);
}; };
PacketReceiver* CreatePacketReceiver( BweReceiver* CreateBweReceiver(BandwidthEstimatorType type,
BandwidthEstimatorType type, int flow_id,
const string& test_name, bool plot) {
const BweTestConfig::EstimatorConfig& config) {
switch (type) { switch (type) {
case kRembEstimator: case kRembEstimator:
return new RembReceiver(test_name, config); return new RembReceiver(flow_id, plot);
case kFullSendSideEstimator: case kFullSendSideEstimator:
return new SendSideBweReceiver(test_name, config); return new SendSideBweReceiver(flow_id);
case kNullEstimator: case kNullEstimator:
return new PacketReceiver(test_name, config); return new BweReceiver(flow_id);
} }
assert(false); assert(false);
return NULL; return NULL;
} }
PacketReceiver::PacketReceiver(PacketProcessorListener* listener,
int flow_id,
BandwidthEstimatorType bwe_type,
bool plot_delay,
bool plot_bwe)
: PacketProcessor(listener, flow_id, kReceiver),
delay_log_prefix_(),
last_delay_plot_ms_(0),
plot_delay_(plot_delay),
bwe_receiver_(CreateBweReceiver(bwe_type, flow_id, plot_bwe)) {
// Setup the prefix strings used when logging.
std::stringstream ss;
ss << "Delay_" << flow_id << "#2";
delay_log_prefix_ = ss.str();
}
PacketReceiver::~PacketReceiver() {
}
void PacketReceiver::RunFor(int64_t time_ms, Packets* in_out) {
for (const auto* packet : *in_out) {
// PacketReceivers are only associated with a single stream, and therefore
// should only process a single flow id.
// TODO(holmer): Break this out into a Demuxer which implements both
// PacketProcessorListener and PacketProcessor.
if (packet->flow_id() != *flow_ids().begin())
continue;
BWE_TEST_LOGGING_CONTEXT("Receiver");
assert(packet->GetPacketType() == Packet::kMedia);
const MediaPacket& media_packet = static_cast<const MediaPacket&>(*packet);
// We're treating the send time (from previous filter) as the arrival
// time once packet reaches the estimator.
int64_t arrival_time_ms = (media_packet.send_time_us() + 500) / 1000;
BWE_TEST_LOGGING_TIME(arrival_time_ms);
PlotDelay(arrival_time_ms, (media_packet.creation_time_us() + 500) / 1000);
bwe_receiver_->ReceivePacket(arrival_time_ms, media_packet.payload_size(),
media_packet.header());
}
}
FeedbackPacket* PacketReceiver::GetFeedback() {
return bwe_receiver_->GetFeedback();
}
void PacketReceiver::PlotDelay(int64_t arrival_time_ms, int64_t send_time_ms) {
static const int kDelayPlotIntervalMs = 100;
if (!plot_delay_)
return;
if (arrival_time_ms - last_delay_plot_ms_ > kDelayPlotIntervalMs) {
BWE_TEST_LOGGING_PLOT(delay_log_prefix_, arrival_time_ms,
arrival_time_ms - send_time_ms);
last_delay_plot_ms_ = arrival_time_ms;
}
}
class PacketProcessorRunner { class PacketProcessorRunner {
public: public:
explicit PacketProcessorRunner(PacketProcessor* processor) explicit PacketProcessorRunner(PacketProcessor* processor)
@ -309,51 +311,35 @@ class PacketProcessorRunner {
}; };
BweTest::BweTest() BweTest::BweTest()
: run_time_ms_(0), : run_time_ms_(0), time_now_ms_(-1), simulation_interval_ms_(-1) {
time_now_ms_(-1),
simulation_interval_ms_(-1),
estimators_(),
processors_() {
} }
BweTest::~BweTest() { BweTest::~BweTest() {
BWE_TEST_LOGGING_GLOBAL_ENABLE(true);
for (const auto& estimator : estimators_) {
estimator.second->VerifyOrWriteBaseline();
estimator.second->LogStats();
}
BWE_TEST_LOGGING_GLOBAL_CONTEXT("");
for (const auto& estimator : estimators_) {
delete estimator.second;
}
} }
void BweTest::SetupTestFromConfig(const BweTestConfig& config) { void BweTest::SetUp() {
const ::testing::TestInfo* const test_info = const ::testing::TestInfo* const test_info =
::testing::UnitTest::GetInstance()->current_test_info(); ::testing::UnitTest::GetInstance()->current_test_info();
string test_name = string test_name =
string(test_info->test_case_name()) + "_" + string(test_info->name()); string(test_info->test_case_name()) + "_" + string(test_info->name());
BWE_TEST_LOGGING_GLOBAL_CONTEXT(test_name); BWE_TEST_LOGGING_GLOBAL_CONTEXT(test_name);
for (const auto& estimator_config : config.estimator_configs) {
estimators_.insert(
std::make_pair(estimator_config.flow_id,
CreatePacketReceiver(estimator_config.bwe_type,
test_name, estimator_config)));
}
BWE_TEST_LOGGING_GLOBAL_ENABLE(false); BWE_TEST_LOGGING_GLOBAL_ENABLE(false);
} }
void BweTest::AddPacketProcessor(PacketProcessor* processor, bool is_sender) { void BweTest::AddPacketProcessor(PacketProcessor* processor,
ProcessorType processor_type) {
assert(processor); assert(processor);
if (is_sender) { switch (processor_type) {
senders_.push_back(static_cast<PacketSender*>(processor)); case kSender:
senders_.push_back(static_cast<PacketSender*>(processor));
break;
case kReceiver:
receivers_.push_back(static_cast<PacketReceiver*>(processor));
break;
case kRegular:
break;
} }
processors_.push_back(PacketProcessorRunner(processor)); processors_.push_back(PacketProcessorRunner(processor));
for (const int& flow_id : processor->flow_ids()) {
RTC_UNUSED(flow_id);
assert(estimators_.count(flow_id) == 1);
}
} }
void BweTest::RemovePacketProcessor(PacketProcessor* processor) { void BweTest::RemovePacketProcessor(PacketProcessor* processor) {
@ -371,8 +357,8 @@ void BweTest::VerboseLogging(bool enable) {
BWE_TEST_LOGGING_GLOBAL_ENABLE(enable); BWE_TEST_LOGGING_GLOBAL_ENABLE(enable);
} }
void BweTest::GiveFeedbackToAffectedSenders(PacketReceiver* estimator) { void BweTest::GiveFeedbackToAffectedSenders(PacketReceiver* receiver) {
FeedbackPacket* feedback = estimator->GetFeedback(); FeedbackPacket* feedback = receiver->GetFeedback();
if (feedback) { if (feedback) {
for (PacketSender* sender : senders_) { for (PacketSender* sender : senders_) {
if (sender->flow_ids().find(feedback->flow_id()) != if (sender->flow_ids().find(feedback->flow_id()) !=
@ -418,15 +404,11 @@ void BweTest::RunFor(int64_t time_ms) {
ASSERT_TRUE(IsTimeSorted(packets)); ASSERT_TRUE(IsTimeSorted(packets));
} }
for (const Packet* packet : packets) { for (const auto* packet : packets)
EstimatorMap::iterator est_it = estimators_.find(packet->flow_id());
ASSERT_TRUE(est_it != estimators_.end());
est_it->second->ReceivePacket(*packet);
delete packet; delete packet;
}
for (const auto& estimator : estimators_) { for (const auto& receiver : receivers_) {
GiveFeedbackToAffectedSenders(estimator.second); GiveFeedbackToAffectedSenders(receiver);
} }
} }
} }

View File

@ -18,108 +18,68 @@
namespace webrtc { namespace webrtc {
struct RemoteBitrateEstimatorFactory;
namespace testing { namespace testing {
namespace bwe { namespace bwe {
struct BweTestConfig { class BweReceiver;
struct EstimatorConfig {
EstimatorConfig()
: debug_name(),
flow_id(0),
estimator_factory(NULL),
control_type(kAimdControl),
bwe_type(kRembEstimator),
update_baseline(false),
plot_delay(true),
plot_estimate(true) {}
EstimatorConfig(std::string debug_name,
int flow_id,
const RemoteBitrateEstimatorFactory* estimator_factory,
BandwidthEstimatorType estimator_type,
bool plot_delay,
bool plot_estimate)
: debug_name(debug_name),
flow_id(flow_id),
estimator_factory(estimator_factory),
control_type(kAimdControl),
bwe_type(kRembEstimator),
update_baseline(false),
plot_delay(plot_delay),
plot_estimate(plot_estimate) {}
EstimatorConfig(std::string debug_name,
int flow_id,
const RemoteBitrateEstimatorFactory* estimator_factory,
RateControlType control_type,
BandwidthEstimatorType estimator_type,
bool plot_delay,
bool plot_estimate)
: debug_name(debug_name),
flow_id(flow_id),
estimator_factory(estimator_factory),
control_type(control_type),
bwe_type(estimator_type),
update_baseline(false),
plot_delay(plot_delay),
plot_estimate(plot_estimate) {}
EstimatorConfig(std::string debug_name,
int flow_id,
const RemoteBitrateEstimatorFactory* estimator_factory,
RateControlType control_type,
BandwidthEstimatorType estimator_type,
bool update_baseline)
: debug_name(debug_name),
flow_id(flow_id),
estimator_factory(estimator_factory),
control_type(control_type),
bwe_type(kRembEstimator),
update_baseline(update_baseline),
plot_delay(false),
plot_estimate(false) {}
std::string debug_name;
int flow_id;
const RemoteBitrateEstimatorFactory* estimator_factory;
RateControlType control_type;
BandwidthEstimatorType bwe_type;
bool update_baseline;
bool plot_delay;
bool plot_estimate;
};
std::vector<EstimatorConfig> estimator_configs;
};
class PacketReceiver; class PacketReceiver;
class PacketProcessorRunner; class PacketProcessorRunner;
class PacketReceiver : public PacketProcessor {
public:
PacketReceiver(PacketProcessorListener* listener,
int flow_id,
BandwidthEstimatorType bwe_type,
bool plot_delay,
bool plot_bwe);
~PacketReceiver();
// Implements PacketProcessor.
virtual void RunFor(int64_t time_ms, Packets* in_out) OVERRIDE;
FeedbackPacket* GetFeedback();
void LogStats();
protected:
void PlotDelay(int64_t arrival_time_ms, int64_t send_time_ms);
std::string delay_log_prefix_;
int64_t last_delay_plot_ms_;
bool plot_delay_;
scoped_ptr<BweReceiver> bwe_receiver_;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PacketReceiver);
};
class BweTest : public PacketProcessorListener { class BweTest : public PacketProcessorListener {
public: public:
BweTest(); BweTest();
virtual ~BweTest(); virtual ~BweTest();
virtual void AddPacketProcessor(PacketProcessor* processor, bool is_sender); virtual void AddPacketProcessor(PacketProcessor* processor,
ProcessorType type);
virtual void RemovePacketProcessor(PacketProcessor* processor); virtual void RemovePacketProcessor(PacketProcessor* processor);
protected: protected:
void SetupTestFromConfig(const BweTestConfig& config); virtual void SetUp();
void VerboseLogging(bool enable); void VerboseLogging(bool enable);
void RunFor(int64_t time_ms); void RunFor(int64_t time_ms);
std::string GetTestName() const; std::string GetTestName() const;
private: private:
typedef std::map<int, PacketReceiver*> EstimatorMap;
void FindPacketsToProcess(const FlowIds& flow_ids, Packets* in, void FindPacketsToProcess(const FlowIds& flow_ids, Packets* in,
Packets* out); Packets* out);
void GiveFeedbackToAffectedSenders(PacketReceiver* estimator); void GiveFeedbackToAffectedSenders(PacketReceiver* receiver);
int64_t run_time_ms_; int64_t run_time_ms_;
int64_t time_now_ms_; int64_t time_now_ms_;
int64_t simulation_interval_ms_; int64_t simulation_interval_ms_;
EstimatorMap estimators_;
Packets previous_packets_; Packets previous_packets_;
std::vector<PacketSender*> senders_; std::vector<PacketSender*> senders_;
std::vector<PacketReceiver*> receivers_;
std::vector<PacketProcessorRunner> processors_; std::vector<PacketProcessorRunner> processors_;
DISALLOW_COPY_AND_ASSIGN(BweTest); DISALLOW_COPY_AND_ASSIGN(BweTest);

View File

@ -163,16 +163,6 @@ MediaPacket::MediaPacket(int64_t send_time_us, uint32_t sequence_number)
header_.sequenceNumber = sequence_number; header_.sequenceNumber = sequence_number;
} }
int64_t MediaPacket::GetAbsSendTimeInMs() const {
const int kInterArrivalShift = 26;
const int kAbsSendTimeInterArrivalUpshift = 8;
const double kTimestampToMs =
1000.0 / static_cast<double>(1 << kInterArrivalShift);
uint32_t timestamp = header_.extension.absoluteSendTime
<< kAbsSendTimeInterArrivalUpshift;
return static_cast<int64_t>(timestamp) * kTimestampToMs;
}
void MediaPacket::SetAbsSendTimeMs(int64_t abs_send_time_ms) { void MediaPacket::SetAbsSendTimeMs(int64_t abs_send_time_ms) {
header_.extension.hasAbsoluteSendTime = true; header_.extension.hasAbsoluteSendTime = true;
header_.extension.absoluteSendTime = ((static_cast<int64_t>(abs_send_time_ms * header_.extension.absoluteSendTime = ((static_cast<int64_t>(abs_send_time_ms *
@ -208,30 +198,30 @@ bool IsTimeSorted(const Packets& packets) {
} }
PacketProcessor::PacketProcessor(PacketProcessorListener* listener, PacketProcessor::PacketProcessor(PacketProcessorListener* listener,
bool is_sender) ProcessorType type)
: listener_(listener) { : listener_(listener) {
flow_ids_.insert(0); flow_ids_.insert(0);
if (listener_) { if (listener_) {
listener_->AddPacketProcessor(this, is_sender); listener_->AddPacketProcessor(this, type);
} }
} }
PacketProcessor::PacketProcessor(PacketProcessorListener* listener, PacketProcessor::PacketProcessor(PacketProcessorListener* listener,
int flow_id, int flow_id,
bool is_sender) ProcessorType type)
: listener_(listener) { : listener_(listener) {
flow_ids_.insert(flow_id); flow_ids_.insert(flow_id);
if (listener_) { if (listener_) {
listener_->AddPacketProcessor(this, is_sender); listener_->AddPacketProcessor(this, type);
} }
} }
PacketProcessor::PacketProcessor(PacketProcessorListener* listener, PacketProcessor::PacketProcessor(PacketProcessorListener* listener,
const FlowIds& flow_ids, const FlowIds& flow_ids,
bool is_sender) ProcessorType type)
: listener_(listener), flow_ids_(flow_ids) { : listener_(listener), flow_ids_(flow_ids) {
if (listener_) { if (listener_) {
listener_->AddPacketProcessor(this, is_sender); listener_->AddPacketProcessor(this, type);
} }
} }
@ -242,24 +232,26 @@ PacketProcessor::~PacketProcessor() {
} }
RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener) RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener)
: PacketProcessor(listener, false), : PacketProcessor(listener, kRegular),
rate_counter_(new RateCounter()), rate_counter_(new RateCounter()),
packets_per_second_stats_(), packets_per_second_stats_(),
kbps_stats_(), kbps_stats_(),
name_("") {} name_("") {
}
RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener, RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener,
const std::string& name) const std::string& name)
: PacketProcessor(listener, false), : PacketProcessor(listener, kRegular),
rate_counter_(new RateCounter()), rate_counter_(new RateCounter()),
packets_per_second_stats_(), packets_per_second_stats_(),
kbps_stats_(), kbps_stats_(),
name_(name) {} name_(name) {
}
RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener, RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener,
const FlowIds& flow_ids, const FlowIds& flow_ids,
const std::string& name) const std::string& name)
: PacketProcessor(listener, flow_ids, false), : PacketProcessor(listener, flow_ids, kRegular),
rate_counter_(new RateCounter()), rate_counter_(new RateCounter()),
packets_per_second_stats_(), packets_per_second_stats_(),
kbps_stats_(), kbps_stats_(),
@ -310,7 +302,7 @@ void RateCounterFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
} }
LossFilter::LossFilter(PacketProcessorListener* listener) LossFilter::LossFilter(PacketProcessorListener* listener)
: PacketProcessor(listener, false), : PacketProcessor(listener, kRegular),
random_(0x12345678), random_(0x12345678),
loss_fraction_(0.0f) { loss_fraction_(0.0f) {
} }
@ -336,9 +328,7 @@ void LossFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
} }
DelayFilter::DelayFilter(PacketProcessorListener* listener) DelayFilter::DelayFilter(PacketProcessorListener* listener)
: PacketProcessor(listener, false), : PacketProcessor(listener, kRegular), delay_us_(0), last_send_time_us_(0) {
delay_us_(0),
last_send_time_us_(0) {
} }
void DelayFilter::SetDelay(int64_t delay_ms) { void DelayFilter::SetDelay(int64_t delay_ms) {
@ -358,7 +348,7 @@ void DelayFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
} }
JitterFilter::JitterFilter(PacketProcessorListener* listener) JitterFilter::JitterFilter(PacketProcessorListener* listener)
: PacketProcessor(listener, false), : PacketProcessor(listener, kRegular),
random_(0x89674523), random_(0x89674523),
stddev_jitter_us_(0), stddev_jitter_us_(0),
last_send_time_us_(0) { last_send_time_us_(0) {
@ -383,7 +373,7 @@ void JitterFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
} }
ReorderFilter::ReorderFilter(PacketProcessorListener* listener) ReorderFilter::ReorderFilter(PacketProcessorListener* listener)
: PacketProcessor(listener, false), : PacketProcessor(listener, kRegular),
random_(0x27452389), random_(0x27452389),
reorder_fraction_(0.0f) { reorder_fraction_(0.0f) {
} }
@ -415,7 +405,7 @@ void ReorderFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
} }
ChokeFilter::ChokeFilter(PacketProcessorListener* listener) ChokeFilter::ChokeFilter(PacketProcessorListener* listener)
: PacketProcessor(listener, false), : PacketProcessor(listener, kRegular),
kbps_(1200), kbps_(1200),
last_send_time_us_(0), last_send_time_us_(0),
delay_cap_helper_(new DelayCapHelper()) { delay_cap_helper_(new DelayCapHelper()) {
@ -423,7 +413,7 @@ ChokeFilter::ChokeFilter(PacketProcessorListener* listener)
ChokeFilter::ChokeFilter(PacketProcessorListener* listener, ChokeFilter::ChokeFilter(PacketProcessorListener* listener,
const FlowIds& flow_ids) const FlowIds& flow_ids)
: PacketProcessor(listener, flow_ids, false), : PacketProcessor(listener, flow_ids, kRegular),
kbps_(1200), kbps_(1200),
last_send_time_us_(0), last_send_time_us_(0),
delay_cap_helper_(new DelayCapHelper()) { delay_cap_helper_(new DelayCapHelper()) {
@ -467,7 +457,7 @@ Stats<double> ChokeFilter::GetDelayStats() const {
TraceBasedDeliveryFilter::TraceBasedDeliveryFilter( TraceBasedDeliveryFilter::TraceBasedDeliveryFilter(
PacketProcessorListener* listener) PacketProcessorListener* listener)
: PacketProcessor(listener, false), : PacketProcessor(listener, kRegular),
current_offset_us_(0), current_offset_us_(0),
delivery_times_us_(), delivery_times_us_(),
next_delivery_it_(), next_delivery_it_(),
@ -476,12 +466,13 @@ TraceBasedDeliveryFilter::TraceBasedDeliveryFilter(
name_(""), name_(""),
delay_cap_helper_(new DelayCapHelper()), delay_cap_helper_(new DelayCapHelper()),
packets_per_second_stats_(), packets_per_second_stats_(),
kbps_stats_() {} kbps_stats_() {
}
TraceBasedDeliveryFilter::TraceBasedDeliveryFilter( TraceBasedDeliveryFilter::TraceBasedDeliveryFilter(
PacketProcessorListener* listener, PacketProcessorListener* listener,
const std::string& name) const std::string& name)
: PacketProcessor(listener, false), : PacketProcessor(listener, kRegular),
current_offset_us_(0), current_offset_us_(0),
delivery_times_us_(), delivery_times_us_(),
next_delivery_it_(), next_delivery_it_(),
@ -490,7 +481,8 @@ TraceBasedDeliveryFilter::TraceBasedDeliveryFilter(
name_(name), name_(name),
delay_cap_helper_(new DelayCapHelper()), delay_cap_helper_(new DelayCapHelper()),
packets_per_second_stats_(), packets_per_second_stats_(),
kbps_stats_() {} kbps_stats_() {
}
TraceBasedDeliveryFilter::~TraceBasedDeliveryFilter() { TraceBasedDeliveryFilter::~TraceBasedDeliveryFilter() {
} }
@ -771,6 +763,9 @@ void FullSendSideBwe::GiveFeedback(const FeedbackPacket& feedback) {
int expected_packets = fb.packet_feedback_vector().back().sequence_number - int expected_packets = fb.packet_feedback_vector().back().sequence_number -
fb.packet_feedback_vector().front().sequence_number + fb.packet_feedback_vector().front().sequence_number +
1; 1;
// Assuming no reordering for now.
if (expected_packets <= 0)
return;
int lost_packets = expected_packets - fb.packet_feedback_vector().size(); int lost_packets = expected_packets - fb.packet_feedback_vector().size();
report_block_.fractionLost = (lost_packets << 8) / expected_packets; report_block_.fractionLost = (lost_packets << 8) / expected_packets;
report_block_.cumulativeLost += lost_packets; report_block_.cumulativeLost += lost_packets;
@ -815,7 +810,7 @@ SendSideBwe* CreateEstimator(BandwidthEstimatorType estimator,
PacketSender::PacketSender(PacketProcessorListener* listener, PacketSender::PacketSender(PacketProcessorListener* listener,
VideoSource* source, VideoSource* source,
BandwidthEstimatorType estimator) BandwidthEstimatorType estimator)
: PacketProcessor(listener, source->flow_id(), true), : PacketProcessor(listener, source->flow_id(), kSender),
// For Packet::send_time_us() to be comparable with timestamps from // 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 PacketSender and the Source must be aligned.
// We assume that both start at time 0. // We assume that both start at time 0.

View File

@ -162,7 +162,7 @@ class Random {
class Packet { class Packet {
public: public:
enum Type { kMediaPacket, kFeedbackPacket }; enum Type { kMedia, kFeedback };
Packet(); Packet();
Packet(int flow_id, int64_t send_time_us, size_t payload_size); Packet(int flow_id, int64_t send_time_us, size_t payload_size);
@ -197,7 +197,7 @@ class MediaPacket : public Packet {
int64_t GetAbsSendTimeInMs() const; int64_t GetAbsSendTimeInMs() const;
void SetAbsSendTimeMs(int64_t abs_send_time_ms); void SetAbsSendTimeMs(int64_t abs_send_time_ms);
const RTPHeader& header() const { return header_; } const RTPHeader& header() const { return header_; }
virtual Packet::Type GetPacketType() const { return kMediaPacket; } virtual Packet::Type GetPacketType() const { return kMedia; }
private: private:
RTPHeader header_; RTPHeader header_;
@ -209,7 +209,7 @@ class FeedbackPacket : public Packet {
: Packet(flow_id, send_time_us, 0) {} : Packet(flow_id, send_time_us, 0) {}
virtual ~FeedbackPacket() {} virtual ~FeedbackPacket() {}
virtual Packet::Type GetPacketType() const { return kFeedbackPacket; } virtual Packet::Type GetPacketType() const { return kFeedback; }
}; };
class RembFeedback : public FeedbackPacket { class RembFeedback : public FeedbackPacket {
@ -252,23 +252,26 @@ bool IsTimeSorted(const Packets& packets);
class PacketProcessor; class PacketProcessor;
enum ProcessorType { kSender, kReceiver, kRegular };
class PacketProcessorListener { class PacketProcessorListener {
public: public:
virtual ~PacketProcessorListener() {} virtual ~PacketProcessorListener() {}
virtual void AddPacketProcessor(PacketProcessor* processor, virtual void AddPacketProcessor(PacketProcessor* processor,
bool is_sender) = 0; ProcessorType type) = 0;
virtual void RemovePacketProcessor(PacketProcessor* processor) = 0; virtual void RemovePacketProcessor(PacketProcessor* processor) = 0;
}; };
class PacketProcessor { class PacketProcessor {
public: public:
PacketProcessor(PacketProcessorListener* listener, bool is_sender); PacketProcessor(PacketProcessorListener* listener, ProcessorType type);
PacketProcessor(PacketProcessorListener* listener, PacketProcessor(PacketProcessorListener* listener,
int flow_id, int flow_id,
bool is_sender); ProcessorType type);
PacketProcessor(PacketProcessorListener* listener, const FlowIds& flow_ids, PacketProcessor(PacketProcessorListener* listener,
bool is_sender); const FlowIds& flow_ids,
ProcessorType type);
virtual ~PacketProcessor(); virtual ~PacketProcessor();
// Called after each simulation batch to allow the processor to plot any // Called after each simulation batch to allow the processor to plot any