OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/voice_engine/test/auto_test/fakes/conference_transport.h" | 11 #include "webrtc/voice_engine/test/auto_test/fakes/conference_transport.h" |
12 | 12 |
13 #include <string> | 13 #include <string> |
14 | 14 |
15 #include "webrtc/base/byteorder.h" | 15 #include "webrtc/base/byteorder.h" |
16 #include "webrtc/base/timeutils.h" | 16 #include "webrtc/base/timeutils.h" |
17 #include "webrtc/test/testsupport/fileutils.h" | |
18 #include "webrtc/system_wrappers/interface/sleep.h" | 17 #include "webrtc/system_wrappers/interface/sleep.h" |
19 | 18 |
20 namespace { | 19 namespace { |
21 static const unsigned int kReflectorSsrc = 0x0000; | 20 static const unsigned int kReflectorSsrc = 0x0000; |
22 static const unsigned int kLocalSsrc = 0x0001; | 21 static const unsigned int kLocalSsrc = 0x0001; |
23 static const unsigned int kFirstRemoteSsrc = 0x0002; | 22 static const unsigned int kFirstRemoteSsrc = 0x0002; |
24 static const webrtc::CodecInst kCodecInst = | 23 static const webrtc::CodecInst kCodecInst = |
25 {120, "opus", 48000, 960, 2, 64000}; | 24 {120, "opus", 48000, 960, 2, 64000}; |
25 static const int kInvalidAudioLevel = 128; | |
26 static const int kEnergyHeaderId = 1; | |
27 static const int kPaddingHeaderId = 0; | |
26 | 28 |
27 static unsigned int ParseSsrc(const void* data, size_t len, bool rtcp) { | 29 static unsigned int ParseSsrc(const void* data, size_t len, bool rtcp) { |
minyue-webrtc
2015/08/06 13:31:22
It would be good to get rid of this parser too. I'
| |
28 const size_t ssrc_pos = (!rtcp) ? 8 : 4; | 30 const size_t ssrc_pos = (!rtcp) ? 8 : 4; |
29 unsigned int ssrc = 0; | 31 unsigned int ssrc = 0; |
30 if (len >= (ssrc_pos + sizeof(ssrc))) { | 32 if (len >= (ssrc_pos + sizeof(ssrc))) { |
31 ssrc = rtc::GetBE32(static_cast<const char*>(data) + ssrc_pos); | 33 ssrc = rtc::GetBE32(static_cast<const char*>(data) + ssrc_pos); |
32 } | 34 } |
33 return ssrc; | 35 return ssrc; |
34 } | 36 } |
37 | |
38 // Parses audio level in RTP header extension according to | |
hlundin-webrtc
2015/08/05 14:04:24
I suggest you use RtpHeaderParser from webrtc/modu
minyue-webrtc
2015/08/05 14:15:16
I actually tried it, but it did not fit here very
hlundin-webrtc
2015/08/05 15:41:19
OK. I used it in webrtc::test::RtpFileSource. Look
Andrew MacDonald
2015/08/05 16:37:07
In any case, you really don't want to be doing thi
minyue-webrtc
2015/08/06 13:31:22
Thanks. I agree that it is better to use existing
| |
39 // https://tools.ietf.org/html/rfc6464 | |
40 static int ParseAudioLevelFromRtp(const uint8_t* data, size_t len) { | |
41 if (len < 4) { | |
42 return kInvalidAudioLevel; | |
tlegrand-webrtc
2015/08/05 13:32:44
If we end up here, the RTP header is too short to
minyue-webrtc
2015/08/06 13:31:22
Sorry Tina, other reviewers want these function to
| |
43 } | |
44 | |
45 const uint32_t first_word = rtc::GetBE32(data); | |
tlegrand-webrtc
2015/08/05 13:32:44
Can we add a more descriptive variable name? What
| |
46 if ((first_word & 0x10000000) == 0) { // Check if RTP header has extension | |
47 printf("No extension %x.\n", first_word); | |
tlegrand-webrtc
2015/08/05 13:32:44
Is the printf needed?
| |
48 return kInvalidAudioLevel; | |
49 } | |
50 | |
51 int cc = (first_word >> 24) & 0x0f; // CSRC count, to calculate header size | |
tlegrand-webrtc
2015/08/05 13:32:44
cc -> csrc_count, perhaps?
| |
52 size_t ext_pos = 12 + cc * 4; | |
tlegrand-webrtc
2015/08/05 13:32:43
The variable names are a bit confusing, since they
| |
53 if (len < ext_pos + 4) { | |
54 return kInvalidAudioLevel; | |
55 } | |
56 | |
57 int ext_type = rtc::GetBE16(data + ext_pos) & 0xffff; | |
58 size_t ext_length = rtc::GetBE16(data + ext_pos + 2) & 0xffff; | |
59 if (len < ext_pos + ext_length * 4) { | |
60 return kInvalidAudioLevel; | |
61 } | |
62 | |
63 size_t offset = 0; | |
64 if (ext_type == 0xbede) { | |
65 // one-byte format | |
66 // 0 1 | |
67 // 0 1 2 3 4 5 7 8 9 0 1 2 3 4 5 | |
68 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
69 // | ID | len=0 |V| level | | |
70 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
71 while (offset < ext_length * 4) { | |
72 uint8_t b = rtc::Get8(data, ext_pos + 4 + offset); | |
tlegrand-webrtc
2015/08/05 13:32:44
Change "b" to a descriptive name.
| |
73 int id = (b >> 4) & 0x0f; | |
74 if (id == kEnergyHeaderId) { | |
75 return rtc::Get8(data, ext_pos + 5 + offset) & 0x7f; | |
76 } else if (id == kPaddingHeaderId) { | |
77 offset++; | |
78 } else { | |
79 int len = b & 0x0f; | |
80 // The len field is the length minus one | |
81 // http://tools.ietf.org/html/rfc5285#section-4.2 | |
82 offset += len + 2; | |
83 } | |
84 } | |
85 } else if ((ext_type & 0xfff0) == 0x1000) { | |
86 // two-byte format | |
tlegrand-webrtc
2015/08/05 13:32:44
Maybe you can save some code lines by only using t
| |
87 // 0 1 2 3 | |
88 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | |
89 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
90 // | ID | len=1 |V| level | 0 (pad) | | |
91 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
92 while (offset < ext_length * 4) { | |
93 int id = rtc::Get8(data, ext_pos + 4 + offset) & 0xff; | |
94 if (id == kEnergyHeaderId) { | |
95 return rtc::Get8(data, ext_pos + 6 + offset) & 0x7f; | |
96 } else if (id == kPaddingHeaderId) { | |
97 offset++; | |
98 } else { | |
99 int len = rtc::Get8(data, ext_pos + 5 + offset) & 0xff; | |
100 offset += len + 2; | |
101 } | |
102 } | |
103 } | |
104 return kInvalidAudioLevel; | |
105 } | |
35 } // namespace | 106 } // namespace |
36 | 107 |
37 namespace voetest { | 108 namespace voetest { |
38 | 109 |
39 ConferenceTransport::ConferenceTransport() | 110 ConferenceTransport::ConferenceTransport() |
40 : pq_crit_(webrtc::CriticalSectionWrapper::CreateCriticalSection()), | 111 : pq_crit_(webrtc::CriticalSectionWrapper::CreateCriticalSection()), |
41 stream_crit_(webrtc::CriticalSectionWrapper::CreateCriticalSection()), | 112 stream_crit_(webrtc::CriticalSectionWrapper::CreateCriticalSection()), |
42 packet_event_(webrtc::EventWrapper::Create()), | 113 packet_event_(webrtc::EventWrapper::Create()), |
43 thread_(webrtc::ThreadWrapper::CreateThread(Run, | 114 thread_(webrtc::ThreadWrapper::CreateThread(Run, |
44 this, | 115 this, |
(...skipping 11 matching lines...) Expand all Loading... | |
56 remote_base_ = webrtc::VoEBase::GetInterface(remote_voe_); | 127 remote_base_ = webrtc::VoEBase::GetInterface(remote_voe_); |
57 remote_codec_ = webrtc::VoECodec::GetInterface(remote_voe_); | 128 remote_codec_ = webrtc::VoECodec::GetInterface(remote_voe_); |
58 remote_network_ = webrtc::VoENetwork::GetInterface(remote_voe_); | 129 remote_network_ = webrtc::VoENetwork::GetInterface(remote_voe_); |
59 remote_rtp_rtcp_ = webrtc::VoERTP_RTCP::GetInterface(remote_voe_); | 130 remote_rtp_rtcp_ = webrtc::VoERTP_RTCP::GetInterface(remote_voe_); |
60 remote_file_ = webrtc::VoEFile::GetInterface(remote_voe_); | 131 remote_file_ = webrtc::VoEFile::GetInterface(remote_voe_); |
61 | 132 |
62 EXPECT_EQ(0, local_base_->Init()); | 133 EXPECT_EQ(0, local_base_->Init()); |
63 local_sender_ = local_base_->CreateChannel(); | 134 local_sender_ = local_base_->CreateChannel(); |
64 EXPECT_EQ(0, local_network_->RegisterExternalTransport(local_sender_, *this)); | 135 EXPECT_EQ(0, local_network_->RegisterExternalTransport(local_sender_, *this)); |
65 EXPECT_EQ(0, local_rtp_rtcp_->SetLocalSSRC(local_sender_, kLocalSsrc)); | 136 EXPECT_EQ(0, local_rtp_rtcp_->SetLocalSSRC(local_sender_, kLocalSsrc)); |
137 EXPECT_EQ(0, local_rtp_rtcp_-> | |
138 SetSendAudioLevelIndicationStatus(local_sender_, true, kEnergyHeaderId)); | |
139 | |
66 EXPECT_EQ(0, local_base_->StartSend(local_sender_)); | 140 EXPECT_EQ(0, local_base_->StartSend(local_sender_)); |
67 | 141 |
68 EXPECT_EQ(0, remote_base_->Init()); | 142 EXPECT_EQ(0, remote_base_->Init()); |
69 reflector_ = remote_base_->CreateChannel(); | 143 reflector_ = remote_base_->CreateChannel(); |
70 EXPECT_EQ(0, remote_network_->RegisterExternalTransport(reflector_, *this)); | 144 EXPECT_EQ(0, remote_network_->RegisterExternalTransport(reflector_, *this)); |
71 EXPECT_EQ(0, remote_rtp_rtcp_->SetLocalSSRC(reflector_, kReflectorSsrc)); | 145 EXPECT_EQ(0, remote_rtp_rtcp_->SetLocalSSRC(reflector_, kReflectorSsrc)); |
72 | 146 |
73 thread_->Start(); | 147 thread_->Start(); |
74 thread_->SetPriority(webrtc::kHighPriority); | 148 thread_->SetPriority(webrtc::kHighPriority); |
75 } | 149 } |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
126 webrtc::CriticalSectionScoped lock(pq_crit_.get()); | 200 webrtc::CriticalSectionScoped lock(pq_crit_.get()); |
127 packet_queue_.push_back(Packet(type, channel, data, len, rtc::Time())); | 201 packet_queue_.push_back(Packet(type, channel, data, len, rtc::Time())); |
128 } | 202 } |
129 packet_event_->Set(); | 203 packet_event_->Set(); |
130 } | 204 } |
131 | 205 |
132 // This simulates the flow of RTP and RTCP packets. Complications like that | 206 // This simulates the flow of RTP and RTCP packets. Complications like that |
133 // a packet is first sent to the reflector, and then forwarded to the receiver | 207 // a packet is first sent to the reflector, and then forwarded to the receiver |
134 // are simplified, in this particular case, to a direct link between the sender | 208 // are simplified, in this particular case, to a direct link between the sender |
135 // and the receiver. | 209 // and the receiver. |
136 void ConferenceTransport::SendPacket(const Packet& packet) const { | 210 void ConferenceTransport::SendPacket(const Packet& packet) { |
137 unsigned int sender_ssrc; | 211 unsigned int sender_ssrc; |
138 int destination = -1; | 212 int destination = -1; |
139 switch (packet.type_) { | 213 switch (packet.type_) { |
140 case Packet::Rtp: | 214 case Packet::Rtp: { |
141 sender_ssrc = ParseSsrc(packet.data_, packet.len_, false); | 215 sender_ssrc = ParseSsrc(packet.data_, packet.len_, false); |
142 if (sender_ssrc == kLocalSsrc) { | 216 if (sender_ssrc == kLocalSsrc) { |
143 remote_network_->ReceivedRTPPacket(reflector_, packet.data_, | 217 remote_network_->ReceivedRTPPacket(reflector_, packet.data_, |
144 packet.len_, webrtc::PacketTime()); | 218 packet.len_, webrtc::PacketTime()); |
145 } else { | 219 } else { |
220 int audio_level = ParseAudioLevelFromRtp(packet.data_, packet.len_); | |
221 if (!loudest_filter_.DecideForward(sender_ssrc, audio_level)) { | |
222 break; | |
223 } | |
146 destination = GetReceiverChannelForSsrc(sender_ssrc); | 224 destination = GetReceiverChannelForSsrc(sender_ssrc); |
147 if (destination != -1) { | 225 if (destination != -1) { |
148 local_network_->ReceivedRTPPacket(destination, packet.data_, | 226 local_network_->ReceivedRTPPacket(destination, packet.data_, |
149 packet.len_, | 227 packet.len_, |
150 webrtc::PacketTime()); | 228 webrtc::PacketTime()); |
151 } | 229 } |
152 } | 230 } |
153 break; | 231 break; |
154 case Packet::Rtcp: | 232 } |
233 case Packet::Rtcp: { | |
155 sender_ssrc = ParseSsrc(packet.data_, packet.len_, true); | 234 sender_ssrc = ParseSsrc(packet.data_, packet.len_, true); |
156 if (sender_ssrc == kLocalSsrc) { | 235 if (sender_ssrc == kLocalSsrc) { |
157 remote_network_->ReceivedRTCPPacket(reflector_, packet.data_, | 236 remote_network_->ReceivedRTCPPacket(reflector_, packet.data_, |
158 packet.len_); | 237 packet.len_); |
159 } else if (sender_ssrc == kReflectorSsrc) { | 238 } else if (sender_ssrc == kReflectorSsrc) { |
160 local_network_->ReceivedRTCPPacket(local_sender_, packet.data_, | 239 local_network_->ReceivedRTCPPacket(local_sender_, packet.data_, |
161 packet.len_); | 240 packet.len_); |
162 } else { | 241 } else { |
163 destination = GetReceiverChannelForSsrc(sender_ssrc); | 242 destination = GetReceiverChannelForSsrc(sender_ssrc); |
164 if (destination != -1) { | 243 if (destination != -1) { |
165 local_network_->ReceivedRTCPPacket(destination, packet.data_, | 244 local_network_->ReceivedRTCPPacket(destination, packet.data_, |
166 packet.len_); | 245 packet.len_); |
167 } | 246 } |
168 } | 247 } |
169 break; | 248 break; |
249 } | |
170 } | 250 } |
171 } | 251 } |
172 | 252 |
173 bool ConferenceTransport::DispatchPackets() { | 253 bool ConferenceTransport::DispatchPackets() { |
174 switch (packet_event_->Wait(1000)) { | 254 switch (packet_event_->Wait(1000)) { |
175 case webrtc::kEventSignaled: | 255 case webrtc::kEventSignaled: |
176 break; | 256 break; |
177 case webrtc::kEventTimeout: | 257 case webrtc::kEventTimeout: |
178 return true; | 258 return true; |
179 case webrtc::kEventError: | 259 case webrtc::kEventError: |
(...skipping 20 matching lines...) Expand all Loading... | |
200 | 280 |
201 SendPacket(packet); | 281 SendPacket(packet); |
202 } | 282 } |
203 return true; | 283 return true; |
204 } | 284 } |
205 | 285 |
206 void ConferenceTransport::SetRtt(unsigned int rtt_ms) { | 286 void ConferenceTransport::SetRtt(unsigned int rtt_ms) { |
207 rtt_ms_ = rtt_ms; | 287 rtt_ms_ = rtt_ms; |
208 } | 288 } |
209 | 289 |
210 unsigned int ConferenceTransport::AddStream() { | 290 unsigned int ConferenceTransport::AddStream(std::string file_name, |
211 const std::string kInputFileName = | 291 webrtc::FileFormats format) { |
212 webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm"); | |
213 | |
214 const int new_sender = remote_base_->CreateChannel(); | 292 const int new_sender = remote_base_->CreateChannel(); |
215 EXPECT_EQ(0, remote_network_->RegisterExternalTransport(new_sender, *this)); | 293 EXPECT_EQ(0, remote_network_->RegisterExternalTransport(new_sender, *this)); |
216 | 294 |
217 const unsigned int remote_ssrc = kFirstRemoteSsrc + stream_count_++; | 295 const unsigned int remote_ssrc = kFirstRemoteSsrc + stream_count_++; |
218 EXPECT_EQ(0, remote_rtp_rtcp_->SetLocalSSRC(new_sender, remote_ssrc)); | 296 EXPECT_EQ(0, remote_rtp_rtcp_->SetLocalSSRC(new_sender, remote_ssrc)); |
297 EXPECT_EQ(0, remote_rtp_rtcp_-> | |
298 SetSendAudioLevelIndicationStatus(new_sender, true, kEnergyHeaderId)); | |
219 | 299 |
220 EXPECT_EQ(0, remote_codec_->SetSendCodec(new_sender, kCodecInst)); | 300 EXPECT_EQ(0, remote_codec_->SetSendCodec(new_sender, kCodecInst)); |
221 EXPECT_EQ(0, remote_base_->StartSend(new_sender)); | 301 EXPECT_EQ(0, remote_base_->StartSend(new_sender)); |
222 EXPECT_EQ(0, remote_file_->StartPlayingFileAsMicrophone( | 302 EXPECT_EQ(0, remote_file_->StartPlayingFileAsMicrophone( |
223 new_sender, kInputFileName.c_str(), true, false, | 303 new_sender, file_name.c_str(), true, false, format, 1.0)); |
224 webrtc::kFileFormatPcm32kHzFile, 1.0)); | |
225 | 304 |
226 const int new_receiver = local_base_->CreateChannel(); | 305 const int new_receiver = local_base_->CreateChannel(); |
227 EXPECT_EQ(0, local_base_->AssociateSendChannel(new_receiver, local_sender_)); | 306 EXPECT_EQ(0, local_base_->AssociateSendChannel(new_receiver, local_sender_)); |
228 | 307 |
229 EXPECT_EQ(0, local_network_->RegisterExternalTransport(new_receiver, *this)); | 308 EXPECT_EQ(0, local_network_->RegisterExternalTransport(new_receiver, *this)); |
230 // Receive channels have to have the same SSRC in order to send receiver | 309 // Receive channels have to have the same SSRC in order to send receiver |
231 // reports with this SSRC. | 310 // reports with this SSRC. |
232 EXPECT_EQ(0, local_rtp_rtcp_->SetLocalSSRC(new_receiver, kLocalSsrc)); | 311 EXPECT_EQ(0, local_rtp_rtcp_->SetLocalSSRC(new_receiver, kLocalSsrc)); |
233 | 312 |
234 { | 313 { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
266 bool ConferenceTransport::GetReceiverStatistics(unsigned int id, | 345 bool ConferenceTransport::GetReceiverStatistics(unsigned int id, |
267 webrtc::CallStatistics* stats) { | 346 webrtc::CallStatistics* stats) { |
268 int dst = GetReceiverChannelForSsrc(id); | 347 int dst = GetReceiverChannelForSsrc(id); |
269 if (dst == -1) { | 348 if (dst == -1) { |
270 return false; | 349 return false; |
271 } | 350 } |
272 EXPECT_EQ(0, local_rtp_rtcp_->GetRTCPStatistics(dst, *stats)); | 351 EXPECT_EQ(0, local_rtp_rtcp_->GetRTCPStatistics(dst, *stats)); |
273 return true; | 352 return true; |
274 } | 353 } |
275 } // namespace voetest | 354 } // namespace voetest |
OLD | NEW |