Home | History | Annotate | Download | only in source
      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/modules/rtp_rtcp/interface/receive_statistics.h"
     14 #include "webrtc/system_wrappers/interface/clock.h"
     15 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
     16 
     17 namespace webrtc {
     18 
     19 const int kPacketSize1 = 100;
     20 const int kPacketSize2 = 300;
     21 const uint32_t kSsrc1 = 1;
     22 const uint32_t kSsrc2 = 2;
     23 
     24 class 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;
     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   scoped_ptr<ReceiveStatistics> receive_statistics_;
     40   RTPHeader header1_;
     41   RTPHeader header2_;
     42 };
     43 
     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   uint32_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 
     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   uint32_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 
    135 TEST_F(ReceiveStatisticsTest, RtcpCallbacks) {
    136   class TestCallback : public RtcpStatisticsCallback {
    137    public:
    138     TestCallback()
    139         : RtcpStatisticsCallback(), num_calls_(0), ssrc_(0), stats_() {}
    140     virtual ~TestCallback() {}
    141 
    142     virtual void StatisticsUpdated(const RtcpStatistics& statistics,
    143                                    uint32_t ssrc) {
    144       ssrc_ = ssrc;
    145       stats_ = statistics;
    146       ++num_calls_;
    147     }
    148 
    149     uint32_t num_calls_;
    150     uint32_t ssrc_;
    151     RtcpStatistics stats_;
    152   } callback;
    153 
    154   receive_statistics_->RegisterRtcpStatisticsCallback(&callback);
    155 
    156   // Add some arbitrary data, with loss and jitter.
    157   header1_.sequenceNumber = 1;
    158   clock_.AdvanceTimeMilliseconds(7);
    159   header1_.timestamp += 3;
    160   receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
    161   header1_.sequenceNumber += 2;
    162   clock_.AdvanceTimeMilliseconds(9);
    163   header1_.timestamp += 9;
    164   receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
    165   --header1_.sequenceNumber;
    166   clock_.AdvanceTimeMilliseconds(13);
    167   header1_.timestamp += 47;
    168   receive_statistics_->IncomingPacket(header1_, kPacketSize1, true);
    169   header1_.sequenceNumber += 3;
    170   clock_.AdvanceTimeMilliseconds(11);
    171   header1_.timestamp += 17;
    172   receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
    173   ++header1_.sequenceNumber;
    174 
    175   EXPECT_EQ(0u, callback.num_calls_);
    176 
    177   // Call GetStatistics, simulating a timed rtcp sender thread.
    178   RtcpStatistics statistics;
    179   receive_statistics_->GetStatistician(kSsrc1)
    180       ->GetStatistics(&statistics, true);
    181 
    182   EXPECT_EQ(1u, callback.num_calls_);
    183   EXPECT_EQ(callback.ssrc_, kSsrc1);
    184   EXPECT_EQ(statistics.cumulative_lost, callback.stats_.cumulative_lost);
    185   EXPECT_EQ(statistics.extended_max_sequence_number,
    186             callback.stats_.extended_max_sequence_number);
    187   EXPECT_EQ(statistics.fraction_lost, callback.stats_.fraction_lost);
    188   EXPECT_EQ(statistics.jitter, callback.stats_.jitter);
    189   EXPECT_EQ(51, statistics.fraction_lost);
    190   EXPECT_EQ(1u, statistics.cumulative_lost);
    191   EXPECT_EQ(5u, statistics.extended_max_sequence_number);
    192   EXPECT_EQ(4u, statistics.jitter);
    193 
    194   receive_statistics_->RegisterRtcpStatisticsCallback(NULL);
    195 
    196   // Add some more data.
    197   header1_.sequenceNumber = 1;
    198   clock_.AdvanceTimeMilliseconds(7);
    199   header1_.timestamp += 3;
    200   receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
    201   header1_.sequenceNumber += 2;
    202   clock_.AdvanceTimeMilliseconds(9);
    203   header1_.timestamp += 9;
    204   receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
    205   --header1_.sequenceNumber;
    206   clock_.AdvanceTimeMilliseconds(13);
    207   header1_.timestamp += 47;
    208   receive_statistics_->IncomingPacket(header1_, kPacketSize1, true);
    209   header1_.sequenceNumber += 3;
    210   clock_.AdvanceTimeMilliseconds(11);
    211   header1_.timestamp += 17;
    212   receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
    213   ++header1_.sequenceNumber;
    214 
    215   receive_statistics_->GetStatistician(kSsrc1)
    216       ->GetStatistics(&statistics, true);
    217 
    218   // Should not have been called after deregister.
    219   EXPECT_EQ(1u, callback.num_calls_);
    220 }
    221 
    222 TEST_F(ReceiveStatisticsTest, RtpCallbacks) {
    223   class TestCallback : public StreamDataCountersCallback {
    224    public:
    225     TestCallback()
    226         : StreamDataCountersCallback(), num_calls_(0), ssrc_(0), stats_() {}
    227     virtual ~TestCallback() {}
    228 
    229     virtual void DataCountersUpdated(const StreamDataCounters& counters,
    230                                      uint32_t ssrc) {
    231       ssrc_ = ssrc;
    232       stats_ = counters;
    233       ++num_calls_;
    234     }
    235 
    236     void ExpectMatches(uint32_t num_calls,
    237                        uint32_t ssrc,
    238                        uint32_t bytes,
    239                        uint32_t padding,
    240                        uint32_t packets,
    241                        uint32_t retransmits,
    242                        uint32_t fec) {
    243       EXPECT_EQ(num_calls, num_calls_);
    244       EXPECT_EQ(ssrc, ssrc_);
    245       EXPECT_EQ(bytes, stats_.bytes);
    246       EXPECT_EQ(padding, stats_.padding_bytes);
    247       EXPECT_EQ(packets, stats_.packets);
    248       EXPECT_EQ(retransmits, stats_.retransmitted_packets);
    249       EXPECT_EQ(fec, stats_.fec_packets);
    250     }
    251 
    252     uint32_t num_calls_;
    253     uint32_t ssrc_;
    254     StreamDataCounters stats_;
    255   } callback;
    256 
    257   receive_statistics_->RegisterRtpStatisticsCallback(&callback);
    258 
    259   const uint32_t kHeaderLength = 20;
    260   const uint32_t kPaddingLength = 9;
    261 
    262   // One packet of size kPacketSize1.
    263   header1_.headerLength = kHeaderLength;
    264   receive_statistics_->IncomingPacket(
    265       header1_, kPacketSize1 + kHeaderLength, false);
    266   callback.ExpectMatches(1, kSsrc1, kPacketSize1, 0, 1, 0, 0);
    267 
    268   ++header1_.sequenceNumber;
    269   clock_.AdvanceTimeMilliseconds(5);
    270   header1_.paddingLength = 9;
    271   // Another packet of size kPacketSize1 with 9 bytes padding.
    272   receive_statistics_->IncomingPacket(
    273       header1_, kPacketSize1 + kHeaderLength + kPaddingLength, false);
    274   callback.ExpectMatches(2, kSsrc1, 2 * kPacketSize1, kPaddingLength, 2, 0, 0);
    275 
    276   clock_.AdvanceTimeMilliseconds(5);
    277   // Retransmit last packet.
    278   receive_statistics_->IncomingPacket(
    279       header1_, kPacketSize1 + kHeaderLength + kPaddingLength, true);
    280   callback.ExpectMatches(
    281       3, kSsrc1, 3 * kPacketSize1, kPaddingLength * 2, 3, 1, 0);
    282 
    283   header1_.paddingLength = 0;
    284   ++header1_.sequenceNumber;
    285   clock_.AdvanceTimeMilliseconds(5);
    286   // One recovered packet.
    287   receive_statistics_->IncomingPacket(
    288       header1_, kPacketSize1 + kHeaderLength, false);
    289   receive_statistics_->FecPacketReceived(kSsrc1);
    290   callback.ExpectMatches(
    291       5, kSsrc1, 4 * kPacketSize1, kPaddingLength * 2, 4, 1, 1);
    292 
    293   receive_statistics_->RegisterRtpStatisticsCallback(NULL);
    294 
    295   // New stats, but callback should not be called.
    296   ++header1_.sequenceNumber;
    297   clock_.AdvanceTimeMilliseconds(5);
    298   receive_statistics_->IncomingPacket(
    299       header1_, kPacketSize1 + kHeaderLength, true);
    300   callback.ExpectMatches(
    301       5, kSsrc1, 4 * kPacketSize1, kPaddingLength * 2, 4, 1, 1);
    302 }
    303 }  // namespace webrtc
    304