blob: eedcf46df7c2a5cd9f9c0e8e55e843304bb7daae [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"
15#include "system_wrappers/include/clock.h"
16#include "test/gmock.h"
17#include "test/gtest.h"
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000018
19namespace webrtc {
Danil Chapovalovd1996b72018-01-16 11:07:18 +010020namespace {
21
Taylor Brandstetter84916932018-06-25 15:50:26 -070022using ::testing::_;
23using ::testing::SaveArg;
Danil Chapovalovd1996b72018-01-16 11:07:18 +010024using ::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
34RTPHeader CreateRtpHeader(uint32_t ssrc) {
35 RTPHeader header;
36 memset(&header, 0, sizeof(header));
37 header.ssrc = ssrc;
38 header.sequenceNumber = 100;
39 return header;
40}
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000041
42class ReceiveStatisticsTest : public ::testing::Test {
43 public:
Yves Gerey665174f2018-06-19 15:03:05 +020044 ReceiveStatisticsTest()
45 : clock_(0), receive_statistics_(ReceiveStatistics::Create(&clock_)) {
Danil Chapovalovd1996b72018-01-16 11:07:18 +010046 header1_ = CreateRtpHeader(kSsrc1);
47 header2_ = CreateRtpHeader(kSsrc2);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000048 }
49
50 protected:
51 SimulatedClock clock_;
kwiberg84be5112016-04-27 01:19:58 -070052 std::unique_ptr<ReceiveStatistics> receive_statistics_;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000053 RTPHeader header1_;
54 RTPHeader header2_;
55};
56
57TEST_F(ReceiveStatisticsTest, TwoIncomingSsrcs) {
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +000058 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000059 ++header1_.sequenceNumber;
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +000060 receive_statistics_->IncomingPacket(header2_, kPacketSize2, false);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000061 ++header2_.sequenceNumber;
62 clock_.AdvanceTimeMilliseconds(100);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +000063 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000064 ++header1_.sequenceNumber;
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +000065 receive_statistics_->IncomingPacket(header2_, kPacketSize2, false);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000066 ++header2_.sequenceNumber;
67
68 StreamStatistician* statistician =
69 receive_statistics_->GetStatistician(kSsrc1);
70 ASSERT_TRUE(statistician != NULL);
71 EXPECT_GT(statistician->BitrateReceived(), 0u);
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000072 size_t bytes_received = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000073 uint32_t packets_received = 0;
74 statistician->GetDataCounters(&bytes_received, &packets_received);
75 EXPECT_EQ(200u, bytes_received);
76 EXPECT_EQ(2u, packets_received);
77
Yves Gerey665174f2018-06-19 15:03:05 +020078 statistician = receive_statistics_->GetStatistician(kSsrc2);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000079 ASSERT_TRUE(statistician != NULL);
80 EXPECT_GT(statistician->BitrateReceived(), 0u);
81 statistician->GetDataCounters(&bytes_received, &packets_received);
82 EXPECT_EQ(600u, bytes_received);
83 EXPECT_EQ(2u, packets_received);
84
Danil Chapovalovc5267d22017-09-18 13:57:19 +020085 EXPECT_EQ(2u, receive_statistics_->RtcpReportBlocks(3).size());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000086 // Add more incoming packets and verify that they are registered in both
87 // access methods.
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +000088 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000089 ++header1_.sequenceNumber;
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +000090 receive_statistics_->IncomingPacket(header2_, kPacketSize2, false);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000091 ++header2_.sequenceNumber;
92
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000093 receive_statistics_->GetStatistician(kSsrc1)->GetDataCounters(
94 &bytes_received, &packets_received);
95 EXPECT_EQ(300u, bytes_received);
96 EXPECT_EQ(3u, packets_received);
97 receive_statistics_->GetStatistician(kSsrc2)->GetDataCounters(
98 &bytes_received, &packets_received);
99 EXPECT_EQ(900u, bytes_received);
100 EXPECT_EQ(3u, packets_received);
101}
102
Danil Chapovalovd1996b72018-01-16 11:07:18 +0100103TEST_F(ReceiveStatisticsTest,
104 RtcpReportBlocksReturnsMaxBlocksWhenThereAreMoreStatisticians) {
105 RTPHeader header1 = CreateRtpHeader(kSsrc1);
106 RTPHeader header2 = CreateRtpHeader(kSsrc2);
107 RTPHeader header3 = CreateRtpHeader(kSsrc3);
108 receive_statistics_->IncomingPacket(header1, kPacketSize1, false);
109 receive_statistics_->IncomingPacket(header2, kPacketSize1, false);
110 receive_statistics_->IncomingPacket(header3, kPacketSize1, false);
111
112 EXPECT_THAT(receive_statistics_->RtcpReportBlocks(2), SizeIs(2));
113 EXPECT_THAT(receive_statistics_->RtcpReportBlocks(2), SizeIs(2));
114 EXPECT_THAT(receive_statistics_->RtcpReportBlocks(2), SizeIs(2));
115}
116
117TEST_F(ReceiveStatisticsTest,
118 RtcpReportBlocksReturnsAllObservedSsrcsWithMultipleCalls) {
119 RTPHeader header1 = CreateRtpHeader(kSsrc1);
120 RTPHeader header2 = CreateRtpHeader(kSsrc2);
121 RTPHeader header3 = CreateRtpHeader(kSsrc3);
122 RTPHeader header4 = CreateRtpHeader(kSsrc4);
123 receive_statistics_->IncomingPacket(header1, kPacketSize1, false);
124 receive_statistics_->IncomingPacket(header2, kPacketSize1, false);
125 receive_statistics_->IncomingPacket(header3, kPacketSize1, false);
126 receive_statistics_->IncomingPacket(header4, kPacketSize1, false);
127
128 std::vector<uint32_t> observed_ssrcs;
129 std::vector<rtcp::ReportBlock> report_blocks =
130 receive_statistics_->RtcpReportBlocks(2);
131 ASSERT_THAT(report_blocks, SizeIs(2));
132 observed_ssrcs.push_back(report_blocks[0].source_ssrc());
133 observed_ssrcs.push_back(report_blocks[1].source_ssrc());
134
135 report_blocks = receive_statistics_->RtcpReportBlocks(2);
136 ASSERT_THAT(report_blocks, SizeIs(2));
137 observed_ssrcs.push_back(report_blocks[0].source_ssrc());
138 observed_ssrcs.push_back(report_blocks[1].source_ssrc());
139
140 EXPECT_THAT(observed_ssrcs,
141 UnorderedElementsAre(kSsrc1, kSsrc2, kSsrc3, kSsrc4));
142}
143
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000144TEST_F(ReceiveStatisticsTest, ActiveStatisticians) {
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000145 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000146 ++header1_.sequenceNumber;
147 clock_.AdvanceTimeMilliseconds(1000);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000148 receive_statistics_->IncomingPacket(header2_, kPacketSize2, false);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000149 ++header2_.sequenceNumber;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000150 // Nothing should time out since only 1000 ms has passed since the first
151 // packet came in.
Danil Chapovalovc5267d22017-09-18 13:57:19 +0200152 EXPECT_EQ(2u, receive_statistics_->RtcpReportBlocks(3).size());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000153
154 clock_.AdvanceTimeMilliseconds(7000);
155 // kSsrc1 should have timed out.
Danil Chapovalovc5267d22017-09-18 13:57:19 +0200156 EXPECT_EQ(1u, receive_statistics_->RtcpReportBlocks(3).size());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000157
158 clock_.AdvanceTimeMilliseconds(1000);
159 // kSsrc2 should have timed out.
Danil Chapovalovc5267d22017-09-18 13:57:19 +0200160 EXPECT_EQ(0u, receive_statistics_->RtcpReportBlocks(3).size());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000161
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000162 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000163 ++header1_.sequenceNumber;
164 // kSsrc1 should be active again and the data counters should have survived.
Danil Chapovalovc5267d22017-09-18 13:57:19 +0200165 EXPECT_EQ(1u, receive_statistics_->RtcpReportBlocks(3).size());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000166 StreamStatistician* statistician =
167 receive_statistics_->GetStatistician(kSsrc1);
168 ASSERT_TRUE(statistician != NULL);
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000169 size_t bytes_received = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000170 uint32_t packets_received = 0;
171 statistician->GetDataCounters(&bytes_received, &packets_received);
172 EXPECT_EQ(200u, bytes_received);
173 EXPECT_EQ(2u, packets_received);
174}
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000175
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000176TEST_F(ReceiveStatisticsTest, GetReceiveStreamDataCounters) {
177 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
178 StreamStatistician* statistician =
179 receive_statistics_->GetStatistician(kSsrc1);
180 ASSERT_TRUE(statistician != NULL);
181
182 StreamDataCounters counters;
183 statistician->GetReceiveStreamDataCounters(&counters);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000184 EXPECT_GT(counters.first_packet_time_ms, -1);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000185 EXPECT_EQ(1u, counters.transmitted.packets);
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000186
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000187 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
188 statistician->GetReceiveStreamDataCounters(&counters);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000189 EXPECT_GT(counters.first_packet_time_ms, -1);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000190 EXPECT_EQ(2u, counters.transmitted.packets);
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000191}
192
Taylor Brandstetter84916932018-06-25 15:50:26 -0700193class MockRtcpCallback : public RtcpStatisticsCallback {
194 public:
195 MOCK_METHOD2(StatisticsUpdated,
196 void(const RtcpStatistics& statistics, uint32_t ssrc));
197 MOCK_METHOD2(CNameChanged, void(const char* cname, uint32_t ssrc));
198};
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000199
Taylor Brandstetter84916932018-06-25 15:50:26 -0700200// Test that the RTCP statistics callback is invoked every time a packet is
201// received (so that at the application level, GetStats will return up-to-date
202// stats, not just stats from the last generated RTCP SR or RR).
203TEST_F(ReceiveStatisticsTest,
204 RtcpStatisticsCallbackInvokedForEveryPacketReceived) {
205 MockRtcpCallback callback;
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000206 receive_statistics_->RegisterRtcpStatisticsCallback(&callback);
207
Taylor Brandstetter84916932018-06-25 15:50:26 -0700208 // Just receive the same packet multiple times; doesn't really matter for the
209 // purposes of this test.
210 EXPECT_CALL(callback, StatisticsUpdated(_, _)).Times(3);
211 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
212 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
213 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
214}
215
216// The callback should also be invoked when |fraction_lost| is updated due to
217// GetStatistics being called.
218TEST_F(ReceiveStatisticsTest,
219 RtcpStatisticsCallbackInvokedWhenFractionLostUpdated) {
220 MockRtcpCallback callback;
221 receive_statistics_->RegisterRtcpStatisticsCallback(&callback);
222
223 EXPECT_CALL(callback, StatisticsUpdated(_, _)).Times(2);
224 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
225 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
226
227 // This just returns the current statistics without updating anything, so no
228 // need to invoke the callback.
229 RtcpStatistics statistics;
230 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(
231 &statistics, /*update_fraction_lost=*/false);
232
233 // Update fraction lost, expecting a new callback.
234 EXPECT_CALL(callback, StatisticsUpdated(_, _)).Times(1);
235 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(
236 &statistics, /*update_fraction_lost=*/true);
237}
238
239TEST_F(ReceiveStatisticsTest,
240 RtcpStatisticsCallbackNotInvokedAfterDeregistered) {
241 // Register the callback and receive a couple packets.
242 MockRtcpCallback callback;
243 receive_statistics_->RegisterRtcpStatisticsCallback(&callback);
244 EXPECT_CALL(callback, StatisticsUpdated(_, _)).Times(2);
245 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
246 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
247
248 // Dereigster the callback. Neither receiving a packet nor generating a
249 // report (calling GetStatistics) should result in another callback.
250 receive_statistics_->RegisterRtcpStatisticsCallback(nullptr);
251 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
252 RtcpStatistics statistics;
253 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(
254 &statistics, /*update_fraction_lost=*/true);
255}
256
257// Test that the RtcpStatisticsCallback sees the exact same values as returned
258// from GetStatistics.
259TEST_F(ReceiveStatisticsTest,
260 RtcpStatisticsFromCallbackMatchThoseFromGetStatistics) {
261 MockRtcpCallback callback;
262 RtcpStatistics stats_from_callback;
263 EXPECT_CALL(callback, StatisticsUpdated(_, _))
264 .WillRepeatedly(SaveArg<0>(&stats_from_callback));
265 receive_statistics_->RegisterRtcpStatisticsCallback(&callback);
266
267 // Using units of milliseconds.
268 header1_.payload_type_frequency = 1000;
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000269 // Add some arbitrary data, with loss and jitter.
270 header1_.sequenceNumber = 1;
271 clock_.AdvanceTimeMilliseconds(7);
272 header1_.timestamp += 3;
273 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
274 header1_.sequenceNumber += 2;
275 clock_.AdvanceTimeMilliseconds(9);
276 header1_.timestamp += 9;
277 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
278 --header1_.sequenceNumber;
279 clock_.AdvanceTimeMilliseconds(13);
280 header1_.timestamp += 47;
281 receive_statistics_->IncomingPacket(header1_, kPacketSize1, true);
282 header1_.sequenceNumber += 3;
283 clock_.AdvanceTimeMilliseconds(11);
284 header1_.timestamp += 17;
285 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000286
Taylor Brandstetter84916932018-06-25 15:50:26 -0700287 // The stats from the last callback due to IncomingPacket should match
288 // those returned by GetStatistics afterwards.
289 RtcpStatistics stats_from_getstatistics;
290 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(
291 &stats_from_getstatistics, /*update_fraction_lost=*/false);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000292
Taylor Brandstetter84916932018-06-25 15:50:26 -0700293 EXPECT_EQ(stats_from_getstatistics.packets_lost,
294 stats_from_callback.packets_lost);
295 EXPECT_EQ(stats_from_getstatistics.extended_highest_sequence_number,
296 stats_from_callback.extended_highest_sequence_number);
297 EXPECT_EQ(stats_from_getstatistics.fraction_lost,
298 stats_from_callback.fraction_lost);
299 EXPECT_EQ(stats_from_getstatistics.jitter, stats_from_callback.jitter);
300
301 // Now update fraction lost, and check that we got matching values from the
302 // new callback.
303 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(
304 &stats_from_getstatistics, /*update_fraction_lost=*/true);
305 EXPECT_EQ(stats_from_getstatistics.packets_lost,
306 stats_from_callback.packets_lost);
307 EXPECT_EQ(stats_from_getstatistics.extended_highest_sequence_number,
308 stats_from_callback.extended_highest_sequence_number);
309 EXPECT_EQ(stats_from_getstatistics.fraction_lost,
310 stats_from_callback.fraction_lost);
311 EXPECT_EQ(stats_from_getstatistics.jitter, stats_from_callback.jitter);
312}
313
314// Test that |fraction_lost| is only updated when a report is generated (when
315// GetStatistics is called with |update_fraction_lost| set to true). Meaning
316// that it will always represent a value computed between two RTCP SR or RRs.
317TEST_F(ReceiveStatisticsTest, FractionLostOnlyUpdatedWhenReportGenerated) {
318 MockRtcpCallback callback;
319 RtcpStatistics stats_from_callback;
320 EXPECT_CALL(callback, StatisticsUpdated(_, _))
321 .WillRepeatedly(SaveArg<0>(&stats_from_callback));
322 receive_statistics_->RegisterRtcpStatisticsCallback(&callback);
323
324 // Simulate losing one packet.
325 header1_.sequenceNumber = 1;
326 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
327 header1_.sequenceNumber = 2;
328 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
329 header1_.sequenceNumber = 4;
330 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
331 // Haven't generated a report yet, so |fraction_lost| should still be 0.
332 EXPECT_EQ(0u, stats_from_callback.fraction_lost);
333
334 // Call GetStatistics with |update_fraction_lost| set to false; should be a
335 // no-op.
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000336 RtcpStatistics statistics;
Taylor Brandstetter84916932018-06-25 15:50:26 -0700337 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(
338 &statistics, /*update_fraction_lost=*/false);
339 EXPECT_EQ(0u, stats_from_callback.fraction_lost);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000340
Taylor Brandstetter84916932018-06-25 15:50:26 -0700341 // Call GetStatistics with |update_fraction_lost| set to true, simulating a
342 // report being generated.
343 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(
344 &statistics, /*update_fraction_lost=*/true);
345 // 25% = 63/255.
346 EXPECT_EQ(63u, stats_from_callback.fraction_lost);
347
348 // Lose another packet.
349 header1_.sequenceNumber = 6;
350 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
351 // Should return same value as before since we haven't generated a new report
352 // yet.
353 EXPECT_EQ(63u, stats_from_callback.fraction_lost);
354
355 // Simulate another report being generated.
356 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(
357 &statistics, /*update_fraction_lost=*/true);
358 // 50% = 127/255.
359 EXPECT_EQ(127, stats_from_callback.fraction_lost);
360}
361
362// Simple test for fraction/cumulative loss computation, with only loss, no
363// duplicates or reordering.
364TEST_F(ReceiveStatisticsTest, SimpleLossComputation) {
365 header1_.sequenceNumber = 1;
366 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
367 header1_.sequenceNumber = 3;
368 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
369 header1_.sequenceNumber = 4;
370 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
371 header1_.sequenceNumber = 5;
372 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
373
374 RtcpStatistics statistics;
375 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(
376 &statistics, /*update_fraction_lost=*/true);
377 // 20% = 51/255.
378 EXPECT_EQ(51u, statistics.fraction_lost);
Harald Alvestrandc7c41912017-12-08 09:59:34 +0100379 EXPECT_EQ(1, statistics.packets_lost);
Taylor Brandstetter84916932018-06-25 15:50:26 -0700380}
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000381
Taylor Brandstetter84916932018-06-25 15:50:26 -0700382// Test that fraction/cumulative loss is computed correctly when there's some
383// reordering.
384TEST_F(ReceiveStatisticsTest, LossComputationWithReordering) {
385 header1_.sequenceNumber = 1;
386 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
387 header1_.sequenceNumber = 3;
388 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
389 header1_.sequenceNumber = 2;
390 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
391 header1_.sequenceNumber = 5;
392 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000393
Taylor Brandstetter84916932018-06-25 15:50:26 -0700394 RtcpStatistics statistics;
395 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(
396 &statistics, /*update_fraction_lost=*/true);
397 // 20% = 51/255.
398 EXPECT_EQ(51u, statistics.fraction_lost);
399}
400
401// Somewhat unintuitively, duplicate packets count against lost packets
402// according to RFC3550.
403TEST_F(ReceiveStatisticsTest, LossComputationWithDuplicates) {
404 // Lose 2 packets, but also receive 1 duplicate. Should actually count as
405 // only 1 packet being lost.
406 header1_.sequenceNumber = 1;
407 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
408 header1_.sequenceNumber = 4;
409 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
410 header1_.sequenceNumber = 4;
411 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
412 header1_.sequenceNumber = 5;
413 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
414
415 RtcpStatistics statistics;
416 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(
417 &statistics, /*update_fraction_lost=*/true);
418 // 20% = 51/255.
419 EXPECT_EQ(51u, statistics.fraction_lost);
420 EXPECT_EQ(1, statistics.packets_lost);
421}
422
423// Test that sequence numbers wrapping around doesn't screw up loss
424// computations.
425TEST_F(ReceiveStatisticsTest, LossComputationWithSequenceNumberWrapping) {
426 // First, test loss computation over a period that included a sequence number
427 // rollover.
428 header1_.sequenceNumber = 65533;
429 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
430 header1_.sequenceNumber = 0;
431 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
432 header1_.sequenceNumber = 65534;
433 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
434 header1_.sequenceNumber = 1;
435 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
436
437 // Only one packet was actually lost, 65535.
438 RtcpStatistics statistics;
439 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(
440 &statistics, /*update_fraction_lost=*/true);
441 // 20% = 51/255.
442 EXPECT_EQ(51u, statistics.fraction_lost);
443 EXPECT_EQ(1, statistics.packets_lost);
444
445 // Now test losing one packet *after* the rollover.
446 header1_.sequenceNumber = 3;
447 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
448 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(
449 &statistics, /*update_fraction_lost=*/true);
450 // 50% = 127/255.
451 EXPECT_EQ(127u, statistics.fraction_lost);
452 EXPECT_EQ(2, statistics.packets_lost);
453}
454
455// Somewhat unintuitively, since duplicate packets count against loss, you can
456// actually end up with negative loss. |fraction_lost| should be clamped to
457// zero in this case, since it's signed, while |packets_lost| is signed so it
458// should be negative.
459TEST_F(ReceiveStatisticsTest, NegativeLoss) {
460 // Receive one packet and simulate a report being generated by calling
461 // GetStatistics, to establish a baseline for |fraction_lost|.
462 header1_.sequenceNumber = 1;
463 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
464 RtcpStatistics statistics;
465 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(
466 &statistics, /*update_fraction_lost=*/true);
467
468 // Receive some duplicate packets. Results in "negative" loss, since
469 // "expected packets since last report" is 3 and "received" is 4, and 3 minus
470 // 4 is -1. See RFC3550 Appendix A.3.
471 header1_.sequenceNumber = 4;
472 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
473 header1_.sequenceNumber = 2;
474 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
475 header1_.sequenceNumber = 2;
476 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
477 header1_.sequenceNumber = 2;
478 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
479 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(
480 &statistics, /*update_fraction_lost=*/true);
481 EXPECT_EQ(0u, statistics.fraction_lost);
Sebastian Jansson436d0362018-08-08 14:41:16 +0200482 // TODO(bugs.webrtc.org/9598): Since old WebRTC implementations reads this
483 // value as unsigned we currently limit it to 0.
484 EXPECT_EQ(0, statistics.packets_lost);
Taylor Brandstetter84916932018-06-25 15:50:26 -0700485
486 // Lose 2 packets; now cumulative loss should become positive again.
487 header1_.sequenceNumber = 7;
488 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
489 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(
490 &statistics, /*update_fraction_lost=*/true);
491 // 66% = 170/255.
492 EXPECT_EQ(170u, statistics.fraction_lost);
493 EXPECT_EQ(1, statistics.packets_lost);
494}
495
496// Since cumulative loss is carried in a signed 24-bit field, it should be
497// clamped to 0x7fffff in the positive direction, 0x800000 in the negative
498// direction.
499TEST_F(ReceiveStatisticsTest, PositiveCumulativeLossClamped) {
500 header1_.sequenceNumber = 1;
501 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
502
503 // Lose 2^23 packets, expecting loss to be clamped to 2^23-1.
504 for (int i = 0; i < 0x800000; ++i) {
505 header1_.sequenceNumber = (header1_.sequenceNumber + 2 % 65536);
506 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
507 }
508 RtcpStatistics statistics;
509 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(
510 &statistics, /*update_fraction_lost=*/false);
511 EXPECT_EQ(0x7fffff, statistics.packets_lost);
512}
513
514TEST_F(ReceiveStatisticsTest, NegativeCumulativeLossClamped) {
515 header1_.sequenceNumber = 1;
516 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
517
518 // Receive 2^23+1 duplicate packets (counted as negative loss), expecting
519 // loss to be clamped to -2^23.
520 for (int i = 0; i < 0x800001; ++i) {
521 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
522 }
523 RtcpStatistics statistics;
524 receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(
525 &statistics, /*update_fraction_lost=*/false);
Sebastian Jansson436d0362018-08-08 14:41:16 +0200526 // TODO(bugs.webrtc.org/9598): Since old WebRTC implementations reads this
527 // value as unsigned we currently limit it to 0.
528 EXPECT_EQ(0, statistics.packets_lost);
Taylor Brandstetter84916932018-06-25 15:50:26 -0700529}
530
531// Test that the extended highest sequence number is computed correctly when
532// sequence numbers wrap around or packets are received out of order.
533TEST_F(ReceiveStatisticsTest, ExtendedHighestSequenceNumberComputation) {
534 MockRtcpCallback callback;
535 RtcpStatistics stats_from_callback;
536 EXPECT_CALL(callback, StatisticsUpdated(_, _))
537 .WillRepeatedly(SaveArg<0>(&stats_from_callback));
538 receive_statistics_->RegisterRtcpStatisticsCallback(&callback);
539
540 header1_.sequenceNumber = 65535;
541 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
542 EXPECT_EQ(65535u, stats_from_callback.extended_highest_sequence_number);
543
544 // Wrap around.
545 header1_.sequenceNumber = 1;
546 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
547 EXPECT_EQ(65536u + 1u, stats_from_callback.extended_highest_sequence_number);
548
549 // Should be treated as out of order; shouldn't increment highest extended
550 // sequence number.
551 header1_.sequenceNumber = 65530;
552 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
553 EXPECT_EQ(65536u + 1u, stats_from_callback.extended_highest_sequence_number);
554
555 // Receive a couple packets then wrap around again.
556 // TODO(bugs.webrtc.org/9445): With large jumps like this, RFC3550 suggests
557 // for the receiver to assume the other side restarted, and reset all its
558 // sequence number counters. Why aren't we doing this?
559 header1_.sequenceNumber = 30000;
560 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
561 EXPECT_EQ(65536u + 30000u,
562 stats_from_callback.extended_highest_sequence_number);
563
564 header1_.sequenceNumber = 50000;
565 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
566 EXPECT_EQ(65536u + 50000u,
567 stats_from_callback.extended_highest_sequence_number);
568
569 header1_.sequenceNumber = 10000;
570 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
571 EXPECT_EQ(2 * 65536u + 10000u,
572 stats_from_callback.extended_highest_sequence_number);
573
574 // If a packet is received more than "MaxReorderingThreshold" packets out of
575 // order (defaults to 50), it's assumed to be in order.
576 // TODO(bugs.webrtc.org/9445): RFC3550 would recommend treating this as a
577 // restart as mentioned above.
578 header1_.sequenceNumber = 9900;
579 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
580 EXPECT_EQ(3 * 65536u + 9900u,
581 stats_from_callback.extended_highest_sequence_number);
582}
583
584// Test jitter computation with no loss/reordering/etc.
585TEST_F(ReceiveStatisticsTest, SimpleJitterComputation) {
586 MockRtcpCallback callback;
587 RtcpStatistics stats_from_callback;
588 EXPECT_CALL(callback, StatisticsUpdated(_, _))
589 .WillRepeatedly(SaveArg<0>(&stats_from_callback));
590 receive_statistics_->RegisterRtcpStatisticsCallback(&callback);
591
592 // Using units of milliseconds.
593 header1_.payload_type_frequency = 1000;
594
595 // Regardless of initial timestamps, jitter should start at 0.
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000596 header1_.sequenceNumber = 1;
597 clock_.AdvanceTimeMilliseconds(7);
598 header1_.timestamp += 3;
599 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
Taylor Brandstetter84916932018-06-25 15:50:26 -0700600 EXPECT_EQ(0u, stats_from_callback.jitter);
601
602 // Incrementing timestamps by the same amount shouldn't increase jitter.
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000603 ++header1_.sequenceNumber;
Taylor Brandstetter84916932018-06-25 15:50:26 -0700604 clock_.AdvanceTimeMilliseconds(50);
605 header1_.timestamp += 50;
606 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
607 EXPECT_EQ(0u, stats_from_callback.jitter);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000608
Taylor Brandstetter84916932018-06-25 15:50:26 -0700609 // Difference of 16ms, divided by 16 yields exactly 1.
610 ++header1_.sequenceNumber;
611 clock_.AdvanceTimeMilliseconds(32);
612 header1_.timestamp += 16;
613 receive_statistics_->IncomingPacket(header1_, kPacketSize1, true);
614 EXPECT_EQ(1u, stats_from_callback.jitter);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000615
Taylor Brandstetter84916932018-06-25 15:50:26 -0700616 // (90 + 1 * 15) / 16 = 6.5625; should round down to 6.
617 // TODO(deadbeef): Why don't we round to the nearest integer?
618 ++header1_.sequenceNumber;
619 clock_.AdvanceTimeMilliseconds(10);
620 header1_.timestamp += 100;
621 receive_statistics_->IncomingPacket(header1_, kPacketSize1, true);
622 EXPECT_EQ(6u, stats_from_callback.jitter);
623
624 // (30 + 6.5625 * 15) / 16 = 8.0273; should round down to 8.
625 ++header1_.sequenceNumber;
626 clock_.AdvanceTimeMilliseconds(50);
627 header1_.timestamp += 20;
628 receive_statistics_->IncomingPacket(header1_, kPacketSize1, true);
629 EXPECT_EQ(8u, stats_from_callback.jitter);
630}
631
632// TODO(deadbeef): Why do we do this? It goes against RFC3550, which explicitly
633// says the calculation should be based on order of arrival and packets may not
634// necessarily arrive in sequence.
635TEST_F(ReceiveStatisticsTest, JitterComputationIgnoresReorderedPackets) {
636 MockRtcpCallback callback;
637 RtcpStatistics stats_from_callback;
638 EXPECT_CALL(callback, StatisticsUpdated(_, _))
639 .WillRepeatedly(SaveArg<0>(&stats_from_callback));
640 receive_statistics_->RegisterRtcpStatisticsCallback(&callback);
641
642 // Using units of milliseconds.
643 header1_.payload_type_frequency = 1000;
644
645 // Regardless of initial timestamps, jitter should start at 0.
646 header1_.sequenceNumber = 1;
647 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
648 EXPECT_EQ(0u, stats_from_callback.jitter);
649
650 // This should be ignored, even though there's a difference of 70 here.
651 header1_.sequenceNumber = 0;
652 clock_.AdvanceTimeMilliseconds(50);
653 header1_.timestamp -= 20;
654 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
655 EXPECT_EQ(0u, stats_from_callback.jitter);
656
657 // Relative to the first packet there's a difference of 181ms in arrival
658 // time, 20ms in timestamp, so jitter should be 161/16 = 10.
659 header1_.sequenceNumber = 2;
660 clock_.AdvanceTimeMilliseconds(131);
661 header1_.timestamp += 40;
662 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
663 EXPECT_EQ(10u, stats_from_callback.jitter);
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000664}
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000665
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000666class RtpTestCallback : public StreamDataCountersCallback {
667 public:
668 RtpTestCallback()
669 : StreamDataCountersCallback(), num_calls_(0), ssrc_(0), stats_() {}
Danil Chapovalovdd7e2842018-03-09 15:37:03 +0000670 ~RtpTestCallback() override = default;
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000671
Danil Chapovalovdd7e2842018-03-09 15:37:03 +0000672 void DataCountersUpdated(const StreamDataCounters& counters,
673 uint32_t ssrc) override {
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000674 ssrc_ = ssrc;
675 stats_ = counters;
676 ++num_calls_;
677 }
678
asapersson@webrtc.org44149392015-02-04 08:34:47 +0000679 void MatchPacketCounter(const RtpPacketCounter& expected,
680 const RtpPacketCounter& actual) {
681 EXPECT_EQ(expected.payload_bytes, actual.payload_bytes);
682 EXPECT_EQ(expected.header_bytes, actual.header_bytes);
683 EXPECT_EQ(expected.padding_bytes, actual.padding_bytes);
684 EXPECT_EQ(expected.packets, actual.packets);
685 }
686
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000687 void Matches(uint32_t num_calls,
688 uint32_t ssrc,
689 const StreamDataCounters& expected) {
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000690 EXPECT_EQ(num_calls, num_calls_);
691 EXPECT_EQ(ssrc, ssrc_);
asapersson@webrtc.org44149392015-02-04 08:34:47 +0000692 MatchPacketCounter(expected.transmitted, stats_.transmitted);
693 MatchPacketCounter(expected.retransmitted, stats_.retransmitted);
694 MatchPacketCounter(expected.fec, stats_.fec);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000695 }
696
697 uint32_t num_calls_;
698 uint32_t ssrc_;
699 StreamDataCounters stats_;
700};
701
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000702TEST_F(ReceiveStatisticsTest, RtpCallbacks) {
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000703 RtpTestCallback callback;
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000704 receive_statistics_->RegisterRtpStatisticsCallback(&callback);
705
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000706 const size_t kHeaderLength = 20;
707 const size_t kPaddingLength = 9;
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000708
709 // One packet of size kPacketSize1.
710 header1_.headerLength = kHeaderLength;
Yves Gerey665174f2018-06-19 15:03:05 +0200711 receive_statistics_->IncomingPacket(header1_, kPacketSize1 + kHeaderLength,
712 false);
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000713 StreamDataCounters expected;
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000714 expected.transmitted.payload_bytes = kPacketSize1;
715 expected.transmitted.header_bytes = kHeaderLength;
716 expected.transmitted.padding_bytes = 0;
717 expected.transmitted.packets = 1;
718 expected.retransmitted.payload_bytes = 0;
719 expected.retransmitted.header_bytes = 0;
720 expected.retransmitted.padding_bytes = 0;
721 expected.retransmitted.packets = 0;
722 expected.fec.packets = 0;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000723 callback.Matches(1, kSsrc1, expected);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000724
725 ++header1_.sequenceNumber;
726 clock_.AdvanceTimeMilliseconds(5);
727 header1_.paddingLength = 9;
728 // Another packet of size kPacketSize1 with 9 bytes padding.
729 receive_statistics_->IncomingPacket(
730 header1_, kPacketSize1 + kHeaderLength + kPaddingLength, false);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000731 expected.transmitted.payload_bytes = kPacketSize1 * 2;
732 expected.transmitted.header_bytes = kHeaderLength * 2;
733 expected.transmitted.padding_bytes = kPaddingLength;
734 expected.transmitted.packets = 2;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000735 callback.Matches(2, kSsrc1, expected);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000736
737 clock_.AdvanceTimeMilliseconds(5);
738 // Retransmit last packet.
739 receive_statistics_->IncomingPacket(
740 header1_, kPacketSize1 + kHeaderLength + kPaddingLength, true);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000741 expected.transmitted.payload_bytes = kPacketSize1 * 3;
742 expected.transmitted.header_bytes = kHeaderLength * 3;
743 expected.transmitted.padding_bytes = kPaddingLength * 2;
744 expected.transmitted.packets = 3;
745 expected.retransmitted.payload_bytes = kPacketSize1;
746 expected.retransmitted.header_bytes = kHeaderLength;
747 expected.retransmitted.padding_bytes = kPaddingLength;
748 expected.retransmitted.packets = 1;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000749 callback.Matches(3, kSsrc1, expected);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000750
751 header1_.paddingLength = 0;
752 ++header1_.sequenceNumber;
753 clock_.AdvanceTimeMilliseconds(5);
asapersson@webrtc.org273fbbb2015-01-27 12:17:29 +0000754 // One FEC packet.
Yves Gerey665174f2018-06-19 15:03:05 +0200755 receive_statistics_->IncomingPacket(header1_, kPacketSize1 + kHeaderLength,
756 false);
asapersson@webrtc.org273fbbb2015-01-27 12:17:29 +0000757 receive_statistics_->FecPacketReceived(header1_,
758 kPacketSize1 + kHeaderLength);
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000759 expected.transmitted.payload_bytes = kPacketSize1 * 4;
760 expected.transmitted.header_bytes = kHeaderLength * 4;
761 expected.transmitted.packets = 4;
asapersson@webrtc.org273fbbb2015-01-27 12:17:29 +0000762 expected.fec.payload_bytes = kPacketSize1;
763 expected.fec.header_bytes = kHeaderLength;
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000764 expected.fec.packets = 1;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000765 callback.Matches(5, kSsrc1, expected);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000766
767 receive_statistics_->RegisterRtpStatisticsCallback(NULL);
768
769 // New stats, but callback should not be called.
770 ++header1_.sequenceNumber;
771 clock_.AdvanceTimeMilliseconds(5);
Yves Gerey665174f2018-06-19 15:03:05 +0200772 receive_statistics_->IncomingPacket(header1_, kPacketSize1 + kHeaderLength,
773 true);
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000774 callback.Matches(5, kSsrc1, expected);
sprang@webrtc.org0e932572014-01-23 10:00:39 +0000775}
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000776
777TEST_F(ReceiveStatisticsTest, RtpCallbacksFecFirst) {
778 RtpTestCallback callback;
779 receive_statistics_->RegisterRtpStatisticsCallback(&callback);
780
781 const uint32_t kHeaderLength = 20;
asapersson@webrtc.org273fbbb2015-01-27 12:17:29 +0000782 header1_.headerLength = kHeaderLength;
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000783
784 // If first packet is FEC, ignore it.
asapersson@webrtc.org273fbbb2015-01-27 12:17:29 +0000785 receive_statistics_->FecPacketReceived(header1_,
786 kPacketSize1 + kHeaderLength);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000787 EXPECT_EQ(0u, callback.num_calls_);
788
Yves Gerey665174f2018-06-19 15:03:05 +0200789 receive_statistics_->IncomingPacket(header1_, kPacketSize1 + kHeaderLength,
790 false);
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000791 StreamDataCounters expected;
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000792 expected.transmitted.payload_bytes = kPacketSize1;
793 expected.transmitted.header_bytes = kHeaderLength;
794 expected.transmitted.padding_bytes = 0;
795 expected.transmitted.packets = 1;
796 expected.fec.packets = 0;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000797 callback.Matches(1, kSsrc1, expected);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000798
asapersson@webrtc.org273fbbb2015-01-27 12:17:29 +0000799 receive_statistics_->FecPacketReceived(header1_,
800 kPacketSize1 + kHeaderLength);
801 expected.fec.payload_bytes = kPacketSize1;
802 expected.fec.header_bytes = kHeaderLength;
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +0000803 expected.fec.packets = 1;
asapersson@webrtc.org97d04892014-12-09 09:47:53 +0000804 callback.Matches(2, kSsrc1, expected);
sprang@webrtc.orgc30e9e22014-09-08 08:20:18 +0000805}
Danil Chapovalovd1996b72018-01-16 11:07:18 +0100806
807} // namespace
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000808} // namespace webrtc