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#include <algorithm>
12#include <vector>
13
14#include "testing/gmock/include/gmock/gmock.h"
15#include "testing/gtest/include/gtest/gtest.h"
16#include "webrtc/common_types.h"
17#include "webrtc/modules/rtp_rtcp/include/receive_statistics.h"
18#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
19#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
20#include "webrtc/modules/rtp_rtcp/source/rtp_receiver_audio.h"
21#include "webrtc/modules/rtp_rtcp/test/testAPI/test_api.h"
22
23namespace webrtc {
24namespace {
25
26const uint64_t kTestPictureId = 12345678;
27const uint8_t kSliPictureId = 156;
28
29class RtcpCallback : public RtcpIntraFrameObserver {
30 public:
31  void SetModule(RtpRtcp* module) {
32    _rtpRtcpModule = module;
33  }
34  virtual void OnRTCPPacketTimeout(const int32_t id) {
35  }
36  virtual void OnLipSyncUpdate(const int32_t id,
37                               const int32_t audioVideoOffset) {}
38  virtual void OnReceivedIntraFrameRequest(uint32_t ssrc) {}
39  virtual void OnReceivedSLI(uint32_t ssrc,
40                             uint8_t pictureId) {
41    EXPECT_EQ(kSliPictureId & 0x3f, pictureId);
42  }
43  virtual void OnReceivedRPSI(uint32_t ssrc,
44                              uint64_t pictureId) {
45    EXPECT_EQ(kTestPictureId, pictureId);
46  }
47  virtual void OnLocalSsrcChanged(uint32_t old_ssrc, uint32_t new_ssrc) {}
48
49 private:
50  RtpRtcp* _rtpRtcpModule;
51};
52
53class TestRtpFeedback : public NullRtpFeedback {
54 public:
55  explicit TestRtpFeedback(RtpRtcp* rtp_rtcp) : rtp_rtcp_(rtp_rtcp) {}
56  virtual ~TestRtpFeedback() {}
57
58  void OnIncomingSSRCChanged(const uint32_t ssrc) override {
59    rtp_rtcp_->SetRemoteSSRC(ssrc);
60  }
61
62 private:
63  RtpRtcp* rtp_rtcp_;
64};
65
66class RtpRtcpRtcpTest : public ::testing::Test {
67 protected:
68  RtpRtcpRtcpTest() : fake_clock(123456) {
69    test_csrcs.push_back(1234);
70    test_csrcs.push_back(2345);
71    test_ssrc = 3456;
72    test_timestamp = 4567;
73    test_sequence_number = 2345;
74  }
75  ~RtpRtcpRtcpTest() {}
76
77  virtual void SetUp() {
78    receiver = new TestRtpReceiver();
79    transport1 = new LoopBackTransport();
80    transport2 = new LoopBackTransport();
81    myRTCPFeedback1 = new RtcpCallback();
82    myRTCPFeedback2 = new RtcpCallback();
83
84    receive_statistics1_.reset(ReceiveStatistics::Create(&fake_clock));
85    receive_statistics2_.reset(ReceiveStatistics::Create(&fake_clock));
86
87    RtpRtcp::Configuration configuration;
88    configuration.audio = true;
89    configuration.clock = &fake_clock;
90    configuration.receive_statistics = receive_statistics1_.get();
91    configuration.outgoing_transport = transport1;
92    configuration.intra_frame_callback = myRTCPFeedback1;
93
94    rtp_payload_registry1_.reset(new RTPPayloadRegistry(
95            RTPPayloadStrategy::CreateStrategy(true)));
96    rtp_payload_registry2_.reset(new RTPPayloadRegistry(
97            RTPPayloadStrategy::CreateStrategy(true)));
98
99    module1 = RtpRtcp::CreateRtpRtcp(configuration);
100
101    rtp_feedback1_.reset(new TestRtpFeedback(module1));
102
103    rtp_receiver1_.reset(RtpReceiver::CreateAudioReceiver(
104        &fake_clock, NULL, receiver, rtp_feedback1_.get(),
105        rtp_payload_registry1_.get()));
106
107    configuration.receive_statistics = receive_statistics2_.get();
108    configuration.outgoing_transport = transport2;
109    configuration.intra_frame_callback = myRTCPFeedback2;
110
111    module2 = RtpRtcp::CreateRtpRtcp(configuration);
112
113    rtp_feedback2_.reset(new TestRtpFeedback(module2));
114
115    rtp_receiver2_.reset(RtpReceiver::CreateAudioReceiver(
116        &fake_clock, NULL, receiver, rtp_feedback2_.get(),
117        rtp_payload_registry2_.get()));
118
119    transport1->SetSendModule(module2, rtp_payload_registry2_.get(),
120                              rtp_receiver2_.get(), receive_statistics2_.get());
121    transport2->SetSendModule(module1, rtp_payload_registry1_.get(),
122                              rtp_receiver1_.get(), receive_statistics1_.get());
123    myRTCPFeedback1->SetModule(module1);
124    myRTCPFeedback2->SetModule(module2);
125
126    module1->SetRTCPStatus(RtcpMode::kCompound);
127    module2->SetRTCPStatus(RtcpMode::kCompound);
128
129    module2->SetSSRC(test_ssrc + 1);
130    module1->SetSSRC(test_ssrc);
131    module1->SetSequenceNumber(test_sequence_number);
132    module1->SetStartTimestamp(test_timestamp);
133
134    module1->SetCsrcs(test_csrcs);
135    EXPECT_EQ(0, module1->SetCNAME("john.doe@test.test"));
136
137    EXPECT_EQ(0, module1->SetSendingStatus(true));
138
139    CodecInst voice_codec;
140    voice_codec.pltype = 96;
141    voice_codec.plfreq = 8000;
142    voice_codec.rate = 64000;
143    memcpy(voice_codec.plname, "PCMU", 5);
144
145    EXPECT_EQ(0, module1->RegisterSendPayload(voice_codec));
146    EXPECT_EQ(0, rtp_receiver1_->RegisterReceivePayload(
147        voice_codec.plname,
148        voice_codec.pltype,
149        voice_codec.plfreq,
150        voice_codec.channels,
151        (voice_codec.rate < 0) ? 0 : voice_codec.rate));
152    EXPECT_EQ(0, module2->RegisterSendPayload(voice_codec));
153    EXPECT_EQ(0, rtp_receiver2_->RegisterReceivePayload(
154        voice_codec.plname,
155        voice_codec.pltype,
156        voice_codec.plfreq,
157        voice_codec.channels,
158        (voice_codec.rate < 0) ? 0 : voice_codec.rate));
159
160    // We need to send one RTP packet to get the RTCP packet to be accepted by
161    // the receiving module.
162    // send RTP packet with the data "testtest"
163    const uint8_t test[9] = "testtest";
164    EXPECT_EQ(0, module1->SendOutgoingData(webrtc::kAudioFrameSpeech, 96,
165                                           0, -1, test, 8));
166  }
167
168  virtual void TearDown() {
169    delete module1;
170    delete module2;
171    delete myRTCPFeedback1;
172    delete myRTCPFeedback2;
173    delete transport1;
174    delete transport2;
175    delete receiver;
176  }
177
178  rtc::scoped_ptr<TestRtpFeedback> rtp_feedback1_;
179  rtc::scoped_ptr<TestRtpFeedback> rtp_feedback2_;
180  rtc::scoped_ptr<ReceiveStatistics> receive_statistics1_;
181  rtc::scoped_ptr<ReceiveStatistics> receive_statistics2_;
182  rtc::scoped_ptr<RTPPayloadRegistry> rtp_payload_registry1_;
183  rtc::scoped_ptr<RTPPayloadRegistry> rtp_payload_registry2_;
184  rtc::scoped_ptr<RtpReceiver> rtp_receiver1_;
185  rtc::scoped_ptr<RtpReceiver> rtp_receiver2_;
186  RtpRtcp* module1;
187  RtpRtcp* module2;
188  TestRtpReceiver* receiver;
189  LoopBackTransport* transport1;
190  LoopBackTransport* transport2;
191  RtcpCallback* myRTCPFeedback1;
192  RtcpCallback* myRTCPFeedback2;
193
194  uint32_t test_ssrc;
195  uint32_t test_timestamp;
196  uint16_t test_sequence_number;
197  std::vector<uint32_t> test_csrcs;
198  SimulatedClock fake_clock;
199};
200
201TEST_F(RtpRtcpRtcpTest, RTCP_PLI_RPSI) {
202  EXPECT_EQ(0, module1->SendRTCPReferencePictureSelection(kTestPictureId));
203  EXPECT_EQ(0, module1->SendRTCPSliceLossIndication(kSliPictureId));
204}
205
206TEST_F(RtpRtcpRtcpTest, RTCP_CNAME) {
207  uint32_t testOfCSRC[webrtc::kRtpCsrcSize];
208  EXPECT_EQ(2, rtp_receiver2_->CSRCs(testOfCSRC));
209  EXPECT_EQ(test_csrcs[0], testOfCSRC[0]);
210  EXPECT_EQ(test_csrcs[1], testOfCSRC[1]);
211
212  // Set cname of mixed.
213  EXPECT_EQ(0, module1->AddMixedCNAME(test_csrcs[0], "john@192.168.0.1"));
214  EXPECT_EQ(0, module1->AddMixedCNAME(test_csrcs[1], "jane@192.168.0.2"));
215
216  EXPECT_EQ(-1, module1->RemoveMixedCNAME(test_csrcs[0] + 1));
217  EXPECT_EQ(0, module1->RemoveMixedCNAME(test_csrcs[1]));
218  EXPECT_EQ(0, module1->AddMixedCNAME(test_csrcs[1], "jane@192.168.0.2"));
219
220  // send RTCP packet, triggered by timer
221  fake_clock.AdvanceTimeMilliseconds(7500);
222  module1->Process();
223  fake_clock.AdvanceTimeMilliseconds(100);
224  module2->Process();
225
226  char cName[RTCP_CNAME_SIZE];
227  EXPECT_EQ(-1, module2->RemoteCNAME(rtp_receiver2_->SSRC() + 1, cName));
228
229  // Check multiple CNAME.
230  EXPECT_EQ(0, module2->RemoteCNAME(rtp_receiver2_->SSRC(), cName));
231  EXPECT_EQ(0, strncmp(cName, "john.doe@test.test", RTCP_CNAME_SIZE));
232
233  EXPECT_EQ(0, module2->RemoteCNAME(test_csrcs[0], cName));
234  EXPECT_EQ(0, strncmp(cName, "john@192.168.0.1", RTCP_CNAME_SIZE));
235
236  EXPECT_EQ(0, module2->RemoteCNAME(test_csrcs[1], cName));
237  EXPECT_EQ(0, strncmp(cName, "jane@192.168.0.2", RTCP_CNAME_SIZE));
238
239  EXPECT_EQ(0, module1->SetSendingStatus(false));
240
241  // Test that BYE clears the CNAME
242  EXPECT_EQ(-1, module2->RemoteCNAME(rtp_receiver2_->SSRC(), cName));
243}
244
245TEST_F(RtpRtcpRtcpTest, RemoteRTCPStatRemote) {
246  std::vector<RTCPReportBlock> report_blocks;
247
248  EXPECT_EQ(0, module1->RemoteRTCPStat(&report_blocks));
249  EXPECT_EQ(0u, report_blocks.size());
250
251  // send RTCP packet, triggered by timer
252  fake_clock.AdvanceTimeMilliseconds(7500);
253  module1->Process();
254  fake_clock.AdvanceTimeMilliseconds(100);
255  module2->Process();
256
257  EXPECT_EQ(0, module1->RemoteRTCPStat(&report_blocks));
258  ASSERT_EQ(1u, report_blocks.size());
259
260  // |test_ssrc+1| is the SSRC of module2 that send the report.
261  EXPECT_EQ(test_ssrc+1, report_blocks[0].remoteSSRC);
262  EXPECT_EQ(test_ssrc, report_blocks[0].sourceSSRC);
263
264  EXPECT_EQ(0u, report_blocks[0].cumulativeLost);
265  EXPECT_LT(0u, report_blocks[0].delaySinceLastSR);
266  EXPECT_EQ(test_sequence_number, report_blocks[0].extendedHighSeqNum);
267  EXPECT_EQ(0u, report_blocks[0].fractionLost);
268}
269
270}  // namespace
271}  // namespace webrtc
272