blob: cf72f29d243349595fd3ad14a3bd3c59359a1b21 [file] [log] [blame]
stefan@webrtc.org14b02792015-02-16 12:02:20 +00001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/remote_bitrate_estimator/test/bwe.h"
stefan@webrtc.org14b02792015-02-16 12:02:20 +000012
stefan@webrtc.org14b02792015-02-16 12:02:20 +000013#include <limits>
stefan@webrtc.org14b02792015-02-16 12:02:20 +000014
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "modules/remote_bitrate_estimator/test/estimators/bbr.h"
16#include "modules/remote_bitrate_estimator/test/estimators/nada.h"
17#include "modules/remote_bitrate_estimator/test/estimators/remb.h"
18#include "modules/remote_bitrate_estimator/test/estimators/send_side.h"
19#include "modules/remote_bitrate_estimator/test/estimators/tcp.h"
20#include "rtc_base/constructormagic.h"
stefan@webrtc.org14b02792015-02-16 12:02:20 +000021
22namespace webrtc {
23namespace testing {
24namespace bwe {
25
Cesar Magalhaes77cabab2015-06-08 11:29:08 +020026// With the assumption that packet loss is lower than 97%, the max gap
27// between elements in the set is lower than 0x8000, hence we have a
28// total order in the set. For (x,y,z) subset of the LinkedSet,
29// (x<=y and y<=z) ==> x<=z so the set can be sorted.
30const int kSetCapacity = 1000;
31
32BweReceiver::BweReceiver(int flow_id)
Cesar Magalhaes9c261f22015-07-15 16:31:18 +020033 : flow_id_(flow_id),
34 received_packets_(kSetCapacity),
35 rate_counter_(),
36 loss_account_() {
37}
38
39BweReceiver::BweReceiver(int flow_id, int64_t window_size_ms)
40 : flow_id_(flow_id),
41 received_packets_(kSetCapacity),
42 rate_counter_(window_size_ms),
43 loss_account_() {
44}
45
46void BweReceiver::ReceivePacket(int64_t arrival_time_ms,
47 const MediaPacket& media_packet) {
48 if (received_packets_.size() == kSetCapacity) {
49 RelieveSetAndUpdateLoss();
50 }
51
52 received_packets_.Insert(media_packet.sequence_number(),
53 media_packet.send_time_ms(), arrival_time_ms,
54 media_packet.payload_size());
55
56 rate_counter_.UpdateRates(media_packet.send_time_ms() * 1000,
57 static_cast<uint32_t>(media_packet.payload_size()));
Cesar Magalhaes77cabab2015-06-08 11:29:08 +020058}
59
stefan@webrtc.org76636842015-02-17 16:03:45 +000060class NullBweSender : public BweSender {
stefan@webrtc.org14b02792015-02-16 12:02:20 +000061 public:
stefan@webrtc.org76636842015-02-17 16:03:45 +000062 NullBweSender() {}
63 virtual ~NullBweSender() {}
stefan@webrtc.org14b02792015-02-16 12:02:20 +000064
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000065 int GetFeedbackIntervalMs() const override { return 1000; }
66 void GiveFeedback(const FeedbackPacket& feedback) override {}
stefan@webrtc.org4346d922015-03-18 13:40:54 +000067 void OnPacketsSent(const Packets& packets) override {}
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000068 int64_t TimeUntilNextProcess() override {
stefan@webrtc.org14b02792015-02-16 12:02:20 +000069 return std::numeric_limits<int64_t>::max();
70 }
pbosa26ac922016-02-25 04:50:01 -080071 void Process() override {}
stefan@webrtc.org14b02792015-02-16 12:02:20 +000072
73 private:
henrikg3c089d72015-09-16 05:37:44 -070074 RTC_DISALLOW_COPY_AND_ASSIGN(NullBweSender);
stefan@webrtc.org14b02792015-02-16 12:02:20 +000075};
76
stefan@webrtc.org14b02792015-02-16 12:02:20 +000077int64_t GetAbsSendTimeInMs(uint32_t abs_send_time) {
78 const int kInterArrivalShift = 26;
79 const int kAbsSendTimeInterArrivalUpshift = 8;
80 const double kTimestampToMs =
81 1000.0 / static_cast<double>(1 << kInterArrivalShift);
82 uint32_t timestamp = abs_send_time << kAbsSendTimeInterArrivalUpshift;
83 return static_cast<int64_t>(timestamp) * kTimestampToMs;
84}
85
stefan@webrtc.org76636842015-02-17 16:03:45 +000086BweSender* CreateBweSender(BandwidthEstimatorType estimator,
87 int kbps,
88 BitrateObserver* observer,
89 Clock* clock) {
stefan@webrtc.org14b02792015-02-16 12:02:20 +000090 switch (estimator) {
91 case kRembEstimator:
stefan@webrtc.org76636842015-02-17 16:03:45 +000092 return new RembBweSender(kbps, observer, clock);
terelius2d81eb32016-10-25 07:04:37 -070093 case kSendSideEstimator:
94 return new SendSideBweSender(kbps, observer, clock);
stefan@webrtc.org76636842015-02-17 16:03:45 +000095 case kNadaEstimator:
96 return new NadaBweSender(kbps, observer, clock);
gnish6dcdf102017-06-05 06:01:26 -070097 case kBbrEstimator:
gnisha36165c2017-08-20 09:19:58 -070098 return new BbrBweSender(observer, clock);
Stefan Holmer37959372015-04-16 19:55:45 +020099 case kTcpEstimator:
kjellanderbdf30722017-09-08 11:00:21 -0700100 FALLTHROUGH();
stefan@webrtc.org14b02792015-02-16 12:02:20 +0000101 case kNullEstimator:
stefan@webrtc.org76636842015-02-17 16:03:45 +0000102 return new NullBweSender();
stefan@webrtc.org14b02792015-02-16 12:02:20 +0000103 }
104 assert(false);
105 return NULL;
106}
107
108BweReceiver* CreateBweReceiver(BandwidthEstimatorType type,
109 int flow_id,
110 bool plot) {
111 switch (type) {
112 case kRembEstimator:
113 return new RembReceiver(flow_id, plot);
terelius2d81eb32016-10-25 07:04:37 -0700114 case kSendSideEstimator:
stefan@webrtc.org14b02792015-02-16 12:02:20 +0000115 return new SendSideBweReceiver(flow_id);
stefan@webrtc.org76636842015-02-17 16:03:45 +0000116 case kNadaEstimator:
117 return new NadaBweReceiver(flow_id);
gnish6dcdf102017-06-05 06:01:26 -0700118 case kBbrEstimator:
119 return new BbrBweReceiver(flow_id);
Stefan Holmer37959372015-04-16 19:55:45 +0200120 case kTcpEstimator:
121 return new TcpBweReceiver(flow_id);
stefan@webrtc.org14b02792015-02-16 12:02:20 +0000122 case kNullEstimator:
123 return new BweReceiver(flow_id);
124 }
125 assert(false);
126 return NULL;
127}
Cesar Magalhaes77cabab2015-06-08 11:29:08 +0200128
Cesar Magalhaes9c261f22015-07-15 16:31:18 +0200129// Take into account all LinkedSet content.
130void BweReceiver::UpdateLoss() {
131 loss_account_.Add(LinkedSetPacketLossRatio());
132}
Cesar Magalhaes77cabab2015-06-08 11:29:08 +0200133
Cesar Magalhaes9c261f22015-07-15 16:31:18 +0200134// Preserve 10% latest packets and update packet loss based on the oldest
135// 90%, that will be removed.
136void BweReceiver::RelieveSetAndUpdateLoss() {
137 // Compute Loss for the whole LinkedSet and updates loss_account_.
138 UpdateLoss();
139
140 size_t num_preserved_elements = received_packets_.size() / 10;
141 PacketNodeIt it = received_packets_.begin();
142 std::advance(it, num_preserved_elements);
143
144 while (it != received_packets_.end()) {
145 received_packets_.Erase(it++);
Cesar Magalhaes77cabab2015-06-08 11:29:08 +0200146 }
Cesar Magalhaes9c261f22015-07-15 16:31:18 +0200147
148 // Compute Loss for the preserved elements
149 loss_account_.Subtract(LinkedSetPacketLossRatio());
150}
151
152float BweReceiver::GlobalReceiverPacketLossRatio() {
153 UpdateLoss();
154 return loss_account_.LossRatio();
155}
156
157// This function considers at most kSetCapacity = 1000 packets.
158LossAccount BweReceiver::LinkedSetPacketLossRatio() {
159 if (received_packets_.empty()) {
160 return LossAccount();
161 }
162
163 uint16_t oldest_seq_num = received_packets_.OldestSeqNumber();
164 uint16_t newest_seq_num = received_packets_.NewestSeqNumber();
165
166 size_t set_total_packets =
167 static_cast<uint16_t>(newest_seq_num - oldest_seq_num + 1);
168
169 size_t set_received_packets = received_packets_.size();
170 size_t set_lost_packets = set_total_packets - set_received_packets;
171
172 return LossAccount(set_total_packets, set_lost_packets);
173}
174
175uint32_t BweReceiver::RecentKbps() const {
176 return (rate_counter_.bits_per_second() + 500) / 1000;
Cesar Magalhaes77cabab2015-06-08 11:29:08 +0200177}
178
179// Go through a fixed time window of most recent packets received and
180// counts packets missing to obtain the packet loss ratio. If an unordered
181// packet falls out of the timewindow it will be counted as missing.
182// E.g.: for a timewindow covering 5 packets of the following arrival sequence
183// {10 7 9 5 6} 8 3 2 4 1, the output will be 1/6 (#8 is considered as missing).
184float BweReceiver::RecentPacketLossRatio() {
185 if (received_packets_.empty()) {
186 return 0.0f;
187 }
188 int number_packets_received = 0;
189
190 PacketNodeIt node_it = received_packets_.begin(); // Latest.
191
192 // Lowest timestamp limit, oldest one that should be checked.
193 int64_t time_limit_ms = (*node_it)->arrival_time_ms - kPacketLossTimeWindowMs;
194 // Oldest and newest values found within the given time window.
Cesar Magalhaes9c261f22015-07-15 16:31:18 +0200195 uint16_t oldest_seq_num = (*node_it)->sequence_number;
196 uint16_t newest_seq_num = oldest_seq_num;
Cesar Magalhaes77cabab2015-06-08 11:29:08 +0200197
198 while (node_it != received_packets_.end()) {
199 if ((*node_it)->arrival_time_ms < time_limit_ms) {
200 break;
201 }
Cesar Magalhaes9c261f22015-07-15 16:31:18 +0200202 uint16_t seq_num = (*node_it)->sequence_number;
203 if (IsNewerSequenceNumber(seq_num, newest_seq_num)) {
204 newest_seq_num = seq_num;
Cesar Magalhaes77cabab2015-06-08 11:29:08 +0200205 }
Cesar Magalhaes9c261f22015-07-15 16:31:18 +0200206 if (IsNewerSequenceNumber(oldest_seq_num, seq_num)) {
207 oldest_seq_num = seq_num;
Cesar Magalhaes77cabab2015-06-08 11:29:08 +0200208 }
209 ++node_it;
210 ++number_packets_received;
211 }
212 // Interval width between oldest and newest sequence number.
Cesar Magalhaes9c261f22015-07-15 16:31:18 +0200213 // There was an overflow if newest_seq_num < oldest_seq_num.
214 int gap = static_cast<uint16_t>(newest_seq_num - oldest_seq_num + 1);
Cesar Magalhaes77cabab2015-06-08 11:29:08 +0200215
216 return static_cast<float>(gap - number_packets_received) / gap;
217}
218
stefan870eee42015-07-14 03:53:57 -0700219LinkedSet::~LinkedSet() {
220 while (!empty())
221 RemoveTail();
222}
223
Cesar Magalhaes77cabab2015-06-08 11:29:08 +0200224void LinkedSet::Insert(uint16_t sequence_number,
225 int64_t send_time_ms,
226 int64_t arrival_time_ms,
227 size_t payload_size) {
Cesar Magalhaes9c261f22015-07-15 16:31:18 +0200228 auto it = map_.find(sequence_number);
Cesar Magalhaes77cabab2015-06-08 11:29:08 +0200229 if (it != map_.end()) {
230 PacketNodeIt node_it = it->second;
231 PacketIdentifierNode* node = *node_it;
232 node->arrival_time_ms = arrival_time_ms;
233 if (node_it != list_.begin()) {
234 list_.erase(node_it);
235 list_.push_front(node);
236 map_[sequence_number] = list_.begin();
237 }
238 } else {
239 if (size() == capacity_) {
240 RemoveTail();
241 }
242 UpdateHead(new PacketIdentifierNode(sequence_number, send_time_ms,
243 arrival_time_ms, payload_size));
244 }
245}
Cesar Magalhaes9c261f22015-07-15 16:31:18 +0200246
247void LinkedSet::Insert(PacketIdentifierNode packet_identifier) {
248 Insert(packet_identifier.sequence_number, packet_identifier.send_time_ms,
249 packet_identifier.arrival_time_ms, packet_identifier.payload_size);
250}
251
Cesar Magalhaes77cabab2015-06-08 11:29:08 +0200252void LinkedSet::RemoveTail() {
253 map_.erase(list_.back()->sequence_number);
stefan870eee42015-07-14 03:53:57 -0700254 delete list_.back();
Cesar Magalhaes77cabab2015-06-08 11:29:08 +0200255 list_.pop_back();
256}
257void LinkedSet::UpdateHead(PacketIdentifierNode* new_head) {
258 list_.push_front(new_head);
259 map_[new_head->sequence_number] = list_.begin();
260}
261
Cesar Magalhaes9c261f22015-07-15 16:31:18 +0200262void LinkedSet::Erase(PacketNodeIt node_it) {
263 map_.erase((*node_it)->sequence_number);
264 delete (*node_it);
265 list_.erase(node_it);
266}
267
268void LossAccount::Add(LossAccount rhs) {
269 num_total += rhs.num_total;
270 num_lost += rhs.num_lost;
271}
272void LossAccount::Subtract(LossAccount rhs) {
273 num_total -= rhs.num_total;
274 num_lost -= rhs.num_lost;
275}
276
277float LossAccount::LossRatio() {
278 if (num_total == 0)
279 return 0.0f;
280 return static_cast<float>(num_lost) / num_total;
281}
282
stefan@webrtc.org14b02792015-02-16 12:02:20 +0000283} // namespace bwe
284} // namespace testing
285} // namespace webrtc