blob: 8b08ce40dacb331cc0ac1fea92668a12f5326fa9 [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
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000068class ReceiveStatisticsTest : public ::testing::Test {
69 public:
Yves Gerey665174f2018-06-19 15:03:05 +020070 ReceiveStatisticsTest()
Danil Chapovalov8ce0d2b2018-11-23 11:03:25 +010071 : clock_(0),
Niels Möller12ebfa62019-08-06 16:04:12 +020072 receive_statistics_(ReceiveStatistics::Create(&clock_, nullptr)) {
Niels Möller1f3206c2018-09-14 08:26:32 +020073 packet1_ = CreateRtpPacket(kSsrc1, kPacketSize1);
74 packet2_ = CreateRtpPacket(kSsrc2, kPacketSize2);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000075 }
76
77 protected:
78 SimulatedClock clock_;
kwiberg84be5112016-04-27 01:19:58 -070079 std::unique_ptr<ReceiveStatistics> receive_statistics_;
Niels Möller1f3206c2018-09-14 08:26:32 +020080 RtpPacketReceived packet1_;
81 RtpPacketReceived packet2_;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000082};
83
84TEST_F(ReceiveStatisticsTest, TwoIncomingSsrcs) {
Niels Möller1f3206c2018-09-14 08:26:32 +020085 receive_statistics_->OnRtpPacket(packet1_);
86 IncrementSequenceNumber(&packet1_);
87 receive_statistics_->OnRtpPacket(packet2_);
88 IncrementSequenceNumber(&packet2_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000089 clock_.AdvanceTimeMilliseconds(100);
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
95 StreamStatistician* statistician =
96 receive_statistics_->GetStatistician(kSsrc1);
97 ASSERT_TRUE(statistician != NULL);
98 EXPECT_GT(statistician->BitrateReceived(), 0u);
Niels Möller01525f92019-08-12 15:12:20 +020099 StreamDataCounters counters = statistician->GetReceiveStreamDataCounters();
100 EXPECT_EQ(176u, counters.transmitted.payload_bytes);
101 EXPECT_EQ(24u, counters.transmitted.header_bytes);
102 EXPECT_EQ(0u, counters.transmitted.padding_bytes);
103 EXPECT_EQ(2u, counters.transmitted.packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000104
Yves Gerey665174f2018-06-19 15:03:05 +0200105 statistician = receive_statistics_->GetStatistician(kSsrc2);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000106 ASSERT_TRUE(statistician != NULL);
107 EXPECT_GT(statistician->BitrateReceived(), 0u);
Niels Möller01525f92019-08-12 15:12:20 +0200108 counters = statistician->GetReceiveStreamDataCounters();
109 EXPECT_EQ(576u, counters.transmitted.payload_bytes);
110 EXPECT_EQ(24u, counters.transmitted.header_bytes);
111 EXPECT_EQ(0u, counters.transmitted.padding_bytes);
112 EXPECT_EQ(2u, counters.transmitted.packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000113
Danil Chapovalovc5267d22017-09-18 13:57:19 +0200114 EXPECT_EQ(2u, receive_statistics_->RtcpReportBlocks(3).size());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000115 // Add more incoming packets and verify that they are registered in both
116 // access methods.
Niels Möller1f3206c2018-09-14 08:26:32 +0200117 receive_statistics_->OnRtpPacket(packet1_);
118 IncrementSequenceNumber(&packet1_);
119 receive_statistics_->OnRtpPacket(packet2_);
120 IncrementSequenceNumber(&packet2_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000121
Niels Möller01525f92019-08-12 15:12:20 +0200122 counters = receive_statistics_->GetStatistician(kSsrc1)
123 ->GetReceiveStreamDataCounters();
124 EXPECT_EQ(264u, counters.transmitted.payload_bytes);
125 EXPECT_EQ(36u, counters.transmitted.header_bytes);
126 EXPECT_EQ(0u, counters.transmitted.padding_bytes);
127 EXPECT_EQ(3u, counters.transmitted.packets);
128
129 counters = receive_statistics_->GetStatistician(kSsrc2)
130 ->GetReceiveStreamDataCounters();
131 EXPECT_EQ(864u, counters.transmitted.payload_bytes);
132 EXPECT_EQ(36u, counters.transmitted.header_bytes);
133 EXPECT_EQ(0u, counters.transmitted.padding_bytes);
134 EXPECT_EQ(3u, counters.transmitted.packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000135}
136
Danil Chapovalovd1996b72018-01-16 11:07:18 +0100137TEST_F(ReceiveStatisticsTest,
138 RtcpReportBlocksReturnsMaxBlocksWhenThereAreMoreStatisticians) {
Niels Möller1f3206c2018-09-14 08:26:32 +0200139 RtpPacketReceived packet1 = CreateRtpPacket(kSsrc1, kPacketSize1);
140 RtpPacketReceived packet2 = CreateRtpPacket(kSsrc2, kPacketSize1);
141 RtpPacketReceived packet3 = CreateRtpPacket(kSsrc3, kPacketSize1);
142 receive_statistics_->OnRtpPacket(packet1);
143 receive_statistics_->OnRtpPacket(packet2);
144 receive_statistics_->OnRtpPacket(packet3);
Danil Chapovalovd1996b72018-01-16 11:07:18 +0100145
146 EXPECT_THAT(receive_statistics_->RtcpReportBlocks(2), SizeIs(2));
147 EXPECT_THAT(receive_statistics_->RtcpReportBlocks(2), SizeIs(2));
148 EXPECT_THAT(receive_statistics_->RtcpReportBlocks(2), SizeIs(2));
149}
150
151TEST_F(ReceiveStatisticsTest,
152 RtcpReportBlocksReturnsAllObservedSsrcsWithMultipleCalls) {
Niels Möller1f3206c2018-09-14 08:26:32 +0200153 RtpPacketReceived packet1 = CreateRtpPacket(kSsrc1, kPacketSize1);
154 RtpPacketReceived packet2 = CreateRtpPacket(kSsrc2, kPacketSize1);
155 RtpPacketReceived packet3 = CreateRtpPacket(kSsrc3, kPacketSize1);
156 RtpPacketReceived packet4 = CreateRtpPacket(kSsrc4, kPacketSize1);
157 receive_statistics_->OnRtpPacket(packet1);
158 receive_statistics_->OnRtpPacket(packet2);
159 receive_statistics_->OnRtpPacket(packet3);
160 receive_statistics_->OnRtpPacket(packet4);
Danil Chapovalovd1996b72018-01-16 11:07:18 +0100161
162 std::vector<uint32_t> observed_ssrcs;
163 std::vector<rtcp::ReportBlock> report_blocks =
164 receive_statistics_->RtcpReportBlocks(2);
165 ASSERT_THAT(report_blocks, SizeIs(2));
166 observed_ssrcs.push_back(report_blocks[0].source_ssrc());
167 observed_ssrcs.push_back(report_blocks[1].source_ssrc());
168
169 report_blocks = receive_statistics_->RtcpReportBlocks(2);
170 ASSERT_THAT(report_blocks, SizeIs(2));
171 observed_ssrcs.push_back(report_blocks[0].source_ssrc());
172 observed_ssrcs.push_back(report_blocks[1].source_ssrc());
173
174 EXPECT_THAT(observed_ssrcs,
175 UnorderedElementsAre(kSsrc1, kSsrc2, kSsrc3, kSsrc4));
176}
177
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000178TEST_F(ReceiveStatisticsTest, ActiveStatisticians) {
Niels Möller1f3206c2018-09-14 08:26:32 +0200179 receive_statistics_->OnRtpPacket(packet1_);
180 IncrementSequenceNumber(&packet1_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000181 clock_.AdvanceTimeMilliseconds(1000);
Niels Möller1f3206c2018-09-14 08:26:32 +0200182 receive_statistics_->OnRtpPacket(packet2_);
183 IncrementSequenceNumber(&packet2_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000184 // Nothing should time out since only 1000 ms has passed since the first
185 // packet came in.
Danil Chapovalovc5267d22017-09-18 13:57:19 +0200186 EXPECT_EQ(2u, receive_statistics_->RtcpReportBlocks(3).size());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000187
188 clock_.AdvanceTimeMilliseconds(7000);
189 // kSsrc1 should have timed out.
Danil Chapovalovc5267d22017-09-18 13:57:19 +0200190 EXPECT_EQ(1u, receive_statistics_->RtcpReportBlocks(3).size());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000191
192 clock_.AdvanceTimeMilliseconds(1000);
193 // kSsrc2 should have timed out.
Danil Chapovalovc5267d22017-09-18 13:57:19 +0200194 EXPECT_EQ(0u, receive_statistics_->RtcpReportBlocks(3).size());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000195
Niels Möller1f3206c2018-09-14 08:26:32 +0200196 receive_statistics_->OnRtpPacket(packet1_);
197 IncrementSequenceNumber(&packet1_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000198 // kSsrc1 should be active again and the data counters should have survived.
Danil Chapovalovc5267d22017-09-18 13:57:19 +0200199 EXPECT_EQ(1u, receive_statistics_->RtcpReportBlocks(3).size());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000200 StreamStatistician* statistician =
201 receive_statistics_->GetStatistician(kSsrc1);
202 ASSERT_TRUE(statistician != NULL);
Niels Möller01525f92019-08-12 15:12:20 +0200203 StreamDataCounters counters = statistician->GetReceiveStreamDataCounters();
204 EXPECT_EQ(176u, counters.transmitted.payload_bytes);
205 EXPECT_EQ(24u, counters.transmitted.header_bytes);
206 EXPECT_EQ(0u, counters.transmitted.padding_bytes);
207 EXPECT_EQ(2u, counters.transmitted.packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000208}
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000209
Niels Möller5304a322018-08-27 13:27:05 +0200210TEST_F(ReceiveStatisticsTest,
211 DoesntCreateRtcpReportBlockUntilFirstReceivedPacketForSsrc) {
212 // Creates a statistician object for the ssrc.
213 receive_statistics_->EnableRetransmitDetection(kSsrc1, true);
214 EXPECT_TRUE(receive_statistics_->GetStatistician(kSsrc1) != nullptr);
215 EXPECT_EQ(0u, receive_statistics_->RtcpReportBlocks(3).size());
216 // Receive first packet
Niels Möller1f3206c2018-09-14 08:26:32 +0200217 receive_statistics_->OnRtpPacket(packet1_);
Niels Möller5304a322018-08-27 13:27:05 +0200218 EXPECT_EQ(1u, receive_statistics_->RtcpReportBlocks(3).size());
219}
220
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000221TEST_F(ReceiveStatisticsTest, GetReceiveStreamDataCounters) {
Niels Möller1f3206c2018-09-14 08:26:32 +0200222 receive_statistics_->OnRtpPacket(packet1_);
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000223 StreamStatistician* statistician =
224 receive_statistics_->GetStatistician(kSsrc1);
225 ASSERT_TRUE(statistician != NULL);
226
Niels Möller58b496b2019-08-12 12:16:31 +0200227 StreamDataCounters counters = statistician->GetReceiveStreamDataCounters();
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000228 EXPECT_GT(counters.first_packet_time_ms, -1);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000229 EXPECT_EQ(1u, counters.transmitted.packets);
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000230
Niels Möller1f3206c2018-09-14 08:26:32 +0200231 receive_statistics_->OnRtpPacket(packet1_);
Niels Möller58b496b2019-08-12 12:16:31 +0200232 counters = statistician->GetReceiveStreamDataCounters();
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000233 EXPECT_GT(counters.first_packet_time_ms, -1);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000234 EXPECT_EQ(2u, counters.transmitted.packets);
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000235}
236
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000237TEST_F(ReceiveStatisticsTest, SimpleLossComputation) {
238 packet1_.SetSequenceNumber(1);
239 receive_statistics_->OnRtpPacket(packet1_);
240 packet1_.SetSequenceNumber(3);
241 receive_statistics_->OnRtpPacket(packet1_);
242 packet1_.SetSequenceNumber(4);
243 receive_statistics_->OnRtpPacket(packet1_);
244 packet1_.SetSequenceNumber(5);
245 receive_statistics_->OnRtpPacket(packet1_);
246
Niels Möller9a9f18a2019-08-02 13:52:37 +0200247 StreamStatistician* statistician =
248 receive_statistics_->GetStatistician(kSsrc1);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000249 RtcpStatistics statistics;
Niels Möller9a9f18a2019-08-02 13:52:37 +0200250 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000251 // 20% = 51/255.
252 EXPECT_EQ(51u, statistics.fraction_lost);
253 EXPECT_EQ(1, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200254 EXPECT_EQ(20, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000255}
256
257TEST_F(ReceiveStatisticsTest, LossComputationWithReordering) {
258 packet1_.SetSequenceNumber(1);
259 receive_statistics_->OnRtpPacket(packet1_);
260 packet1_.SetSequenceNumber(3);
261 receive_statistics_->OnRtpPacket(packet1_);
262 packet1_.SetSequenceNumber(2);
263 receive_statistics_->OnRtpPacket(packet1_);
264 packet1_.SetSequenceNumber(5);
265 receive_statistics_->OnRtpPacket(packet1_);
266
Niels Möller9a9f18a2019-08-02 13:52:37 +0200267 StreamStatistician* statistician =
268 receive_statistics_->GetStatistician(kSsrc1);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000269 RtcpStatistics statistics;
Niels Möller9a9f18a2019-08-02 13:52:37 +0200270 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000271 // 20% = 51/255.
272 EXPECT_EQ(51u, statistics.fraction_lost);
273 EXPECT_EQ(1, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200274 EXPECT_EQ(20, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000275}
276
277TEST_F(ReceiveStatisticsTest, LossComputationWithDuplicates) {
278 // Lose 2 packets, but also receive 1 duplicate. Should actually count as
279 // only 1 packet being lost.
280 packet1_.SetSequenceNumber(1);
281 receive_statistics_->OnRtpPacket(packet1_);
282 packet1_.SetSequenceNumber(4);
283 receive_statistics_->OnRtpPacket(packet1_);
284 packet1_.SetSequenceNumber(4);
285 receive_statistics_->OnRtpPacket(packet1_);
286 packet1_.SetSequenceNumber(5);
287 receive_statistics_->OnRtpPacket(packet1_);
288
Niels Möller9a9f18a2019-08-02 13:52:37 +0200289 StreamStatistician* statistician =
290 receive_statistics_->GetStatistician(kSsrc1);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000291 RtcpStatistics statistics;
Niels Möller9a9f18a2019-08-02 13:52:37 +0200292 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000293 // 20% = 51/255.
294 EXPECT_EQ(51u, statistics.fraction_lost);
295 EXPECT_EQ(1, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200296 EXPECT_EQ(20, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000297}
298
299TEST_F(ReceiveStatisticsTest, LossComputationWithSequenceNumberWrapping) {
300 // First, test loss computation over a period that included a sequence number
301 // rollover.
302 packet1_.SetSequenceNumber(0xfffd);
303 receive_statistics_->OnRtpPacket(packet1_);
304 packet1_.SetSequenceNumber(0);
305 receive_statistics_->OnRtpPacket(packet1_);
306 packet1_.SetSequenceNumber(0xfffe);
307 receive_statistics_->OnRtpPacket(packet1_);
308 packet1_.SetSequenceNumber(1);
309 receive_statistics_->OnRtpPacket(packet1_);
310
311 // Only one packet was actually lost, 0xffff.
Niels Möller9a9f18a2019-08-02 13:52:37 +0200312 StreamStatistician* statistician =
313 receive_statistics_->GetStatistician(kSsrc1);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000314 RtcpStatistics statistics;
Niels Möller9a9f18a2019-08-02 13:52:37 +0200315 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000316 // 20% = 51/255.
317 EXPECT_EQ(51u, statistics.fraction_lost);
318 EXPECT_EQ(1, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200319 EXPECT_EQ(20, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000320
321 // Now test losing one packet *after* the rollover.
322 packet1_.SetSequenceNumber(3);
323 receive_statistics_->OnRtpPacket(packet1_);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200324 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000325 // 50% = 127/255.
326 EXPECT_EQ(127u, statistics.fraction_lost);
327 EXPECT_EQ(2, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200328 // 2 packets lost, 7 expected
329 EXPECT_EQ(28, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000330}
331
332TEST_F(ReceiveStatisticsTest, StreamRestartDoesntCountAsLoss) {
333 RtcpStatistics statistics;
Niels Möller87da1092019-05-24 14:04:28 +0200334 receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000335
336 packet1_.SetSequenceNumber(0);
337 receive_statistics_->OnRtpPacket(packet1_);
338 packet1_.SetSequenceNumber(1);
339 receive_statistics_->OnRtpPacket(packet1_);
340
341 packet1_.SetSequenceNumber(400);
342 receive_statistics_->OnRtpPacket(packet1_);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200343 StreamStatistician* statistician =
344 receive_statistics_->GetStatistician(kSsrc1);
345 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000346 EXPECT_EQ(0, statistics.fraction_lost);
347 EXPECT_EQ(0, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200348 EXPECT_EQ(0, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000349
350 packet1_.SetSequenceNumber(401);
351 receive_statistics_->OnRtpPacket(packet1_);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200352 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000353 EXPECT_EQ(0, statistics.fraction_lost);
354 EXPECT_EQ(0, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200355 EXPECT_EQ(0, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000356}
357
358TEST_F(ReceiveStatisticsTest, CountsLossAfterStreamRestart) {
359 RtcpStatistics statistics;
Niels Möller87da1092019-05-24 14:04:28 +0200360 receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000361
362 packet1_.SetSequenceNumber(0);
363 receive_statistics_->OnRtpPacket(packet1_);
364 packet1_.SetSequenceNumber(1);
365 receive_statistics_->OnRtpPacket(packet1_);
366
367 packet1_.SetSequenceNumber(400);
368 receive_statistics_->OnRtpPacket(packet1_);
369 packet1_.SetSequenceNumber(401);
370 receive_statistics_->OnRtpPacket(packet1_);
371 packet1_.SetSequenceNumber(403);
372 receive_statistics_->OnRtpPacket(packet1_);
373
Niels Möller9a9f18a2019-08-02 13:52:37 +0200374 StreamStatistician* statistician =
375 receive_statistics_->GetStatistician(kSsrc1);
376
377 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000378 EXPECT_EQ(1, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200379 // Is this reasonable? */
380 EXPECT_EQ(0, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000381}
382
383TEST_F(ReceiveStatisticsTest, StreamCanRestartAtSequenceNumberWrapAround) {
384 RtcpStatistics statistics;
Niels Möller87da1092019-05-24 14:04:28 +0200385 receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000386
387 packet1_.SetSequenceNumber(0xffff - 401);
388 receive_statistics_->OnRtpPacket(packet1_);
389 packet1_.SetSequenceNumber(0xffff - 400);
390 receive_statistics_->OnRtpPacket(packet1_);
391
392 packet1_.SetSequenceNumber(0xffff);
393 receive_statistics_->OnRtpPacket(packet1_);
394 packet1_.SetSequenceNumber(0);
395 receive_statistics_->OnRtpPacket(packet1_);
396 packet1_.SetSequenceNumber(2);
397 receive_statistics_->OnRtpPacket(packet1_);
398
399 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
400 true);
401 EXPECT_EQ(1, statistics.packets_lost);
402}
403
404TEST_F(ReceiveStatisticsTest, StreamRestartNeedsTwoConsecutivePackets) {
405 RtcpStatistics statistics;
Niels Möller87da1092019-05-24 14:04:28 +0200406 receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000407
408 packet1_.SetSequenceNumber(400);
409 receive_statistics_->OnRtpPacket(packet1_);
410 packet1_.SetSequenceNumber(401);
411 receive_statistics_->OnRtpPacket(packet1_);
412
413 packet1_.SetSequenceNumber(1);
414 receive_statistics_->OnRtpPacket(packet1_);
415 packet1_.SetSequenceNumber(3);
416 receive_statistics_->OnRtpPacket(packet1_);
417 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
418 true);
419 EXPECT_EQ(401u, statistics.extended_highest_sequence_number);
420
421 packet1_.SetSequenceNumber(4);
422 receive_statistics_->OnRtpPacket(packet1_);
423 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
424 true);
425 EXPECT_EQ(4u, statistics.extended_highest_sequence_number);
426}
427
428TEST_F(ReceiveStatisticsTest, WrapsAroundExtendedHighestSequenceNumber) {
429 RtcpStatistics statistics;
430 packet1_.SetSequenceNumber(0xffff);
431 receive_statistics_->OnRtpPacket(packet1_);
432 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
433 true);
434 EXPECT_EQ(0xffffu, statistics.extended_highest_sequence_number);
435
436 // Wrap around.
437 packet1_.SetSequenceNumber(1);
438 receive_statistics_->OnRtpPacket(packet1_);
439 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
440 true);
441 EXPECT_EQ(0x10001u, statistics.extended_highest_sequence_number);
442
443 // Should be treated as out of order; shouldn't increment highest extended
444 // sequence number.
445 packet1_.SetSequenceNumber(0x10000 - 6);
446 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
447 true);
448 EXPECT_EQ(0x10001u, statistics.extended_highest_sequence_number);
449
450 // Receive a couple packets then wrap around again.
Niels Möller87da1092019-05-24 14:04:28 +0200451 receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000452 for (int i = 10; i < 0xffff; i += 150) {
453 packet1_.SetSequenceNumber(i);
454 receive_statistics_->OnRtpPacket(packet1_);
455 }
456 packet1_.SetSequenceNumber(1);
457 receive_statistics_->OnRtpPacket(packet1_);
458 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
459 true);
460 EXPECT_EQ(0x20001u, statistics.extended_highest_sequence_number);
461}
462
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000463class RtpTestCallback : public StreamDataCountersCallback {
464 public:
465 RtpTestCallback()
466 : StreamDataCountersCallback(), num_calls_(0), ssrc_(0), stats_() {}
Danil Chapovalovdd7e2842018-03-09 15:37:03 +0000467 ~RtpTestCallback() override = default;
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000468
Danil Chapovalovdd7e2842018-03-09 15:37:03 +0000469 void DataCountersUpdated(const StreamDataCounters& counters,
470 uint32_t ssrc) override {
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000471 ssrc_ = ssrc;
472 stats_ = counters;
473 ++num_calls_;
474 }
475
asapersson@webrtc.org44149392015-02-04 08:34:47 +0000476 void MatchPacketCounter(const RtpPacketCounter& expected,
477 const RtpPacketCounter& actual) {
478 EXPECT_EQ(expected.payload_bytes, actual.payload_bytes);
479 EXPECT_EQ(expected.header_bytes, actual.header_bytes);
480 EXPECT_EQ(expected.padding_bytes, actual.padding_bytes);
481 EXPECT_EQ(expected.packets, actual.packets);
482 }
483
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000484 void Matches(uint32_t num_calls,
485 uint32_t ssrc,
486 const StreamDataCounters& expected) {
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000487 EXPECT_EQ(num_calls, num_calls_);
488 EXPECT_EQ(ssrc, ssrc_);
asapersson@webrtc.org44149392015-02-04 08:34:47 +0000489 MatchPacketCounter(expected.transmitted, stats_.transmitted);
490 MatchPacketCounter(expected.retransmitted, stats_.retransmitted);
491 MatchPacketCounter(expected.fec, stats_.fec);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000492 }
493
494 uint32_t num_calls_;
495 uint32_t ssrc_;
496 StreamDataCounters stats_;
497};
498
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000499TEST_F(ReceiveStatisticsTest, RtpCallbacks) {
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000500 RtpTestCallback callback;
Niels Möller12ebfa62019-08-06 16:04:12 +0200501 receive_statistics_ = ReceiveStatistics::Create(&clock_, &callback);
Niels Möller5304a322018-08-27 13:27:05 +0200502 receive_statistics_->EnableRetransmitDetection(kSsrc1, true);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000503
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000504 const size_t kHeaderLength = 20;
505 const size_t kPaddingLength = 9;
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000506
Niels Möller1f3206c2018-09-14 08:26:32 +0200507 // One packet with payload size kPacketSize1.
508 RtpPacketReceived packet1 =
509 CreateRtpPacket(kSsrc1, kHeaderLength, kPacketSize1, 0);
510 receive_statistics_->OnRtpPacket(packet1);
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000511 StreamDataCounters expected;
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000512 expected.transmitted.payload_bytes = kPacketSize1;
513 expected.transmitted.header_bytes = kHeaderLength;
514 expected.transmitted.padding_bytes = 0;
515 expected.transmitted.packets = 1;
516 expected.retransmitted.payload_bytes = 0;
517 expected.retransmitted.header_bytes = 0;
518 expected.retransmitted.padding_bytes = 0;
519 expected.retransmitted.packets = 0;
520 expected.fec.packets = 0;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000521 callback.Matches(1, kSsrc1, expected);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000522
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000523 // Another packet of size kPacketSize1 with 9 bytes padding.
Niels Möller1f3206c2018-09-14 08:26:32 +0200524 RtpPacketReceived packet2 =
525 CreateRtpPacket(kSsrc1, kHeaderLength, kPacketSize1, 9);
526 packet2.SetSequenceNumber(packet1.SequenceNumber() + 1);
527 clock_.AdvanceTimeMilliseconds(5);
528 receive_statistics_->OnRtpPacket(packet2);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000529 expected.transmitted.payload_bytes = kPacketSize1 * 2;
530 expected.transmitted.header_bytes = kHeaderLength * 2;
531 expected.transmitted.padding_bytes = kPaddingLength;
532 expected.transmitted.packets = 2;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000533 callback.Matches(2, kSsrc1, expected);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000534
535 clock_.AdvanceTimeMilliseconds(5);
536 // Retransmit last packet.
Niels Möller1f3206c2018-09-14 08:26:32 +0200537 receive_statistics_->OnRtpPacket(packet2);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000538 expected.transmitted.payload_bytes = kPacketSize1 * 3;
539 expected.transmitted.header_bytes = kHeaderLength * 3;
540 expected.transmitted.padding_bytes = kPaddingLength * 2;
541 expected.transmitted.packets = 3;
542 expected.retransmitted.payload_bytes = kPacketSize1;
543 expected.retransmitted.header_bytes = kHeaderLength;
544 expected.retransmitted.padding_bytes = kPaddingLength;
545 expected.retransmitted.packets = 1;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000546 callback.Matches(3, kSsrc1, expected);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000547
asapersson@webrtc.org273fbbb2015-01-27 12:17:29 +0000548 // One FEC packet.
Niels Möller1f3206c2018-09-14 08:26:32 +0200549 packet1.SetSequenceNumber(packet2.SequenceNumber() + 1);
550 clock_.AdvanceTimeMilliseconds(5);
551 receive_statistics_->OnRtpPacket(packet1);
552 receive_statistics_->FecPacketReceived(packet1);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000553 expected.transmitted.payload_bytes = kPacketSize1 * 4;
554 expected.transmitted.header_bytes = kHeaderLength * 4;
555 expected.transmitted.packets = 4;
asapersson@webrtc.org273fbbb2015-01-27 12:17:29 +0000556 expected.fec.payload_bytes = kPacketSize1;
557 expected.fec.header_bytes = kHeaderLength;
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000558 expected.fec.packets = 1;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000559 callback.Matches(5, kSsrc1, expected);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000560}
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000561
Henrik Boströmcb755b02019-04-02 15:11:48 +0200562TEST_F(ReceiveStatisticsTest, LastPacketReceivedTimestamp) {
563 RtpTestCallback callback;
Niels Möller12ebfa62019-08-06 16:04:12 +0200564 receive_statistics_ = ReceiveStatistics::Create(&clock_, &callback);
Henrik Boströmcb755b02019-04-02 15:11:48 +0200565
566 clock_.AdvanceTimeMilliseconds(42);
567 receive_statistics_->OnRtpPacket(packet1_);
568 EXPECT_EQ(42, callback.stats_.last_packet_received_timestamp_ms);
569
570 clock_.AdvanceTimeMilliseconds(3);
571 receive_statistics_->OnRtpPacket(packet1_);
572 EXPECT_EQ(45, callback.stats_.last_packet_received_timestamp_ms);
573}
574
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000575TEST_F(ReceiveStatisticsTest, RtpCallbacksFecFirst) {
576 RtpTestCallback callback;
Niels Möller12ebfa62019-08-06 16:04:12 +0200577 receive_statistics_ = ReceiveStatistics::Create(&clock_, &callback);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000578
579 const uint32_t kHeaderLength = 20;
Niels Möller1f3206c2018-09-14 08:26:32 +0200580 RtpPacketReceived packet =
581 CreateRtpPacket(kSsrc1, kHeaderLength, kPacketSize1, 0);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000582 // If first packet is FEC, ignore it.
Niels Möller1f3206c2018-09-14 08:26:32 +0200583 receive_statistics_->FecPacketReceived(packet);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000584 EXPECT_EQ(0u, callback.num_calls_);
585
Niels Möller1f3206c2018-09-14 08:26:32 +0200586 receive_statistics_->OnRtpPacket(packet);
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000587 StreamDataCounters expected;
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000588 expected.transmitted.payload_bytes = kPacketSize1;
589 expected.transmitted.header_bytes = kHeaderLength;
590 expected.transmitted.padding_bytes = 0;
591 expected.transmitted.packets = 1;
592 expected.fec.packets = 0;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000593 callback.Matches(1, kSsrc1, expected);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000594
Niels Möller1f3206c2018-09-14 08:26:32 +0200595 receive_statistics_->FecPacketReceived(packet);
asapersson@webrtc.org273fbbb2015-01-27 12:17:29 +0000596 expected.fec.payload_bytes = kPacketSize1;
597 expected.fec.header_bytes = kHeaderLength;
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000598 expected.fec.packets = 1;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000599 callback.Matches(2, kSsrc1, expected);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000600}
Danil Chapovalovd1996b72018-01-16 11:07:18 +0100601
602} // namespace
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000603} // namespace webrtc