blob: 2c6dc3851aef0da8f5c0e569ddb9e540568309eb [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
kwiberg84be5112016-04-27 01:19:58 -070011#include <memory>
Danil Chapovalovd1996b72018-01-16 11:07:18 +010012#include <vector>
kwiberg84be5112016-04-27 01:19:58 -070013
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020014#include "modules/rtp_rtcp/include/receive_statistics.h"
Niels Möller1f3206c2018-09-14 08:26:32 +020015#include "modules/rtp_rtcp/source/rtp_packet_received.h"
16#include "rtc_base/random.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "system_wrappers/include/clock.h"
18#include "test/gmock.h"
19#include "test/gtest.h"
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000020
21namespace webrtc {
Danil Chapovalovd1996b72018-01-16 11:07:18 +010022namespace {
23
24using ::testing::SizeIs;
25using ::testing::UnorderedElementsAre;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000026
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000027const size_t kPacketSize1 = 100;
28const size_t kPacketSize2 = 300;
Danil Chapovalovd1996b72018-01-16 11:07:18 +010029const uint32_t kSsrc1 = 101;
30const uint32_t kSsrc2 = 202;
31const uint32_t kSsrc3 = 203;
32const uint32_t kSsrc4 = 304;
33
Niels Möller1f3206c2018-09-14 08:26:32 +020034RtpPacketReceived CreateRtpPacket(uint32_t ssrc,
35 size_t header_size,
36 size_t payload_size,
37 size_t padding_size) {
38 RtpPacketReceived packet;
39 packet.SetSsrc(ssrc);
40 packet.SetSequenceNumber(100);
41 packet.set_payload_type_frequency(90000);
42 RTC_CHECK_GE(header_size, 12);
43 RTC_CHECK_EQ(header_size % 4, 0);
44 if (header_size > 12) {
45 // Insert csrcs to increase header size.
46 const int num_csrcs = (header_size - 12) / 4;
47 std::vector<uint32_t> csrcs(num_csrcs);
48 packet.SetCsrcs(csrcs);
49 }
50 packet.SetPayloadSize(payload_size);
Danil Chapovalovf7fcaf02018-10-10 14:56:01 +020051 packet.SetPadding(padding_size);
Niels Möller1f3206c2018-09-14 08:26:32 +020052 return packet;
53}
54
55RtpPacketReceived CreateRtpPacket(uint32_t ssrc, size_t packet_size) {
56 return CreateRtpPacket(ssrc, 12, packet_size - 12, 0);
57}
58
59void IncrementSequenceNumber(RtpPacketReceived* packet, uint16_t incr) {
60 packet->SetSequenceNumber(packet->SequenceNumber() + incr);
61}
62
63void IncrementSequenceNumber(RtpPacketReceived* packet) {
64 IncrementSequenceNumber(packet, 1);
65}
66
67void IncrementTimestamp(RtpPacketReceived* packet, uint32_t incr) {
68 packet->SetTimestamp(packet->Timestamp() + incr);
Danil Chapovalovd1996b72018-01-16 11:07:18 +010069}
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000070
71class ReceiveStatisticsTest : public ::testing::Test {
72 public:
Yves Gerey665174f2018-06-19 15:03:05 +020073 ReceiveStatisticsTest()
Danil Chapovalov8ce0d2b2018-11-23 11:03:25 +010074 : clock_(0),
75 receive_statistics_(
76 ReceiveStatistics::Create(&clock_, nullptr, nullptr)) {
Niels Möller1f3206c2018-09-14 08:26:32 +020077 packet1_ = CreateRtpPacket(kSsrc1, kPacketSize1);
78 packet2_ = CreateRtpPacket(kSsrc2, kPacketSize2);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000079 }
80
81 protected:
82 SimulatedClock clock_;
kwiberg84be5112016-04-27 01:19:58 -070083 std::unique_ptr<ReceiveStatistics> receive_statistics_;
Niels Möller1f3206c2018-09-14 08:26:32 +020084 RtpPacketReceived packet1_;
85 RtpPacketReceived packet2_;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000086};
87
88TEST_F(ReceiveStatisticsTest, TwoIncomingSsrcs) {
Niels Möller1f3206c2018-09-14 08:26:32 +020089 receive_statistics_->OnRtpPacket(packet1_);
90 IncrementSequenceNumber(&packet1_);
91 receive_statistics_->OnRtpPacket(packet2_);
92 IncrementSequenceNumber(&packet2_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000093 clock_.AdvanceTimeMilliseconds(100);
Niels Möller1f3206c2018-09-14 08:26:32 +020094 receive_statistics_->OnRtpPacket(packet1_);
95 IncrementSequenceNumber(&packet1_);
96 receive_statistics_->OnRtpPacket(packet2_);
97 IncrementSequenceNumber(&packet2_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000098
99 StreamStatistician* statistician =
100 receive_statistics_->GetStatistician(kSsrc1);
101 ASSERT_TRUE(statistician != NULL);
102 EXPECT_GT(statistician->BitrateReceived(), 0u);
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000103 size_t bytes_received = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000104 uint32_t packets_received = 0;
105 statistician->GetDataCounters(&bytes_received, &packets_received);
106 EXPECT_EQ(200u, bytes_received);
107 EXPECT_EQ(2u, packets_received);
108
Yves Gerey665174f2018-06-19 15:03:05 +0200109 statistician = receive_statistics_->GetStatistician(kSsrc2);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000110 ASSERT_TRUE(statistician != NULL);
111 EXPECT_GT(statistician->BitrateReceived(), 0u);
112 statistician->GetDataCounters(&bytes_received, &packets_received);
113 EXPECT_EQ(600u, bytes_received);
114 EXPECT_EQ(2u, packets_received);
115
Danil Chapovalovc5267d22017-09-18 13:57:19 +0200116 EXPECT_EQ(2u, receive_statistics_->RtcpReportBlocks(3).size());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000117 // Add more incoming packets and verify that they are registered in both
118 // access methods.
Niels Möller1f3206c2018-09-14 08:26:32 +0200119 receive_statistics_->OnRtpPacket(packet1_);
120 IncrementSequenceNumber(&packet1_);
121 receive_statistics_->OnRtpPacket(packet2_);
122 IncrementSequenceNumber(&packet2_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000123
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000124 receive_statistics_->GetStatistician(kSsrc1)->GetDataCounters(
125 &bytes_received, &packets_received);
126 EXPECT_EQ(300u, bytes_received);
127 EXPECT_EQ(3u, packets_received);
128 receive_statistics_->GetStatistician(kSsrc2)->GetDataCounters(
129 &bytes_received, &packets_received);
130 EXPECT_EQ(900u, bytes_received);
131 EXPECT_EQ(3u, packets_received);
132}
133
Danil Chapovalovd1996b72018-01-16 11:07:18 +0100134TEST_F(ReceiveStatisticsTest,
135 RtcpReportBlocksReturnsMaxBlocksWhenThereAreMoreStatisticians) {
Niels Möller1f3206c2018-09-14 08:26:32 +0200136 RtpPacketReceived packet1 = CreateRtpPacket(kSsrc1, kPacketSize1);
137 RtpPacketReceived packet2 = CreateRtpPacket(kSsrc2, kPacketSize1);
138 RtpPacketReceived packet3 = CreateRtpPacket(kSsrc3, kPacketSize1);
139 receive_statistics_->OnRtpPacket(packet1);
140 receive_statistics_->OnRtpPacket(packet2);
141 receive_statistics_->OnRtpPacket(packet3);
Danil Chapovalovd1996b72018-01-16 11:07:18 +0100142
143 EXPECT_THAT(receive_statistics_->RtcpReportBlocks(2), SizeIs(2));
144 EXPECT_THAT(receive_statistics_->RtcpReportBlocks(2), SizeIs(2));
145 EXPECT_THAT(receive_statistics_->RtcpReportBlocks(2), SizeIs(2));
146}
147
148TEST_F(ReceiveStatisticsTest,
149 RtcpReportBlocksReturnsAllObservedSsrcsWithMultipleCalls) {
Niels Möller1f3206c2018-09-14 08:26:32 +0200150 RtpPacketReceived packet1 = CreateRtpPacket(kSsrc1, kPacketSize1);
151 RtpPacketReceived packet2 = CreateRtpPacket(kSsrc2, kPacketSize1);
152 RtpPacketReceived packet3 = CreateRtpPacket(kSsrc3, kPacketSize1);
153 RtpPacketReceived packet4 = CreateRtpPacket(kSsrc4, kPacketSize1);
154 receive_statistics_->OnRtpPacket(packet1);
155 receive_statistics_->OnRtpPacket(packet2);
156 receive_statistics_->OnRtpPacket(packet3);
157 receive_statistics_->OnRtpPacket(packet4);
Danil Chapovalovd1996b72018-01-16 11:07:18 +0100158
159 std::vector<uint32_t> observed_ssrcs;
160 std::vector<rtcp::ReportBlock> report_blocks =
161 receive_statistics_->RtcpReportBlocks(2);
162 ASSERT_THAT(report_blocks, SizeIs(2));
163 observed_ssrcs.push_back(report_blocks[0].source_ssrc());
164 observed_ssrcs.push_back(report_blocks[1].source_ssrc());
165
166 report_blocks = receive_statistics_->RtcpReportBlocks(2);
167 ASSERT_THAT(report_blocks, SizeIs(2));
168 observed_ssrcs.push_back(report_blocks[0].source_ssrc());
169 observed_ssrcs.push_back(report_blocks[1].source_ssrc());
170
171 EXPECT_THAT(observed_ssrcs,
172 UnorderedElementsAre(kSsrc1, kSsrc2, kSsrc3, kSsrc4));
173}
174
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000175TEST_F(ReceiveStatisticsTest, ActiveStatisticians) {
Niels Möller1f3206c2018-09-14 08:26:32 +0200176 receive_statistics_->OnRtpPacket(packet1_);
177 IncrementSequenceNumber(&packet1_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000178 clock_.AdvanceTimeMilliseconds(1000);
Niels Möller1f3206c2018-09-14 08:26:32 +0200179 receive_statistics_->OnRtpPacket(packet2_);
180 IncrementSequenceNumber(&packet2_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000181 // Nothing should time out since only 1000 ms has passed since the first
182 // packet came in.
Danil Chapovalovc5267d22017-09-18 13:57:19 +0200183 EXPECT_EQ(2u, receive_statistics_->RtcpReportBlocks(3).size());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000184
185 clock_.AdvanceTimeMilliseconds(7000);
186 // kSsrc1 should have timed out.
Danil Chapovalovc5267d22017-09-18 13:57:19 +0200187 EXPECT_EQ(1u, receive_statistics_->RtcpReportBlocks(3).size());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000188
189 clock_.AdvanceTimeMilliseconds(1000);
190 // kSsrc2 should have timed out.
Danil Chapovalovc5267d22017-09-18 13:57:19 +0200191 EXPECT_EQ(0u, receive_statistics_->RtcpReportBlocks(3).size());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000192
Niels Möller1f3206c2018-09-14 08:26:32 +0200193 receive_statistics_->OnRtpPacket(packet1_);
194 IncrementSequenceNumber(&packet1_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000195 // kSsrc1 should be active again and the data counters should have survived.
Danil Chapovalovc5267d22017-09-18 13:57:19 +0200196 EXPECT_EQ(1u, receive_statistics_->RtcpReportBlocks(3).size());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000197 StreamStatistician* statistician =
198 receive_statistics_->GetStatistician(kSsrc1);
199 ASSERT_TRUE(statistician != NULL);
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000200 size_t bytes_received = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000201 uint32_t packets_received = 0;
202 statistician->GetDataCounters(&bytes_received, &packets_received);
203 EXPECT_EQ(200u, bytes_received);
204 EXPECT_EQ(2u, packets_received);
205}
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000206
Niels Möller5304a322018-08-27 13:27:05 +0200207TEST_F(ReceiveStatisticsTest,
208 DoesntCreateRtcpReportBlockUntilFirstReceivedPacketForSsrc) {
209 // Creates a statistician object for the ssrc.
210 receive_statistics_->EnableRetransmitDetection(kSsrc1, true);
211 EXPECT_TRUE(receive_statistics_->GetStatistician(kSsrc1) != nullptr);
212 EXPECT_EQ(0u, receive_statistics_->RtcpReportBlocks(3).size());
213 // Receive first packet
Niels Möller1f3206c2018-09-14 08:26:32 +0200214 receive_statistics_->OnRtpPacket(packet1_);
Niels Möller5304a322018-08-27 13:27:05 +0200215 EXPECT_EQ(1u, receive_statistics_->RtcpReportBlocks(3).size());
216}
217
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000218TEST_F(ReceiveStatisticsTest, GetReceiveStreamDataCounters) {
Niels Möller1f3206c2018-09-14 08:26:32 +0200219 receive_statistics_->OnRtpPacket(packet1_);
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000220 StreamStatistician* statistician =
221 receive_statistics_->GetStatistician(kSsrc1);
222 ASSERT_TRUE(statistician != NULL);
223
224 StreamDataCounters counters;
225 statistician->GetReceiveStreamDataCounters(&counters);
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(1u, counters.transmitted.packets);
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000228
Niels Möller1f3206c2018-09-14 08:26:32 +0200229 receive_statistics_->OnRtpPacket(packet1_);
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000230 statistician->GetReceiveStreamDataCounters(&counters);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000231 EXPECT_GT(counters.first_packet_time_ms, -1);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000232 EXPECT_EQ(2u, counters.transmitted.packets);
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000233}
234
Qingsi Wang2370b082018-08-21 14:24:26 -0700235TEST_F(ReceiveStatisticsTest, RtcpCallbacks) {
236 class TestCallback : public RtcpStatisticsCallback {
237 public:
238 TestCallback()
239 : RtcpStatisticsCallback(), num_calls_(0), ssrc_(0), stats_() {}
240 ~TestCallback() override {}
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000241
Qingsi Wang2370b082018-08-21 14:24:26 -0700242 void StatisticsUpdated(const RtcpStatistics& statistics,
243 uint32_t ssrc) override {
244 ssrc_ = ssrc;
245 stats_ = statistics;
246 ++num_calls_;
247 }
248
249 void CNameChanged(const char* cname, uint32_t ssrc) override {}
250
251 uint32_t num_calls_;
252 uint32_t ssrc_;
253 RtcpStatistics stats_;
254 } callback;
255
Danil Chapovalov8ce0d2b2018-11-23 11:03:25 +0100256 receive_statistics_ = ReceiveStatistics::Create(&clock_, &callback, nullptr);
Niels Möller5304a322018-08-27 13:27:05 +0200257 receive_statistics_->EnableRetransmitDetection(kSsrc1, true);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000258
259 // Add some arbitrary data, with loss and jitter.
Niels Möller1f3206c2018-09-14 08:26:32 +0200260 packet1_.SetSequenceNumber(1);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000261 clock_.AdvanceTimeMilliseconds(7);
Niels Möller1f3206c2018-09-14 08:26:32 +0200262 IncrementTimestamp(&packet1_, 3);
263 receive_statistics_->OnRtpPacket(packet1_);
264 IncrementSequenceNumber(&packet1_, 2);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000265 clock_.AdvanceTimeMilliseconds(9);
Niels Möller1f3206c2018-09-14 08:26:32 +0200266 IncrementTimestamp(&packet1_, 9);
267 receive_statistics_->OnRtpPacket(packet1_);
268 IncrementSequenceNumber(&packet1_, -1);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000269 clock_.AdvanceTimeMilliseconds(13);
Niels Möller1f3206c2018-09-14 08:26:32 +0200270 IncrementTimestamp(&packet1_, 47);
271 receive_statistics_->OnRtpPacket(packet1_);
272 IncrementSequenceNumber(&packet1_, 3);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000273 clock_.AdvanceTimeMilliseconds(11);
Niels Möller1f3206c2018-09-14 08:26:32 +0200274 IncrementTimestamp(&packet1_, 17);
275 receive_statistics_->OnRtpPacket(packet1_);
276 IncrementSequenceNumber(&packet1_);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000277
Qingsi Wang2370b082018-08-21 14:24:26 -0700278 EXPECT_EQ(0u, callback.num_calls_);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000279
Qingsi Wang2370b082018-08-21 14:24:26 -0700280 // Call GetStatistics, simulating a timed rtcp sender thread.
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000281 RtcpStatistics statistics;
Qingsi Wang2370b082018-08-21 14:24:26 -0700282 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
283 true);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000284
Qingsi Wang2370b082018-08-21 14:24:26 -0700285 EXPECT_EQ(1u, callback.num_calls_);
286 EXPECT_EQ(callback.ssrc_, kSsrc1);
287 EXPECT_EQ(statistics.packets_lost, callback.stats_.packets_lost);
288 EXPECT_EQ(statistics.extended_highest_sequence_number,
289 callback.stats_.extended_highest_sequence_number);
290 EXPECT_EQ(statistics.fraction_lost, callback.stats_.fraction_lost);
291 EXPECT_EQ(statistics.jitter, callback.stats_.jitter);
292 EXPECT_EQ(51, statistics.fraction_lost);
Harald Alvestrandc7c41912017-12-08 09:59:34 +0100293 EXPECT_EQ(1, statistics.packets_lost);
Qingsi Wang2370b082018-08-21 14:24:26 -0700294 EXPECT_EQ(5u, statistics.extended_highest_sequence_number);
Niels Möller5304a322018-08-27 13:27:05 +0200295 EXPECT_EQ(177u, statistics.jitter);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000296}
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000297
Danil Chapovalovb438b5a2018-12-05 14:55:46 +0000298TEST_F(ReceiveStatisticsTest, SimpleLossComputation) {
299 packet1_.SetSequenceNumber(1);
300 receive_statistics_->OnRtpPacket(packet1_);
301 packet1_.SetSequenceNumber(3);
302 receive_statistics_->OnRtpPacket(packet1_);
303 packet1_.SetSequenceNumber(4);
304 receive_statistics_->OnRtpPacket(packet1_);
305 packet1_.SetSequenceNumber(5);
306 receive_statistics_->OnRtpPacket(packet1_);
307
308 RtcpStatistics statistics;
309 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
310 true);
311 // 20% = 51/255.
312 EXPECT_EQ(51u, statistics.fraction_lost);
313 EXPECT_EQ(1, statistics.packets_lost);
314}
315
316TEST_F(ReceiveStatisticsTest, LossComputationWithReordering) {
317 packet1_.SetSequenceNumber(1);
318 receive_statistics_->OnRtpPacket(packet1_);
319 packet1_.SetSequenceNumber(3);
320 receive_statistics_->OnRtpPacket(packet1_);
321 packet1_.SetSequenceNumber(2);
322 receive_statistics_->OnRtpPacket(packet1_);
323 packet1_.SetSequenceNumber(5);
324 receive_statistics_->OnRtpPacket(packet1_);
325
326 RtcpStatistics statistics;
327 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
328 true);
329 // 20% = 51/255.
330 EXPECT_EQ(51u, statistics.fraction_lost);
331 EXPECT_EQ(1, statistics.packets_lost);
332}
333
334TEST_F(ReceiveStatisticsTest, LossComputationWithDuplicates) {
335 // Lose 2 packets, but also receive 1 duplicate. Should actually count as
336 // only 1 packet being lost.
337 packet1_.SetSequenceNumber(1);
338 receive_statistics_->OnRtpPacket(packet1_);
339 packet1_.SetSequenceNumber(4);
340 receive_statistics_->OnRtpPacket(packet1_);
341 packet1_.SetSequenceNumber(4);
342 receive_statistics_->OnRtpPacket(packet1_);
343 packet1_.SetSequenceNumber(5);
344 receive_statistics_->OnRtpPacket(packet1_);
345
346 RtcpStatistics statistics;
347 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
348 true);
349 // 20% = 51/255.
350 EXPECT_EQ(51u, statistics.fraction_lost);
351 EXPECT_EQ(1, statistics.packets_lost);
352}
353
354TEST_F(ReceiveStatisticsTest, LossComputationWithSequenceNumberWrapping) {
355 // First, test loss computation over a period that included a sequence number
356 // rollover.
357 packet1_.SetSequenceNumber(0xfffd);
358 receive_statistics_->OnRtpPacket(packet1_);
359 packet1_.SetSequenceNumber(0);
360 receive_statistics_->OnRtpPacket(packet1_);
361 packet1_.SetSequenceNumber(0xfffe);
362 receive_statistics_->OnRtpPacket(packet1_);
363 packet1_.SetSequenceNumber(1);
364 receive_statistics_->OnRtpPacket(packet1_);
365
366 // Only one packet was actually lost, 0xffff.
367 RtcpStatistics statistics;
368 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
369 true);
370 // 20% = 51/255.
371 EXPECT_EQ(51u, statistics.fraction_lost);
372 EXPECT_EQ(1, statistics.packets_lost);
373
374 // Now test losing one packet *after* the rollover.
375 packet1_.SetSequenceNumber(3);
376 receive_statistics_->OnRtpPacket(packet1_);
377 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
378 true);
379 // 50% = 127/255.
380 EXPECT_EQ(127u, statistics.fraction_lost);
381 EXPECT_EQ(2, statistics.packets_lost);
382}
383
384TEST_F(ReceiveStatisticsTest, StreamRestartDoesntCountAsLoss) {
385 RtcpStatistics statistics;
386 receive_statistics_->SetMaxReorderingThreshold(200);
387
388 packet1_.SetSequenceNumber(0);
389 receive_statistics_->OnRtpPacket(packet1_);
390 packet1_.SetSequenceNumber(1);
391 receive_statistics_->OnRtpPacket(packet1_);
392
393 packet1_.SetSequenceNumber(400);
394 receive_statistics_->OnRtpPacket(packet1_);
395 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
396 true);
397 EXPECT_EQ(0, statistics.fraction_lost);
398 EXPECT_EQ(0, statistics.packets_lost);
399
400 packet1_.SetSequenceNumber(401);
401 receive_statistics_->OnRtpPacket(packet1_);
402 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
403 true);
404 EXPECT_EQ(0, statistics.fraction_lost);
405 EXPECT_EQ(0, statistics.packets_lost);
406}
407
408TEST_F(ReceiveStatisticsTest, CountsLossAfterStreamRestart) {
409 RtcpStatistics statistics;
410 receive_statistics_->SetMaxReorderingThreshold(200);
411
412 packet1_.SetSequenceNumber(0);
413 receive_statistics_->OnRtpPacket(packet1_);
414 packet1_.SetSequenceNumber(1);
415 receive_statistics_->OnRtpPacket(packet1_);
416
417 packet1_.SetSequenceNumber(400);
418 receive_statistics_->OnRtpPacket(packet1_);
419 packet1_.SetSequenceNumber(401);
420 receive_statistics_->OnRtpPacket(packet1_);
421 packet1_.SetSequenceNumber(403);
422 receive_statistics_->OnRtpPacket(packet1_);
423
424 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
425 true);
426 EXPECT_EQ(1, statistics.packets_lost);
427}
428
429TEST_F(ReceiveStatisticsTest, StreamCanRestartAtSequenceNumberWrapAround) {
430 RtcpStatistics statistics;
431 receive_statistics_->SetMaxReorderingThreshold(200);
432
433 packet1_.SetSequenceNumber(0xffff - 401);
434 receive_statistics_->OnRtpPacket(packet1_);
435 packet1_.SetSequenceNumber(0xffff - 400);
436 receive_statistics_->OnRtpPacket(packet1_);
437
438 packet1_.SetSequenceNumber(0xffff);
439 receive_statistics_->OnRtpPacket(packet1_);
440 packet1_.SetSequenceNumber(0);
441 receive_statistics_->OnRtpPacket(packet1_);
442 packet1_.SetSequenceNumber(2);
443 receive_statistics_->OnRtpPacket(packet1_);
444
445 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
446 true);
447 EXPECT_EQ(1, statistics.packets_lost);
448}
449
450TEST_F(ReceiveStatisticsTest, StreamRestartNeedsTwoConsecutivePackets) {
451 RtcpStatistics statistics;
452 receive_statistics_->SetMaxReorderingThreshold(200);
453
454 packet1_.SetSequenceNumber(400);
455 receive_statistics_->OnRtpPacket(packet1_);
456 packet1_.SetSequenceNumber(401);
457 receive_statistics_->OnRtpPacket(packet1_);
458
459 packet1_.SetSequenceNumber(1);
460 receive_statistics_->OnRtpPacket(packet1_);
461 packet1_.SetSequenceNumber(3);
462 receive_statistics_->OnRtpPacket(packet1_);
463 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
464 true);
465 EXPECT_EQ(401u, statistics.extended_highest_sequence_number);
466
467 packet1_.SetSequenceNumber(4);
468 receive_statistics_->OnRtpPacket(packet1_);
469 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
470 true);
471 EXPECT_EQ(4u, statistics.extended_highest_sequence_number);
472}
473
474TEST_F(ReceiveStatisticsTest, WrapsAroundExtendedHighestSequenceNumber) {
475 RtcpStatistics statistics;
476 packet1_.SetSequenceNumber(0xffff);
477 receive_statistics_->OnRtpPacket(packet1_);
478 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
479 true);
480 EXPECT_EQ(0xffffu, statistics.extended_highest_sequence_number);
481
482 // Wrap around.
483 packet1_.SetSequenceNumber(1);
484 receive_statistics_->OnRtpPacket(packet1_);
485 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
486 true);
487 EXPECT_EQ(0x10001u, statistics.extended_highest_sequence_number);
488
489 // Should be treated as out of order; shouldn't increment highest extended
490 // sequence number.
491 packet1_.SetSequenceNumber(0x10000 - 6);
492 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
493 true);
494 EXPECT_EQ(0x10001u, statistics.extended_highest_sequence_number);
495
496 // Receive a couple packets then wrap around again.
497 receive_statistics_->SetMaxReorderingThreshold(200);
498 for (int i = 10; i < 0xffff; i += 150) {
499 packet1_.SetSequenceNumber(i);
500 receive_statistics_->OnRtpPacket(packet1_);
501 }
502 packet1_.SetSequenceNumber(1);
503 receive_statistics_->OnRtpPacket(packet1_);
504 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
505 true);
506 EXPECT_EQ(0x20001u, statistics.extended_highest_sequence_number);
507}
508
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000509class RtpTestCallback : public StreamDataCountersCallback {
510 public:
511 RtpTestCallback()
512 : StreamDataCountersCallback(), num_calls_(0), ssrc_(0), stats_() {}
Danil Chapovalovdd7e2842018-03-09 15:37:03 +0000513 ~RtpTestCallback() override = default;
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000514
Danil Chapovalovdd7e2842018-03-09 15:37:03 +0000515 void DataCountersUpdated(const StreamDataCounters& counters,
516 uint32_t ssrc) override {
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000517 ssrc_ = ssrc;
518 stats_ = counters;
519 ++num_calls_;
520 }
521
asapersson@webrtc.org44149392015-02-04 08:34:47 +0000522 void MatchPacketCounter(const RtpPacketCounter& expected,
523 const RtpPacketCounter& actual) {
524 EXPECT_EQ(expected.payload_bytes, actual.payload_bytes);
525 EXPECT_EQ(expected.header_bytes, actual.header_bytes);
526 EXPECT_EQ(expected.padding_bytes, actual.padding_bytes);
527 EXPECT_EQ(expected.packets, actual.packets);
528 }
529
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000530 void Matches(uint32_t num_calls,
531 uint32_t ssrc,
532 const StreamDataCounters& expected) {
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000533 EXPECT_EQ(num_calls, num_calls_);
534 EXPECT_EQ(ssrc, ssrc_);
asapersson@webrtc.org44149392015-02-04 08:34:47 +0000535 MatchPacketCounter(expected.transmitted, stats_.transmitted);
536 MatchPacketCounter(expected.retransmitted, stats_.retransmitted);
537 MatchPacketCounter(expected.fec, stats_.fec);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000538 }
539
540 uint32_t num_calls_;
541 uint32_t ssrc_;
542 StreamDataCounters stats_;
543};
544
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000545TEST_F(ReceiveStatisticsTest, RtpCallbacks) {
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000546 RtpTestCallback callback;
Danil Chapovalov8ce0d2b2018-11-23 11:03:25 +0100547 receive_statistics_ = ReceiveStatistics::Create(&clock_, nullptr, &callback);
Niels Möller5304a322018-08-27 13:27:05 +0200548 receive_statistics_->EnableRetransmitDetection(kSsrc1, true);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000549
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000550 const size_t kHeaderLength = 20;
551 const size_t kPaddingLength = 9;
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000552
Niels Möller1f3206c2018-09-14 08:26:32 +0200553 // One packet with payload size kPacketSize1.
554 RtpPacketReceived packet1 =
555 CreateRtpPacket(kSsrc1, kHeaderLength, kPacketSize1, 0);
556 receive_statistics_->OnRtpPacket(packet1);
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000557 StreamDataCounters expected;
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000558 expected.transmitted.payload_bytes = kPacketSize1;
559 expected.transmitted.header_bytes = kHeaderLength;
560 expected.transmitted.padding_bytes = 0;
561 expected.transmitted.packets = 1;
562 expected.retransmitted.payload_bytes = 0;
563 expected.retransmitted.header_bytes = 0;
564 expected.retransmitted.padding_bytes = 0;
565 expected.retransmitted.packets = 0;
566 expected.fec.packets = 0;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000567 callback.Matches(1, kSsrc1, expected);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000568
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000569 // Another packet of size kPacketSize1 with 9 bytes padding.
Niels Möller1f3206c2018-09-14 08:26:32 +0200570 RtpPacketReceived packet2 =
571 CreateRtpPacket(kSsrc1, kHeaderLength, kPacketSize1, 9);
572 packet2.SetSequenceNumber(packet1.SequenceNumber() + 1);
573 clock_.AdvanceTimeMilliseconds(5);
574 receive_statistics_->OnRtpPacket(packet2);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000575 expected.transmitted.payload_bytes = kPacketSize1 * 2;
576 expected.transmitted.header_bytes = kHeaderLength * 2;
577 expected.transmitted.padding_bytes = kPaddingLength;
578 expected.transmitted.packets = 2;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000579 callback.Matches(2, kSsrc1, expected);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000580
581 clock_.AdvanceTimeMilliseconds(5);
582 // Retransmit last packet.
Niels Möller1f3206c2018-09-14 08:26:32 +0200583 receive_statistics_->OnRtpPacket(packet2);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000584 expected.transmitted.payload_bytes = kPacketSize1 * 3;
585 expected.transmitted.header_bytes = kHeaderLength * 3;
586 expected.transmitted.padding_bytes = kPaddingLength * 2;
587 expected.transmitted.packets = 3;
588 expected.retransmitted.payload_bytes = kPacketSize1;
589 expected.retransmitted.header_bytes = kHeaderLength;
590 expected.retransmitted.padding_bytes = kPaddingLength;
591 expected.retransmitted.packets = 1;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000592 callback.Matches(3, kSsrc1, expected);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000593
asapersson@webrtc.org273fbbb2015-01-27 12:17:29 +0000594 // One FEC packet.
Niels Möller1f3206c2018-09-14 08:26:32 +0200595 packet1.SetSequenceNumber(packet2.SequenceNumber() + 1);
596 clock_.AdvanceTimeMilliseconds(5);
597 receive_statistics_->OnRtpPacket(packet1);
598 receive_statistics_->FecPacketReceived(packet1);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000599 expected.transmitted.payload_bytes = kPacketSize1 * 4;
600 expected.transmitted.header_bytes = kHeaderLength * 4;
601 expected.transmitted.packets = 4;
asapersson@webrtc.org273fbbb2015-01-27 12:17:29 +0000602 expected.fec.payload_bytes = kPacketSize1;
603 expected.fec.header_bytes = kHeaderLength;
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000604 expected.fec.packets = 1;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000605 callback.Matches(5, kSsrc1, expected);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000606}
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000607
Henrik Boströmcb755b02019-04-02 15:11:48 +0200608TEST_F(ReceiveStatisticsTest, LastPacketReceivedTimestamp) {
609 RtpTestCallback callback;
610 receive_statistics_ = ReceiveStatistics::Create(&clock_, nullptr, &callback);
611
612 clock_.AdvanceTimeMilliseconds(42);
613 receive_statistics_->OnRtpPacket(packet1_);
614 EXPECT_EQ(42, callback.stats_.last_packet_received_timestamp_ms);
615
616 clock_.AdvanceTimeMilliseconds(3);
617 receive_statistics_->OnRtpPacket(packet1_);
618 EXPECT_EQ(45, callback.stats_.last_packet_received_timestamp_ms);
619}
620
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000621TEST_F(ReceiveStatisticsTest, RtpCallbacksFecFirst) {
622 RtpTestCallback callback;
Danil Chapovalov8ce0d2b2018-11-23 11:03:25 +0100623 receive_statistics_ = ReceiveStatistics::Create(&clock_, nullptr, &callback);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000624
625 const uint32_t kHeaderLength = 20;
Niels Möller1f3206c2018-09-14 08:26:32 +0200626 RtpPacketReceived packet =
627 CreateRtpPacket(kSsrc1, kHeaderLength, kPacketSize1, 0);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000628 // If first packet is FEC, ignore it.
Niels Möller1f3206c2018-09-14 08:26:32 +0200629 receive_statistics_->FecPacketReceived(packet);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000630 EXPECT_EQ(0u, callback.num_calls_);
631
Niels Möller1f3206c2018-09-14 08:26:32 +0200632 receive_statistics_->OnRtpPacket(packet);
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000633 StreamDataCounters expected;
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000634 expected.transmitted.payload_bytes = kPacketSize1;
635 expected.transmitted.header_bytes = kHeaderLength;
636 expected.transmitted.padding_bytes = 0;
637 expected.transmitted.packets = 1;
638 expected.fec.packets = 0;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000639 callback.Matches(1, kSsrc1, expected);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000640
Niels Möller1f3206c2018-09-14 08:26:32 +0200641 receive_statistics_->FecPacketReceived(packet);
asapersson@webrtc.org273fbbb2015-01-27 12:17:29 +0000642 expected.fec.payload_bytes = kPacketSize1;
643 expected.fec.header_bytes = kHeaderLength;
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000644 expected.fec.packets = 1;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000645 callback.Matches(2, kSsrc1, expected);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000646}
Danil Chapovalovd1996b72018-01-16 11:07:18 +0100647
648} // namespace
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000649} // namespace webrtc