1 /*
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 <memory>
12
13 #include "modules/rtp_rtcp/include/receive_statistics.h"
14 #include "system_wrappers/include/clock.h"
15 #include "test/gmock.h"
16 #include "test/gtest.h"
17
18 namespace webrtc {
19
20 const size_t kPacketSize1 = 100;
21 const size_t kPacketSize2 = 300;
22 const uint32_t kSsrc1 = 1;
23 const uint32_t kSsrc2 = 2;
24
25 class ReceiveStatisticsTest : public ::testing::Test {
26 public:
ReceiveStatisticsTest()27 ReceiveStatisticsTest() :
28 clock_(0),
29 receive_statistics_(ReceiveStatistics::Create(&clock_)) {
30 memset(&header1_, 0, sizeof(header1_));
31 header1_.ssrc = kSsrc1;
32 header1_.sequenceNumber = 100;
33 memset(&header2_, 0, sizeof(header2_));
34 header2_.ssrc = kSsrc2;
35 header2_.sequenceNumber = 100;
36 }
37
38 protected:
39 SimulatedClock clock_;
40 std::unique_ptr<ReceiveStatistics> receive_statistics_;
41 RTPHeader header1_;
42 RTPHeader header2_;
43 };
44
TEST_F(ReceiveStatisticsTest,TwoIncomingSsrcs)45 TEST_F(ReceiveStatisticsTest, TwoIncomingSsrcs) {
46 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
47 ++header1_.sequenceNumber;
48 receive_statistics_->IncomingPacket(header2_, kPacketSize2, false);
49 ++header2_.sequenceNumber;
50 clock_.AdvanceTimeMilliseconds(100);
51 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
52 ++header1_.sequenceNumber;
53 receive_statistics_->IncomingPacket(header2_, kPacketSize2, false);
54 ++header2_.sequenceNumber;
55
56 StreamStatistician* statistician =
57 receive_statistics_->GetStatistician(kSsrc1);
58 ASSERT_TRUE(statistician != NULL);
59 EXPECT_GT(statistician->BitrateReceived(), 0u);
60 size_t bytes_received = 0;
61 uint32_t packets_received = 0;
62 statistician->GetDataCounters(&bytes_received, &packets_received);
63 EXPECT_EQ(200u, bytes_received);
64 EXPECT_EQ(2u, packets_received);
65
66 statistician =
67 receive_statistics_->GetStatistician(kSsrc2);
68 ASSERT_TRUE(statistician != NULL);
69 EXPECT_GT(statistician->BitrateReceived(), 0u);
70 statistician->GetDataCounters(&bytes_received, &packets_received);
71 EXPECT_EQ(600u, bytes_received);
72 EXPECT_EQ(2u, packets_received);
73
74 EXPECT_EQ(2u, receive_statistics_->RtcpReportBlocks(3).size());
75 // Add more incoming packets and verify that they are registered in both
76 // access methods.
77 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
78 ++header1_.sequenceNumber;
79 receive_statistics_->IncomingPacket(header2_, kPacketSize2, false);
80 ++header2_.sequenceNumber;
81
82 receive_statistics_->GetStatistician(kSsrc1)->GetDataCounters(
83 &bytes_received, &packets_received);
84 EXPECT_EQ(300u, bytes_received);
85 EXPECT_EQ(3u, packets_received);
86 receive_statistics_->GetStatistician(kSsrc2)->GetDataCounters(
87 &bytes_received, &packets_received);
88 EXPECT_EQ(900u, bytes_received);
89 EXPECT_EQ(3u, packets_received);
90 }
91
TEST_F(ReceiveStatisticsTest,ActiveStatisticians)92 TEST_F(ReceiveStatisticsTest, ActiveStatisticians) {
93 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
94 ++header1_.sequenceNumber;
95 clock_.AdvanceTimeMilliseconds(1000);
96 receive_statistics_->IncomingPacket(header2_, kPacketSize2, false);
97 ++header2_.sequenceNumber;
98 // Nothing should time out since only 1000 ms has passed since the first
99 // packet came in.
100 EXPECT_EQ(2u, receive_statistics_->RtcpReportBlocks(3).size());
101
102 clock_.AdvanceTimeMilliseconds(7000);
103 // kSsrc1 should have timed out.
104 EXPECT_EQ(1u, receive_statistics_->RtcpReportBlocks(3).size());
105
106 clock_.AdvanceTimeMilliseconds(1000);
107 // kSsrc2 should have timed out.
108 EXPECT_EQ(0u, receive_statistics_->RtcpReportBlocks(3).size());
109
110 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
111 ++header1_.sequenceNumber;
112 // kSsrc1 should be active again and the data counters should have survived.
113 EXPECT_EQ(1u, receive_statistics_->RtcpReportBlocks(3).size());
114 StreamStatistician* statistician =
115 receive_statistics_->GetStatistician(kSsrc1);
116 ASSERT_TRUE(statistician != NULL);
117 size_t bytes_received = 0;
118 uint32_t packets_received = 0;
119 statistician->GetDataCounters(&bytes_received, &packets_received);
120 EXPECT_EQ(200u, bytes_received);
121 EXPECT_EQ(2u, packets_received);
122 }
123
TEST_F(ReceiveStatisticsTest,GetReceiveStreamDataCounters)124 TEST_F(ReceiveStatisticsTest, GetReceiveStreamDataCounters) {
125 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
126 StreamStatistician* statistician =
127 receive_statistics_->GetStatistician(kSsrc1);
128 ASSERT_TRUE(statistician != NULL);
129
130 StreamDataCounters counters;
131 statistician->GetReceiveStreamDataCounters(&counters);
132 EXPECT_GT(counters.first_packet_time_ms, -1);
133 EXPECT_EQ(1u, counters.transmitted.packets);
134
135 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
136 statistician->GetReceiveStreamDataCounters(&counters);
137 EXPECT_GT(counters.first_packet_time_ms, -1);
138 EXPECT_EQ(2u, counters.transmitted.packets);
139 }
140
TEST_F(ReceiveStatisticsTest,RtcpCallbacks)141 TEST_F(ReceiveStatisticsTest, RtcpCallbacks) {
142 class TestCallback : public RtcpStatisticsCallback {
143 public:
144 TestCallback()
145 : RtcpStatisticsCallback(), num_calls_(0), ssrc_(0), stats_() {}
146 virtual ~TestCallback() {}
147
148 void StatisticsUpdated(const RtcpStatistics& statistics,
149 uint32_t ssrc) override {
150 ssrc_ = ssrc;
151 stats_ = statistics;
152 ++num_calls_;
153 }
154
155 void CNameChanged(const char* cname, uint32_t ssrc) override {}
156
157 uint32_t num_calls_;
158 uint32_t ssrc_;
159 RtcpStatistics stats_;
160 } callback;
161
162 receive_statistics_->RegisterRtcpStatisticsCallback(&callback);
163
164 // Add some arbitrary data, with loss and jitter.
165 header1_.sequenceNumber = 1;
166 clock_.AdvanceTimeMilliseconds(7);
167 header1_.timestamp += 3;
168 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
169 header1_.sequenceNumber += 2;
170 clock_.AdvanceTimeMilliseconds(9);
171 header1_.timestamp += 9;
172 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
173 --header1_.sequenceNumber;
174 clock_.AdvanceTimeMilliseconds(13);
175 header1_.timestamp += 47;
176 receive_statistics_->IncomingPacket(header1_, kPacketSize1, true);
177 header1_.sequenceNumber += 3;
178 clock_.AdvanceTimeMilliseconds(11);
179 header1_.timestamp += 17;
180 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
181 ++header1_.sequenceNumber;
182
183 EXPECT_EQ(0u, callback.num_calls_);
184
185 // Call GetStatistics, simulating a timed rtcp sender thread.
186 RtcpStatistics statistics;
187 receive_statistics_->GetStatistician(kSsrc1)
188 ->GetStatistics(&statistics, true);
189
190 EXPECT_EQ(1u, callback.num_calls_);
191 EXPECT_EQ(callback.ssrc_, kSsrc1);
192 EXPECT_EQ(statistics.packets_lost, callback.stats_.packets_lost);
193 EXPECT_EQ(statistics.extended_highest_sequence_number,
194 callback.stats_.extended_highest_sequence_number);
195 EXPECT_EQ(statistics.fraction_lost, callback.stats_.fraction_lost);
196 EXPECT_EQ(statistics.jitter, callback.stats_.jitter);
197 EXPECT_EQ(51, statistics.fraction_lost);
198 EXPECT_EQ(1u, statistics.packets_lost);
199 EXPECT_EQ(5u, statistics.extended_highest_sequence_number);
200 EXPECT_EQ(4u, statistics.jitter);
201
202 receive_statistics_->RegisterRtcpStatisticsCallback(NULL);
203
204 // Add some more data.
205 header1_.sequenceNumber = 1;
206 clock_.AdvanceTimeMilliseconds(7);
207 header1_.timestamp += 3;
208 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
209 header1_.sequenceNumber += 2;
210 clock_.AdvanceTimeMilliseconds(9);
211 header1_.timestamp += 9;
212 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
213 --header1_.sequenceNumber;
214 clock_.AdvanceTimeMilliseconds(13);
215 header1_.timestamp += 47;
216 receive_statistics_->IncomingPacket(header1_, kPacketSize1, true);
217 header1_.sequenceNumber += 3;
218 clock_.AdvanceTimeMilliseconds(11);
219 header1_.timestamp += 17;
220 receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
221 ++header1_.sequenceNumber;
222
223 receive_statistics_->GetStatistician(kSsrc1)
224 ->GetStatistics(&statistics, true);
225
226 // Should not have been called after deregister.
227 EXPECT_EQ(1u, callback.num_calls_);
228 }
229
230 class RtpTestCallback : public StreamDataCountersCallback {
231 public:
RtpTestCallback()232 RtpTestCallback()
233 : StreamDataCountersCallback(), num_calls_(0), ssrc_(0), stats_() {}
~RtpTestCallback()234 virtual ~RtpTestCallback() {}
235
DataCountersUpdated(const StreamDataCounters & counters,uint32_t ssrc)236 virtual void DataCountersUpdated(const StreamDataCounters& counters,
237 uint32_t ssrc) {
238 ssrc_ = ssrc;
239 stats_ = counters;
240 ++num_calls_;
241 }
242
MatchPacketCounter(const RtpPacketCounter & expected,const RtpPacketCounter & actual)243 void MatchPacketCounter(const RtpPacketCounter& expected,
244 const RtpPacketCounter& actual) {
245 EXPECT_EQ(expected.payload_bytes, actual.payload_bytes);
246 EXPECT_EQ(expected.header_bytes, actual.header_bytes);
247 EXPECT_EQ(expected.padding_bytes, actual.padding_bytes);
248 EXPECT_EQ(expected.packets, actual.packets);
249 }
250
Matches(uint32_t num_calls,uint32_t ssrc,const StreamDataCounters & expected)251 void Matches(uint32_t num_calls,
252 uint32_t ssrc,
253 const StreamDataCounters& expected) {
254 EXPECT_EQ(num_calls, num_calls_);
255 EXPECT_EQ(ssrc, ssrc_);
256 MatchPacketCounter(expected.transmitted, stats_.transmitted);
257 MatchPacketCounter(expected.retransmitted, stats_.retransmitted);
258 MatchPacketCounter(expected.fec, stats_.fec);
259 }
260
261 uint32_t num_calls_;
262 uint32_t ssrc_;
263 StreamDataCounters stats_;
264 };
265
TEST_F(ReceiveStatisticsTest,RtpCallbacks)266 TEST_F(ReceiveStatisticsTest, RtpCallbacks) {
267 RtpTestCallback callback;
268 receive_statistics_->RegisterRtpStatisticsCallback(&callback);
269
270 const size_t kHeaderLength = 20;
271 const size_t kPaddingLength = 9;
272
273 // One packet of size kPacketSize1.
274 header1_.headerLength = kHeaderLength;
275 receive_statistics_->IncomingPacket(
276 header1_, kPacketSize1 + kHeaderLength, false);
277 StreamDataCounters expected;
278 expected.transmitted.payload_bytes = kPacketSize1;
279 expected.transmitted.header_bytes = kHeaderLength;
280 expected.transmitted.padding_bytes = 0;
281 expected.transmitted.packets = 1;
282 expected.retransmitted.payload_bytes = 0;
283 expected.retransmitted.header_bytes = 0;
284 expected.retransmitted.padding_bytes = 0;
285 expected.retransmitted.packets = 0;
286 expected.fec.packets = 0;
287 callback.Matches(1, kSsrc1, expected);
288
289 ++header1_.sequenceNumber;
290 clock_.AdvanceTimeMilliseconds(5);
291 header1_.paddingLength = 9;
292 // Another packet of size kPacketSize1 with 9 bytes padding.
293 receive_statistics_->IncomingPacket(
294 header1_, kPacketSize1 + kHeaderLength + kPaddingLength, false);
295 expected.transmitted.payload_bytes = kPacketSize1 * 2;
296 expected.transmitted.header_bytes = kHeaderLength * 2;
297 expected.transmitted.padding_bytes = kPaddingLength;
298 expected.transmitted.packets = 2;
299 callback.Matches(2, kSsrc1, expected);
300
301 clock_.AdvanceTimeMilliseconds(5);
302 // Retransmit last packet.
303 receive_statistics_->IncomingPacket(
304 header1_, kPacketSize1 + kHeaderLength + kPaddingLength, true);
305 expected.transmitted.payload_bytes = kPacketSize1 * 3;
306 expected.transmitted.header_bytes = kHeaderLength * 3;
307 expected.transmitted.padding_bytes = kPaddingLength * 2;
308 expected.transmitted.packets = 3;
309 expected.retransmitted.payload_bytes = kPacketSize1;
310 expected.retransmitted.header_bytes = kHeaderLength;
311 expected.retransmitted.padding_bytes = kPaddingLength;
312 expected.retransmitted.packets = 1;
313 callback.Matches(3, kSsrc1, expected);
314
315 header1_.paddingLength = 0;
316 ++header1_.sequenceNumber;
317 clock_.AdvanceTimeMilliseconds(5);
318 // One FEC packet.
319 receive_statistics_->IncomingPacket(
320 header1_, kPacketSize1 + kHeaderLength, false);
321 receive_statistics_->FecPacketReceived(header1_,
322 kPacketSize1 + kHeaderLength);
323 expected.transmitted.payload_bytes = kPacketSize1 * 4;
324 expected.transmitted.header_bytes = kHeaderLength * 4;
325 expected.transmitted.packets = 4;
326 expected.fec.payload_bytes = kPacketSize1;
327 expected.fec.header_bytes = kHeaderLength;
328 expected.fec.packets = 1;
329 callback.Matches(5, kSsrc1, expected);
330
331 receive_statistics_->RegisterRtpStatisticsCallback(NULL);
332
333 // New stats, but callback should not be called.
334 ++header1_.sequenceNumber;
335 clock_.AdvanceTimeMilliseconds(5);
336 receive_statistics_->IncomingPacket(
337 header1_, kPacketSize1 + kHeaderLength, true);
338 callback.Matches(5, kSsrc1, expected);
339 }
340
TEST_F(ReceiveStatisticsTest,RtpCallbacksFecFirst)341 TEST_F(ReceiveStatisticsTest, RtpCallbacksFecFirst) {
342 RtpTestCallback callback;
343 receive_statistics_->RegisterRtpStatisticsCallback(&callback);
344
345 const uint32_t kHeaderLength = 20;
346 header1_.headerLength = kHeaderLength;
347
348 // If first packet is FEC, ignore it.
349 receive_statistics_->FecPacketReceived(header1_,
350 kPacketSize1 + kHeaderLength);
351 EXPECT_EQ(0u, callback.num_calls_);
352
353 receive_statistics_->IncomingPacket(
354 header1_, kPacketSize1 + kHeaderLength, false);
355 StreamDataCounters expected;
356 expected.transmitted.payload_bytes = kPacketSize1;
357 expected.transmitted.header_bytes = kHeaderLength;
358 expected.transmitted.padding_bytes = 0;
359 expected.transmitted.packets = 1;
360 expected.fec.packets = 0;
361 callback.Matches(1, kSsrc1, expected);
362
363 receive_statistics_->FecPacketReceived(header1_,
364 kPacketSize1 + kHeaderLength);
365 expected.fec.payload_bytes = kPacketSize1;
366 expected.fec.header_bytes = kHeaderLength;
367 expected.fec.packets = 1;
368 callback.Matches(2, kSsrc1, expected);
369 }
370 } // namespace webrtc
371