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
17namespace webrtc {
18namespace testing {
19namespace bwe {
20
21class DelayCapHelper {
22 public:
23  // Max delay = 0 stands for +infinite.
24  DelayCapHelper() : max_delay_us_(0), delay_stats_() {}
25
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
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
39  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
50const 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
55const 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
65void 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
83uint32_t RateCounter::bits_per_second() const {
84  return (8 * recently_received_bytes_) / BitrateWindowS();
85}
86
87uint32_t RateCounter::packets_per_second() const {
88  return recently_received_packets_ / BitrateWindowS();
89}
90
91double RateCounter::BitrateWindowS() const {
92  return static_cast<double>(window_size_us_) / (1000 * 1000);
93}
94
95Packet::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
104Packet::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
113Packet::~Packet() {
114}
115
116bool Packet::operator<(const Packet& rhs) const {
117  return send_time_us_ < rhs.send_time_us_;
118}
119
120void 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
125MediaPacket::MediaPacket() {
126  memset(&header_, 0, sizeof(header_));
127}
128
129MediaPacket::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
138MediaPacket::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
145MediaPacket::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
151void 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
157RembFeedback::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
167SendSideBweFeedback::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
176bool 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
187PacketProcessor::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
196PacketProcessor::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
205PacketProcessor::~PacketProcessor() {
206  if (listener_) {
207    listener_->RemovePacketProcessor(this);
208  }
209}
210
211uint32_t PacketProcessor::packets_per_second() const {
212  return rate_counter_.packets_per_second();
213}
214
215uint32_t PacketProcessor::bits_per_second() const {
216  return rate_counter_.bits_per_second();
217}
218
219RateCounterFilter::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
233RateCounterFilter::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
252RateCounterFilter::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
261RateCounterFilter::~RateCounterFilter() {
262  LogStats();
263}
264
265
266void RateCounterFilter::LogStats() {
267  BWE_TEST_LOGGING_CONTEXT("RateCounterFilter");
268  packets_per_second_stats_.Log("pps");
269  kbps_stats_.Log("kbps");
270}
271
272Stats<double> RateCounterFilter::GetBitrateStats() const {
273  return kbps_stats_;
274}
275
276void 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
292void 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
302LossFilter::LossFilter(PacketProcessorListener* listener, int flow_id)
303    : PacketProcessor(listener, flow_id, kRegular),
304      random_(0x12345678),
305      loss_fraction_(0.0f) {
306}
307
308LossFilter::LossFilter(PacketProcessorListener* listener,
309                       const FlowIds& flow_ids)
310    : PacketProcessor(listener, flow_ids, kRegular),
311      random_(0x12345678),
312      loss_fraction_(0.0f) {
313}
314
315void 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
323void 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
335const int64_t kDefaultOneWayDelayUs = 0;
336
337DelayFilter::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
343DelayFilter::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
350void 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
357void 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
366JitterFilter::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
374JitterFilter::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
383const int kN = 3;  // Truncated N sigma gaussian.
384
385void 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
393namespace {
394inline 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
402void 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.
423int64_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
435ReorderFilter::ReorderFilter(PacketProcessorListener* listener, int flow_id)
436    : PacketProcessor(listener, flow_id, kRegular),
437      random_(0x27452389),
438      reorder_fraction_(0.0f) {
439}
440
441ReorderFilter::ReorderFilter(PacketProcessorListener* listener,
442                             const FlowIds& flow_ids)
443    : PacketProcessor(listener, flow_ids, kRegular),
444      random_(0x27452389),
445      reorder_fraction_(0.0f) {
446}
447
448void 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
456void 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
474const uint32_t kDefaultKbps = 1200;
475
476ChokeFilter::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
483ChokeFilter::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
491ChokeFilter::~ChokeFilter() {}
492
493void 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
499uint32_t ChokeFilter::capacity_kbps() {
500  return capacity_kbps_;
501}
502
503void 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
526void ChokeFilter::set_max_delay_ms(int64_t max_delay_ms) {
527  delay_cap_helper_->set_max_delay_ms(max_delay_ms);
528}
529
530Stats<double> ChokeFilter::GetDelayStats() const {
531  return delay_cap_helper_->delay_stats();
532}
533
534TraceBasedDeliveryFilter::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
549TraceBasedDeliveryFilter::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
564TraceBasedDeliveryFilter::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
580TraceBasedDeliveryFilter::~TraceBasedDeliveryFilter() {
581}
582
583bool 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
611void 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
619void 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
644void TraceBasedDeliveryFilter::set_max_delay_ms(int64_t max_delay_ms) {
645  delay_cap_helper_->set_max_delay_ms(max_delay_ms);
646}
647
648Stats<double> TraceBasedDeliveryFilter::GetDelayStats() const {
649  return delay_cap_helper_->delay_stats();
650}
651
652Stats<double> TraceBasedDeliveryFilter::GetBitrateStats() const {
653  return kbps_stats_;
654}
655
656void 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
673VideoSource::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
694uint32_t VideoSource::NextFrameSize() {
695  return frame_size_bytes_;
696}
697
698int64_t VideoSource::GetTimeUntilNextFrameMs() const {
699  return next_frame_ms_ + next_frame_rand_ms_ - now_ms_;
700}
701
702uint32_t VideoSource::NextPacketSize(uint32_t frame_size,
703                                     uint32_t remaining_payload) {
704  return std::min(kMaxPayloadSizeBytes, remaining_payload);
705}
706
707void 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
754AdaptiveVideoSource::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
762void 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
767PeriodicKeyFrameSource::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
780uint32_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
807uint32_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