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