rtcp_sender_unittest.cc revision 0cb48a0a18a5fa40107b83c147101c9cef85e116
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 <gmock/gmock.h> 17#include <gtest/gtest.h> 18 19#include "common_types.h" 20#include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h" 21#include "modules/remote_bitrate_estimator/include/mock/mock_remote_bitrate_observer.h" 22#include "modules/rtp_rtcp/source/rtcp_receiver.h" 23#include "modules/rtp_rtcp/source/rtcp_sender.h" 24#include "modules/rtp_rtcp/source/rtp_utility.h" 25#include "modules/rtp_rtcp/source/rtp_rtcp_impl.h" 26 27namespace webrtc { 28 29void CreateRtpPacket(const bool marker_bit, const WebRtc_UWord8 payload, 30 const WebRtc_UWord16 seq_num, const WebRtc_UWord32 timestamp, 31 const WebRtc_UWord32 ssrc, WebRtc_UWord8* array, 32 WebRtc_UWord16* cur_pos) { 33 ASSERT_TRUE(payload <= 127); 34 array[(*cur_pos)++] = 0x80; 35 array[(*cur_pos)++] = payload | (marker_bit ? 0x80 : 0); 36 array[(*cur_pos)++] = seq_num >> 8; 37 array[(*cur_pos)++] = seq_num; 38 array[(*cur_pos)++] = timestamp >> 24; 39 array[(*cur_pos)++] = timestamp >> 16; 40 array[(*cur_pos)++] = timestamp >> 8; 41 array[(*cur_pos)++] = timestamp; 42 array[(*cur_pos)++] = ssrc >> 24; 43 array[(*cur_pos)++] = ssrc >> 16; 44 array[(*cur_pos)++] = ssrc >> 8; 45 array[(*cur_pos)++] = ssrc; 46 // VP8 payload header 47 array[(*cur_pos)++] = 0x90; // X bit = 1 48 array[(*cur_pos)++] = 0x20; // T bit = 1 49 array[(*cur_pos)++] = 0x00; // TID = 0 50 array[(*cur_pos)++] = 0x00; // Key frame 51 array[(*cur_pos)++] = 0x00; 52 array[(*cur_pos)++] = 0x00; 53 array[(*cur_pos)++] = 0x9d; 54 array[(*cur_pos)++] = 0x01; 55 array[(*cur_pos)++] = 0x2a; 56 array[(*cur_pos)++] = 128; 57 array[(*cur_pos)++] = 0; 58 array[(*cur_pos)++] = 96; 59 array[(*cur_pos)++] = 0; 60} 61 62class TestTransport : public Transport, 63 public RtpData { 64 public: 65 TestTransport() 66 : rtcp_receiver_(NULL) { 67 } 68 void SetRTCPReceiver(RTCPReceiver* rtcp_receiver) { 69 rtcp_receiver_ = rtcp_receiver; 70 } 71 virtual int SendPacket(int /*ch*/, const void* /*data*/, int /*len*/) { 72 return -1; 73 } 74 75 virtual int SendRTCPPacket(int /*ch*/, const void *packet, int packet_len) { 76 RTCPUtility::RTCPParserV2 rtcpParser((WebRtc_UWord8*)packet, 77 (WebRtc_Word32)packet_len, 78 true); // Allow non-compound RTCP 79 80 EXPECT_TRUE(rtcpParser.IsValid()); 81 RTCPHelp::RTCPPacketInformation rtcpPacketInformation; 82 EXPECT_EQ(0, rtcp_receiver_->IncomingRTCPPacket(rtcpPacketInformation, 83 &rtcpParser)); 84 rtcp_packet_info_.rtcpPacketTypeFlags = 85 rtcpPacketInformation.rtcpPacketTypeFlags; 86 rtcp_packet_info_.remoteSSRC = rtcpPacketInformation.remoteSSRC; 87 rtcp_packet_info_.applicationSubType = 88 rtcpPacketInformation.applicationSubType; 89 rtcp_packet_info_.applicationName = rtcpPacketInformation.applicationName; 90 rtcp_packet_info_.reportBlock = rtcpPacketInformation.reportBlock; 91 rtcp_packet_info_.fractionLost = rtcpPacketInformation.fractionLost; 92 rtcp_packet_info_.roundTripTime = rtcpPacketInformation.roundTripTime; 93 rtcp_packet_info_.lastReceivedExtendedHighSeqNum = 94 rtcpPacketInformation.lastReceivedExtendedHighSeqNum; 95 rtcp_packet_info_.jitter = rtcpPacketInformation.jitter; 96 rtcp_packet_info_.interArrivalJitter = 97 rtcpPacketInformation.interArrivalJitter; 98 rtcp_packet_info_.sliPictureId = rtcpPacketInformation.sliPictureId; 99 rtcp_packet_info_.rpsiPictureId = rtcpPacketInformation.rpsiPictureId; 100 rtcp_packet_info_.receiverEstimatedMaxBitrate = 101 rtcpPacketInformation.receiverEstimatedMaxBitrate; 102 rtcp_packet_info_.ntp_secs = rtcpPacketInformation.ntp_secs; 103 rtcp_packet_info_.ntp_frac = rtcpPacketInformation.ntp_frac; 104 rtcp_packet_info_.rtp_timestamp = rtcpPacketInformation.rtp_timestamp; 105 106 return packet_len; 107 } 108 109 virtual int OnReceivedPayloadData(const WebRtc_UWord8* payloadData, 110 const WebRtc_UWord16 payloadSize, 111 const WebRtcRTPHeader* rtpHeader) { 112 return 0; 113 } 114 RTCPReceiver* rtcp_receiver_; 115 RTCPHelp::RTCPPacketInformation rtcp_packet_info_; 116}; 117 118class RtcpSenderTest : public ::testing::Test { 119 protected: 120 RtcpSenderTest() 121 : over_use_detector_options_(), 122 system_clock_(Clock::GetRealTimeClock()), 123 remote_bitrate_observer_(), 124 remote_bitrate_estimator_( 125 RemoteBitrateEstimator::Create( 126 over_use_detector_options_, 127 RemoteBitrateEstimator::kSingleStreamEstimation, 128 &remote_bitrate_observer_, 129 system_clock_)) { 130 test_transport_ = new TestTransport(); 131 132 RtpRtcp::Configuration configuration; 133 configuration.id = 0; 134 configuration.audio = false; 135 configuration.clock = system_clock_; 136 configuration.incoming_data = test_transport_; 137 configuration.outgoing_transport = test_transport_; 138 configuration.remote_bitrate_estimator = remote_bitrate_estimator_.get(); 139 140 rtp_rtcp_impl_ = new ModuleRtpRtcpImpl(configuration); 141 rtcp_sender_ = new RTCPSender(0, false, system_clock_, rtp_rtcp_impl_); 142 rtcp_receiver_ = new RTCPReceiver(0, system_clock_, rtp_rtcp_impl_); 143 test_transport_->SetRTCPReceiver(rtcp_receiver_); 144 // Initialize 145 EXPECT_EQ(0, rtcp_sender_->Init()); 146 EXPECT_EQ(0, rtcp_sender_->RegisterSendTransport(test_transport_)); 147 } 148 ~RtcpSenderTest() { 149 delete rtcp_sender_; 150 delete rtcp_receiver_; 151 delete rtp_rtcp_impl_; 152 delete test_transport_; 153 } 154 155 // Helper function: Incoming RTCP has a specific packet type. 156 bool gotPacketType(RTCPPacketType packet_type) { 157 return ((test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags) & 158 packet_type) != 0U; 159 } 160 161 OverUseDetectorOptions over_use_detector_options_; 162 Clock* system_clock_; 163 ModuleRtpRtcpImpl* rtp_rtcp_impl_; 164 RTCPSender* rtcp_sender_; 165 RTCPReceiver* rtcp_receiver_; 166 TestTransport* test_transport_; 167 MockRemoteBitrateObserver remote_bitrate_observer_; 168 scoped_ptr<RemoteBitrateEstimator> remote_bitrate_estimator_; 169 170 enum {kMaxPacketLength = 1500}; 171 uint8_t packet_[kMaxPacketLength]; 172}; 173 174TEST_F(RtcpSenderTest, RtcpOff) { 175 EXPECT_EQ(0, rtcp_sender_->SetRTCPStatus(kRtcpOff)); 176 EXPECT_EQ(-1, rtcp_sender_->SendRTCP(kRtcpSr)); 177} 178 179TEST_F(RtcpSenderTest, IJStatus) { 180 ASSERT_FALSE(rtcp_sender_->IJ()); 181 EXPECT_EQ(0, rtcp_sender_->SetIJStatus(true)); 182 ASSERT_TRUE(rtcp_sender_->IJ()); 183} 184 185TEST_F(RtcpSenderTest, TestCompound) { 186 const bool marker_bit = false; 187 const WebRtc_UWord8 payload = 100; 188 const WebRtc_UWord16 seq_num = 11111; 189 const WebRtc_UWord32 timestamp = 1234567; 190 const WebRtc_UWord32 ssrc = 0x11111111; 191 WebRtc_UWord16 packet_length = 0; 192 CreateRtpPacket(marker_bit, payload, seq_num, timestamp, ssrc, packet_, 193 &packet_length); 194 EXPECT_EQ(25, packet_length); 195 196 VideoCodec codec_inst; 197 strncpy(codec_inst.plName, "VP8", webrtc::kPayloadNameSize - 1); 198 codec_inst.codecType = webrtc::kVideoCodecVP8; 199 codec_inst.plType = payload; 200 EXPECT_EQ(0, rtp_rtcp_impl_->RegisterReceivePayload(codec_inst)); 201 202 // Make sure RTP packet has been received. 203 EXPECT_EQ(0, rtp_rtcp_impl_->IncomingPacket(packet_, packet_length)); 204 205 EXPECT_EQ(0, rtcp_sender_->SetIJStatus(true)); 206 EXPECT_EQ(0, rtcp_sender_->SetRTCPStatus(kRtcpCompound)); 207 EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpRr)); 208 209 // Transmission time offset packet should be received. 210 ASSERT_TRUE(test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags & 211 kRtcpTransmissionTimeOffset); 212} 213 214TEST_F(RtcpSenderTest, TestCompound_NoRtpReceived) { 215 EXPECT_EQ(0, rtcp_sender_->SetIJStatus(true)); 216 EXPECT_EQ(0, rtcp_sender_->SetRTCPStatus(kRtcpCompound)); 217 EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpRr)); 218 219 // Transmission time offset packet should not be received. 220 ASSERT_FALSE(test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags & 221 kRtcpTransmissionTimeOffset); 222} 223 224// This test is written to verify actual behaviour. It does not seem 225// to make much sense to send an empty TMMBN, since there is no place 226// to put an actual limit here. It's just information that no limit 227// is set, which is kind of the starting assumption. 228// See http://code.google.com/p/webrtc/issues/detail?id=468 for one 229// situation where this caused confusion. 230TEST_F(RtcpSenderTest, SendsTmmbnIfSetAndEmpty) { 231 EXPECT_EQ(0, rtcp_sender_->SetRTCPStatus(kRtcpCompound)); 232 TMMBRSet bounding_set; 233 EXPECT_EQ(0, rtcp_sender_->SetTMMBN(&bounding_set, 3)); 234 ASSERT_EQ(0U, test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags); 235 EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpSr)); 236 // We now expect the packet to show up in the rtcp_packet_info_ of 237 // test_transport_. 238 ASSERT_NE(0U, test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags); 239 EXPECT_TRUE(gotPacketType(kRtcpTmmbn)); 240 TMMBRSet* incoming_set = NULL; 241 bool owner = false; 242 // The BoundingSet function returns the number of members of the 243 // bounding set, and touches the incoming set only if there's > 1. 244 EXPECT_EQ(0, test_transport_->rtcp_receiver_->BoundingSet(owner, 245 incoming_set)); 246} 247 248TEST_F(RtcpSenderTest, SendsTmmbnIfSetAndValid) { 249 EXPECT_EQ(0, rtcp_sender_->SetRTCPStatus(kRtcpCompound)); 250 TMMBRSet bounding_set; 251 bounding_set.VerifyAndAllocateSet(1); 252 const WebRtc_UWord32 kSourceSsrc = 12345; 253 bounding_set.AddEntry(32768, 0, kSourceSsrc); 254 255 EXPECT_EQ(0, rtcp_sender_->SetTMMBN(&bounding_set, 3)); 256 ASSERT_EQ(0U, test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags); 257 EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpSr)); 258 // We now expect the packet to show up in the rtcp_packet_info_ of 259 // test_transport_. 260 ASSERT_NE(0U, test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags); 261 EXPECT_TRUE(gotPacketType(kRtcpTmmbn)); 262 TMMBRSet incoming_set; 263 bool owner = false; 264 // We expect 1 member of the incoming set. 265 EXPECT_EQ(1, test_transport_->rtcp_receiver_->BoundingSet(owner, 266 &incoming_set)); 267 EXPECT_EQ(kSourceSsrc, incoming_set.Ssrc(0)); 268} 269} // namespace webrtc 270