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