Add support for bi-directional simulations by having both an uplink and a downlink.

Partially make PacketReceiver a source which should be possible to hook up to the network.

Require that flow ids are set in all constructors.

BUG=4173
R=pbos@webrtc.org

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

Cr-Commit-Position: refs/heads/master@{#8367}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8367 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
stefan@webrtc.org 2015-02-13 15:46:23 +00:00
parent d5ce2e63df
commit 56cb0ea99c
7 changed files with 501 additions and 361 deletions

View File

@ -42,11 +42,11 @@ INSTANTIATE_TEST_CASE_P(VideoSendersTest,
TEST_P(BweSimulation, SprintUplinkTest) {
VerboseLogging(true);
AdaptiveVideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
RateCounterFilter counter1(this, "sender_output");
TraceBasedDeliveryFilter filter(this, "link_capacity");
RateCounterFilter counter2(this, "receiver_input");
PacketReceiver receiver(this, 0, GetParam(), true, true);
PacketSender sender(&uplink_, &source, GetParam());
RateCounterFilter counter1(&uplink_, 0, "sender_output");
TraceBasedDeliveryFilter filter(&uplink_, 0, "link_capacity");
RateCounterFilter counter2(&uplink_, 0, "receiver_input");
PacketReceiver receiver(&uplink_, 0, GetParam(), true, true);
ASSERT_TRUE(filter.Init(test::ResourcePath("sprint-uplink", "rx")));
RunFor(60 * 1000);
}
@ -54,38 +54,53 @@ TEST_P(BweSimulation, SprintUplinkTest) {
TEST_P(BweSimulation, Verizon4gDownlinkTest) {
VerboseLogging(true);
AdaptiveVideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
RateCounterFilter counter1(this, "sender_output");
TraceBasedDeliveryFilter filter(this, "link_capacity");
RateCounterFilter counter2(this, "receiver_input");
PacketReceiver receiver(this, 0, GetParam(), true, true);
PacketSender sender(&downlink_, &source, GetParam());
RateCounterFilter counter1(&downlink_, 0, "sender_output");
TraceBasedDeliveryFilter filter(&downlink_, 0, "link_capacity");
RateCounterFilter counter2(&downlink_, 0, "receiver_input");
PacketReceiver receiver(&downlink_, 0, GetParam(), true, true);
ASSERT_TRUE(filter.Init(test::ResourcePath("verizon4g-downlink", "rx")));
RunFor(22 * 60 * 1000);
}
TEST_P(BweSimulation, Choke1000kbps500kbps1000kbps) {
VerboseLogging(true);
AdaptiveVideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
ChokeFilter filter(this);
RateCounterFilter counter(this, "receiver_input");
PacketReceiver receiver(this, 0, GetParam(), true, true);
filter.SetCapacity(1000);
filter.SetMaxDelay(500);
const int kFlowIds[] = {0, 1};
const size_t kNumFlows = sizeof(kFlowIds) / sizeof(kFlowIds[0]);
AdaptiveVideoSource source(kFlowIds[0], 30, 300, 0, 0);
PacketSender 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());
ChokeFilter choke2(&downlink_, kFlowIds[1]);
DelayFilter delay(&downlink_, CreateFlowIds(kFlowIds, kNumFlows));
RateCounterFilter counter2(&downlink_, kFlowIds[1], "receiver_input_1");
PacketReceiver receiver2(&downlink_, kFlowIds[1], GetParam(), true, false);
choke2.SetCapacity(500);
delay.SetDelay(0);
choke.SetCapacity(1000);
choke.SetMaxDelay(500);
RunFor(60 * 1000);
filter.SetCapacity(500);
choke.SetCapacity(500);
RunFor(60 * 1000);
filter.SetCapacity(1000);
choke.SetCapacity(1000);
RunFor(60 * 1000);
}
TEST_P(BweSimulation, PacerChoke1000kbps500kbps1000kbps) {
VerboseLogging(true);
PeriodicKeyFrameSource source(0, 30, 300, 0, 0, 1000);
PacedVideoSender sender(this, &source, GetParam());
ChokeFilter filter(this);
RateCounterFilter counter(this, "receiver_input");
PacketReceiver receiver(this, 0, GetParam(), true, true);
PacedVideoSender sender(&uplink_, &source, GetParam());
ChokeFilter filter(&uplink_, 0);
RateCounterFilter counter(&uplink_, 0, "receiver_input");
PacketReceiver receiver(&uplink_, 0, GetParam(), true, true);
filter.SetCapacity(1000);
filter.SetMaxDelay(500);
RunFor(60 * 1000);
@ -98,10 +113,10 @@ TEST_P(BweSimulation, PacerChoke1000kbps500kbps1000kbps) {
TEST_P(BweSimulation, PacerChoke10000kbps) {
VerboseLogging(true);
PeriodicKeyFrameSource source(0, 30, 300, 0, 0, 1000);
PacedVideoSender sender(this, &source, GetParam());
ChokeFilter filter(this);
RateCounterFilter counter(this, "receiver_input");
PacketReceiver receiver(this, 0, GetParam(), true, true);
PacedVideoSender sender(&uplink_, &source, GetParam());
ChokeFilter filter(&uplink_, 0);
RateCounterFilter counter(&uplink_, 0, "receiver_input");
PacketReceiver receiver(&uplink_, 0, GetParam(), true, true);
filter.SetCapacity(10000);
filter.SetMaxDelay(500);
RunFor(60 * 1000);
@ -110,10 +125,10 @@ TEST_P(BweSimulation, PacerChoke10000kbps) {
TEST_P(BweSimulation, PacerChoke200kbps30kbps200kbps) {
VerboseLogging(true);
PeriodicKeyFrameSource source(0, 30, 300, 0, 0, 1000);
PacedVideoSender sender(this, &source, GetParam());
ChokeFilter filter(this);
RateCounterFilter counter(this, "receiver_input");
PacketReceiver receiver(this, 0, GetParam(), true, true);
PacedVideoSender sender(&uplink_, &source, GetParam());
ChokeFilter filter(&uplink_, 0);
RateCounterFilter counter(&uplink_, 0, "receiver_input");
PacketReceiver receiver(&uplink_, 0, GetParam(), true, true);
filter.SetCapacity(200);
filter.SetMaxDelay(500);
RunFor(60 * 1000);
@ -126,10 +141,10 @@ TEST_P(BweSimulation, PacerChoke200kbps30kbps200kbps) {
TEST_P(BweSimulation, Choke200kbps30kbps200kbps) {
VerboseLogging(true);
AdaptiveVideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
ChokeFilter filter(this);
RateCounterFilter counter(this, "receiver_input");
PacketReceiver receiver(this, 0, GetParam(), true, true);
PacketSender sender(&uplink_, &source, GetParam());
ChokeFilter filter(&uplink_, 0);
RateCounterFilter counter(&uplink_, 0, "receiver_input");
PacketReceiver receiver(&uplink_, 0, GetParam(), true, true);
filter.SetCapacity(200);
filter.SetMaxDelay(500);
RunFor(60 * 1000);
@ -142,12 +157,12 @@ TEST_P(BweSimulation, Choke200kbps30kbps200kbps) {
TEST_P(BweSimulation, GoogleWifiTrace3Mbps) {
VerboseLogging(true);
AdaptiveVideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, kRembEstimator);
RateCounterFilter counter1(this, "sender_output");
TraceBasedDeliveryFilter filter(this, "link_capacity");
PacketSender sender(&uplink_, &source, kRembEstimator);
RateCounterFilter counter1(&uplink_, 0, "sender_output");
TraceBasedDeliveryFilter filter(&uplink_, 0, "link_capacity");
filter.SetMaxDelay(500);
RateCounterFilter counter2(this, "receiver_input");
PacketReceiver receiver(this, 0, GetParam(), true, true);
RateCounterFilter counter2(&uplink_, 0, "receiver_input");
PacketReceiver receiver(&uplink_, 0, GetParam(), true, true);
ASSERT_TRUE(filter.Init(test::ResourcePath("google-wifi-3mbps", "rx")));
RunFor(300 * 1000);
}
@ -155,12 +170,12 @@ TEST_P(BweSimulation, GoogleWifiTrace3Mbps) {
TEST_P(BweSimulation, PacerGoogleWifiTrace3Mbps) {
VerboseLogging(true);
PeriodicKeyFrameSource source(0, 30, 300, 0, 0, 1000);
PacedVideoSender sender(this, &source, kRembEstimator);
RateCounterFilter counter1(this, "sender_output");
TraceBasedDeliveryFilter filter(this, "link_capacity");
PacedVideoSender sender(&uplink_, &source, kRembEstimator);
RateCounterFilter counter1(&uplink_, 0, "sender_output");
TraceBasedDeliveryFilter filter(&uplink_, 0, "link_capacity");
filter.SetMaxDelay(500);
RateCounterFilter counter2(this, "receiver_input");
PacketReceiver receiver(this, 0, GetParam(), true, true);
RateCounterFilter counter2(&uplink_, 0, "receiver_input");
PacketReceiver receiver(&uplink_, 0, GetParam(), true, true);
ASSERT_TRUE(filter.Init(test::ResourcePath("google-wifi-3mbps", "rx")));
RunFor(300 * 1000);
}
@ -176,25 +191,25 @@ TEST_P(BweSimulation, SelfFairnessTest) {
// competing for the bandwidth.
sources[i].reset(
new AdaptiveVideoSource(kAllFlowIds[i], 30, 300, 0, i * 20000));
senders[i].reset(new PacketSender(this, sources[i].get(), GetParam()));
senders[i].reset(new PacketSender(&uplink_, sources[i].get(), GetParam()));
}
ChokeFilter choke(this, CreateFlowIds(kAllFlowIds, kNumFlows));
ChokeFilter choke(&uplink_, CreateFlowIds(kAllFlowIds, kNumFlows));
choke.SetCapacity(1000);
scoped_ptr<RateCounterFilter> rate_counters[kNumFlows];
for (size_t i = 0; i < kNumFlows; ++i) {
rate_counters[i].reset(new RateCounterFilter(
this, CreateFlowIds(&kAllFlowIds[i], 1), "receiver_input"));
&uplink_, CreateFlowIds(&kAllFlowIds[i], 1), "receiver_input"));
}
RateCounterFilter total_utilization(
this, CreateFlowIds(kAllFlowIds, kNumFlows), "total_utilization");
&uplink_, 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));
receivers[i].reset(new PacketReceiver(&uplink_, kAllFlowIds[i], GetParam(),
i == 0, false));
}
RunFor(30 * 60 * 1000);
@ -212,25 +227,26 @@ TEST_P(BweSimulation, PacedSelfFairnessTest) {
// competing for the bandwidth.
sources[i].reset(new PeriodicKeyFrameSource(kAllFlowIds[i], 30, 300, 0,
i * 20000, 1000));
senders[i].reset(new PacedVideoSender(this, sources[i].get(), GetParam()));
senders[i].reset(
new PacedVideoSender(&uplink_, sources[i].get(), GetParam()));
}
ChokeFilter choke(this, CreateFlowIds(kAllFlowIds, kNumFlows));
ChokeFilter choke(&uplink_, CreateFlowIds(kAllFlowIds, kNumFlows));
choke.SetCapacity(1000);
scoped_ptr<RateCounterFilter> rate_counters[kNumFlows];
for (size_t i = 0; i < kNumFlows; ++i) {
rate_counters[i].reset(new RateCounterFilter(
this, CreateFlowIds(&kAllFlowIds[i], 1), "receiver_input"));
&uplink_, CreateFlowIds(&kAllFlowIds[i], 1), "receiver_input"));
}
RateCounterFilter total_utilization(
this, CreateFlowIds(kAllFlowIds, kNumFlows), "total_utilization");
&uplink_, 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));
receivers[i].reset(new PacketReceiver(&uplink_, kAllFlowIds[i], GetParam(),
i == 0, false));
}
RunFor(30 * 60 * 1000);

