blob: 6a8ba6620a17589b1ed823b29dfff3c1edd690c2 [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
250 void CNameChanged(const char* cname, uint32_t ssrc) override {}
251
252 uint32_t num_calls_;
253 uint32_t ssrc_;
254 RtcpStatistics stats_;
255 } callback;
256
Danil Chapovalov8ce0d2b2018-11-23 11:03:25 +0100257 receive_statistics_ = ReceiveStatistics::Create(&clock_, &callback, nullptr);
Niels Möller5304a322018-08-27 13:27:05 +0200258 receive_statistics_->EnableRetransmitDetection(kSsrc1, true);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000259
260 // Add some arbitrary data, with loss and jitter.
Niels Möller1f3206c2018-09-14 08:26:32 +0200261 packet1_.SetSequenceNumber(1);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000262 clock_.AdvanceTimeMilliseconds(7);
Niels Möller1f3206c2018-09-14 08:26:32 +0200263 IncrementTimestamp(&packet1_, 3);
264 receive_statistics_->OnRtpPacket(packet1_);
265 IncrementSequenceNumber(&packet1_, 2);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000266 clock_.AdvanceTimeMilliseconds(9);
Niels Möller1f3206c2018-09-14 08:26:32 +0200267 IncrementTimestamp(&packet1_, 9);
268 receive_statistics_->OnRtpPacket(packet1_);
269 IncrementSequenceNumber(&packet1_, -1);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000270 clock_.AdvanceTimeMilliseconds(13);
Niels Möller1f3206c2018-09-14 08:26:32 +0200271 IncrementTimestamp(&packet1_, 47);
272 receive_statistics_->OnRtpPacket(packet1_);
273 IncrementSequenceNumber(&packet1_, 3);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000274 clock_.AdvanceTimeMilliseconds(11);
Niels Möller1f3206c2018-09-14 08:26:32 +0200275 IncrementTimestamp(&packet1_, 17);
276 receive_statistics_->OnRtpPacket(packet1_);
277 IncrementSequenceNumber(&packet1_);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000278
Qingsi Wang2370b082018-08-21 14:24:26 -0700279 EXPECT_EQ(0u, callback.num_calls_);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000280
Qingsi Wang2370b082018-08-21 14:24:26 -0700281 // Call GetStatistics, simulating a timed rtcp sender thread.
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000282 RtcpStatistics statistics;
Qingsi Wang2370b082018-08-21 14:24:26 -0700283 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
284 true);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000285
Qingsi Wang2370b082018-08-21 14:24:26 -0700286 EXPECT_EQ(1u, callback.num_calls_);
287 EXPECT_EQ(callback.ssrc_, kSsrc1);
288 EXPECT_EQ(statistics.packets_lost, callback.stats_.packets_lost);
289 EXPECT_EQ(statistics.extended_highest_sequence_number,
290 callback.stats_.extended_highest_sequence_number);
291 EXPECT_EQ(statistics.fraction_lost, callback.stats_.fraction_lost);
292 EXPECT_EQ(statistics.jitter, callback.stats_.jitter);
293 EXPECT_EQ(51, statistics.fraction_lost);
Harald Alvestrandc7c41912017-12-08 09:59:34 +0100294 EXPECT_EQ(1, statistics.packets_lost);
Qingsi Wang2370b082018-08-21 14:24:26 -0700295 EXPECT_EQ(5u, statistics.extended_highest_sequence_number);
Niels Möller5304a322018-08-27 13:27:05 +0200296 EXPECT_EQ(177u, statistics.jitter);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000297}
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000298
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000299TEST_F(ReceiveStatisticsTest, SimpleLossComputation) {
300 packet1_.SetSequenceNumber(1);
301 receive_statistics_->OnRtpPacket(packet1_);
302 packet1_.SetSequenceNumber(3);
303 receive_statistics_->OnRtpPacket(packet1_);
304 packet1_.SetSequenceNumber(4);
305 receive_statistics_->OnRtpPacket(packet1_);
306 packet1_.SetSequenceNumber(5);
307 receive_statistics_->OnRtpPacket(packet1_);
308
Niels Möller9a9f18a2019-08-02 13:52:37 +0200309 StreamStatistician* statistician =
310 receive_statistics_->GetStatistician(kSsrc1);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000311 RtcpStatistics statistics;
Niels Möller9a9f18a2019-08-02 13:52:37 +0200312 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000313 // 20% = 51/255.
314 EXPECT_EQ(51u, statistics.fraction_lost);
315 EXPECT_EQ(1, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200316 EXPECT_EQ(20, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000317}
318
319TEST_F(ReceiveStatisticsTest, LossComputationWithReordering) {
320 packet1_.SetSequenceNumber(1);
321 receive_statistics_->OnRtpPacket(packet1_);
322 packet1_.SetSequenceNumber(3);
323 receive_statistics_->OnRtpPacket(packet1_);
324 packet1_.SetSequenceNumber(2);
325 receive_statistics_->OnRtpPacket(packet1_);
326 packet1_.SetSequenceNumber(5);
327 receive_statistics_->OnRtpPacket(packet1_);
328
Niels Möller9a9f18a2019-08-02 13:52:37 +0200329 StreamStatistician* statistician =
330 receive_statistics_->GetStatistician(kSsrc1);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000331 RtcpStatistics statistics;
Niels Möller9a9f18a2019-08-02 13:52:37 +0200332 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000333 // 20% = 51/255.
334 EXPECT_EQ(51u, statistics.fraction_lost);
335 EXPECT_EQ(1, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200336 EXPECT_EQ(20, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000337}
338
339TEST_F(ReceiveStatisticsTest, LossComputationWithDuplicates) {
340 // Lose 2 packets, but also receive 1 duplicate. Should actually count as
341 // only 1 packet being lost.
342 packet1_.SetSequenceNumber(1);
343 receive_statistics_->OnRtpPacket(packet1_);
344 packet1_.SetSequenceNumber(4);
345 receive_statistics_->OnRtpPacket(packet1_);
346 packet1_.SetSequenceNumber(4);
347 receive_statistics_->OnRtpPacket(packet1_);
348 packet1_.SetSequenceNumber(5);
349 receive_statistics_->OnRtpPacket(packet1_);
350
Niels Möller9a9f18a2019-08-02 13:52:37 +0200351 StreamStatistician* statistician =
352 receive_statistics_->GetStatistician(kSsrc1);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000353 RtcpStatistics statistics;
Niels Möller9a9f18a2019-08-02 13:52:37 +0200354 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000355 // 20% = 51/255.
356 EXPECT_EQ(51u, statistics.fraction_lost);
357 EXPECT_EQ(1, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200358 EXPECT_EQ(20, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000359}
360
361TEST_F(ReceiveStatisticsTest, LossComputationWithSequenceNumberWrapping) {
362 // First, test loss computation over a period that included a sequence number
363 // rollover.
364 packet1_.SetSequenceNumber(0xfffd);
365 receive_statistics_->OnRtpPacket(packet1_);
366 packet1_.SetSequenceNumber(0);
367 receive_statistics_->OnRtpPacket(packet1_);
368 packet1_.SetSequenceNumber(0xfffe);
369 receive_statistics_->OnRtpPacket(packet1_);
370 packet1_.SetSequenceNumber(1);
371 receive_statistics_->OnRtpPacket(packet1_);
372
373 // Only one packet was actually lost, 0xffff.
Niels Möller9a9f18a2019-08-02 13:52:37 +0200374 StreamStatistician* statistician =
375 receive_statistics_->GetStatistician(kSsrc1);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000376 RtcpStatistics statistics;
Niels Möller9a9f18a2019-08-02 13:52:37 +0200377 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000378 // 20% = 51/255.
379 EXPECT_EQ(51u, statistics.fraction_lost);
380 EXPECT_EQ(1, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200381 EXPECT_EQ(20, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000382
383 // Now test losing one packet *after* the rollover.
384 packet1_.SetSequenceNumber(3);
385 receive_statistics_->OnRtpPacket(packet1_);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200386 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000387 // 50% = 127/255.
388 EXPECT_EQ(127u, statistics.fraction_lost);
389 EXPECT_EQ(2, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200390 // 2 packets lost, 7 expected
391 EXPECT_EQ(28, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000392}
393
394TEST_F(ReceiveStatisticsTest, StreamRestartDoesntCountAsLoss) {
395 RtcpStatistics statistics;
Niels Möller87da1092019-05-24 14:04:28 +0200396 receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000397
398 packet1_.SetSequenceNumber(0);
399 receive_statistics_->OnRtpPacket(packet1_);
400 packet1_.SetSequenceNumber(1);
401 receive_statistics_->OnRtpPacket(packet1_);
402
403 packet1_.SetSequenceNumber(400);
404 receive_statistics_->OnRtpPacket(packet1_);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200405 StreamStatistician* statistician =
406 receive_statistics_->GetStatistician(kSsrc1);
407 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000408 EXPECT_EQ(0, statistics.fraction_lost);
409 EXPECT_EQ(0, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200410 EXPECT_EQ(0, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000411
412 packet1_.SetSequenceNumber(401);
413 receive_statistics_->OnRtpPacket(packet1_);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200414 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000415 EXPECT_EQ(0, statistics.fraction_lost);
416 EXPECT_EQ(0, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200417 EXPECT_EQ(0, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000418}
419
420TEST_F(ReceiveStatisticsTest, CountsLossAfterStreamRestart) {
421 RtcpStatistics statistics;
Niels Möller87da1092019-05-24 14:04:28 +0200422 receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000423
424 packet1_.SetSequenceNumber(0);
425 receive_statistics_->OnRtpPacket(packet1_);
426 packet1_.SetSequenceNumber(1);
427 receive_statistics_->OnRtpPacket(packet1_);
428
429 packet1_.SetSequenceNumber(400);
430 receive_statistics_->OnRtpPacket(packet1_);
431 packet1_.SetSequenceNumber(401);
432 receive_statistics_->OnRtpPacket(packet1_);
433 packet1_.SetSequenceNumber(403);
434 receive_statistics_->OnRtpPacket(packet1_);
435
Niels Möller9a9f18a2019-08-02 13:52:37 +0200436 StreamStatistician* statistician =
437 receive_statistics_->GetStatistician(kSsrc1);
438
439 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000440 EXPECT_EQ(1, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200441 // Is this reasonable? */
442 EXPECT_EQ(0, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000443}
444
445TEST_F(ReceiveStatisticsTest, StreamCanRestartAtSequenceNumberWrapAround) {
446 RtcpStatistics statistics;
Niels Möller87da1092019-05-24 14:04:28 +0200447 receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000448
449 packet1_.SetSequenceNumber(0xffff - 401);
450 receive_statistics_->OnRtpPacket(packet1_);
451 packet1_.SetSequenceNumber(0xffff - 400);
452 receive_statistics_->OnRtpPacket(packet1_);
453
454 packet1_.SetSequenceNumber(0xffff);
455 receive_statistics_->OnRtpPacket(packet1_);
456 packet1_.SetSequenceNumber(0);
457 receive_statistics_->OnRtpPacket(packet1_);
458 packet1_.SetSequenceNumber(2);
459 receive_statistics_->OnRtpPacket(packet1_);
460
461 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
462 true);
463 EXPECT_EQ(1, statistics.packets_lost);
464}
465
466TEST_F(ReceiveStatisticsTest, StreamRestartNeedsTwoConsecutivePackets) {
467 RtcpStatistics statistics;
Niels Möller87da1092019-05-24 14:04:28 +0200468 receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000469
470 packet1_.SetSequenceNumber(400);
471 receive_statistics_->OnRtpPacket(packet1_);
472 packet1_.SetSequenceNumber(401);
473 receive_statistics_->OnRtpPacket(packet1_);
474
475 packet1_.SetSequenceNumber(1);
476 receive_statistics_->OnRtpPacket(packet1_);
477 packet1_.SetSequenceNumber(3);
478 receive_statistics_->OnRtpPacket(packet1_);
479 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
480 true);
481 EXPECT_EQ(401u, statistics.extended_highest_sequence_number);
482
483 packet1_.SetSequenceNumber(4);
484 receive_statistics_->OnRtpPacket(packet1_);
485 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
486 true);
487 EXPECT_EQ(4u, statistics.extended_highest_sequence_number);
488}
489
490TEST_F(ReceiveStatisticsTest, WrapsAroundExtendedHighestSequenceNumber) {
491 RtcpStatistics statistics;
492 packet1_.SetSequenceNumber(0xffff);
493 receive_statistics_->OnRtpPacket(packet1_);
494 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
495 true);
496 EXPECT_EQ(0xffffu, statistics.extended_highest_sequence_number);
497
498 // Wrap around.
499 packet1_.SetSequenceNumber(1);
500 receive_statistics_->OnRtpPacket(packet1_);
501 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
502 true);
503 EXPECT_EQ(0x10001u, statistics.extended_highest_sequence_number);
504
505 // Should be treated as out of order; shouldn't increment highest extended
506 // sequence number.
507 packet1_.SetSequenceNumber(0x10000 - 6);
508 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
509 true);
510 EXPECT_EQ(0x10001u, statistics.extended_highest_sequence_number);
511
512 // Receive a couple packets then wrap around again.
Niels Möller87da1092019-05-24 14:04:28 +0200513 receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000514 for (int i = 10; i < 0xffff; i += 150) {
515 packet1_.SetSequenceNumber(i);
516 receive_statistics_->OnRtpPacket(packet1_);
517 }
518 packet1_.SetSequenceNumber(1);
519 receive_statistics_->OnRtpPacket(packet1_);
520 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
521 true);
522 EXPECT_EQ(0x20001u, statistics.extended_highest_sequence_number);
523}
524
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000525class RtpTestCallback : public StreamDataCountersCallback {
526 public:
527 RtpTestCallback()
528 : StreamDataCountersCallback(), num_calls_(0), ssrc_(0), stats_() {}
Danil Chapovalovdd7e2842018-03-09 15:37:03 +0000529 ~RtpTestCallback() override = default;
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000530
Danil Chapovalovdd7e2842018-03-09 15:37:03 +0000531 void DataCountersUpdated(const StreamDataCounters& counters,
532 uint32_t ssrc) override {
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000533 ssrc_ = ssrc;
534 stats_ = counters;
535 ++num_calls_;
536 }
537
asapersson@webrtc.org44149392015-02-04 08:34:47 +0000538 void MatchPacketCounter(const RtpPacketCounter& expected,
539 const RtpPacketCounter& actual) {
540 EXPECT_EQ(expected.payload_bytes, actual.payload_bytes);
541 EXPECT_EQ(expected.header_bytes, actual.header_bytes);
542 EXPECT_EQ(expected.padding_bytes, actual.padding_bytes);
543 EXPECT_EQ(expected.packets, actual.packets);
544 }
545
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000546 void Matches(uint32_t num_calls,
547 uint32_t ssrc,
548 const StreamDataCounters& expected) {
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000549 EXPECT_EQ(num_calls, num_calls_);
550 EXPECT_EQ(ssrc, ssrc_);
asapersson@webrtc.org44149392015-02-04 08:34:47 +0000551 MatchPacketCounter(expected.transmitted, stats_.transmitted);
552 MatchPacketCounter(expected.retransmitted, stats_.retransmitted);
553 MatchPacketCounter(expected.fec, stats_.fec);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000554 }
555
556 uint32_t num_calls_;
557 uint32_t ssrc_;
558 StreamDataCounters stats_;
559};
560
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000561TEST_F(ReceiveStatisticsTest, RtpCallbacks) {
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000562 RtpTestCallback callback;
Danil Chapovalov8ce0d2b2018-11-23 11:03:25 +0100563 receive_statistics_ = ReceiveStatistics::Create(&clock_, nullptr, &callback);
Niels Möller5304a322018-08-27 13:27:05 +0200564 receive_statistics_->EnableRetransmitDetection(kSsrc1, true);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000565
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000566 const size_t kHeaderLength = 20;
567 const size_t kPaddingLength = 9;
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000568
Niels Möller1f3206c2018-09-14 08:26:32 +0200569 // One packet with payload size kPacketSize1.
570 RtpPacketReceived packet1 =
571 CreateRtpPacket(kSsrc1, kHeaderLength, kPacketSize1, 0);
572 receive_statistics_->OnRtpPacket(packet1);
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000573 StreamDataCounters expected;
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000574 expected.transmitted.payload_bytes = kPacketSize1;
575 expected.transmitted.header_bytes = kHeaderLength;
576 expected.transmitted.padding_bytes = 0;
577 expected.transmitted.packets = 1;
578 expected.retransmitted.payload_bytes = 0;
579 expected.retransmitted.header_bytes = 0;
580 expected.retransmitted.padding_bytes = 0;
581 expected.retransmitted.packets = 0;
582 expected.fec.packets = 0;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000583 callback.Matches(1, kSsrc1, expected);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000584
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000585 // Another packet of size kPacketSize1 with 9 bytes padding.
Niels Möller1f3206c2018-09-14 08:26:32 +0200586 RtpPacketReceived packet2 =
587 CreateRtpPacket(kSsrc1, kHeaderLength, kPacketSize1, 9);
588 packet2.SetSequenceNumber(packet1.SequenceNumber() + 1);
589 clock_.AdvanceTimeMilliseconds(5);
590 receive_statistics_->OnRtpPacket(packet2);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000591 expected.transmitted.payload_bytes = kPacketSize1 * 2;
592 expected.transmitted.header_bytes = kHeaderLength * 2;
593 expected.transmitted.padding_bytes = kPaddingLength;
594 expected.transmitted.packets = 2;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000595 callback.Matches(2, kSsrc1, expected);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000596
597 clock_.AdvanceTimeMilliseconds(5);
598 // Retransmit last packet.
Niels Möller1f3206c2018-09-14 08:26:32 +0200599 receive_statistics_->OnRtpPacket(packet2);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000600 expected.transmitted.payload_bytes = kPacketSize1 * 3;
601 expected.transmitted.header_bytes = kHeaderLength * 3;
602 expected.transmitted.padding_bytes = kPaddingLength * 2;
603 expected.transmitted.packets = 3;
604 expected.retransmitted.payload_bytes = kPacketSize1;
605 expected.retransmitted.header_bytes = kHeaderLength;
606 expected.retransmitted.padding_bytes = kPaddingLength;
607 expected.retransmitted.packets = 1;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000608 callback.Matches(3, kSsrc1, expected);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000609
asapersson@webrtc.org273fbbb2015-01-27 12:17:29 +0000610 // One FEC packet.
Niels Möller1f3206c2018-09-14 08:26:32 +0200611 packet1.SetSequenceNumber(packet2.SequenceNumber() + 1);
612 clock_.AdvanceTimeMilliseconds(5);
613 receive_statistics_->OnRtpPacket(packet1);
614 receive_statistics_->FecPacketReceived(packet1);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000615 expected.transmitted.payload_bytes = kPacketSize1 * 4;
616 expected.transmitted.header_bytes = kHeaderLength * 4;
617 expected.transmitted.packets = 4;
asapersson@webrtc.org273fbbb2015-01-27 12:17:29 +0000618 expected.fec.payload_bytes = kPacketSize1;
619 expected.fec.header_bytes = kHeaderLength;
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000620 expected.fec.packets = 1;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000621 callback.Matches(5, kSsrc1, expected);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000622}
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000623
Henrik Boströmcb755b02019-04-02 15:11:48 +0200624TEST_F(ReceiveStatisticsTest, LastPacketReceivedTimestamp) {
625 RtpTestCallback callback;
626 receive_statistics_ = ReceiveStatistics::Create(&clock_, nullptr, &callback);
627
628 clock_.AdvanceTimeMilliseconds(42);
629 receive_statistics_->OnRtpPacket(packet1_);
630 EXPECT_EQ(42, callback.stats_.last_packet_received_timestamp_ms);
631
632 clock_.AdvanceTimeMilliseconds(3);
633 receive_statistics_->OnRtpPacket(packet1_);
634 EXPECT_EQ(45, callback.stats_.last_packet_received_timestamp_ms);
635}
636
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000637TEST_F(ReceiveStatisticsTest, RtpCallbacksFecFirst) {
638 RtpTestCallback callback;
Danil Chapovalov8ce0d2b2018-11-23 11:03:25 +0100639 receive_statistics_ = ReceiveStatistics::Create(&clock_, nullptr, &callback);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000640
641 const uint32_t kHeaderLength = 20;
Niels Möller1f3206c2018-09-14 08:26:32 +0200642 RtpPacketReceived packet =
643 CreateRtpPacket(kSsrc1, kHeaderLength, kPacketSize1, 0);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000644 // If first packet is FEC, ignore it.
Niels Möller1f3206c2018-09-14 08:26:32 +0200645 receive_statistics_->FecPacketReceived(packet);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000646 EXPECT_EQ(0u, callback.num_calls_);
647
Niels Möller1f3206c2018-09-14 08:26:32 +0200648 receive_statistics_->OnRtpPacket(packet);
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000649 StreamDataCounters expected;
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000650 expected.transmitted.payload_bytes = kPacketSize1;
651 expected.transmitted.header_bytes = kHeaderLength;
652 expected.transmitted.padding_bytes = 0;
653 expected.transmitted.packets = 1;
654 expected.fec.packets = 0;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000655 callback.Matches(1, kSsrc1, expected);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000656
Niels Möller1f3206c2018-09-14 08:26:32 +0200657 receive_statistics_->FecPacketReceived(packet);
asapersson@webrtc.org273fbbb2015-01-27 12:17:29 +0000658 expected.fec.payload_bytes = kPacketSize1;
659 expected.fec.header_bytes = kHeaderLength;
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000660 expected.fec.packets = 1;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000661 callback.Matches(2, kSsrc1, expected);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000662}
Danil Chapovalovd1996b72018-01-16 11:07:18 +0100663
664} // namespace
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000665} // namespace webrtc