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/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:
     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 
     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 
     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 
    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 
    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:
    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 
    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 
    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 
    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 
    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