View File

@ -34,25 +34,25 @@ INSTANTIATE_TEST_CASE_P(VideoSendersTest,
TEST_P(DefaultBweTest, UnlimitedSpeed) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
PacketReceiver receiver(this, 0, GetParam(), false, false);
PacketSender 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(this, &source, GetParam());
LossFilter loss(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
PacketSender sender(&uplink_, &source, GetParam());
LossFilter loss(&uplink_, 0);
PacketReceiver receiver(&uplink_, 0, GetParam(), false, false);
loss.SetLoss(20.0);
RunFor(10 * 60 * 1000);
}
TEST_P(DefaultBweTest, IncreasingLoss1) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
LossFilter loss(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
PacketSender sender(&uplink_, &source, GetParam());
LossFilter loss(&uplink_, 0);
PacketReceiver receiver(&uplink_, 0, GetParam(), false, false);
for (int i = 0; i < 76; ++i) {
loss.SetLoss(i);
RunFor(5000);
@ -61,18 +61,18 @@ TEST_P(DefaultBweTest, IncreasingLoss1) {
TEST_P(DefaultBweTest, SteadyDelay) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
DelayFilter delay(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
PacketSender sender(&uplink_, &source, GetParam());
DelayFilter delay(&uplink_, 0);
PacketReceiver receiver(&uplink_, 0, GetParam(), false, false);
delay.SetDelay(1000);
RunFor(10 * 60 * 1000);
}
TEST_P(DefaultBweTest, IncreasingDelay1) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
DelayFilter delay(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
PacketSender sender(&uplink_, &source, GetParam());
DelayFilter delay(&uplink_, 0);
PacketReceiver receiver(&uplink_, 0, GetParam(), false, false);
RunFor(10 * 60 * 1000);
for (int i = 0; i < 30 * 2; ++i) {
delay.SetDelay(i);
@ -83,10 +83,10 @@ TEST_P(DefaultBweTest, IncreasingDelay1) {
TEST_P(DefaultBweTest, IncreasingDelay2) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
DelayFilter delay(this);
RateCounterFilter counter(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
PacketSender sender(&uplink_, &source, GetParam());
DelayFilter delay(&uplink_, 0);
RateCounterFilter counter(&uplink_, 0, "");
PacketReceiver receiver(&uplink_, 0, GetParam(), false, false);
RunFor(1 * 60 * 1000);
for (int i = 1; i < 51; ++i) {
delay.SetDelay(10.0f * i);
@ -98,9 +98,9 @@ TEST_P(DefaultBweTest, IncreasingDelay2) {
TEST_P(DefaultBweTest, JumpyDelay1) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
DelayFilter delay(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
PacketSender sender(&uplink_, &source, GetParam());
DelayFilter delay(&uplink_, 0);
PacketReceiver receiver(&uplink_, 0, GetParam(), false, false);
RunFor(10 * 60 * 1000);
for (int i = 1; i < 200; ++i) {
delay.SetDelay((10 * i) % 500);
@ -114,19 +114,19 @@ TEST_P(DefaultBweTest, JumpyDelay1) {
TEST_P(DefaultBweTest, SteadyJitter) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
JitterFilter jitter(this);
RateCounterFilter counter(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
PacketSender sender(&uplink_, &source, GetParam());
JitterFilter jitter(&uplink_, 0);
RateCounterFilter counter(&uplink_, 0, "");
PacketReceiver receiver(&uplink_, 0, GetParam(), false, false);
jitter.SetJitter(20);
RunFor(2 * 60 * 1000);
}
TEST_P(DefaultBweTest, IncreasingJitter1) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
JitterFilter jitter(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
PacketSender sender(&uplink_, &source, GetParam());
JitterFilter jitter(&uplink_, 0);
PacketReceiver receiver(&uplink_, 0, GetParam(), false, false);
for (int i = 0; i < 2 * 60 * 2; ++i) {
jitter.SetJitter(i);
RunFor(10 * 1000);
@ -136,9 +136,9 @@ TEST_P(DefaultBweTest, IncreasingJitter1) {
TEST_P(DefaultBweTest, IncreasingJitter2) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
JitterFilter jitter(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
PacketSender sender(&uplink_, &source, GetParam());
JitterFilter jitter(&uplink_, 0);
PacketReceiver receiver(&uplink_, 0, GetParam(), false, false);
RunFor(30 * 1000);
for (int i = 1; i < 51; ++i) {
jitter.SetJitter(10.0f * i);
@ -150,18 +150,18 @@ TEST_P(DefaultBweTest, IncreasingJitter2) {
TEST_P(DefaultBweTest, SteadyReorder) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
ReorderFilter reorder(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
PacketSender sender(&uplink_, &source, GetParam());
ReorderFilter reorder(&uplink_, 0);
PacketReceiver receiver(&uplink_, 0, GetParam(), false, false);
reorder.SetReorder(20.0);
RunFor(10 * 60 * 1000);
}
TEST_P(DefaultBweTest, IncreasingReorder1) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
ReorderFilter reorder(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
PacketSender sender(&uplink_, &source, GetParam());
ReorderFilter reorder(&uplink_, 0);
PacketReceiver receiver(&uplink_, 0, GetParam(), false, false);
for (int i = 0; i < 76; ++i) {
reorder.SetReorder(i);
RunFor(5000);
@ -170,18 +170,18 @@ TEST_P(DefaultBweTest, IncreasingReorder1) {
TEST_P(DefaultBweTest, SteadyChoke) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
ChokeFilter choke(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
PacketSender sender(&uplink_, &source, GetParam());
ChokeFilter choke(&uplink_, 0);
PacketReceiver receiver(&uplink_, 0, GetParam(), false, false);
choke.SetCapacity(140);
RunFor(10 * 60 * 1000);
}
TEST_P(DefaultBweTest, IncreasingChoke1) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
ChokeFilter choke(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
PacketSender sender(&uplink_, &source, GetParam());
ChokeFilter choke(&uplink_, 0);
PacketReceiver receiver(&uplink_, 0, GetParam(), false, false);
for (int i = 1200; i >= 100; i -= 100) {
choke.SetCapacity(i);
RunFor(5000);
@ -190,9 +190,9 @@ TEST_P(DefaultBweTest, IncreasingChoke1) {
TEST_P(DefaultBweTest, IncreasingChoke2) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
ChokeFilter choke(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
PacketSender sender(&uplink_, &source, GetParam());
ChokeFilter choke(&uplink_, 0);
PacketReceiver receiver(&uplink_, 0, GetParam(), false, false);
RunFor(60 * 1000);
for (int i = 1200; i >= 100; i -= 20) {
choke.SetCapacity(i);
@ -202,11 +202,11 @@ TEST_P(DefaultBweTest, IncreasingChoke2) {
TEST_P(DefaultBweTest, Multi1) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
DelayFilter delay(this);
ChokeFilter choke(this);
RateCounterFilter counter(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
PacketSender sender(&uplink_, &source, GetParam());
DelayFilter delay(&uplink_, 0);
ChokeFilter choke(&uplink_, 0);
RateCounterFilter counter(&uplink_, 0, "");
PacketReceiver receiver(&uplink_, 0, GetParam(), false, false);
choke.SetCapacity(1000);
RunFor(1 * 60 * 1000);
for (int i = 1; i < 51; ++i) {
@ -220,11 +220,11 @@ TEST_P(DefaultBweTest, Multi1) {
TEST_P(DefaultBweTest, Multi2) {
VideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
ChokeFilter choke(this);
JitterFilter jitter(this);
RateCounterFilter counter(this);
PacketReceiver receiver(this, 0, GetParam(), false, false);
PacketSender sender(&uplink_, &source, GetParam());
ChokeFilter choke(&uplink_, 0);
JitterFilter jitter(&uplink_, 0);
RateCounterFilter counter(&uplink_, 0, "");
PacketReceiver receiver(&uplink_, 0, GetParam(), false, false);
choke.SetCapacity(2000);
jitter.SetJitter(120);
RunFor(5 * 60 * 1000);
@ -278,10 +278,10 @@ INSTANTIATE_TEST_CASE_P(VideoSendersTest,
TEST_P(BweFeedbackTest, Choke1000kbps500kbps1000kbps) {
AdaptiveVideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
ChokeFilter filter(this);
RateCounterFilter counter(this, "receiver_input");
PacketReceiver receiver(this, 0, GetParam(), false, false);
PacketSender sender(&uplink_, &source, GetParam());
ChokeFilter filter(&uplink_, 0);
RateCounterFilter counter(&uplink_, 0, "receiver_input");
PacketReceiver receiver(&uplink_, 0, GetParam(), false, false);
const int kHighCapacityKbps = 1000;
const int kLowCapacityKbps = 500;
filter.SetCapacity(kHighCapacityKbps);
@ -297,10 +297,10 @@ TEST_P(BweFeedbackTest, Choke1000kbps500kbps1000kbps) {
TEST_P(BweFeedbackTest, Choke200kbps30kbps200kbps) {
AdaptiveVideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
ChokeFilter filter(this);
RateCounterFilter counter(this, "receiver_input");
PacketReceiver receiver(this, 0, GetParam(), false, false);
PacketSender sender(&uplink_, &source, GetParam());
ChokeFilter filter(&uplink_, 0);
RateCounterFilter counter(&uplink_, 0, "receiver_input");
PacketReceiver receiver(&uplink_, 0, GetParam(), false, false);
const int kHighCapacityKbps = 200;
const int kLowCapacityKbps = 30;
filter.SetCapacity(kHighCapacityKbps);
@ -317,11 +317,11 @@ TEST_P(BweFeedbackTest, Choke200kbps30kbps200kbps) {
TEST_P(BweFeedbackTest, Verizon4gDownlinkTest) {
AdaptiveVideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
RateCounterFilter counter1(this, "sender_output");
TraceBasedDeliveryFilter filter(this, "link_capacity");
RateCounterFilter counter2(this, "receiver_input");
PacketReceiver receiver(this, 0, GetParam(), false, false);
PacketSender sender(&uplink_, &source, GetParam());
RateCounterFilter counter1(&uplink_, 0, "sender_output");
TraceBasedDeliveryFilter filter(&uplink_, 0, "link_capacity");
RateCounterFilter counter2(&uplink_, 0, "receiver_input");
PacketReceiver receiver(&uplink_, 0, GetParam(), false, false);
ASSERT_TRUE(filter.Init(test::ResourcePath("verizon4g-downlink", "rx")));
RunFor(22 * 60 * 1000);
PrintResults(filter.GetBitrateStats().GetMean(), counter2.GetBitrateStats(),
@ -331,12 +331,12 @@ TEST_P(BweFeedbackTest, Verizon4gDownlinkTest) {
// webrtc:3277
TEST_P(BweFeedbackTest, DISABLED_GoogleWifiTrace3Mbps) {
AdaptiveVideoSource source(0, 30, 300, 0, 0);
PacketSender sender(this, &source, GetParam());
RateCounterFilter counter1(this, "sender_output");
TraceBasedDeliveryFilter filter(this, "link_capacity");
PacketSender sender(&uplink_, &source, GetParam());
RateCounterFilter counter1(&uplink_, 0, "sender_output");
TraceBasedDeliveryFilter filter(&uplink_, 0, "link_capacity");
filter.SetMaxDelay(500);
RateCounterFilter counter2(this, "receiver_input");
PacketReceiver receiver(this, 0, GetParam(), false, false);
RateCounterFilter counter2(&uplink_, 0, "receiver_input");
PacketReceiver receiver(&uplink_, 0, GetParam(), false, false);
ASSERT_TRUE(filter.Init(test::ResourcePath("google-wifi-3mbps", "rx")));
RunFor(300 * 1000);
PrintResults(filter.GetBitrateStats().GetMean(), counter2.GetBitrateStats(),

View File

@ -33,7 +33,7 @@ class BweReceiver {
virtual void ReceivePacket(int64_t arrival_time_ms,
size_t payload_size,
const RTPHeader& header) {}
virtual FeedbackPacket* GetFeedback() { return NULL; }
virtual FeedbackPacket* GetFeedback(int64_t now_ms) { return NULL; }
protected:
int flow_id_;
@ -50,7 +50,8 @@ int64_t GetAbsSendTimeInMs(uint32_t abs_send_time) {
class SendSideBweReceiver : public BweReceiver {
public:
explicit SendSideBweReceiver(int flow_id) : BweReceiver(flow_id) {}
explicit SendSideBweReceiver(int flow_id)
: BweReceiver(flow_id), last_feedback_ms_(0) {}
virtual void ReceivePacket(int64_t arrival_time_ms,
size_t payload_size,
const RTPHeader& header) OVERRIDE {
@ -59,14 +60,18 @@ class SendSideBweReceiver : public BweReceiver {
header.sequenceNumber, payload_size));
}
virtual FeedbackPacket* GetFeedback() OVERRIDE {
FeedbackPacket* fb =
new SendSideBweFeedback(flow_id_, 0, packet_feedback_vector_);
virtual FeedbackPacket* GetFeedback(int64_t now_ms) OVERRIDE {
if (now_ms - last_feedback_ms_ < 100)
return NULL;
last_feedback_ms_ = now_ms;
FeedbackPacket* fb = new SendSideBweFeedback(flow_id_, now_ms * 1000,
packet_feedback_vector_);
packet_feedback_vector_.clear();
return fb;
}
private:
int64_t last_feedback_ms_;
std::vector<PacketInfo> packet_feedback_vector_;
};
@ -112,7 +117,7 @@ class RembReceiver : public BweReceiver, public RemoteBitrateObserver {
ASSERT_TRUE(arrival_time_ms == clock_.TimeInMilliseconds());
}
virtual FeedbackPacket* GetFeedback() {
virtual FeedbackPacket* GetFeedback(int64_t now_ms) OVERRIDE {
BWE_TEST_LOGGING_CONTEXT("Remb");
uint32_t estimated_bps = 0;
RembFeedback* feedback = NULL;
@ -122,8 +127,8 @@ class RembReceiver : public BweReceiver, public RemoteBitrateObserver {
if (!statisticians.empty()) {
report_block = BuildReportBlock(statisticians.begin()->second);
}
feedback = new RembFeedback(flow_id_, clock_.TimeInMilliseconds(),
estimated_bps, report_block);
feedback = new RembFeedback(flow_id_, now_ms * 1000, estimated_bps,
report_block);
double estimated_kbps = static_cast<double>(estimated_bps) / 1000.0;
RTC_UNUSED(estimated_kbps);
@ -135,9 +140,9 @@ class RembReceiver : public BweReceiver, public RemoteBitrateObserver {
return feedback;
}
// Implements RemoteBitrateObserver.
virtual void OnReceiveBitrateChanged(const vector<unsigned int>& ssrcs,
unsigned int bitrate) {
}
unsigned int bitrate) OVERRIDE {}
private:
static RTCPReportBlock BuildReportBlock(StreamStatistician* statistician) {
@ -210,29 +215,37 @@ PacketReceiver::~PacketReceiver() {
}
void PacketReceiver::RunFor(int64_t time_ms, Packets* in_out) {
for (const auto* packet : *in_out) {
Packets feedback;
for (auto it = in_out->begin(); it != in_out->end();) {
// 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);
if ((*it)->GetPacketType() == Packet::kMedia &&
(*it)->flow_id() == *flow_ids().begin()) {
BWE_TEST_LOGGING_CONTEXT("Receiver");
const MediaPacket* media_packet = static_cast<const MediaPacket*>(*it);
// 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());
bwe_receiver_->ReceivePacket(arrival_time_ms,
media_packet->payload_size(),
media_packet->header());
FeedbackPacket* fb = bwe_receiver_->GetFeedback(arrival_time_ms);
if (fb)
feedback.push_back(fb);
delete media_packet;
it = in_out->erase(it);
} else {
++it;
}
}
}
FeedbackPacket* PacketReceiver::GetFeedback() {
return bwe_receiver_->GetFeedback();
// Insert feedback packets to be sent back to the sender.
in_out->merge(feedback, DereferencingComparator<Packet>);
}
void PacketReceiver::PlotDelay(int64_t arrival_time_ms, int64_t send_time_ms) {
@ -256,7 +269,7 @@ class PacketProcessorRunner {
delete packet;
}
bool HasProcessor(const PacketProcessor* processor) const {
bool RunsProcessor(const PacketProcessor* processor) const {
return processor == processor_;
}
@ -312,9 +325,13 @@ class PacketProcessorRunner {
BweTest::BweTest()
: run_time_ms_(0), time_now_ms_(-1), simulation_interval_ms_(-1) {
links_.push_back(&uplink_);
links_.push_back(&downlink_);
}
BweTest::~BweTest() {
for (Packet* packet : packets_)
delete packet;
}
void BweTest::SetUp() {
@ -326,8 +343,8 @@ void BweTest::SetUp() {
BWE_TEST_LOGGING_GLOBAL_ENABLE(false);
}
void BweTest::AddPacketProcessor(PacketProcessor* processor,
ProcessorType processor_type) {
void Link::AddPacketProcessor(PacketProcessor* processor,
ProcessorType processor_type) {
assert(processor);
switch (processor_type) {
case kSender:
@ -342,10 +359,10 @@ void BweTest::AddPacketProcessor(PacketProcessor* processor,
processors_.push_back(PacketProcessorRunner(processor));
}
void BweTest::RemovePacketProcessor(PacketProcessor* processor) {
void Link::RemovePacketProcessor(PacketProcessor* processor) {
for (vector<PacketProcessorRunner>::iterator it = processors_.begin();
it != processors_.end(); ++it) {
if (it->HasProcessor(processor)) {
if (it->RunsProcessor(processor)) {
processors_.erase(it);
return;
}
@ -353,29 +370,24 @@ void BweTest::RemovePacketProcessor(PacketProcessor* processor) {
assert(false);
}
void BweTest::VerboseLogging(bool enable) {
BWE_TEST_LOGGING_GLOBAL_ENABLE(enable);
// Ownership of the created packets is handed over to the caller.
void Link::Run(int64_t run_for_ms, int64_t now_ms, Packets* packets) {
for (auto& processor : processors_) {
processor.RunFor(run_for_ms, now_ms, packets);
}
}
void BweTest::GiveFeedbackToAffectedSenders(PacketReceiver* receiver) {
FeedbackPacket* feedback = receiver->GetFeedback();
if (feedback) {
for (PacketSender* sender : senders_) {
if (sender->flow_ids().find(feedback->flow_id()) !=
sender->flow_ids().end()) {
sender->GiveFeedback(*feedback);
break;
}
}
}
delete feedback;
void BweTest::VerboseLogging(bool enable) {
BWE_TEST_LOGGING_GLOBAL_ENABLE(enable);
}
void BweTest::RunFor(int64_t time_ms) {
// Set simulation interval from first packet sender.
// TODO(holmer): Support different feedback intervals for different flows.
if (!senders_.empty()) {
simulation_interval_ms_ = senders_[0]->GetFeedbackIntervalMs();
if (!uplink_.senders().empty()) {
simulation_interval_ms_ = uplink_.senders()[0]->GetFeedbackIntervalMs();
} else if (!downlink_.senders().empty()) {
simulation_interval_ms_ = downlink_.senders()[0]->GetFeedbackIntervalMs();
}
assert(simulation_interval_ms_ > 0);
if (time_now_ms_ == -1) {
@ -384,32 +396,12 @@ void BweTest::RunFor(int64_t time_ms) {
for (run_time_ms_ += time_ms;
time_now_ms_ <= run_time_ms_ - simulation_interval_ms_;
time_now_ms_ += simulation_interval_ms_) {
Packets packets;
for (PacketProcessorRunner& processor : processors_) {
processor.RunFor(simulation_interval_ms_, time_now_ms_, &packets);
}
// Verify packets are in order between batches.
if (!packets.empty()) {
if (!previous_packets_.empty()) {
packets.splice(packets.begin(), previous_packets_,
--previous_packets_.end());
ASSERT_TRUE(IsTimeSorted(packets));
delete packets.front();
packets.erase(packets.begin());
}
ASSERT_LE(packets.front()->send_time_us(), time_now_ms_ * 1000);
ASSERT_LE(packets.back()->send_time_us(), time_now_ms_ * 1000);
} else {
ASSERT_TRUE(IsTimeSorted(packets));
}
for (const auto* packet : packets)
delete packet;
for (const auto& receiver : receivers_) {
GiveFeedbackToAffectedSenders(receiver);
}
// Packets are first generated on the first link, passed through all the
// PacketProcessors and PacketReceivers. The PacketReceivers produces
// FeedbackPackets which are then processed by the next link, where they
// at some point will be consumed by a PacketSender.
for (Link* link : links_)
link->Run(simulation_interval_ms_, time_now_ms_, &packets_);
}
}

View File

@ -22,7 +22,6 @@ namespace testing {
namespace bwe {
class BweReceiver;
class PacketReceiver;
class PacketProcessorRunner;
class PacketReceiver : public PacketProcessor {
@ -37,13 +36,12 @@ class PacketReceiver : public PacketProcessor {
// 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);
int64_t now_ms_;
std::string delay_log_prefix_;
int64_t last_delay_plot_ms_;
bool plot_delay_;
@ -53,22 +51,38 @@ class PacketReceiver : public PacketProcessor {
DISALLOW_IMPLICIT_CONSTRUCTORS(PacketReceiver);
};
class BweTest : public PacketProcessorListener {
class Link : public PacketProcessorListener {
public:
BweTest();
virtual ~BweTest();
virtual void AddPacketProcessor(PacketProcessor* processor,
ProcessorType type);
virtual void RemovePacketProcessor(PacketProcessor* processor);
void Run(int64_t run_for_ms, int64_t now_ms, Packets* packets);
const std::vector<PacketSender*>& senders() { return senders_; }
const std::vector<PacketProcessorRunner>& processors() { return processors_; }
private:
std::vector<PacketSender*> senders_;
std::vector<PacketReceiver*> receivers_;
std::vector<PacketProcessorRunner> processors_;
};
class BweTest {
public:
BweTest();
~BweTest();
protected:
virtual void SetUp();
void SetUp();
void VerboseLogging(bool enable);
void RunFor(int64_t time_ms);
std::string GetTestName() const;
Link downlink_;
Link uplink_;
private:
void FindPacketsToProcess(const FlowIds& flow_ids, Packets* in,
Packets* out);
@ -77,10 +91,8 @@ class BweTest : public PacketProcessorListener {
int64_t run_time_ms_;
int64_t time_now_ms_;
int64_t simulation_interval_ms_;
Packets previous_packets_;
std::vector<PacketSender*> senders_;
std::vector<PacketReceiver*> receivers_;
std::vector<PacketProcessorRunner> processors_;
std::vector<Link*> links_;
Packets packets_;
DISALLOW_COPY_AND_ASSIGN(BweTest);
};

View File

@ -84,6 +84,7 @@ class RateCounter {
uint32_t bits_per_second() const {
return bytes_per_second_ * 8;
}
uint32_t packets_per_second() const { return packets_per_second_; }
private:
@ -197,15 +198,6 @@ bool IsTimeSorted(const Packets& packets) {
return true;
}
PacketProcessor::PacketProcessor(PacketProcessorListener* listener,
ProcessorType type)
: listener_(listener) {
flow_ids_.insert(0);
if (listener_) {
listener_->AddPacketProcessor(this, type);
}
}
PacketProcessor::PacketProcessor(PacketProcessorListener* listener,
int flow_id,
ProcessorType type)
@ -231,17 +223,10 @@ PacketProcessor::~PacketProcessor() {
}
}
RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener)
: PacketProcessor(listener, kRegular),
rate_counter_(new RateCounter()),
packets_per_second_stats_(),
kbps_stats_(),
name_("") {
}
RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener,
const std::string& name)
: PacketProcessor(listener, kRegular),
int flow_id,
const char* name)
: PacketProcessor(listener, flow_id, kRegular),
rate_counter_(new RateCounter()),
packets_per_second_stats_(),
kbps_stats_(),
@ -250,7 +235,7 @@ RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener,
RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener,
const FlowIds& flow_ids,
const std::string& name)
const char* name)
: PacketProcessor(listener, flow_ids, kRegular),
rate_counter_(new RateCounter()),
packets_per_second_stats_(),
@ -301,8 +286,15 @@ void RateCounterFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
kbps_stats_.Push(rate_counter_->bits_per_second() / 1000.0);
}
LossFilter::LossFilter(PacketProcessorListener* listener)
: PacketProcessor(listener, kRegular),
LossFilter::LossFilter(PacketProcessorListener* listener, int flow_id)
: PacketProcessor(listener, flow_id, kRegular),
random_(0x12345678),
loss_fraction_(0.0f) {
}
LossFilter::LossFilter(PacketProcessorListener* listener,
const FlowIds& flow_ids)
: PacketProcessor(listener, flow_ids, kRegular),
random_(0x12345678),
loss_fraction_(0.0f) {
}
@ -327,8 +319,17 @@ void LossFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
}
}
DelayFilter::DelayFilter(PacketProcessorListener* listener)
: PacketProcessor(listener, kRegular), delay_us_(0), last_send_time_us_(0) {
DelayFilter::DelayFilter(PacketProcessorListener* listener, int flow_id)
: PacketProcessor(listener, flow_id, kRegular),
delay_us_(0),
last_send_time_us_(0) {
}
DelayFilter::DelayFilter(PacketProcessorListener* listener,
const FlowIds& flow_ids)
: PacketProcessor(listener, flow_ids, kRegular),
delay_us_(0),
last_send_time_us_(0) {
}
void DelayFilter::SetDelay(int64_t delay_ms) {
@ -347,8 +348,16 @@ void DelayFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
}
}
JitterFilter::JitterFilter(PacketProcessorListener* listener)
: PacketProcessor(listener, kRegular),
JitterFilter::JitterFilter(PacketProcessorListener* listener, int flow_id)
: PacketProcessor(listener, flow_id, kRegular),
random_(0x89674523),
stddev_jitter_us_(0),
last_send_time_us_(0) {
}
JitterFilter::JitterFilter(PacketProcessorListener* listener,
const FlowIds& flow_ids)
: PacketProcessor(listener, flow_ids, kRegular),
random_(0x89674523),
stddev_jitter_us_(0),
last_send_time_us_(0) {
@ -372,8 +381,15 @@ void JitterFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
}
}
ReorderFilter::ReorderFilter(PacketProcessorListener* listener)
: PacketProcessor(listener, kRegular),
ReorderFilter::ReorderFilter(PacketProcessorListener* listener, int flow_id)
: PacketProcessor(listener, flow_id, kRegular),
random_(0x27452389),
reorder_fraction_(0.0f) {
}
ReorderFilter::ReorderFilter(PacketProcessorListener* listener,
const FlowIds& flow_ids)
: PacketProcessor(listener, flow_ids, kRegular),
random_(0x27452389),
reorder_fraction_(0.0f) {
}
@ -404,8 +420,8 @@ void ReorderFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
}
}
ChokeFilter::ChokeFilter(PacketProcessorListener* listener)
: PacketProcessor(listener, kRegular),
ChokeFilter::ChokeFilter(PacketProcessorListener* listener, int flow_id)
: PacketProcessor(listener, flow_id, kRegular),
kbps_(1200),
last_send_time_us_(0),
delay_cap_helper_(new DelayCapHelper()) {
@ -456,8 +472,9 @@ Stats<double> ChokeFilter::GetDelayStats() const {
}
TraceBasedDeliveryFilter::TraceBasedDeliveryFilter(
PacketProcessorListener* listener)
: PacketProcessor(listener, kRegular),
PacketProcessorListener* listener,
int flow_id)
: PacketProcessor(listener, flow_id, kRegular),
current_offset_us_(0),
delivery_times_us_(),
next_delivery_it_(),
@ -471,8 +488,24 @@ TraceBasedDeliveryFilter::TraceBasedDeliveryFilter(
TraceBasedDeliveryFilter::TraceBasedDeliveryFilter(
PacketProcessorListener* listener,
const std::string& name)
: PacketProcessor(listener, kRegular),
const FlowIds& flow_ids)
: PacketProcessor(listener, flow_ids, kRegular),
current_offset_us_(0),
delivery_times_us_(),
next_delivery_it_(),
local_time_us_(-1),
rate_counter_(new RateCounter),
name_(""),
delay_cap_helper_(new DelayCapHelper()),
packets_per_second_stats_(),
kbps_stats_() {
}
TraceBasedDeliveryFilter::TraceBasedDeliveryFilter(
PacketProcessorListener* listener,
int flow_id,
const char* name)
: PacketProcessor(listener, flow_id, kRegular),
current_offset_us_(0),
delivery_times_us_(),
next_delivery_it_(),
@ -584,12 +617,12 @@ VideoSource::VideoSource(int flow_id,
int64_t first_frame_offset_ms)
: kMaxPayloadSizeBytes(1200),
kTimestampBase(0xff80ff00ul),
flow_id_(flow_id),
frame_period_ms_(1000.0 / fps),
bytes_per_second_((1000 * kbps) / 8),
frame_size_bytes_(bytes_per_second_ / fps),
bits_per_second_(1000 * kbps),
frame_size_bytes_(bits_per_second_ / 8 / fps),
flow_id_(flow_id),
next_frame_ms_(first_frame_offset_ms),
now_ms_(0.0),
now_ms_(0),
prototype_header_() {
memset(&prototype_header_, 0, sizeof(prototype_header_));
prototype_header_.ssrc = ssrc;
@ -646,8 +679,8 @@ AdaptiveVideoSource::AdaptiveVideoSource(int flow_id,
}
void AdaptiveVideoSource::SetBitrateBps(int bitrate_bps) {
bytes_per_second_ = std::min(bitrate_bps / 8, 2500000 / 8);
frame_size_bytes_ = (bytes_per_second_ * frame_period_ms_ + 500) / 1000;
bits_per_second_ = std::min(bitrate_bps, 2500000);
frame_size_bytes_ = (bits_per_second_ / 8 * frame_period_ms_ + 500) / 1000;
}
PeriodicKeyFrameSource::PeriodicKeyFrameSource(int flow_id,
@ -757,8 +790,6 @@ void FullSendSideBwe::GiveFeedback(const FeedbackPacket& feedback) {
if (fb.packet_feedback_vector().empty())
return;
rbe_->IncomingPacketFeedbackVector(fb.packet_feedback_vector());
if (rbe_->TimeUntilNextProcess() <= 0)
rbe_->Process();
// TODO(holmer): Handle losses in between feedback packets.
int expected_packets = fb.packet_feedback_vector().back().sequence_number -
fb.packet_feedback_vector().front().sequence_number +
@ -817,7 +848,7 @@ PacketSender::PacketSender(PacketProcessorListener* listener,
clock_(0),
source_(source),
bwe_(CreateEstimator(estimator,
8 * source_->bytes_per_second() / 1000,
source_->bits_per_second() / 1000,
this,
&clock_)) {
modules_.push_back(bwe_.get());
@ -827,22 +858,59 @@ PacketSender::~PacketSender() {
}
void PacketSender::RunFor(int64_t time_ms, Packets* in_out) {
start_of_run_ms_ = clock_.TimeInMilliseconds();
while (time_ms > 0) {
int64_t time_to_run_ms = std::min(time_ms, static_cast<int64_t>(100));
source_->RunFor(time_to_run_ms, in_out);
int64_t now_ms = clock_.TimeInMilliseconds();
std::list<FeedbackPacket*> feedbacks =
GetFeedbackPackets(in_out, now_ms + time_ms);
ProcessFeedbackAndGeneratePackets(time_ms, &feedbacks, in_out);
}
void PacketSender::ProcessFeedbackAndGeneratePackets(
int64_t time_ms,
std::list<FeedbackPacket*>* feedbacks,
Packets* generated) {
do {
// Make sure to at least run Process() below every 100 ms.
int64_t time_to_run_ms = std::min<int64_t>(time_ms, 100);
if (!feedbacks->empty()) {
int64_t time_until_feedback_ms =
feedbacks->front()->send_time_us() / 1000 -
clock_.TimeInMilliseconds();
time_to_run_ms =
std::max<int64_t>(std::min(time_ms, time_until_feedback_ms), 0);
}
source_->RunFor(time_to_run_ms, generated);
clock_.AdvanceTimeMilliseconds(time_to_run_ms);
if (!feedbacks->empty()) {
bwe_->GiveFeedback(*feedbacks->front());
delete feedbacks->front();
feedbacks->pop_front();
}
bwe_->Process();
time_ms -= time_to_run_ms;
}
} while (time_ms > 0);
assert(feedbacks->empty());
}
int PacketSender::GetFeedbackIntervalMs() const {
return bwe_->GetFeedbackIntervalMs();
}
void PacketSender::GiveFeedback(const FeedbackPacket& feedback) {
bwe_->GiveFeedback(feedback);
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,
@ -861,9 +929,8 @@ PacedVideoSender::PacedVideoSender(PacketProcessorListener* listener,
: PacketSender(listener, source, estimator),
pacer_(&clock_,
this,
8 * source->bytes_per_second() / 1000,
PacedSender::kDefaultPaceMultiplier * 8 *
source->bytes_per_second() /
source->bits_per_second() / 1000,
PacedSender::kDefaultPaceMultiplier * source->bits_per_second() /
1000,
0) {
modules_.push_back(&pacer_);
@ -877,47 +944,64 @@ PacedVideoSender::~PacedVideoSender() {
}
void PacedVideoSender::RunFor(int64_t time_ms, Packets* in_out) {
start_of_run_ms_ = clock_.TimeInMilliseconds();
Packets generated_packets;
source_->RunFor(time_ms, &generated_packets);
// Run process periodically to allow the packets to be paced out.
int64_t end_time_ms = clock_.TimeInMilliseconds() + time_ms;
Packets::iterator it = generated_packets.begin();
while (clock_.TimeInMilliseconds() <= end_time_ms) {
// Run process periodically to allow the packets to be paced out.
std::list<FeedbackPacket*> feedbacks =
GetFeedbackPackets(in_out, end_time_ms);
int64_t last_run_time_ms = -1;
do {
int64_t time_until_process_ms = TimeUntilNextProcess(modules_);
int64_t time_until_feedback_ms = time_ms;
if (!feedbacks.empty())
time_until_feedback_ms = feedbacks.front()->send_time_us() / 1000 -
clock_.TimeInMilliseconds();
int time_until_packet_ms = time_ms;
if (it != generated_packets.end())
time_until_packet_ms =
((*it)->send_time_us() + 500) / 1000 - clock_.TimeInMilliseconds();
assert(time_until_packet_ms >= 0);
int64_t time_until_next_event_ms =
std::min(time_until_feedback_ms, time_until_process_ms);
int time_until_next_event_ms = time_until_packet_ms;
if (time_until_process_ms < time_until_packet_ms) {
time_until_next_event_ms = time_until_process_ms;
time_until_next_event_ms =
std::min(source_->GetTimeUntilNextFrameMs(), time_until_next_event_ms);
// Never run for longer than we have been asked for.
if (clock_.TimeInMilliseconds() + time_until_next_event_ms > end_time_ms)
time_until_next_event_ms = end_time_ms - clock_.TimeInMilliseconds();
// Make sure we don't get stuck if an event doesn't trigger. This typically
// happens if the prober wants to probe, but there's no packet to send.
if (time_until_next_event_ms == 0 && last_run_time_ms == 0)
time_until_next_event_ms = 1;
last_run_time_ms = time_until_next_event_ms;
Packets generated_packets;
source_->RunFor(time_until_next_event_ms, &generated_packets);
if (!generated_packets.empty()) {
for (Packet* packet : generated_packets) {
MediaPacket* media_packet = static_cast<MediaPacket*>(packet);
pacer_.SendPacket(PacedSender::kNormalPriority,
media_packet->header().ssrc,
media_packet->header().sequenceNumber,
(media_packet->send_time_us() + 500) / 1000,
media_packet->payload_size(), false);
pacer_queue_.push_back(packet);
assert(pacer_queue_.size() < 10000);
}
}
if (clock_.TimeInMilliseconds() + time_until_next_event_ms > end_time_ms) {
clock_.AdvanceTimeMilliseconds(end_time_ms - clock_.TimeInMilliseconds());
break;
}
clock_.AdvanceTimeMilliseconds(time_until_next_event_ms);
if (time_until_process_ms < time_until_packet_ms) {
// Time to process.
CallProcess(modules_);
} else {
// Time to send next packet to pacer.
MediaPacket* media_packet = static_cast<MediaPacket*>(*it);
pacer_.SendPacket(PacedSender::kNormalPriority,
media_packet->header().ssrc,
media_packet->header().sequenceNumber,
(media_packet->send_time_us() + 500) / 1000,
media_packet->payload_size(), false);
pacer_queue_.push_back(media_packet);
assert(pacer_queue_.size() < 10000);
++it;
if (time_until_next_event_ms == time_until_feedback_ms) {
if (!feedbacks.empty()) {
bwe_->GiveFeedback(*feedbacks.front());
delete feedbacks.front();
feedbacks.pop_front();
}
bwe_->Process();
}
}
if (time_until_next_event_ms == time_until_process_ms) {
CallProcess(modules_);
}
} while (clock_.TimeInMilliseconds() < end_time_ms);
QueuePackets(in_out, end_time_ms * 1000);
}

View File

@ -46,6 +46,8 @@ const FlowIds CreateFlowIds(const int *flow_ids_array, size_t num_flow_ids);
template <typename T>
bool DereferencingComparator(const T* const& a, const T* const& b) {
assert(a != NULL);
assert(b != NULL);
return *a < *b;
}
@ -265,7 +267,6 @@ class PacketProcessorListener {
class PacketProcessor {
public:
PacketProcessor(PacketProcessorListener* listener, ProcessorType type);
PacketProcessor(PacketProcessorListener* listener,
int flow_id,
ProcessorType type);
@ -294,12 +295,12 @@ class PacketProcessor {
class RateCounterFilter : public PacketProcessor {
public:
explicit RateCounterFilter(PacketProcessorListener* listener);
RateCounterFilter(PacketProcessorListener* listener,
const std::string& name);
int flow_id,
const char* name);
RateCounterFilter(PacketProcessorListener* listener,
const FlowIds& flow_ids,
const std::string& name);
const char* name);
virtual ~RateCounterFilter();
uint32_t packets_per_second() const;
@ -321,7 +322,8 @@ class RateCounterFilter : public PacketProcessor {
class LossFilter : public PacketProcessor {
public:
explicit LossFilter(PacketProcessorListener* listener);
LossFilter(PacketProcessorListener* listener, int flow_id);
LossFilter(PacketProcessorListener* listener, const FlowIds& flow_ids);
virtual ~LossFilter() {}
void SetLoss(float loss_percent);
@ -336,7 +338,8 @@ class LossFilter : public PacketProcessor {
class DelayFilter : public PacketProcessor {
public:
explicit DelayFilter(PacketProcessorListener* listener);
DelayFilter(PacketProcessorListener* listener, int flow_id);
DelayFilter(PacketProcessorListener* listener, const FlowIds& flow_ids);
virtual ~DelayFilter() {}
void SetDelay(int64_t delay_ms);
@ -351,7 +354,8 @@ class DelayFilter : public PacketProcessor {
class JitterFilter : public PacketProcessor {
public:
explicit JitterFilter(PacketProcessorListener* listener);
JitterFilter(PacketProcessorListener* listener, int flow_id);
JitterFilter(PacketProcessorListener* listener, const FlowIds& flow_ids);
virtual ~JitterFilter() {}
void SetJitter(int64_t stddev_jitter_ms);
@ -368,7 +372,8 @@ class JitterFilter : public PacketProcessor {
// Reorders two consecutive packets with a probability of reorder_percent.
class ReorderFilter : public PacketProcessor {
public:
explicit ReorderFilter(PacketProcessorListener* listener);
ReorderFilter(PacketProcessorListener* listener, int flow_id);
ReorderFilter(PacketProcessorListener* listener, const FlowIds& flow_ids);
virtual ~ReorderFilter() {}
void SetReorder(float reorder_percent);
@ -384,7 +389,7 @@ class ReorderFilter : public PacketProcessor {
// Apply a bitrate choke with an infinite queue on the packet stream.
class ChokeFilter : public PacketProcessor {
public:
explicit ChokeFilter(PacketProcessorListener* listener);
ChokeFilter(PacketProcessorListener* listener, int flow_id);
ChokeFilter(PacketProcessorListener* listener, const FlowIds& flow_ids);
virtual ~ChokeFilter();
@ -404,9 +409,12 @@ class ChokeFilter : public PacketProcessor {
class TraceBasedDeliveryFilter : public PacketProcessor {
public:
explicit TraceBasedDeliveryFilter(PacketProcessorListener* listener);
TraceBasedDeliveryFilter(PacketProcessorListener* listener, int flow_id);
TraceBasedDeliveryFilter(PacketProcessorListener* listener,
const std::string& name);
const FlowIds& flow_ids);
TraceBasedDeliveryFilter(PacketProcessorListener* listener,
int flow_id,
const char* name);
virtual ~TraceBasedDeliveryFilter();
// The file should contain nanosecond timestamps corresponding to the time
@ -446,12 +454,13 @@ class VideoSource {
int64_t first_frame_offset_ms);
virtual ~VideoSource() {}
uint32_t max_payload_size_bytes() const { return kMaxPayloadSizeBytes; }
uint32_t bytes_per_second() const { return bytes_per_second_; }
virtual void RunFor(int64_t time_ms, Packets* in_out);
virtual void SetBitrateBps(int bitrate_bps) {}
virtual int flow_id() const { return flow_id_; }
virtual void SetBitrateBps(int bitrate_bps) {}
uint32_t bits_per_second() const { return bits_per_second_; }
uint32_t max_payload_size_bytes() const { return kMaxPayloadSizeBytes; }
int64_t GetTimeUntilNextFrameMs() const { return next_frame_ms_ - now_ms_; }
protected:
virtual uint32_t NextFrameSize();
@ -460,14 +469,14 @@ class VideoSource {
const uint32_t kMaxPayloadSizeBytes;
const uint32_t kTimestampBase;
const int flow_id_;
const double frame_period_ms_;
uint32_t bytes_per_second_;
uint32_t bits_per_second_;
uint32_t frame_size_bytes_;
private:
double next_frame_ms_;
double now_ms_;
const int flow_id_;
int64_t next_frame_ms_;
int64_t now_ms_;
RTPHeader prototype_header_;
DISALLOW_IMPLICIT_CONSTRUCTORS(VideoSource);
@ -602,7 +611,6 @@ class PacketSender : public PacketProcessor, public BitrateObserver {
// output of the estimators is sampled and therefore the baseline files may
// have to be regenerated.
virtual int GetFeedbackIntervalMs() const;
virtual void GiveFeedback(const FeedbackPacket& feedback);
virtual void RunFor(int64_t time_ms, Packets* in_out) OVERRIDE;
virtual VideoSource* source() const { return source_; }
@ -613,6 +621,12 @@ class PacketSender : public PacketProcessor, public BitrateObserver {
int64_t rtt) OVERRIDE;
protected:
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_;
scoped_ptr<SendSideBwe> bwe_;

View File

@ -181,10 +181,7 @@ TEST(BweTestFramework_StatsTest, MinMax) {
class BweTestFramework_RateCounterFilterTest : public ::testing::Test {
public:
BweTestFramework_RateCounterFilterTest()
: filter_(NULL),
now_ms_(0) {
}
BweTestFramework_RateCounterFilterTest() : filter_(NULL, 0, ""), now_ms_(0) {}
virtual ~BweTestFramework_RateCounterFilterTest() {}
protected:
@ -244,7 +241,7 @@ TEST_F(BweTestFramework_RateCounterFilterTest, Long) {
}
static void TestLossFilter(float loss_percent, bool zero_tolerance) {
LossFilter filter(NULL);
LossFilter filter(NULL, 0);
filter.SetLoss(loss_percent);
Packets::size_type sent_packets = 0;
Packets::size_type remaining_packets = 0;
@ -308,10 +305,7 @@ TEST(BweTestFramework_LossFilterTest, Loss100) {
class BweTestFramework_DelayFilterTest : public ::testing::Test {
public:
BweTestFramework_DelayFilterTest()
: filter_(NULL),
now_ms_(0),
sequence_number_(0) {
}
: filter_(NULL, 0), now_ms_(0), sequence_number_(0) {}
virtual ~BweTestFramework_DelayFilterTest() {
for (auto* packet : accumulated_packets_)
delete packet;
@ -416,7 +410,7 @@ TEST_F(BweTestFramework_DelayFilterTest, Delay100) {
}
TEST_F(BweTestFramework_DelayFilterTest, JumpToZeroDelay) {
DelayFilter delay(NULL);
DelayFilter delay(NULL, 0);
Packets acc;
Packets packets;
@ -464,7 +458,7 @@ TEST_F(BweTestFramework_DelayFilterTest, IncreasingDelay) {
}
static void TestJitterFilter(int64_t stddev_jitter_ms) {
JitterFilter filter(NULL);
JitterFilter filter(NULL, 0);
filter.SetJitter(stddev_jitter_ms);
int64_t now_ms = 0;
@ -547,7 +541,7 @@ static void TestReorderFilter(uint32_t reorder_percent, uint32_t near_value) {
ASSERT_TRUE(IsSequenceNumberSorted(packets));
// Reorder packets, verify that send times are still in order.
ReorderFilter filter(NULL);
ReorderFilter filter(NULL, 0);
filter.SetReorder(reorder_percent);
filter.RunFor(now_ms, &packets);
ASSERT_TRUE(IsTimeSorted(packets));
@ -674,14 +668,14 @@ TEST_F(BweTestFramework_ChokeFilterTest, Short) {
// 100ms, 100 packets, 10 kbps choke -> 1 kbit of data should have propagated.
// That is actually just a single packet, since each packet has 1000 bits of
// payload.
ChokeFilter filter(NULL);
ChokeFilter filter(NULL, 0);
filter.SetCapacity(10);
TestChoke(&filter, 100, 100, 1);
}
TEST_F(BweTestFramework_ChokeFilterTest, Medium) {
// 100ms, 10 packets, 10 kbps choke -> 1 packet through, or 1 kbit.
ChokeFilter filter(NULL);
ChokeFilter filter(NULL, 0);
filter.SetCapacity(10);
TestChoke(&filter, 100, 10, 1);
// 200ms, no new packets -> another packet through.
@ -694,7 +688,7 @@ TEST_F(BweTestFramework_ChokeFilterTest, Medium) {
TEST_F(BweTestFramework_ChokeFilterTest, Long) {
// 100ms, 100 packets in queue, 10 kbps choke -> 1 packet through, or 1 kbit.
ChokeFilter filter(NULL);
ChokeFilter filter(NULL, 0);
filter.SetCapacity(10);
TestChoke(&filter, 100, 100, 1);
// 200ms, no input, another packet through.
@ -716,7 +710,7 @@ TEST_F(BweTestFramework_ChokeFilterTest, Long) {
TEST_F(BweTestFramework_ChokeFilterTest, MaxDelay) {
// 10 kbps choke, 500 ms delay cap
ChokeFilter filter(NULL);
ChokeFilter filter(NULL, 0);
filter.SetCapacity(10);
filter.SetMaxDelay(500);
// 100ms, 100 packets in queue, 10 kbps choke -> 1 packet through, or 1 kbit.
@ -745,7 +739,7 @@ TEST_F(BweTestFramework_ChokeFilterTest, MaxDelay) {
TEST_F(BweTestFramework_ChokeFilterTest, ShortTrace) {
// According to the input file 6 packets should be transmitted within
// 100 milliseconds.
TraceBasedDeliveryFilter filter(NULL);
TraceBasedDeliveryFilter filter(NULL, 0);
ASSERT_TRUE(filter.Init(test::ResourcePath("synthetic-trace", "rx")));
TestChoke(&filter, 100, 100, 6);
}
@ -753,13 +747,13 @@ TEST_F(BweTestFramework_ChokeFilterTest, ShortTrace) {
TEST_F(BweTestFramework_ChokeFilterTest, ShortTraceTwoWraps) {
// According to the input file 19 packets should be transmitted within
// 280 milliseconds (at the wrapping point two packets are sent back to back).
TraceBasedDeliveryFilter filter(NULL);
TraceBasedDeliveryFilter filter(NULL, 0);
ASSERT_TRUE(filter.Init(test::ResourcePath("synthetic-trace", "rx")));
TestChoke(&filter, 280, 100, 19);
}
TEST_F(BweTestFramework_ChokeFilterTest, ShortTraceMaxDelay) {
TraceBasedDeliveryFilter filter(NULL);
TraceBasedDeliveryFilter filter(NULL, 0);
filter.SetMaxDelay(25);
ASSERT_TRUE(filter.Init(test::ResourcePath("synthetic-trace", "rx")));
// Uses all slots up to 110 ms. Several packets are being dropped.
@ -818,7 +812,7 @@ TEST(BweTestFramework_VideoSenderTest, Fps1Kbps80_1s) {
// 1 fps, 80 kbps
VideoSource source(0, 1.0f, 80, 0x1234, 0);
PacketSender sender(NULL, &source, kNullEstimator);
EXPECT_EQ(10000u, source.bytes_per_second());
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.
TestVideoSender(&sender, 1, 9, 400, 10000);
@ -836,7 +830,7 @@ TEST(BweTestFramework_VideoSenderTest, Fps1Kbps80_1s_Offset) {
// 1 fps, 80 kbps, offset 0.5 of a frame period, ==0.5s in this case.
VideoSource source(0, 1.0f, 80, 0x1234, 500);
PacketSender sender(NULL, &source, kNullEstimator);
EXPECT_EQ(10000u, source.bytes_per_second());
EXPECT_EQ(80000u, source.bits_per_second());
// 499ms, no output.
TestVideoSender(&sender, 499, 0, 0, 0);
// 500ms, first frame (this is the offset we set), 10 packets of 1000 bytes.
@ -857,7 +851,7 @@ TEST(BweTestFramework_VideoSenderTest, Fps50Kpbs80_11s) {
// 50 fps, 80 kbps.
VideoSource source(0, 50.0f, 80, 0x1234, 0);
PacketSender sender(NULL, &source, kNullEstimator);
EXPECT_EQ(10000u, source.bytes_per_second());
EXPECT_EQ(80000u, source.bits_per_second());
// 9998ms, should see 500 frames, 200 byte payloads, total 100000 bytes.
TestVideoSender(&sender, 9998, 500, 200, 100000);
// 9999ms, nothing.
@ -874,7 +868,7 @@ TEST(BweTestFramework_VideoSenderTest, Fps10Kpbs120_1s) {
// 20 fps, 120 kbps.
VideoSource source(0, 20.0f, 120, 0x1234, 0);
PacketSender sender(NULL, &source, kNullEstimator);
EXPECT_EQ(15000u, source.bytes_per_second());
EXPECT_EQ(120000u, source.bits_per_second());
// 498ms, 10 frames with 750 byte payloads, total 7500 bytes.
TestVideoSender(&sender, 498, 10, 750, 7500);
// 499ms, nothing.
@ -891,7 +885,7 @@ TEST(BweTestFramework_VideoSenderTest, Fps30Kbps800_20s) {
// 20 fps, 820 kbps.
VideoSource source(0, 25.0f, 820, 0x1234, 0);
PacketSender sender(NULL, &source, kNullEstimator);
EXPECT_EQ(102500u, source.bytes_per_second());
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),
// so packet count should be 5*250=1250 and last packet of each frame has
@ -913,7 +907,7 @@ TEST(BweTestFramework_VideoSenderTest, TestAppendInOrder) {
// 1 fps, 80 kbps, 250ms offset.
VideoSource source1(0, 1.0f, 80, 0x1234, 250);
PacketSender sender1(NULL, &source1, kNullEstimator);
EXPECT_EQ(10000u, source1.bytes_per_second());
EXPECT_EQ(80000u, source1.bits_per_second());
Packets packets;
// Generate some packets, verify they are sorted.
sender1.RunFor(999, &packets);
@ -929,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);
EXPECT_EQ(20000u, source2.bytes_per_second());
EXPECT_EQ(160000u, source2.bits_per_second());
// Generate some packets, verify that they are merged with the packets already
// on the list.
sender2.RunFor(999, &packets);
@ -948,35 +942,63 @@ TEST(BweTestFramework_VideoSenderTest, FeedbackIneffective) {
VideoSource source(0, 25.0f, 820, 0x1234, 0);
PacketSender sender(NULL, &source, kNullEstimator);
EXPECT_EQ(102500u, source.bytes_per_second());
EXPECT_EQ(820000u, source.bits_per_second());
TestVideoSender(&sender, 9998, 1000, 500, 1025000);
// Make sure feedback has no effect on a regular video sender.
RembFeedback feedback(0, 0, 512000, RTCPReportBlock());
sender.GiveFeedback(feedback);
EXPECT_EQ(102500u, source.bytes_per_second());
RembFeedback* feedback = new RembFeedback(0, 0, 512000, RTCPReportBlock());
Packets packets;
packets.push_back(feedback);
sender.RunFor(0, &packets);
EXPECT_EQ(820000u, source.bits_per_second());
TestVideoSender(&sender, 9998, 1000, 500, 1025000);
}
TEST(BweTestFramework_AdaptiveVideoSenderTest, FeedbackChangesBitrate) {
AdaptiveVideoSource source(0, 25.0f, 820, 0x1234, 0);
PacketSender sender(NULL, &source, kRembEstimator);
EXPECT_EQ(102500u, source.bytes_per_second());
EXPECT_EQ(820000u, source.bits_per_second());
TestVideoSender(&sender, 9998, 1000, 500, 1025000);
// Make sure we can reduce the bitrate.
RembFeedback feedback(0, 0, 512000, RTCPReportBlock());
sender.GiveFeedback(feedback);
EXPECT_EQ(64000u, source.bytes_per_second());
RembFeedback* feedback = new RembFeedback(0, 0, 512000, RTCPReportBlock());
Packets packets;
packets.push_back(feedback);
sender.RunFor(0, &packets);
EXPECT_EQ(512000u, source.bits_per_second());
TestVideoSender(&sender, 9998, 750, 160, 640000);
// Increase the bitrate to the initial bitrate and verify that the output is
// the same.
RembFeedback feedback2(0, 0, 820000, RTCPReportBlock());
sender.GiveFeedback(feedback2);
Packets packets;
feedback = new RembFeedback(0, 0, 820000, RTCPReportBlock());
packets.push_back(feedback);
sender.RunFor(10000, &packets);
EXPECT_EQ(102500u, source.bytes_per_second());
EXPECT_EQ(820000u, source.bits_per_second());
for (auto* packet : packets)
delete packet;
}
TEST(BweTestFramework_AdaptiveVideoSenderTest, Paced_FeedbackChangesBitrate) {
AdaptiveVideoSource source(0, 25.0f, 820, 0x1234, 0);
PacedVideoSender sender(NULL, &source, kRembEstimator);
EXPECT_EQ(820000u, source.bits_per_second());
TestVideoSender(&sender, 9998, 1000, 500, 1025000);
// Make sure we can reduce the bitrate.
RembFeedback* feedback = new RembFeedback(0, 1, 512000, RTCPReportBlock());
Packets packets;
packets.push_back(feedback);
sender.RunFor(10000, &packets);
ASSERT_EQ(512000u, source.bits_per_second());
TestVideoSender(&sender, 9998, 750, 160, 640000);
// Increase the bitrate to the initial bitrate and verify that the output is
// the same.
feedback = new RembFeedback(0, 0, 820000, RTCPReportBlock());
packets.push_back(feedback);
sender.RunFor(10000, &packets);
EXPECT_EQ(820000u, source.bits_per_second());
for (auto* packet : packets)
delete packet;