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