• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2015 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/voice_engine/test/auto_test/fakes/conference_transport.h"
12 
13 #include <string>
14 
15 #include "webrtc/base/byteorder.h"
16 #include "webrtc/base/timeutils.h"
17 #include "webrtc/system_wrappers/include/sleep.h"
18 
19 namespace {
20   static const unsigned int kReflectorSsrc = 0x0000;
21   static const unsigned int kLocalSsrc = 0x0001;
22   static const unsigned int kFirstRemoteSsrc = 0x0002;
23   static const webrtc::CodecInst kCodecInst =
24       {120, "opus", 48000, 960, 2, 64000};
25   static const int kAudioLevelHeaderId = 1;
26 
ParseRtcpSsrc(const void * data,size_t len)27   static unsigned int ParseRtcpSsrc(const void* data, size_t len) {
28     const size_t ssrc_pos = 4;
29     unsigned int ssrc = 0;
30     if (len >= (ssrc_pos + sizeof(ssrc))) {
31       ssrc = rtc::GetBE32(static_cast<const char*>(data) + ssrc_pos);
32     }
33     return ssrc;
34   }
35 }  // namespace
36 
37 namespace voetest {
38 
ConferenceTransport()39 ConferenceTransport::ConferenceTransport()
40     : pq_crit_(webrtc::CriticalSectionWrapper::CreateCriticalSection()),
41       stream_crit_(webrtc::CriticalSectionWrapper::CreateCriticalSection()),
42       packet_event_(webrtc::EventWrapper::Create()),
43       thread_(Run, this, "ConferenceTransport"),
44       rtt_ms_(0),
45       stream_count_(0),
46       rtp_header_parser_(webrtc::RtpHeaderParser::Create()) {
47   rtp_header_parser_->
48       RegisterRtpHeaderExtension(webrtc::kRtpExtensionAudioLevel,
49                                  kAudioLevelHeaderId);
50 
51   local_voe_ = webrtc::VoiceEngine::Create();
52   local_base_ = webrtc::VoEBase::GetInterface(local_voe_);
53   local_network_ = webrtc::VoENetwork::GetInterface(local_voe_);
54   local_rtp_rtcp_ = webrtc::VoERTP_RTCP::GetInterface(local_voe_);
55 
56   // In principle, we can use one VoiceEngine to achieve the same goal. Well, in
57   // here, we use two engines to make it more like reality.
58   remote_voe_ = webrtc::VoiceEngine::Create();
59   remote_base_ = webrtc::VoEBase::GetInterface(remote_voe_);
60   remote_codec_ = webrtc::VoECodec::GetInterface(remote_voe_);
61   remote_network_ = webrtc::VoENetwork::GetInterface(remote_voe_);
62   remote_rtp_rtcp_ = webrtc::VoERTP_RTCP::GetInterface(remote_voe_);
63   remote_file_ = webrtc::VoEFile::GetInterface(remote_voe_);
64 
65   EXPECT_EQ(0, local_base_->Init());
66   local_sender_ = local_base_->CreateChannel();
67   EXPECT_EQ(0, local_network_->RegisterExternalTransport(local_sender_, *this));
68   EXPECT_EQ(0, local_rtp_rtcp_->SetLocalSSRC(local_sender_, kLocalSsrc));
69   EXPECT_EQ(0, local_rtp_rtcp_->
70       SetSendAudioLevelIndicationStatus(local_sender_, true,
71                                         kAudioLevelHeaderId));
72 
73   EXPECT_EQ(0, local_base_->StartSend(local_sender_));
74 
75   EXPECT_EQ(0, remote_base_->Init());
76   reflector_ = remote_base_->CreateChannel();
77   EXPECT_EQ(0, remote_network_->RegisterExternalTransport(reflector_, *this));
78   EXPECT_EQ(0, remote_rtp_rtcp_->SetLocalSSRC(reflector_, kReflectorSsrc));
79 
80   thread_.Start();
81   thread_.SetPriority(rtc::kHighPriority);
82 }
83 
~ConferenceTransport()84 ConferenceTransport::~ConferenceTransport() {
85   // Must stop sending, otherwise DispatchPackets() cannot quit.
86   EXPECT_EQ(0, remote_network_->DeRegisterExternalTransport(reflector_));
87   EXPECT_EQ(0, local_network_->DeRegisterExternalTransport(local_sender_));
88 
89   while (!streams_.empty()) {
90     auto stream = streams_.begin();
91     RemoveStream(stream->first);
92   }
93 
94   thread_.Stop();
95 
96   remote_file_->Release();
97   remote_rtp_rtcp_->Release();
98   remote_network_->Release();
99   remote_base_->Release();
100 
101   local_rtp_rtcp_->Release();
102   local_network_->Release();
103   local_base_->Release();
104 
105   EXPECT_TRUE(webrtc::VoiceEngine::Delete(remote_voe_));
106   EXPECT_TRUE(webrtc::VoiceEngine::Delete(local_voe_));
107 }
108 
SendRtp(const uint8_t * data,size_t len,const webrtc::PacketOptions & options)109 bool ConferenceTransport::SendRtp(const uint8_t* data,
110                                   size_t len,
111                                   const webrtc::PacketOptions& options) {
112   StorePacket(Packet::Rtp, data, len);
113   return true;
114 }
115 
SendRtcp(const uint8_t * data,size_t len)116 bool ConferenceTransport::SendRtcp(const uint8_t* data, size_t len) {
117   StorePacket(Packet::Rtcp, data, len);
118   return true;
119 }
120 
GetReceiverChannelForSsrc(unsigned int sender_ssrc) const121 int ConferenceTransport::GetReceiverChannelForSsrc(unsigned int sender_ssrc)
122     const {
123   webrtc::CriticalSectionScoped lock(stream_crit_.get());
124   auto it = streams_.find(sender_ssrc);
125   if (it != streams_.end()) {
126     return it->second.second;
127   }
128   return -1;
129 }
130 
StorePacket(Packet::Type type,const void * data,size_t len)131 void ConferenceTransport::StorePacket(Packet::Type type,
132                                       const void* data,
133                                       size_t len) {
134   {
135     webrtc::CriticalSectionScoped lock(pq_crit_.get());
136     packet_queue_.push_back(Packet(type, data, len, rtc::Time()));
137   }
138   packet_event_->Set();
139 }
140 
141 // This simulates the flow of RTP and RTCP packets. Complications like that
142 // a packet is first sent to the reflector, and then forwarded to the receiver
143 // are simplified, in this particular case, to a direct link between the sender
144 // and the receiver.
SendPacket(const Packet & packet)145 void ConferenceTransport::SendPacket(const Packet& packet) {
146   int destination = -1;
147 
148   switch (packet.type_) {
149     case Packet::Rtp: {
150       webrtc::RTPHeader rtp_header;
151       rtp_header_parser_->Parse(packet.data_, packet.len_, &rtp_header);
152       if (rtp_header.ssrc == kLocalSsrc) {
153         remote_network_->ReceivedRTPPacket(reflector_, packet.data_,
154                                            packet.len_, webrtc::PacketTime());
155       } else {
156         if (loudest_filter_.ForwardThisPacket(rtp_header)) {
157           destination = GetReceiverChannelForSsrc(rtp_header.ssrc);
158           if (destination != -1) {
159             local_network_->ReceivedRTPPacket(destination, packet.data_,
160                                               packet.len_,
161                                               webrtc::PacketTime());
162           }
163         }
164       }
165       break;
166     }
167     case Packet::Rtcp: {
168       unsigned int sender_ssrc = ParseRtcpSsrc(packet.data_, packet.len_);
169       if (sender_ssrc == kLocalSsrc) {
170         remote_network_->ReceivedRTCPPacket(reflector_, packet.data_,
171                                             packet.len_);
172       } else if (sender_ssrc == kReflectorSsrc) {
173         local_network_->ReceivedRTCPPacket(local_sender_, packet.data_,
174                                            packet.len_);
175       } else {
176         destination = GetReceiverChannelForSsrc(sender_ssrc);
177         if (destination != -1) {
178           local_network_->ReceivedRTCPPacket(destination, packet.data_,
179                                              packet.len_);
180         }
181       }
182       break;
183     }
184   }
185 }
186 
DispatchPackets()187 bool ConferenceTransport::DispatchPackets() {
188   switch (packet_event_->Wait(1000)) {
189     case webrtc::kEventSignaled:
190       break;
191     case webrtc::kEventTimeout:
192       return true;
193     case webrtc::kEventError:
194       ADD_FAILURE() << "kEventError encountered.";
195       return true;
196   }
197 
198   while (true) {
199     Packet packet;
200     {
201       webrtc::CriticalSectionScoped lock(pq_crit_.get());
202       if (packet_queue_.empty())
203         break;
204       packet = packet_queue_.front();
205       packet_queue_.pop_front();
206     }
207 
208     int32_t elapsed_time_ms = rtc::TimeSince(packet.send_time_ms_);
209     int32_t sleep_ms = rtt_ms_ / 2 - elapsed_time_ms;
210     if (sleep_ms > 0) {
211       // Every packet should be delayed by half of RTT.
212       webrtc::SleepMs(sleep_ms);
213     }
214 
215     SendPacket(packet);
216   }
217   return true;
218 }
219 
SetRtt(unsigned int rtt_ms)220 void ConferenceTransport::SetRtt(unsigned int rtt_ms) {
221   rtt_ms_ = rtt_ms;
222 }
223 
AddStream(std::string file_name,webrtc::FileFormats format)224 unsigned int ConferenceTransport::AddStream(std::string file_name,
225                                             webrtc::FileFormats format) {
226   const int new_sender = remote_base_->CreateChannel();
227   EXPECT_EQ(0, remote_network_->RegisterExternalTransport(new_sender, *this));
228 
229   const unsigned int remote_ssrc = kFirstRemoteSsrc + stream_count_++;
230   EXPECT_EQ(0, remote_rtp_rtcp_->SetLocalSSRC(new_sender, remote_ssrc));
231   EXPECT_EQ(0, remote_rtp_rtcp_->
232       SetSendAudioLevelIndicationStatus(new_sender, true, kAudioLevelHeaderId));
233 
234   EXPECT_EQ(0, remote_codec_->SetSendCodec(new_sender, kCodecInst));
235   EXPECT_EQ(0, remote_base_->StartSend(new_sender));
236   EXPECT_EQ(0, remote_file_->StartPlayingFileAsMicrophone(
237       new_sender, file_name.c_str(), true, false, format, 1.0));
238 
239   const int new_receiver = local_base_->CreateChannel();
240   EXPECT_EQ(0, local_base_->AssociateSendChannel(new_receiver, local_sender_));
241 
242   EXPECT_EQ(0, local_network_->RegisterExternalTransport(new_receiver, *this));
243   // Receive channels have to have the same SSRC in order to send receiver
244   // reports with this SSRC.
245   EXPECT_EQ(0, local_rtp_rtcp_->SetLocalSSRC(new_receiver, kLocalSsrc));
246 
247   {
248     webrtc::CriticalSectionScoped lock(stream_crit_.get());
249     streams_[remote_ssrc] = std::make_pair(new_sender, new_receiver);
250   }
251   return remote_ssrc;  // remote ssrc used as stream id.
252 }
253 
RemoveStream(unsigned int id)254 bool ConferenceTransport::RemoveStream(unsigned int id) {
255   webrtc::CriticalSectionScoped lock(stream_crit_.get());
256   auto it = streams_.find(id);
257   if (it == streams_.end()) {
258     return false;
259   }
260   EXPECT_EQ(0, remote_network_->
261       DeRegisterExternalTransport(it->second.second));
262   EXPECT_EQ(0, local_network_->
263       DeRegisterExternalTransport(it->second.first));
264   EXPECT_EQ(0, remote_base_->DeleteChannel(it->second.second));
265   EXPECT_EQ(0, local_base_->DeleteChannel(it->second.first));
266   streams_.erase(it);
267   return true;
268 }
269 
StartPlayout(unsigned int id)270 bool ConferenceTransport::StartPlayout(unsigned int id) {
271   int dst = GetReceiverChannelForSsrc(id);
272   if (dst == -1) {
273     return false;
274   }
275   EXPECT_EQ(0, local_base_->StartPlayout(dst));
276   return true;
277 }
278 
GetReceiverStatistics(unsigned int id,webrtc::CallStatistics * stats)279 bool ConferenceTransport::GetReceiverStatistics(unsigned int id,
280                                                 webrtc::CallStatistics* stats) {
281   int dst = GetReceiverChannelForSsrc(id);
282   if (dst == -1) {
283     return false;
284   }
285   EXPECT_EQ(0, local_rtp_rtcp_->GetRTCPStatistics(dst, *stats));
286   return true;
287 }
288 }  // namespace voetest
289