rtcp_sender_unittest.cc revision b7eda43810125cd01b29671a6beab61ddb48ebdb
1/* 2 * Copyright (c) 2012 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 12/* 13 * This file includes unit tests for the RTCPSender. 14 */ 15 16#include "testing/gmock/include/gmock/gmock.h" 17#include "testing/gtest/include/gtest/gtest.h" 18 19#include "webrtc/common_types.h" 20#include "webrtc/modules/remote_bitrate_estimator/include/mock/mock_remote_bitrate_observer.h" 21#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h" 22#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" 23#include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h" 24#include "webrtc/modules/rtp_rtcp/interface/rtp_receiver.h" 25#include "webrtc/modules/rtp_rtcp/source/rtcp_receiver.h" 26#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h" 27#include "webrtc/modules/rtp_rtcp/source/rtp_receiver_video.h" 28#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h" 29#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" 30 31namespace webrtc { 32 33TEST(NACKStringBuilderTest, TestCase1) { 34 NACKStringBuilder builder; 35 builder.PushNACK(5); 36 builder.PushNACK(7); 37 builder.PushNACK(9); 38 builder.PushNACK(10); 39 builder.PushNACK(11); 40 builder.PushNACK(12); 41 builder.PushNACK(15); 42 builder.PushNACK(18); 43 builder.PushNACK(19); 44 EXPECT_EQ(std::string("5,7,9-12,15,18-19"), builder.GetResult()); 45} 46 47TEST(NACKStringBuilderTest, TestCase2) { 48 NACKStringBuilder builder; 49 builder.PushNACK(5); 50 builder.PushNACK(6); 51 builder.PushNACK(7); 52 builder.PushNACK(9); 53 builder.PushNACK(10); 54 builder.PushNACK(11); 55 builder.PushNACK(12); 56 builder.PushNACK(15); 57 builder.PushNACK(18); 58 builder.PushNACK(19); 59 EXPECT_EQ(std::string("5-7,9-12,15,18-19"), builder.GetResult()); 60} 61 62TEST(NACKStringBuilderTest, TestCase3) { 63 NACKStringBuilder builder; 64 builder.PushNACK(5); 65 builder.PushNACK(7); 66 builder.PushNACK(9); 67 builder.PushNACK(10); 68 builder.PushNACK(11); 69 builder.PushNACK(12); 70 builder.PushNACK(15); 71 builder.PushNACK(18); 72 builder.PushNACK(19); 73 builder.PushNACK(21); 74 EXPECT_EQ(std::string("5,7,9-12,15,18-19,21"), builder.GetResult()); 75} 76 77TEST(NACKStringBuilderTest, TestCase4) { 78 NACKStringBuilder builder; 79 builder.PushNACK(5); 80 builder.PushNACK(7); 81 builder.PushNACK(8); 82 builder.PushNACK(9); 83 builder.PushNACK(10); 84 builder.PushNACK(11); 85 builder.PushNACK(12); 86 builder.PushNACK(15); 87 builder.PushNACK(18); 88 builder.PushNACK(19); 89 EXPECT_EQ(std::string("5,7-12,15,18-19"), builder.GetResult()); 90} 91 92TEST(NACKStringBuilderTest, TestCase5) { 93 NACKStringBuilder builder; 94 builder.PushNACK(5); 95 builder.PushNACK(7); 96 builder.PushNACK(9); 97 builder.PushNACK(10); 98 builder.PushNACK(11); 99 builder.PushNACK(12); 100 builder.PushNACK(15); 101 builder.PushNACK(16); 102 builder.PushNACK(18); 103 builder.PushNACK(19); 104 EXPECT_EQ(std::string("5,7,9-12,15-16,18-19"), builder.GetResult()); 105} 106 107TEST(NACKStringBuilderTest, TestCase6) { 108 NACKStringBuilder builder; 109 builder.PushNACK(5); 110 builder.PushNACK(7); 111 builder.PushNACK(9); 112 builder.PushNACK(10); 113 builder.PushNACK(11); 114 builder.PushNACK(12); 115 builder.PushNACK(15); 116 builder.PushNACK(16); 117 builder.PushNACK(17); 118 builder.PushNACK(18); 119 builder.PushNACK(19); 120 EXPECT_EQ(std::string("5,7,9-12,15-19"), builder.GetResult()); 121} 122 123TEST(NACKStringBuilderTest, TestCase7) { 124 NACKStringBuilder builder; 125 builder.PushNACK(5); 126 builder.PushNACK(6); 127 builder.PushNACK(7); 128 builder.PushNACK(8); 129 builder.PushNACK(11); 130 builder.PushNACK(12); 131 builder.PushNACK(13); 132 builder.PushNACK(14); 133 builder.PushNACK(15); 134 EXPECT_EQ(std::string("5-8,11-15"), builder.GetResult()); 135} 136 137TEST(NACKStringBuilderTest, TestCase8) { 138 NACKStringBuilder builder; 139 builder.PushNACK(5); 140 builder.PushNACK(7); 141 builder.PushNACK(9); 142 builder.PushNACK(11); 143 builder.PushNACK(15); 144 builder.PushNACK(17); 145 builder.PushNACK(19); 146 EXPECT_EQ(std::string("5,7,9,11,15,17,19"), builder.GetResult()); 147} 148 149TEST(NACKStringBuilderTest, TestCase9) { 150 NACKStringBuilder builder; 151 builder.PushNACK(5); 152 builder.PushNACK(6); 153 builder.PushNACK(7); 154 builder.PushNACK(8); 155 builder.PushNACK(9); 156 builder.PushNACK(10); 157 builder.PushNACK(11); 158 builder.PushNACK(12); 159 EXPECT_EQ(std::string("5-12"), builder.GetResult()); 160} 161 162TEST(NACKStringBuilderTest, TestCase10) { 163 NACKStringBuilder builder; 164 builder.PushNACK(5); 165 EXPECT_EQ(std::string("5"), builder.GetResult()); 166} 167 168TEST(NACKStringBuilderTest, TestCase11) { 169 NACKStringBuilder builder; 170 EXPECT_EQ(std::string(""), builder.GetResult()); 171} 172 173TEST(NACKStringBuilderTest, TestCase12) { 174 NACKStringBuilder builder; 175 builder.PushNACK(5); 176 builder.PushNACK(6); 177 EXPECT_EQ(std::string("5-6"), builder.GetResult()); 178} 179 180TEST(NACKStringBuilderTest, TestCase13) { 181 NACKStringBuilder builder; 182 builder.PushNACK(5); 183 builder.PushNACK(6); 184 builder.PushNACK(9); 185 EXPECT_EQ(std::string("5-6,9"), builder.GetResult()); 186} 187 188void CreateRtpPacket(const bool marker_bit, const uint8_t payload, 189 const uint16_t seq_num, const uint32_t timestamp, 190 const uint32_t ssrc, uint8_t* array, 191 uint16_t* cur_pos) { 192 ASSERT_TRUE(payload <= 127); 193 array[(*cur_pos)++] = 0x80; 194 array[(*cur_pos)++] = payload | (marker_bit ? 0x80 : 0); 195 array[(*cur_pos)++] = seq_num >> 8; 196 array[(*cur_pos)++] = seq_num; 197 array[(*cur_pos)++] = timestamp >> 24; 198 array[(*cur_pos)++] = timestamp >> 16; 199 array[(*cur_pos)++] = timestamp >> 8; 200 array[(*cur_pos)++] = timestamp; 201 array[(*cur_pos)++] = ssrc >> 24; 202 array[(*cur_pos)++] = ssrc >> 16; 203 array[(*cur_pos)++] = ssrc >> 8; 204 array[(*cur_pos)++] = ssrc; 205 // VP8 payload header 206 array[(*cur_pos)++] = 0x90; // X bit = 1 207 array[(*cur_pos)++] = 0x20; // T bit = 1 208 array[(*cur_pos)++] = 0x00; // TID = 0 209 array[(*cur_pos)++] = 0x00; // Key frame 210 array[(*cur_pos)++] = 0x00; 211 array[(*cur_pos)++] = 0x00; 212 array[(*cur_pos)++] = 0x9d; 213 array[(*cur_pos)++] = 0x01; 214 array[(*cur_pos)++] = 0x2a; 215 array[(*cur_pos)++] = 128; 216 array[(*cur_pos)++] = 0; 217 array[(*cur_pos)++] = 96; 218 array[(*cur_pos)++] = 0; 219} 220 221class TestTransport : public Transport, 222 public NullRtpData { 223 public: 224 TestTransport() 225 : rtcp_receiver_(NULL) { 226 } 227 void SetRTCPReceiver(RTCPReceiver* rtcp_receiver) { 228 rtcp_receiver_ = rtcp_receiver; 229 } 230 virtual int SendPacket(int /*ch*/, const void* /*data*/, int /*len*/) { 231 return -1; 232 } 233 234 virtual int SendRTCPPacket(int /*ch*/, const void *packet, int packet_len) { 235 RTCPUtility::RTCPParserV2 rtcpParser((uint8_t*)packet, 236 (int32_t)packet_len, 237 true); // Allow non-compound RTCP 238 239 EXPECT_TRUE(rtcpParser.IsValid()); 240 RTCPHelp::RTCPPacketInformation rtcpPacketInformation; 241 EXPECT_EQ(0, rtcp_receiver_->IncomingRTCPPacket(rtcpPacketInformation, 242 &rtcpParser)); 243 rtcp_packet_info_.rtcpPacketTypeFlags = 244 rtcpPacketInformation.rtcpPacketTypeFlags; 245 rtcp_packet_info_.remoteSSRC = rtcpPacketInformation.remoteSSRC; 246 rtcp_packet_info_.applicationSubType = 247 rtcpPacketInformation.applicationSubType; 248 rtcp_packet_info_.applicationName = rtcpPacketInformation.applicationName; 249 rtcp_packet_info_.reportBlock = rtcpPacketInformation.reportBlock; 250 rtcp_packet_info_.fractionLost = rtcpPacketInformation.fractionLost; 251 rtcp_packet_info_.roundTripTime = rtcpPacketInformation.roundTripTime; 252 rtcp_packet_info_.lastReceivedExtendedHighSeqNum = 253 rtcpPacketInformation.lastReceivedExtendedHighSeqNum; 254 rtcp_packet_info_.jitter = rtcpPacketInformation.jitter; 255 rtcp_packet_info_.interArrivalJitter = 256 rtcpPacketInformation.interArrivalJitter; 257 rtcp_packet_info_.sliPictureId = rtcpPacketInformation.sliPictureId; 258 rtcp_packet_info_.rpsiPictureId = rtcpPacketInformation.rpsiPictureId; 259 rtcp_packet_info_.receiverEstimatedMaxBitrate = 260 rtcpPacketInformation.receiverEstimatedMaxBitrate; 261 rtcp_packet_info_.ntp_secs = rtcpPacketInformation.ntp_secs; 262 rtcp_packet_info_.ntp_frac = rtcpPacketInformation.ntp_frac; 263 rtcp_packet_info_.rtp_timestamp = rtcpPacketInformation.rtp_timestamp; 264 265 return packet_len; 266 } 267 268 virtual int OnReceivedPayloadData(const uint8_t* payloadData, 269 const uint16_t payloadSize, 270 const WebRtcRTPHeader* rtpHeader) { 271 return 0; 272 } 273 RTCPReceiver* rtcp_receiver_; 274 RTCPHelp::RTCPPacketInformation rtcp_packet_info_; 275}; 276 277class RtcpSenderTest : public ::testing::Test { 278 protected: 279 RtcpSenderTest() 280 : over_use_detector_options_(), 281 system_clock_(Clock::GetRealTimeClock()), 282 rtp_payload_registry_(new RTPPayloadRegistry( 283 0, RTPPayloadStrategy::CreateStrategy(false))), 284 remote_bitrate_observer_(), 285 remote_bitrate_estimator_( 286 RemoteBitrateEstimatorFactory().Create( 287 &remote_bitrate_observer_, 288 system_clock_)) { 289 test_transport_ = new TestTransport(); 290 291 RtpRtcp::Configuration configuration; 292 configuration.id = 0; 293 configuration.audio = false; 294 configuration.clock = system_clock_; 295 configuration.outgoing_transport = test_transport_; 296 configuration.remote_bitrate_estimator = remote_bitrate_estimator_.get(); 297 298 rtp_rtcp_impl_ = new ModuleRtpRtcpImpl(configuration); 299 rtp_receiver_.reset(RtpReceiver::CreateVideoReceiver( 300 0, system_clock_, test_transport_, NULL, rtp_payload_registry_.get())); 301 rtcp_sender_ = new RTCPSender(0, false, system_clock_, rtp_rtcp_impl_); 302 rtcp_receiver_ = new RTCPReceiver(0, system_clock_, rtp_rtcp_impl_); 303 test_transport_->SetRTCPReceiver(rtcp_receiver_); 304 // Initialize 305 EXPECT_EQ(0, rtcp_sender_->Init()); 306 EXPECT_EQ(0, rtcp_sender_->RegisterSendTransport(test_transport_)); 307 } 308 ~RtcpSenderTest() { 309 delete rtcp_sender_; 310 delete rtcp_receiver_; 311 delete rtp_rtcp_impl_; 312 delete test_transport_; 313 } 314 315 // Helper function: Incoming RTCP has a specific packet type. 316 bool gotPacketType(RTCPPacketType packet_type) { 317 return ((test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags) & 318 packet_type) != 0U; 319 } 320 321 OverUseDetectorOptions over_use_detector_options_; 322 Clock* system_clock_; 323 scoped_ptr<RTPPayloadRegistry> rtp_payload_registry_; 324 scoped_ptr<RtpReceiver> rtp_receiver_; 325 ModuleRtpRtcpImpl* rtp_rtcp_impl_; 326 RTCPSender* rtcp_sender_; 327 RTCPReceiver* rtcp_receiver_; 328 TestTransport* test_transport_; 329 MockRemoteBitrateObserver remote_bitrate_observer_; 330 scoped_ptr<RemoteBitrateEstimator> remote_bitrate_estimator_; 331 332 enum {kMaxPacketLength = 1500}; 333 uint8_t packet_[kMaxPacketLength]; 334}; 335 336TEST_F(RtcpSenderTest, RtcpOff) { 337 EXPECT_EQ(0, rtcp_sender_->SetRTCPStatus(kRtcpOff)); 338 EXPECT_EQ(-1, rtcp_sender_->SendRTCP(kRtcpSr, NULL)); 339} 340 341TEST_F(RtcpSenderTest, IJStatus) { 342 ASSERT_FALSE(rtcp_sender_->IJ()); 343 EXPECT_EQ(0, rtcp_sender_->SetIJStatus(true)); 344 ASSERT_TRUE(rtcp_sender_->IJ()); 345} 346 347TEST_F(RtcpSenderTest, TestCompound) { 348 const bool marker_bit = false; 349 const uint8_t payload = 100; 350 const uint16_t seq_num = 11111; 351 const uint32_t timestamp = 1234567; 352 const uint32_t ssrc = 0x11111111; 353 uint16_t packet_length = 0; 354 CreateRtpPacket(marker_bit, payload, seq_num, timestamp, ssrc, packet_, 355 &packet_length); 356 EXPECT_EQ(25, packet_length); 357 358 VideoCodec codec_inst; 359 strncpy(codec_inst.plName, "VP8", webrtc::kPayloadNameSize - 1); 360 codec_inst.codecType = webrtc::kVideoCodecVP8; 361 codec_inst.plType = payload; 362 EXPECT_EQ(0, rtp_receiver_->RegisterReceivePayload(codec_inst.plName, 363 codec_inst.plType, 364 90000, 365 0, 366 codec_inst.maxBitrate)); 367 368 // Make sure RTP packet has been received. 369 scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create()); 370 RTPHeader header; 371 EXPECT_TRUE(parser->Parse(packet_, packet_length, &header)); 372 PayloadUnion payload_specific; 373 EXPECT_TRUE(rtp_payload_registry_->GetPayloadSpecifics(header.payloadType, 374 &payload_specific)); 375 EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(&header, packet_, packet_length, 376 payload_specific, true)); 377 378 EXPECT_EQ(0, rtcp_sender_->SetIJStatus(true)); 379 EXPECT_EQ(0, rtcp_sender_->SetRTCPStatus(kRtcpCompound)); 380 ReceiveStatistics::RtpReceiveStatistics receive_stats; 381 memset(&receive_stats, 0, sizeof(receive_stats)); 382 EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpRr, &receive_stats)); 383 384 // Transmission time offset packet should be received. 385 ASSERT_TRUE(test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags & 386 kRtcpTransmissionTimeOffset); 387} 388 389TEST_F(RtcpSenderTest, TestCompound_NoRtpReceived) { 390 EXPECT_EQ(0, rtcp_sender_->SetIJStatus(true)); 391 EXPECT_EQ(0, rtcp_sender_->SetRTCPStatus(kRtcpCompound)); 392 // |receive_stats| is NULL since no data has been received. 393 ReceiveStatistics::RtpReceiveStatistics* receive_stats = NULL; 394 EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpRr, receive_stats)); 395 396 // Transmission time offset packet should not be received. 397 ASSERT_FALSE(test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags & 398 kRtcpTransmissionTimeOffset); 399} 400 401// This test is written to verify actual behaviour. It does not seem 402// to make much sense to send an empty TMMBN, since there is no place 403// to put an actual limit here. It's just information that no limit 404// is set, which is kind of the starting assumption. 405// See http://code.google.com/p/webrtc/issues/detail?id=468 for one 406// situation where this caused confusion. 407TEST_F(RtcpSenderTest, SendsTmmbnIfSetAndEmpty) { 408 EXPECT_EQ(0, rtcp_sender_->SetRTCPStatus(kRtcpCompound)); 409 TMMBRSet bounding_set; 410 EXPECT_EQ(0, rtcp_sender_->SetTMMBN(&bounding_set, 3)); 411 ASSERT_EQ(0U, test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags); 412 ReceiveStatistics::RtpReceiveStatistics receive_stats; 413 memset(&receive_stats, 0, sizeof(receive_stats)); 414 EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpSr, &receive_stats)); 415 // We now expect the packet to show up in the rtcp_packet_info_ of 416 // test_transport_. 417 ASSERT_NE(0U, test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags); 418 EXPECT_TRUE(gotPacketType(kRtcpTmmbn)); 419 TMMBRSet* incoming_set = NULL; 420 bool owner = false; 421 // The BoundingSet function returns the number of members of the 422 // bounding set, and touches the incoming set only if there's > 1. 423 EXPECT_EQ(0, test_transport_->rtcp_receiver_->BoundingSet(owner, 424 incoming_set)); 425} 426 427TEST_F(RtcpSenderTest, SendsTmmbnIfSetAndValid) { 428 EXPECT_EQ(0, rtcp_sender_->SetRTCPStatus(kRtcpCompound)); 429 TMMBRSet bounding_set; 430 bounding_set.VerifyAndAllocateSet(1); 431 const uint32_t kSourceSsrc = 12345; 432 bounding_set.AddEntry(32768, 0, kSourceSsrc); 433 434 EXPECT_EQ(0, rtcp_sender_->SetTMMBN(&bounding_set, 3)); 435 ASSERT_EQ(0U, test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags); 436 ReceiveStatistics::RtpReceiveStatistics receive_stats; 437 memset(&receive_stats, 0, sizeof(receive_stats)); 438 EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpSr, &receive_stats)); 439 // We now expect the packet to show up in the rtcp_packet_info_ of 440 // test_transport_. 441 ASSERT_NE(0U, test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags); 442 EXPECT_TRUE(gotPacketType(kRtcpTmmbn)); 443 TMMBRSet incoming_set; 444 bool owner = false; 445 // We expect 1 member of the incoming set. 446 EXPECT_EQ(1, test_transport_->rtcp_receiver_->BoundingSet(owner, 447 &incoming_set)); 448 EXPECT_EQ(kSourceSsrc, incoming_set.Ssrc(0)); 449} 450} // namespace webrtc 451