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