2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
11 #include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h"
23 : kWindowSizeUs(1000000),
24 packets_per_second_(0),
26 last_accumulated_us_(0),
29 void UpdateRates(int64_t send_time_us, uint32_t payload_size) {
30 packets_per_second_++;
31 bytes_per_second_ += payload_size;
32 last_accumulated_us_ = send_time_us;
33 window_.push_back(std::make_pair(send_time_us, payload_size));
34 while (!window_.empty()) {
35 const TimeSizePair& packet = window_.front();
36 if (packet.first > (last_accumulated_us_ - kWindowSizeUs)) {
39 assert(packets_per_second_ >= 1);
40 assert(bytes_per_second_ >= packet.second);
41 packets_per_second_--;
42 bytes_per_second_ -= packet.second;
47 uint32_t bits_per_second() const {
48 return bytes_per_second_ * 8;
50 uint32_t packets_per_second() const { return packets_per_second_; }
53 typedef std::pair<int64_t, uint32_t> TimeSizePair;
55 const int64_t kWindowSizeUs;
56 uint32_t packets_per_second_;
57 uint32_t bytes_per_second_;
58 int64_t last_accumulated_us_;
59 std::list<TimeSizePair> window_;
62 Random::Random(uint32_t seed)
63 : a_(0x531FDB97 ^ seed),
64 b_(0x6420ECA8 + seed) {
67 float Random::Rand() {
68 const float kScale = 1.0f / 0xffffffff;
69 float result = kScale * b_;
75 int Random::Gaussian(int mean, int standard_deviation) {
76 // Creating a Normal distribution variable from two independent uniform
77 // variables based on the Box-Muller transform, which is defined on the
78 // interval (0, 1], hence the mask+add below.
79 const double kPi = 3.14159265358979323846;
80 const double kScale = 1.0 / 0x80000000ul;
81 double u1 = kScale * ((a_ & 0x7ffffffful) + 1);
82 double u2 = kScale * ((b_ & 0x7ffffffful) + 1);
85 return static_cast<int>(mean + standard_deviation *
86 std::sqrt(-2 * std::log(u1)) * std::cos(2 * kPi * u2));
90 : creation_time_us_(-1),
93 memset(&header_, 0, sizeof(header_));
96 Packet::Packet(int64_t send_time_us, uint32_t payload_size,
97 const RTPHeader& header)
98 : creation_time_us_(send_time_us),
99 send_time_us_(send_time_us),
100 payload_size_(payload_size),
104 Packet::Packet(int64_t send_time_us, uint32_t sequence_number)
105 : creation_time_us_(send_time_us),
106 send_time_us_(send_time_us),
108 memset(&header_, 0, sizeof(header_));
109 header_.sequenceNumber = sequence_number;
112 bool Packet::operator<(const Packet& rhs) const {
113 return send_time_us_ < rhs.send_time_us_;
116 void Packet::set_send_time_us(int64_t send_time_us) {
117 assert(send_time_us >= 0);
118 send_time_us_ = send_time_us;
121 bool IsTimeSorted(const Packets& packets) {
122 PacketsConstIt last_it = packets.begin();
123 for (PacketsConstIt it = last_it; it != packets.end(); ++it) {
124 if (it != last_it && *it < *last_it) {
132 PacketProcessor::PacketProcessor(PacketProcessorListener* listener)
133 : listener_(listener) {
135 listener_->AddPacketProcessor(this);
139 PacketProcessor::~PacketProcessor() {
141 listener_->RemovePacketProcessor(this);
145 RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener)
146 : PacketProcessor(listener),
147 rate_counter_(new RateCounter()),
152 RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener,
153 const std::string& name)
154 : PacketProcessor(listener),
155 rate_counter_(new RateCounter()),
160 RateCounterFilter::~RateCounterFilter() {
164 uint32_t RateCounterFilter::packets_per_second() const {
165 return rate_counter_->packets_per_second();
168 uint32_t RateCounterFilter::bits_per_second() const {
169 return rate_counter_->bits_per_second();
172 void RateCounterFilter::LogStats() {
173 BWE_TEST_LOGGING_CONTEXT("RateCounterFilter");
174 pps_stats_.Log("pps");
175 kbps_stats_.Log("kbps");
178 void RateCounterFilter::Plot(int64_t timestamp_ms) {
179 BWE_TEST_LOGGING_CONTEXT(name_.c_str());
180 BWE_TEST_LOGGING_PLOT("Throughput_#1", timestamp_ms,
181 rate_counter_->bits_per_second() / 1000.0);
184 void RateCounterFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
186 for (PacketsConstIt it = in_out->begin(); it != in_out->end(); ++it) {
187 rate_counter_->UpdateRates(it->send_time_us(), it->payload_size());
189 pps_stats_.Push(rate_counter_->packets_per_second());
190 kbps_stats_.Push(rate_counter_->bits_per_second() / 1000.0);
193 LossFilter::LossFilter(PacketProcessorListener* listener)
194 : PacketProcessor(listener),
196 loss_fraction_(0.0f) {
199 void LossFilter::SetLoss(float loss_percent) {
200 BWE_TEST_LOGGING_ENABLE(false);
201 BWE_TEST_LOGGING_LOG1("Loss", "%f%%", loss_percent);
202 assert(loss_percent >= 0.0f);
203 assert(loss_percent <= 100.0f);
204 loss_fraction_ = loss_percent * 0.01f;
207 void LossFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
209 for (PacketsIt it = in_out->begin(); it != in_out->end(); ) {
210 if (random_.Rand() < loss_fraction_) {
211 it = in_out->erase(it);
218 DelayFilter::DelayFilter(PacketProcessorListener* listener)
219 : PacketProcessor(listener),
221 last_send_time_us_(0) {
224 void DelayFilter::SetDelay(int64_t delay_ms) {
225 BWE_TEST_LOGGING_ENABLE(false);
226 BWE_TEST_LOGGING_LOG1("Delay", "%d ms", static_cast<int>(delay_ms));
227 assert(delay_ms >= 0);
228 delay_us_ = delay_ms * 1000;
231 void DelayFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
233 for (PacketsIt it = in_out->begin(); it != in_out->end(); ++it) {
234 int64_t new_send_time_us = it->send_time_us() + delay_us_;
235 last_send_time_us_ = std::max(last_send_time_us_, new_send_time_us);
236 it->set_send_time_us(last_send_time_us_);
240 JitterFilter::JitterFilter(PacketProcessorListener* listener)
241 : PacketProcessor(listener),
243 stddev_jitter_us_(0),
244 last_send_time_us_(0) {
247 void JitterFilter::SetJitter(int64_t stddev_jitter_ms) {
248 BWE_TEST_LOGGING_ENABLE(false);
249 BWE_TEST_LOGGING_LOG1("Jitter", "%d ms",
250 static_cast<int>(stddev_jitter_ms));
251 assert(stddev_jitter_ms >= 0);
252 stddev_jitter_us_ = stddev_jitter_ms * 1000;
255 void JitterFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
257 for (PacketsIt it = in_out->begin(); it != in_out->end(); ++it) {
258 int64_t new_send_time_us = it->send_time_us();
259 new_send_time_us += random_.Gaussian(0, stddev_jitter_us_);
260 last_send_time_us_ = std::max(last_send_time_us_, new_send_time_us);
261 it->set_send_time_us(last_send_time_us_);
265 ReorderFilter::ReorderFilter(PacketProcessorListener* listener)
266 : PacketProcessor(listener),
268 reorder_fraction_(0.0f) {
271 void ReorderFilter::SetReorder(float reorder_percent) {
272 BWE_TEST_LOGGING_ENABLE(false);
273 BWE_TEST_LOGGING_LOG1("Reordering", "%f%%", reorder_percent);
274 assert(reorder_percent >= 0.0f);
275 assert(reorder_percent <= 100.0f);
276 reorder_fraction_ = reorder_percent * 0.01f;
279 void ReorderFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
281 if (in_out->size() >= 2) {
282 PacketsIt last_it = in_out->begin();
283 PacketsIt it = last_it;
284 while (++it != in_out->end()) {
285 if (random_.Rand() < reorder_fraction_) {
286 int64_t t1 = last_it->send_time_us();
287 int64_t t2 = it->send_time_us();
288 std::swap(*last_it, *it);
289 last_it->set_send_time_us(t1);
290 it->set_send_time_us(t2);
297 ChokeFilter::ChokeFilter(PacketProcessorListener* listener)
298 : PacketProcessor(listener),
301 last_send_time_us_(0) {
304 void ChokeFilter::SetCapacity(uint32_t kbps) {
305 BWE_TEST_LOGGING_ENABLE(false);
306 BWE_TEST_LOGGING_LOG1("BitrateChoke", "%d kbps", kbps);
310 void ChokeFilter::SetMaxDelay(int64_t max_delay_ms) {
311 BWE_TEST_LOGGING_ENABLE(false);
312 BWE_TEST_LOGGING_LOG1("Max Delay", "%d ms", static_cast<int>(max_delay_ms));
313 assert(max_delay_ms >= 0);
314 max_delay_us_ = max_delay_ms * 1000;
317 void ChokeFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
319 for (PacketsIt it = in_out->begin(); it != in_out->end(); ) {
320 int64_t earliest_send_time_us = last_send_time_us_ +
321 (it->payload_size() * 8 * 1000 + kbps_ / 2) / kbps_;
322 int64_t new_send_time_us = std::max(it->send_time_us(),
323 earliest_send_time_us);
324 if (max_delay_us_ == 0 ||
325 max_delay_us_ >= (new_send_time_us - it->send_time_us())) {
326 it->set_send_time_us(new_send_time_us);
327 last_send_time_us_ = new_send_time_us;
330 it = in_out->erase(it);
335 TraceBasedDeliveryFilter::TraceBasedDeliveryFilter(
336 PacketProcessorListener* listener)
337 : PacketProcessor(listener),
338 delivery_times_us_(),
341 rate_counter_(new RateCounter),
344 TraceBasedDeliveryFilter::TraceBasedDeliveryFilter(
345 PacketProcessorListener* listener,
346 const std::string& name)
347 : PacketProcessor(listener),
348 delivery_times_us_(),
351 rate_counter_(new RateCounter),
354 TraceBasedDeliveryFilter::~TraceBasedDeliveryFilter() {
357 bool TraceBasedDeliveryFilter::Init(const std::string& filename) {
358 FILE* trace_file = fopen(filename.c_str(), "r");
362 int64_t first_timestamp = -1;
363 while(!feof(trace_file)) {
364 const size_t kMaxLineLength = 100;
365 char line[kMaxLineLength];
366 if (fgets(line, kMaxLineLength, trace_file)) {
367 std::string line_string(line);
368 std::istringstream buffer(line_string);
371 timestamp /= 1000; // Convert to microseconds.
372 if (first_timestamp == -1)
373 first_timestamp = timestamp;
374 assert(delivery_times_us_.empty() ||
375 timestamp - first_timestamp - delivery_times_us_.back() >= 0);
376 delivery_times_us_.push_back(timestamp - first_timestamp);
379 assert(!delivery_times_us_.empty());
380 next_delivery_it_ = delivery_times_us_.begin();
385 void TraceBasedDeliveryFilter::Plot(int64_t timestamp_ms) {
386 BWE_TEST_LOGGING_CONTEXT(name_.c_str());
387 // This plots the max possible throughput of the trace-based delivery filter,
388 // which will be reached if a packet sent on every packet slot of the trace.
389 BWE_TEST_LOGGING_PLOT("MaxThroughput_#1", timestamp_ms,
390 rate_counter_->bits_per_second() / 1000.0);
393 void TraceBasedDeliveryFilter::RunFor(int64_t time_ms, Packets* in_out) {
395 for (PacketsIt it = in_out->begin(); it != in_out->end(); ++it) {
398 const int kPayloadSize = 1240;
399 rate_counter_->UpdateRates(local_time_us_, kPayloadSize);
400 } while (local_time_us_ < it->send_time_us());
401 it->set_send_time_us(local_time_us_);
405 void TraceBasedDeliveryFilter::ProceedToNextSlot() {
406 if (*next_delivery_it_ <= local_time_us_) {
408 if (next_delivery_it_ == delivery_times_us_.end()) {
409 // When the trace wraps we allow two packets to be sent back-to-back.
410 for (TimeList::iterator it = delivery_times_us_.begin();
411 it != delivery_times_us_.end(); ++it) {
412 *it += local_time_us_;
414 next_delivery_it_ = delivery_times_us_.begin();
417 local_time_us_ = *next_delivery_it_;
420 PacketSender::PacketSender(PacketProcessorListener* listener)
421 : PacketProcessor(listener) {
424 VideoSender::VideoSender(PacketProcessorListener* listener, float fps,
425 uint32_t kbps, uint32_t ssrc, float first_frame_offset)
426 : PacketSender(listener),
427 kMaxPayloadSizeBytes(1000),
428 kTimestampBase(0xff80ff00ul),
429 frame_period_ms_(1000.0 / fps),
430 bytes_per_second_((1000 * kbps) / 8),
431 frame_size_bytes_(bytes_per_second_ / fps),
432 next_frame_ms_(frame_period_ms_ * first_frame_offset),
434 prototype_header_() {
435 assert(first_frame_offset >= 0.0f);
436 assert(first_frame_offset < 1.0f);
437 memset(&prototype_header_, 0, sizeof(prototype_header_));
438 prototype_header_.ssrc = ssrc;
439 prototype_header_.sequenceNumber = 0xf000u;
442 uint32_t VideoSender::GetCapacityKbps() const {
443 return (bytes_per_second_ * 8) / 1000;
446 void VideoSender::RunFor(int64_t time_ms, Packets* in_out) {
450 while (now_ms_ >= next_frame_ms_) {
451 prototype_header_.sequenceNumber++;
452 prototype_header_.timestamp = kTimestampBase +
453 static_cast<uint32_t>(next_frame_ms_ * 90.0);
454 prototype_header_.extension.absoluteSendTime = (kTimestampBase +
455 ((static_cast<int64_t>(next_frame_ms_ * (1 << 18)) + 500) / 1000)) &
457 prototype_header_.extension.transmissionTimeOffset = 0;
459 // Generate new packets for this frame, all with the same timestamp,
460 // but the payload size is capped, so if the whole frame doesn't fit in
461 // one packet, we will see a number of equally sized packets followed by
462 // one smaller at the tail.
463 int64_t send_time_us = next_frame_ms_ * 1000.0;
464 uint32_t payload_size = frame_size_bytes_;
465 while (payload_size > 0) {
466 uint32_t size = std::min(kMaxPayloadSizeBytes, payload_size);
467 newPackets.push_back(Packet(send_time_us, size, prototype_header_));
468 payload_size -= size;
471 next_frame_ms_ += frame_period_ms_;
473 in_out->merge(newPackets);
476 AdaptiveVideoSender::AdaptiveVideoSender(PacketProcessorListener* listener,
480 float first_frame_offset)
481 : VideoSender(listener, fps, kbps, ssrc, first_frame_offset) {}
483 void AdaptiveVideoSender::GiveFeedback(const PacketSender::Feedback& feedback) {
484 bytes_per_second_ = feedback.estimated_bps / 8;
485 frame_size_bytes_ = (bytes_per_second_ * frame_period_ms_ + 500) / 1000;
488 } // namespace testing
489 } // namespace webrtc