1/*
2 *  Copyright (c) 2015 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#ifndef WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BWE_H_
12#define WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BWE_H_
13
14#include <list>
15#include <map>
16#include <sstream>
17#include <string>
18
19#include "webrtc/test/testsupport/gtest_prod_util.h"
20#include "webrtc/modules/remote_bitrate_estimator/test/packet.h"
21#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
22#include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h"
23
24namespace webrtc {
25namespace testing {
26namespace bwe {
27
28// Overload map comparator.
29class SequenceNumberOlderThan {
30 public:
31  bool operator()(uint16_t seq_num_1, uint16_t seq_num_2) const {
32    return IsNewerSequenceNumber(seq_num_2, seq_num_1);
33  }
34};
35
36// Holds information for computing global packet loss.
37struct LossAccount {
38  LossAccount() : num_total(0), num_lost(0) {}
39  LossAccount(size_t num_total, size_t num_lost)
40      : num_total(num_total), num_lost(num_lost) {}
41  void Add(LossAccount rhs);
42  void Subtract(LossAccount rhs);
43  float LossRatio();
44  size_t num_total;
45  size_t num_lost;
46};
47
48// Holds only essential information about packets to be saved for
49// further use, e.g. for calculating packet loss and receiving rate.
50struct PacketIdentifierNode {
51  PacketIdentifierNode(uint16_t sequence_number,
52                       int64_t send_time_ms,
53                       int64_t arrival_time_ms,
54                       size_t payload_size)
55      : sequence_number(sequence_number),
56        send_time_ms(send_time_ms),
57        arrival_time_ms(arrival_time_ms),
58        payload_size(payload_size) {}
59
60  uint16_t sequence_number;
61  int64_t send_time_ms;
62  int64_t arrival_time_ms;
63  size_t payload_size;
64};
65
66typedef std::list<PacketIdentifierNode*>::iterator PacketNodeIt;
67
68// FIFO implementation for a limited capacity set.
69// Used for keeping the latest arrived packets while avoiding duplicates.
70// Allows efficient insertion, deletion and search.
71class LinkedSet {
72 public:
73  explicit LinkedSet(int capacity) : capacity_(capacity) {}
74  ~LinkedSet();
75
76  // If the arriving packet (identified by its sequence number) is already
77  // in the LinkedSet, move its Node to the head of the list. Else, create
78  // a PacketIdentifierNode n_ and then UpdateHead(n_), calling RemoveTail()
79  // if the LinkedSet reached its maximum capacity.
80  void Insert(uint16_t sequence_number,
81              int64_t send_time_ms,
82              int64_t arrival_time_ms,
83              size_t payload_size);
84
85  void Insert(PacketIdentifierNode packet_identifier);
86
87  PacketNodeIt begin() { return list_.begin(); }
88  PacketNodeIt end() { return list_.end(); }
89
90  bool empty() const { return list_.empty(); }
91  size_t size() const { return list_.size(); }
92  size_t capacity() const { return capacity_; }
93
94  uint16_t OldestSeqNumber() const { return empty() ? 0 : map_.begin()->first; }
95  uint16_t NewestSeqNumber() const {
96    return empty() ? 0 : map_.rbegin()->first;
97  }
98
99  void Erase(PacketNodeIt node_it);
100
101 private:
102  // Pop oldest element from the back of the list and remove it from the map.
103  void RemoveTail();
104  // Add new element to the front of the list and insert it in the map.
105  void UpdateHead(PacketIdentifierNode* new_head);
106  size_t capacity_;
107  std::map<uint16_t, PacketNodeIt, SequenceNumberOlderThan> map_;
108  std::list<PacketIdentifierNode*> list_;
109};
110
111const int kMinBitrateKbps = 50;
112const int kMaxBitrateKbps = 2500;
113
114class BweSender : public Module {
115 public:
116  BweSender() {}
117  explicit BweSender(int bitrate_kbps) : bitrate_kbps_(bitrate_kbps) {}
118  virtual ~BweSender() {}
119
120  virtual int GetFeedbackIntervalMs() const = 0;
121  virtual void GiveFeedback(const FeedbackPacket& feedback) = 0;
122  virtual void OnPacketsSent(const Packets& packets) = 0;
123
124 protected:
125  int bitrate_kbps_;
126
127 private:
128  RTC_DISALLOW_COPY_AND_ASSIGN(BweSender);
129};
130
131class BweReceiver {
132 public:
133  explicit BweReceiver(int flow_id);
134  BweReceiver(int flow_id, int64_t window_size_ms);
135
136  virtual ~BweReceiver() {}
137
138  virtual void ReceivePacket(int64_t arrival_time_ms,
139                             const MediaPacket& media_packet);
140  virtual FeedbackPacket* GetFeedback(int64_t now_ms) { return NULL; }
141
142  size_t GetSetCapacity() { return received_packets_.capacity(); }
143  double BitrateWindowS() const { return rate_counter_.BitrateWindowS(); }
144  uint32_t RecentKbps() const;  // Receiving Rate.
145
146  // Computes packet loss during an entire simulation, up to 4 billion packets.
147  float GlobalReceiverPacketLossRatio();  // Plot histogram.
148  float RecentPacketLossRatio();          // Plot dynamics.
149
150  static const int64_t kPacketLossTimeWindowMs = 500;
151  static const int64_t kReceivingRateTimeWindowMs = 1000;
152
153 protected:
154  int flow_id_;
155  // Deals with packets sent more than once.
156  LinkedSet received_packets_;
157  // Used for calculating recent receiving rate.
158  RateCounter rate_counter_;
159
160 private:
161  FRIEND_TEST_ALL_PREFIXES(BweReceiverTest, RecentKbps);
162  FRIEND_TEST_ALL_PREFIXES(BweReceiverTest, Loss);
163
164  void UpdateLoss();
165  void RelieveSetAndUpdateLoss();
166  // Packet loss for packets stored in the LinkedSet, up to 1000 packets.
167  // Used to update global loss account whenever the set is filled and cleared.
168  LossAccount LinkedSetPacketLossRatio();
169
170  // Used for calculating global packet loss ratio.
171  LossAccount loss_account_;
172};
173
174enum BandwidthEstimatorType {
175  kNullEstimator,
176  kNadaEstimator,
177  kRembEstimator,
178  kFullSendSideEstimator,
179  kTcpEstimator
180};
181
182const std::string bwe_names[] = {"Null", "NADA", "REMB", "GCC", "TCP"};
183
184int64_t GetAbsSendTimeInMs(uint32_t abs_send_time);
185
186BweSender* CreateBweSender(BandwidthEstimatorType estimator,
187                           int kbps,
188                           BitrateObserver* observer,
189                           Clock* clock);
190
191BweReceiver* CreateBweReceiver(BandwidthEstimatorType type,
192                               int flow_id,
193                               bool plot);
194}  // namespace bwe
195}  // namespace testing
196}  // namespace webrtc
197#endif  // WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BWE_H_
198