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