• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "webrtc/base/scoped_ptr.h"
14 #include "webrtc/modules/rtp_rtcp/include/receive_statistics.h"
15 #include "webrtc/system_wrappers/include/clock.h"
16 
17 namespace webrtc {
18 
19 const size_t kPacketSize1 = 100;
20 const size_t kPacketSize2 = 300;
21 const uint32_t kSsrc1 = 1;
22 const uint32_t kSsrc2 = 2;
23 
24 class ReceiveStatisticsTest : public ::testing::Test {
25  public:
ReceiveStatisticsTest()26   ReceiveStatisticsTest() :
27       clock_(0),
28       receive_statistics_(ReceiveStatistics::Create(&clock_)) {
29     memset(&header1_, 0, sizeof(header1_));
30     header1_.ssrc = kSsrc1;
31     header1_.sequenceNumber = 100;
32     memset(&header2_, 0, sizeof(header2_));
33     header2_.ssrc = kSsrc2;
34     header2_.sequenceNumber = 100;
35   }
36 
37  protected:
38   SimulatedClock clock_;
39   rtc::scoped_ptr<ReceiveStatistics> receive_statistics_;
40   RTPHeader header1_;
41   RTPHeader header2_;
42 };
43 
TEST_F(ReceiveStatisticsTest,TwoIncomingSsrcs)44 TEST_F(ReceiveStatisticsTest, TwoIncomingSsrcs) {
45   receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
46   ++header1_.sequenceNumber;
47   receive_statistics_->IncomingPacket(header2_, kPacketSize2, false);
48   ++header2_.sequenceNumber;
49   clock_.AdvanceTimeMilliseconds(100);
50   receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
51   ++header1_.sequenceNumber;
52   receive_statistics_->IncomingPacket(header2_, kPacketSize2, false);
53   ++header2_.sequenceNumber;
54 
55   StreamStatistician* statistician =
56       receive_statistics_->GetStatistician(kSsrc1);
57   ASSERT_TRUE(statistician != NULL);
58   EXPECT_GT(statistician->BitrateReceived(), 0u);
59   size_t bytes_received = 0;
60   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.
77   receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
78   ++header1_.sequenceNumber;
79   receive_statistics_->IncomingPacket(header2_, kPacketSize2, false);
80   ++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 
TEST_F(ReceiveStatisticsTest,ActiveStatisticians)99 TEST_F(ReceiveStatisticsTest, ActiveStatisticians) {
100   receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
101   ++header1_.sequenceNumber;
102   clock_.AdvanceTimeMilliseconds(1000);
103   receive_statistics_->IncomingPacket(header2_, kPacketSize2, false);
104   ++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 
120   receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
121   ++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);
128   size_t bytes_received = 0;
129   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 }
134 
TEST_F(ReceiveStatisticsTest,GetReceiveStreamDataCounters)135 TEST_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);
143   EXPECT_GT(counters.first_packet_time_ms, -1);
144   EXPECT_EQ(1u, counters.transmitted.packets);
145 
146   receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
147   statistician->GetReceiveStreamDataCounters(&counters);
148   EXPECT_GT(counters.first_packet_time_ms, -1);
149   EXPECT_EQ(2u, counters.transmitted.packets);
150 }
151 
TEST_F(ReceiveStatisticsTest,RtcpCallbacks)152 TEST_F(ReceiveStatisticsTest, RtcpCallbacks) {
153   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 
166     void CNameChanged(const char* cname, uint32_t ssrc) override {}
167 
168     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);
208   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);
212 
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 }
240 
241 class RtpTestCallback : public StreamDataCountersCallback {
242  public:
RtpTestCallback()243   RtpTestCallback()
244       : StreamDataCountersCallback(), num_calls_(0), ssrc_(0), stats_() {}
~RtpTestCallback()245   virtual ~RtpTestCallback() {}
246 
DataCountersUpdated(const StreamDataCounters & counters,uint32_t ssrc)247   virtual void DataCountersUpdated(const StreamDataCounters& counters,
248                                    uint32_t ssrc) {
249     ssrc_ = ssrc;
250     stats_ = counters;
251     ++num_calls_;
252   }
253 
MatchPacketCounter(const RtpPacketCounter & expected,const RtpPacketCounter & actual)254   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 
Matches(uint32_t num_calls,uint32_t ssrc,const StreamDataCounters & expected)262   void Matches(uint32_t num_calls,
263                uint32_t ssrc,
264                const StreamDataCounters& expected) {
265     EXPECT_EQ(num_calls, num_calls_);
266     EXPECT_EQ(ssrc, ssrc_);
267     MatchPacketCounter(expected.transmitted, stats_.transmitted);
268     MatchPacketCounter(expected.retransmitted, stats_.retransmitted);
269     MatchPacketCounter(expected.fec, stats_.fec);
270   }
271 
272   uint32_t num_calls_;
273   uint32_t ssrc_;
274   StreamDataCounters stats_;
275 };
276 
TEST_F(ReceiveStatisticsTest,RtpCallbacks)277 TEST_F(ReceiveStatisticsTest, RtpCallbacks) {
278   RtpTestCallback callback;
279   receive_statistics_->RegisterRtpStatisticsCallback(&callback);
280 
281   const size_t kHeaderLength = 20;
282   const size_t kPaddingLength = 9;
283 
284   // One packet of size kPacketSize1.
285   header1_.headerLength = kHeaderLength;
286   receive_statistics_->IncomingPacket(
287       header1_, kPacketSize1 + kHeaderLength, false);
288   StreamDataCounters expected;
289   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;
298   callback.Matches(1, kSsrc1, expected);
299 
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);
306   expected.transmitted.payload_bytes = kPacketSize1 * 2;
307   expected.transmitted.header_bytes = kHeaderLength * 2;
308   expected.transmitted.padding_bytes = kPaddingLength;
309   expected.transmitted.packets = 2;
310   callback.Matches(2, kSsrc1, expected);
311 
312   clock_.AdvanceTimeMilliseconds(5);
313   // Retransmit last packet.
314   receive_statistics_->IncomingPacket(
315       header1_, kPacketSize1 + kHeaderLength + kPaddingLength, true);
316   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;
324   callback.Matches(3, kSsrc1, expected);
325 
326   header1_.paddingLength = 0;
327   ++header1_.sequenceNumber;
328   clock_.AdvanceTimeMilliseconds(5);
329   // One FEC packet.
330   receive_statistics_->IncomingPacket(
331       header1_, kPacketSize1 + kHeaderLength, false);
332   receive_statistics_->FecPacketReceived(header1_,
333                                          kPacketSize1 + kHeaderLength);
334   expected.transmitted.payload_bytes = kPacketSize1 * 4;
335   expected.transmitted.header_bytes = kHeaderLength * 4;
336   expected.transmitted.packets = 4;
337   expected.fec.payload_bytes = kPacketSize1;
338   expected.fec.header_bytes = kHeaderLength;
339   expected.fec.packets = 1;
340   callback.Matches(5, kSsrc1, expected);
341 
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);
349   callback.Matches(5, kSsrc1, expected);
350 }
351 
TEST_F(ReceiveStatisticsTest,RtpCallbacksFecFirst)352 TEST_F(ReceiveStatisticsTest, RtpCallbacksFecFirst) {
353   RtpTestCallback callback;
354   receive_statistics_->RegisterRtpStatisticsCallback(&callback);
355 
356   const uint32_t kHeaderLength = 20;
357   header1_.headerLength = kHeaderLength;
358 
359   // If first packet is FEC, ignore it.
360   receive_statistics_->FecPacketReceived(header1_,
361                                          kPacketSize1 + kHeaderLength);
362   EXPECT_EQ(0u, callback.num_calls_);
363 
364   receive_statistics_->IncomingPacket(
365       header1_, kPacketSize1 + kHeaderLength, false);
366   StreamDataCounters expected;
367   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;
372   callback.Matches(1, kSsrc1, expected);
373 
374   receive_statistics_->FecPacketReceived(header1_,
375                                          kPacketSize1 + kHeaderLength);
376   expected.fec.payload_bytes = kPacketSize1;
377   expected.fec.header_bytes = kHeaderLength;
378   expected.fec.packets = 1;
379   callback.Matches(2, kSsrc1, expected);
380 }
381 }  // namespace webrtc
382