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:
@ -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
|
||||
|
@ -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_) {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,14 +310,17 @@ 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),
|
||||
packets.push_back(new Packet(now_ms_ * 1000 + (sequence_number_ >> 4),
|
||||
sequence_number_));
|
||||
sequence_number_++;
|
||||
}
|
||||
@ -308,7 +328,7 @@ class BweTestFramework_DelayFilterTest : public ::testing::Test {
|
||||
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
|
||||
|
Reference in New Issue
Block a user