• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
21 class DelayCapHelper {
22  public:
23   // Max delay = 0 stands for +infinite.
DelayCapHelper()24   DelayCapHelper() : max_delay_us_(0), delay_stats_() {}
25 
set_max_delay_ms(int64_t max_delay_ms)26   void set_max_delay_ms(int64_t max_delay_ms) {
27     BWE_TEST_LOGGING_ENABLE(false);
28     BWE_TEST_LOGGING_LOG1("Max Delay", "%d ms", static_cast<int>(max_delay_ms));
29     assert(max_delay_ms >= 0);
30     max_delay_us_ = max_delay_ms * 1000;
31   }
32 
ShouldSendPacket(int64_t send_time_us,int64_t arrival_time_us)33   bool ShouldSendPacket(int64_t send_time_us, int64_t arrival_time_us) {
34     int64_t packet_delay_us = send_time_us - arrival_time_us;
35     delay_stats_.Push((std::min(packet_delay_us, max_delay_us_) + 500) / 1000);
36     return (max_delay_us_ == 0 || max_delay_us_ >= packet_delay_us);
37   }
38 
delay_stats() const39   const Stats<double>& delay_stats() const {
40     return delay_stats_;
41   }
42 
43  private:
44   int64_t max_delay_us_;
45   Stats<double> delay_stats_;
46 
47   RTC_DISALLOW_COPY_AND_ASSIGN(DelayCapHelper);
48 };
49 
CreateFlowIds(const int * flow_ids_array,size_t num_flow_ids)50 const FlowIds CreateFlowIds(const int *flow_ids_array, size_t num_flow_ids) {
51   FlowIds flow_ids(&flow_ids_array[0], flow_ids_array + num_flow_ids);
52   return flow_ids;
53 }
54 
CreateFlowIdRange(int initial_value,int last_value)55 const FlowIds CreateFlowIdRange(int initial_value, int last_value) {
56   int size = last_value - initial_value + 1;
57   assert(size > 0);
58   int* flow_ids_array = new int[size];
59   for (int i = initial_value; i <= last_value; ++i) {
60     flow_ids_array[i - initial_value] = i;
61   }
62   return CreateFlowIds(flow_ids_array, size);
63 }
64 
UpdateRates(int64_t send_time_us,uint32_t payload_size)65 void RateCounter::UpdateRates(int64_t send_time_us, uint32_t payload_size) {
66   ++recently_received_packets_;
67   recently_received_bytes_ += payload_size;
68   last_accumulated_us_ = send_time_us;
69   window_.push_back(std::make_pair(send_time_us, payload_size));
70   while (!window_.empty()) {
71     const TimeSizePair& packet = window_.front();
72     if (packet.first > (last_accumulated_us_ - window_size_us_)) {
73       break;
74     }
75     assert(recently_received_packets_ >= 1);
76     assert(recently_received_bytes_ >= packet.second);
77     --recently_received_packets_;
78     recently_received_bytes_ -= packet.second;
79     window_.pop_front();
80   }
81 }
82 
bits_per_second() const83 uint32_t RateCounter::bits_per_second() const {
84   return (8 * recently_received_bytes_) / BitrateWindowS();
85 }
86 
packets_per_second() const87 uint32_t RateCounter::packets_per_second() const {
88   return recently_received_packets_ / BitrateWindowS();
89 }
90 
BitrateWindowS() const91 double RateCounter::BitrateWindowS() const {
92   return static_cast<double>(window_size_us_) / (1000 * 1000);
93 }
94 
Packet()95 Packet::Packet()
96     : flow_id_(0),
97       creation_time_us_(-1),
98       send_time_us_(-1),
99       sender_timestamp_us_(-1),
100       payload_size_(0),
101       paced_(false) {
102 }
103 
Packet(int flow_id,int64_t send_time_us,size_t payload_size)104 Packet::Packet(int flow_id, int64_t send_time_us, size_t payload_size)
105     : flow_id_(flow_id),
106       creation_time_us_(send_time_us),
107       send_time_us_(send_time_us),
108       sender_timestamp_us_(send_time_us),
109       payload_size_(payload_size),
110       paced_(false) {
111 }
112 
~Packet()113 Packet::~Packet() {
114 }
115 
operator <(const Packet & rhs) const116 bool Packet::operator<(const Packet& rhs) const {
117   return send_time_us_ < rhs.send_time_us_;
118 }
119 
set_send_time_us(int64_t send_time_us)120 void Packet::set_send_time_us(int64_t send_time_us) {
121   assert(send_time_us >= 0);
122   send_time_us_ = send_time_us;
123 }
124 
MediaPacket()125 MediaPacket::MediaPacket() {
126   memset(&header_, 0, sizeof(header_));
127 }
128 
MediaPacket(int flow_id,int64_t send_time_us,size_t payload_size,uint16_t sequence_number)129 MediaPacket::MediaPacket(int flow_id,
130                          int64_t send_time_us,
131                          size_t payload_size,
132                          uint16_t sequence_number)
133     : Packet(flow_id, send_time_us, payload_size) {
134   header_ = RTPHeader();
135   header_.sequenceNumber = sequence_number;
136 }
137 
MediaPacket(int flow_id,int64_t send_time_us,size_t payload_size,const RTPHeader & header)138 MediaPacket::MediaPacket(int flow_id,
139                          int64_t send_time_us,
140                          size_t payload_size,
141                          const RTPHeader& header)
142     : Packet(flow_id, send_time_us, payload_size), header_(header) {
143 }
144 
MediaPacket(int64_t send_time_us,uint16_t sequence_number)145 MediaPacket::MediaPacket(int64_t send_time_us, uint16_t sequence_number)
146     : Packet(0, send_time_us, 0) {
147   header_ = RTPHeader();
148   header_.sequenceNumber = sequence_number;
149 }
150 
SetAbsSendTimeMs(int64_t abs_send_time_ms)151 void MediaPacket::SetAbsSendTimeMs(int64_t abs_send_time_ms) {
152   header_.extension.hasAbsoluteSendTime = true;
153   header_.extension.absoluteSendTime = ((static_cast<int64_t>(abs_send_time_ms *
154     (1 << 18)) + 500) / 1000) & 0x00fffffful;
155 }
156 
RembFeedback(int flow_id,int64_t send_time_us,int64_t last_send_time_ms,uint32_t estimated_bps,RTCPReportBlock report_block)157 RembFeedback::RembFeedback(int flow_id,
158                            int64_t send_time_us,
159                            int64_t last_send_time_ms,
160                            uint32_t estimated_bps,
161                            RTCPReportBlock report_block)
162     : FeedbackPacket(flow_id, send_time_us, last_send_time_ms),
163       estimated_bps_(estimated_bps),
164       report_block_(report_block) {
165 }
166 
SendSideBweFeedback(int flow_id,int64_t send_time_us,int64_t last_send_time_ms,const std::vector<PacketInfo> & packet_feedback_vector)167 SendSideBweFeedback::SendSideBweFeedback(
168     int flow_id,
169     int64_t send_time_us,
170     int64_t last_send_time_ms,
171     const std::vector<PacketInfo>& packet_feedback_vector)
172     : FeedbackPacket(flow_id, send_time_us, last_send_time_ms),
173       packet_feedback_vector_(packet_feedback_vector) {
174 }
175 
IsTimeSorted(const Packets & packets)176 bool IsTimeSorted(const Packets& packets) {
177   PacketsConstIt last_it = packets.begin();
178   for (PacketsConstIt it = last_it; it != packets.end(); ++it) {
179     if (it != last_it && **it < **last_it) {
180       return false;
181     }
182     last_it = it;
183   }
184   return true;
185 }
186 
PacketProcessor(PacketProcessorListener * listener,int flow_id,ProcessorType type)187 PacketProcessor::PacketProcessor(PacketProcessorListener* listener,
188                                  int flow_id,
189                                  ProcessorType type)
190     : listener_(listener), flow_ids_(&flow_id, &flow_id + 1) {
191   if (listener_) {
192     listener_->AddPacketProcessor(this, type);
193   }
194 }
195 
PacketProcessor(PacketProcessorListener * listener,const FlowIds & flow_ids,ProcessorType type)196 PacketProcessor::PacketProcessor(PacketProcessorListener* listener,
197                                  const FlowIds& flow_ids,
198                                  ProcessorType type)
199     : listener_(listener), flow_ids_(flow_ids) {
200   if (listener_) {
201     listener_->AddPacketProcessor(this, type);
202   }
203 }
204 
~PacketProcessor()205 PacketProcessor::~PacketProcessor() {
206   if (listener_) {
207     listener_->RemovePacketProcessor(this);
208   }
209 }
210 
packets_per_second() const211 uint32_t PacketProcessor::packets_per_second() const {
212   return rate_counter_.packets_per_second();
213 }
214 
bits_per_second() const215 uint32_t PacketProcessor::bits_per_second() const {
216   return rate_counter_.bits_per_second();
217 }
218 
RateCounterFilter(PacketProcessorListener * listener,int flow_id,const char * name,const std::string & plot_name)219 RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener,
220                                      int flow_id,
221                                      const char* name,
222                                      const std::string& plot_name)
223     : PacketProcessor(listener, flow_id, kRegular),
224       packets_per_second_stats_(),
225       kbps_stats_(),
226       start_plotting_time_ms_(0),
227       plot_name_(plot_name) {
228   std::stringstream ss;
229   ss << name << "_" << flow_id;
230   name_ = ss.str();
231 }
232 
RateCounterFilter(PacketProcessorListener * listener,const FlowIds & flow_ids,const char * name,const std::string & plot_name)233 RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener,
234                                      const FlowIds& flow_ids,
235                                      const char* name,
236                                      const std::string& plot_name)
237     : PacketProcessor(listener, flow_ids, kRegular),
238       packets_per_second_stats_(),
239       kbps_stats_(),
240       start_plotting_time_ms_(0),
241       plot_name_(plot_name) {
242   std::stringstream ss;
243   ss << name;
244   char delimiter = '_';
245   for (int flow_id : flow_ids) {
246     ss << delimiter << flow_id;
247     delimiter = ',';
248   }
249   name_ = ss.str();
250 }
251 
RateCounterFilter(PacketProcessorListener * listener,const FlowIds & flow_ids,const char * name,int64_t start_plotting_time_ms,const std::string & plot_name)252 RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener,
253                                      const FlowIds& flow_ids,
254                                      const char* name,
255                                      int64_t start_plotting_time_ms,
256                                      const std::string& plot_name)
257     : RateCounterFilter(listener, flow_ids, name, plot_name) {
258   start_plotting_time_ms_ = start_plotting_time_ms;
259 }
260 
~RateCounterFilter()261 RateCounterFilter::~RateCounterFilter() {
262   LogStats();
263 }
264 
265 
LogStats()266 void RateCounterFilter::LogStats() {
267   BWE_TEST_LOGGING_CONTEXT("RateCounterFilter");
268   packets_per_second_stats_.Log("pps");
269   kbps_stats_.Log("kbps");
270 }
271 
GetBitrateStats() const272 Stats<double> RateCounterFilter::GetBitrateStats() const {
273   return kbps_stats_;
274 }
275 
Plot(int64_t timestamp_ms)276 void RateCounterFilter::Plot(int64_t timestamp_ms) {
277   uint32_t plot_kbps = 0;
278   if (timestamp_ms >= start_plotting_time_ms_) {
279     plot_kbps = rate_counter_.bits_per_second() / 1000.0;
280   }
281   BWE_TEST_LOGGING_CONTEXT(name_.c_str());
282   if (plot_name_.empty()) {
283     BWE_TEST_LOGGING_PLOT(0, "Throughput_kbps#1", timestamp_ms, plot_kbps);
284   } else {
285     BWE_TEST_LOGGING_PLOT_WITH_NAME(0, "Throughput_kbps#1", timestamp_ms,
286                                     plot_kbps, plot_name_);
287   }
288 
289   RTC_UNUSED(plot_kbps);
290 }
291 
RunFor(int64_t,Packets * in_out)292 void RateCounterFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
293   assert(in_out);
294   for (const Packet* packet : *in_out) {
295     rate_counter_.UpdateRates(packet->send_time_us(),
296                               static_cast<int>(packet->payload_size()));
297   }
298   packets_per_second_stats_.Push(rate_counter_.packets_per_second());
299   kbps_stats_.Push(rate_counter_.bits_per_second() / 1000.0);
300 }
301 
LossFilter(PacketProcessorListener * listener,int flow_id)302 LossFilter::LossFilter(PacketProcessorListener* listener, int flow_id)
303     : PacketProcessor(listener, flow_id, kRegular),
304       random_(0x12345678),
305       loss_fraction_(0.0f) {
306 }
307 
LossFilter(PacketProcessorListener * listener,const FlowIds & flow_ids)308 LossFilter::LossFilter(PacketProcessorListener* listener,
309                        const FlowIds& flow_ids)
310     : PacketProcessor(listener, flow_ids, kRegular),
311       random_(0x12345678),
312       loss_fraction_(0.0f) {
313 }
314 
SetLoss(float loss_percent)315 void LossFilter::SetLoss(float loss_percent) {
316   BWE_TEST_LOGGING_ENABLE(false);
317   BWE_TEST_LOGGING_LOG1("Loss", "%f%%", loss_percent);
318   assert(loss_percent >= 0.0f);
319   assert(loss_percent <= 100.0f);
320   loss_fraction_ = loss_percent * 0.01f;
321 }
322 
RunFor(int64_t,Packets * in_out)323 void LossFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
324   assert(in_out);
325   for (PacketsIt it = in_out->begin(); it != in_out->end(); ) {
326     if (random_.Rand<float>() < loss_fraction_) {
327       delete *it;
328       it = in_out->erase(it);
329     } else {
330       ++it;
331     }
332   }
333 }
334 
335 const int64_t kDefaultOneWayDelayUs = 0;
336 
DelayFilter(PacketProcessorListener * listener,int flow_id)337 DelayFilter::DelayFilter(PacketProcessorListener* listener, int flow_id)
338     : PacketProcessor(listener, flow_id, kRegular),
339       one_way_delay_us_(kDefaultOneWayDelayUs),
340       last_send_time_us_(0) {
341 }
342 
DelayFilter(PacketProcessorListener * listener,const FlowIds & flow_ids)343 DelayFilter::DelayFilter(PacketProcessorListener* listener,
344                          const FlowIds& flow_ids)
345     : PacketProcessor(listener, flow_ids, kRegular),
346       one_way_delay_us_(kDefaultOneWayDelayUs),
347       last_send_time_us_(0) {
348 }
349 
SetOneWayDelayMs(int64_t one_way_delay_ms)350 void DelayFilter::SetOneWayDelayMs(int64_t one_way_delay_ms) {
351   BWE_TEST_LOGGING_ENABLE(false);
352   BWE_TEST_LOGGING_LOG1("Delay", "%d ms", static_cast<int>(one_way_delay_ms));
353   assert(one_way_delay_ms >= 0);
354   one_way_delay_us_ = one_way_delay_ms * 1000;
355 }
356 
RunFor(int64_t,Packets * in_out)357 void DelayFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
358   assert(in_out);
359   for (Packet* packet : *in_out) {
360     int64_t new_send_time_us = packet->send_time_us() + one_way_delay_us_;
361     last_send_time_us_ = std::max(last_send_time_us_, new_send_time_us);
362     packet->set_send_time_us(last_send_time_us_);
363   }
364 }
365 
JitterFilter(PacketProcessorListener * listener,int flow_id)366 JitterFilter::JitterFilter(PacketProcessorListener* listener, int flow_id)
367     : PacketProcessor(listener, flow_id, kRegular),
368       random_(0x89674523),
369       stddev_jitter_us_(0),
370       last_send_time_us_(0),
371       reordering_(false) {
372 }
373 
JitterFilter(PacketProcessorListener * listener,const FlowIds & flow_ids)374 JitterFilter::JitterFilter(PacketProcessorListener* listener,
375                            const FlowIds& flow_ids)
376     : PacketProcessor(listener, flow_ids, kRegular),
377       random_(0x89674523),
378       stddev_jitter_us_(0),
379       last_send_time_us_(0),
380       reordering_(false) {
381 }
382 
383 const int kN = 3;  // Truncated N sigma gaussian.
384 
SetMaxJitter(int64_t max_jitter_ms)385 void JitterFilter::SetMaxJitter(int64_t max_jitter_ms) {
386   BWE_TEST_LOGGING_ENABLE(false);
387   BWE_TEST_LOGGING_LOG1("Max Jitter", "%d ms", static_cast<int>(max_jitter_ms));
388   assert(max_jitter_ms >= 0);
389   // Truncated gaussian, Max jitter = kN*sigma.
390   stddev_jitter_us_ = (max_jitter_ms * 1000 + kN / 2) / kN;
391 }
392 
393 namespace {
TruncatedNSigmaGaussian(Random * const random,int64_t mean,int64_t std_dev)394 inline int64_t TruncatedNSigmaGaussian(Random* const random,
395                                        int64_t mean,
396                                        int64_t std_dev) {
397   int64_t gaussian_random = random->Gaussian(mean, std_dev);
398   return std::max(std::min(gaussian_random, kN * std_dev), -kN * std_dev);
399 }
400 }
401 
RunFor(int64_t,Packets * in_out)402 void JitterFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
403   assert(in_out);
404   for (Packet* packet : *in_out) {
405     int64_t jitter_us =
406         std::abs(TruncatedNSigmaGaussian(&random_, 0, stddev_jitter_us_));
407     int64_t new_send_time_us = packet->send_time_us() + jitter_us;
408 
409     if (!reordering_) {
410       new_send_time_us = std::max(last_send_time_us_, new_send_time_us);
411     }
412 
413     // Receiver timestamp cannot be lower than sender timestamp.
414     assert(new_send_time_us >= packet->sender_timestamp_us());
415 
416     packet->set_send_time_us(new_send_time_us);
417     last_send_time_us_ = new_send_time_us;
418   }
419 }
420 
421 // Computes the expected value for a right sided (abs) truncated gaussian.
422 // Does not take into account  possible reoerdering updates.
MeanUs()423 int64_t JitterFilter::MeanUs() {
424   const double kPi = 3.1415926535897932;
425   double max_jitter_us = static_cast<double>(kN * stddev_jitter_us_);
426   double right_sided_mean_us =
427       static_cast<double>(stddev_jitter_us_) / sqrt(kPi / 2.0);
428   double truncated_mean_us =
429       right_sided_mean_us *
430           (1.0 - exp(-pow(static_cast<double>(kN), 2.0) / 2.0)) +
431       max_jitter_us * erfc(static_cast<double>(kN));
432   return static_cast<int64_t>(truncated_mean_us + 0.5);
433 }
434 
ReorderFilter(PacketProcessorListener * listener,int flow_id)435 ReorderFilter::ReorderFilter(PacketProcessorListener* listener, int flow_id)
436     : PacketProcessor(listener, flow_id, kRegular),
437       random_(0x27452389),
438       reorder_fraction_(0.0f) {
439 }
440 
ReorderFilter(PacketProcessorListener * listener,const FlowIds & flow_ids)441 ReorderFilter::ReorderFilter(PacketProcessorListener* listener,
442                              const FlowIds& flow_ids)
443     : PacketProcessor(listener, flow_ids, kRegular),
444       random_(0x27452389),
445       reorder_fraction_(0.0f) {
446 }
447 
SetReorder(float reorder_percent)448 void ReorderFilter::SetReorder(float reorder_percent) {
449   BWE_TEST_LOGGING_ENABLE(false);
450   BWE_TEST_LOGGING_LOG1("Reordering", "%f%%", reorder_percent);
451   assert(reorder_percent >= 0.0f);
452   assert(reorder_percent <= 100.0f);
453   reorder_fraction_ = reorder_percent * 0.01f;
454 }
455 
RunFor(int64_t,Packets * in_out)456 void ReorderFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
457   assert(in_out);
458   if (in_out->size() >= 2) {
459     PacketsIt last_it = in_out->begin();
460     PacketsIt it = last_it;
461     while (++it != in_out->end()) {
462       if (random_.Rand<float>() < reorder_fraction_) {
463         int64_t t1 = (*last_it)->send_time_us();
464         int64_t t2 = (*it)->send_time_us();
465         std::swap(*last_it, *it);
466         (*last_it)->set_send_time_us(t1);
467         (*it)->set_send_time_us(t2);
468       }
469       last_it = it;
470     }
471   }
472 }
473 
474 const uint32_t kDefaultKbps = 1200;
475 
ChokeFilter(PacketProcessorListener * listener,int flow_id)476 ChokeFilter::ChokeFilter(PacketProcessorListener* listener, int flow_id)
477     : PacketProcessor(listener, flow_id, kRegular),
478       capacity_kbps_(kDefaultKbps),
479       last_send_time_us_(0),
480       delay_cap_helper_(new DelayCapHelper()) {
481 }
482 
ChokeFilter(PacketProcessorListener * listener,const FlowIds & flow_ids)483 ChokeFilter::ChokeFilter(PacketProcessorListener* listener,
484                          const FlowIds& flow_ids)
485     : PacketProcessor(listener, flow_ids, kRegular),
486       capacity_kbps_(kDefaultKbps),
487       last_send_time_us_(0),
488       delay_cap_helper_(new DelayCapHelper()) {
489 }
490 
~ChokeFilter()491 ChokeFilter::~ChokeFilter() {}
492 
set_capacity_kbps(uint32_t kbps)493 void ChokeFilter::set_capacity_kbps(uint32_t kbps) {
494   BWE_TEST_LOGGING_ENABLE(false);
495   BWE_TEST_LOGGING_LOG1("BitrateChoke", "%d kbps", kbps);
496   capacity_kbps_ = kbps;
497 }
498 
capacity_kbps()499 uint32_t ChokeFilter::capacity_kbps() {
500   return capacity_kbps_;
501 }
502 
RunFor(int64_t,Packets * in_out)503 void ChokeFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
504   assert(in_out);
505   for (PacketsIt it = in_out->begin(); it != in_out->end(); ) {
506     int64_t earliest_send_time_us =
507         std::max(last_send_time_us_, (*it)->send_time_us());
508 
509     int64_t new_send_time_us =
510         earliest_send_time_us +
511         ((*it)->payload_size() * 8 * 1000 + capacity_kbps_ / 2) /
512             capacity_kbps_;
513 
514     if (delay_cap_helper_->ShouldSendPacket(new_send_time_us,
515                                             (*it)->send_time_us())) {
516       (*it)->set_send_time_us(new_send_time_us);
517       last_send_time_us_ = new_send_time_us;
518       ++it;
519     } else {
520       delete *it;
521       it = in_out->erase(it);
522     }
523   }
524 }
525 
set_max_delay_ms(int64_t max_delay_ms)526 void ChokeFilter::set_max_delay_ms(int64_t max_delay_ms) {
527   delay_cap_helper_->set_max_delay_ms(max_delay_ms);
528 }
529 
GetDelayStats() const530 Stats<double> ChokeFilter::GetDelayStats() const {
531   return delay_cap_helper_->delay_stats();
532 }
533 
TraceBasedDeliveryFilter(PacketProcessorListener * listener,int flow_id)534 TraceBasedDeliveryFilter::TraceBasedDeliveryFilter(
535     PacketProcessorListener* listener,
536     int flow_id)
537     : PacketProcessor(listener, flow_id, kRegular),
538       current_offset_us_(0),
539       delivery_times_us_(),
540       next_delivery_it_(),
541       local_time_us_(-1),
542       rate_counter_(new RateCounter),
543       name_(""),
544       delay_cap_helper_(new DelayCapHelper()),
545       packets_per_second_stats_(),
546       kbps_stats_() {
547 }
548 
TraceBasedDeliveryFilter(PacketProcessorListener * listener,const FlowIds & flow_ids)549 TraceBasedDeliveryFilter::TraceBasedDeliveryFilter(
550     PacketProcessorListener* listener,
551     const FlowIds& flow_ids)
552     : PacketProcessor(listener, flow_ids, kRegular),
553       current_offset_us_(0),
554       delivery_times_us_(),
555       next_delivery_it_(),
556       local_time_us_(-1),
557       rate_counter_(new RateCounter),
558       name_(""),
559       delay_cap_helper_(new DelayCapHelper()),
560       packets_per_second_stats_(),
561       kbps_stats_() {
562 }
563 
TraceBasedDeliveryFilter(PacketProcessorListener * listener,int flow_id,const char * name)564 TraceBasedDeliveryFilter::TraceBasedDeliveryFilter(
565     PacketProcessorListener* listener,
566     int flow_id,
567     const char* name)
568     : PacketProcessor(listener, flow_id, kRegular),
569       current_offset_us_(0),
570       delivery_times_us_(),
571       next_delivery_it_(),
572       local_time_us_(-1),
573       rate_counter_(new RateCounter),
574       name_(name),
575       delay_cap_helper_(new DelayCapHelper()),
576       packets_per_second_stats_(),
577       kbps_stats_() {
578 }
579 
~TraceBasedDeliveryFilter()580 TraceBasedDeliveryFilter::~TraceBasedDeliveryFilter() {
581 }
582 
Init(const std::string & filename)583 bool TraceBasedDeliveryFilter::Init(const std::string& filename) {
584   FILE* trace_file = fopen(filename.c_str(), "r");
585   if (!trace_file) {
586     return false;
587   }
588   int64_t first_timestamp = -1;
589   while (!feof(trace_file)) {
590     const size_t kMaxLineLength = 100;
591     char line[kMaxLineLength];
592     if (fgets(line, kMaxLineLength, trace_file)) {
593       std::string line_string(line);
594       std::istringstream buffer(line_string);
595       int64_t timestamp;
596       buffer >> timestamp;
597       timestamp /= 1000;  // Convert to microseconds.
598       if (first_timestamp == -1)
599         first_timestamp = timestamp;
600       assert(delivery_times_us_.empty() ||
601              timestamp - first_timestamp - delivery_times_us_.back() >= 0);
602       delivery_times_us_.push_back(timestamp - first_timestamp);
603     }
604   }
605   assert(!delivery_times_us_.empty());
606   next_delivery_it_ = delivery_times_us_.begin();
607   fclose(trace_file);
608   return true;
609 }
610 
Plot(int64_t timestamp_ms)611 void TraceBasedDeliveryFilter::Plot(int64_t timestamp_ms) {
612   BWE_TEST_LOGGING_CONTEXT(name_.c_str());
613   // This plots the max possible throughput of the trace-based delivery filter,
614   // which will be reached if a packet sent on every packet slot of the trace.
615   BWE_TEST_LOGGING_PLOT(0, "MaxThroughput_#1", timestamp_ms,
616                         rate_counter_->bits_per_second() / 1000.0);
617 }
618 
RunFor(int64_t time_ms,Packets * in_out)619 void TraceBasedDeliveryFilter::RunFor(int64_t time_ms, Packets* in_out) {
620   assert(in_out);
621   for (PacketsIt it = in_out->begin(); it != in_out->end();) {
622     while (local_time_us_ < (*it)->send_time_us()) {
623       ProceedToNextSlot();
624     }
625     // Drop any packets that have been queued for too long.
626     while (!delay_cap_helper_->ShouldSendPacket(local_time_us_,
627                                                 (*it)->send_time_us())) {
628       delete *it;
629       it = in_out->erase(it);
630       if (it == in_out->end()) {
631         return;
632       }
633     }
634     if (local_time_us_ >= (*it)->send_time_us()) {
635       (*it)->set_send_time_us(local_time_us_);
636       ProceedToNextSlot();
637     }
638     ++it;
639   }
640   packets_per_second_stats_.Push(rate_counter_->packets_per_second());
641   kbps_stats_.Push(rate_counter_->bits_per_second() / 1000.0);
642 }
643 
set_max_delay_ms(int64_t max_delay_ms)644 void TraceBasedDeliveryFilter::set_max_delay_ms(int64_t max_delay_ms) {
645   delay_cap_helper_->set_max_delay_ms(max_delay_ms);
646 }
647 
GetDelayStats() const648 Stats<double> TraceBasedDeliveryFilter::GetDelayStats() const {
649   return delay_cap_helper_->delay_stats();
650 }
651 
GetBitrateStats() const652 Stats<double> TraceBasedDeliveryFilter::GetBitrateStats() const {
653   return kbps_stats_;
654 }
655 
ProceedToNextSlot()656 void TraceBasedDeliveryFilter::ProceedToNextSlot() {
657   if (*next_delivery_it_ <= local_time_us_) {
658     ++next_delivery_it_;
659     if (next_delivery_it_ == delivery_times_us_.end()) {
660       // When the trace wraps we allow two packets to be sent back-to-back.
661       for (int64_t& delivery_time_us : delivery_times_us_) {
662         delivery_time_us += local_time_us_ - current_offset_us_;
663       }
664       current_offset_us_ += local_time_us_ - current_offset_us_;
665       next_delivery_it_ = delivery_times_us_.begin();
666     }
667   }
668   local_time_us_ = *next_delivery_it_;
669   const int kPayloadSize = 1200;
670   rate_counter_->UpdateRates(local_time_us_, kPayloadSize);
671 }
672 
VideoSource(int flow_id,float fps,uint32_t kbps,uint32_t ssrc,int64_t first_frame_offset_ms)673 VideoSource::VideoSource(int flow_id,
674                          float fps,
675                          uint32_t kbps,
676                          uint32_t ssrc,
677                          int64_t first_frame_offset_ms)
678     : kMaxPayloadSizeBytes(1200),
679       kTimestampBase(0xff80ff00ul),
680       frame_period_ms_(1000.0 / fps),
681       bits_per_second_(1000 * kbps),
682       frame_size_bytes_(bits_per_second_ / 8 / fps),
683       random_(0x12345678),
684       flow_id_(flow_id),
685       next_frame_ms_(first_frame_offset_ms),
686       next_frame_rand_ms_(0),
687       now_ms_(0),
688       prototype_header_() {
689   memset(&prototype_header_, 0, sizeof(prototype_header_));
690   prototype_header_.ssrc = ssrc;
691   prototype_header_.sequenceNumber = 0xf000u;
692 }
693 
NextFrameSize()694 uint32_t VideoSource::NextFrameSize() {
695   return frame_size_bytes_;
696 }
697 
GetTimeUntilNextFrameMs() const698 int64_t VideoSource::GetTimeUntilNextFrameMs() const {
699   return next_frame_ms_ + next_frame_rand_ms_ - now_ms_;
700 }
701 
NextPacketSize(uint32_t frame_size,uint32_t remaining_payload)702 uint32_t VideoSource::NextPacketSize(uint32_t frame_size,
703                                      uint32_t remaining_payload) {
704   return std::min(kMaxPayloadSizeBytes, remaining_payload);
705 }
706 
RunFor(int64_t time_ms,Packets * in_out)707 void VideoSource::RunFor(int64_t time_ms, Packets* in_out) {
708   assert(in_out);
709 
710   now_ms_ += time_ms;
711   Packets new_packets;
712 
713   while (now_ms_ >= next_frame_ms_) {
714     const int64_t kRandAmplitude = 2;
715     // A variance picked uniformly from {-1, 0, 1} ms is added to the frame
716     // timestamp.
717     next_frame_rand_ms_ = kRandAmplitude * (random_.Rand<float>() - 0.5);
718 
719     // Ensure frame will not have a negative timestamp.
720     int64_t next_frame_ms =
721         std::max<int64_t>(next_frame_ms_ + next_frame_rand_ms_, 0);
722 
723     prototype_header_.timestamp =
724         kTimestampBase + static_cast<uint32_t>(next_frame_ms * 90.0);
725     prototype_header_.extension.transmissionTimeOffset = 0;
726 
727     // Generate new packets for this frame, all with the same timestamp,
728     // but the payload size is capped, so if the whole frame doesn't fit in
729     // one packet, we will see a number of equally sized packets followed by
730     // one smaller at the tail.
731 
732     int64_t send_time_us = next_frame_ms * 1000.0;
733 
734     uint32_t frame_size = NextFrameSize();
735     uint32_t payload_size = frame_size;
736 
737     while (payload_size > 0) {
738       ++prototype_header_.sequenceNumber;
739       uint32_t size = NextPacketSize(frame_size, payload_size);
740       MediaPacket* new_packet =
741           new MediaPacket(flow_id_, send_time_us, size, prototype_header_);
742       new_packets.push_back(new_packet);
743       new_packet->SetAbsSendTimeMs(next_frame_ms);
744       new_packet->set_sender_timestamp_us(send_time_us);
745       payload_size -= size;
746     }
747 
748     next_frame_ms_ += frame_period_ms_;
749   }
750 
751   in_out->merge(new_packets, DereferencingComparator<Packet>);
752 }
753 
AdaptiveVideoSource(int flow_id,float fps,uint32_t kbps,uint32_t ssrc,int64_t first_frame_offset_ms)754 AdaptiveVideoSource::AdaptiveVideoSource(int flow_id,
755                                          float fps,
756                                          uint32_t kbps,
757                                          uint32_t ssrc,
758                                          int64_t first_frame_offset_ms)
759     : VideoSource(flow_id, fps, kbps, ssrc, first_frame_offset_ms) {
760 }
761 
SetBitrateBps(int bitrate_bps)762 void AdaptiveVideoSource::SetBitrateBps(int bitrate_bps) {
763   bits_per_second_ = std::min(bitrate_bps, 2500000);
764   frame_size_bytes_ = (bits_per_second_ / 8 * frame_period_ms_ + 500) / 1000;
765 }
766 
PeriodicKeyFrameSource(int flow_id,float fps,uint32_t kbps,uint32_t ssrc,int64_t first_frame_offset_ms,int key_frame_interval)767 PeriodicKeyFrameSource::PeriodicKeyFrameSource(int flow_id,
768                                                float fps,
769                                                uint32_t kbps,
770                                                uint32_t ssrc,
771                                                int64_t first_frame_offset_ms,
772                                                int key_frame_interval)
773     : AdaptiveVideoSource(flow_id, fps, kbps, ssrc, first_frame_offset_ms),
774       key_frame_interval_(key_frame_interval),
775       frame_counter_(0),
776       compensation_bytes_(0),
777       compensation_per_frame_(0) {
778 }
779 
NextFrameSize()780 uint32_t PeriodicKeyFrameSource::NextFrameSize() {
781   uint32_t payload_size = frame_size_bytes_;
782   if (frame_counter_ == 0) {
783     payload_size = kMaxPayloadSizeBytes * 12;
784     compensation_bytes_ = 4 * frame_size_bytes_;
785     compensation_per_frame_ = compensation_bytes_ / 30;
786   } else if (key_frame_interval_ > 0 &&
787              (frame_counter_ % key_frame_interval_ == 0)) {
788     payload_size *= 5;
789     compensation_bytes_ = payload_size - frame_size_bytes_;
790     compensation_per_frame_ = compensation_bytes_ / 30;
791   } else if (compensation_bytes_ > 0) {
792     if (compensation_per_frame_ > static_cast<int>(payload_size)) {
793       // Skip this frame.
794       compensation_bytes_ -= payload_size;
795       payload_size = 0;
796     } else {
797       payload_size -= compensation_per_frame_;
798       compensation_bytes_ -= compensation_per_frame_;
799     }
800   }
801   if (compensation_bytes_ < 0)
802     compensation_bytes_ = 0;
803   ++frame_counter_;
804   return payload_size;
805 }
806 
NextPacketSize(uint32_t frame_size,uint32_t remaining_payload)807 uint32_t PeriodicKeyFrameSource::NextPacketSize(uint32_t frame_size,
808                                                 uint32_t remaining_payload) {
809   uint32_t fragments =
810       (frame_size + (kMaxPayloadSizeBytes - 1)) / kMaxPayloadSizeBytes;
811   uint32_t avg_size = (frame_size + fragments - 1) / fragments;
812   return std::min(avg_size, remaining_payload);
813 }
814 }  // namespace bwe
815 }  // namespace testing
816 }  // namespace webrtc
817