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 "webrtc/system_wrappers/interface/atomic32.h"
12#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
13#include "webrtc/system_wrappers/interface/event_wrapper.h"
14#include "webrtc/test/testsupport/fileutils.h"
15#include "webrtc/voice_engine/test/auto_test/fixtures/after_streaming_fixture.h"
16#include "webrtc/voice_engine/test/auto_test/voe_standard_test.h"
17
18class TestRtpObserver : public webrtc::VoERTPObserver {
19 public:
20  TestRtpObserver()
21      : crit_(voetest::CriticalSectionWrapper::CreateCriticalSection()),
22        changed_ssrc_event_(voetest::EventWrapper::Create()) {}
23  virtual ~TestRtpObserver() {}
24  virtual void OnIncomingCSRCChanged(int channel,
25                                     unsigned int CSRC,
26                                     bool added) {}
27  virtual void OnIncomingSSRCChanged(int channel,
28                                     unsigned int SSRC);
29  void WaitForChangedSsrc() {
30    // 10 seconds should be enough.
31    EXPECT_EQ(voetest::kEventSignaled, changed_ssrc_event_->Wait(10*1000));
32    changed_ssrc_event_->Reset();
33  }
34  void SetIncomingSsrc(unsigned int ssrc) {
35    voetest::CriticalSectionScoped lock(crit_.get());
36    incoming_ssrc_ = ssrc;
37  }
38 public:
39  voetest::scoped_ptr<voetest::CriticalSectionWrapper> crit_;
40  unsigned int incoming_ssrc_;
41  voetest::scoped_ptr<voetest::EventWrapper> changed_ssrc_event_;
42};
43
44void TestRtpObserver::OnIncomingSSRCChanged(int channel,
45                                            unsigned int SSRC) {
46  char msg[128];
47  sprintf(msg, "\n=> OnIncomingSSRCChanged(channel=%d, SSRC=%u)\n", channel,
48          SSRC);
49  TEST_LOG("%s", msg);
50
51  {
52    voetest::CriticalSectionScoped lock(crit_.get());
53    if (incoming_ssrc_ == SSRC)
54      changed_ssrc_event_->Set();
55  }
56}
57
58class RtcpAppHandler : public webrtc::VoERTCPObserver {
59 public:
60  RtcpAppHandler() : length_in_bytes_(0), sub_type_(0), name_(0) {}
61  void OnApplicationDataReceived(int channel,
62                                 unsigned char sub_type,
63                                 unsigned int name,
64                                 const unsigned char* data,
65                                 unsigned short length_in_bytes);
66  void Reset();
67  ~RtcpAppHandler() {}
68  unsigned short length_in_bytes_;
69  unsigned char data_[256];
70  unsigned char sub_type_;
71  unsigned int name_;
72};
73
74
75static const char* const RTCP_CNAME = "Whatever";
76
77class RtpRtcpTest : public AfterStreamingFixture {
78 protected:
79  void SetUp() {
80    // We need a second channel for this test, so set it up.
81    second_channel_ = voe_base_->CreateChannel();
82    EXPECT_GE(second_channel_, 0);
83
84    transport_ = new LoopBackTransport(voe_network_);
85    EXPECT_EQ(0, voe_network_->RegisterExternalTransport(second_channel_,
86                                                         *transport_));
87
88    EXPECT_EQ(0, voe_base_->StartReceive(second_channel_));
89    EXPECT_EQ(0, voe_base_->StartPlayout(second_channel_));
90    EXPECT_EQ(0, voe_rtp_rtcp_->SetLocalSSRC(second_channel_, 5678));
91    EXPECT_EQ(0, voe_base_->StartSend(second_channel_));
92
93    // We'll set up the RTCP CNAME and SSRC to something arbitrary here.
94    voe_rtp_rtcp_->SetRTCP_CNAME(channel_, RTCP_CNAME);
95  }
96
97  void TearDown() {
98    EXPECT_EQ(0, voe_network_->DeRegisterExternalTransport(second_channel_));
99    voe_base_->DeleteChannel(second_channel_);
100    delete transport_;
101  }
102
103  int second_channel_;
104  LoopBackTransport* transport_;
105};
106
107void RtcpAppHandler::OnApplicationDataReceived(
108    const int /*channel*/, unsigned char sub_type,
109    unsigned int name, const unsigned char* data,
110    unsigned short length_in_bytes) {
111  length_in_bytes_ = length_in_bytes;
112  memcpy(data_, &data[0], length_in_bytes);
113  sub_type_ = sub_type;
114  name_ = name;
115}
116
117void RtcpAppHandler::Reset() {
118  length_in_bytes_ = 0;
119  memset(data_, 0, sizeof(data_));
120  sub_type_ = 0;
121  name_ = 0;
122}
123
124TEST_F(RtpRtcpTest, RemoteRtcpCnameHasPropagatedToRemoteSide) {
125  if (!FLAGS_include_timing_dependent_tests) {
126    TEST_LOG("Skipping test - running in slow execution environment...\n");
127    return;
128  }
129
130  // We need to sleep a bit here for the name to propagate. For instance,
131  // 200 milliseconds is not enough, so we'll go with one second here.
132  Sleep(1000);
133
134  char char_buffer[256];
135  voe_rtp_rtcp_->GetRemoteRTCP_CNAME(channel_, char_buffer);
136  EXPECT_STREQ(RTCP_CNAME, char_buffer);
137}
138
139// Flakily hangs on Linux. code.google.com/p/webrtc/issues/detail?id=2178.
140TEST_F(RtpRtcpTest, DISABLED_ON_LINUX(SSRCPropagatesCorrectly)) {
141  unsigned int local_ssrc = 1234;
142  EXPECT_EQ(0, voe_base_->StopSend(channel_));
143  EXPECT_EQ(0, voe_rtp_rtcp_->SetLocalSSRC(channel_, local_ssrc));
144  EXPECT_EQ(0, voe_base_->StartSend(channel_));
145
146  Sleep(1000);
147
148  unsigned int ssrc;
149  EXPECT_EQ(0, voe_rtp_rtcp_->GetLocalSSRC(channel_, ssrc));
150  EXPECT_EQ(local_ssrc, ssrc);
151
152  EXPECT_EQ(0, voe_rtp_rtcp_->GetRemoteSSRC(channel_, ssrc));
153  EXPECT_EQ(local_ssrc, ssrc);
154}
155
156// TODO(xians, phoglund): Re-enable when issue 372 is resolved.
157TEST_F(RtpRtcpTest, DISABLED_CanCreateRtpDumpFilesWithoutError) {
158  // Create two RTP dump files (3 seconds long). You can verify these after
159  // the test using rtpplay or NetEqRTPplay if you like.
160  std::string output_path = webrtc::test::OutputPath();
161  std::string incoming_filename = output_path + "dump_in_3sec.rtp";
162  std::string outgoing_filename = output_path + "dump_out_3sec.rtp";
163
164  EXPECT_EQ(0, voe_rtp_rtcp_->StartRTPDump(
165      channel_, incoming_filename.c_str(), webrtc::kRtpIncoming));
166  EXPECT_EQ(0, voe_rtp_rtcp_->StartRTPDump(
167      channel_, outgoing_filename.c_str(), webrtc::kRtpOutgoing));
168
169  Sleep(3000);
170
171  EXPECT_EQ(0, voe_rtp_rtcp_->StopRTPDump(channel_, webrtc::kRtpIncoming));
172  EXPECT_EQ(0, voe_rtp_rtcp_->StopRTPDump(channel_, webrtc::kRtpOutgoing));
173}
174
175