blob: 25424565bfc9e4d57257e839888c3e9bbf901e06 [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);
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000099 size_t bytes_received = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000100 uint32_t packets_received = 0;
101 statistician->GetDataCounters(&bytes_received, &packets_received);
102 EXPECT_EQ(200u, bytes_received);
103 EXPECT_EQ(2u, packets_received);
104
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);
108 statistician->GetDataCounters(&bytes_received, &packets_received);
109 EXPECT_EQ(600u, bytes_received);
110 EXPECT_EQ(2u, packets_received);
111
Danil Chapovalovc5267d22017-09-18 13:57:19 +0200112 EXPECT_EQ(2u, receive_statistics_->RtcpReportBlocks(3).size());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000113 // Add more incoming packets and verify that they are registered in both
114 // access methods.
Niels Möller1f3206c2018-09-14 08:26:32 +0200115 receive_statistics_->OnRtpPacket(packet1_);
116 IncrementSequenceNumber(&packet1_);
117 receive_statistics_->OnRtpPacket(packet2_);
118 IncrementSequenceNumber(&packet2_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000119
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000120 receive_statistics_->GetStatistician(kSsrc1)->GetDataCounters(
121 &bytes_received, &packets_received);
122 EXPECT_EQ(300u, bytes_received);
123 EXPECT_EQ(3u, packets_received);
124 receive_statistics_->GetStatistician(kSsrc2)->GetDataCounters(
125 &bytes_received, &packets_received);
126 EXPECT_EQ(900u, bytes_received);
127 EXPECT_EQ(3u, packets_received);
128}
129
Danil Chapovalovd1996b72018-01-16 11:07:18 +0100130TEST_F(ReceiveStatisticsTest,
131 RtcpReportBlocksReturnsMaxBlocksWhenThereAreMoreStatisticians) {
Niels Möller1f3206c2018-09-14 08:26:32 +0200132 RtpPacketReceived packet1 = CreateRtpPacket(kSsrc1, kPacketSize1);
133 RtpPacketReceived packet2 = CreateRtpPacket(kSsrc2, kPacketSize1);
134 RtpPacketReceived packet3 = CreateRtpPacket(kSsrc3, kPacketSize1);
135 receive_statistics_->OnRtpPacket(packet1);
136 receive_statistics_->OnRtpPacket(packet2);
137 receive_statistics_->OnRtpPacket(packet3);
Danil Chapovalovd1996b72018-01-16 11:07:18 +0100138
139 EXPECT_THAT(receive_statistics_->RtcpReportBlocks(2), SizeIs(2));
140 EXPECT_THAT(receive_statistics_->RtcpReportBlocks(2), SizeIs(2));
141 EXPECT_THAT(receive_statistics_->RtcpReportBlocks(2), SizeIs(2));
142}
143
144TEST_F(ReceiveStatisticsTest,
145 RtcpReportBlocksReturnsAllObservedSsrcsWithMultipleCalls) {
Niels Möller1f3206c2018-09-14 08:26:32 +0200146 RtpPacketReceived packet1 = CreateRtpPacket(kSsrc1, kPacketSize1);
147 RtpPacketReceived packet2 = CreateRtpPacket(kSsrc2, kPacketSize1);
148 RtpPacketReceived packet3 = CreateRtpPacket(kSsrc3, kPacketSize1);
149 RtpPacketReceived packet4 = CreateRtpPacket(kSsrc4, kPacketSize1);
150 receive_statistics_->OnRtpPacket(packet1);
151 receive_statistics_->OnRtpPacket(packet2);
152 receive_statistics_->OnRtpPacket(packet3);
153 receive_statistics_->OnRtpPacket(packet4);
Danil Chapovalovd1996b72018-01-16 11:07:18 +0100154
155 std::vector<uint32_t> observed_ssrcs;
156 std::vector<rtcp::ReportBlock> report_blocks =
157 receive_statistics_->RtcpReportBlocks(2);
158 ASSERT_THAT(report_blocks, SizeIs(2));
159 observed_ssrcs.push_back(report_blocks[0].source_ssrc());
160 observed_ssrcs.push_back(report_blocks[1].source_ssrc());
161
162 report_blocks = 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 EXPECT_THAT(observed_ssrcs,
168 UnorderedElementsAre(kSsrc1, kSsrc2, kSsrc3, kSsrc4));
169}
170
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000171TEST_F(ReceiveStatisticsTest, ActiveStatisticians) {
Niels Möller1f3206c2018-09-14 08:26:32 +0200172 receive_statistics_->OnRtpPacket(packet1_);
173 IncrementSequenceNumber(&packet1_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000174 clock_.AdvanceTimeMilliseconds(1000);
Niels Möller1f3206c2018-09-14 08:26:32 +0200175 receive_statistics_->OnRtpPacket(packet2_);
176 IncrementSequenceNumber(&packet2_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000177 // Nothing should time out since only 1000 ms has passed since the first
178 // packet came in.
Danil Chapovalovc5267d22017-09-18 13:57:19 +0200179 EXPECT_EQ(2u, receive_statistics_->RtcpReportBlocks(3).size());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000180
181 clock_.AdvanceTimeMilliseconds(7000);
182 // kSsrc1 should have timed out.
Danil Chapovalovc5267d22017-09-18 13:57:19 +0200183 EXPECT_EQ(1u, receive_statistics_->RtcpReportBlocks(3).size());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000184
185 clock_.AdvanceTimeMilliseconds(1000);
186 // kSsrc2 should have timed out.
Danil Chapovalovc5267d22017-09-18 13:57:19 +0200187 EXPECT_EQ(0u, receive_statistics_->RtcpReportBlocks(3).size());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000188
Niels Möller1f3206c2018-09-14 08:26:32 +0200189 receive_statistics_->OnRtpPacket(packet1_);
190 IncrementSequenceNumber(&packet1_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000191 // kSsrc1 should be active again and the data counters should have survived.
Danil Chapovalovc5267d22017-09-18 13:57:19 +0200192 EXPECT_EQ(1u, receive_statistics_->RtcpReportBlocks(3).size());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000193 StreamStatistician* statistician =
194 receive_statistics_->GetStatistician(kSsrc1);
195 ASSERT_TRUE(statistician != NULL);
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000196 size_t bytes_received = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000197 uint32_t packets_received = 0;
198 statistician->GetDataCounters(&bytes_received, &packets_received);
199 EXPECT_EQ(200u, bytes_received);
200 EXPECT_EQ(2u, packets_received);
201}
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000202
Niels Möller5304a322018-08-27 13:27:05 +0200203TEST_F(ReceiveStatisticsTest,
204 DoesntCreateRtcpReportBlockUntilFirstReceivedPacketForSsrc) {
205 // Creates a statistician object for the ssrc.
206 receive_statistics_->EnableRetransmitDetection(kSsrc1, true);
207 EXPECT_TRUE(receive_statistics_->GetStatistician(kSsrc1) != nullptr);
208 EXPECT_EQ(0u, receive_statistics_->RtcpReportBlocks(3).size());
209 // Receive first packet
Niels Möller1f3206c2018-09-14 08:26:32 +0200210 receive_statistics_->OnRtpPacket(packet1_);
Niels Möller5304a322018-08-27 13:27:05 +0200211 EXPECT_EQ(1u, receive_statistics_->RtcpReportBlocks(3).size());
212}
213
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000214TEST_F(ReceiveStatisticsTest, GetReceiveStreamDataCounters) {
Niels Möller1f3206c2018-09-14 08:26:32 +0200215 receive_statistics_->OnRtpPacket(packet1_);
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000216 StreamStatistician* statistician =
217 receive_statistics_->GetStatistician(kSsrc1);
218 ASSERT_TRUE(statistician != NULL);
219
Niels Möller58b496b2019-08-12 12:16:31 +0200220 StreamDataCounters counters = statistician->GetReceiveStreamDataCounters();
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000221 EXPECT_GT(counters.first_packet_time_ms, -1);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000222 EXPECT_EQ(1u, counters.transmitted.packets);
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000223
Niels Möller1f3206c2018-09-14 08:26:32 +0200224 receive_statistics_->OnRtpPacket(packet1_);
Niels Möller58b496b2019-08-12 12:16:31 +0200225 counters = statistician->GetReceiveStreamDataCounters();
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000226 EXPECT_GT(counters.first_packet_time_ms, -1);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000227 EXPECT_EQ(2u, counters.transmitted.packets);
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000228}
229
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000230TEST_F(ReceiveStatisticsTest, SimpleLossComputation) {
231 packet1_.SetSequenceNumber(1);
232 receive_statistics_->OnRtpPacket(packet1_);
233 packet1_.SetSequenceNumber(3);
234 receive_statistics_->OnRtpPacket(packet1_);
235 packet1_.SetSequenceNumber(4);
236 receive_statistics_->OnRtpPacket(packet1_);
237 packet1_.SetSequenceNumber(5);
238 receive_statistics_->OnRtpPacket(packet1_);
239
Niels Möller9a9f18a2019-08-02 13:52:37 +0200240 StreamStatistician* statistician =
241 receive_statistics_->GetStatistician(kSsrc1);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000242 RtcpStatistics statistics;
Niels Möller9a9f18a2019-08-02 13:52:37 +0200243 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000244 // 20% = 51/255.
245 EXPECT_EQ(51u, statistics.fraction_lost);
246 EXPECT_EQ(1, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200247 EXPECT_EQ(20, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000248}
249
250TEST_F(ReceiveStatisticsTest, LossComputationWithReordering) {
251 packet1_.SetSequenceNumber(1);
252 receive_statistics_->OnRtpPacket(packet1_);
253 packet1_.SetSequenceNumber(3);
254 receive_statistics_->OnRtpPacket(packet1_);
255 packet1_.SetSequenceNumber(2);
256 receive_statistics_->OnRtpPacket(packet1_);
257 packet1_.SetSequenceNumber(5);
258 receive_statistics_->OnRtpPacket(packet1_);
259
Niels Möller9a9f18a2019-08-02 13:52:37 +0200260 StreamStatistician* statistician =
261 receive_statistics_->GetStatistician(kSsrc1);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000262 RtcpStatistics statistics;
Niels Möller9a9f18a2019-08-02 13:52:37 +0200263 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000264 // 20% = 51/255.
265 EXPECT_EQ(51u, statistics.fraction_lost);
266 EXPECT_EQ(1, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200267 EXPECT_EQ(20, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000268}
269
270TEST_F(ReceiveStatisticsTest, LossComputationWithDuplicates) {
271 // Lose 2 packets, but also receive 1 duplicate. Should actually count as
272 // only 1 packet being lost.
273 packet1_.SetSequenceNumber(1);
274 receive_statistics_->OnRtpPacket(packet1_);
275 packet1_.SetSequenceNumber(4);
276 receive_statistics_->OnRtpPacket(packet1_);
277 packet1_.SetSequenceNumber(4);
278 receive_statistics_->OnRtpPacket(packet1_);
279 packet1_.SetSequenceNumber(5);
280 receive_statistics_->OnRtpPacket(packet1_);
281
Niels Möller9a9f18a2019-08-02 13:52:37 +0200282 StreamStatistician* statistician =
283 receive_statistics_->GetStatistician(kSsrc1);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000284 RtcpStatistics statistics;
Niels Möller9a9f18a2019-08-02 13:52:37 +0200285 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000286 // 20% = 51/255.
287 EXPECT_EQ(51u, statistics.fraction_lost);
288 EXPECT_EQ(1, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200289 EXPECT_EQ(20, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000290}
291
292TEST_F(ReceiveStatisticsTest, LossComputationWithSequenceNumberWrapping) {
293 // First, test loss computation over a period that included a sequence number
294 // rollover.
295 packet1_.SetSequenceNumber(0xfffd);
296 receive_statistics_->OnRtpPacket(packet1_);
297 packet1_.SetSequenceNumber(0);
298 receive_statistics_->OnRtpPacket(packet1_);
299 packet1_.SetSequenceNumber(0xfffe);
300 receive_statistics_->OnRtpPacket(packet1_);
301 packet1_.SetSequenceNumber(1);
302 receive_statistics_->OnRtpPacket(packet1_);
303
304 // Only one packet was actually lost, 0xffff.
Niels Möller9a9f18a2019-08-02 13:52:37 +0200305 StreamStatistician* statistician =
306 receive_statistics_->GetStatistician(kSsrc1);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000307 RtcpStatistics statistics;
Niels Möller9a9f18a2019-08-02 13:52:37 +0200308 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000309 // 20% = 51/255.
310 EXPECT_EQ(51u, statistics.fraction_lost);
311 EXPECT_EQ(1, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200312 EXPECT_EQ(20, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000313
314 // Now test losing one packet *after* the rollover.
315 packet1_.SetSequenceNumber(3);
316 receive_statistics_->OnRtpPacket(packet1_);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200317 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000318 // 50% = 127/255.
319 EXPECT_EQ(127u, statistics.fraction_lost);
320 EXPECT_EQ(2, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200321 // 2 packets lost, 7 expected
322 EXPECT_EQ(28, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000323}
324
325TEST_F(ReceiveStatisticsTest, StreamRestartDoesntCountAsLoss) {
326 RtcpStatistics statistics;
Niels Möller87da1092019-05-24 14:04:28 +0200327 receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000328
329 packet1_.SetSequenceNumber(0);
330 receive_statistics_->OnRtpPacket(packet1_);
331 packet1_.SetSequenceNumber(1);
332 receive_statistics_->OnRtpPacket(packet1_);
333
334 packet1_.SetSequenceNumber(400);
335 receive_statistics_->OnRtpPacket(packet1_);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200336 StreamStatistician* statistician =
337 receive_statistics_->GetStatistician(kSsrc1);
338 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000339 EXPECT_EQ(0, statistics.fraction_lost);
340 EXPECT_EQ(0, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200341 EXPECT_EQ(0, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000342
343 packet1_.SetSequenceNumber(401);
344 receive_statistics_->OnRtpPacket(packet1_);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200345 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
351TEST_F(ReceiveStatisticsTest, CountsLossAfterStreamRestart) {
352 RtcpStatistics statistics;
Niels Möller87da1092019-05-24 14:04:28 +0200353 receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000354
355 packet1_.SetSequenceNumber(0);
356 receive_statistics_->OnRtpPacket(packet1_);
357 packet1_.SetSequenceNumber(1);
358 receive_statistics_->OnRtpPacket(packet1_);
359
360 packet1_.SetSequenceNumber(400);
361 receive_statistics_->OnRtpPacket(packet1_);
362 packet1_.SetSequenceNumber(401);
363 receive_statistics_->OnRtpPacket(packet1_);
364 packet1_.SetSequenceNumber(403);
365 receive_statistics_->OnRtpPacket(packet1_);
366
Niels Möller9a9f18a2019-08-02 13:52:37 +0200367 StreamStatistician* statistician =
368 receive_statistics_->GetStatistician(kSsrc1);
369
370 statistician->GetStatistics(&statistics, true);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000371 EXPECT_EQ(1, statistics.packets_lost);
Niels Möller9a9f18a2019-08-02 13:52:37 +0200372 // Is this reasonable? */
373 EXPECT_EQ(0, statistician->GetFractionLostInPercent());
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000374}
375
376TEST_F(ReceiveStatisticsTest, StreamCanRestartAtSequenceNumberWrapAround) {
377 RtcpStatistics statistics;
Niels Möller87da1092019-05-24 14:04:28 +0200378 receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000379
380 packet1_.SetSequenceNumber(0xffff - 401);
381 receive_statistics_->OnRtpPacket(packet1_);
382 packet1_.SetSequenceNumber(0xffff - 400);
383 receive_statistics_->OnRtpPacket(packet1_);
384
385 packet1_.SetSequenceNumber(0xffff);
386 receive_statistics_->OnRtpPacket(packet1_);
387 packet1_.SetSequenceNumber(0);
388 receive_statistics_->OnRtpPacket(packet1_);
389 packet1_.SetSequenceNumber(2);
390 receive_statistics_->OnRtpPacket(packet1_);
391
392 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
393 true);
394 EXPECT_EQ(1, statistics.packets_lost);
395}
396
397TEST_F(ReceiveStatisticsTest, StreamRestartNeedsTwoConsecutivePackets) {
398 RtcpStatistics statistics;
Niels Möller87da1092019-05-24 14:04:28 +0200399 receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000400
401 packet1_.SetSequenceNumber(400);
402 receive_statistics_->OnRtpPacket(packet1_);
403 packet1_.SetSequenceNumber(401);
404 receive_statistics_->OnRtpPacket(packet1_);
405
406 packet1_.SetSequenceNumber(1);
407 receive_statistics_->OnRtpPacket(packet1_);
408 packet1_.SetSequenceNumber(3);
409 receive_statistics_->OnRtpPacket(packet1_);
410 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
411 true);
412 EXPECT_EQ(401u, statistics.extended_highest_sequence_number);
413
414 packet1_.SetSequenceNumber(4);
415 receive_statistics_->OnRtpPacket(packet1_);
416 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
417 true);
418 EXPECT_EQ(4u, statistics.extended_highest_sequence_number);
419}
420
421TEST_F(ReceiveStatisticsTest, WrapsAroundExtendedHighestSequenceNumber) {
422 RtcpStatistics statistics;
423 packet1_.SetSequenceNumber(0xffff);
424 receive_statistics_->OnRtpPacket(packet1_);
425 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
426 true);
427 EXPECT_EQ(0xffffu, statistics.extended_highest_sequence_number);
428
429 // Wrap around.
430 packet1_.SetSequenceNumber(1);
431 receive_statistics_->OnRtpPacket(packet1_);
432 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
433 true);
434 EXPECT_EQ(0x10001u, statistics.extended_highest_sequence_number);
435
436 // Should be treated as out of order; shouldn't increment highest extended
437 // sequence number.
438 packet1_.SetSequenceNumber(0x10000 - 6);
439 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
440 true);
441 EXPECT_EQ(0x10001u, statistics.extended_highest_sequence_number);
442
443 // Receive a couple packets then wrap around again.
Niels Möller87da1092019-05-24 14:04:28 +0200444 receive_statistics_->SetMaxReorderingThreshold(kSsrc1, 200);
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000445 for (int i = 10; i < 0xffff; i += 150) {
446 packet1_.SetSequenceNumber(i);
447 receive_statistics_->OnRtpPacket(packet1_);
448 }
449 packet1_.SetSequenceNumber(1);
450 receive_statistics_->OnRtpPacket(packet1_);
451 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
452 true);
453 EXPECT_EQ(0x20001u, statistics.extended_highest_sequence_number);
454}
455
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000456class RtpTestCallback : public StreamDataCountersCallback {
457 public:
458 RtpTestCallback()
459 : StreamDataCountersCallback(), num_calls_(0), ssrc_(0), stats_() {}
Danil Chapovalovdd7e2842018-03-09 15:37:03 +0000460 ~RtpTestCallback() override = default;
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000461
Danil Chapovalovdd7e2842018-03-09 15:37:03 +0000462 void DataCountersUpdated(const StreamDataCounters& counters,
463 uint32_t ssrc) override {
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000464 ssrc_ = ssrc;
465 stats_ = counters;
466 ++num_calls_;
467 }
468
asapersson@webrtc.org44149392015-02-04 08:34:47 +0000469 void MatchPacketCounter(const RtpPacketCounter& expected,
470 const RtpPacketCounter& actual) {
471 EXPECT_EQ(expected.payload_bytes, actual.payload_bytes);
472 EXPECT_EQ(expected.header_bytes, actual.header_bytes);
473 EXPECT_EQ(expected.padding_bytes, actual.padding_bytes);
474 EXPECT_EQ(expected.packets, actual.packets);
475 }
476
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000477 void Matches(uint32_t num_calls,
478 uint32_t ssrc,
479 const StreamDataCounters& expected) {
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000480 EXPECT_EQ(num_calls, num_calls_);
481 EXPECT_EQ(ssrc, ssrc_);
asapersson@webrtc.org44149392015-02-04 08:34:47 +0000482 MatchPacketCounter(expected.transmitted, stats_.transmitted);
483 MatchPacketCounter(expected.retransmitted, stats_.retransmitted);
484 MatchPacketCounter(expected.fec, stats_.fec);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000485 }
486
487 uint32_t num_calls_;
488 uint32_t ssrc_;
489 StreamDataCounters stats_;
490};
491
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000492TEST_F(ReceiveStatisticsTest, RtpCallbacks) {
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000493 RtpTestCallback callback;
Niels Möller12ebfa62019-08-06 16:04:12 +0200494 receive_statistics_ = ReceiveStatistics::Create(&clock_, &callback);
Niels Möller5304a322018-08-27 13:27:05 +0200495 receive_statistics_->EnableRetransmitDetection(kSsrc1, true);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000496
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000497 const size_t kHeaderLength = 20;
498 const size_t kPaddingLength = 9;
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000499
Niels Möller1f3206c2018-09-14 08:26:32 +0200500 // One packet with payload size kPacketSize1.
501 RtpPacketReceived packet1 =
502 CreateRtpPacket(kSsrc1, kHeaderLength, kPacketSize1, 0);
503 receive_statistics_->OnRtpPacket(packet1);
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000504 StreamDataCounters expected;
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000505 expected.transmitted.payload_bytes = kPacketSize1;
506 expected.transmitted.header_bytes = kHeaderLength;
507 expected.transmitted.padding_bytes = 0;
508 expected.transmitted.packets = 1;
509 expected.retransmitted.payload_bytes = 0;
510 expected.retransmitted.header_bytes = 0;
511 expected.retransmitted.padding_bytes = 0;
512 expected.retransmitted.packets = 0;
513 expected.fec.packets = 0;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000514 callback.Matches(1, kSsrc1, expected);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000515
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000516 // Another packet of size kPacketSize1 with 9 bytes padding.
Niels Möller1f3206c2018-09-14 08:26:32 +0200517 RtpPacketReceived packet2 =
518 CreateRtpPacket(kSsrc1, kHeaderLength, kPacketSize1, 9);
519 packet2.SetSequenceNumber(packet1.SequenceNumber() + 1);
520 clock_.AdvanceTimeMilliseconds(5);
521 receive_statistics_->OnRtpPacket(packet2);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000522 expected.transmitted.payload_bytes = kPacketSize1 * 2;
523 expected.transmitted.header_bytes = kHeaderLength * 2;
524 expected.transmitted.padding_bytes = kPaddingLength;
525 expected.transmitted.packets = 2;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000526 callback.Matches(2, kSsrc1, expected);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000527
528 clock_.AdvanceTimeMilliseconds(5);
529 // Retransmit last packet.
Niels Möller1f3206c2018-09-14 08:26:32 +0200530 receive_statistics_->OnRtpPacket(packet2);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000531 expected.transmitted.payload_bytes = kPacketSize1 * 3;
532 expected.transmitted.header_bytes = kHeaderLength * 3;
533 expected.transmitted.padding_bytes = kPaddingLength * 2;
534 expected.transmitted.packets = 3;
535 expected.retransmitted.payload_bytes = kPacketSize1;
536 expected.retransmitted.header_bytes = kHeaderLength;
537 expected.retransmitted.padding_bytes = kPaddingLength;
538 expected.retransmitted.packets = 1;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000539 callback.Matches(3, kSsrc1, expected);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000540
asapersson@webrtc.org273fbbb2015-01-27 12:17:29 +0000541 // One FEC packet.
Niels Möller1f3206c2018-09-14 08:26:32 +0200542 packet1.SetSequenceNumber(packet2.SequenceNumber() + 1);
543 clock_.AdvanceTimeMilliseconds(5);
544 receive_statistics_->OnRtpPacket(packet1);
545 receive_statistics_->FecPacketReceived(packet1);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000546 expected.transmitted.payload_bytes = kPacketSize1 * 4;
547 expected.transmitted.header_bytes = kHeaderLength * 4;
548 expected.transmitted.packets = 4;
asapersson@webrtc.org273fbbb2015-01-27 12:17:29 +0000549 expected.fec.payload_bytes = kPacketSize1;
550 expected.fec.header_bytes = kHeaderLength;
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000551 expected.fec.packets = 1;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000552 callback.Matches(5, kSsrc1, expected);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000553}
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000554
Henrik Boströmcb755b02019-04-02 15:11:48 +0200555TEST_F(ReceiveStatisticsTest, LastPacketReceivedTimestamp) {
556 RtpTestCallback callback;
Niels Möller12ebfa62019-08-06 16:04:12 +0200557 receive_statistics_ = ReceiveStatistics::Create(&clock_, &callback);
Henrik Boströmcb755b02019-04-02 15:11:48 +0200558
559 clock_.AdvanceTimeMilliseconds(42);
560 receive_statistics_->OnRtpPacket(packet1_);
561 EXPECT_EQ(42, callback.stats_.last_packet_received_timestamp_ms);
562
563 clock_.AdvanceTimeMilliseconds(3);
564 receive_statistics_->OnRtpPacket(packet1_);
565 EXPECT_EQ(45, callback.stats_.last_packet_received_timestamp_ms);
566}
567
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000568TEST_F(ReceiveStatisticsTest, RtpCallbacksFecFirst) {
569 RtpTestCallback callback;
Niels Möller12ebfa62019-08-06 16:04:12 +0200570 receive_statistics_ = ReceiveStatistics::Create(&clock_, &callback);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000571
572 const uint32_t kHeaderLength = 20;
Niels Möller1f3206c2018-09-14 08:26:32 +0200573 RtpPacketReceived packet =
574 CreateRtpPacket(kSsrc1, kHeaderLength, kPacketSize1, 0);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000575 // If first packet is FEC, ignore it.
Niels Möller1f3206c2018-09-14 08:26:32 +0200576 receive_statistics_->FecPacketReceived(packet);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000577 EXPECT_EQ(0u, callback.num_calls_);
578
Niels Möller1f3206c2018-09-14 08:26:32 +0200579 receive_statistics_->OnRtpPacket(packet);
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000580 StreamDataCounters expected;
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000581 expected.transmitted.payload_bytes = kPacketSize1;
582 expected.transmitted.header_bytes = kHeaderLength;
583 expected.transmitted.padding_bytes = 0;
584 expected.transmitted.packets = 1;
585 expected.fec.packets = 0;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000586 callback.Matches(1, kSsrc1, expected);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000587
Niels Möller1f3206c2018-09-14 08:26:32 +0200588 receive_statistics_->FecPacketReceived(packet);
asapersson@webrtc.org273fbbb2015-01-27 12:17:29 +0000589 expected.fec.payload_bytes = kPacketSize1;
590 expected.fec.header_bytes = kHeaderLength;
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000591 expected.fec.packets = 1;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000592 callback.Matches(2, kSsrc1, expected);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000593}
Danil Chapovalovd1996b72018-01-16 11:07:18 +0100594
595} // namespace
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000596} // namespace webrtc