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