blob: 5b522281df9d0eaee9dac1fb7595dae10e3e3816 [file] [log] [blame]
stefan@webrtc.orga20e2d42013-08-21 20:58:211/*
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
11#include "testing/gmock/include/gmock/gmock.h"
12#include "testing/gtest/include/gtest/gtest.h"
kwiberg@webrtc.orgdeb9dae2015-02-26 14:34:5513#include "webrtc/base/scoped_ptr.h"
stefan@webrtc.orga20e2d42013-08-21 20:58:2114#include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h"
Henrik Kjellander78f65d02015-10-28 17:17:4015#include "webrtc/system_wrappers/include/clock.h"
stefan@webrtc.orga20e2d42013-08-21 20:58:2116
17namespace webrtc {
18
pkasting@chromium.org0ab923a2014-11-20 22:28:1419const size_t kPacketSize1 = 100;
20const size_t kPacketSize2 = 300;
stefan@webrtc.orga20e2d42013-08-21 20:58:2121const uint32_t kSsrc1 = 1;
22const uint32_t kSsrc2 = 2;
stefan@webrtc.orga20e2d42013-08-21 20:58:2123
24class ReceiveStatisticsTest : public ::testing::Test {
25 public:
26 ReceiveStatisticsTest() :
27 clock_(0),
28 receive_statistics_(ReceiveStatistics::Create(&clock_)) {
29 memset(&header1_, 0, sizeof(header1_));
30 header1_.ssrc = kSsrc1;
sprang@webrtc.org7d99cd42014-01-23 10:00:3931 header1_.sequenceNumber = 100;
stefan@webrtc.orga20e2d42013-08-21 20:58:2132 memset(&header2_, 0, sizeof(header2_));
33 header2_.ssrc = kSsrc2;
sprang@webrtc.org7d99cd42014-01-23 10:00:3934 header2_.sequenceNumber = 100;
stefan@webrtc.orga20e2d42013-08-21 20:58:2135 }
36
37 protected:
38 SimulatedClock clock_;
kwiberg@webrtc.orgdeb9dae2015-02-26 14:34:5539 rtc::scoped_ptr<ReceiveStatistics> receive_statistics_;
stefan@webrtc.orga20e2d42013-08-21 20:58:2140 RTPHeader header1_;
41 RTPHeader header2_;
42};
43
44TEST_F(ReceiveStatisticsTest, TwoIncomingSsrcs) {
stefan@webrtc.orgdb74c612013-09-06 13:40:1145 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
stefan@webrtc.orga20e2d42013-08-21 20:58:2146 ++header1_.sequenceNumber;
stefan@webrtc.orgdb74c612013-09-06 13:40:1147 receive_statistics_->IncomingPacket(header2_, kPacketSize2, false);
stefan@webrtc.orga20e2d42013-08-21 20:58:2148 ++header2_.sequenceNumber;
49 clock_.AdvanceTimeMilliseconds(100);
stefan@webrtc.orgdb74c612013-09-06 13:40:1150 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
stefan@webrtc.orga20e2d42013-08-21 20:58:2151 ++header1_.sequenceNumber;
stefan@webrtc.orgdb74c612013-09-06 13:40:1152 receive_statistics_->IncomingPacket(header2_, kPacketSize2, false);
stefan@webrtc.orga20e2d42013-08-21 20:58:2153 ++header2_.sequenceNumber;
54
55 StreamStatistician* statistician =
56 receive_statistics_->GetStatistician(kSsrc1);
57 ASSERT_TRUE(statistician != NULL);
58 EXPECT_GT(statistician->BitrateReceived(), 0u);
pkasting@chromium.org0ab923a2014-11-20 22:28:1459 size_t bytes_received = 0;
stefan@webrtc.orga20e2d42013-08-21 20:58:2160 uint32_t packets_received = 0;
61 statistician->GetDataCounters(&bytes_received, &packets_received);
62 EXPECT_EQ(200u, bytes_received);
63 EXPECT_EQ(2u, packets_received);
64
65 statistician =
66 receive_statistics_->GetStatistician(kSsrc2);
67 ASSERT_TRUE(statistician != NULL);
68 EXPECT_GT(statistician->BitrateReceived(), 0u);
69 statistician->GetDataCounters(&bytes_received, &packets_received);
70 EXPECT_EQ(600u, bytes_received);
71 EXPECT_EQ(2u, packets_received);
72
73 StatisticianMap statisticians = receive_statistics_->GetActiveStatisticians();
74 EXPECT_EQ(2u, statisticians.size());
75 // Add more incoming packets and verify that they are registered in both
76 // access methods.
stefan@webrtc.orgdb74c612013-09-06 13:40:1177 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
stefan@webrtc.orga20e2d42013-08-21 20:58:2178 ++header1_.sequenceNumber;
stefan@webrtc.orgdb74c612013-09-06 13:40:1179 receive_statistics_->IncomingPacket(header2_, kPacketSize2, false);
stefan@webrtc.orga20e2d42013-08-21 20:58:2180 ++header2_.sequenceNumber;
81
82 statisticians[kSsrc1]->GetDataCounters(&bytes_received, &packets_received);
83 EXPECT_EQ(300u, bytes_received);
84 EXPECT_EQ(3u, packets_received);
85 statisticians[kSsrc2]->GetDataCounters(&bytes_received, &packets_received);
86 EXPECT_EQ(900u, bytes_received);
87 EXPECT_EQ(3u, packets_received);
88
89 receive_statistics_->GetStatistician(kSsrc1)->GetDataCounters(
90 &bytes_received, &packets_received);
91 EXPECT_EQ(300u, bytes_received);
92 EXPECT_EQ(3u, packets_received);
93 receive_statistics_->GetStatistician(kSsrc2)->GetDataCounters(
94 &bytes_received, &packets_received);
95 EXPECT_EQ(900u, bytes_received);
96 EXPECT_EQ(3u, packets_received);
97}
98
99TEST_F(ReceiveStatisticsTest, ActiveStatisticians) {
stefan@webrtc.orgdb74c612013-09-06 13:40:11100 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
stefan@webrtc.orga20e2d42013-08-21 20:58:21101 ++header1_.sequenceNumber;
102 clock_.AdvanceTimeMilliseconds(1000);
stefan@webrtc.orgdb74c612013-09-06 13:40:11103 receive_statistics_->IncomingPacket(header2_, kPacketSize2, false);
stefan@webrtc.orga20e2d42013-08-21 20:58:21104 ++header2_.sequenceNumber;
105 StatisticianMap statisticians = receive_statistics_->GetActiveStatisticians();
106 // Nothing should time out since only 1000 ms has passed since the first
107 // packet came in.
108 EXPECT_EQ(2u, statisticians.size());
109
110 clock_.AdvanceTimeMilliseconds(7000);
111 // kSsrc1 should have timed out.
112 statisticians = receive_statistics_->GetActiveStatisticians();
113 EXPECT_EQ(1u, statisticians.size());
114
115 clock_.AdvanceTimeMilliseconds(1000);
116 // kSsrc2 should have timed out.
117 statisticians = receive_statistics_->GetActiveStatisticians();
118 EXPECT_EQ(0u, statisticians.size());
119
stefan@webrtc.orgdb74c612013-09-06 13:40:11120 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
stefan@webrtc.orga20e2d42013-08-21 20:58:21121 ++header1_.sequenceNumber;
122 // kSsrc1 should be active again and the data counters should have survived.
123 statisticians = receive_statistics_->GetActiveStatisticians();
124 EXPECT_EQ(1u, statisticians.size());
125 StreamStatistician* statistician =
126 receive_statistics_->GetStatistician(kSsrc1);
127 ASSERT_TRUE(statistician != NULL);
pkasting@chromium.org0ab923a2014-11-20 22:28:14128 size_t bytes_received = 0;
stefan@webrtc.orga20e2d42013-08-21 20:58:21129 uint32_t packets_received = 0;
130 statistician->GetDataCounters(&bytes_received, &packets_received);
131 EXPECT_EQ(200u, bytes_received);
132 EXPECT_EQ(2u, packets_received);
133}
sprang@webrtc.org4f1f5fa2013-12-19 13:26:02134
asapersson@webrtc.org96568c22014-12-09 09:47:53135TEST_F(ReceiveStatisticsTest, GetReceiveStreamDataCounters) {
136 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
137 StreamStatistician* statistician =
138 receive_statistics_->GetStatistician(kSsrc1);
139 ASSERT_TRUE(statistician != NULL);
140
141 StreamDataCounters counters;
142 statistician->GetReceiveStreamDataCounters(&counters);
asapersson@webrtc.orgc76c5532014-12-16 12:03:11143 EXPECT_GT(counters.first_packet_time_ms, -1);
asapersson@webrtc.org96763da2015-01-22 09:39:59144 EXPECT_EQ(1u, counters.transmitted.packets);
asapersson@webrtc.org96568c22014-12-09 09:47:53145
asapersson@webrtc.org96568c22014-12-09 09:47:53146 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
147 statistician->GetReceiveStreamDataCounters(&counters);
asapersson@webrtc.orgc76c5532014-12-16 12:03:11148 EXPECT_GT(counters.first_packet_time_ms, -1);
asapersson@webrtc.org96763da2015-01-22 09:39:59149 EXPECT_EQ(2u, counters.transmitted.packets);
asapersson@webrtc.org96568c22014-12-09 09:47:53150}
151
sprang@webrtc.org7d99cd42014-01-23 10:00:39152TEST_F(ReceiveStatisticsTest, RtcpCallbacks) {
sprang@webrtc.org4f1f5fa2013-12-19 13:26:02153 class TestCallback : public RtcpStatisticsCallback {
154 public:
155 TestCallback()
156 : RtcpStatisticsCallback(), num_calls_(0), ssrc_(0), stats_() {}
157 virtual ~TestCallback() {}
158
159 virtual void StatisticsUpdated(const RtcpStatistics& statistics,
160 uint32_t ssrc) {
161 ssrc_ = ssrc;
162 stats_ = statistics;
163 ++num_calls_;
164 }
165
kjellander@webrtc.org860ac532015-03-04 12:58:35166 void CNameChanged(const char* cname, uint32_t ssrc) override {}
pbos@webrtc.org1a36f782014-12-18 13:50:16167
sprang@webrtc.org4f1f5fa2013-12-19 13:26:02168 uint32_t num_calls_;
169 uint32_t ssrc_;
170 RtcpStatistics stats_;
171 } callback;
172
173 receive_statistics_->RegisterRtcpStatisticsCallback(&callback);
174
175 // Add some arbitrary data, with loss and jitter.
176 header1_.sequenceNumber = 1;
177 clock_.AdvanceTimeMilliseconds(7);
178 header1_.timestamp += 3;
179 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
180 header1_.sequenceNumber += 2;
181 clock_.AdvanceTimeMilliseconds(9);
182 header1_.timestamp += 9;
183 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
184 --header1_.sequenceNumber;
185 clock_.AdvanceTimeMilliseconds(13);
186 header1_.timestamp += 47;
187 receive_statistics_->IncomingPacket(header1_, kPacketSize1, true);
188 header1_.sequenceNumber += 3;
189 clock_.AdvanceTimeMilliseconds(11);
190 header1_.timestamp += 17;
191 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
192 ++header1_.sequenceNumber;
193
194 EXPECT_EQ(0u, callback.num_calls_);
195
196 // Call GetStatistics, simulating a timed rtcp sender thread.
197 RtcpStatistics statistics;
198 receive_statistics_->GetStatistician(kSsrc1)
199 ->GetStatistics(&statistics, true);
200
201 EXPECT_EQ(1u, callback.num_calls_);
202 EXPECT_EQ(callback.ssrc_, kSsrc1);
203 EXPECT_EQ(statistics.cumulative_lost, callback.stats_.cumulative_lost);
204 EXPECT_EQ(statistics.extended_max_sequence_number,
205 callback.stats_.extended_max_sequence_number);
206 EXPECT_EQ(statistics.fraction_lost, callback.stats_.fraction_lost);
207 EXPECT_EQ(statistics.jitter, callback.stats_.jitter);
sprang@webrtc.org7d99cd42014-01-23 10:00:39208 EXPECT_EQ(51, statistics.fraction_lost);
209 EXPECT_EQ(1u, statistics.cumulative_lost);
210 EXPECT_EQ(5u, statistics.extended_max_sequence_number);
211 EXPECT_EQ(4u, statistics.jitter);
sprang@webrtc.org4f1f5fa2013-12-19 13:26:02212
213 receive_statistics_->RegisterRtcpStatisticsCallback(NULL);
214
215 // Add some more data.
216 header1_.sequenceNumber = 1;
217 clock_.AdvanceTimeMilliseconds(7);
218 header1_.timestamp += 3;
219 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
220 header1_.sequenceNumber += 2;
221 clock_.AdvanceTimeMilliseconds(9);
222 header1_.timestamp += 9;
223 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
224 --header1_.sequenceNumber;
225 clock_.AdvanceTimeMilliseconds(13);
226 header1_.timestamp += 47;
227 receive_statistics_->IncomingPacket(header1_, kPacketSize1, true);
228 header1_.sequenceNumber += 3;
229 clock_.AdvanceTimeMilliseconds(11);
230 header1_.timestamp += 17;
231 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
232 ++header1_.sequenceNumber;
233
234 receive_statistics_->GetStatistician(kSsrc1)
235 ->GetStatistics(&statistics, true);
236
237 // Should not have been called after deregister.
238 EXPECT_EQ(1u, callback.num_calls_);
239}
sprang@webrtc.org7d99cd42014-01-23 10:00:39240
sprang@webrtc.org17189d22014-09-08 08:20:18241class RtpTestCallback : public StreamDataCountersCallback {
242 public:
243 RtpTestCallback()
244 : StreamDataCountersCallback(), num_calls_(0), ssrc_(0), stats_() {}
245 virtual ~RtpTestCallback() {}
246
247 virtual void DataCountersUpdated(const StreamDataCounters& counters,
248 uint32_t ssrc) {
249 ssrc_ = ssrc;
250 stats_ = counters;
251 ++num_calls_;
252 }
253
asapersson@webrtc.org1a8794b2015-02-04 08:34:47254 void MatchPacketCounter(const RtpPacketCounter& expected,
255 const RtpPacketCounter& actual) {
256 EXPECT_EQ(expected.payload_bytes, actual.payload_bytes);
257 EXPECT_EQ(expected.header_bytes, actual.header_bytes);
258 EXPECT_EQ(expected.padding_bytes, actual.padding_bytes);
259 EXPECT_EQ(expected.packets, actual.packets);
260 }
261
asapersson@webrtc.org96568c22014-12-09 09:47:53262 void Matches(uint32_t num_calls,
263 uint32_t ssrc,
264 const StreamDataCounters& expected) {
sprang@webrtc.org17189d22014-09-08 08:20:18265 EXPECT_EQ(num_calls, num_calls_);
266 EXPECT_EQ(ssrc, ssrc_);
asapersson@webrtc.org1a8794b2015-02-04 08:34:47267 MatchPacketCounter(expected.transmitted, stats_.transmitted);
268 MatchPacketCounter(expected.retransmitted, stats_.retransmitted);
269 MatchPacketCounter(expected.fec, stats_.fec);
sprang@webrtc.org17189d22014-09-08 08:20:18270 }
271
272 uint32_t num_calls_;
273 uint32_t ssrc_;
274 StreamDataCounters stats_;
275};
276
sprang@webrtc.org7d99cd42014-01-23 10:00:39277TEST_F(ReceiveStatisticsTest, RtpCallbacks) {
sprang@webrtc.org17189d22014-09-08 08:20:18278 RtpTestCallback callback;
sprang@webrtc.org7d99cd42014-01-23 10:00:39279 receive_statistics_->RegisterRtpStatisticsCallback(&callback);
280
pkasting@chromium.org0ab923a2014-11-20 22:28:14281 const size_t kHeaderLength = 20;
282 const size_t kPaddingLength = 9;
sprang@webrtc.org7d99cd42014-01-23 10:00:39283
284 // One packet of size kPacketSize1.
285 header1_.headerLength = kHeaderLength;
286 receive_statistics_->IncomingPacket(
287 header1_, kPacketSize1 + kHeaderLength, false);
asapersson@webrtc.org96568c22014-12-09 09:47:53288 StreamDataCounters expected;
asapersson@webrtc.org96763da2015-01-22 09:39:59289 expected.transmitted.payload_bytes = kPacketSize1;
290 expected.transmitted.header_bytes = kHeaderLength;
291 expected.transmitted.padding_bytes = 0;
292 expected.transmitted.packets = 1;
293 expected.retransmitted.payload_bytes = 0;
294 expected.retransmitted.header_bytes = 0;
295 expected.retransmitted.padding_bytes = 0;
296 expected.retransmitted.packets = 0;
297 expected.fec.packets = 0;
asapersson@webrtc.org96568c22014-12-09 09:47:53298 callback.Matches(1, kSsrc1, expected);
sprang@webrtc.org7d99cd42014-01-23 10:00:39299
300 ++header1_.sequenceNumber;
301 clock_.AdvanceTimeMilliseconds(5);
302 header1_.paddingLength = 9;
303 // Another packet of size kPacketSize1 with 9 bytes padding.
304 receive_statistics_->IncomingPacket(
305 header1_, kPacketSize1 + kHeaderLength + kPaddingLength, false);
asapersson@webrtc.org96763da2015-01-22 09:39:59306 expected.transmitted.payload_bytes = kPacketSize1 * 2;
307 expected.transmitted.header_bytes = kHeaderLength * 2;
308 expected.transmitted.padding_bytes = kPaddingLength;
309 expected.transmitted.packets = 2;
asapersson@webrtc.org96568c22014-12-09 09:47:53310 callback.Matches(2, kSsrc1, expected);
sprang@webrtc.org7d99cd42014-01-23 10:00:39311
312 clock_.AdvanceTimeMilliseconds(5);
313 // Retransmit last packet.
314 receive_statistics_->IncomingPacket(
315 header1_, kPacketSize1 + kHeaderLength + kPaddingLength, true);
asapersson@webrtc.org96763da2015-01-22 09:39:59316 expected.transmitted.payload_bytes = kPacketSize1 * 3;
317 expected.transmitted.header_bytes = kHeaderLength * 3;
318 expected.transmitted.padding_bytes = kPaddingLength * 2;
319 expected.transmitted.packets = 3;
320 expected.retransmitted.payload_bytes = kPacketSize1;
321 expected.retransmitted.header_bytes = kHeaderLength;
322 expected.retransmitted.padding_bytes = kPaddingLength;
323 expected.retransmitted.packets = 1;
asapersson@webrtc.org96568c22014-12-09 09:47:53324 callback.Matches(3, kSsrc1, expected);
sprang@webrtc.org7d99cd42014-01-23 10:00:39325
326 header1_.paddingLength = 0;
327 ++header1_.sequenceNumber;
328 clock_.AdvanceTimeMilliseconds(5);
asapersson@webrtc.org08c57f72015-01-27 12:17:29329 // One FEC packet.
sprang@webrtc.org7d99cd42014-01-23 10:00:39330 receive_statistics_->IncomingPacket(
331 header1_, kPacketSize1 + kHeaderLength, false);
asapersson@webrtc.org08c57f72015-01-27 12:17:29332 receive_statistics_->FecPacketReceived(header1_,
333 kPacketSize1 + kHeaderLength);
asapersson@webrtc.org96763da2015-01-22 09:39:59334 expected.transmitted.payload_bytes = kPacketSize1 * 4;
335 expected.transmitted.header_bytes = kHeaderLength * 4;
336 expected.transmitted.packets = 4;
asapersson@webrtc.org08c57f72015-01-27 12:17:29337 expected.fec.payload_bytes = kPacketSize1;
338 expected.fec.header_bytes = kHeaderLength;
asapersson@webrtc.org96763da2015-01-22 09:39:59339 expected.fec.packets = 1;
asapersson@webrtc.org96568c22014-12-09 09:47:53340 callback.Matches(5, kSsrc1, expected);
sprang@webrtc.org7d99cd42014-01-23 10:00:39341
342 receive_statistics_->RegisterRtpStatisticsCallback(NULL);
343
344 // New stats, but callback should not be called.
345 ++header1_.sequenceNumber;
346 clock_.AdvanceTimeMilliseconds(5);
347 receive_statistics_->IncomingPacket(
348 header1_, kPacketSize1 + kHeaderLength, true);
asapersson@webrtc.org96568c22014-12-09 09:47:53349 callback.Matches(5, kSsrc1, expected);
sprang@webrtc.org7d99cd42014-01-23 10:00:39350}
sprang@webrtc.org17189d22014-09-08 08:20:18351
352TEST_F(ReceiveStatisticsTest, RtpCallbacksFecFirst) {
353 RtpTestCallback callback;
354 receive_statistics_->RegisterRtpStatisticsCallback(&callback);
355
356 const uint32_t kHeaderLength = 20;
asapersson@webrtc.org08c57f72015-01-27 12:17:29357 header1_.headerLength = kHeaderLength;
sprang@webrtc.org17189d22014-09-08 08:20:18358
359 // If first packet is FEC, ignore it.
asapersson@webrtc.org08c57f72015-01-27 12:17:29360 receive_statistics_->FecPacketReceived(header1_,
361 kPacketSize1 + kHeaderLength);
sprang@webrtc.org17189d22014-09-08 08:20:18362 EXPECT_EQ(0u, callback.num_calls_);
363
sprang@webrtc.org17189d22014-09-08 08:20:18364 receive_statistics_->IncomingPacket(
365 header1_, kPacketSize1 + kHeaderLength, false);
asapersson@webrtc.org96568c22014-12-09 09:47:53366 StreamDataCounters expected;
asapersson@webrtc.org96763da2015-01-22 09:39:59367 expected.transmitted.payload_bytes = kPacketSize1;
368 expected.transmitted.header_bytes = kHeaderLength;
369 expected.transmitted.padding_bytes = 0;
370 expected.transmitted.packets = 1;
371 expected.fec.packets = 0;
asapersson@webrtc.org96568c22014-12-09 09:47:53372 callback.Matches(1, kSsrc1, expected);
sprang@webrtc.org17189d22014-09-08 08:20:18373
asapersson@webrtc.org08c57f72015-01-27 12:17:29374 receive_statistics_->FecPacketReceived(header1_,
375 kPacketSize1 + kHeaderLength);
376 expected.fec.payload_bytes = kPacketSize1;
377 expected.fec.header_bytes = kHeaderLength;
asapersson@webrtc.org96763da2015-01-22 09:39:59378 expected.fec.packets = 1;
asapersson@webrtc.org96568c22014-12-09 09:47:53379 callback.Matches(2, kSsrc1, expected);
sprang@webrtc.org17189d22014-09-08 08:20:18380}
stefan@webrtc.orga20e2d42013-08-21 20:58:21381} // namespace webrtc