Switched lists of packets to lists of packet pointers. Allows Packet polymorphism.

This allows for different packet types in a follow-up CL, so that feedback can be passed through the network instead being fed directly into senders. It also made the whole simulator faster.

BUG=4173
R=pbos@webrtc.org, sprang@webrtc.org

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

Cr-Commit-Position: refs/heads/master@{#8227}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8227 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
stefan@webrtc.org
2015-02-02 14:51:20 +00:00
parent c957ffc6dc
commit 946ad76f7e
5 changed files with 173 additions and 112 deletions

View File

@ -247,7 +247,7 @@ TEST_P(MultiFlowBweSimulation, PacedSelfFairnessTest) {
RateCounterFilter total_utilization(
this, CreateFlowIds(kAllFlowIds, kNumFlows), "total_utilization");
RunFor(3 * 60 * 1000);
RunFor(30 * 60 * 1000);
}
#endif // BWE_TEST_LOGGING_COMPILE_TIME_ENABLE
} // namespace bwe

View File

@ -184,6 +184,11 @@ class PacketProcessorRunner {
explicit PacketProcessorRunner(PacketProcessor* processor)
: processor_(processor) {}
~PacketProcessorRunner() {
for (auto* packet : queue_)
delete packet;
}
bool HasProcessor(const PacketProcessor* processor) const {
return processor == processor_;
}
@ -194,9 +199,9 @@ class PacketProcessorRunner {
processor_->RunFor(time_ms, &to_process);
QueuePackets(&to_process, time_now_ms * 1000);
if (!to_process.empty()) {
processor_->Plot((to_process.back().send_time_us() + 500) / 1000);
processor_->Plot((to_process.back()->send_time_us() + 500) / 1000);
}
in_out->merge(to_process);
in_out->merge(to_process, DereferencingComparator<Packet>);
}
private:
@ -207,7 +212,7 @@ class PacketProcessorRunner {
// TODO(holmer): Further optimize this by looking for consecutive flow ids
// in the packet list and only doing the binary search + splice once for a
// sequence.
if (flow_ids.find(it->flow_id()) != flow_ids.end()) {
if (flow_ids.find((*it)->flow_id()) != flow_ids.end()) {
Packets::iterator next = it;
++next;
out->splice(out->end(), *in, it);
@ -219,19 +224,19 @@ class PacketProcessorRunner {
}
void QueuePackets(Packets* batch, int64_t end_of_batch_time_us) {
queue_.merge(*batch);
queue_.merge(*batch, DereferencingComparator<Packet>);
if (queue_.empty()) {
return;
}
Packets::iterator it = queue_.begin();
for (; it != queue_.end(); ++it) {
if (it->send_time_us() > end_of_batch_time_us) {
if ((*it)->send_time_us() > end_of_batch_time_us) {
break;
}
}
Packets to_transfer;
to_transfer.splice(to_transfer.begin(), queue_, queue_.begin(), it);
batch->merge(to_transfer);
batch->merge(to_transfer, DereferencingComparator<Packet>);
}
PacketProcessor* processor_;
@ -278,10 +283,10 @@ void BweTest::SetupTestFromConfig(const BweTestConfig& config) {
void BweTest::AddPacketProcessor(PacketProcessor* processor, bool is_sender) {
assert(processor);
processors_.push_back(PacketProcessorRunner(processor));
if (is_sender) {
senders_.push_back(static_cast<PacketSender*>(processor));
}
processors_.push_back(PacketProcessorRunner(processor));
for (const auto& flow_id : processor->flow_ids()) {
RTC_UNUSED(flow_id);
assert(estimators_.count(flow_id) == 1);
@ -345,18 +350,20 @@ void BweTest::RunFor(int64_t time_ms) {
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);
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) {
EstimatorMap::iterator est_it = estimators_.find(packet.flow_id());
for (const auto* packet : packets) {
EstimatorMap::iterator est_it = estimators_.find(packet->flow_id());
ASSERT_TRUE(est_it != estimators_.end());
est_it->second->EatPacket(packet);
est_it->second->EatPacket(*packet);
delete packet;
}
for (const auto& estimator : estimators_) {

View File

@ -145,6 +145,9 @@ Packet::Packet(int64_t send_time_us, uint32_t sequence_number)
header_.sequenceNumber = sequence_number;
}
Packet::~Packet() {
}
bool Packet::operator<(const Packet& rhs) const {
return send_time_us_ < rhs.send_time_us_;
}
@ -163,7 +166,7 @@ void Packet::SetAbsSendTimeMs(int64_t abs_send_time_ms) {
bool IsTimeSorted(const Packets& packets) {
PacketsConstIt last_it = packets.begin();
for (PacketsConstIt it = last_it; it != packets.end(); ++it) {
if (it != last_it && *it < *last_it) {
if (it != last_it && **it < **last_it) {
return false;
}
last_it = it;
@ -266,8 +269,8 @@ void RateCounterFilter::Plot(int64_t timestamp_ms) {
void RateCounterFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
assert(in_out);
for (const auto& packet : *in_out) {
rate_counter_->UpdateRates(packet.send_time_us(), packet.payload_size());
for (const auto* packet : *in_out) {
rate_counter_->UpdateRates(packet->send_time_us(), packet->payload_size());
}
packets_per_second_stats_.Push(rate_counter_->packets_per_second());
kbps_stats_.Push(rate_counter_->bits_per_second() / 1000.0);
@ -291,6 +294,7 @@ void LossFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
assert(in_out);
for (PacketsIt it = in_out->begin(); it != in_out->end(); ) {
if (random_.Rand() < loss_fraction_) {
delete *it;
it = in_out->erase(it);
} else {
++it;
@ -313,10 +317,10 @@ void DelayFilter::SetDelay(int64_t delay_ms) {
void DelayFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
assert(in_out);
for (auto& packet : *in_out) {
int64_t new_send_time_us = packet.send_time_us() + delay_us_;
for (auto* packet : *in_out) {
int64_t new_send_time_us = packet->send_time_us() + delay_us_;
last_send_time_us_ = std::max(last_send_time_us_, new_send_time_us);
packet.set_send_time_us(last_send_time_us_);
packet->set_send_time_us(last_send_time_us_);
}
}
@ -337,11 +341,11 @@ void JitterFilter::SetJitter(int64_t stddev_jitter_ms) {
void JitterFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
assert(in_out);
for (auto& packet : *in_out) {
int64_t new_send_time_us = packet.send_time_us();
for (auto* packet : *in_out) {
int64_t new_send_time_us = packet->send_time_us();
new_send_time_us += random_.Gaussian(0, stddev_jitter_us_);
last_send_time_us_ = std::max(last_send_time_us_, new_send_time_us);
packet.set_send_time_us(last_send_time_us_);
packet->set_send_time_us(last_send_time_us_);
}
}
@ -366,11 +370,11 @@ void ReorderFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
PacketsIt it = last_it;
while (++it != in_out->end()) {
if (random_.Rand() < reorder_fraction_) {
int64_t t1 = last_it->send_time_us();
int64_t t2 = it->send_time_us();
std::swap(*last_it, *it);
last_it->set_send_time_us(t1);
it->set_send_time_us(t2);
int64_t t1 = (*last_it)->send_time_us();
int64_t t2 = (*it)->send_time_us();
std::swap(**last_it, **it);
(*last_it)->set_send_time_us(t1);
(*it)->set_send_time_us(t2);
}
last_it = it;
}
@ -403,16 +407,18 @@ void ChokeFilter::SetCapacity(uint32_t kbps) {
void ChokeFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
assert(in_out);
for (PacketsIt it = in_out->begin(); it != in_out->end(); ) {
int64_t earliest_send_time_us = last_send_time_us_ +
(it->payload_size() * 8 * 1000 + kbps_ / 2) / kbps_;
int64_t new_send_time_us = std::max(it->send_time_us(),
earliest_send_time_us);
int64_t earliest_send_time_us =
last_send_time_us_ +
((*it)->payload_size() * 8 * 1000 + kbps_ / 2) / kbps_;
int64_t new_send_time_us =
std::max((*it)->send_time_us(), earliest_send_time_us);
if (delay_cap_helper_->ShouldSendPacket(new_send_time_us,
it->send_time_us())) {
it->set_send_time_us(new_send_time_us);
(*it)->send_time_us())) {
(*it)->set_send_time_us(new_send_time_us);
last_send_time_us_ = new_send_time_us;
++it;
} else {
delete *it;
it = in_out->erase(it);
}
}
@ -495,19 +501,20 @@ void TraceBasedDeliveryFilter::Plot(int64_t timestamp_ms) {
void TraceBasedDeliveryFilter::RunFor(int64_t time_ms, Packets* in_out) {
assert(in_out);
for (PacketsIt it = in_out->begin(); it != in_out->end();) {
while (local_time_us_ < it->send_time_us()) {
while (local_time_us_ < (*it)->send_time_us()) {
ProceedToNextSlot();
}
// Drop any packets that have been queued for too long.
while (!delay_cap_helper_->ShouldSendPacket(local_time_us_,
it->send_time_us())) {
(*it)->send_time_us())) {
delete *it;
it = in_out->erase(it);
if (it == in_out->end()) {
return;
}
}
if (local_time_us_ >= it->send_time_us()) {
it->set_send_time_us(local_time_us_);
if (local_time_us_ >= (*it)->send_time_us()) {
(*it)->set_send_time_us(local_time_us_);
ProceedToNextSlot();
}
++it;
@ -594,14 +601,14 @@ void VideoSource::RunFor(int64_t time_ms, Packets* in_out) {
++prototype_header_.sequenceNumber;
uint32_t size = NextPacketSize(frame_size, payload_size);
new_packets.push_back(
Packet(flow_id_, send_time_us, size, prototype_header_));
new_packets.back().SetAbsSendTimeMs(next_frame_ms_);
new Packet(flow_id_, send_time_us, size, prototype_header_));
new_packets.back()->SetAbsSendTimeMs(next_frame_ms_);
payload_size -= size;
}
next_frame_ms_ += frame_period_ms_;
}
in_out->merge(new_packets);
in_out->merge(new_packets, DereferencingComparator<Packet>);
}
AdaptiveVideoSource::AdaptiveVideoSource(int flow_id,
@ -707,14 +714,12 @@ void RegularVideoSender::GiveFeedback(const Feedback& feedback) {
void RegularVideoSender::RunFor(int64_t time_ms, Packets* in_out) {
start_of_run_ms_ = clock_.TimeInMilliseconds();
int64_t time_left_ms = time_ms;
while (time_left_ms > 0) {
const int64_t kMaxRunTimeMs = 100;
int64_t time_to_run_ms = std::min(time_left_ms, kMaxRunTimeMs);
while (time_ms > 0) {
int64_t time_to_run_ms = std::min(time_ms, static_cast<int64_t>(100));
PacketSender::RunFor(time_to_run_ms, in_out);
clock_.AdvanceTimeMilliseconds(time_to_run_ms);
bitrate_controller_->Process();
time_left_ms -= time_to_run_ms;
time_ms -= time_to_run_ms;
}
}
@ -723,7 +728,7 @@ void RegularVideoSender::OnNetworkChanged(uint32_t target_bitrate_bps,
int64_t rtt) {
source_->SetBitrateBps(target_bitrate_bps);
std::stringstream ss;
ss << "SendEstimate_" << *flow_ids().begin() << "#1";
ss << "SendEstimate_" << source_->flow_id() << "#1";
BWE_TEST_LOGGING_PLOT(ss.str(), clock_.TimeInMilliseconds(),
target_bitrate_bps / 1000);
}
@ -744,6 +749,10 @@ PacedVideoSender::PacedVideoSender(PacketProcessorListener* listener,
}
PacedVideoSender::~PacedVideoSender() {
for (auto* packet : pacer_queue_)
delete packet;
for (auto* packet : queue_)
delete packet;
}
void PacedVideoSender::RunFor(int64_t time_ms, Packets* in_out) {
@ -759,7 +768,7 @@ void PacedVideoSender::RunFor(int64_t time_ms, Packets* in_out) {
int time_until_packet_ms = time_ms;
if (it != generated_packets.end())
time_until_packet_ms =
(it->send_time_us() + 500) / 1000 - clock_.TimeInMilliseconds();
((*it)->send_time_us() + 500) / 1000 - clock_.TimeInMilliseconds();
assert(time_until_packet_ms >= 0);
int time_until_next_event_ms = time_until_packet_ms;
@ -777,17 +786,12 @@ void PacedVideoSender::RunFor(int64_t time_ms, Packets* in_out) {
CallProcess(modules_);
} else {
// Time to send next packet to pacer.
pacer_.SendPacket(PacedSender::kNormalPriority,
it->header().ssrc,
it->header().sequenceNumber,
(it->send_time_us() + 500) / 1000,
it->payload_size(),
false);
pacer_.SendPacket(PacedSender::kNormalPriority, (*it)->header().ssrc,
(*it)->header().sequenceNumber,
((*it)->send_time_us() + 500) / 1000,
(*it)->payload_size(), false);
pacer_queue_.push_back(*it);
const size_t kMaxPacerQueueSize = 10000;
if (pacer_queue_.size() > kMaxPacerQueueSize) {
pacer_queue_.pop_front();
}
assert(pacer_queue_.size() < 10000);
++it;
}
}
@ -817,19 +821,19 @@ void PacedVideoSender::CallProcess(const std::list<Module*>& modules) {
void PacedVideoSender::QueuePackets(Packets* batch,
int64_t end_of_batch_time_us) {
queue_.merge(*batch);
queue_.merge(*batch, DereferencingComparator<Packet>);
if (queue_.empty()) {
return;
}
Packets::iterator it = queue_.begin();
for (; it != queue_.end(); ++it) {
if (it->send_time_us() > end_of_batch_time_us) {
if ((*it)->send_time_us() > end_of_batch_time_us) {
break;
}
}
Packets to_transfer;
to_transfer.splice(to_transfer.begin(), queue_, queue_.begin(), it);
batch->merge(to_transfer);
batch->merge(to_transfer, DereferencingComparator<Packet>);
}
bool PacedVideoSender::TimeToSendPacket(uint32_t ssrc,
@ -838,14 +842,15 @@ bool PacedVideoSender::TimeToSendPacket(uint32_t ssrc,
bool retransmission) {
for (Packets::iterator it = pacer_queue_.begin(); it != pacer_queue_.end();
++it) {
if (it->header().sequenceNumber == sequence_number) {
if ((*it)->header().sequenceNumber == sequence_number) {
int64_t pace_out_time_ms = clock_.TimeInMilliseconds();
// Make sure a packet is never paced out earlier than when it was put into
// the pacer.
assert(pace_out_time_ms >= (it->send_time_us() + 500) / 1000);
it->SetAbsSendTimeMs(pace_out_time_ms);
it->set_send_time_us(1000 * pace_out_time_ms);
assert(pace_out_time_ms >= ((*it)->send_time_us() + 500) / 1000);
(*it)->SetAbsSendTimeMs(pace_out_time_ms);
(*it)->set_send_time_us(1000 * pace_out_time_ms);
queue_.push_back(*it);
pacer_queue_.erase(it);
return true;
}
}

View File

@ -42,6 +42,11 @@ class RateCounter;
typedef std::set<int> FlowIds;
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) {
return *a < *b;
}
template<typename T> class Stats {
public:
Stats()
@ -160,6 +165,8 @@ class Packet {
const RTPHeader& header);
Packet(int64_t send_time_us, uint32_t sequence_number);
virtual ~Packet();
bool operator<(const Packet& rhs) const;
int flow_id() const { return flow_id_; }
@ -178,9 +185,9 @@ class Packet {
RTPHeader header_; // Actual contents.
};
typedef std::list<Packet> Packets;
typedef std::list<Packet>::iterator PacketsIt;
typedef std::list<Packet>::const_iterator PacketsConstIt;
typedef std::list<Packet*> Packets;
typedef std::list<Packet*>::iterator PacketsIt;
typedef std::list<Packet*>::const_iterator PacketsConstIt;
bool IsTimeSorted(const Packets& packets);

View File

@ -58,8 +58,8 @@ TEST(BweTestFramework_RandomTest, Gaussian) {
static bool IsSequenceNumberSorted(const Packets& packets) {
PacketsConstIt last_it = packets.begin();
for (PacketsConstIt it = last_it; it != packets.end(); ++it) {
if (IsNewerSequenceNumber(last_it->header().sequenceNumber,
it->header().sequenceNumber)) {
if (IsNewerSequenceNumber((*last_it)->header().sequenceNumber,
(*it)->header().sequenceNumber)) {
return false;
}
last_it = it;
@ -72,20 +72,24 @@ TEST(BweTestFramework_PacketTest, IsTimeSorted) {
// Insert some packets in order...
EXPECT_TRUE(IsTimeSorted(packets));
packets.push_back(Packet(100, 0));
packets.push_back(new Packet(100, 0));
EXPECT_TRUE(IsTimeSorted(packets));
packets.push_back(Packet(110, 0));
packets.push_back(new Packet(110, 0));
EXPECT_TRUE(IsTimeSorted(packets));
// ...and one out-of-order...
packets.push_back(Packet(100, 0));
packets.push_back(new Packet(100, 0));
EXPECT_FALSE(IsTimeSorted(packets));
// ...remove the out-of-order packet, insert another in-order packet.
delete packets.back();
packets.pop_back();
packets.push_back(Packet(120, 0));
packets.push_back(new Packet(120, 0));
EXPECT_TRUE(IsTimeSorted(packets));
for (auto* packet : packets)
delete packet;
}
TEST(BweTestFramework_PacketTest, IsSequenceNumberSorted) {
@ -93,20 +97,24 @@ TEST(BweTestFramework_PacketTest, IsSequenceNumberSorted) {
// Insert some packets in order...
EXPECT_TRUE(IsSequenceNumberSorted(packets));
packets.push_back(Packet(0, 100));
packets.push_back(new Packet(0, 100));
EXPECT_TRUE(IsSequenceNumberSorted(packets));
packets.push_back(Packet(0, 110));
packets.push_back(new Packet(0, 110));
EXPECT_TRUE(IsSequenceNumberSorted(packets));
// ...and one out-of-order...
packets.push_back(Packet(0, 100));
packets.push_back(new Packet(0, 100));
EXPECT_FALSE(IsSequenceNumberSorted(packets));
// ...remove the out-of-order packet, insert another in-order packet.
delete packets.back();
packets.pop_back();
packets.push_back(Packet(0, 120));
packets.push_back(new Packet(0, 120));
EXPECT_TRUE(IsSequenceNumberSorted(packets));
for (auto* packet : packets)
delete packet;
}
TEST(BweTestFramework_StatsTest, Mean) {
@ -184,12 +192,16 @@ class BweTestFramework_RateCounterFilterTest : public ::testing::Test {
RTPHeader header;
// "Send" a packet every 10 ms.
for (int64_t i = 0; i < run_for_ms; i += 10, now_ms_ += 10) {
packets.push_back(Packet(0, now_ms_ * 1000, payload_bits / 8, header));
packets.push_back(
new Packet(0, now_ms_ * 1000, payload_bits / 8, header));
}
filter_.RunFor(run_for_ms, &packets);
ASSERT_TRUE(IsTimeSorted(packets));
EXPECT_EQ(expected_pps, filter_.packets_per_second());
EXPECT_EQ(expected_bps, filter_.bits_per_second());
for (auto* packet : packets)
delete packet;
}
private:
@ -245,17 +257,22 @@ static void TestLossFilter(float loss_percent, bool zero_tolerance) {
remaining_packets += packets.size();
EXPECT_EQ(0u, sent_packets);
EXPECT_EQ(0u, remaining_packets);
for (auto* packet : packets)
delete packet;
}
// Generate and process 10000 packets in different batch sizes (some empty)
for (int i = 0; i < 2225; ++i) {
Packets packets;
packets.insert(packets.end(), i % 10, Packet());
for (int j = 0; j < i % 10; ++j)
packets.push_back(new Packet(i, i));
sent_packets += packets.size();
filter.RunFor(0, &packets);
ASSERT_TRUE(IsTimeSorted(packets));
ASSERT_TRUE(IsSequenceNumberSorted(packets));
remaining_packets += packets.size();
for (auto* packet : packets)
delete packet;
}
float loss_fraction = 0.01f * (100.0f - loss_percent);
@ -293,22 +310,25 @@ class BweTestFramework_DelayFilterTest : public ::testing::Test {
now_ms_(0),
sequence_number_(0) {
}
virtual ~BweTestFramework_DelayFilterTest() {}
virtual ~BweTestFramework_DelayFilterTest() {
for (auto* packet : accumulated_packets_)
delete packet;
}
protected:
void TestDelayFilter(int64_t run_for_ms, uint32_t in_packets,
uint32_t out_packets) {
Packets packets;
for (uint32_t i = 0; i < in_packets; ++i) {
packets.push_back(Packet(now_ms_ * 1000 + (sequence_number_ >> 4),
sequence_number_));
packets.push_back(new Packet(now_ms_ * 1000 + (sequence_number_ >> 4),
sequence_number_));
sequence_number_++;
}
filter_.RunFor(run_for_ms, &packets);
ASSERT_TRUE(IsTimeSorted(packets));
ASSERT_TRUE(IsSequenceNumberSorted(packets));
for (PacketsConstIt it = packets.begin(); it != packets.end(); ++it) {
EXPECT_LE(now_ms_ * 1000, it->send_time_us());
EXPECT_LE(now_ms_ * 1000, (*it)->send_time_us());
}
EXPECT_EQ(out_packets, packets.size());
accumulated_packets_.splice(accumulated_packets_.end(), packets);
@ -401,7 +421,7 @@ TEST_F(BweTestFramework_DelayFilterTest, JumpToZeroDelay) {
// Delay a bunch of packets, accumulate them to the 'acc' list.
delay.SetDelay(100.0f);
for (uint32_t i = 0; i < 10; ++i) {
packets.push_back(Packet(i * 100, i));
packets.push_back(new Packet(i * 100, i));
}
delay.RunFor(1000, &packets);
acc.splice(acc.end(), packets);
@ -412,12 +432,15 @@ TEST_F(BweTestFramework_DelayFilterTest, JumpToZeroDelay) {
// to the 'acc' list and verify that it is all sorted.
delay.SetDelay(0.0f);
for (uint32_t i = 10; i < 50; ++i) {
packets.push_back(Packet(i * 100, i));
packets.push_back(new Packet(i * 100, i));
}
delay.RunFor(1000, &packets);
acc.splice(acc.end(), packets);
ASSERT_TRUE(IsTimeSorted(acc));
ASSERT_TRUE(IsSequenceNumberSorted(acc));
for (auto* packet : acc)
delete packet;
}
TEST_F(BweTestFramework_DelayFilterTest, IncreasingDelay) {
@ -451,10 +474,11 @@ static void TestJitterFilter(int64_t stddev_jitter_ms) {
for (uint32_t i = 0; i < 1000; ++i) {
Packets packets;
for (uint32_t j = 0; j < i % 100; ++j) {
packets.push_back(Packet(now_ms * 1000, sequence_number++));
packets.push_back(new Packet(now_ms * 1000, sequence_number));
original.push_back(new Packet(now_ms * 1000, sequence_number));
++sequence_number;
now_ms += 5 * stddev_jitter_ms;
}
original.insert(original.end(), packets.begin(), packets.end());
filter.RunFor(stddev_jitter_ms, &packets);
jittered.splice(jittered.end(), packets);
}
@ -472,12 +496,16 @@ static void TestJitterFilter(int64_t stddev_jitter_ms) {
Stats<double> jitter_us;
for (PacketsIt it1 = original.begin(), it2 = jittered.begin();
it1 != original.end() && it2 != jittered.end(); ++it1, ++it2) {
EXPECT_EQ(it1->header().sequenceNumber, it2->header().sequenceNumber);
jitter_us.Push(it2->send_time_us() - it1->send_time_us());
EXPECT_EQ((*it1)->header().sequenceNumber, (*it2)->header().sequenceNumber);
jitter_us.Push((*it2)->send_time_us() - (*it1)->send_time_us());
}
EXPECT_NEAR(0.0, jitter_us.GetMean(), stddev_jitter_ms * 1000.0 * 0.008);
EXPECT_NEAR(stddev_jitter_ms * 1000.0, jitter_us.GetStdDev(),
stddev_jitter_ms * 1000.0 * 0.02);
for (auto* packet : original)
delete packet;
for (auto* packet : jittered)
delete packet;
}
TEST(BweTestFramework_JitterFilterTest, Jitter0) {
@ -508,7 +536,7 @@ static void TestReorderFilter(uint32_t reorder_percent, uint32_t near_value) {
int64_t now_ms = 0;
uint32_t sequence_number = 1;
for (uint32_t i = 0; i < kPacketCount; ++i, now_ms += 10) {
packets.push_back(Packet(now_ms * 1000, sequence_number++));
packets.push_back(new Packet(now_ms * 1000, sequence_number++));
}
ASSERT_TRUE(IsTimeSorted(packets));
ASSERT_TRUE(IsSequenceNumberSorted(packets));
@ -523,8 +551,8 @@ static void TestReorderFilter(uint32_t reorder_percent, uint32_t near_value) {
// of-order packets have been moved in the stream.
uint32_t distance = 0;
uint32_t last_sequence_number = 0;
for (PacketsIt it = packets.begin(); it != packets.end(); ++it) {
uint32_t sequence_number = it->header().sequenceNumber;
for (auto* packet : packets) {
uint32_t sequence_number = packet->header().sequenceNumber;
if (sequence_number < last_sequence_number) {
distance += last_sequence_number - sequence_number;
}
@ -535,6 +563,9 @@ static void TestReorderFilter(uint32_t reorder_percent, uint32_t near_value) {
// maximum distance a packet can be moved is PacketCount - 1.
EXPECT_NEAR(
((kPacketCount - 1) * reorder_percent) / 100, distance, near_value);
for (auto* packet : packets)
delete packet;
}
TEST(BweTestFramework_ReorderFilterTest, Reorder0) {
@ -574,7 +605,10 @@ class BweTestFramework_ChokeFilterTest : public ::testing::Test {
output_packets_(),
send_times_us_() {
}
virtual ~BweTestFramework_ChokeFilterTest() {}
virtual ~BweTestFramework_ChokeFilterTest() {
for (auto* packet : output_packets_)
delete packet;
}
protected:
void TestChoke(PacketProcessor* filter,
@ -588,7 +622,7 @@ class BweTestFramework_ChokeFilterTest : public ::testing::Test {
int64_t send_time_ms = now_ms_ + (i * run_for_ms) / packets_to_generate;
header.sequenceNumber = sequence_number_++;
// Payload is 1000 bits.
packets.push_back(Packet(0, send_time_ms * 1000, 125, header));
packets.push_back(new Packet(0, send_time_ms * 1000, 125, header));
send_times_us_.push_back(send_time_ms * 1000);
}
ASSERT_TRUE(IsTimeSorted(packets));
@ -601,22 +635,21 @@ class BweTestFramework_ChokeFilterTest : public ::testing::Test {
// Sum up the transmitted bytes up until the current time.
uint32_t bytes_transmitted = 0;
while (!output_packets_.empty()) {
const Packet& packet = output_packets_.front();
if (packet.send_time_us() > now_ms_ * 1000) {
const Packet* packet = output_packets_.front();
if (packet->send_time_us() > now_ms_ * 1000) {
break;
}
bytes_transmitted += packet.payload_size();
bytes_transmitted += packet->payload_size();
delete output_packets_.front();
output_packets_.pop_front();
}
EXPECT_EQ(expected_kbit_transmitted, (bytes_transmitted * 8) / 1000);
}
void CheckMaxDelay(int64_t max_delay_ms) {
for (PacketsIt it = output_packets_.begin(); it != output_packets_.end();
++it) {
const Packet& packet = *it;
int64_t delay_us = packet.send_time_us() -
send_times_us_[packet.header().sequenceNumber];
for (const auto* packet : output_packets_) {
int64_t delay_us = packet->send_time_us() -
send_times_us_[packet->header().sequenceNumber];
EXPECT_GE(max_delay_ms * 1000, delay_us);
}
}
@ -747,25 +780,28 @@ void TestVideoSender(PacketSender* sender,
uint32_t absolute_send_time_wraps = 0;
uint32_t rtp_timestamp = 0;
uint32_t rtp_timestamp_wraps = 0;
for (PacketsIt it = packets.begin(); it != packets.end(); ++it) {
EXPECT_LE(send_time_us, it->send_time_us());
send_time_us = it->send_time_us();
if (sender->source()->max_payload_size_bytes() != it->payload_size()) {
EXPECT_EQ(expected_payload_size, it->payload_size());
for (const auto* packet : packets) {
EXPECT_LE(send_time_us, packet->send_time_us());
send_time_us = packet->send_time_us();
if (sender->source()->max_payload_size_bytes() != packet->payload_size()) {
EXPECT_EQ(expected_payload_size, packet->payload_size());
}
total_payload_size += it->payload_size();
if (absolute_send_time > it->header().extension.absoluteSendTime) {
total_payload_size += packet->payload_size();
if (absolute_send_time > packet->header().extension.absoluteSendTime) {
absolute_send_time_wraps++;
}
absolute_send_time = it->header().extension.absoluteSendTime;
if (rtp_timestamp > it->header().timestamp) {
absolute_send_time = packet->header().extension.absoluteSendTime;
if (rtp_timestamp > packet->header().timestamp) {
rtp_timestamp_wraps++;
}
rtp_timestamp = it->header().timestamp;
rtp_timestamp = packet->header().timestamp;
}
EXPECT_EQ(expected_total_payload_size, total_payload_size);
EXPECT_GE(1u, absolute_send_time_wraps);
EXPECT_GE(1u, rtp_timestamp_wraps);
for (auto* packet : packets)
delete packet;
}
TEST(BweTestFramework_VideoSenderTest, Fps1Kbps80_1s) {
@ -893,6 +929,9 @@ TEST(BweTestFramework_VideoSenderTest, TestAppendInOrder) {
sender2.RunFor(1000, &packets);
ASSERT_TRUE(IsTimeSorted(packets));
EXPECT_EQ(54u, packets.size());
for (auto* packet : packets)
delete packet;
}
TEST(BweTestFramework_VideoSenderTest, FeedbackIneffective) {
@ -928,6 +967,9 @@ TEST(BweTestFramework_AdaptiveVideoSenderTest, FeedbackChangesBitrate) {
Packets packets;
sender.RunFor(10000, &packets);
EXPECT_EQ(102500u, source.bytes_per_second());
for (auto* packet : packets)
delete packet;
}
} // namespace bwe
} // namespace testing