blob: a06754e5a6ce54c6b115da62267d7355df9e4034 [file] [log] [blame]
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001/*
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
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "modules/rtp_rtcp/include/receive_statistics.h"
12
kwiberg84be5112016-04-27 01:19:58 -070013#include <memory>
Danil Chapovalovd1996b72018-01-16 11:07:18 +010014#include <vector>
kwiberg84be5112016-04-27 01:19:58 -070015
Niels Möller1f3206c2018-09-14 08:26:32 +020016#include "modules/rtp_rtcp/source/rtp_packet_received.h"
17#include "rtc_base/random.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "system_wrappers/include/clock.h"
19#include "test/gmock.h"
20#include "test/gtest.h"
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000021
22namespace webrtc {
Danil Chapovalovd1996b72018-01-16 11:07:18 +010023namespace {
24
25using ::testing::SizeIs;
26using ::testing::UnorderedElementsAre;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000027
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000028const size_t kPacketSize1 = 100;
29const size_t kPacketSize2 = 300;
Danil Chapovalovd1996b72018-01-16 11:07:18 +010030const uint32_t kSsrc1 = 101;
31const uint32_t kSsrc2 = 202;
32const uint32_t kSsrc3 = 203;
33const uint32_t kSsrc4 = 304;
34
Niels Möller1f3206c2018-09-14 08:26:32 +020035RtpPacketReceived CreateRtpPacket(uint32_t ssrc,
36 size_t header_size,
37 size_t payload_size,
38 size_t padding_size) {
39 RtpPacketReceived packet;
40 packet.SetSsrc(ssrc);
41 packet.SetSequenceNumber(100);
42 packet.set_payload_type_frequency(90000);
43 RTC_CHECK_GE(header_size, 12);
44 RTC_CHECK_EQ(header_size % 4, 0);
45 if (header_size > 12) {
46 // Insert csrcs to increase header size.
47 const int num_csrcs = (header_size - 12) / 4;
48 std::vector<uint32_t> csrcs(num_csrcs);
49 packet.SetCsrcs(csrcs);
50 }
51 packet.SetPayloadSize(payload_size);
Danil Chapovalovf7fcaf02018-10-10 14:56:01 +020052 packet.SetPadding(padding_size);
Niels Möller1f3206c2018-09-14 08:26:32 +020053 return packet;
54}
55
56RtpPacketReceived CreateRtpPacket(uint32_t ssrc, size_t packet_size) {
57 return CreateRtpPacket(ssrc, 12, packet_size - 12, 0);
58}
59
60void IncrementSequenceNumber(RtpPacketReceived* packet, uint16_t incr) {
61 packet->SetSequenceNumber(packet->SequenceNumber() + incr);
62}
63
64void IncrementSequenceNumber(RtpPacketReceived* packet) {
65 IncrementSequenceNumber(packet, 1);
66}
67
68void IncrementTimestamp(RtpPacketReceived* packet, uint32_t incr) {
69 packet->SetTimestamp(packet->Timestamp() + incr);
Danil Chapovalovd1996b72018-01-16 11:07:18 +010070}
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000071
72class ReceiveStatisticsTest : public ::testing::Test {
73 public:
Yves Gerey665174f2018-06-19 15:03:05 +020074 ReceiveStatisticsTest()
Danil Chapovalov8ce0d2b2018-11-23 11:03:25 +010075 : clock_(0),
76 receive_statistics_(
77 ReceiveStatistics::Create(&clock_, nullptr, nullptr)) {
Niels Möller1f3206c2018-09-14 08:26:32 +020078 packet1_ = CreateRtpPacket(kSsrc1, kPacketSize1);
79 packet2_ = CreateRtpPacket(kSsrc2, kPacketSize2);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000080 }
81
82 protected:
83 SimulatedClock clock_;
kwiberg84be5112016-04-27 01:19:58 -070084 std::unique_ptr<ReceiveStatistics> receive_statistics_;
Niels Möller1f3206c2018-09-14 08:26:32 +020085 RtpPacketReceived packet1_;
86 RtpPacketReceived packet2_;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000087};
88
89TEST_F(ReceiveStatisticsTest, TwoIncomingSsrcs) {
Niels Möller1f3206c2018-09-14 08:26:32 +020090 receive_statistics_->OnRtpPacket(packet1_);
91 IncrementSequenceNumber(&packet1_);
92 receive_statistics_->OnRtpPacket(packet2_);
93 IncrementSequenceNumber(&packet2_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000094 clock_.AdvanceTimeMilliseconds(100);
Niels Möller1f3206c2018-09-14 08:26:32 +020095 receive_statistics_->OnRtpPacket(packet1_);
96 IncrementSequenceNumber(&packet1_);
97 receive_statistics_->OnRtpPacket(packet2_);
98 IncrementSequenceNumber(&packet2_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000099
100 StreamStatistician* statistician =
101 receive_statistics_->GetStatistician(kSsrc1);
102 ASSERT_TRUE(statistician != NULL);
103 EXPECT_GT(statistician->BitrateReceived(), 0u);
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000104 size_t bytes_received = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000105 uint32_t packets_received = 0;
106 statistician->GetDataCounters(&bytes_received, &packets_received);
107 EXPECT_EQ(200u, bytes_received);
108 EXPECT_EQ(2u, packets_received);
109
Yves Gerey665174f2018-06-19 15:03:05 +0200110 statistician = receive_statistics_->GetStatistician(kSsrc2);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000111 ASSERT_TRUE(statistician != NULL);
112 EXPECT_GT(statistician->BitrateReceived(), 0u);
113 statistician->GetDataCounters(&bytes_received, &packets_received);
114 EXPECT_EQ(600u, bytes_received);
115 EXPECT_EQ(2u, packets_received);
116
Danil Chapovalovc5267d22017-09-18 13:57:19 +0200117 EXPECT_EQ(2u, receive_statistics_->RtcpReportBlocks(3).size());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000118 // Add more incoming packets and verify that they are registered in both
119 // access methods.
Niels Möller1f3206c2018-09-14 08:26:32 +0200120 receive_statistics_->OnRtpPacket(packet1_);
121 IncrementSequenceNumber(&packet1_);
122 receive_statistics_->OnRtpPacket(packet2_);
123 IncrementSequenceNumber(&packet2_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000124
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000125 receive_statistics_->GetStatistician(kSsrc1)->GetDataCounters(
126 &bytes_received, &packets_received);
127 EXPECT_EQ(300u, bytes_received);
128 EXPECT_EQ(3u, packets_received);
129 receive_statistics_->GetStatistician(kSsrc2)->GetDataCounters(
130 &bytes_received, &packets_received);
131 EXPECT_EQ(900u, bytes_received);
132 EXPECT_EQ(3u, packets_received);
133}
134
Danil Chapovalovd1996b72018-01-16 11:07:18 +0100135TEST_F(ReceiveStatisticsTest,
136 RtcpReportBlocksReturnsMaxBlocksWhenThereAreMoreStatisticians) {
Niels Möller1f3206c2018-09-14 08:26:32 +0200137 RtpPacketReceived packet1 = CreateRtpPacket(kSsrc1, kPacketSize1);
138 RtpPacketReceived packet2 = CreateRtpPacket(kSsrc2, kPacketSize1);
139 RtpPacketReceived packet3 = CreateRtpPacket(kSsrc3, kPacketSize1);
140 receive_statistics_->OnRtpPacket(packet1);
141 receive_statistics_->OnRtpPacket(packet2);
142 receive_statistics_->OnRtpPacket(packet3);
Danil Chapovalovd1996b72018-01-16 11:07:18 +0100143
144 EXPECT_THAT(receive_statistics_->RtcpReportBlocks(2), SizeIs(2));
145 EXPECT_THAT(receive_statistics_->RtcpReportBlocks(2), SizeIs(2));
146 EXPECT_THAT(receive_statistics_->RtcpReportBlocks(2), SizeIs(2));
147}
148
149TEST_F(ReceiveStatisticsTest,
150 RtcpReportBlocksReturnsAllObservedSsrcsWithMultipleCalls) {
Niels Möller1f3206c2018-09-14 08:26:32 +0200151 RtpPacketReceived packet1 = CreateRtpPacket(kSsrc1, kPacketSize1);
152 RtpPacketReceived packet2 = CreateRtpPacket(kSsrc2, kPacketSize1);
153 RtpPacketReceived packet3 = CreateRtpPacket(kSsrc3, kPacketSize1);
154 RtpPacketReceived packet4 = CreateRtpPacket(kSsrc4, kPacketSize1);
155 receive_statistics_->OnRtpPacket(packet1);
156 receive_statistics_->OnRtpPacket(packet2);
157 receive_statistics_->OnRtpPacket(packet3);
158 receive_statistics_->OnRtpPacket(packet4);
Danil Chapovalovd1996b72018-01-16 11:07:18 +0100159
160 std::vector<uint32_t> observed_ssrcs;
161 std::vector<rtcp::ReportBlock> report_blocks =
162 receive_statistics_->RtcpReportBlocks(2);
163 ASSERT_THAT(report_blocks, SizeIs(2));
164 observed_ssrcs.push_back(report_blocks[0].source_ssrc());
165 observed_ssrcs.push_back(report_blocks[1].source_ssrc());
166
167 report_blocks = receive_statistics_->RtcpReportBlocks(2);
168 ASSERT_THAT(report_blocks, SizeIs(2));
169 observed_ssrcs.push_back(report_blocks[0].source_ssrc());
170 observed_ssrcs.push_back(report_blocks[1].source_ssrc());
171
172 EXPECT_THAT(observed_ssrcs,
173 UnorderedElementsAre(kSsrc1, kSsrc2, kSsrc3, kSsrc4));
174}
175
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000176TEST_F(ReceiveStatisticsTest, ActiveStatisticians) {
Niels Möller1f3206c2018-09-14 08:26:32 +0200177 receive_statistics_->OnRtpPacket(packet1_);
178 IncrementSequenceNumber(&packet1_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000179 clock_.AdvanceTimeMilliseconds(1000);
Niels Möller1f3206c2018-09-14 08:26:32 +0200180 receive_statistics_->OnRtpPacket(packet2_);
181 IncrementSequenceNumber(&packet2_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000182 // Nothing should time out since only 1000 ms has passed since the first
183 // packet came in.
Danil Chapovalovc5267d22017-09-18 13:57:19 +0200184 EXPECT_EQ(2u, receive_statistics_->RtcpReportBlocks(3).size());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000185
186 clock_.AdvanceTimeMilliseconds(7000);
187 // kSsrc1 should have timed out.
Danil Chapovalovc5267d22017-09-18 13:57:19 +0200188 EXPECT_EQ(1u, receive_statistics_->RtcpReportBlocks(3).size());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000189
190 clock_.AdvanceTimeMilliseconds(1000);
191 // kSsrc2 should have timed out.
Danil Chapovalovc5267d22017-09-18 13:57:19 +0200192 EXPECT_EQ(0u, receive_statistics_->RtcpReportBlocks(3).size());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000193
Niels Möller1f3206c2018-09-14 08:26:32 +0200194 receive_statistics_->OnRtpPacket(packet1_);
195 IncrementSequenceNumber(&packet1_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000196 // kSsrc1 should be active again and the data counters should have survived.
Danil Chapovalovc5267d22017-09-18 13:57:19 +0200197 EXPECT_EQ(1u, receive_statistics_->RtcpReportBlocks(3).size());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000198 StreamStatistician* statistician =
199 receive_statistics_->GetStatistician(kSsrc1);
200 ASSERT_TRUE(statistician != NULL);
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000201 size_t bytes_received = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000202 uint32_t packets_received = 0;
203 statistician->GetDataCounters(&bytes_received, &packets_received);
204 EXPECT_EQ(200u, bytes_received);
205 EXPECT_EQ(2u, packets_received);
206}
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000207
Niels Möller5304a322018-08-27 13:27:05 +0200208TEST_F(ReceiveStatisticsTest,
209 DoesntCreateRtcpReportBlockUntilFirstReceivedPacketForSsrc) {
210 // Creates a statistician object for the ssrc.
211 receive_statistics_->EnableRetransmitDetection(kSsrc1, true);
212 EXPECT_TRUE(receive_statistics_->GetStatistician(kSsrc1) != nullptr);
213 EXPECT_EQ(0u, receive_statistics_->RtcpReportBlocks(3).size());
214 // Receive first packet
Niels Möller1f3206c2018-09-14 08:26:32 +0200215 receive_statistics_->OnRtpPacket(packet1_);
Niels Möller5304a322018-08-27 13:27:05 +0200216 EXPECT_EQ(1u, receive_statistics_->RtcpReportBlocks(3).size());
217}
218
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000219TEST_F(ReceiveStatisticsTest, GetReceiveStreamDataCounters) {
Niels Möller1f3206c2018-09-14 08:26:32 +0200220 receive_statistics_->OnRtpPacket(packet1_);
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000221 StreamStatistician* statistician =
222 receive_statistics_->GetStatistician(kSsrc1);
223 ASSERT_TRUE(statistician != NULL);
224
225 StreamDataCounters counters;
226 statistician->GetReceiveStreamDataCounters(&counters);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000227 EXPECT_GT(counters.first_packet_time_ms, -1);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000228 EXPECT_EQ(1u, counters.transmitted.packets);
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000229
Niels Möller1f3206c2018-09-14 08:26:32 +0200230 receive_statistics_->OnRtpPacket(packet1_);
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000231 statistician->GetReceiveStreamDataCounters(&counters);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000232 EXPECT_GT(counters.first_packet_time_ms, -1);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000233 EXPECT_EQ(2u, counters.transmitted.packets);
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000234}
235
Qingsi Wang2370b082018-08-21 14:24:26 -0700236TEST_F(ReceiveStatisticsTest, RtcpCallbacks) {
237 class TestCallback : public RtcpStatisticsCallback {
238 public:
239 TestCallback()
240 : RtcpStatisticsCallback(), num_calls_(0), ssrc_(0), stats_() {}
241 ~TestCallback() override {}
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000242
Qingsi Wang2370b082018-08-21 14:24:26 -0700243 void StatisticsUpdated(const RtcpStatistics& statistics,
244 uint32_t ssrc) override {
245 ssrc_ = ssrc;
246 stats_ = statistics;
247 ++num_calls_;
248 }
249
Qingsi Wang2370b082018-08-21 14:24:26 -0700250 uint32_t num_calls_;
251 uint32_t ssrc_;
252 RtcpStatistics stats_;
253 } callback;
254
Danil Chapovalov8ce0d2b2018-11-23 11:03:25 +0100255 receive_statistics_ = ReceiveStatistics::Create(&clock_, &callback, nullptr);
Niels Möller5304a322018-08-27 13:27:05 +0200256 receive_statistics_->EnableRetransmitDetection(kSsrc1, true);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000257
258 // Add some arbitrary data, with loss and jitter.
Niels Möller1f3206c2018-09-14 08:26:32 +0200259 packet1_.SetSequenceNumber(1);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000260 clock_.AdvanceTimeMilliseconds(7);
Niels Möller1f3206c2018-09-14 08:26:32 +0200261 IncrementTimestamp(&packet1_, 3);
262 receive_statistics_->OnRtpPacket(packet1_);
263 IncrementSequenceNumber(&packet1_, 2);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000264 clock_.AdvanceTimeMilliseconds(9);
Niels Möller1f3206c2018-09-14 08:26:32 +0200265 IncrementTimestamp(&packet1_, 9);
266 receive_statistics_->OnRtpPacket(packet1_);
267 IncrementSequenceNumber(&packet1_, -1);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000268 clock_.AdvanceTimeMilliseconds(13);
Niels Möller1f3206c2018-09-14 08:26:32 +0200269 IncrementTimestamp(&packet1_, 47);
270 receive_statistics_->OnRtpPacket(packet1_);
271 IncrementSequenceNumber(&packet1_, 3);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000272 clock_.AdvanceTimeMilliseconds(11);
Niels Möller1f3206c2018-09-14 08:26:32 +0200273 IncrementTimestamp(&packet1_, 17);
274 receive_statistics_->OnRtpPacket(packet1_);
275 IncrementSequenceNumber(&packet1_);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000276
Qingsi Wang2370b082018-08-21 14:24:26 -0700277 EXPECT_EQ(0u, callback.num_calls_);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000278
Qingsi Wang2370b082018-08-21 14:24:26 -0700279 // Call GetStatistics, simulating a timed rtcp sender thread.
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000280 RtcpStatistics statistics;
Qingsi Wang2370b082018-08-21 14:24:26 -0700281 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
282 true);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000283
Qingsi Wang2370b082018-08-21 14:24:26 -0700284 EXPECT_EQ(1u, callback.num_calls_);
285 EXPECT_EQ(callback.ssrc_, kSsrc1);
286 EXPECT_EQ(statistics.packets_lost, callback.stats_.packets_lost);
287 EXPECT_EQ(statistics.extended_highest_sequence_number,
288 callback.stats_.extended_highest_sequence_number);
289 EXPECT_EQ(statistics.fraction_lost, callback.stats_.fraction_lost);
290 EXPECT_EQ(statistics.jitter, callback.stats_.jitter);
291 EXPECT_EQ(51, statistics.fraction_lost);
Harald Alvestrandc7c41912017-12-08 09:59:34 +0100292 EXPECT_EQ(1, statistics.packets_lost);
Qingsi Wang2370b082018-08-21 14:24:26 -0700293 EXPECT_EQ(5u, statistics.extended_highest_sequence_number);
Niels Möller5304a322018-08-27 13:27:05 +0200294 EXPECT_EQ(177u, statistics.jitter);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000295}
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000296
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000297TEST_F(ReceiveStatisticsTest, SimpleLossComputation) {
298 packet1_.SetSequenceNumber(1);
299 receive_statistics_->OnRtpPacket(packet1_);
300 packet1_.SetSequenceNumber(3);
301 receive_statistics_->OnRtpPacket(packet1_);
302 packet1_.SetSequenceNumber(4);
303 receive_statistics_->OnRtpPacket(packet1_);
304 packet1_.SetSequenceNumber(5);
305 receive_statistics_->OnRtpPacket(packet1_);
306
Niels Möller9a9f18a2019-08-02 13:52:37 +0200307 StreamStatistician* statistician =
308 receive_statistics_->GetStatistician(kSsrc1);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000309 RtcpStatistics statistics;
Niels Möller9a9f18a2019-08-02 13:52:37 +0200310 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000311 // 20% = 51/255.
312 EXPECT_EQ(51u, statistics.fraction_lost);
313 EXPECT_EQ(1, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200314 EXPECT_EQ(20, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000315}
316
317TEST_F(ReceiveStatisticsTest, LossComputationWithReordering) {
318 packet1_.SetSequenceNumber(1);
319 receive_statistics_->OnRtpPacket(packet1_);
320 packet1_.SetSequenceNumber(3);
321 receive_statistics_->OnRtpPacket(packet1_);
322 packet1_.SetSequenceNumber(2);
323 receive_statistics_->OnRtpPacket(packet1_);
324 packet1_.SetSequenceNumber(5);
325 receive_statistics_->OnRtpPacket(packet1_);
326
Niels Möller9a9f18a2019-08-02 13:52:37 +0200327 StreamStatistician* statistician =
328 receive_statistics_->GetStatistician(kSsrc1);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000329 RtcpStatistics statistics;
Niels Möller9a9f18a2019-08-02 13:52:37 +0200330 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000331 // 20% = 51/255.
332 EXPECT_EQ(51u, statistics.fraction_lost);
333 EXPECT_EQ(1, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200334 EXPECT_EQ(20, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000335}
336
337TEST_F(ReceiveStatisticsTest, LossComputationWithDuplicates) {
338 // Lose 2 packets, but also receive 1 duplicate. Should actually count as
339 // only 1 packet being lost.
340 packet1_.SetSequenceNumber(1);
341 receive_statistics_->OnRtpPacket(packet1_);
342 packet1_.SetSequenceNumber(4);
343 receive_statistics_->OnRtpPacket(packet1_);
344 packet1_.SetSequenceNumber(4);
345 receive_statistics_->OnRtpPacket(packet1_);
346 packet1_.SetSequenceNumber(5);
347 receive_statistics_->OnRtpPacket(packet1_);
348
Niels Möller9a9f18a2019-08-02 13:52:37 +0200349 StreamStatistician* statistician =
350 receive_statistics_->GetStatistician(kSsrc1);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000351 RtcpStatistics statistics;
Niels Möller9a9f18a2019-08-02 13:52:37 +0200352 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000353 // 20% = 51/255.
354 EXPECT_EQ(51u, statistics.fraction_lost);
355 EXPECT_EQ(1, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200356 EXPECT_EQ(20, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000357}
358
359TEST_F(ReceiveStatisticsTest, LossComputationWithSequenceNumberWrapping) {
360 // First, test loss computation over a period that included a sequence number
361 // rollover.
362 packet1_.SetSequenceNumber(0xfffd);
363 receive_statistics_->OnRtpPacket(packet1_);
364 packet1_.SetSequenceNumber(0);
365 receive_statistics_->OnRtpPacket(packet1_);
366 packet1_.SetSequenceNumber(0xfffe);
367 receive_statistics_->OnRtpPacket(packet1_);
368 packet1_.SetSequenceNumber(1);
369 receive_statistics_->OnRtpPacket(packet1_);
370
371 // Only one packet was actually lost, 0xffff.
Niels Möller9a9f18a2019-08-02 13:52:37 +0200372 StreamStatistician* statistician =
373 receive_statistics_->GetStatistician(kSsrc1);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000374 RtcpStatistics statistics;
Niels Möller9a9f18a2019-08-02 13:52:37 +0200375 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000376 // 20% = 51/255.
377 EXPECT_EQ(51u, statistics.fraction_lost);
378 EXPECT_EQ(1, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200379 EXPECT_EQ(20, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000380
381 // Now test losing one packet *after* the rollover.
382 packet1_.SetSequenceNumber(3);
383 receive_statistics_->OnRtpPacket(packet1_);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200384 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000385 // 50% = 127/255.
386 EXPECT_EQ(127u, statistics.fraction_lost);
387 EXPECT_EQ(2, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200388 // 2 packets lost, 7 expected
389 EXPECT_EQ(28, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000390}
391
392TEST_F(ReceiveStatisticsTest, StreamRestartDoesntCountAsLoss) {
393 RtcpStatistics statistics;
Niels Möller87da1092019-05-24 14:04:28 +0200394 receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000395
396 packet1_.SetSequenceNumber(0);
397 receive_statistics_->OnRtpPacket(packet1_);
398 packet1_.SetSequenceNumber(1);
399 receive_statistics_->OnRtpPacket(packet1_);
400
401 packet1_.SetSequenceNumber(400);
402 receive_statistics_->OnRtpPacket(packet1_);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200403 StreamStatistician* statistician =
404 receive_statistics_->GetStatistician(kSsrc1);
405 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000406 EXPECT_EQ(0, statistics.fraction_lost);
407 EXPECT_EQ(0, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200408 EXPECT_EQ(0, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000409
410 packet1_.SetSequenceNumber(401);
411 receive_statistics_->OnRtpPacket(packet1_);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200412 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000413 EXPECT_EQ(0, statistics.fraction_lost);
414 EXPECT_EQ(0, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200415 EXPECT_EQ(0, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000416}
417
418TEST_F(ReceiveStatisticsTest, CountsLossAfterStreamRestart) {
419 RtcpStatistics statistics;
Niels Möller87da1092019-05-24 14:04:28 +0200420 receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000421
422 packet1_.SetSequenceNumber(0);
423 receive_statistics_->OnRtpPacket(packet1_);
424 packet1_.SetSequenceNumber(1);
425 receive_statistics_->OnRtpPacket(packet1_);
426
427 packet1_.SetSequenceNumber(400);
428 receive_statistics_->OnRtpPacket(packet1_);
429 packet1_.SetSequenceNumber(401);
430 receive_statistics_->OnRtpPacket(packet1_);
431 packet1_.SetSequenceNumber(403);
432 receive_statistics_->OnRtpPacket(packet1_);
433
Niels Möller9a9f18a2019-08-02 13:52:37 +0200434 StreamStatistician* statistician =
435 receive_statistics_->GetStatistician(kSsrc1);
436
437 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000438 EXPECT_EQ(1, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200439 // Is this reasonable? */
440 EXPECT_EQ(0, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000441}
442
443TEST_F(ReceiveStatisticsTest, StreamCanRestartAtSequenceNumberWrapAround) {
444 RtcpStatistics statistics;
Niels Möller87da1092019-05-24 14:04:28 +0200445 receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000446
447 packet1_.SetSequenceNumber(0xffff - 401);
448 receive_statistics_->OnRtpPacket(packet1_);
449 packet1_.SetSequenceNumber(0xffff - 400);
450 receive_statistics_->OnRtpPacket(packet1_);
451
452 packet1_.SetSequenceNumber(0xffff);
453 receive_statistics_->OnRtpPacket(packet1_);
454 packet1_.SetSequenceNumber(0);
455 receive_statistics_->OnRtpPacket(packet1_);
456 packet1_.SetSequenceNumber(2);
457 receive_statistics_->OnRtpPacket(packet1_);
458
459 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
460 true);
461 EXPECT_EQ(1, statistics.packets_lost);
462}
463
464TEST_F(ReceiveStatisticsTest, StreamRestartNeedsTwoConsecutivePackets) {
465 RtcpStatistics statistics;
Niels Möller87da1092019-05-24 14:04:28 +0200466 receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000467
468 packet1_.SetSequenceNumber(400);
469 receive_statistics_->OnRtpPacket(packet1_);
470 packet1_.SetSequenceNumber(401);
471 receive_statistics_->OnRtpPacket(packet1_);
472
473 packet1_.SetSequenceNumber(1);
474 receive_statistics_->OnRtpPacket(packet1_);
475 packet1_.SetSequenceNumber(3);
476 receive_statistics_->OnRtpPacket(packet1_);
477 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
478 true);
479 EXPECT_EQ(401u, statistics.extended_highest_sequence_number);
480
481 packet1_.SetSequenceNumber(4);
482 receive_statistics_->OnRtpPacket(packet1_);
483 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
484 true);
485 EXPECT_EQ(4u, statistics.extended_highest_sequence_number);
486}
487
488TEST_F(ReceiveStatisticsTest, WrapsAroundExtendedHighestSequenceNumber) {
489 RtcpStatistics statistics;
490 packet1_.SetSequenceNumber(0xffff);
491 receive_statistics_->OnRtpPacket(packet1_);
492 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
493 true);
494 EXPECT_EQ(0xffffu, statistics.extended_highest_sequence_number);
495
496 // Wrap around.
497 packet1_.SetSequenceNumber(1);
498 receive_statistics_->OnRtpPacket(packet1_);
499 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
500 true);
501 EXPECT_EQ(0x10001u, statistics.extended_highest_sequence_number);
502
503 // Should be treated as out of order; shouldn't increment highest extended
504 // sequence number.
505 packet1_.SetSequenceNumber(0x10000 - 6);
506 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
507 true);
508 EXPECT_EQ(0x10001u, statistics.extended_highest_sequence_number);
509
510 // Receive a couple packets then wrap around again.
Niels Möller87da1092019-05-24 14:04:28 +0200511 receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000512 for (int i = 10; i < 0xffff; i += 150) {
513 packet1_.SetSequenceNumber(i);
514 receive_statistics_->OnRtpPacket(packet1_);
515 }
516 packet1_.SetSequenceNumber(1);
517 receive_statistics_->OnRtpPacket(packet1_);
518 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
519 true);
520 EXPECT_EQ(0x20001u, statistics.extended_highest_sequence_number);
521}
522
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000523class RtpTestCallback : public StreamDataCountersCallback {
524 public:
525 RtpTestCallback()
526 : StreamDataCountersCallback(), num_calls_(0), ssrc_(0), stats_() {}
Danil Chapovalovdd7e2842018-03-09 15:37:03 +0000527 ~RtpTestCallback() override = default;
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000528
Danil Chapovalovdd7e2842018-03-09 15:37:03 +0000529 void DataCountersUpdated(const StreamDataCounters& counters,
530 uint32_t ssrc) override {
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000531 ssrc_ = ssrc;
532 stats_ = counters;
533 ++num_calls_;
534 }
535
asapersson@webrtc.org44149392015-02-04 08:34:47 +0000536 void MatchPacketCounter(const RtpPacketCounter& expected,
537 const RtpPacketCounter& actual) {
538 EXPECT_EQ(expected.payload_bytes, actual.payload_bytes);
539 EXPECT_EQ(expected.header_bytes, actual.header_bytes);
540 EXPECT_EQ(expected.padding_bytes, actual.padding_bytes);
541 EXPECT_EQ(expected.packets, actual.packets);
542 }
543
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000544 void Matches(uint32_t num_calls,
545 uint32_t ssrc,
546 const StreamDataCounters& expected) {
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000547 EXPECT_EQ(num_calls, num_calls_);
548 EXPECT_EQ(ssrc, ssrc_);
asapersson@webrtc.org44149392015-02-04 08:34:47 +0000549 MatchPacketCounter(expected.transmitted, stats_.transmitted);
550 MatchPacketCounter(expected.retransmitted, stats_.retransmitted);
551 MatchPacketCounter(expected.fec, stats_.fec);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000552 }
553
554 uint32_t num_calls_;
555 uint32_t ssrc_;
556 StreamDataCounters stats_;
557};
558
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000559TEST_F(ReceiveStatisticsTest, RtpCallbacks) {
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000560 RtpTestCallback callback;
Danil Chapovalov8ce0d2b2018-11-23 11:03:25 +0100561 receive_statistics_ = ReceiveStatistics::Create(&clock_, nullptr, &callback);
Niels Möller5304a322018-08-27 13:27:05 +0200562 receive_statistics_->EnableRetransmitDetection(kSsrc1, true);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000563
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000564 const size_t kHeaderLength = 20;
565 const size_t kPaddingLength = 9;
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000566
Niels Möller1f3206c2018-09-14 08:26:32 +0200567 // One packet with payload size kPacketSize1.
568 RtpPacketReceived packet1 =
569 CreateRtpPacket(kSsrc1, kHeaderLength, kPacketSize1, 0);
570 receive_statistics_->OnRtpPacket(packet1);
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000571 StreamDataCounters expected;
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000572 expected.transmitted.payload_bytes = kPacketSize1;
573 expected.transmitted.header_bytes = kHeaderLength;
574 expected.transmitted.padding_bytes = 0;
575 expected.transmitted.packets = 1;
576 expected.retransmitted.payload_bytes = 0;
577 expected.retransmitted.header_bytes = 0;
578 expected.retransmitted.padding_bytes = 0;
579 expected.retransmitted.packets = 0;
580 expected.fec.packets = 0;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000581 callback.Matches(1, kSsrc1, expected);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000582
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000583 // Another packet of size kPacketSize1 with 9 bytes padding.
Niels Möller1f3206c2018-09-14 08:26:32 +0200584 RtpPacketReceived packet2 =
585 CreateRtpPacket(kSsrc1, kHeaderLength, kPacketSize1, 9);
586 packet2.SetSequenceNumber(packet1.SequenceNumber() + 1);
587 clock_.AdvanceTimeMilliseconds(5);
588 receive_statistics_->OnRtpPacket(packet2);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000589 expected.transmitted.payload_bytes = kPacketSize1 * 2;
590 expected.transmitted.header_bytes = kHeaderLength * 2;
591 expected.transmitted.padding_bytes = kPaddingLength;
592 expected.transmitted.packets = 2;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000593 callback.Matches(2, kSsrc1, expected);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000594
595 clock_.AdvanceTimeMilliseconds(5);
596 // Retransmit last packet.
Niels Möller1f3206c2018-09-14 08:26:32 +0200597 receive_statistics_->OnRtpPacket(packet2);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000598 expected.transmitted.payload_bytes = kPacketSize1 * 3;
599 expected.transmitted.header_bytes = kHeaderLength * 3;
600 expected.transmitted.padding_bytes = kPaddingLength * 2;
601 expected.transmitted.packets = 3;
602 expected.retransmitted.payload_bytes = kPacketSize1;
603 expected.retransmitted.header_bytes = kHeaderLength;
604 expected.retransmitted.padding_bytes = kPaddingLength;
605 expected.retransmitted.packets = 1;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000606 callback.Matches(3, kSsrc1, expected);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000607
asapersson@webrtc.org273fbbb2015-01-27 12:17:29 +0000608 // One FEC packet.
Niels Möller1f3206c2018-09-14 08:26:32 +0200609 packet1.SetSequenceNumber(packet2.SequenceNumber() + 1);
610 clock_.AdvanceTimeMilliseconds(5);
611 receive_statistics_->OnRtpPacket(packet1);
612 receive_statistics_->FecPacketReceived(packet1);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000613 expected.transmitted.payload_bytes = kPacketSize1 * 4;
614 expected.transmitted.header_bytes = kHeaderLength * 4;
615 expected.transmitted.packets = 4;
asapersson@webrtc.org273fbbb2015-01-27 12:17:29 +0000616 expected.fec.payload_bytes = kPacketSize1;
617 expected.fec.header_bytes = kHeaderLength;
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000618 expected.fec.packets = 1;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000619 callback.Matches(5, kSsrc1, expected);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000620}
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000621
Henrik Boströmcb755b02019-04-02 15:11:48 +0200622TEST_F(ReceiveStatisticsTest, LastPacketReceivedTimestamp) {
623 RtpTestCallback callback;
624 receive_statistics_ = ReceiveStatistics::Create(&clock_, nullptr, &callback);
625
626 clock_.AdvanceTimeMilliseconds(42);
627 receive_statistics_->OnRtpPacket(packet1_);
628 EXPECT_EQ(42, callback.stats_.last_packet_received_timestamp_ms);
629
630 clock_.AdvanceTimeMilliseconds(3);
631 receive_statistics_->OnRtpPacket(packet1_);
632 EXPECT_EQ(45, callback.stats_.last_packet_received_timestamp_ms);
633}
634
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000635TEST_F(ReceiveStatisticsTest, RtpCallbacksFecFirst) {
636 RtpTestCallback callback;
Danil Chapovalov8ce0d2b2018-11-23 11:03:25 +0100637 receive_statistics_ = ReceiveStatistics::Create(&clock_, nullptr, &callback);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000638
639 const uint32_t kHeaderLength = 20;
Niels Möller1f3206c2018-09-14 08:26:32 +0200640 RtpPacketReceived packet =
641 CreateRtpPacket(kSsrc1, kHeaderLength, kPacketSize1, 0);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000642 // If first packet is FEC, ignore it.
Niels Möller1f3206c2018-09-14 08:26:32 +0200643 receive_statistics_->FecPacketReceived(packet);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000644 EXPECT_EQ(0u, callback.num_calls_);
645
Niels Möller1f3206c2018-09-14 08:26:32 +0200646 receive_statistics_->OnRtpPacket(packet);
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000647 StreamDataCounters expected;
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000648 expected.transmitted.payload_bytes = kPacketSize1;
649 expected.transmitted.header_bytes = kHeaderLength;
650 expected.transmitted.padding_bytes = 0;
651 expected.transmitted.packets = 1;
652 expected.fec.packets = 0;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000653 callback.Matches(1, kSsrc1, expected);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000654
Niels Möller1f3206c2018-09-14 08:26:32 +0200655 receive_statistics_->FecPacketReceived(packet);
asapersson@webrtc.org273fbbb2015-01-27 12:17:29 +0000656 expected.fec.payload_bytes = kPacketSize1;
657 expected.fec.header_bytes = kHeaderLength;
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000658 expected.fec.packets = 1;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000659 callback.Matches(2, kSsrc1, expected);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000660}
Danil Chapovalovd1996b72018-01-16 11:07:18 +0100661
662} // namespace
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000663} // namespace webrtc