1 // Copyright 2008 Google Inc. 2 // 3 // Author: Justin Uberti (juberti (at) google.com) 4 5 #ifdef WIN32 6 #include "talk/base/win32.h" 7 #include <objbase.h> 8 #endif 9 10 #include "talk/base/byteorder.h" 11 #include "talk/base/gunit.h" 12 #include "talk/media/base/constants.h" 13 #include "talk/media/base/fakemediaengine.h" 14 #include "talk/media/base/fakemediaprocessor.h" 15 #include "talk/media/base/fakenetworkinterface.h" 16 #include "talk/media/base/fakertp.h" 17 #include "talk/media/webrtc/fakewebrtcvoiceengine.h" 18 #include "talk/media/webrtc/webrtcvoiceengine.h" 19 #include "talk/p2p/base/fakesession.h" 20 #include "talk/session/media/channel.h" 21 22 // Tests for the WebRtcVoiceEngine/VoiceChannel code. 23 24 static const cricket::AudioCodec kPcmuCodec(0, "PCMU", 8000, 64000, 1, 0); 25 static const cricket::AudioCodec kIsacCodec(103, "ISAC", 16000, 32000, 1, 0); 26 static const cricket::AudioCodec kCeltCodec(110, "CELT", 32000, 64000, 2, 0); 27 static const cricket::AudioCodec kOpusCodec(111, "opus", 48000, 64000, 2, 0); 28 static const cricket::AudioCodec kRedCodec(117, "red", 8000, 0, 1, 0); 29 static const cricket::AudioCodec kCn8000Codec(13, "CN", 8000, 0, 1, 0); 30 static const cricket::AudioCodec kCn16000Codec(105, "CN", 16000, 0, 1, 0); 31 static const cricket::AudioCodec 32 kTelephoneEventCodec(106, "telephone-event", 8000, 0, 1, 0); 33 static const cricket::AudioCodec* const kAudioCodecs[] = { 34 &kPcmuCodec, &kIsacCodec, &kCeltCodec, &kOpusCodec, &kRedCodec, 35 &kCn8000Codec, &kCn16000Codec, &kTelephoneEventCodec, 36 }; 37 const char kRingbackTone[] = "RIFF____WAVE____ABCD1234"; 38 static uint32 kSsrc1 = 0x99; 39 static uint32 kSsrc2 = 0x98; 40 41 class FakeVoEWrapper : public cricket::VoEWrapper { 42 public: 43 explicit FakeVoEWrapper(cricket::FakeWebRtcVoiceEngine* engine) 44 : cricket::VoEWrapper(engine, // processing 45 engine, // base 46 engine, // codec 47 engine, // dtmf 48 engine, // file 49 engine, // hw 50 engine, // media 51 engine, // neteq 52 engine, // network 53 engine, // rtp 54 engine, // sync 55 engine) { // volume 56 } 57 }; 58 59 class FakeVoETraceWrapper : public cricket::VoETraceWrapper { 60 public: 61 virtual int SetTraceFilter(const unsigned int filter) { 62 filter_ = filter; 63 return 0; 64 } 65 virtual int SetTraceFile(const char* fileNameUTF8) { 66 return 0; 67 } 68 virtual int SetTraceCallback(webrtc::TraceCallback* callback) { 69 return 0; 70 } 71 unsigned int filter_; 72 }; 73 74 class WebRtcVoiceEngineTestFake : public testing::Test { 75 public: 76 class ChannelErrorListener : public sigslot::has_slots<> { 77 public: 78 explicit ChannelErrorListener(cricket::VoiceMediaChannel* channel) 79 : ssrc_(0), error_(cricket::VoiceMediaChannel::ERROR_NONE) { 80 ASSERT(channel != NULL); 81 channel->SignalMediaError.connect( 82 this, &ChannelErrorListener::OnVoiceChannelError); 83 } 84 void OnVoiceChannelError(uint32 ssrc, 85 cricket::VoiceMediaChannel::Error error) { 86 ssrc_ = ssrc; 87 error_ = error; 88 } 89 void Reset() { 90 ssrc_ = 0; 91 error_ = cricket::VoiceMediaChannel::ERROR_NONE; 92 } 93 uint32 ssrc() const { 94 return ssrc_; 95 } 96 cricket::VoiceMediaChannel::Error error() const { 97 return error_; 98 } 99 100 private: 101 uint32 ssrc_; 102 cricket::VoiceMediaChannel::Error error_; 103 }; 104 105 WebRtcVoiceEngineTestFake() 106 : voe_(kAudioCodecs, ARRAY_SIZE(kAudioCodecs)), 107 voe_sc_(kAudioCodecs, ARRAY_SIZE(kAudioCodecs)), 108 trace_wrapper_(new FakeVoETraceWrapper()), 109 engine_(new FakeVoEWrapper(&voe_), 110 new FakeVoEWrapper(&voe_sc_), 111 trace_wrapper_), 112 channel_(NULL), soundclip_(NULL) { 113 options_conference_.conference_mode.Set(true); 114 options_adjust_agc_.adjust_agc_delta.Set(-10); 115 } 116 bool SetupEngine() { 117 bool result = engine_.Init(talk_base::Thread::Current()); 118 if (result) { 119 channel_ = engine_.CreateChannel(); 120 result = (channel_ != NULL); 121 } 122 if (result) { 123 result = channel_->AddSendStream( 124 cricket::StreamParams::CreateLegacy(kSsrc1)); 125 } 126 return result; 127 } 128 void SetupForMultiSendStream() { 129 EXPECT_TRUE(SetupEngine()); 130 // Remove stream added in Setup, which is corresponding to default channel. 131 int default_channel_num = voe_.GetLastChannel(); 132 uint32 default_send_ssrc = 0u; 133 EXPECT_EQ(0, voe_.GetLocalSSRC(default_channel_num, default_send_ssrc)); 134 EXPECT_EQ(kSsrc1, default_send_ssrc); 135 EXPECT_TRUE(channel_->RemoveSendStream(default_send_ssrc)); 136 137 // Verify the default channel still exists. 138 EXPECT_EQ(0, voe_.GetLocalSSRC(default_channel_num, default_send_ssrc)); 139 } 140 void DeliverPacket(const void* data, int len) { 141 talk_base::Buffer packet(data, len); 142 channel_->OnPacketReceived(&packet, talk_base::PacketTime()); 143 } 144 virtual void TearDown() { 145 delete soundclip_; 146 delete channel_; 147 engine_.Terminate(); 148 } 149 150 void TestInsertDtmf(uint32 ssrc, bool caller) { 151 EXPECT_TRUE(engine_.Init(talk_base::Thread::Current())); 152 channel_ = engine_.CreateChannel(); 153 EXPECT_TRUE(channel_ != NULL); 154 if (caller) { 155 // if this is a caller, local description will be applied and add the 156 // send stream. 157 EXPECT_TRUE(channel_->AddSendStream( 158 cricket::StreamParams::CreateLegacy(kSsrc1))); 159 } 160 int channel_id = voe_.GetLastChannel(); 161 162 // Test we can only InsertDtmf when the other side supports telephone-event. 163 std::vector<cricket::AudioCodec> codecs; 164 codecs.push_back(kPcmuCodec); 165 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 166 EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE)); 167 EXPECT_FALSE(channel_->CanInsertDtmf()); 168 EXPECT_FALSE(channel_->InsertDtmf(ssrc, 1, 111, cricket::DF_SEND)); 169 codecs.push_back(kTelephoneEventCodec); 170 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 171 EXPECT_TRUE(channel_->CanInsertDtmf()); 172 173 if (!caller) { 174 // There's no active send channel yet. 175 EXPECT_FALSE(channel_->InsertDtmf(ssrc, 2, 123, cricket::DF_SEND)); 176 EXPECT_TRUE(channel_->AddSendStream( 177 cricket::StreamParams::CreateLegacy(kSsrc1))); 178 } 179 180 // Check we fail if the ssrc is invalid. 181 EXPECT_FALSE(channel_->InsertDtmf(-1, 1, 111, cricket::DF_SEND)); 182 183 // Test send 184 EXPECT_FALSE(voe_.WasSendTelephoneEventCalled(channel_id, 2, 123)); 185 EXPECT_TRUE(channel_->InsertDtmf(ssrc, 2, 123, cricket::DF_SEND)); 186 EXPECT_TRUE(voe_.WasSendTelephoneEventCalled(channel_id, 2, 123)); 187 188 // Test play 189 EXPECT_FALSE(voe_.WasPlayDtmfToneCalled(3, 134)); 190 EXPECT_TRUE(channel_->InsertDtmf(ssrc, 3, 134, cricket::DF_PLAY)); 191 EXPECT_TRUE(voe_.WasPlayDtmfToneCalled(3, 134)); 192 193 // Test send and play 194 EXPECT_FALSE(voe_.WasSendTelephoneEventCalled(channel_id, 4, 145)); 195 EXPECT_FALSE(voe_.WasPlayDtmfToneCalled(4, 145)); 196 EXPECT_TRUE(channel_->InsertDtmf(ssrc, 4, 145, 197 cricket::DF_PLAY | cricket::DF_SEND)); 198 EXPECT_TRUE(voe_.WasSendTelephoneEventCalled(channel_id, 4, 145)); 199 EXPECT_TRUE(voe_.WasPlayDtmfToneCalled(4, 145)); 200 } 201 202 // Test that send bandwidth is set correctly. 203 // |codec| is the codec under test. 204 // |default_bitrate| is the default bitrate for the codec. 205 // |auto_bitrate| is a parameter to set to SetSendBandwidth(). 206 // |desired_bitrate| is a parameter to set to SetSendBandwidth(). 207 // |expected_result| is expected results from SetSendBandwidth(). 208 void TestSendBandwidth(const cricket::AudioCodec& codec, 209 int default_bitrate, 210 bool auto_bitrate, 211 int desired_bitrate, 212 bool expected_result) { 213 int channel_num = voe_.GetLastChannel(); 214 std::vector<cricket::AudioCodec> codecs; 215 216 codecs.push_back(codec); 217 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 218 219 bool result = channel_->SetSendBandwidth(auto_bitrate, desired_bitrate); 220 EXPECT_EQ(expected_result, result); 221 222 webrtc::CodecInst temp_codec; 223 EXPECT_FALSE(voe_.GetSendCodec(channel_num, temp_codec)); 224 225 if (result) { 226 // If SetSendBandwidth() returns true then bitrate is set correctly. 227 if (auto_bitrate) { 228 EXPECT_EQ(default_bitrate, temp_codec.rate); 229 } else { 230 EXPECT_EQ(desired_bitrate, temp_codec.rate); 231 } 232 } else { 233 // If SetSendBandwidth() returns false then bitrate is set to the 234 // default value. 235 EXPECT_EQ(default_bitrate, temp_codec.rate); 236 } 237 } 238 239 240 void TestSetSendRtpHeaderExtensions(int channel_id) { 241 std::vector<cricket::RtpHeaderExtension> extensions; 242 bool enable = false; 243 unsigned char id = 0; 244 245 // Ensure audio levels are off by default. 246 EXPECT_EQ(0, voe_.GetRTPAudioLevelIndicationStatus( 247 channel_id, enable, id)); 248 EXPECT_FALSE(enable); 249 250 // Ensure unknown extensions won't cause an error. 251 extensions.push_back(cricket::RtpHeaderExtension( 252 "urn:ietf:params:unknowextention", 1)); 253 EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(extensions)); 254 EXPECT_EQ(0, voe_.GetRTPAudioLevelIndicationStatus( 255 channel_id, enable, id)); 256 EXPECT_FALSE(enable); 257 258 // Ensure audio levels stay off with an empty list of headers. 259 EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(extensions)); 260 EXPECT_EQ(0, voe_.GetRTPAudioLevelIndicationStatus( 261 channel_id, enable, id)); 262 EXPECT_FALSE(enable); 263 264 // Ensure audio levels are enabled if the audio-level header is specified. 265 extensions.push_back(cricket::RtpHeaderExtension( 266 "urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8)); 267 EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(extensions)); 268 EXPECT_EQ(0, voe_.GetRTPAudioLevelIndicationStatus( 269 channel_id, enable, id)); 270 EXPECT_TRUE(enable); 271 EXPECT_EQ(8, id); 272 273 // Ensure audio levels go back off with an empty list. 274 extensions.clear(); 275 EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(extensions)); 276 EXPECT_EQ(0, voe_.GetRTPAudioLevelIndicationStatus( 277 channel_id, enable, id)); 278 EXPECT_FALSE(enable); 279 } 280 281 protected: 282 cricket::FakeWebRtcVoiceEngine voe_; 283 cricket::FakeWebRtcVoiceEngine voe_sc_; 284 FakeVoETraceWrapper* trace_wrapper_; 285 cricket::WebRtcVoiceEngine engine_; 286 cricket::VoiceMediaChannel* channel_; 287 cricket::SoundclipMedia* soundclip_; 288 289 cricket::AudioOptions options_conference_; 290 cricket::AudioOptions options_adjust_agc_; 291 }; 292 293 // Tests that our stub library "works". 294 TEST_F(WebRtcVoiceEngineTestFake, StartupShutdown) { 295 EXPECT_FALSE(voe_.IsInited()); 296 EXPECT_FALSE(voe_sc_.IsInited()); 297 EXPECT_TRUE(engine_.Init(talk_base::Thread::Current())); 298 EXPECT_TRUE(voe_.IsInited()); 299 // The soundclip engine is lazily initialized. 300 EXPECT_FALSE(voe_sc_.IsInited()); 301 engine_.Terminate(); 302 EXPECT_FALSE(voe_.IsInited()); 303 EXPECT_FALSE(voe_sc_.IsInited()); 304 } 305 306 // Tests that we can create and destroy a channel. 307 TEST_F(WebRtcVoiceEngineTestFake, CreateChannel) { 308 EXPECT_TRUE(engine_.Init(talk_base::Thread::Current())); 309 channel_ = engine_.CreateChannel(); 310 EXPECT_TRUE(channel_ != NULL); 311 } 312 313 // Tests that we properly handle failures in CreateChannel. 314 TEST_F(WebRtcVoiceEngineTestFake, CreateChannelFail) { 315 voe_.set_fail_create_channel(true); 316 EXPECT_TRUE(engine_.Init(talk_base::Thread::Current())); 317 channel_ = engine_.CreateChannel(); 318 EXPECT_TRUE(channel_ == NULL); 319 } 320 321 // Tests that the list of supported codecs is created properly and ordered 322 // correctly 323 TEST_F(WebRtcVoiceEngineTestFake, CodecPreference) { 324 const std::vector<cricket::AudioCodec>& codecs = engine_.codecs(); 325 ASSERT_FALSE(codecs.empty()); 326 EXPECT_STRCASEEQ("opus", codecs[0].name.c_str()); 327 EXPECT_EQ(48000, codecs[0].clockrate); 328 EXPECT_EQ(2, codecs[0].channels); 329 EXPECT_EQ(64000, codecs[0].bitrate); 330 int pref = codecs[0].preference; 331 for (size_t i = 1; i < codecs.size(); ++i) { 332 EXPECT_GT(pref, codecs[i].preference); 333 pref = codecs[i].preference; 334 } 335 } 336 337 // Tests that we can find codecs by name or id, and that we interpret the 338 // clockrate and bitrate fields properly. 339 TEST_F(WebRtcVoiceEngineTestFake, FindCodec) { 340 cricket::AudioCodec codec; 341 webrtc::CodecInst codec_inst; 342 // Find PCMU with explicit clockrate and bitrate. 343 EXPECT_TRUE(engine_.FindWebRtcCodec(kPcmuCodec, &codec_inst)); 344 // Find ISAC with explicit clockrate and 0 bitrate. 345 EXPECT_TRUE(engine_.FindWebRtcCodec(kIsacCodec, &codec_inst)); 346 // Find telephone-event with explicit clockrate and 0 bitrate. 347 EXPECT_TRUE(engine_.FindWebRtcCodec(kTelephoneEventCodec, &codec_inst)); 348 // Find ISAC with a different payload id. 349 codec = kIsacCodec; 350 codec.id = 127; 351 EXPECT_TRUE(engine_.FindWebRtcCodec(codec, &codec_inst)); 352 EXPECT_EQ(codec.id, codec_inst.pltype); 353 // Find PCMU with a 0 clockrate. 354 codec = kPcmuCodec; 355 codec.clockrate = 0; 356 EXPECT_TRUE(engine_.FindWebRtcCodec(codec, &codec_inst)); 357 EXPECT_EQ(codec.id, codec_inst.pltype); 358 EXPECT_EQ(8000, codec_inst.plfreq); 359 // Find PCMU with a 0 bitrate. 360 codec = kPcmuCodec; 361 codec.bitrate = 0; 362 EXPECT_TRUE(engine_.FindWebRtcCodec(codec, &codec_inst)); 363 EXPECT_EQ(codec.id, codec_inst.pltype); 364 EXPECT_EQ(64000, codec_inst.rate); 365 // Find ISAC with an explicit bitrate. 366 codec = kIsacCodec; 367 codec.bitrate = 32000; 368 EXPECT_TRUE(engine_.FindWebRtcCodec(codec, &codec_inst)); 369 EXPECT_EQ(codec.id, codec_inst.pltype); 370 EXPECT_EQ(32000, codec_inst.rate); 371 } 372 373 // Test that we set our inbound codecs properly, including changing PT. 374 TEST_F(WebRtcVoiceEngineTestFake, SetRecvCodecs) { 375 EXPECT_TRUE(SetupEngine()); 376 int channel_num = voe_.GetLastChannel(); 377 std::vector<cricket::AudioCodec> codecs; 378 codecs.push_back(kIsacCodec); 379 codecs.push_back(kPcmuCodec); 380 codecs.push_back(kTelephoneEventCodec); 381 codecs[0].id = 106; // collide with existing telephone-event 382 codecs[2].id = 126; 383 EXPECT_TRUE(channel_->SetRecvCodecs(codecs)); 384 webrtc::CodecInst gcodec; 385 talk_base::strcpyn(gcodec.plname, ARRAY_SIZE(gcodec.plname), "ISAC"); 386 gcodec.plfreq = 16000; 387 gcodec.channels = 1; 388 EXPECT_EQ(0, voe_.GetRecPayloadType(channel_num, gcodec)); 389 EXPECT_EQ(106, gcodec.pltype); 390 EXPECT_STREQ("ISAC", gcodec.plname); 391 talk_base::strcpyn(gcodec.plname, ARRAY_SIZE(gcodec.plname), 392 "telephone-event"); 393 gcodec.plfreq = 8000; 394 EXPECT_EQ(0, voe_.GetRecPayloadType(channel_num, gcodec)); 395 EXPECT_EQ(126, gcodec.pltype); 396 EXPECT_STREQ("telephone-event", gcodec.plname); 397 } 398 399 // Test that we fail to set an unknown inbound codec. 400 TEST_F(WebRtcVoiceEngineTestFake, SetRecvCodecsUnsupportedCodec) { 401 EXPECT_TRUE(SetupEngine()); 402 std::vector<cricket::AudioCodec> codecs; 403 codecs.push_back(kIsacCodec); 404 codecs.push_back(cricket::AudioCodec(127, "XYZ", 32000, 0, 1, 0)); 405 EXPECT_FALSE(channel_->SetRecvCodecs(codecs)); 406 } 407 408 // Test that we fail if we have duplicate types in the inbound list. 409 TEST_F(WebRtcVoiceEngineTestFake, SetRecvCodecsDuplicatePayloadType) { 410 EXPECT_TRUE(SetupEngine()); 411 std::vector<cricket::AudioCodec> codecs; 412 codecs.push_back(kIsacCodec); 413 codecs.push_back(kCn16000Codec); 414 codecs[1].id = kIsacCodec.id; 415 EXPECT_FALSE(channel_->SetRecvCodecs(codecs)); 416 } 417 418 // Test that we can decode OPUS without stereo parameters. 419 TEST_F(WebRtcVoiceEngineTestFake, SetRecvCodecsWithOpusNoStereo) { 420 EXPECT_TRUE(SetupEngine()); 421 EXPECT_TRUE(channel_->SetOptions(options_conference_)); 422 std::vector<cricket::AudioCodec> codecs; 423 codecs.push_back(kIsacCodec); 424 codecs.push_back(kPcmuCodec); 425 codecs.push_back(kOpusCodec); 426 EXPECT_TRUE(channel_->SetRecvCodecs(codecs)); 427 EXPECT_TRUE(channel_->AddRecvStream( 428 cricket::StreamParams::CreateLegacy(kSsrc1))); 429 int channel_num2 = voe_.GetLastChannel(); 430 webrtc::CodecInst opus; 431 engine_.FindWebRtcCodec(kOpusCodec, &opus); 432 // Even without stereo parameters, recv codecs still specify channels = 2. 433 EXPECT_EQ(2, opus.channels); 434 EXPECT_EQ(111, opus.pltype); 435 EXPECT_STREQ("opus", opus.plname); 436 opus.pltype = 0; 437 EXPECT_EQ(0, voe_.GetRecPayloadType(channel_num2, opus)); 438 EXPECT_EQ(111, opus.pltype); 439 } 440 441 // Test that we can decode OPUS with stereo = 0. 442 TEST_F(WebRtcVoiceEngineTestFake, SetRecvCodecsWithOpus0Stereo) { 443 EXPECT_TRUE(SetupEngine()); 444 EXPECT_TRUE(channel_->SetOptions(options_conference_)); 445 std::vector<cricket::AudioCodec> codecs; 446 codecs.push_back(kIsacCodec); 447 codecs.push_back(kPcmuCodec); 448 codecs.push_back(kOpusCodec); 449 codecs[2].params["stereo"] = "0"; 450 EXPECT_TRUE(channel_->SetRecvCodecs(codecs)); 451 EXPECT_TRUE(channel_->AddRecvStream( 452 cricket::StreamParams::CreateLegacy(kSsrc1))); 453 int channel_num2 = voe_.GetLastChannel(); 454 webrtc::CodecInst opus; 455 engine_.FindWebRtcCodec(kOpusCodec, &opus); 456 // Even when stereo is off, recv codecs still specify channels = 2. 457 EXPECT_EQ(2, opus.channels); 458 EXPECT_EQ(111, opus.pltype); 459 EXPECT_STREQ("opus", opus.plname); 460 opus.pltype = 0; 461 EXPECT_EQ(0, voe_.GetRecPayloadType(channel_num2, opus)); 462 EXPECT_EQ(111, opus.pltype); 463 } 464 465 // Test that we can decode OPUS with stereo = 1. 466 TEST_F(WebRtcVoiceEngineTestFake, SetRecvCodecsWithOpus1Stereo) { 467 EXPECT_TRUE(SetupEngine()); 468 EXPECT_TRUE(channel_->SetOptions(options_conference_)); 469 std::vector<cricket::AudioCodec> codecs; 470 codecs.push_back(kIsacCodec); 471 codecs.push_back(kPcmuCodec); 472 codecs.push_back(kOpusCodec); 473 codecs[2].params["stereo"] = "1"; 474 EXPECT_TRUE(channel_->SetRecvCodecs(codecs)); 475 EXPECT_TRUE(channel_->AddRecvStream( 476 cricket::StreamParams::CreateLegacy(kSsrc1))); 477 int channel_num2 = voe_.GetLastChannel(); 478 webrtc::CodecInst opus; 479 engine_.FindWebRtcCodec(kOpusCodec, &opus); 480 EXPECT_EQ(2, opus.channels); 481 EXPECT_EQ(111, opus.pltype); 482 EXPECT_STREQ("opus", opus.plname); 483 opus.pltype = 0; 484 EXPECT_EQ(0, voe_.GetRecPayloadType(channel_num2, opus)); 485 EXPECT_EQ(111, opus.pltype); 486 } 487 488 // Test that changes to recv codecs are applied to all streams. 489 TEST_F(WebRtcVoiceEngineTestFake, SetRecvCodecsWithMultipleStreams) { 490 EXPECT_TRUE(SetupEngine()); 491 EXPECT_TRUE(channel_->SetOptions(options_conference_)); 492 std::vector<cricket::AudioCodec> codecs; 493 codecs.push_back(kIsacCodec); 494 codecs.push_back(kPcmuCodec); 495 codecs.push_back(kTelephoneEventCodec); 496 codecs[0].id = 106; // collide with existing telephone-event 497 codecs[2].id = 126; 498 EXPECT_TRUE(channel_->SetRecvCodecs(codecs)); 499 EXPECT_TRUE(channel_->AddRecvStream( 500 cricket::StreamParams::CreateLegacy(kSsrc1))); 501 int channel_num2 = voe_.GetLastChannel(); 502 webrtc::CodecInst gcodec; 503 talk_base::strcpyn(gcodec.plname, ARRAY_SIZE(gcodec.plname), "ISAC"); 504 gcodec.plfreq = 16000; 505 gcodec.channels = 1; 506 EXPECT_EQ(0, voe_.GetRecPayloadType(channel_num2, gcodec)); 507 EXPECT_EQ(106, gcodec.pltype); 508 EXPECT_STREQ("ISAC", gcodec.plname); 509 talk_base::strcpyn(gcodec.plname, ARRAY_SIZE(gcodec.plname), 510 "telephone-event"); 511 gcodec.plfreq = 8000; 512 gcodec.channels = 1; 513 EXPECT_EQ(0, voe_.GetRecPayloadType(channel_num2, gcodec)); 514 EXPECT_EQ(126, gcodec.pltype); 515 EXPECT_STREQ("telephone-event", gcodec.plname); 516 } 517 518 TEST_F(WebRtcVoiceEngineTestFake, SetRecvCodecsAfterAddingStreams) { 519 EXPECT_TRUE(SetupEngine()); 520 EXPECT_TRUE(channel_->SetOptions(options_conference_)); 521 std::vector<cricket::AudioCodec> codecs; 522 codecs.push_back(kIsacCodec); 523 codecs[0].id = 106; // collide with existing telephone-event 524 525 EXPECT_TRUE(channel_->AddRecvStream( 526 cricket::StreamParams::CreateLegacy(kSsrc1))); 527 EXPECT_TRUE(channel_->SetRecvCodecs(codecs)); 528 529 int channel_num2 = voe_.GetLastChannel(); 530 webrtc::CodecInst gcodec; 531 talk_base::strcpyn(gcodec.plname, ARRAY_SIZE(gcodec.plname), "ISAC"); 532 gcodec.plfreq = 16000; 533 gcodec.channels = 1; 534 EXPECT_EQ(0, voe_.GetRecPayloadType(channel_num2, gcodec)); 535 EXPECT_EQ(106, gcodec.pltype); 536 EXPECT_STREQ("ISAC", gcodec.plname); 537 } 538 539 // Test that we can apply the same set of codecs again while playing. 540 TEST_F(WebRtcVoiceEngineTestFake, SetRecvCodecsWhilePlaying) { 541 EXPECT_TRUE(SetupEngine()); 542 int channel_num = voe_.GetLastChannel(); 543 std::vector<cricket::AudioCodec> codecs; 544 codecs.push_back(kIsacCodec); 545 codecs.push_back(kCn16000Codec); 546 EXPECT_TRUE(channel_->SetRecvCodecs(codecs)); 547 EXPECT_TRUE(channel_->SetPlayout(true)); 548 EXPECT_TRUE(channel_->SetRecvCodecs(codecs)); 549 550 // Changing the payload type of a codec should fail. 551 codecs[0].id = 127; 552 EXPECT_FALSE(channel_->SetRecvCodecs(codecs)); 553 EXPECT_TRUE(voe_.GetPlayout(channel_num)); 554 } 555 556 // Test that we can add a codec while playing. 557 TEST_F(WebRtcVoiceEngineTestFake, AddRecvCodecsWhilePlaying) { 558 EXPECT_TRUE(SetupEngine()); 559 int channel_num = voe_.GetLastChannel(); 560 std::vector<cricket::AudioCodec> codecs; 561 codecs.push_back(kIsacCodec); 562 codecs.push_back(kCn16000Codec); 563 EXPECT_TRUE(channel_->SetRecvCodecs(codecs)); 564 EXPECT_TRUE(channel_->SetPlayout(true)); 565 566 codecs.push_back(kOpusCodec); 567 EXPECT_TRUE(channel_->SetRecvCodecs(codecs)); 568 EXPECT_TRUE(voe_.GetPlayout(channel_num)); 569 webrtc::CodecInst gcodec; 570 EXPECT_TRUE(engine_.FindWebRtcCodec(kOpusCodec, &gcodec)); 571 EXPECT_EQ(kOpusCodec.id, gcodec.pltype); 572 } 573 574 TEST_F(WebRtcVoiceEngineTestFake, SetSendBandwidthAuto) { 575 EXPECT_TRUE(SetupEngine()); 576 EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs())); 577 578 // Test that when autobw is true, bitrate is kept as the default 579 // value. autobw is true for the following tests. 580 581 // ISAC, default bitrate == 32000. 582 TestSendBandwidth(kIsacCodec, 32000, true, 96000, true); 583 584 // PCMU, default bitrate == 64000. 585 TestSendBandwidth(kPcmuCodec, 64000, true, 96000, true); 586 587 // CELT, default bitrate == 64000. 588 TestSendBandwidth(kCeltCodec, 64000, true, 96000, true); 589 590 // opus, default bitrate == 64000. 591 TestSendBandwidth(kOpusCodec, 64000, true, 96000, true); 592 } 593 594 TEST_F(WebRtcVoiceEngineTestFake, SetSendBandwidthFixedMultiRateAsCaller) { 595 EXPECT_TRUE(SetupEngine()); 596 EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs())); 597 598 // Test that we can set bitrate if a multi-rate codec is used. 599 // autobw is false for the following tests. 600 601 // ISAC, default bitrate == 32000. 602 TestSendBandwidth(kIsacCodec, 32000, false, 128000, true); 603 604 // CELT, default bitrate == 64000. 605 TestSendBandwidth(kCeltCodec, 64000, false, 96000, true); 606 607 // opus, default bitrate == 64000. 608 TestSendBandwidth(kOpusCodec, 64000, false, 96000, true); 609 } 610 611 TEST_F(WebRtcVoiceEngineTestFake, SetSendBandwidthFixedMultiRateAsCallee) { 612 EXPECT_TRUE(engine_.Init(talk_base::Thread::Current())); 613 channel_ = engine_.CreateChannel(); 614 EXPECT_TRUE(channel_ != NULL); 615 EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs())); 616 617 int desired_bitrate = 128000; 618 EXPECT_TRUE(channel_->SetSendBandwidth(false, desired_bitrate)); 619 620 EXPECT_TRUE(channel_->AddSendStream( 621 cricket::StreamParams::CreateLegacy(kSsrc1))); 622 623 int channel_num = voe_.GetLastChannel(); 624 webrtc::CodecInst codec; 625 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, codec)); 626 EXPECT_EQ(desired_bitrate, codec.rate); 627 } 628 629 // Test that bitrate cannot be set for CBR codecs. 630 // Bitrate is ignored if it is higher than the fixed bitrate. 631 // Bitrate less then the fixed bitrate is an error. 632 TEST_F(WebRtcVoiceEngineTestFake, SetSendBandwidthFixedCbr) { 633 EXPECT_TRUE(SetupEngine()); 634 EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs())); 635 636 webrtc::CodecInst codec; 637 int channel_num = voe_.GetLastChannel(); 638 std::vector<cricket::AudioCodec> codecs; 639 640 // PCMU, default bitrate == 64000. 641 codecs.push_back(kPcmuCodec); 642 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 643 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, codec)); 644 EXPECT_EQ(64000, codec.rate); 645 EXPECT_TRUE(channel_->SetSendBandwidth(false, 128000)); 646 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, codec)); 647 EXPECT_EQ(64000, codec.rate); 648 EXPECT_FALSE(channel_->SetSendBandwidth(false, 128)); 649 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, codec)); 650 EXPECT_EQ(64000, codec.rate); 651 } 652 653 // Test that we apply codecs properly. 654 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecs) { 655 EXPECT_TRUE(SetupEngine()); 656 int channel_num = voe_.GetLastChannel(); 657 std::vector<cricket::AudioCodec> codecs; 658 codecs.push_back(kIsacCodec); 659 codecs.push_back(kPcmuCodec); 660 codecs.push_back(kRedCodec); 661 codecs[0].id = 96; 662 codecs[0].bitrate = 48000; 663 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 664 webrtc::CodecInst gcodec; 665 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 666 EXPECT_EQ(96, gcodec.pltype); 667 EXPECT_EQ(48000, gcodec.rate); 668 EXPECT_STREQ("ISAC", gcodec.plname); 669 EXPECT_FALSE(voe_.GetVAD(channel_num)); 670 EXPECT_FALSE(voe_.GetFEC(channel_num)); 671 EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false)); 672 EXPECT_EQ(105, voe_.GetSendCNPayloadType(channel_num, true)); 673 EXPECT_EQ(106, voe_.GetSendTelephoneEventPayloadType(channel_num)); 674 } 675 676 // TODO(pthatcher): Change failure behavior to returning false rather 677 // than defaulting to PCMU. 678 // Test that if clockrate is not 48000 for opus, we fail by fallback to PCMU. 679 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusBadClockrate) { 680 EXPECT_TRUE(SetupEngine()); 681 int channel_num = voe_.GetLastChannel(); 682 std::vector<cricket::AudioCodec> codecs; 683 codecs.push_back(kOpusCodec); 684 codecs[0].bitrate = 0; 685 codecs[0].clockrate = 50000; 686 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 687 webrtc::CodecInst gcodec; 688 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 689 EXPECT_STREQ("PCMU", gcodec.plname); 690 } 691 692 // Test that if channels=0 for opus, we fail by falling back to PCMU. 693 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusBad0ChannelsNoStereo) { 694 EXPECT_TRUE(SetupEngine()); 695 int channel_num = voe_.GetLastChannel(); 696 std::vector<cricket::AudioCodec> codecs; 697 codecs.push_back(kOpusCodec); 698 codecs[0].bitrate = 0; 699 codecs[0].channels = 0; 700 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 701 webrtc::CodecInst gcodec; 702 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 703 EXPECT_STREQ("PCMU", gcodec.plname); 704 } 705 706 // Test that if channels=0 for opus, we fail by falling back to PCMU. 707 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusBad0Channels1Stereo) { 708 EXPECT_TRUE(SetupEngine()); 709 int channel_num = voe_.GetLastChannel(); 710 std::vector<cricket::AudioCodec> codecs; 711 codecs.push_back(kOpusCodec); 712 codecs[0].bitrate = 0; 713 codecs[0].channels = 0; 714 codecs[0].params["stereo"] = "1"; 715 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 716 webrtc::CodecInst gcodec; 717 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 718 EXPECT_STREQ("PCMU", gcodec.plname); 719 } 720 721 // Test that if channel is 1 for opus and there's no stereo, we fail. 722 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpus1ChannelNoStereo) { 723 EXPECT_TRUE(SetupEngine()); 724 int channel_num = voe_.GetLastChannel(); 725 std::vector<cricket::AudioCodec> codecs; 726 codecs.push_back(kOpusCodec); 727 codecs[0].bitrate = 0; 728 codecs[0].channels = 1; 729 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 730 webrtc::CodecInst gcodec; 731 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 732 EXPECT_STREQ("PCMU", gcodec.plname); 733 } 734 735 // Test that if channel is 1 for opus and stereo=0, we fail. 736 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusBad1Channel0Stereo) { 737 EXPECT_TRUE(SetupEngine()); 738 int channel_num = voe_.GetLastChannel(); 739 std::vector<cricket::AudioCodec> codecs; 740 codecs.push_back(kOpusCodec); 741 codecs[0].bitrate = 0; 742 codecs[0].channels = 1; 743 codecs[0].params["stereo"] = "0"; 744 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 745 webrtc::CodecInst gcodec; 746 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 747 EXPECT_STREQ("PCMU", gcodec.plname); 748 } 749 750 // Test that if channel is 1 for opus and stereo=1, we fail. 751 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusBad1Channel1Stereo) { 752 EXPECT_TRUE(SetupEngine()); 753 int channel_num = voe_.GetLastChannel(); 754 std::vector<cricket::AudioCodec> codecs; 755 codecs.push_back(kOpusCodec); 756 codecs[0].bitrate = 0; 757 codecs[0].channels = 1; 758 codecs[0].params["stereo"] = "1"; 759 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 760 webrtc::CodecInst gcodec; 761 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 762 EXPECT_STREQ("PCMU", gcodec.plname); 763 } 764 765 // Test that with bitrate=0 and no stereo, 766 // channels and bitrate are 1 and 32000. 767 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusGood0BitrateNoStereo) { 768 EXPECT_TRUE(SetupEngine()); 769 int channel_num = voe_.GetLastChannel(); 770 std::vector<cricket::AudioCodec> codecs; 771 codecs.push_back(kOpusCodec); 772 codecs[0].bitrate = 0; 773 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 774 webrtc::CodecInst gcodec; 775 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 776 EXPECT_STREQ("opus", gcodec.plname); 777 EXPECT_EQ(1, gcodec.channels); 778 EXPECT_EQ(32000, gcodec.rate); 779 } 780 781 // Test that with bitrate=0 and stereo=0, 782 // channels and bitrate are 1 and 32000. 783 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusGood0Bitrate0Stereo) { 784 EXPECT_TRUE(SetupEngine()); 785 int channel_num = voe_.GetLastChannel(); 786 std::vector<cricket::AudioCodec> codecs; 787 codecs.push_back(kOpusCodec); 788 codecs[0].bitrate = 0; 789 codecs[0].params["stereo"] = "0"; 790 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 791 webrtc::CodecInst gcodec; 792 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 793 EXPECT_STREQ("opus", gcodec.plname); 794 EXPECT_EQ(1, gcodec.channels); 795 EXPECT_EQ(32000, gcodec.rate); 796 } 797 798 // Test that with bitrate=invalid and stereo=0, 799 // channels and bitrate are 1 and 32000. 800 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusGoodXBitrate0Stereo) { 801 EXPECT_TRUE(SetupEngine()); 802 int channel_num = voe_.GetLastChannel(); 803 std::vector<cricket::AudioCodec> codecs; 804 codecs.push_back(kOpusCodec); 805 codecs[0].params["stereo"] = "0"; 806 webrtc::CodecInst gcodec; 807 808 // bitrate that's out of the range between 6000 and 510000 will be considered 809 // as invalid and ignored. 810 codecs[0].bitrate = 5999; 811 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 812 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 813 EXPECT_STREQ("opus", gcodec.plname); 814 EXPECT_EQ(1, gcodec.channels); 815 EXPECT_EQ(32000, gcodec.rate); 816 817 codecs[0].bitrate = 510001; 818 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 819 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 820 EXPECT_STREQ("opus", gcodec.plname); 821 EXPECT_EQ(1, gcodec.channels); 822 EXPECT_EQ(32000, gcodec.rate); 823 } 824 825 // Test that with bitrate=0 and stereo=1, 826 // channels and bitrate are 2 and 64000. 827 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusGood0Bitrate1Stereo) { 828 EXPECT_TRUE(SetupEngine()); 829 int channel_num = voe_.GetLastChannel(); 830 std::vector<cricket::AudioCodec> codecs; 831 codecs.push_back(kOpusCodec); 832 codecs[0].bitrate = 0; 833 codecs[0].params["stereo"] = "1"; 834 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 835 webrtc::CodecInst gcodec; 836 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 837 EXPECT_STREQ("opus", gcodec.plname); 838 EXPECT_EQ(2, gcodec.channels); 839 EXPECT_EQ(64000, gcodec.rate); 840 } 841 842 // Test that with bitrate=invalid and stereo=1, 843 // channels and bitrate are 2 and 64000. 844 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusGoodXBitrate1Stereo) { 845 EXPECT_TRUE(SetupEngine()); 846 int channel_num = voe_.GetLastChannel(); 847 std::vector<cricket::AudioCodec> codecs; 848 codecs.push_back(kOpusCodec); 849 codecs[0].params["stereo"] = "1"; 850 webrtc::CodecInst gcodec; 851 852 // bitrate that's out of the range between 6000 and 510000 will be considered 853 // as invalid and ignored. 854 codecs[0].bitrate = 5999; 855 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 856 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 857 EXPECT_STREQ("opus", gcodec.plname); 858 EXPECT_EQ(2, gcodec.channels); 859 EXPECT_EQ(64000, gcodec.rate); 860 861 codecs[0].bitrate = 510001; 862 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 863 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 864 EXPECT_STREQ("opus", gcodec.plname); 865 EXPECT_EQ(2, gcodec.channels); 866 EXPECT_EQ(64000, gcodec.rate); 867 } 868 869 // Test that with bitrate=N and stereo unset, 870 // channels and bitrate are 1 and N. 871 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusGoodNBitrateNoStereo) { 872 EXPECT_TRUE(SetupEngine()); 873 int channel_num = voe_.GetLastChannel(); 874 std::vector<cricket::AudioCodec> codecs; 875 codecs.push_back(kOpusCodec); 876 codecs[0].bitrate = 96000; 877 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 878 webrtc::CodecInst gcodec; 879 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 880 EXPECT_EQ(111, gcodec.pltype); 881 EXPECT_EQ(96000, gcodec.rate); 882 EXPECT_STREQ("opus", gcodec.plname); 883 EXPECT_EQ(1, gcodec.channels); 884 EXPECT_EQ(48000, gcodec.plfreq); 885 } 886 887 // Test that with bitrate=N and stereo=0, 888 // channels and bitrate are 1 and N. 889 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusGoodNBitrate0Stereo) { 890 EXPECT_TRUE(SetupEngine()); 891 int channel_num = voe_.GetLastChannel(); 892 std::vector<cricket::AudioCodec> codecs; 893 codecs.push_back(kOpusCodec); 894 codecs[0].bitrate = 30000; 895 codecs[0].params["stereo"] = "0"; 896 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 897 webrtc::CodecInst gcodec; 898 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 899 EXPECT_EQ(1, gcodec.channels); 900 EXPECT_EQ(30000, gcodec.rate); 901 EXPECT_STREQ("opus", gcodec.plname); 902 } 903 904 // Test that with bitrate=N and without any parameters, 905 // channels and bitrate are 1 and N. 906 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusGoodNBitrateNoParameters) { 907 EXPECT_TRUE(SetupEngine()); 908 int channel_num = voe_.GetLastChannel(); 909 std::vector<cricket::AudioCodec> codecs; 910 codecs.push_back(kOpusCodec); 911 codecs[0].bitrate = 30000; 912 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 913 webrtc::CodecInst gcodec; 914 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 915 EXPECT_EQ(1, gcodec.channels); 916 EXPECT_EQ(30000, gcodec.rate); 917 EXPECT_STREQ("opus", gcodec.plname); 918 } 919 920 // Test that with bitrate=N and stereo=1, 921 // channels and bitrate are 2 and N. 922 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusGoodNBitrate1Stereo) { 923 EXPECT_TRUE(SetupEngine()); 924 int channel_num = voe_.GetLastChannel(); 925 std::vector<cricket::AudioCodec> codecs; 926 codecs.push_back(kOpusCodec); 927 codecs[0].bitrate = 30000; 928 codecs[0].params["stereo"] = "1"; 929 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 930 webrtc::CodecInst gcodec; 931 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 932 EXPECT_EQ(2, gcodec.channels); 933 EXPECT_EQ(30000, gcodec.rate); 934 EXPECT_STREQ("opus", gcodec.plname); 935 } 936 937 // Test that bitrate will be overridden by the "maxaveragebitrate" parameter. 938 // Also test that the "maxaveragebitrate" can't be set to values outside the 939 // range of 6000 and 510000 940 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusMaxAverageBitrate) { 941 EXPECT_TRUE(SetupEngine()); 942 int channel_num = voe_.GetLastChannel(); 943 std::vector<cricket::AudioCodec> codecs; 944 codecs.push_back(kOpusCodec); 945 codecs[0].bitrate = 30000; 946 webrtc::CodecInst gcodec; 947 948 // Ignore if less than 6000. 949 codecs[0].params["maxaveragebitrate"] = "5999"; 950 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 951 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 952 EXPECT_EQ(30000, gcodec.rate); 953 954 // Ignore if larger than 510000. 955 codecs[0].params["maxaveragebitrate"] = "510001"; 956 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 957 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 958 EXPECT_EQ(30000, gcodec.rate); 959 960 codecs[0].params["maxaveragebitrate"] = "200000"; 961 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 962 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 963 EXPECT_EQ(200000, gcodec.rate); 964 } 965 966 // Test that we can enable NACK with opus as caller. 967 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecEnableNackAsCaller) { 968 EXPECT_TRUE(SetupEngine()); 969 int channel_num = voe_.GetLastChannel(); 970 std::vector<cricket::AudioCodec> codecs; 971 codecs.push_back(kOpusCodec); 972 codecs[0].AddFeedbackParam(cricket::FeedbackParam(cricket::kRtcpFbParamNack, 973 cricket::kParamValueEmpty)); 974 EXPECT_FALSE(voe_.GetNACK(channel_num)); 975 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 976 EXPECT_TRUE(voe_.GetNACK(channel_num)); 977 } 978 979 // Test that we can enable NACK with opus as callee. 980 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecEnableNackAsCallee) { 981 EXPECT_TRUE(engine_.Init(talk_base::Thread::Current())); 982 channel_ = engine_.CreateChannel(); 983 EXPECT_TRUE(channel_ != NULL); 984 985 int channel_num = voe_.GetLastChannel(); 986 std::vector<cricket::AudioCodec> codecs; 987 codecs.push_back(kOpusCodec); 988 codecs[0].AddFeedbackParam(cricket::FeedbackParam(cricket::kRtcpFbParamNack, 989 cricket::kParamValueEmpty)); 990 EXPECT_FALSE(voe_.GetNACK(channel_num)); 991 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 992 EXPECT_FALSE(voe_.GetNACK(channel_num)); 993 994 EXPECT_TRUE(channel_->AddSendStream( 995 cricket::StreamParams::CreateLegacy(kSsrc1))); 996 EXPECT_TRUE(voe_.GetNACK(channel_num)); 997 } 998 999 // Test that we can enable NACK on receive streams. 1000 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecEnableNackRecvStreams) { 1001 EXPECT_TRUE(SetupEngine()); 1002 EXPECT_TRUE(channel_->SetOptions(options_conference_)); 1003 int channel_num1 = voe_.GetLastChannel(); 1004 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2))); 1005 int channel_num2 = voe_.GetLastChannel(); 1006 std::vector<cricket::AudioCodec> codecs; 1007 codecs.push_back(kOpusCodec); 1008 codecs[0].AddFeedbackParam(cricket::FeedbackParam(cricket::kRtcpFbParamNack, 1009 cricket::kParamValueEmpty)); 1010 EXPECT_FALSE(voe_.GetNACK(channel_num1)); 1011 EXPECT_FALSE(voe_.GetNACK(channel_num2)); 1012 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1013 EXPECT_TRUE(voe_.GetNACK(channel_num1)); 1014 EXPECT_TRUE(voe_.GetNACK(channel_num2)); 1015 } 1016 1017 // Test that we can disable NACK. 1018 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecDisableNack) { 1019 EXPECT_TRUE(SetupEngine()); 1020 int channel_num = voe_.GetLastChannel(); 1021 std::vector<cricket::AudioCodec> codecs; 1022 codecs.push_back(kOpusCodec); 1023 codecs[0].AddFeedbackParam(cricket::FeedbackParam(cricket::kRtcpFbParamNack, 1024 cricket::kParamValueEmpty)); 1025 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1026 EXPECT_TRUE(voe_.GetNACK(channel_num)); 1027 1028 codecs.clear(); 1029 codecs.push_back(kOpusCodec); 1030 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1031 EXPECT_FALSE(voe_.GetNACK(channel_num)); 1032 } 1033 1034 // Test that we can disable NACK on receive streams. 1035 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecDisableNackRecvStreams) { 1036 EXPECT_TRUE(SetupEngine()); 1037 EXPECT_TRUE(channel_->SetOptions(options_conference_)); 1038 int channel_num1 = voe_.GetLastChannel(); 1039 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2))); 1040 int channel_num2 = voe_.GetLastChannel(); 1041 std::vector<cricket::AudioCodec> codecs; 1042 codecs.push_back(kOpusCodec); 1043 codecs[0].AddFeedbackParam(cricket::FeedbackParam(cricket::kRtcpFbParamNack, 1044 cricket::kParamValueEmpty)); 1045 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1046 EXPECT_TRUE(voe_.GetNACK(channel_num1)); 1047 EXPECT_TRUE(voe_.GetNACK(channel_num2)); 1048 1049 codecs.clear(); 1050 codecs.push_back(kOpusCodec); 1051 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1052 EXPECT_FALSE(voe_.GetNACK(channel_num1)); 1053 EXPECT_FALSE(voe_.GetNACK(channel_num2)); 1054 } 1055 1056 // Test that NACK is enabled on a new receive stream. 1057 TEST_F(WebRtcVoiceEngineTestFake, AddRecvStreamEnableNack) { 1058 EXPECT_TRUE(SetupEngine()); 1059 EXPECT_TRUE(channel_->SetOptions(options_conference_)); 1060 int channel_num = voe_.GetLastChannel(); 1061 std::vector<cricket::AudioCodec> codecs; 1062 codecs.push_back(kIsacCodec); 1063 codecs[0].AddFeedbackParam(cricket::FeedbackParam(cricket::kRtcpFbParamNack, 1064 cricket::kParamValueEmpty)); 1065 codecs.push_back(kCn16000Codec); 1066 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1067 EXPECT_TRUE(voe_.GetNACK(channel_num)); 1068 1069 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2))); 1070 channel_num = voe_.GetLastChannel(); 1071 EXPECT_TRUE(voe_.GetNACK(channel_num)); 1072 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(3))); 1073 channel_num = voe_.GetLastChannel(); 1074 EXPECT_TRUE(voe_.GetNACK(channel_num)); 1075 } 1076 1077 // Test that we can apply CELT with stereo mode but fail with mono mode. 1078 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsCelt) { 1079 EXPECT_TRUE(SetupEngine()); 1080 int channel_num = voe_.GetLastChannel(); 1081 std::vector<cricket::AudioCodec> codecs; 1082 codecs.push_back(kCeltCodec); 1083 codecs.push_back(kPcmuCodec); 1084 codecs[0].id = 96; 1085 codecs[0].channels = 2; 1086 codecs[0].bitrate = 96000; 1087 codecs[1].bitrate = 96000; 1088 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1089 webrtc::CodecInst gcodec; 1090 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 1091 EXPECT_EQ(96, gcodec.pltype); 1092 EXPECT_EQ(96000, gcodec.rate); 1093 EXPECT_EQ(2, gcodec.channels); 1094 EXPECT_STREQ("CELT", gcodec.plname); 1095 // Doesn't support mono, expect it to fall back to the next codec in the list. 1096 codecs[0].channels = 1; 1097 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1098 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 1099 EXPECT_EQ(0, gcodec.pltype); 1100 EXPECT_EQ(1, gcodec.channels); 1101 EXPECT_EQ(64000, gcodec.rate); 1102 EXPECT_STREQ("PCMU", gcodec.plname); 1103 } 1104 1105 // Test that we can switch back and forth between CELT and ISAC with CN. 1106 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsIsacCeltSwitching) { 1107 EXPECT_TRUE(SetupEngine()); 1108 int channel_num = voe_.GetLastChannel(); 1109 std::vector<cricket::AudioCodec> celt_codecs; 1110 celt_codecs.push_back(kCeltCodec); 1111 EXPECT_TRUE(channel_->SetSendCodecs(celt_codecs)); 1112 webrtc::CodecInst gcodec; 1113 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 1114 EXPECT_EQ(110, gcodec.pltype); 1115 EXPECT_STREQ("CELT", gcodec.plname); 1116 1117 std::vector<cricket::AudioCodec> isac_codecs; 1118 isac_codecs.push_back(kIsacCodec); 1119 isac_codecs.push_back(kCn16000Codec); 1120 isac_codecs.push_back(kCeltCodec); 1121 EXPECT_TRUE(channel_->SetSendCodecs(isac_codecs)); 1122 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 1123 EXPECT_EQ(103, gcodec.pltype); 1124 EXPECT_STREQ("ISAC", gcodec.plname); 1125 1126 EXPECT_TRUE(channel_->SetSendCodecs(celt_codecs)); 1127 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 1128 EXPECT_EQ(110, gcodec.pltype); 1129 EXPECT_STREQ("CELT", gcodec.plname); 1130 } 1131 1132 // Test that we handle various ways of specifying bitrate. 1133 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsBitrate) { 1134 EXPECT_TRUE(SetupEngine()); 1135 int channel_num = voe_.GetLastChannel(); 1136 std::vector<cricket::AudioCodec> codecs; 1137 codecs.push_back(kIsacCodec); // bitrate == 32000 1138 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1139 webrtc::CodecInst gcodec; 1140 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 1141 EXPECT_EQ(103, gcodec.pltype); 1142 EXPECT_STREQ("ISAC", gcodec.plname); 1143 EXPECT_EQ(32000, gcodec.rate); 1144 1145 codecs[0].bitrate = 0; // bitrate == default 1146 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1147 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 1148 EXPECT_EQ(103, gcodec.pltype); 1149 EXPECT_STREQ("ISAC", gcodec.plname); 1150 EXPECT_EQ(-1, gcodec.rate); 1151 1152 codecs[0].bitrate = 28000; // bitrate == 28000 1153 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1154 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 1155 EXPECT_EQ(103, gcodec.pltype); 1156 EXPECT_STREQ("ISAC", gcodec.plname); 1157 EXPECT_EQ(28000, gcodec.rate); 1158 1159 codecs[0] = kPcmuCodec; // bitrate == 64000 1160 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1161 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 1162 EXPECT_EQ(0, gcodec.pltype); 1163 EXPECT_STREQ("PCMU", gcodec.plname); 1164 EXPECT_EQ(64000, gcodec.rate); 1165 1166 codecs[0].bitrate = 0; // bitrate == default 1167 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1168 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 1169 EXPECT_EQ(0, gcodec.pltype); 1170 EXPECT_STREQ("PCMU", gcodec.plname); 1171 EXPECT_EQ(64000, gcodec.rate); 1172 1173 codecs[0] = kOpusCodec; 1174 codecs[0].bitrate = 0; // bitrate == default 1175 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1176 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 1177 EXPECT_EQ(111, gcodec.pltype); 1178 EXPECT_STREQ("opus", gcodec.plname); 1179 EXPECT_EQ(32000, gcodec.rate); 1180 } 1181 1182 // Test that we fall back to PCMU if no codecs are specified. 1183 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsNoCodecs) { 1184 EXPECT_TRUE(SetupEngine()); 1185 int channel_num = voe_.GetLastChannel(); 1186 std::vector<cricket::AudioCodec> codecs; 1187 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1188 webrtc::CodecInst gcodec; 1189 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 1190 EXPECT_EQ(0, gcodec.pltype); 1191 EXPECT_STREQ("PCMU", gcodec.plname); 1192 EXPECT_FALSE(voe_.GetVAD(channel_num)); 1193 EXPECT_FALSE(voe_.GetFEC(channel_num)); 1194 EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false)); 1195 EXPECT_EQ(105, voe_.GetSendCNPayloadType(channel_num, true)); 1196 EXPECT_EQ(106, voe_.GetSendTelephoneEventPayloadType(channel_num)); 1197 } 1198 1199 // Test that we set VAD and DTMF types correctly as caller. 1200 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsCNandDTMFAsCaller) { 1201 EXPECT_TRUE(SetupEngine()); 1202 int channel_num = voe_.GetLastChannel(); 1203 std::vector<cricket::AudioCodec> codecs; 1204 codecs.push_back(kIsacCodec); 1205 codecs.push_back(kPcmuCodec); 1206 // TODO(juberti): cn 32000 1207 codecs.push_back(kCn16000Codec); 1208 codecs.push_back(kCn8000Codec); 1209 codecs.push_back(kTelephoneEventCodec); 1210 codecs.push_back(kRedCodec); 1211 codecs[0].id = 96; 1212 codecs[2].id = 97; // wideband CN 1213 codecs[4].id = 98; // DTMF 1214 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1215 webrtc::CodecInst gcodec; 1216 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 1217 EXPECT_EQ(96, gcodec.pltype); 1218 EXPECT_STREQ("ISAC", gcodec.plname); 1219 EXPECT_TRUE(voe_.GetVAD(channel_num)); 1220 EXPECT_FALSE(voe_.GetFEC(channel_num)); 1221 EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false)); 1222 EXPECT_EQ(97, voe_.GetSendCNPayloadType(channel_num, true)); 1223 EXPECT_EQ(98, voe_.GetSendTelephoneEventPayloadType(channel_num)); 1224 } 1225 1226 // Test that we set VAD and DTMF types correctly as callee. 1227 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsCNandDTMFAsCallee) { 1228 EXPECT_TRUE(engine_.Init(talk_base::Thread::Current())); 1229 channel_ = engine_.CreateChannel(); 1230 EXPECT_TRUE(channel_ != NULL); 1231 1232 int channel_num = voe_.GetLastChannel(); 1233 std::vector<cricket::AudioCodec> codecs; 1234 codecs.push_back(kIsacCodec); 1235 codecs.push_back(kPcmuCodec); 1236 // TODO(juberti): cn 32000 1237 codecs.push_back(kCn16000Codec); 1238 codecs.push_back(kCn8000Codec); 1239 codecs.push_back(kTelephoneEventCodec); 1240 codecs.push_back(kRedCodec); 1241 codecs[0].id = 96; 1242 codecs[2].id = 97; // wideband CN 1243 codecs[4].id = 98; // DTMF 1244 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1245 EXPECT_TRUE(channel_->AddSendStream( 1246 cricket::StreamParams::CreateLegacy(kSsrc1))); 1247 1248 webrtc::CodecInst gcodec; 1249 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 1250 EXPECT_EQ(96, gcodec.pltype); 1251 EXPECT_STREQ("ISAC", gcodec.plname); 1252 EXPECT_TRUE(voe_.GetVAD(channel_num)); 1253 EXPECT_FALSE(voe_.GetFEC(channel_num)); 1254 EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false)); 1255 EXPECT_EQ(97, voe_.GetSendCNPayloadType(channel_num, true)); 1256 EXPECT_EQ(98, voe_.GetSendTelephoneEventPayloadType(channel_num)); 1257 } 1258 1259 // Test that we only apply VAD if we have a CN codec that matches the 1260 // send codec clockrate. 1261 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsCNNoMatch) { 1262 EXPECT_TRUE(SetupEngine()); 1263 int channel_num = voe_.GetLastChannel(); 1264 std::vector<cricket::AudioCodec> codecs; 1265 // Set ISAC(16K) and CN(16K). VAD should be activated. 1266 codecs.push_back(kIsacCodec); 1267 codecs.push_back(kCn16000Codec); 1268 codecs[1].id = 97; 1269 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1270 webrtc::CodecInst gcodec; 1271 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 1272 EXPECT_STREQ("ISAC", gcodec.plname); 1273 EXPECT_TRUE(voe_.GetVAD(channel_num)); 1274 EXPECT_EQ(97, voe_.GetSendCNPayloadType(channel_num, true)); 1275 // Set PCMU(8K) and CN(16K). VAD should not be activated. 1276 codecs[0] = kPcmuCodec; 1277 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1278 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 1279 EXPECT_STREQ("PCMU", gcodec.plname); 1280 EXPECT_FALSE(voe_.GetVAD(channel_num)); 1281 // Set PCMU(8K) and CN(8K). VAD should be activated. 1282 codecs[1] = kCn8000Codec; 1283 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1284 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 1285 EXPECT_STREQ("PCMU", gcodec.plname); 1286 EXPECT_TRUE(voe_.GetVAD(channel_num)); 1287 EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false)); 1288 // Set ISAC(16K) and CN(8K). VAD should not be activated. 1289 codecs[0] = kIsacCodec; 1290 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1291 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 1292 EXPECT_STREQ("ISAC", gcodec.plname); 1293 EXPECT_FALSE(voe_.GetVAD(channel_num)); 1294 } 1295 1296 // Test that we perform case-insensitive matching of codec names. 1297 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsCaseInsensitive) { 1298 EXPECT_TRUE(SetupEngine()); 1299 int channel_num = voe_.GetLastChannel(); 1300 std::vector<cricket::AudioCodec> codecs; 1301 codecs.push_back(kIsacCodec); 1302 codecs.push_back(kPcmuCodec); 1303 codecs.push_back(kCn16000Codec); 1304 codecs.push_back(kCn8000Codec); 1305 codecs.push_back(kTelephoneEventCodec); 1306 codecs.push_back(kRedCodec); 1307 codecs[0].name = "iSaC"; 1308 codecs[0].id = 96; 1309 codecs[2].id = 97; // wideband CN 1310 codecs[4].id = 98; // DTMF 1311 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1312 webrtc::CodecInst gcodec; 1313 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 1314 EXPECT_EQ(96, gcodec.pltype); 1315 EXPECT_STREQ("ISAC", gcodec.plname); 1316 EXPECT_TRUE(voe_.GetVAD(channel_num)); 1317 EXPECT_FALSE(voe_.GetFEC(channel_num)); 1318 EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false)); 1319 EXPECT_EQ(97, voe_.GetSendCNPayloadType(channel_num, true)); 1320 EXPECT_EQ(98, voe_.GetSendTelephoneEventPayloadType(channel_num)); 1321 } 1322 1323 // Test that we set up FEC correctly as caller. 1324 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsREDAsCaller) { 1325 EXPECT_TRUE(SetupEngine()); 1326 int channel_num = voe_.GetLastChannel(); 1327 std::vector<cricket::AudioCodec> codecs; 1328 codecs.push_back(kRedCodec); 1329 codecs.push_back(kIsacCodec); 1330 codecs.push_back(kPcmuCodec); 1331 codecs[0].id = 127; 1332 codecs[0].params[""] = "96/96"; 1333 codecs[1].id = 96; 1334 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1335 webrtc::CodecInst gcodec; 1336 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 1337 EXPECT_EQ(96, gcodec.pltype); 1338 EXPECT_STREQ("ISAC", gcodec.plname); 1339 EXPECT_TRUE(voe_.GetFEC(channel_num)); 1340 EXPECT_EQ(127, voe_.GetSendFECPayloadType(channel_num)); 1341 } 1342 1343 // Test that we set up FEC correctly as callee. 1344 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsREDAsCallee) { 1345 EXPECT_TRUE(engine_.Init(talk_base::Thread::Current())); 1346 channel_ = engine_.CreateChannel(); 1347 EXPECT_TRUE(channel_ != NULL); 1348 1349 int channel_num = voe_.GetLastChannel(); 1350 std::vector<cricket::AudioCodec> codecs; 1351 codecs.push_back(kRedCodec); 1352 codecs.push_back(kIsacCodec); 1353 codecs.push_back(kPcmuCodec); 1354 codecs[0].id = 127; 1355 codecs[0].params[""] = "96/96"; 1356 codecs[1].id = 96; 1357 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1358 EXPECT_TRUE(channel_->AddSendStream( 1359 cricket::StreamParams::CreateLegacy(kSsrc1))); 1360 webrtc::CodecInst gcodec; 1361 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 1362 EXPECT_EQ(96, gcodec.pltype); 1363 EXPECT_STREQ("ISAC", gcodec.plname); 1364 EXPECT_TRUE(voe_.GetFEC(channel_num)); 1365 EXPECT_EQ(127, voe_.GetSendFECPayloadType(channel_num)); 1366 } 1367 1368 // Test that we set up FEC correctly if params are omitted. 1369 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsREDNoParams) { 1370 EXPECT_TRUE(SetupEngine()); 1371 int channel_num = voe_.GetLastChannel(); 1372 std::vector<cricket::AudioCodec> codecs; 1373 codecs.push_back(kRedCodec); 1374 codecs.push_back(kIsacCodec); 1375 codecs.push_back(kPcmuCodec); 1376 codecs[0].id = 127; 1377 codecs[1].id = 96; 1378 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1379 webrtc::CodecInst gcodec; 1380 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 1381 EXPECT_EQ(96, gcodec.pltype); 1382 EXPECT_STREQ("ISAC", gcodec.plname); 1383 EXPECT_TRUE(voe_.GetFEC(channel_num)); 1384 EXPECT_EQ(127, voe_.GetSendFECPayloadType(channel_num)); 1385 } 1386 1387 // Test that we ignore RED if the parameters aren't named the way we expect. 1388 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsBadRED1) { 1389 EXPECT_TRUE(SetupEngine()); 1390 int channel_num = voe_.GetLastChannel(); 1391 std::vector<cricket::AudioCodec> codecs; 1392 codecs.push_back(kRedCodec); 1393 codecs.push_back(kIsacCodec); 1394 codecs.push_back(kPcmuCodec); 1395 codecs[0].id = 127; 1396 codecs[0].params["ABC"] = "96/96"; 1397 codecs[1].id = 96; 1398 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1399 webrtc::CodecInst gcodec; 1400 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 1401 EXPECT_EQ(96, gcodec.pltype); 1402 EXPECT_STREQ("ISAC", gcodec.plname); 1403 EXPECT_FALSE(voe_.GetFEC(channel_num)); 1404 } 1405 1406 // Test that we ignore RED if it uses different primary/secondary encoding. 1407 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsBadRED2) { 1408 EXPECT_TRUE(SetupEngine()); 1409 int channel_num = voe_.GetLastChannel(); 1410 std::vector<cricket::AudioCodec> codecs; 1411 codecs.push_back(kRedCodec); 1412 codecs.push_back(kIsacCodec); 1413 codecs.push_back(kPcmuCodec); 1414 codecs[0].id = 127; 1415 codecs[0].params[""] = "96/0"; 1416 codecs[1].id = 96; 1417 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1418 webrtc::CodecInst gcodec; 1419 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 1420 EXPECT_EQ(96, gcodec.pltype); 1421 EXPECT_STREQ("ISAC", gcodec.plname); 1422 EXPECT_FALSE(voe_.GetFEC(channel_num)); 1423 } 1424 1425 // Test that we ignore RED if it uses more than 2 encodings. 1426 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsBadRED3) { 1427 EXPECT_TRUE(SetupEngine()); 1428 int channel_num = voe_.GetLastChannel(); 1429 std::vector<cricket::AudioCodec> codecs; 1430 codecs.push_back(kRedCodec); 1431 codecs.push_back(kIsacCodec); 1432 codecs.push_back(kPcmuCodec); 1433 codecs[0].id = 127; 1434 codecs[0].params[""] = "96/96/96"; 1435 codecs[1].id = 96; 1436 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1437 webrtc::CodecInst gcodec; 1438 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 1439 EXPECT_EQ(96, gcodec.pltype); 1440 EXPECT_STREQ("ISAC", gcodec.plname); 1441 EXPECT_FALSE(voe_.GetFEC(channel_num)); 1442 } 1443 1444 // Test that we ignore RED if it has bogus codec ids. 1445 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsBadRED4) { 1446 EXPECT_TRUE(SetupEngine()); 1447 int channel_num = voe_.GetLastChannel(); 1448 std::vector<cricket::AudioCodec> codecs; 1449 codecs.push_back(kRedCodec); 1450 codecs.push_back(kIsacCodec); 1451 codecs.push_back(kPcmuCodec); 1452 codecs[0].id = 127; 1453 codecs[0].params[""] = "ABC/ABC"; 1454 codecs[1].id = 96; 1455 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1456 webrtc::CodecInst gcodec; 1457 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 1458 EXPECT_EQ(96, gcodec.pltype); 1459 EXPECT_STREQ("ISAC", gcodec.plname); 1460 EXPECT_FALSE(voe_.GetFEC(channel_num)); 1461 } 1462 1463 // Test that we ignore RED if it refers to a codec that is not present. 1464 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsBadRED5) { 1465 EXPECT_TRUE(SetupEngine()); 1466 int channel_num = voe_.GetLastChannel(); 1467 std::vector<cricket::AudioCodec> codecs; 1468 codecs.push_back(kRedCodec); 1469 codecs.push_back(kIsacCodec); 1470 codecs.push_back(kPcmuCodec); 1471 codecs[0].id = 127; 1472 codecs[0].params[""] = "97/97"; 1473 codecs[1].id = 96; 1474 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1475 webrtc::CodecInst gcodec; 1476 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 1477 EXPECT_EQ(96, gcodec.pltype); 1478 EXPECT_STREQ("ISAC", gcodec.plname); 1479 EXPECT_FALSE(voe_.GetFEC(channel_num)); 1480 } 1481 1482 // Test that we support setting an empty list of recv header extensions. 1483 TEST_F(WebRtcVoiceEngineTestFake, SetRecvRtpHeaderExtensions) { 1484 EXPECT_TRUE(SetupEngine()); 1485 std::vector<cricket::RtpHeaderExtension> extensions; 1486 int channel_num = voe_.GetLastChannel(); 1487 bool enable = false; 1488 unsigned char id = 0; 1489 1490 // An empty list shouldn't cause audio-level headers to be enabled. 1491 EXPECT_TRUE(channel_->SetRecvRtpHeaderExtensions(extensions)); 1492 EXPECT_EQ(0, voe_.GetRTPAudioLevelIndicationStatus( 1493 channel_num, enable, id)); 1494 EXPECT_FALSE(enable); 1495 1496 // Nor should indicating we can receive the audio-level header. 1497 extensions.push_back(cricket::RtpHeaderExtension( 1498 "urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8)); 1499 EXPECT_TRUE(channel_->SetRecvRtpHeaderExtensions(extensions)); 1500 EXPECT_EQ(0, voe_.GetRTPAudioLevelIndicationStatus( 1501 channel_num, enable, id)); 1502 EXPECT_FALSE(enable); 1503 } 1504 1505 // Test that we support setting certain send header extensions. 1506 TEST_F(WebRtcVoiceEngineTestFake, SetSendRtpHeaderExtensions) { 1507 EXPECT_TRUE(SetupEngine()); 1508 std::vector<cricket::RtpHeaderExtension> extensions; 1509 int channel_num = voe_.GetLastChannel(); 1510 TestSetSendRtpHeaderExtensions(channel_num); 1511 } 1512 1513 // Test that we can create a channel and start sending/playing out on it. 1514 TEST_F(WebRtcVoiceEngineTestFake, SendAndPlayout) { 1515 EXPECT_TRUE(SetupEngine()); 1516 int channel_num = voe_.GetLastChannel(); 1517 std::vector<cricket::AudioCodec> codecs; 1518 codecs.push_back(kPcmuCodec); 1519 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1520 EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE)); 1521 EXPECT_TRUE(voe_.GetSend(channel_num)); 1522 EXPECT_TRUE(channel_->SetPlayout(true)); 1523 EXPECT_TRUE(voe_.GetPlayout(channel_num)); 1524 EXPECT_TRUE(channel_->SetSend(cricket::SEND_NOTHING)); 1525 EXPECT_FALSE(voe_.GetSend(channel_num)); 1526 EXPECT_TRUE(channel_->SetPlayout(false)); 1527 EXPECT_FALSE(voe_.GetPlayout(channel_num)); 1528 } 1529 1530 // Test that we can add and remove send streams. 1531 TEST_F(WebRtcVoiceEngineTestFake, CreateAndDeleteMultipleSendStreams) { 1532 SetupForMultiSendStream(); 1533 1534 static const uint32 kSsrcs4[] = {1, 2, 3, 4}; 1535 1536 // Set the global state for sending. 1537 EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE)); 1538 1539 for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) { 1540 EXPECT_TRUE(channel_->AddSendStream( 1541 cricket::StreamParams::CreateLegacy(kSsrcs4[i]))); 1542 1543 // Verify that we are in a sending state for all the created streams. 1544 int channel_num = voe_.GetChannelFromLocalSsrc(kSsrcs4[i]); 1545 EXPECT_TRUE(voe_.GetSend(channel_num)); 1546 } 1547 1548 // Remove the first send channel, which is the default channel. It will only 1549 // recycle the default channel but not delete it. 1550 EXPECT_TRUE(channel_->RemoveSendStream(kSsrcs4[0])); 1551 // Stream should already be Removed from the send stream list. 1552 EXPECT_FALSE(channel_->RemoveSendStream(kSsrcs4[0])); 1553 // But the default still exists. 1554 EXPECT_EQ(0, voe_.GetChannelFromLocalSsrc(kSsrcs4[0])); 1555 1556 // Delete the rest of send channel streams. 1557 for (unsigned int i = 1; i < ARRAY_SIZE(kSsrcs4); ++i) { 1558 EXPECT_TRUE(channel_->RemoveSendStream(kSsrcs4[i])); 1559 // Stream should already be deleted. 1560 EXPECT_FALSE(channel_->RemoveSendStream(kSsrcs4[i])); 1561 EXPECT_EQ(-1, voe_.GetChannelFromLocalSsrc(kSsrcs4[i])); 1562 } 1563 } 1564 1565 // Test SetSendCodecs correctly configure the codecs in all send streams. 1566 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsWithMultipleSendStreams) { 1567 SetupForMultiSendStream(); 1568 1569 static const uint32 kSsrcs4[] = {1, 2, 3, 4}; 1570 // Create send streams. 1571 for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) { 1572 EXPECT_TRUE(channel_->AddSendStream( 1573 cricket::StreamParams::CreateLegacy(kSsrcs4[i]))); 1574 } 1575 1576 std::vector<cricket::AudioCodec> codecs; 1577 // Set ISAC(16K) and CN(16K). VAD should be activated. 1578 codecs.push_back(kIsacCodec); 1579 codecs.push_back(kCn16000Codec); 1580 codecs[1].id = 97; 1581 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1582 1583 // Verify ISAC and VAD are corrected configured on all send channels. 1584 webrtc::CodecInst gcodec; 1585 for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) { 1586 int channel_num = voe_.GetChannelFromLocalSsrc(kSsrcs4[i]); 1587 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 1588 EXPECT_STREQ("ISAC", gcodec.plname); 1589 EXPECT_TRUE(voe_.GetVAD(channel_num)); 1590 EXPECT_EQ(97, voe_.GetSendCNPayloadType(channel_num, true)); 1591 } 1592 1593 // Change to PCMU(8K) and CN(16K). VAD should not be activated. 1594 codecs[0] = kPcmuCodec; 1595 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1596 for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) { 1597 int channel_num = voe_.GetChannelFromLocalSsrc(kSsrcs4[i]); 1598 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); 1599 EXPECT_STREQ("PCMU", gcodec.plname); 1600 EXPECT_FALSE(voe_.GetVAD(channel_num)); 1601 } 1602 } 1603 1604 // Test we can SetSend on all send streams correctly. 1605 TEST_F(WebRtcVoiceEngineTestFake, SetSendWithMultipleSendStreams) { 1606 SetupForMultiSendStream(); 1607 1608 static const uint32 kSsrcs4[] = {1, 2, 3, 4}; 1609 // Create the send channels and they should be a SEND_NOTHING date. 1610 for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) { 1611 EXPECT_TRUE(channel_->AddSendStream( 1612 cricket::StreamParams::CreateLegacy(kSsrcs4[i]))); 1613 int channel_num = voe_.GetLastChannel(); 1614 EXPECT_FALSE(voe_.GetSend(channel_num)); 1615 } 1616 1617 // Set the global state for starting sending. 1618 EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE)); 1619 for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) { 1620 // Verify that we are in a sending state for all the send streams. 1621 int channel_num = voe_.GetChannelFromLocalSsrc(kSsrcs4[i]); 1622 EXPECT_TRUE(voe_.GetSend(channel_num)); 1623 } 1624 1625 // Set the global state for stopping sending. 1626 EXPECT_TRUE(channel_->SetSend(cricket::SEND_NOTHING)); 1627 for (unsigned int i = 1; i < ARRAY_SIZE(kSsrcs4); ++i) { 1628 // Verify that we are in a stop state for all the send streams. 1629 int channel_num = voe_.GetChannelFromLocalSsrc(kSsrcs4[i]); 1630 EXPECT_FALSE(voe_.GetSend(channel_num)); 1631 } 1632 } 1633 1634 // Test we can set the correct statistics on all send streams. 1635 TEST_F(WebRtcVoiceEngineTestFake, GetStatsWithMultipleSendStreams) { 1636 SetupForMultiSendStream(); 1637 1638 static const uint32 kSsrcs4[] = {1, 2, 3, 4}; 1639 // Create send streams. 1640 for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) { 1641 EXPECT_TRUE(channel_->AddSendStream( 1642 cricket::StreamParams::CreateLegacy(kSsrcs4[i]))); 1643 } 1644 1645 // We need send codec to be set to get all stats. 1646 std::vector<cricket::AudioCodec> codecs; 1647 codecs.push_back(kPcmuCodec); 1648 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1649 1650 cricket::VoiceMediaInfo info; 1651 EXPECT_EQ(true, channel_->GetStats(&info)); 1652 EXPECT_EQ(static_cast<size_t>(ARRAY_SIZE(kSsrcs4)), info.senders.size()); 1653 1654 // Verify the statistic information is correct. 1655 for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) { 1656 EXPECT_EQ(kSsrcs4[i], info.senders[i].ssrc()); 1657 EXPECT_EQ(kPcmuCodec.name, info.senders[i].codec_name); 1658 EXPECT_EQ(cricket::kIntStatValue, info.senders[i].bytes_sent); 1659 EXPECT_EQ(cricket::kIntStatValue, info.senders[i].packets_sent); 1660 EXPECT_EQ(cricket::kIntStatValue, info.senders[i].packets_lost); 1661 EXPECT_EQ(cricket::kFractionLostStatValue, info.senders[i].fraction_lost); 1662 EXPECT_EQ(cricket::kIntStatValue, info.senders[i].ext_seqnum); 1663 EXPECT_EQ(cricket::kIntStatValue, info.senders[i].rtt_ms); 1664 EXPECT_EQ(cricket::kIntStatValue, info.senders[i].jitter_ms); 1665 } 1666 1667 EXPECT_EQ(1u, info.receivers.size()); 1668 } 1669 1670 // Test that we support setting certain send header extensions on multiple 1671 // send streams. 1672 TEST_F(WebRtcVoiceEngineTestFake, 1673 SetSendRtpHeaderExtensionsWithMultpleSendStreams) { 1674 SetupForMultiSendStream(); 1675 1676 static const uint32 kSsrcs4[] = {1, 2, 3, 4}; 1677 // Create send streams. 1678 for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) { 1679 EXPECT_TRUE(channel_->AddSendStream( 1680 cricket::StreamParams::CreateLegacy(kSsrcs4[i]))); 1681 } 1682 1683 // Test SendRtpHeaderExtensions on each send channel. 1684 for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) { 1685 int channel_num = voe_.GetChannelFromLocalSsrc(kSsrcs4[i]); 1686 TestSetSendRtpHeaderExtensions(channel_num); 1687 } 1688 } 1689 1690 // Test that we can add and remove receive streams, and do proper send/playout. 1691 // We can receive on multiple streams while sending one stream. 1692 TEST_F(WebRtcVoiceEngineTestFake, PlayoutWithMultipleStreams) { 1693 EXPECT_TRUE(SetupEngine()); 1694 int channel_num1 = voe_.GetLastChannel(); 1695 1696 // Start playout on the default channel. 1697 EXPECT_TRUE(channel_->SetOptions(options_conference_)); 1698 EXPECT_TRUE(channel_->SetPlayout(true)); 1699 EXPECT_TRUE(voe_.GetPlayout(channel_num1)); 1700 1701 // Adding another stream should disable playout on the default channel. 1702 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2))); 1703 int channel_num2 = voe_.GetLastChannel(); 1704 std::vector<cricket::AudioCodec> codecs; 1705 codecs.push_back(kPcmuCodec); 1706 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1707 EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE)); 1708 EXPECT_TRUE(voe_.GetSend(channel_num1)); 1709 EXPECT_FALSE(voe_.GetSend(channel_num2)); 1710 1711 // Make sure only the new channel is played out. 1712 EXPECT_FALSE(voe_.GetPlayout(channel_num1)); 1713 EXPECT_TRUE(voe_.GetPlayout(channel_num2)); 1714 1715 // Adding yet another stream should have stream 2 and 3 enabled for playout. 1716 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(3))); 1717 int channel_num3 = voe_.GetLastChannel(); 1718 EXPECT_FALSE(voe_.GetPlayout(channel_num1)); 1719 EXPECT_TRUE(voe_.GetPlayout(channel_num2)); 1720 EXPECT_TRUE(voe_.GetPlayout(channel_num3)); 1721 EXPECT_FALSE(voe_.GetSend(channel_num3)); 1722 1723 // Stop sending. 1724 EXPECT_TRUE(channel_->SetSend(cricket::SEND_NOTHING)); 1725 EXPECT_FALSE(voe_.GetSend(channel_num1)); 1726 EXPECT_FALSE(voe_.GetSend(channel_num2)); 1727 EXPECT_FALSE(voe_.GetSend(channel_num3)); 1728 1729 // Stop playout. 1730 EXPECT_TRUE(channel_->SetPlayout(false)); 1731 EXPECT_FALSE(voe_.GetPlayout(channel_num1)); 1732 EXPECT_FALSE(voe_.GetPlayout(channel_num2)); 1733 EXPECT_FALSE(voe_.GetPlayout(channel_num3)); 1734 1735 // Restart playout and make sure the default channel still is not played out. 1736 EXPECT_TRUE(channel_->SetPlayout(true)); 1737 EXPECT_FALSE(voe_.GetPlayout(channel_num1)); 1738 EXPECT_TRUE(voe_.GetPlayout(channel_num2)); 1739 EXPECT_TRUE(voe_.GetPlayout(channel_num3)); 1740 1741 // Now remove the new streams and verify that the default channel is 1742 // played out again. 1743 EXPECT_TRUE(channel_->RemoveRecvStream(3)); 1744 EXPECT_TRUE(channel_->RemoveRecvStream(2)); 1745 1746 EXPECT_TRUE(voe_.GetPlayout(channel_num1)); 1747 } 1748 1749 // Test that we can set the devices to use. 1750 TEST_F(WebRtcVoiceEngineTestFake, SetDevices) { 1751 EXPECT_TRUE(SetupEngine()); 1752 int channel_num = voe_.GetLastChannel(); 1753 std::vector<cricket::AudioCodec> codecs; 1754 codecs.push_back(kPcmuCodec); 1755 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1756 1757 cricket::Device default_dev(cricket::kFakeDefaultDeviceName, 1758 cricket::kFakeDefaultDeviceId); 1759 cricket::Device dev(cricket::kFakeDeviceName, 1760 cricket::kFakeDeviceId); 1761 1762 // Test SetDevices() while not sending or playing. 1763 EXPECT_TRUE(engine_.SetDevices(&default_dev, &default_dev)); 1764 1765 // Test SetDevices() while sending and playing. 1766 EXPECT_TRUE(engine_.SetLocalMonitor(true)); 1767 EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE)); 1768 EXPECT_TRUE(channel_->SetPlayout(true)); 1769 EXPECT_TRUE(voe_.GetRecordingMicrophone()); 1770 EXPECT_TRUE(voe_.GetSend(channel_num)); 1771 EXPECT_TRUE(voe_.GetPlayout(channel_num)); 1772 1773 EXPECT_TRUE(engine_.SetDevices(&dev, &dev)); 1774 1775 EXPECT_TRUE(voe_.GetRecordingMicrophone()); 1776 EXPECT_TRUE(voe_.GetSend(channel_num)); 1777 EXPECT_TRUE(voe_.GetPlayout(channel_num)); 1778 1779 // Test that failure to open newly selected devices does not prevent opening 1780 // ones after that. 1781 voe_.set_fail_start_recording_microphone(true); 1782 voe_.set_playout_fail_channel(channel_num); 1783 voe_.set_send_fail_channel(channel_num); 1784 1785 EXPECT_FALSE(engine_.SetDevices(&default_dev, &default_dev)); 1786 1787 EXPECT_FALSE(voe_.GetRecordingMicrophone()); 1788 EXPECT_FALSE(voe_.GetSend(channel_num)); 1789 EXPECT_FALSE(voe_.GetPlayout(channel_num)); 1790 1791 voe_.set_fail_start_recording_microphone(false); 1792 voe_.set_playout_fail_channel(-1); 1793 voe_.set_send_fail_channel(-1); 1794 1795 EXPECT_TRUE(engine_.SetDevices(&dev, &dev)); 1796 1797 EXPECT_TRUE(voe_.GetRecordingMicrophone()); 1798 EXPECT_TRUE(voe_.GetSend(channel_num)); 1799 EXPECT_TRUE(voe_.GetPlayout(channel_num)); 1800 } 1801 1802 // Test that we can set the devices to use even if we failed to 1803 // open the initial ones. 1804 TEST_F(WebRtcVoiceEngineTestFake, SetDevicesWithInitiallyBadDevices) { 1805 EXPECT_TRUE(SetupEngine()); 1806 int channel_num = voe_.GetLastChannel(); 1807 std::vector<cricket::AudioCodec> codecs; 1808 codecs.push_back(kPcmuCodec); 1809 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1810 1811 cricket::Device default_dev(cricket::kFakeDefaultDeviceName, 1812 cricket::kFakeDefaultDeviceId); 1813 cricket::Device dev(cricket::kFakeDeviceName, 1814 cricket::kFakeDeviceId); 1815 1816 // Test that failure to open devices selected before starting 1817 // send/play does not prevent opening newly selected ones after that. 1818 voe_.set_fail_start_recording_microphone(true); 1819 voe_.set_playout_fail_channel(channel_num); 1820 voe_.set_send_fail_channel(channel_num); 1821 1822 EXPECT_TRUE(engine_.SetDevices(&default_dev, &default_dev)); 1823 1824 EXPECT_FALSE(engine_.SetLocalMonitor(true)); 1825 EXPECT_FALSE(channel_->SetSend(cricket::SEND_MICROPHONE)); 1826 EXPECT_FALSE(channel_->SetPlayout(true)); 1827 EXPECT_FALSE(voe_.GetRecordingMicrophone()); 1828 EXPECT_FALSE(voe_.GetSend(channel_num)); 1829 EXPECT_FALSE(voe_.GetPlayout(channel_num)); 1830 1831 voe_.set_fail_start_recording_microphone(false); 1832 voe_.set_playout_fail_channel(-1); 1833 voe_.set_send_fail_channel(-1); 1834 1835 EXPECT_TRUE(engine_.SetDevices(&dev, &dev)); 1836 1837 EXPECT_TRUE(voe_.GetRecordingMicrophone()); 1838 EXPECT_TRUE(voe_.GetSend(channel_num)); 1839 EXPECT_TRUE(voe_.GetPlayout(channel_num)); 1840 } 1841 1842 // Test that we can create a channel configured for multi-point conferences, 1843 // and start sending/playing out on it. 1844 TEST_F(WebRtcVoiceEngineTestFake, ConferenceSendAndPlayout) { 1845 EXPECT_TRUE(SetupEngine()); 1846 int channel_num = voe_.GetLastChannel(); 1847 EXPECT_TRUE(channel_->SetOptions(options_conference_)); 1848 std::vector<cricket::AudioCodec> codecs; 1849 codecs.push_back(kPcmuCodec); 1850 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1851 EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE)); 1852 EXPECT_TRUE(voe_.GetSend(channel_num)); 1853 } 1854 1855 // Test that we can create a channel configured for Codian bridges, 1856 // and start sending/playing out on it. 1857 TEST_F(WebRtcVoiceEngineTestFake, CodianSendAndPlayout) { 1858 EXPECT_TRUE(SetupEngine()); 1859 int channel_num = voe_.GetLastChannel(); 1860 webrtc::AgcConfig agc_config; 1861 EXPECT_EQ(0, voe_.GetAgcConfig(agc_config)); 1862 EXPECT_EQ(0, agc_config.targetLeveldBOv); 1863 EXPECT_TRUE(channel_->SetOptions(options_adjust_agc_)); 1864 std::vector<cricket::AudioCodec> codecs; 1865 codecs.push_back(kPcmuCodec); 1866 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1867 EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE)); 1868 EXPECT_TRUE(voe_.GetSend(channel_num)); 1869 EXPECT_EQ(0, voe_.GetAgcConfig(agc_config)); 1870 EXPECT_EQ(agc_config.targetLeveldBOv, 10); // level was attenuated 1871 EXPECT_TRUE(channel_->SetPlayout(true)); 1872 EXPECT_TRUE(voe_.GetPlayout(channel_num)); 1873 EXPECT_TRUE(channel_->SetSend(cricket::SEND_NOTHING)); 1874 EXPECT_FALSE(voe_.GetSend(channel_num)); 1875 EXPECT_EQ(0, voe_.GetAgcConfig(agc_config)); 1876 EXPECT_EQ(0, agc_config.targetLeveldBOv); // level was restored 1877 EXPECT_TRUE(channel_->SetPlayout(false)); 1878 EXPECT_FALSE(voe_.GetPlayout(channel_num)); 1879 } 1880 1881 TEST_F(WebRtcVoiceEngineTestFake, TxAgcConfigViaOptions) { 1882 EXPECT_TRUE(SetupEngine()); 1883 webrtc::AgcConfig agc_config; 1884 EXPECT_EQ(0, voe_.GetAgcConfig(agc_config)); 1885 EXPECT_EQ(0, agc_config.targetLeveldBOv); 1886 1887 cricket::AudioOptions options; 1888 options.tx_agc_target_dbov.Set(3); 1889 options.tx_agc_digital_compression_gain.Set(9); 1890 options.tx_agc_limiter.Set(true); 1891 options.auto_gain_control.Set(true); 1892 EXPECT_TRUE(engine_.SetOptions(options)); 1893 1894 EXPECT_EQ(0, voe_.GetAgcConfig(agc_config)); 1895 EXPECT_EQ(3, agc_config.targetLeveldBOv); 1896 EXPECT_EQ(9, agc_config.digitalCompressionGaindB); 1897 EXPECT_TRUE(agc_config.limiterEnable); 1898 1899 // Check interaction with adjust_agc_delta. Both should be respected, for 1900 // backwards compatibility. 1901 options.adjust_agc_delta.Set(-10); 1902 EXPECT_TRUE(engine_.SetOptions(options)); 1903 1904 EXPECT_EQ(0, voe_.GetAgcConfig(agc_config)); 1905 EXPECT_EQ(13, agc_config.targetLeveldBOv); 1906 } 1907 1908 TEST_F(WebRtcVoiceEngineTestFake, RxAgcConfigViaOptions) { 1909 EXPECT_TRUE(SetupEngine()); 1910 int channel_num = voe_.GetLastChannel(); 1911 cricket::AudioOptions options; 1912 options.rx_agc_target_dbov.Set(6); 1913 options.rx_agc_digital_compression_gain.Set(0); 1914 options.rx_agc_limiter.Set(true); 1915 options.rx_auto_gain_control.Set(true); 1916 EXPECT_TRUE(channel_->SetOptions(options)); 1917 1918 webrtc::AgcConfig agc_config; 1919 EXPECT_EQ(0, engine_.voe()->processing()->GetRxAgcConfig( 1920 channel_num, agc_config)); 1921 EXPECT_EQ(6, agc_config.targetLeveldBOv); 1922 EXPECT_EQ(0, agc_config.digitalCompressionGaindB); 1923 EXPECT_TRUE(agc_config.limiterEnable); 1924 } 1925 1926 TEST_F(WebRtcVoiceEngineTestFake, SampleRatesViaOptions) { 1927 EXPECT_TRUE(SetupEngine()); 1928 cricket::AudioOptions options; 1929 options.recording_sample_rate.Set(48000u); 1930 options.playout_sample_rate.Set(44100u); 1931 EXPECT_TRUE(engine_.SetOptions(options)); 1932 1933 unsigned int recording_sample_rate, playout_sample_rate; 1934 EXPECT_EQ(0, voe_.RecordingSampleRate(&recording_sample_rate)); 1935 EXPECT_EQ(0, voe_.PlayoutSampleRate(&playout_sample_rate)); 1936 EXPECT_EQ(48000u, recording_sample_rate); 1937 EXPECT_EQ(44100u, playout_sample_rate); 1938 } 1939 1940 TEST_F(WebRtcVoiceEngineTestFake, TraceFilterViaTraceOptions) { 1941 EXPECT_TRUE(SetupEngine()); 1942 engine_.SetLogging(talk_base::LS_INFO, ""); 1943 EXPECT_EQ( 1944 // Info: 1945 webrtc::kTraceStateInfo | webrtc::kTraceInfo | 1946 // Warning: 1947 webrtc::kTraceTerseInfo | webrtc::kTraceWarning | 1948 // Error: 1949 webrtc::kTraceError | webrtc::kTraceCritical, 1950 static_cast<int>(trace_wrapper_->filter_)); 1951 // Now set it explicitly 1952 std::string filter = 1953 "tracefilter " + talk_base::ToString(webrtc::kTraceDefault); 1954 engine_.SetLogging(talk_base::LS_VERBOSE, filter.c_str()); 1955 EXPECT_EQ(static_cast<unsigned int>(webrtc::kTraceDefault), 1956 trace_wrapper_->filter_); 1957 } 1958 1959 // Test that we can set the outgoing SSRC properly. 1960 // SSRC is set in SetupEngine by calling AddSendStream. 1961 TEST_F(WebRtcVoiceEngineTestFake, SetSendSsrc) { 1962 EXPECT_TRUE(SetupEngine()); 1963 int channel_num = voe_.GetLastChannel(); 1964 unsigned int send_ssrc; 1965 EXPECT_EQ(0, voe_.GetLocalSSRC(channel_num, send_ssrc)); 1966 EXPECT_NE(0U, send_ssrc); 1967 EXPECT_EQ(0, voe_.GetLocalSSRC(channel_num, send_ssrc)); 1968 EXPECT_EQ(kSsrc1, send_ssrc); 1969 } 1970 1971 TEST_F(WebRtcVoiceEngineTestFake, GetStats) { 1972 // Setup. We need send codec to be set to get all stats. 1973 EXPECT_TRUE(SetupEngine()); 1974 std::vector<cricket::AudioCodec> codecs; 1975 codecs.push_back(kPcmuCodec); 1976 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 1977 1978 cricket::VoiceMediaInfo info; 1979 EXPECT_EQ(true, channel_->GetStats(&info)); 1980 EXPECT_EQ(1u, info.senders.size()); 1981 EXPECT_EQ(kSsrc1, info.senders[0].ssrc()); 1982 EXPECT_EQ(kPcmuCodec.name, info.senders[0].codec_name); 1983 EXPECT_EQ(cricket::kIntStatValue, info.senders[0].bytes_sent); 1984 EXPECT_EQ(cricket::kIntStatValue, info.senders[0].packets_sent); 1985 EXPECT_EQ(cricket::kIntStatValue, info.senders[0].packets_lost); 1986 EXPECT_EQ(cricket::kFractionLostStatValue, info.senders[0].fraction_lost); 1987 EXPECT_EQ(cricket::kIntStatValue, info.senders[0].ext_seqnum); 1988 EXPECT_EQ(cricket::kIntStatValue, info.senders[0].rtt_ms); 1989 EXPECT_EQ(cricket::kIntStatValue, info.senders[0].jitter_ms); 1990 // TODO(sriniv): Add testing for more fields. These are not populated 1991 // in FakeWebrtcVoiceEngine yet. 1992 // EXPECT_EQ(cricket::kIntStatValue, info.senders[0].audio_level); 1993 // EXPECT_EQ(cricket::kIntStatValue, info.senders[0].echo_delay_median_ms); 1994 // EXPECT_EQ(cricket::kIntStatValue, info.senders[0].echo_delay_std_ms); 1995 // EXPECT_EQ(cricket::kIntStatValue, info.senders[0].echo_return_loss); 1996 // EXPECT_EQ(cricket::kIntStatValue, 1997 // info.senders[0].echo_return_loss_enhancement); 1998 1999 EXPECT_EQ(1u, info.receivers.size()); 2000 // TODO(sriniv): Add testing for receiver fields. 2001 } 2002 2003 // Test that we can set the outgoing SSRC properly with multiple streams. 2004 // SSRC is set in SetupEngine by calling AddSendStream. 2005 TEST_F(WebRtcVoiceEngineTestFake, SetSendSsrcWithMultipleStreams) { 2006 EXPECT_TRUE(SetupEngine()); 2007 EXPECT_TRUE(channel_->SetOptions(options_conference_)); 2008 int channel_num1 = voe_.GetLastChannel(); 2009 unsigned int send_ssrc; 2010 EXPECT_EQ(0, voe_.GetLocalSSRC(channel_num1, send_ssrc)); 2011 EXPECT_EQ(kSsrc1, send_ssrc); 2012 2013 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2))); 2014 int channel_num2 = voe_.GetLastChannel(); 2015 EXPECT_EQ(0, voe_.GetLocalSSRC(channel_num2, send_ssrc)); 2016 EXPECT_EQ(kSsrc1, send_ssrc); 2017 } 2018 2019 // Test that the local SSRC is the same on sending and receiving channels if the 2020 // receive channel is created before the send channel. 2021 TEST_F(WebRtcVoiceEngineTestFake, SetSendSsrcAfterCreatingReceiveChannel) { 2022 EXPECT_TRUE(engine_.Init(talk_base::Thread::Current())); 2023 channel_ = engine_.CreateChannel(); 2024 EXPECT_TRUE(channel_->SetOptions(options_conference_)); 2025 2026 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1))); 2027 int receive_channel_num = voe_.GetLastChannel(); 2028 EXPECT_TRUE(channel_->AddSendStream( 2029 cricket::StreamParams::CreateLegacy(1234))); 2030 int send_channel_num = voe_.GetLastChannel(); 2031 2032 unsigned int ssrc = 0; 2033 EXPECT_EQ(0, voe_.GetLocalSSRC(send_channel_num, ssrc)); 2034 EXPECT_EQ(1234U, ssrc); 2035 ssrc = 0; 2036 EXPECT_EQ(0, voe_.GetLocalSSRC(receive_channel_num, ssrc)); 2037 EXPECT_EQ(1234U, ssrc); 2038 } 2039 2040 // Test that we can properly receive packets. 2041 TEST_F(WebRtcVoiceEngineTestFake, Recv) { 2042 EXPECT_TRUE(SetupEngine()); 2043 int channel_num = voe_.GetLastChannel(); 2044 DeliverPacket(kPcmuFrame, sizeof(kPcmuFrame)); 2045 EXPECT_TRUE(voe_.CheckPacket(channel_num, kPcmuFrame, 2046 sizeof(kPcmuFrame))); 2047 } 2048 2049 // Test that we can properly receive packets on multiple streams. 2050 TEST_F(WebRtcVoiceEngineTestFake, RecvWithMultipleStreams) { 2051 EXPECT_TRUE(SetupEngine()); 2052 EXPECT_TRUE(channel_->SetOptions(options_conference_)); 2053 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1))); 2054 int channel_num1 = voe_.GetLastChannel(); 2055 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2))); 2056 int channel_num2 = voe_.GetLastChannel(); 2057 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(3))); 2058 int channel_num3 = voe_.GetLastChannel(); 2059 // Create packets with the right SSRCs. 2060 char packets[4][sizeof(kPcmuFrame)]; 2061 for (size_t i = 0; i < ARRAY_SIZE(packets); ++i) { 2062 memcpy(packets[i], kPcmuFrame, sizeof(kPcmuFrame)); 2063 talk_base::SetBE32(packets[i] + 8, static_cast<uint32>(i)); 2064 } 2065 EXPECT_TRUE(voe_.CheckNoPacket(channel_num1)); 2066 EXPECT_TRUE(voe_.CheckNoPacket(channel_num2)); 2067 EXPECT_TRUE(voe_.CheckNoPacket(channel_num3)); 2068 DeliverPacket(packets[0], sizeof(packets[0])); 2069 EXPECT_TRUE(voe_.CheckNoPacket(channel_num1)); 2070 EXPECT_TRUE(voe_.CheckNoPacket(channel_num2)); 2071 EXPECT_TRUE(voe_.CheckNoPacket(channel_num3)); 2072 DeliverPacket(packets[1], sizeof(packets[1])); 2073 EXPECT_TRUE(voe_.CheckPacket(channel_num1, packets[1], 2074 sizeof(packets[1]))); 2075 EXPECT_TRUE(voe_.CheckNoPacket(channel_num2)); 2076 EXPECT_TRUE(voe_.CheckNoPacket(channel_num3)); 2077 DeliverPacket(packets[2], sizeof(packets[2])); 2078 EXPECT_TRUE(voe_.CheckNoPacket(channel_num1)); 2079 EXPECT_TRUE(voe_.CheckPacket(channel_num2, packets[2], 2080 sizeof(packets[2]))); 2081 EXPECT_TRUE(voe_.CheckNoPacket(channel_num3)); 2082 DeliverPacket(packets[3], sizeof(packets[3])); 2083 EXPECT_TRUE(voe_.CheckNoPacket(channel_num1)); 2084 EXPECT_TRUE(voe_.CheckNoPacket(channel_num2)); 2085 EXPECT_TRUE(voe_.CheckPacket(channel_num3, packets[3], 2086 sizeof(packets[3]))); 2087 EXPECT_TRUE(channel_->RemoveRecvStream(3)); 2088 EXPECT_TRUE(channel_->RemoveRecvStream(2)); 2089 EXPECT_TRUE(channel_->RemoveRecvStream(1)); 2090 } 2091 2092 // Test that we properly handle failures to add a stream. 2093 TEST_F(WebRtcVoiceEngineTestFake, AddStreamFail) { 2094 EXPECT_TRUE(SetupEngine()); 2095 voe_.set_fail_create_channel(true); 2096 EXPECT_TRUE(channel_->SetOptions(options_conference_)); 2097 EXPECT_FALSE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2))); 2098 2099 // In 1:1 call, we should not try to create a new channel. 2100 cricket::AudioOptions options_no_conference_; 2101 options_no_conference_.conference_mode.Set(false); 2102 EXPECT_TRUE(channel_->SetOptions(options_no_conference_)); 2103 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2))); 2104 } 2105 2106 // Test that AddRecvStream doesn't create new channel for 1:1 call. 2107 TEST_F(WebRtcVoiceEngineTestFake, AddRecvStream1On1) { 2108 EXPECT_TRUE(SetupEngine()); 2109 int channel_num = voe_.GetLastChannel(); 2110 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1))); 2111 EXPECT_EQ(channel_num, voe_.GetLastChannel()); 2112 } 2113 2114 // Test that after adding a recv stream, we do not decode more codecs than 2115 // those previously passed into SetRecvCodecs. 2116 TEST_F(WebRtcVoiceEngineTestFake, AddRecvStreamUnsupportedCodec) { 2117 EXPECT_TRUE(SetupEngine()); 2118 EXPECT_TRUE(channel_->SetOptions(options_conference_)); 2119 std::vector<cricket::AudioCodec> codecs; 2120 codecs.push_back(kIsacCodec); 2121 codecs.push_back(kPcmuCodec); 2122 EXPECT_TRUE(channel_->SetRecvCodecs(codecs)); 2123 EXPECT_TRUE(channel_->AddRecvStream( 2124 cricket::StreamParams::CreateLegacy(kSsrc1))); 2125 int channel_num2 = voe_.GetLastChannel(); 2126 webrtc::CodecInst gcodec; 2127 talk_base::strcpyn(gcodec.plname, ARRAY_SIZE(gcodec.plname), "CELT"); 2128 gcodec.plfreq = 32000; 2129 gcodec.channels = 2; 2130 EXPECT_EQ(-1, voe_.GetRecPayloadType(channel_num2, gcodec)); 2131 } 2132 2133 // Test that we properly clean up any streams that were added, even if 2134 // not explicitly removed. 2135 TEST_F(WebRtcVoiceEngineTestFake, StreamCleanup) { 2136 EXPECT_TRUE(SetupEngine()); 2137 EXPECT_TRUE(channel_->SetOptions(options_conference_)); 2138 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1))); 2139 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2))); 2140 EXPECT_EQ(3, voe_.GetNumChannels()); // default channel + 2 added 2141 delete channel_; 2142 channel_ = NULL; 2143 EXPECT_EQ(0, voe_.GetNumChannels()); 2144 } 2145 2146 TEST_F(WebRtcVoiceEngineTestFake, TestAddRecvStreamFailWithZeroSsrc) { 2147 EXPECT_TRUE(SetupEngine()); 2148 EXPECT_FALSE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(0))); 2149 } 2150 2151 TEST_F(WebRtcVoiceEngineTestFake, TestNoLeakingWhenAddRecvStreamFail) { 2152 EXPECT_TRUE(SetupEngine()); 2153 // Stream 1 reuses default channel. 2154 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1))); 2155 // Manually delete default channel to simulate a failure. 2156 int default_channel = voe_.GetLastChannel(); 2157 EXPECT_EQ(0, voe_.DeleteChannel(default_channel)); 2158 // Add recv stream 2 should fail because default channel is gone. 2159 EXPECT_FALSE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2))); 2160 int new_channel = voe_.GetLastChannel(); 2161 EXPECT_NE(default_channel, new_channel); 2162 // The last created channel should have already been deleted. 2163 EXPECT_EQ(-1, voe_.DeleteChannel(new_channel)); 2164 } 2165 2166 // Test the InsertDtmf on default send stream as caller. 2167 TEST_F(WebRtcVoiceEngineTestFake, InsertDtmfOnDefaultSendStreamAsCaller) { 2168 TestInsertDtmf(0, true); 2169 } 2170 2171 // Test the InsertDtmf on default send stream as callee 2172 TEST_F(WebRtcVoiceEngineTestFake, InsertDtmfOnDefaultSendStreamAsCallee) { 2173 TestInsertDtmf(0, false); 2174 } 2175 2176 // Test the InsertDtmf on specified send stream as caller. 2177 TEST_F(WebRtcVoiceEngineTestFake, InsertDtmfOnSendStreamAsCaller) { 2178 TestInsertDtmf(kSsrc1, true); 2179 } 2180 2181 // Test the InsertDtmf on specified send stream as callee. 2182 TEST_F(WebRtcVoiceEngineTestFake, InsertDtmfOnSendStreamAsCallee) { 2183 TestInsertDtmf(kSsrc1, false); 2184 } 2185 2186 // Test that we can play a ringback tone properly in a single-stream call. 2187 TEST_F(WebRtcVoiceEngineTestFake, PlayRingback) { 2188 EXPECT_TRUE(SetupEngine()); 2189 int channel_num = voe_.GetLastChannel(); 2190 EXPECT_EQ(0, voe_.IsPlayingFileLocally(channel_num)); 2191 // Check we fail if no ringback tone specified. 2192 EXPECT_FALSE(channel_->PlayRingbackTone(0, true, true)); 2193 EXPECT_EQ(0, voe_.IsPlayingFileLocally(channel_num)); 2194 // Check we can set and play a ringback tone. 2195 EXPECT_TRUE(channel_->SetRingbackTone( 2196 kRingbackTone, static_cast<int>(strlen(kRingbackTone)))); 2197 EXPECT_TRUE(channel_->PlayRingbackTone(0, true, true)); 2198 EXPECT_EQ(1, voe_.IsPlayingFileLocally(channel_num)); 2199 // Check we can stop the tone manually. 2200 EXPECT_TRUE(channel_->PlayRingbackTone(0, false, false)); 2201 EXPECT_EQ(0, voe_.IsPlayingFileLocally(channel_num)); 2202 // Check we stop the tone if a packet arrives. 2203 EXPECT_TRUE(channel_->PlayRingbackTone(0, true, true)); 2204 EXPECT_EQ(1, voe_.IsPlayingFileLocally(channel_num)); 2205 DeliverPacket(kPcmuFrame, sizeof(kPcmuFrame)); 2206 EXPECT_EQ(0, voe_.IsPlayingFileLocally(channel_num)); 2207 } 2208 2209 // Test that we can play a ringback tone properly in a multi-stream call. 2210 TEST_F(WebRtcVoiceEngineTestFake, PlayRingbackWithMultipleStreams) { 2211 EXPECT_TRUE(SetupEngine()); 2212 EXPECT_TRUE(channel_->SetOptions(options_conference_)); 2213 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1))); 2214 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2))); 2215 int channel_num = voe_.GetLastChannel(); 2216 EXPECT_EQ(0, voe_.IsPlayingFileLocally(channel_num)); 2217 // Check we fail if no ringback tone specified. 2218 EXPECT_FALSE(channel_->PlayRingbackTone(2, true, true)); 2219 EXPECT_EQ(0, voe_.IsPlayingFileLocally(channel_num)); 2220 // Check we can set and play a ringback tone on the correct ssrc. 2221 EXPECT_TRUE(channel_->SetRingbackTone( 2222 kRingbackTone, static_cast<int>(strlen(kRingbackTone)))); 2223 EXPECT_FALSE(channel_->PlayRingbackTone(77, true, true)); 2224 EXPECT_TRUE(channel_->PlayRingbackTone(2, true, true)); 2225 EXPECT_EQ(1, voe_.IsPlayingFileLocally(channel_num)); 2226 // Check we can stop the tone manually. 2227 EXPECT_TRUE(channel_->PlayRingbackTone(2, false, false)); 2228 EXPECT_EQ(0, voe_.IsPlayingFileLocally(channel_num)); 2229 // Check we stop the tone if a packet arrives, but only with the right SSRC. 2230 EXPECT_TRUE(channel_->PlayRingbackTone(2, true, true)); 2231 EXPECT_EQ(1, voe_.IsPlayingFileLocally(channel_num)); 2232 // Send a packet with SSRC 1; the tone should not stop. 2233 DeliverPacket(kPcmuFrame, sizeof(kPcmuFrame)); 2234 EXPECT_EQ(1, voe_.IsPlayingFileLocally(channel_num)); 2235 // Send a packet with SSRC 2; the tone should stop. 2236 char packet[sizeof(kPcmuFrame)]; 2237 memcpy(packet, kPcmuFrame, sizeof(kPcmuFrame)); 2238 talk_base::SetBE32(packet + 8, 2); 2239 DeliverPacket(packet, sizeof(packet)); 2240 EXPECT_EQ(0, voe_.IsPlayingFileLocally(channel_num)); 2241 } 2242 2243 // Tests creating soundclips, and make sure they come from the right engine. 2244 TEST_F(WebRtcVoiceEngineTestFake, CreateSoundclip) { 2245 EXPECT_TRUE(engine_.Init(talk_base::Thread::Current())); 2246 EXPECT_FALSE(voe_sc_.IsInited()); 2247 soundclip_ = engine_.CreateSoundclip(); 2248 EXPECT_TRUE(voe_sc_.IsInited()); 2249 ASSERT_TRUE(soundclip_ != NULL); 2250 EXPECT_EQ(0, voe_.GetNumChannels()); 2251 EXPECT_EQ(1, voe_sc_.GetNumChannels()); 2252 int channel_num = voe_sc_.GetLastChannel(); 2253 EXPECT_TRUE(voe_sc_.GetPlayout(channel_num)); 2254 delete soundclip_; 2255 soundclip_ = NULL; 2256 EXPECT_EQ(0, voe_sc_.GetNumChannels()); 2257 // Make sure the soundclip engine is uninitialized on shutdown, now that 2258 // we've initialized it by creating a soundclip. 2259 engine_.Terminate(); 2260 EXPECT_FALSE(voe_sc_.IsInited()); 2261 } 2262 2263 // Tests playing out a fake sound. 2264 TEST_F(WebRtcVoiceEngineTestFake, PlaySoundclip) { 2265 static const char kZeroes[16000] = {}; 2266 EXPECT_TRUE(engine_.Init(talk_base::Thread::Current())); 2267 soundclip_ = engine_.CreateSoundclip(); 2268 ASSERT_TRUE(soundclip_ != NULL); 2269 EXPECT_TRUE(soundclip_->PlaySound(kZeroes, sizeof(kZeroes), 0)); 2270 } 2271 2272 TEST_F(WebRtcVoiceEngineTestFake, MediaEngineCallbackOnError) { 2273 talk_base::scoped_ptr<ChannelErrorListener> listener; 2274 cricket::WebRtcVoiceMediaChannel* media_channel; 2275 unsigned int ssrc = 0; 2276 2277 EXPECT_TRUE(SetupEngine()); 2278 EXPECT_TRUE(channel_->SetOptions(options_conference_)); 2279 EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE)); 2280 2281 media_channel = static_cast<cricket::WebRtcVoiceMediaChannel*>(channel_); 2282 listener.reset(new ChannelErrorListener(channel_)); 2283 2284 // Test on WebRtc VoE channel. 2285 voe_.TriggerCallbackOnError(media_channel->voe_channel(), 2286 VE_SATURATION_WARNING); 2287 EXPECT_EQ(cricket::VoiceMediaChannel::ERROR_REC_DEVICE_SATURATION, 2288 listener->error()); 2289 EXPECT_NE(-1, voe_.GetLocalSSRC(voe_.GetLastChannel(), ssrc)); 2290 EXPECT_EQ(ssrc, listener->ssrc()); 2291 2292 listener->Reset(); 2293 voe_.TriggerCallbackOnError(-1, VE_TYPING_NOISE_WARNING); 2294 EXPECT_EQ(cricket::VoiceMediaChannel::ERROR_REC_TYPING_NOISE_DETECTED, 2295 listener->error()); 2296 EXPECT_EQ(0U, listener->ssrc()); 2297 2298 // Add another stream and test on that. 2299 ++ssrc; 2300 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy( 2301 ssrc))); 2302 listener->Reset(); 2303 voe_.TriggerCallbackOnError(voe_.GetLastChannel(), 2304 VE_SATURATION_WARNING); 2305 EXPECT_EQ(cricket::VoiceMediaChannel::ERROR_REC_DEVICE_SATURATION, 2306 listener->error()); 2307 EXPECT_EQ(ssrc, listener->ssrc()); 2308 2309 // Testing a non-existing channel. 2310 listener->Reset(); 2311 voe_.TriggerCallbackOnError(voe_.GetLastChannel() + 2, 2312 VE_SATURATION_WARNING); 2313 EXPECT_EQ(0, listener->error()); 2314 } 2315 2316 TEST_F(WebRtcVoiceEngineTestFake, TestSetPlayoutError) { 2317 EXPECT_TRUE(SetupEngine()); 2318 EXPECT_TRUE(channel_->SetOptions(options_conference_)); 2319 std::vector<cricket::AudioCodec> codecs; 2320 codecs.push_back(kPcmuCodec); 2321 EXPECT_TRUE(channel_->SetSendCodecs(codecs)); 2322 EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE)); 2323 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2))); 2324 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(3))); 2325 EXPECT_TRUE(channel_->SetPlayout(true)); 2326 voe_.set_playout_fail_channel(voe_.GetLastChannel() - 1); 2327 EXPECT_TRUE(channel_->SetPlayout(false)); 2328 EXPECT_FALSE(channel_->SetPlayout(true)); 2329 } 2330 2331 // Test that the Registering/Unregistering with the 2332 // webrtcvoiceengine works as expected 2333 TEST_F(WebRtcVoiceEngineTestFake, RegisterVoiceProcessor) { 2334 EXPECT_TRUE(SetupEngine()); 2335 EXPECT_TRUE(channel_->SetOptions(options_conference_)); 2336 EXPECT_TRUE(channel_->AddRecvStream( 2337 cricket::StreamParams::CreateLegacy(kSsrc2))); 2338 cricket::FakeMediaProcessor vp_1; 2339 cricket::FakeMediaProcessor vp_2; 2340 2341 EXPECT_FALSE(engine_.RegisterProcessor(kSsrc2, &vp_1, cricket::MPD_TX)); 2342 EXPECT_TRUE(engine_.RegisterProcessor(kSsrc2, &vp_1, cricket::MPD_RX)); 2343 EXPECT_TRUE(engine_.RegisterProcessor(kSsrc2, &vp_2, cricket::MPD_RX)); 2344 voe_.TriggerProcessPacket(cricket::MPD_RX); 2345 voe_.TriggerProcessPacket(cricket::MPD_TX); 2346 2347 EXPECT_TRUE(voe_.IsExternalMediaProcessorRegistered()); 2348 EXPECT_EQ(1, vp_1.voice_frame_count()); 2349 EXPECT_EQ(1, vp_2.voice_frame_count()); 2350 2351 EXPECT_TRUE(engine_.UnregisterProcessor(kSsrc2, 2352 &vp_2, 2353 cricket::MPD_RX)); 2354 voe_.TriggerProcessPacket(cricket::MPD_RX); 2355 EXPECT_TRUE(voe_.IsExternalMediaProcessorRegistered()); 2356 EXPECT_EQ(1, vp_2.voice_frame_count()); 2357 EXPECT_EQ(2, vp_1.voice_frame_count()); 2358 2359 EXPECT_TRUE(engine_.UnregisterProcessor(kSsrc2, 2360 &vp_1, 2361 cricket::MPD_RX)); 2362 voe_.TriggerProcessPacket(cricket::MPD_RX); 2363 EXPECT_FALSE(voe_.IsExternalMediaProcessorRegistered()); 2364 EXPECT_EQ(2, vp_1.voice_frame_count()); 2365 2366 EXPECT_FALSE(engine_.RegisterProcessor(kSsrc1, &vp_1, cricket::MPD_RX)); 2367 EXPECT_TRUE(engine_.RegisterProcessor(kSsrc1, &vp_1, cricket::MPD_TX)); 2368 voe_.TriggerProcessPacket(cricket::MPD_RX); 2369 voe_.TriggerProcessPacket(cricket::MPD_TX); 2370 EXPECT_TRUE(voe_.IsExternalMediaProcessorRegistered()); 2371 EXPECT_EQ(3, vp_1.voice_frame_count()); 2372 2373 EXPECT_TRUE(engine_.UnregisterProcessor(kSsrc1, 2374 &vp_1, 2375 cricket::MPD_RX_AND_TX)); 2376 voe_.TriggerProcessPacket(cricket::MPD_TX); 2377 EXPECT_FALSE(voe_.IsExternalMediaProcessorRegistered()); 2378 EXPECT_EQ(3, vp_1.voice_frame_count()); 2379 EXPECT_TRUE(channel_->RemoveRecvStream(kSsrc2)); 2380 EXPECT_FALSE(engine_.RegisterProcessor(kSsrc2, &vp_1, cricket::MPD_RX)); 2381 EXPECT_FALSE(voe_.IsExternalMediaProcessorRegistered()); 2382 2383 // Test that we can register a processor on the receive channel on SSRC 0. 2384 // This tests the 1:1 case when the receive SSRC is unknown. 2385 EXPECT_TRUE(engine_.RegisterProcessor(0, &vp_1, cricket::MPD_RX)); 2386 voe_.TriggerProcessPacket(cricket::MPD_RX); 2387 EXPECT_TRUE(voe_.IsExternalMediaProcessorRegistered()); 2388 EXPECT_EQ(4, vp_1.voice_frame_count()); 2389 EXPECT_TRUE(engine_.UnregisterProcessor(0, 2390 &vp_1, 2391 cricket::MPD_RX)); 2392 2393 // The following tests test that FindChannelNumFromSsrc is doing 2394 // what we expect. 2395 // pick an invalid ssrc and make sure we can't register 2396 EXPECT_FALSE(engine_.RegisterProcessor(99, 2397 &vp_1, 2398 cricket::MPD_RX)); 2399 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1))); 2400 EXPECT_TRUE(engine_.RegisterProcessor(1, 2401 &vp_1, 2402 cricket::MPD_RX)); 2403 EXPECT_TRUE(engine_.UnregisterProcessor(1, 2404 &vp_1, 2405 cricket::MPD_RX)); 2406 EXPECT_FALSE(engine_.RegisterProcessor(1, 2407 &vp_1, 2408 cricket::MPD_TX)); 2409 EXPECT_TRUE(channel_->RemoveRecvStream(1)); 2410 } 2411 2412 TEST_F(WebRtcVoiceEngineTestFake, SetAudioOptions) { 2413 EXPECT_TRUE(SetupEngine()); 2414 2415 bool ec_enabled; 2416 webrtc::EcModes ec_mode; 2417 bool ec_metrics_enabled; 2418 webrtc::AecmModes aecm_mode; 2419 bool cng_enabled; 2420 bool agc_enabled; 2421 webrtc::AgcModes agc_mode; 2422 webrtc::AgcConfig agc_config; 2423 bool ns_enabled; 2424 webrtc::NsModes ns_mode; 2425 bool highpass_filter_enabled; 2426 bool stereo_swapping_enabled; 2427 bool typing_detection_enabled; 2428 voe_.GetEcStatus(ec_enabled, ec_mode); 2429 voe_.GetEcMetricsStatus(ec_metrics_enabled); 2430 voe_.GetAecmMode(aecm_mode, cng_enabled); 2431 voe_.GetAgcStatus(agc_enabled, agc_mode); 2432 voe_.GetAgcConfig(agc_config); 2433 voe_.GetNsStatus(ns_enabled, ns_mode); 2434 highpass_filter_enabled = voe_.IsHighPassFilterEnabled(); 2435 stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled(); 2436 voe_.GetTypingDetectionStatus(typing_detection_enabled); 2437 EXPECT_TRUE(ec_enabled); 2438 EXPECT_TRUE(ec_metrics_enabled); 2439 EXPECT_FALSE(cng_enabled); 2440 EXPECT_TRUE(agc_enabled); 2441 EXPECT_EQ(0, agc_config.targetLeveldBOv); 2442 EXPECT_TRUE(ns_enabled); 2443 EXPECT_TRUE(highpass_filter_enabled); 2444 EXPECT_FALSE(stereo_swapping_enabled); 2445 EXPECT_TRUE(typing_detection_enabled); 2446 EXPECT_EQ(ec_mode, webrtc::kEcConference); 2447 EXPECT_EQ(ns_mode, webrtc::kNsHighSuppression); 2448 2449 // Nothing set, so all ignored. 2450 cricket::AudioOptions options; 2451 ASSERT_TRUE(engine_.SetOptions(options)); 2452 voe_.GetEcStatus(ec_enabled, ec_mode); 2453 voe_.GetEcMetricsStatus(ec_metrics_enabled); 2454 voe_.GetAecmMode(aecm_mode, cng_enabled); 2455 voe_.GetAgcStatus(agc_enabled, agc_mode); 2456 voe_.GetAgcConfig(agc_config); 2457 voe_.GetNsStatus(ns_enabled, ns_mode); 2458 highpass_filter_enabled = voe_.IsHighPassFilterEnabled(); 2459 stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled(); 2460 voe_.GetTypingDetectionStatus(typing_detection_enabled); 2461 EXPECT_TRUE(ec_enabled); 2462 EXPECT_TRUE(ec_metrics_enabled); 2463 EXPECT_FALSE(cng_enabled); 2464 EXPECT_TRUE(agc_enabled); 2465 EXPECT_EQ(0, agc_config.targetLeveldBOv); 2466 EXPECT_TRUE(ns_enabled); 2467 EXPECT_TRUE(highpass_filter_enabled); 2468 EXPECT_FALSE(stereo_swapping_enabled); 2469 EXPECT_TRUE(typing_detection_enabled); 2470 EXPECT_EQ(ec_mode, webrtc::kEcConference); 2471 EXPECT_EQ(ns_mode, webrtc::kNsHighSuppression); 2472 2473 // Turn echo cancellation off 2474 options.echo_cancellation.Set(false); 2475 ASSERT_TRUE(engine_.SetOptions(options)); 2476 voe_.GetEcStatus(ec_enabled, ec_mode); 2477 EXPECT_FALSE(ec_enabled); 2478 2479 // Turn echo cancellation back on, with settings, and make sure 2480 // nothing else changed. 2481 options.echo_cancellation.Set(true); 2482 ASSERT_TRUE(engine_.SetOptions(options)); 2483 voe_.GetEcStatus(ec_enabled, ec_mode); 2484 voe_.GetEcMetricsStatus(ec_metrics_enabled); 2485 voe_.GetAecmMode(aecm_mode, cng_enabled); 2486 voe_.GetAgcStatus(agc_enabled, agc_mode); 2487 voe_.GetAgcConfig(agc_config); 2488 voe_.GetNsStatus(ns_enabled, ns_mode); 2489 highpass_filter_enabled = voe_.IsHighPassFilterEnabled(); 2490 stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled(); 2491 voe_.GetTypingDetectionStatus(typing_detection_enabled); 2492 EXPECT_TRUE(ec_enabled); 2493 EXPECT_TRUE(ec_metrics_enabled); 2494 EXPECT_TRUE(agc_enabled); 2495 EXPECT_EQ(0, agc_config.targetLeveldBOv); 2496 EXPECT_TRUE(ns_enabled); 2497 EXPECT_TRUE(highpass_filter_enabled); 2498 EXPECT_FALSE(stereo_swapping_enabled); 2499 EXPECT_TRUE(typing_detection_enabled); 2500 EXPECT_EQ(ec_mode, webrtc::kEcConference); 2501 EXPECT_EQ(ns_mode, webrtc::kNsHighSuppression); 2502 2503 // Turn off AGC 2504 options.auto_gain_control.Set(false); 2505 ASSERT_TRUE(engine_.SetOptions(options)); 2506 voe_.GetAgcStatus(agc_enabled, agc_mode); 2507 EXPECT_FALSE(agc_enabled); 2508 2509 // Turn AGC back on 2510 options.auto_gain_control.Set(true); 2511 options.adjust_agc_delta.Clear(); 2512 ASSERT_TRUE(engine_.SetOptions(options)); 2513 voe_.GetAgcStatus(agc_enabled, agc_mode); 2514 EXPECT_TRUE(agc_enabled); 2515 voe_.GetAgcConfig(agc_config); 2516 EXPECT_EQ(0, agc_config.targetLeveldBOv); 2517 2518 // Turn off other options (and stereo swapping on). 2519 options.noise_suppression.Set(false); 2520 options.highpass_filter.Set(false); 2521 options.typing_detection.Set(false); 2522 options.stereo_swapping.Set(true); 2523 ASSERT_TRUE(engine_.SetOptions(options)); 2524 voe_.GetNsStatus(ns_enabled, ns_mode); 2525 highpass_filter_enabled = voe_.IsHighPassFilterEnabled(); 2526 stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled(); 2527 voe_.GetTypingDetectionStatus(typing_detection_enabled); 2528 EXPECT_FALSE(ns_enabled); 2529 EXPECT_FALSE(highpass_filter_enabled); 2530 EXPECT_FALSE(typing_detection_enabled); 2531 EXPECT_TRUE(stereo_swapping_enabled); 2532 2533 // Turn on "conference mode" to ensure it has no impact. 2534 options.conference_mode.Set(true); 2535 ASSERT_TRUE(engine_.SetOptions(options)); 2536 voe_.GetEcStatus(ec_enabled, ec_mode); 2537 voe_.GetNsStatus(ns_enabled, ns_mode); 2538 EXPECT_TRUE(ec_enabled); 2539 EXPECT_EQ(webrtc::kEcConference, ec_mode); 2540 EXPECT_FALSE(ns_enabled); 2541 EXPECT_EQ(webrtc::kNsHighSuppression, ns_mode); 2542 } 2543 2544 TEST_F(WebRtcVoiceEngineTestFake, DefaultOptions) { 2545 EXPECT_TRUE(SetupEngine()); 2546 2547 bool ec_enabled; 2548 webrtc::EcModes ec_mode; 2549 bool ec_metrics_enabled; 2550 bool agc_enabled; 2551 webrtc::AgcModes agc_mode; 2552 bool ns_enabled; 2553 webrtc::NsModes ns_mode; 2554 bool highpass_filter_enabled; 2555 bool stereo_swapping_enabled; 2556 bool typing_detection_enabled; 2557 2558 voe_.GetEcStatus(ec_enabled, ec_mode); 2559 voe_.GetEcMetricsStatus(ec_metrics_enabled); 2560 voe_.GetAgcStatus(agc_enabled, agc_mode); 2561 voe_.GetNsStatus(ns_enabled, ns_mode); 2562 highpass_filter_enabled = voe_.IsHighPassFilterEnabled(); 2563 stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled(); 2564 voe_.GetTypingDetectionStatus(typing_detection_enabled); 2565 EXPECT_TRUE(ec_enabled); 2566 EXPECT_TRUE(agc_enabled); 2567 EXPECT_TRUE(ns_enabled); 2568 EXPECT_TRUE(highpass_filter_enabled); 2569 EXPECT_TRUE(typing_detection_enabled); 2570 EXPECT_FALSE(stereo_swapping_enabled); 2571 } 2572 2573 TEST_F(WebRtcVoiceEngineTestFake, InitDoesNotOverwriteDefaultAgcConfig) { 2574 webrtc::AgcConfig set_config = {0}; 2575 set_config.targetLeveldBOv = 3; 2576 set_config.digitalCompressionGaindB = 9; 2577 set_config.limiterEnable = true; 2578 EXPECT_EQ(0, voe_.SetAgcConfig(set_config)); 2579 EXPECT_TRUE(engine_.Init(talk_base::Thread::Current())); 2580 2581 webrtc::AgcConfig config = {0}; 2582 EXPECT_EQ(0, voe_.GetAgcConfig(config)); 2583 EXPECT_EQ(set_config.targetLeveldBOv, config.targetLeveldBOv); 2584 EXPECT_EQ(set_config.digitalCompressionGaindB, 2585 config.digitalCompressionGaindB); 2586 EXPECT_EQ(set_config.limiterEnable, config.limiterEnable); 2587 } 2588 2589 2590 TEST_F(WebRtcVoiceEngineTestFake, SetOptionOverridesViaChannels) { 2591 EXPECT_TRUE(SetupEngine()); 2592 talk_base::scoped_ptr<cricket::VoiceMediaChannel> channel1( 2593 engine_.CreateChannel()); 2594 talk_base::scoped_ptr<cricket::VoiceMediaChannel> channel2( 2595 engine_.CreateChannel()); 2596 2597 // Have to add a stream to make SetSend work. 2598 cricket::StreamParams stream1; 2599 stream1.ssrcs.push_back(1); 2600 channel1->AddSendStream(stream1); 2601 cricket::StreamParams stream2; 2602 stream2.ssrcs.push_back(2); 2603 channel2->AddSendStream(stream2); 2604 2605 // AEC and AGC and NS 2606 cricket::AudioOptions options_all; 2607 options_all.echo_cancellation.Set(true); 2608 options_all.auto_gain_control.Set(true); 2609 options_all.noise_suppression.Set(true); 2610 2611 ASSERT_TRUE(channel1->SetOptions(options_all)); 2612 cricket::AudioOptions expected_options = options_all; 2613 cricket::AudioOptions actual_options; 2614 ASSERT_TRUE(channel1->GetOptions(&actual_options)); 2615 EXPECT_EQ(expected_options, actual_options); 2616 ASSERT_TRUE(channel2->SetOptions(options_all)); 2617 ASSERT_TRUE(channel2->GetOptions(&actual_options)); 2618 EXPECT_EQ(expected_options, actual_options); 2619 2620 // unset NS 2621 cricket::AudioOptions options_no_ns; 2622 options_no_ns.noise_suppression.Set(false); 2623 ASSERT_TRUE(channel1->SetOptions(options_no_ns)); 2624 2625 expected_options.echo_cancellation.Set(true); 2626 expected_options.auto_gain_control.Set(true); 2627 expected_options.noise_suppression.Set(false); 2628 ASSERT_TRUE(channel1->GetOptions(&actual_options)); 2629 EXPECT_EQ(expected_options, actual_options); 2630 2631 // unset AGC 2632 cricket::AudioOptions options_no_agc; 2633 options_no_agc.auto_gain_control.Set(false); 2634 ASSERT_TRUE(channel2->SetOptions(options_no_agc)); 2635 2636 expected_options.echo_cancellation.Set(true); 2637 expected_options.auto_gain_control.Set(false); 2638 expected_options.noise_suppression.Set(true); 2639 ASSERT_TRUE(channel2->GetOptions(&actual_options)); 2640 EXPECT_EQ(expected_options, actual_options); 2641 2642 ASSERT_TRUE(engine_.SetOptions(options_all)); 2643 bool ec_enabled; 2644 webrtc::EcModes ec_mode; 2645 bool agc_enabled; 2646 webrtc::AgcModes agc_mode; 2647 bool ns_enabled; 2648 webrtc::NsModes ns_mode; 2649 voe_.GetEcStatus(ec_enabled, ec_mode); 2650 voe_.GetAgcStatus(agc_enabled, agc_mode); 2651 voe_.GetNsStatus(ns_enabled, ns_mode); 2652 EXPECT_TRUE(ec_enabled); 2653 EXPECT_TRUE(agc_enabled); 2654 EXPECT_TRUE(ns_enabled); 2655 2656 channel1->SetSend(cricket::SEND_MICROPHONE); 2657 voe_.GetEcStatus(ec_enabled, ec_mode); 2658 voe_.GetAgcStatus(agc_enabled, agc_mode); 2659 voe_.GetNsStatus(ns_enabled, ns_mode); 2660 EXPECT_TRUE(ec_enabled); 2661 EXPECT_TRUE(agc_enabled); 2662 EXPECT_FALSE(ns_enabled); 2663 2664 channel1->SetSend(cricket::SEND_NOTHING); 2665 voe_.GetEcStatus(ec_enabled, ec_mode); 2666 voe_.GetAgcStatus(agc_enabled, agc_mode); 2667 voe_.GetNsStatus(ns_enabled, ns_mode); 2668 EXPECT_TRUE(ec_enabled); 2669 EXPECT_TRUE(agc_enabled); 2670 EXPECT_TRUE(ns_enabled); 2671 2672 channel2->SetSend(cricket::SEND_MICROPHONE); 2673 voe_.GetEcStatus(ec_enabled, ec_mode); 2674 voe_.GetAgcStatus(agc_enabled, agc_mode); 2675 voe_.GetNsStatus(ns_enabled, ns_mode); 2676 EXPECT_TRUE(ec_enabled); 2677 EXPECT_FALSE(agc_enabled); 2678 EXPECT_TRUE(ns_enabled); 2679 2680 channel2->SetSend(cricket::SEND_NOTHING); 2681 voe_.GetEcStatus(ec_enabled, ec_mode); 2682 voe_.GetAgcStatus(agc_enabled, agc_mode); 2683 voe_.GetNsStatus(ns_enabled, ns_mode); 2684 EXPECT_TRUE(ec_enabled); 2685 EXPECT_TRUE(agc_enabled); 2686 EXPECT_TRUE(ns_enabled); 2687 2688 // Make sure settings take effect while we are sending. 2689 ASSERT_TRUE(engine_.SetOptions(options_all)); 2690 cricket::AudioOptions options_no_agc_nor_ns; 2691 options_no_agc_nor_ns.auto_gain_control.Set(false); 2692 options_no_agc_nor_ns.noise_suppression.Set(false); 2693 channel2->SetSend(cricket::SEND_MICROPHONE); 2694 channel2->SetOptions(options_no_agc_nor_ns); 2695 2696 expected_options.echo_cancellation.Set(true); 2697 expected_options.auto_gain_control.Set(false); 2698 expected_options.noise_suppression.Set(false); 2699 ASSERT_TRUE(channel2->GetOptions(&actual_options)); 2700 EXPECT_EQ(expected_options, actual_options); 2701 voe_.GetEcStatus(ec_enabled, ec_mode); 2702 voe_.GetAgcStatus(agc_enabled, agc_mode); 2703 voe_.GetNsStatus(ns_enabled, ns_mode); 2704 EXPECT_TRUE(ec_enabled); 2705 EXPECT_FALSE(agc_enabled); 2706 EXPECT_FALSE(ns_enabled); 2707 } 2708 2709 // This test verifies DSCP settings are properly applied on voice media channel. 2710 TEST_F(WebRtcVoiceEngineTestFake, TestSetDscpOptions) { 2711 EXPECT_TRUE(SetupEngine()); 2712 talk_base::scoped_ptr<cricket::VoiceMediaChannel> channel( 2713 engine_.CreateChannel()); 2714 talk_base::scoped_ptr<cricket::FakeNetworkInterface> network_interface( 2715 new cricket::FakeNetworkInterface); 2716 channel->SetInterface(network_interface.get()); 2717 cricket::AudioOptions options; 2718 options.dscp.Set(true); 2719 EXPECT_TRUE(channel->SetOptions(options)); 2720 EXPECT_EQ(talk_base::DSCP_EF, network_interface->dscp()); 2721 options.dscp.Set(false); 2722 EXPECT_TRUE(channel->SetOptions(options)); 2723 EXPECT_EQ(talk_base::DSCP_DEFAULT, network_interface->dscp()); 2724 } 2725 2726 TEST(WebRtcVoiceEngineTest, TestDefaultOptionsBeforeInit) { 2727 cricket::WebRtcVoiceEngine engine; 2728 cricket::AudioOptions options = engine.GetOptions(); 2729 // The default options should have at least a few things set. We purposefully 2730 // don't check the option values here, though. 2731 EXPECT_TRUE(options.echo_cancellation.IsSet()); 2732 EXPECT_TRUE(options.auto_gain_control.IsSet()); 2733 EXPECT_TRUE(options.noise_suppression.IsSet()); 2734 } 2735 2736 // Test that GetReceiveChannelNum returns the default channel for the first 2737 // recv stream in 1-1 calls. 2738 TEST_F(WebRtcVoiceEngineTestFake, TestGetReceiveChannelNumIn1To1Calls) { 2739 EXPECT_TRUE(SetupEngine()); 2740 cricket::WebRtcVoiceMediaChannel* media_channel = 2741 static_cast<cricket::WebRtcVoiceMediaChannel*>(channel_); 2742 // Test that GetChannelNum returns the default channel if the SSRC is unknown. 2743 EXPECT_EQ(media_channel->voe_channel(), 2744 media_channel->GetReceiveChannelNum(0)); 2745 cricket::StreamParams stream; 2746 stream.ssrcs.push_back(kSsrc2); 2747 EXPECT_TRUE(channel_->AddRecvStream(stream)); 2748 EXPECT_EQ(media_channel->voe_channel(), 2749 media_channel->GetReceiveChannelNum(kSsrc2)); 2750 } 2751 2752 // Test that GetReceiveChannelNum doesn't return the default channel for the 2753 // first recv stream in conference calls. 2754 TEST_F(WebRtcVoiceEngineTestFake, TestGetChannelNumInConferenceCalls) { 2755 EXPECT_TRUE(SetupEngine()); 2756 EXPECT_TRUE(channel_->SetOptions(options_conference_)); 2757 cricket::StreamParams stream; 2758 stream.ssrcs.push_back(kSsrc2); 2759 EXPECT_TRUE(channel_->AddRecvStream(stream)); 2760 cricket::WebRtcVoiceMediaChannel* media_channel = 2761 static_cast<cricket::WebRtcVoiceMediaChannel*>(channel_); 2762 EXPECT_LT(media_channel->voe_channel(), 2763 media_channel->GetReceiveChannelNum(kSsrc2)); 2764 } 2765 2766 TEST_F(WebRtcVoiceEngineTestFake, SetOutputScaling) { 2767 EXPECT_TRUE(SetupEngine()); 2768 double left, right; 2769 EXPECT_TRUE(channel_->SetOutputScaling(0, 1, 2)); 2770 EXPECT_TRUE(channel_->GetOutputScaling(0, &left, &right)); 2771 EXPECT_DOUBLE_EQ(1, left); 2772 EXPECT_DOUBLE_EQ(2, right); 2773 2774 EXPECT_FALSE(channel_->SetOutputScaling(kSsrc2, 1, 2)); 2775 cricket::StreamParams stream; 2776 stream.ssrcs.push_back(kSsrc2); 2777 EXPECT_TRUE(channel_->AddRecvStream(stream)); 2778 2779 EXPECT_TRUE(channel_->SetOutputScaling(kSsrc2, 2, 1)); 2780 EXPECT_TRUE(channel_->GetOutputScaling(kSsrc2, &left, &right)); 2781 EXPECT_DOUBLE_EQ(2, left); 2782 EXPECT_DOUBLE_EQ(1, right); 2783 } 2784 2785 2786 // Tests for the actual WebRtc VoE library. 2787 2788 // Tests that the library initializes and shuts down properly. 2789 TEST(WebRtcVoiceEngineTest, StartupShutdown) { 2790 cricket::WebRtcVoiceEngine engine; 2791 EXPECT_TRUE(engine.Init(talk_base::Thread::Current())); 2792 cricket::VoiceMediaChannel* channel = engine.CreateChannel(); 2793 EXPECT_TRUE(channel != NULL); 2794 delete channel; 2795 engine.Terminate(); 2796 2797 // Reinit to catch regression where VoiceEngineObserver reference is lost 2798 EXPECT_TRUE(engine.Init(talk_base::Thread::Current())); 2799 engine.Terminate(); 2800 } 2801 2802 // Tests that the logging from the library is cleartext. 2803 TEST(WebRtcVoiceEngineTest, DISABLED_HasUnencryptedLogging) { 2804 cricket::WebRtcVoiceEngine engine; 2805 talk_base::scoped_ptr<talk_base::MemoryStream> stream( 2806 new talk_base::MemoryStream); 2807 size_t size = 0; 2808 bool cleartext = true; 2809 talk_base::LogMessage::AddLogToStream(stream.get(), talk_base::LS_VERBOSE); 2810 engine.SetLogging(talk_base::LS_VERBOSE, ""); 2811 EXPECT_TRUE(engine.Init(talk_base::Thread::Current())); 2812 EXPECT_TRUE(stream->GetSize(&size)); 2813 EXPECT_GT(size, 0U); 2814 engine.Terminate(); 2815 talk_base::LogMessage::RemoveLogToStream(stream.get()); 2816 const char* buf = stream->GetBuffer(); 2817 for (size_t i = 0; i < size && cleartext; ++i) { 2818 int ch = static_cast<int>(buf[i]); 2819 ASSERT_GE(ch, 0) << "Out of bounds character in WebRtc VoE log: " 2820 << std::hex << ch; 2821 cleartext = (isprint(ch) || isspace(ch)); 2822 } 2823 EXPECT_TRUE(cleartext); 2824 } 2825 2826 // Tests we do not see any references to a monitor thread being spun up 2827 // when initiating the engine. 2828 TEST(WebRtcVoiceEngineTest, HasNoMonitorThread) { 2829 cricket::WebRtcVoiceEngine engine; 2830 talk_base::scoped_ptr<talk_base::MemoryStream> stream( 2831 new talk_base::MemoryStream); 2832 talk_base::LogMessage::AddLogToStream(stream.get(), talk_base::LS_VERBOSE); 2833 engine.SetLogging(talk_base::LS_VERBOSE, ""); 2834 EXPECT_TRUE(engine.Init(talk_base::Thread::Current())); 2835 engine.Terminate(); 2836 talk_base::LogMessage::RemoveLogToStream(stream.get()); 2837 2838 size_t size = 0; 2839 EXPECT_TRUE(stream->GetSize(&size)); 2840 EXPECT_GT(size, 0U); 2841 const std::string logs(stream->GetBuffer(), size); 2842 EXPECT_NE(std::string::npos, logs.find("ProcessThread")); 2843 } 2844 2845 // Tests that the library is configured with the codecs we want. 2846 TEST(WebRtcVoiceEngineTest, HasCorrectCodecs) { 2847 cricket::WebRtcVoiceEngine engine; 2848 // Check codecs by name. 2849 EXPECT_TRUE(engine.FindCodec( 2850 cricket::AudioCodec(96, "OPUS", 48000, 0, 2, 0))); 2851 EXPECT_TRUE(engine.FindCodec( 2852 cricket::AudioCodec(96, "ISAC", 16000, 0, 1, 0))); 2853 EXPECT_TRUE(engine.FindCodec( 2854 cricket::AudioCodec(96, "ISAC", 32000, 0, 1, 0))); 2855 // Check that name matching is case-insensitive. 2856 EXPECT_TRUE(engine.FindCodec( 2857 cricket::AudioCodec(96, "ILBC", 8000, 0, 1, 0))); 2858 EXPECT_TRUE(engine.FindCodec( 2859 cricket::AudioCodec(96, "iLBC", 8000, 0, 1, 0))); 2860 EXPECT_TRUE(engine.FindCodec( 2861 cricket::AudioCodec(96, "PCMU", 8000, 0, 1, 0))); 2862 EXPECT_TRUE(engine.FindCodec( 2863 cricket::AudioCodec(96, "PCMA", 8000, 0, 1, 0))); 2864 EXPECT_TRUE(engine.FindCodec( 2865 cricket::AudioCodec(96, "G722", 16000, 0, 1, 0))); 2866 EXPECT_TRUE(engine.FindCodec( 2867 cricket::AudioCodec(96, "red", 8000, 0, 1, 0))); 2868 EXPECT_TRUE(engine.FindCodec( 2869 cricket::AudioCodec(96, "CN", 32000, 0, 1, 0))); 2870 EXPECT_TRUE(engine.FindCodec( 2871 cricket::AudioCodec(96, "CN", 16000, 0, 1, 0))); 2872 EXPECT_TRUE(engine.FindCodec( 2873 cricket::AudioCodec(96, "CN", 8000, 0, 1, 0))); 2874 EXPECT_TRUE(engine.FindCodec( 2875 cricket::AudioCodec(96, "telephone-event", 8000, 0, 1, 0))); 2876 // Check codecs with an id by id. 2877 EXPECT_TRUE(engine.FindCodec( 2878 cricket::AudioCodec(0, "", 8000, 0, 1, 0))); // PCMU 2879 EXPECT_TRUE(engine.FindCodec( 2880 cricket::AudioCodec(8, "", 8000, 0, 1, 0))); // PCMA 2881 EXPECT_TRUE(engine.FindCodec( 2882 cricket::AudioCodec(9, "", 16000, 0, 1, 0))); // G722 2883 EXPECT_TRUE(engine.FindCodec( 2884 cricket::AudioCodec(13, "", 8000, 0, 1, 0))); // CN 2885 // Check sample/bitrate matching. 2886 EXPECT_TRUE(engine.FindCodec( 2887 cricket::AudioCodec(0, "PCMU", 8000, 64000, 1, 0))); 2888 // Check that bad codecs fail. 2889 EXPECT_FALSE(engine.FindCodec(cricket::AudioCodec(99, "ABCD", 0, 0, 1, 0))); 2890 EXPECT_FALSE(engine.FindCodec(cricket::AudioCodec(88, "", 0, 0, 1, 0))); 2891 EXPECT_FALSE(engine.FindCodec(cricket::AudioCodec(0, "", 0, 0, 2, 0))); 2892 EXPECT_FALSE(engine.FindCodec(cricket::AudioCodec(0, "", 5000, 0, 1, 0))); 2893 EXPECT_FALSE(engine.FindCodec(cricket::AudioCodec(0, "", 0, 5000, 1, 0))); 2894 // Check that there aren't any extra codecs lying around. 2895 EXPECT_EQ(13U, engine.codecs().size()); 2896 // Verify the payload id of common audio codecs, including CN, ISAC, and G722. 2897 for (std::vector<cricket::AudioCodec>::const_iterator it = 2898 engine.codecs().begin(); it != engine.codecs().end(); ++it) { 2899 if (it->name == "CN" && it->clockrate == 16000) { 2900 EXPECT_EQ(105, it->id); 2901 } else if (it->name == "CN" && it->clockrate == 32000) { 2902 EXPECT_EQ(106, it->id); 2903 } else if (it->name == "ISAC" && it->clockrate == 16000) { 2904 EXPECT_EQ(103, it->id); 2905 } else if (it->name == "ISAC" && it->clockrate == 32000) { 2906 EXPECT_EQ(104, it->id); 2907 } else if (it->name == "G722" && it->clockrate == 16000) { 2908 EXPECT_EQ(9, it->id); 2909 } else if (it->name == "telephone-event") { 2910 EXPECT_EQ(126, it->id); 2911 } else if (it->name == "red") { 2912 EXPECT_EQ(127, it->id); 2913 } else if (it->name == "opus") { 2914 EXPECT_EQ(111, it->id); 2915 ASSERT_TRUE(it->params.find("minptime") != it->params.end()); 2916 EXPECT_EQ("10", it->params.find("minptime")->second); 2917 ASSERT_TRUE(it->params.find("maxptime") != it->params.end()); 2918 EXPECT_EQ("60", it->params.find("maxptime")->second); 2919 } 2920 } 2921 2922 engine.Terminate(); 2923 } 2924 2925 // Tests that VoE supports at least 32 channels 2926 TEST(WebRtcVoiceEngineTest, Has32Channels) { 2927 cricket::WebRtcVoiceEngine engine; 2928 EXPECT_TRUE(engine.Init(talk_base::Thread::Current())); 2929 2930 cricket::VoiceMediaChannel* channels[32]; 2931 int num_channels = 0; 2932 2933 while (num_channels < ARRAY_SIZE(channels)) { 2934 cricket::VoiceMediaChannel* channel = engine.CreateChannel(); 2935 if (!channel) 2936 break; 2937 2938 channels[num_channels++] = channel; 2939 } 2940 2941 int expected = ARRAY_SIZE(channels); 2942 EXPECT_EQ(expected, num_channels); 2943 2944 while (num_channels > 0) { 2945 delete channels[--num_channels]; 2946 } 2947 2948 engine.Terminate(); 2949 } 2950 2951 // Test that we set our preferred codecs properly. 2952 TEST(WebRtcVoiceEngineTest, SetRecvCodecs) { 2953 cricket::WebRtcVoiceEngine engine; 2954 EXPECT_TRUE(engine.Init(talk_base::Thread::Current())); 2955 cricket::WebRtcVoiceMediaChannel channel(&engine); 2956 EXPECT_TRUE(channel.SetRecvCodecs(engine.codecs())); 2957 } 2958 2959 #ifdef WIN32 2960 // Test our workarounds to WebRtc VoE' munging of the coinit count 2961 TEST(WebRtcVoiceEngineTest, CoInitialize) { 2962 cricket::WebRtcVoiceEngine* engine = new cricket::WebRtcVoiceEngine(); 2963 2964 // Initial refcount should be 0. 2965 EXPECT_EQ(S_OK, CoInitializeEx(NULL, COINIT_MULTITHREADED)); 2966 2967 // Engine should start even with COM already inited. 2968 EXPECT_TRUE(engine->Init(talk_base::Thread::Current())); 2969 engine->Terminate(); 2970 EXPECT_TRUE(engine->Init(talk_base::Thread::Current())); 2971 engine->Terminate(); 2972 2973 // Refcount after terminate should be 1 (in reality 3); test if it is nonzero. 2974 EXPECT_EQ(S_FALSE, CoInitializeEx(NULL, COINIT_MULTITHREADED)); 2975 // Decrement refcount to (hopefully) 0. 2976 CoUninitialize(); 2977 CoUninitialize(); 2978 delete engine; 2979 2980 // Ensure refcount is 0. 2981 EXPECT_EQ(S_OK, CoInitializeEx(NULL, COINIT_MULTITHREADED)); 2982 CoUninitialize(); 2983 } 2984 #endif 2985 2986 2987 TEST_F(WebRtcVoiceEngineTestFake, SetExperimentalAcm) { 2988 EXPECT_TRUE(SetupEngine()); 2989 2990 // By default experimental ACM should not be used. 2991 int media_channel = engine_.CreateMediaVoiceChannel(); 2992 ASSERT_GE(media_channel, 0); 2993 EXPECT_FALSE(voe_.IsUsingExperimentalAcm(media_channel)); 2994 2995 int soundclip_channel = engine_.CreateSoundclipVoiceChannel(); 2996 ASSERT_GE(soundclip_channel, 0); 2997 EXPECT_FALSE(voe_sc_.IsUsingExperimentalAcm(soundclip_channel)); 2998 2999 // Set options to use experimental ACM. 3000 cricket::AudioOptions options; 3001 options.experimental_acm.Set(true); 3002 ASSERT_TRUE(engine_.SetOptions(options)); 3003 media_channel = engine_.CreateMediaVoiceChannel(); 3004 ASSERT_GE(media_channel, 0); 3005 EXPECT_TRUE(voe_.IsUsingExperimentalAcm(media_channel)); 3006 3007 soundclip_channel = engine_.CreateSoundclipVoiceChannel(); 3008 ASSERT_GE(soundclip_channel, 0); 3009 EXPECT_TRUE(voe_sc_.IsUsingExperimentalAcm(soundclip_channel)); 3010 3011 // Set option to use legacy ACM. 3012 options.experimental_acm.Set(false); 3013 ASSERT_TRUE(engine_.SetOptions(options)); 3014 media_channel = engine_.CreateMediaVoiceChannel(); 3015 ASSERT_GE(media_channel, 0); 3016 EXPECT_FALSE(voe_.IsUsingExperimentalAcm(media_channel)); 3017 3018 soundclip_channel = engine_.CreateSoundclipVoiceChannel(); 3019 ASSERT_GE(soundclip_channel, 0); 3020 EXPECT_FALSE(voe_sc_.IsUsingExperimentalAcm(soundclip_channel)); 3021 } 3022