1 /* 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 3 * 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. 9 */ 10 11 #include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h" 12 13 #include <stdio.h> 14 15 #include <sstream> 16 17 namespace webrtc { 18 namespace testing { 19 namespace bwe { 20 class DelayCapHelper { 21 public: 22 DelayCapHelper() : max_delay_us_(0), delay_stats_() {} 23 24 void SetMaxDelay(int max_delay_ms) { 25 BWE_TEST_LOGGING_ENABLE(false); 26 BWE_TEST_LOGGING_LOG1("Max Delay", "%d ms", static_cast<int>(max_delay_ms)); 27 assert(max_delay_ms >= 0); 28 max_delay_us_ = max_delay_ms * 1000; 29 } 30 31 bool ShouldSendPacket(int64_t send_time_us, int64_t arrival_time_us) { 32 int64_t packet_delay_us = send_time_us - arrival_time_us; 33 delay_stats_.Push(std::min(packet_delay_us, max_delay_us_) / 1000); 34 return (max_delay_us_ == 0 || max_delay_us_ >= packet_delay_us); 35 } 36 37 const Stats<double>& delay_stats() const { 38 return delay_stats_; 39 } 40 41 private: 42 int64_t max_delay_us_; 43 Stats<double> delay_stats_; 44 45 DISALLOW_COPY_AND_ASSIGN(DelayCapHelper); 46 }; 47 48 const FlowIds CreateFlowIds(const int *flow_ids_array, size_t num_flow_ids) { 49 FlowIds flow_ids(&flow_ids_array[0], flow_ids_array + num_flow_ids); 50 return flow_ids; 51 } 52 53 class RateCounter { 54 public: 55 RateCounter() 56 : kWindowSizeUs(1000000), 57 packets_per_second_(0), 58 bytes_per_second_(0), 59 last_accumulated_us_(0), 60 window_() {} 61 62 void UpdateRates(int64_t send_time_us, uint32_t payload_size) { 63 packets_per_second_++; 64 bytes_per_second_ += payload_size; 65 last_accumulated_us_ = send_time_us; 66 window_.push_back(std::make_pair(send_time_us, payload_size)); 67 while (!window_.empty()) { 68 const TimeSizePair& packet = window_.front(); 69 if (packet.first > (last_accumulated_us_ - kWindowSizeUs)) { 70 break; 71 } 72 assert(packets_per_second_ >= 1); 73 assert(bytes_per_second_ >= packet.second); 74 packets_per_second_--; 75 bytes_per_second_ -= packet.second; 76 window_.pop_front(); 77 } 78 } 79 80 uint32_t bits_per_second() const { 81 return bytes_per_second_ * 8; 82 } 83 uint32_t packets_per_second() const { return packets_per_second_; } 84 85 private: 86 typedef std::pair<int64_t, uint32_t> TimeSizePair; 87 88 const int64_t kWindowSizeUs; 89 uint32_t packets_per_second_; 90 uint32_t bytes_per_second_; 91 int64_t last_accumulated_us_; 92 std::list<TimeSizePair> window_; 93 }; 94 95 Random::Random(uint32_t seed) 96 : a_(0x531FDB97 ^ seed), 97 b_(0x6420ECA8 + seed) { 98 } 99 100 float Random::Rand() { 101 const float kScale = 1.0f / 0xffffffff; 102 float result = kScale * b_; 103 a_ ^= b_; 104 b_ += a_; 105 return result; 106 } 107 108 int Random::Gaussian(int mean, int standard_deviation) { 109 // Creating a Normal distribution variable from two independent uniform 110 // variables based on the Box-Muller transform, which is defined on the 111 // interval (0, 1], hence the mask+add below. 112 const double kPi = 3.14159265358979323846; 113 const double kScale = 1.0 / 0x80000000ul; 114 double u1 = kScale * ((a_ & 0x7ffffffful) + 1); 115 double u2 = kScale * ((b_ & 0x7ffffffful) + 1); 116 a_ ^= b_; 117 b_ += a_; 118 return static_cast<int>(mean + standard_deviation * 119 sqrt(-2 * log(u1)) * cos(2 * kPi * u2)); 120 } 121 122 Packet::Packet() 123 : flow_id_(0), 124 creation_time_us_(-1), 125 send_time_us_(-1), 126 payload_size_(0) { 127 memset(&header_, 0, sizeof(header_)); 128 } 129 130 Packet::Packet(int flow_id, int64_t send_time_us, uint32_t payload_size, 131 const RTPHeader& header) 132 : flow_id_(flow_id), 133 creation_time_us_(send_time_us), 134 send_time_us_(send_time_us), 135 payload_size_(payload_size), 136 header_(header) { 137 } 138 139 Packet::Packet(int64_t send_time_us, uint32_t sequence_number) 140 : flow_id_(0), 141 creation_time_us_(send_time_us), 142 send_time_us_(send_time_us), 143 payload_size_(0) { 144 memset(&header_, 0, sizeof(header_)); 145 header_.sequenceNumber = sequence_number; 146 } 147 148 bool Packet::operator<(const Packet& rhs) const { 149 return send_time_us_ < rhs.send_time_us_; 150 } 151 152 void Packet::set_send_time_us(int64_t send_time_us) { 153 assert(send_time_us >= 0); 154 send_time_us_ = send_time_us; 155 } 156 157 bool IsTimeSorted(const Packets& packets) { 158 PacketsConstIt last_it = packets.begin(); 159 for (PacketsConstIt it = last_it; it != packets.end(); ++it) { 160 if (it != last_it && *it < *last_it) { 161 return false; 162 } 163 last_it = it; 164 } 165 return true; 166 } 167 168 PacketProcessor::PacketProcessor(PacketProcessorListener* listener, 169 bool is_sender) 170 : listener_(listener), flow_ids_(1, 0) { 171 if (listener_) { 172 listener_->AddPacketProcessor(this, is_sender); 173 } 174 } 175 176 PacketProcessor::PacketProcessor(PacketProcessorListener* listener, 177 const FlowIds& flow_ids, 178 bool is_sender) 179 : listener_(listener), flow_ids_(flow_ids) { 180 if (listener_) { 181 listener_->AddPacketProcessor(this, is_sender); 182 } 183 } 184 185 PacketProcessor::~PacketProcessor() { 186 if (listener_) { 187 listener_->RemovePacketProcessor(this); 188 } 189 } 190 191 RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener) 192 : PacketProcessor(listener, false), 193 rate_counter_(new RateCounter()), 194 packets_per_second_stats_(), 195 kbps_stats_(), 196 name_("") {} 197 198 RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener, 199 const std::string& name) 200 : PacketProcessor(listener, false), 201 rate_counter_(new RateCounter()), 202 packets_per_second_stats_(), 203 kbps_stats_(), 204 name_(name) {} 205 206 RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener, 207 const FlowIds& flow_ids, 208 const std::string& name) 209 : PacketProcessor(listener, flow_ids, false), 210 rate_counter_(new RateCounter()), 211 packets_per_second_stats_(), 212 kbps_stats_(), 213 name_(name) { 214 std::stringstream ss; 215 ss << name_ << "_"; 216 for (size_t i = 0; i < flow_ids.size(); ++i) { 217 ss << flow_ids[i] << ","; 218 } 219 name_ = ss.str(); 220 } 221 222 RateCounterFilter::~RateCounterFilter() { 223 LogStats(); 224 } 225 226 uint32_t RateCounterFilter::packets_per_second() const { 227 return rate_counter_->packets_per_second(); 228 } 229 230 uint32_t RateCounterFilter::bits_per_second() const { 231 return rate_counter_->bits_per_second(); 232 } 233 234 void RateCounterFilter::LogStats() { 235 BWE_TEST_LOGGING_CONTEXT("RateCounterFilter"); 236 packets_per_second_stats_.Log("pps"); 237 kbps_stats_.Log("kbps"); 238 } 239 240 Stats<double> RateCounterFilter::GetBitrateStats() const { 241 return kbps_stats_; 242 } 243 244 void RateCounterFilter::Plot(int64_t timestamp_ms) { 245 BWE_TEST_LOGGING_CONTEXT(name_.c_str()); 246 BWE_TEST_LOGGING_PLOT("Throughput_#1", timestamp_ms, 247 rate_counter_->bits_per_second() / 1000.0); 248 } 249 250 void RateCounterFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) { 251 assert(in_out); 252 for (PacketsConstIt it = in_out->begin(); it != in_out->end(); ++it) { 253 rate_counter_->UpdateRates(it->send_time_us(), it->payload_size()); 254 } 255 packets_per_second_stats_.Push(rate_counter_->packets_per_second()); 256 kbps_stats_.Push(rate_counter_->bits_per_second() / 1000.0); 257 } 258 259 LossFilter::LossFilter(PacketProcessorListener* listener) 260 : PacketProcessor(listener, false), 261 random_(0x12345678), 262 loss_fraction_(0.0f) { 263 } 264 265 void LossFilter::SetLoss(float loss_percent) { 266 BWE_TEST_LOGGING_ENABLE(false); 267 BWE_TEST_LOGGING_LOG1("Loss", "%f%%", loss_percent); 268 assert(loss_percent >= 0.0f); 269 assert(loss_percent <= 100.0f); 270 loss_fraction_ = loss_percent * 0.01f; 271 } 272 273 void LossFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) { 274 assert(in_out); 275 for (PacketsIt it = in_out->begin(); it != in_out->end(); ) { 276 if (random_.Rand() < loss_fraction_) { 277 it = in_out->erase(it); 278 } else { 279 ++it; 280 } 281 } 282 } 283 284 DelayFilter::DelayFilter(PacketProcessorListener* listener) 285 : PacketProcessor(listener, false), 286 delay_us_(0), 287 last_send_time_us_(0) { 288 } 289 290 void DelayFilter::SetDelay(int64_t delay_ms) { 291 BWE_TEST_LOGGING_ENABLE(false); 292 BWE_TEST_LOGGING_LOG1("Delay", "%d ms", static_cast<int>(delay_ms)); 293 assert(delay_ms >= 0); 294 delay_us_ = delay_ms * 1000; 295 } 296 297 void DelayFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) { 298 assert(in_out); 299 for (PacketsIt it = in_out->begin(); it != in_out->end(); ++it) { 300 int64_t new_send_time_us = it->send_time_us() + delay_us_; 301 last_send_time_us_ = std::max(last_send_time_us_, new_send_time_us); 302 it->set_send_time_us(last_send_time_us_); 303 } 304 } 305 306 JitterFilter::JitterFilter(PacketProcessorListener* listener) 307 : PacketProcessor(listener, false), 308 random_(0x89674523), 309 stddev_jitter_us_(0), 310 last_send_time_us_(0) { 311 } 312 313 void JitterFilter::SetJitter(int64_t stddev_jitter_ms) { 314 BWE_TEST_LOGGING_ENABLE(false); 315 BWE_TEST_LOGGING_LOG1("Jitter", "%d ms", 316 static_cast<int>(stddev_jitter_ms)); 317 assert(stddev_jitter_ms >= 0); 318 stddev_jitter_us_ = stddev_jitter_ms * 1000; 319 } 320 321 void JitterFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) { 322 assert(in_out); 323 for (PacketsIt it = in_out->begin(); it != in_out->end(); ++it) { 324 int64_t new_send_time_us = it->send_time_us(); 325 new_send_time_us += random_.Gaussian(0, stddev_jitter_us_); 326 last_send_time_us_ = std::max(last_send_time_us_, new_send_time_us); 327 it->set_send_time_us(last_send_time_us_); 328 } 329 } 330 331 ReorderFilter::ReorderFilter(PacketProcessorListener* listener) 332 : PacketProcessor(listener, false), 333 random_(0x27452389), 334 reorder_fraction_(0.0f) { 335 } 336 337 void ReorderFilter::SetReorder(float reorder_percent) { 338 BWE_TEST_LOGGING_ENABLE(false); 339 BWE_TEST_LOGGING_LOG1("Reordering", "%f%%", reorder_percent); 340 assert(reorder_percent >= 0.0f); 341 assert(reorder_percent <= 100.0f); 342 reorder_fraction_ = reorder_percent * 0.01f; 343 } 344 345 void ReorderFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) { 346 assert(in_out); 347 if (in_out->size() >= 2) { 348 PacketsIt last_it = in_out->begin(); 349 PacketsIt it = last_it; 350 while (++it != in_out->end()) { 351 if (random_.Rand() < reorder_fraction_) { 352 int64_t t1 = last_it->send_time_us(); 353 int64_t t2 = it->send_time_us(); 354 std::swap(*last_it, *it); 355 last_it->set_send_time_us(t1); 356 it->set_send_time_us(t2); 357 } 358 last_it = it; 359 } 360 } 361 } 362 363 ChokeFilter::ChokeFilter(PacketProcessorListener* listener) 364 : PacketProcessor(listener, false), 365 kbps_(1200), 366 last_send_time_us_(0), 367 delay_cap_helper_(new DelayCapHelper()) { 368 } 369 370 ChokeFilter::ChokeFilter(PacketProcessorListener* listener, 371 const FlowIds& flow_ids) 372 : PacketProcessor(listener, flow_ids, false), 373 kbps_(1200), 374 last_send_time_us_(0), 375 delay_cap_helper_(new DelayCapHelper()) { 376 } 377 378 ChokeFilter::~ChokeFilter() {} 379 380 void ChokeFilter::SetCapacity(uint32_t kbps) { 381 BWE_TEST_LOGGING_ENABLE(false); 382 BWE_TEST_LOGGING_LOG1("BitrateChoke", "%d kbps", kbps); 383 kbps_ = kbps; 384 } 385 386 void ChokeFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) { 387 assert(in_out); 388 for (PacketsIt it = in_out->begin(); it != in_out->end(); ) { 389 int64_t earliest_send_time_us = last_send_time_us_ + 390 (it->payload_size() * 8 * 1000 + kbps_ / 2) / kbps_; 391 int64_t new_send_time_us = std::max(it->send_time_us(), 392 earliest_send_time_us); 393 if (delay_cap_helper_->ShouldSendPacket(new_send_time_us, 394 it->send_time_us())) { 395 it->set_send_time_us(new_send_time_us); 396 last_send_time_us_ = new_send_time_us; 397 ++it; 398 } else { 399 it = in_out->erase(it); 400 } 401 } 402 } 403 404 void ChokeFilter::SetMaxDelay(int max_delay_ms) { 405 delay_cap_helper_->SetMaxDelay(max_delay_ms); 406 } 407 408 Stats<double> ChokeFilter::GetDelayStats() const { 409 return delay_cap_helper_->delay_stats(); 410 } 411 412 TraceBasedDeliveryFilter::TraceBasedDeliveryFilter( 413 PacketProcessorListener* listener) 414 : PacketProcessor(listener, false), 415 current_offset_us_(0), 416 delivery_times_us_(), 417 next_delivery_it_(), 418 local_time_us_(-1), 419 rate_counter_(new RateCounter), 420 name_(""), 421 delay_cap_helper_(new DelayCapHelper()), 422 packets_per_second_stats_(), 423 kbps_stats_() {} 424 425 TraceBasedDeliveryFilter::TraceBasedDeliveryFilter( 426 PacketProcessorListener* listener, 427 const std::string& name) 428 : PacketProcessor(listener, false), 429 current_offset_us_(0), 430 delivery_times_us_(), 431 next_delivery_it_(), 432 local_time_us_(-1), 433 rate_counter_(new RateCounter), 434 name_(name), 435 delay_cap_helper_(new DelayCapHelper()), 436 packets_per_second_stats_(), 437 kbps_stats_() {} 438 439 TraceBasedDeliveryFilter::~TraceBasedDeliveryFilter() { 440 } 441 442 bool TraceBasedDeliveryFilter::Init(const std::string& filename) { 443 FILE* trace_file = fopen(filename.c_str(), "r"); 444 if (!trace_file) { 445 return false; 446 } 447 int64_t first_timestamp = -1; 448 while(!feof(trace_file)) { 449 const size_t kMaxLineLength = 100; 450 char line[kMaxLineLength]; 451 if (fgets(line, kMaxLineLength, trace_file)) { 452 std::string line_string(line); 453 std::istringstream buffer(line_string); 454 int64_t timestamp; 455 buffer >> timestamp; 456 timestamp /= 1000; // Convert to microseconds. 457 if (first_timestamp == -1) 458 first_timestamp = timestamp; 459 assert(delivery_times_us_.empty() || 460 timestamp - first_timestamp - delivery_times_us_.back() >= 0); 461 delivery_times_us_.push_back(timestamp - first_timestamp); 462 } 463 } 464 assert(!delivery_times_us_.empty()); 465 next_delivery_it_ = delivery_times_us_.begin(); 466 fclose(trace_file); 467 return true; 468 } 469 470 void TraceBasedDeliveryFilter::Plot(int64_t timestamp_ms) { 471 BWE_TEST_LOGGING_CONTEXT(name_.c_str()); 472 // This plots the max possible throughput of the trace-based delivery filter, 473 // which will be reached if a packet sent on every packet slot of the trace. 474 BWE_TEST_LOGGING_PLOT("MaxThroughput_#1", timestamp_ms, 475 rate_counter_->bits_per_second() / 1000.0); 476 } 477 478 void TraceBasedDeliveryFilter::RunFor(int64_t time_ms, Packets* in_out) { 479 assert(in_out); 480 for (PacketsIt it = in_out->begin(); it != in_out->end();) { 481 while (local_time_us_ < it->send_time_us()) { 482 ProceedToNextSlot(); 483 } 484 // Drop any packets that have been queued for too long. 485 while (!delay_cap_helper_->ShouldSendPacket(local_time_us_, 486 it->send_time_us())) { 487 it = in_out->erase(it); 488 if (it == in_out->end()) { 489 return; 490 } 491 } 492 if (local_time_us_ >= it->send_time_us()) { 493 it->set_send_time_us(local_time_us_); 494 ProceedToNextSlot(); 495 } 496 ++it; 497 } 498 packets_per_second_stats_.Push(rate_counter_->packets_per_second()); 499 kbps_stats_.Push(rate_counter_->bits_per_second() / 1000.0); 500 } 501 502 void TraceBasedDeliveryFilter::SetMaxDelay(int max_delay_ms) { 503 delay_cap_helper_->SetMaxDelay(max_delay_ms); 504 } 505 506 Stats<double> TraceBasedDeliveryFilter::GetDelayStats() const { 507 return delay_cap_helper_->delay_stats(); 508 } 509 510 Stats<double> TraceBasedDeliveryFilter::GetBitrateStats() const { 511 return kbps_stats_; 512 } 513 514 void TraceBasedDeliveryFilter::ProceedToNextSlot() { 515 if (*next_delivery_it_ <= local_time_us_) { 516 ++next_delivery_it_; 517 if (next_delivery_it_ == delivery_times_us_.end()) { 518 // When the trace wraps we allow two packets to be sent back-to-back. 519 for (TimeList::iterator it = delivery_times_us_.begin(); 520 it != delivery_times_us_.end(); ++it) { 521 *it += local_time_us_ - current_offset_us_; 522 } 523 current_offset_us_ += local_time_us_ - current_offset_us_; 524 next_delivery_it_ = delivery_times_us_.begin(); 525 } 526 } 527 local_time_us_ = *next_delivery_it_; 528 const int kPayloadSize = 1200; 529 rate_counter_->UpdateRates(local_time_us_, kPayloadSize); 530 } 531 532 PacketSender::PacketSender(PacketProcessorListener* listener) 533 : PacketProcessor(listener, true) {} 534 535 PacketSender::PacketSender(PacketProcessorListener* listener, 536 const FlowIds& flow_ids) 537 : PacketProcessor(listener, flow_ids, true) { 538 539 } 540 541 VideoSender::VideoSender(int flow_id, PacketProcessorListener* listener, 542 float fps, uint32_t kbps, uint32_t ssrc, 543 float first_frame_offset) 544 : PacketSender(listener, FlowIds(1, flow_id)), 545 kMaxPayloadSizeBytes(1200), 546 kTimestampBase(0xff80ff00ul), 547 frame_period_ms_(1000.0 / fps), 548 bytes_per_second_((1000 * kbps) / 8), 549 frame_size_bytes_(bytes_per_second_ / fps), 550 next_frame_ms_(frame_period_ms_ * first_frame_offset), 551 now_ms_(0.0), 552 prototype_header_() { 553 assert(first_frame_offset >= 0.0f); 554 assert(first_frame_offset < 1.0f); 555 memset(&prototype_header_, 0, sizeof(prototype_header_)); 556 prototype_header_.ssrc = ssrc; 557 prototype_header_.sequenceNumber = 0xf000u; 558 } 559 560 uint32_t VideoSender::GetCapacityKbps() const { 561 return (bytes_per_second_ * 8) / 1000; 562 } 563 564 void VideoSender::RunFor(int64_t time_ms, Packets* in_out) { 565 assert(in_out); 566 now_ms_ += time_ms; 567 Packets new_packets; 568 while (now_ms_ >= next_frame_ms_) { 569 prototype_header_.sequenceNumber++; 570 prototype_header_.timestamp = kTimestampBase + 571 static_cast<uint32_t>(next_frame_ms_ * 90.0); 572 prototype_header_.extension.absoluteSendTime = (kTimestampBase + 573 ((static_cast<int64_t>(next_frame_ms_ * (1 << 18)) + 500) / 1000)) & 574 0x00fffffful; 575 prototype_header_.extension.transmissionTimeOffset = 0; 576 577 // Generate new packets for this frame, all with the same timestamp, 578 // but the payload size is capped, so if the whole frame doesn't fit in 579 // one packet, we will see a number of equally sized packets followed by 580 // one smaller at the tail. 581 int64_t send_time_us = next_frame_ms_ * 1000.0; 582 uint32_t payload_size = frame_size_bytes_; 583 while (payload_size > 0) { 584 uint32_t size = std::min(kMaxPayloadSizeBytes, payload_size); 585 new_packets.push_back(Packet(flow_ids()[0], send_time_us, size, 586 prototype_header_)); 587 payload_size -= size; 588 } 589 590 next_frame_ms_ += frame_period_ms_; 591 } 592 in_out->merge(new_packets); 593 } 594 595 AdaptiveVideoSender::AdaptiveVideoSender(int flow_id, 596 PacketProcessorListener* listener, 597 float fps, 598 uint32_t kbps, 599 uint32_t ssrc, 600 float first_frame_offset) 601 : VideoSender(flow_id, listener, fps, kbps, ssrc, first_frame_offset) {} 602 603 void AdaptiveVideoSender::GiveFeedback(const PacketSender::Feedback& feedback) { 604 bytes_per_second_ = feedback.estimated_bps / 8; 605 frame_size_bytes_ = (bytes_per_second_ * frame_period_ms_ + 500) / 1000; 606 } 607 } // namespace bwe 608 } // namespace testing 609 } // namespace webrtc 610