blob: b476b4dc54fa9517a038f8ee38056642182543a7 [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
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000705// Test that with bitrate=invalid and stereo=0,
706// channels and bitrate are 1 and 32000.
707TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusGoodXBitrate0Stereo) {
708 EXPECT_TRUE(SetupEngine());
709 int channel_num = voe_.GetLastChannel();
710 std::vector<cricket::AudioCodec> codecs;
711 codecs.push_back(kOpusCodec);
712 codecs[0].params["stereo"] = "0";
713 webrtc::CodecInst gcodec;
714
715 // bitrate that's out of the range between 6000 and 510000 will be considered
716 // as invalid and ignored.
717 codecs[0].bitrate = 5999;
718 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
719 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
720 EXPECT_STREQ("opus", gcodec.plname);
721 EXPECT_EQ(1, gcodec.channels);
722 EXPECT_EQ(32000, gcodec.rate);
723
724 codecs[0].bitrate = 510001;
725 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
726 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
727 EXPECT_STREQ("opus", gcodec.plname);
728 EXPECT_EQ(1, gcodec.channels);
729 EXPECT_EQ(32000, gcodec.rate);
730}
731
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000732// Test that with bitrate=0 and stereo=1,
733// channels and bitrate are 2 and 64000.
734TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusGood0Bitrate1Stereo) {
735 EXPECT_TRUE(SetupEngine());
736 int channel_num = voe_.GetLastChannel();
737 std::vector<cricket::AudioCodec> codecs;
738 codecs.push_back(kOpusCodec);
739 codecs[0].bitrate = 0;
740 codecs[0].params["stereo"] = "1";
741 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
742 webrtc::CodecInst gcodec;
743 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
744 EXPECT_STREQ("opus", gcodec.plname);
745 EXPECT_EQ(2, gcodec.channels);
746 EXPECT_EQ(64000, gcodec.rate);
747}
748
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000749// Test that with bitrate=invalid and stereo=1,
750// channels and bitrate are 2 and 64000.
751TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusGoodXBitrate1Stereo) {
752 EXPECT_TRUE(SetupEngine());
753 int channel_num = voe_.GetLastChannel();
754 std::vector<cricket::AudioCodec> codecs;
755 codecs.push_back(kOpusCodec);
756 codecs[0].params["stereo"] = "1";
757 webrtc::CodecInst gcodec;
758
759 // bitrate that's out of the range between 6000 and 510000 will be considered
760 // as invalid and ignored.
761 codecs[0].bitrate = 5999;
762 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
763 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
764 EXPECT_STREQ("opus", gcodec.plname);
765 EXPECT_EQ(2, gcodec.channels);
766 EXPECT_EQ(64000, gcodec.rate);
767
768 codecs[0].bitrate = 510001;
769 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
770 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
771 EXPECT_STREQ("opus", gcodec.plname);
772 EXPECT_EQ(2, gcodec.channels);
773 EXPECT_EQ(64000, gcodec.rate);
774}
775
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000776// Test that with bitrate=N and stereo unset,
777// channels and bitrate are 1 and N.
778TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusGoodNBitrateNoStereo) {
779 EXPECT_TRUE(SetupEngine());
780 int channel_num = voe_.GetLastChannel();
781 std::vector<cricket::AudioCodec> codecs;
782 codecs.push_back(kOpusCodec);
783 codecs[0].bitrate = 96000;
784 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
785 webrtc::CodecInst gcodec;
786 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
787 EXPECT_EQ(111, gcodec.pltype);
788 EXPECT_EQ(96000, gcodec.rate);
789 EXPECT_STREQ("opus", gcodec.plname);
790 EXPECT_EQ(1, gcodec.channels);
791 EXPECT_EQ(48000, gcodec.plfreq);
792}
793
794// Test that with bitrate=N and stereo=0,
795// channels and bitrate are 1 and N.
796TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusGoodNBitrate0Stereo) {
797 EXPECT_TRUE(SetupEngine());
798 int channel_num = voe_.GetLastChannel();
799 std::vector<cricket::AudioCodec> codecs;
800 codecs.push_back(kOpusCodec);
801 codecs[0].bitrate = 30000;
802 codecs[0].params["stereo"] = "0";
803 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
804 webrtc::CodecInst gcodec;
805 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
806 EXPECT_EQ(1, gcodec.channels);
807 EXPECT_EQ(30000, gcodec.rate);
808 EXPECT_STREQ("opus", gcodec.plname);
809}
810
811// Test that with bitrate=N and without any parameters,
812// channels and bitrate are 1 and N.
813TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusGoodNBitrateNoParameters) {
814 EXPECT_TRUE(SetupEngine());
815 int channel_num = voe_.GetLastChannel();
816 std::vector<cricket::AudioCodec> codecs;
817 codecs.push_back(kOpusCodec);
818 codecs[0].bitrate = 30000;
819 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
820 webrtc::CodecInst gcodec;
821 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
822 EXPECT_EQ(1, gcodec.channels);
823 EXPECT_EQ(30000, gcodec.rate);
824 EXPECT_STREQ("opus", gcodec.plname);
825}
826
827// Test that with bitrate=N and stereo=1,
828// channels and bitrate are 2 and N.
829TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusGoodNBitrate1Stereo) {
830 EXPECT_TRUE(SetupEngine());
831 int channel_num = voe_.GetLastChannel();
832 std::vector<cricket::AudioCodec> codecs;
833 codecs.push_back(kOpusCodec);
834 codecs[0].bitrate = 30000;
835 codecs[0].params["stereo"] = "1";
836 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
837 webrtc::CodecInst gcodec;
838 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
839 EXPECT_EQ(2, gcodec.channels);
840 EXPECT_EQ(30000, gcodec.rate);
841 EXPECT_STREQ("opus", gcodec.plname);
842}
843
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000844// Test that bitrate will be overridden by the "maxaveragebitrate" parameter.
845// Also test that the "maxaveragebitrate" can't be set to values outside the
846// range of 6000 and 510000
847TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusMaxAverageBitrate) {
848 EXPECT_TRUE(SetupEngine());
849 int channel_num = voe_.GetLastChannel();
850 std::vector<cricket::AudioCodec> codecs;
851 codecs.push_back(kOpusCodec);
852 codecs[0].bitrate = 30000;
853 webrtc::CodecInst gcodec;
854
855 // Ignore if less than 6000.
856 codecs[0].params["maxaveragebitrate"] = "5999";
857 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
858 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
859 EXPECT_EQ(30000, gcodec.rate);
860
861 // Ignore if larger than 510000.
862 codecs[0].params["maxaveragebitrate"] = "510001";
863 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
864 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
865 EXPECT_EQ(30000, gcodec.rate);
866
867 codecs[0].params["maxaveragebitrate"] = "200000";
868 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
869 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
870 EXPECT_EQ(200000, gcodec.rate);
871}
872
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000873// Test that we can enable NACK with opus.
874TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecEnableNack) {
875 EXPECT_TRUE(SetupEngine());
876 int channel_num = voe_.GetLastChannel();
877 std::vector<cricket::AudioCodec> codecs;
878 codecs.push_back(kOpusCodec);
879 codecs[0].AddFeedbackParam(cricket::FeedbackParam(cricket::kRtcpFbParamNack,
880 cricket::kParamValueEmpty));
881 EXPECT_FALSE(voe_.GetNACK(channel_num));
882 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
883 EXPECT_TRUE(voe_.GetNACK(channel_num));
884}
885
886// Test that we can enable NACK on receive streams.
887TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecEnableNackRecvStreams) {
888 EXPECT_TRUE(SetupEngine());
889 EXPECT_TRUE(channel_->SetOptions(options_conference_));
890 int channel_num1 = voe_.GetLastChannel();
891 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
892 int channel_num2 = voe_.GetLastChannel();
893 std::vector<cricket::AudioCodec> codecs;
894 codecs.push_back(kOpusCodec);
895 codecs[0].AddFeedbackParam(cricket::FeedbackParam(cricket::kRtcpFbParamNack,
896 cricket::kParamValueEmpty));
897 EXPECT_FALSE(voe_.GetNACK(channel_num1));
898 EXPECT_FALSE(voe_.GetNACK(channel_num2));
899 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
900 EXPECT_TRUE(voe_.GetNACK(channel_num1));
901 EXPECT_TRUE(voe_.GetNACK(channel_num2));
902}
903
904// Test that we can disable NACK.
905TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecDisableNack) {
906 EXPECT_TRUE(SetupEngine());
907 int channel_num = voe_.GetLastChannel();
908 std::vector<cricket::AudioCodec> codecs;
909 codecs.push_back(kOpusCodec);
910 codecs[0].AddFeedbackParam(cricket::FeedbackParam(cricket::kRtcpFbParamNack,
911 cricket::kParamValueEmpty));
912 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
913 EXPECT_TRUE(voe_.GetNACK(channel_num));
914
915 codecs.clear();
916 codecs.push_back(kOpusCodec);
917 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
918 EXPECT_FALSE(voe_.GetNACK(channel_num));
919}
920
921// Test that we can disable NACK on receive streams.
922TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecDisableNackRecvStreams) {
923 EXPECT_TRUE(SetupEngine());
924 EXPECT_TRUE(channel_->SetOptions(options_conference_));
925 int channel_num1 = voe_.GetLastChannel();
926 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
927 int channel_num2 = voe_.GetLastChannel();
928 std::vector<cricket::AudioCodec> codecs;
929 codecs.push_back(kOpusCodec);
930 codecs[0].AddFeedbackParam(cricket::FeedbackParam(cricket::kRtcpFbParamNack,
931 cricket::kParamValueEmpty));
932 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
933 EXPECT_TRUE(voe_.GetNACK(channel_num1));
934 EXPECT_TRUE(voe_.GetNACK(channel_num2));
935
936 codecs.clear();
937 codecs.push_back(kOpusCodec);
938 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
939 EXPECT_FALSE(voe_.GetNACK(channel_num1));
940 EXPECT_FALSE(voe_.GetNACK(channel_num2));
941}
942
943// Test that NACK is enabled on a new receive stream.
944TEST_F(WebRtcVoiceEngineTestFake, AddRecvStreamEnableNack) {
945 EXPECT_TRUE(SetupEngine());
946 EXPECT_TRUE(channel_->SetOptions(options_conference_));
947 int channel_num = voe_.GetLastChannel();
948 std::vector<cricket::AudioCodec> codecs;
949 codecs.push_back(kIsacCodec);
950 codecs[0].AddFeedbackParam(cricket::FeedbackParam(cricket::kRtcpFbParamNack,
951 cricket::kParamValueEmpty));
952 codecs.push_back(kCn16000Codec);
953 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
954 EXPECT_TRUE(voe_.GetNACK(channel_num));
955
956 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
957 channel_num = voe_.GetLastChannel();
958 EXPECT_TRUE(voe_.GetNACK(channel_num));
959 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(3)));
960 channel_num = voe_.GetLastChannel();
961 EXPECT_TRUE(voe_.GetNACK(channel_num));
962}
963
964// Test that we can apply CELT with stereo mode but fail with mono mode.
965TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsCelt) {
966 EXPECT_TRUE(SetupEngine());
967 int channel_num = voe_.GetLastChannel();
968 std::vector<cricket::AudioCodec> codecs;
969 codecs.push_back(kCeltCodec);
970 codecs.push_back(kPcmuCodec);
971 codecs[0].id = 96;
972 codecs[0].channels = 2;
973 codecs[0].bitrate = 96000;
974 codecs[1].bitrate = 96000;
975 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
976 webrtc::CodecInst gcodec;
977 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
978 EXPECT_EQ(96, gcodec.pltype);
979 EXPECT_EQ(96000, gcodec.rate);
980 EXPECT_EQ(2, gcodec.channels);
981 EXPECT_STREQ("CELT", gcodec.plname);
982 // Doesn't support mono, expect it to fall back to the next codec in the list.
983 codecs[0].channels = 1;
984 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
985 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
986 EXPECT_EQ(0, gcodec.pltype);
987 EXPECT_EQ(1, gcodec.channels);
988 EXPECT_EQ(64000, gcodec.rate);
989 EXPECT_STREQ("PCMU", gcodec.plname);
990}
991
992// Test that we can switch back and forth between CELT and ISAC with CN.
993TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsIsacCeltSwitching) {
994 EXPECT_TRUE(SetupEngine());
995 int channel_num = voe_.GetLastChannel();
996 std::vector<cricket::AudioCodec> celt_codecs;
997 celt_codecs.push_back(kCeltCodec);
998 EXPECT_TRUE(channel_->SetSendCodecs(celt_codecs));
999 webrtc::CodecInst gcodec;
1000 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
1001 EXPECT_EQ(110, gcodec.pltype);
1002 EXPECT_STREQ("CELT", gcodec.plname);
1003
1004 std::vector<cricket::AudioCodec> isac_codecs;
1005 isac_codecs.push_back(kIsacCodec);
1006 isac_codecs.push_back(kCn16000Codec);
1007 isac_codecs.push_back(kCeltCodec);
1008 EXPECT_TRUE(channel_->SetSendCodecs(isac_codecs));
1009 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
1010 EXPECT_EQ(103, gcodec.pltype);
1011 EXPECT_STREQ("ISAC", gcodec.plname);
1012
1013 EXPECT_TRUE(channel_->SetSendCodecs(celt_codecs));
1014 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
1015 EXPECT_EQ(110, gcodec.pltype);
1016 EXPECT_STREQ("CELT", gcodec.plname);
1017}
1018
1019// Test that we handle various ways of specifying bitrate.
1020TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsBitrate) {
1021 EXPECT_TRUE(SetupEngine());
1022 int channel_num = voe_.GetLastChannel();
1023 std::vector<cricket::AudioCodec> codecs;
1024 codecs.push_back(kIsacCodec); // bitrate == 32000
1025 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1026 webrtc::CodecInst gcodec;
1027 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
1028 EXPECT_EQ(103, gcodec.pltype);
1029 EXPECT_STREQ("ISAC", gcodec.plname);
1030 EXPECT_EQ(32000, gcodec.rate);
1031
1032 codecs[0].bitrate = 0; // bitrate == default
1033 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1034 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
1035 EXPECT_EQ(103, gcodec.pltype);
1036 EXPECT_STREQ("ISAC", gcodec.plname);
1037 EXPECT_EQ(-1, gcodec.rate);
1038
1039 codecs[0].bitrate = 28000; // bitrate == 28000
1040 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1041 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
1042 EXPECT_EQ(103, gcodec.pltype);
1043 EXPECT_STREQ("ISAC", gcodec.plname);
1044 EXPECT_EQ(28000, gcodec.rate);
1045
1046 codecs[0] = kPcmuCodec; // bitrate == 64000
1047 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1048 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
1049 EXPECT_EQ(0, gcodec.pltype);
1050 EXPECT_STREQ("PCMU", gcodec.plname);
1051 EXPECT_EQ(64000, gcodec.rate);
1052
1053 codecs[0].bitrate = 0; // bitrate == default
1054 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1055 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
1056 EXPECT_EQ(0, gcodec.pltype);
1057 EXPECT_STREQ("PCMU", gcodec.plname);
1058 EXPECT_EQ(64000, gcodec.rate);
1059
1060 codecs[0] = kOpusCodec;
1061 codecs[0].bitrate = 0; // bitrate == default
1062 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1063 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
1064 EXPECT_EQ(111, gcodec.pltype);
1065 EXPECT_STREQ("opus", gcodec.plname);
1066 EXPECT_EQ(32000, gcodec.rate);
1067}
1068
1069// Test that we fall back to PCMU if no codecs are specified.
1070TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsNoCodecs) {
1071 EXPECT_TRUE(SetupEngine());
1072 int channel_num = voe_.GetLastChannel();
1073 std::vector<cricket::AudioCodec> codecs;
1074 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1075 webrtc::CodecInst gcodec;
1076 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
1077 EXPECT_EQ(0, gcodec.pltype);
1078 EXPECT_STREQ("PCMU", gcodec.plname);
1079 EXPECT_FALSE(voe_.GetVAD(channel_num));
1080 EXPECT_FALSE(voe_.GetFEC(channel_num));
1081 EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false));
1082 EXPECT_EQ(105, voe_.GetSendCNPayloadType(channel_num, true));
1083 EXPECT_EQ(106, voe_.GetSendTelephoneEventPayloadType(channel_num));
1084}
1085
1086// Test that we set VAD and DTMF types correctly.
1087TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsCNandDTMF) {
1088 EXPECT_TRUE(SetupEngine());
1089 int channel_num = voe_.GetLastChannel();
1090 std::vector<cricket::AudioCodec> codecs;
1091 codecs.push_back(kIsacCodec);
1092 codecs.push_back(kPcmuCodec);
1093 // TODO(juberti): cn 32000
1094 codecs.push_back(kCn16000Codec);
1095 codecs.push_back(kCn8000Codec);
1096 codecs.push_back(kTelephoneEventCodec);
1097 codecs.push_back(kRedCodec);
1098 codecs[0].id = 96;
1099 codecs[2].id = 97; // wideband CN
1100 codecs[4].id = 98; // DTMF
1101 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1102 webrtc::CodecInst gcodec;
1103 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
1104 EXPECT_EQ(96, gcodec.pltype);
1105 EXPECT_STREQ("ISAC", gcodec.plname);
1106 EXPECT_TRUE(voe_.GetVAD(channel_num));
1107 EXPECT_FALSE(voe_.GetFEC(channel_num));
1108 EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false));
1109 EXPECT_EQ(97, voe_.GetSendCNPayloadType(channel_num, true));
1110 EXPECT_EQ(98, voe_.GetSendTelephoneEventPayloadType(channel_num));
1111}
1112
1113// Test that we only apply VAD if we have a CN codec that matches the
1114// send codec clockrate.
1115TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsCNNoMatch) {
1116 EXPECT_TRUE(SetupEngine());
1117 int channel_num = voe_.GetLastChannel();
1118 std::vector<cricket::AudioCodec> codecs;
1119 // Set ISAC(16K) and CN(16K). VAD should be activated.
1120 codecs.push_back(kIsacCodec);
1121 codecs.push_back(kCn16000Codec);
1122 codecs[1].id = 97;
1123 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1124 webrtc::CodecInst gcodec;
1125 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
1126 EXPECT_STREQ("ISAC", gcodec.plname);
1127 EXPECT_TRUE(voe_.GetVAD(channel_num));
1128 EXPECT_EQ(97, voe_.GetSendCNPayloadType(channel_num, true));
1129 // Set PCMU(8K) and CN(16K). VAD should not be activated.
1130 codecs[0] = kPcmuCodec;
1131 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1132 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
1133 EXPECT_STREQ("PCMU", gcodec.plname);
1134 EXPECT_FALSE(voe_.GetVAD(channel_num));
1135 // Set PCMU(8K) and CN(8K). VAD should be activated.
1136 codecs[1] = kCn8000Codec;
1137 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1138 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
1139 EXPECT_STREQ("PCMU", gcodec.plname);
1140 EXPECT_TRUE(voe_.GetVAD(channel_num));
1141 EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false));
1142 // Set ISAC(16K) and CN(8K). VAD should not be activated.
1143 codecs[0] = kIsacCodec;
1144 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1145 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
1146 EXPECT_STREQ("ISAC", gcodec.plname);
1147 EXPECT_FALSE(voe_.GetVAD(channel_num));
1148}
1149
1150// Test that we perform case-insensitive matching of codec names.
1151TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsCaseInsensitive) {
1152 EXPECT_TRUE(SetupEngine());
1153 int channel_num = voe_.GetLastChannel();
1154 std::vector<cricket::AudioCodec> codecs;
1155 codecs.push_back(kIsacCodec);
1156 codecs.push_back(kPcmuCodec);
1157 codecs.push_back(kCn16000Codec);
1158 codecs.push_back(kCn8000Codec);
1159 codecs.push_back(kTelephoneEventCodec);
1160 codecs.push_back(kRedCodec);
1161 codecs[0].name = "iSaC";
1162 codecs[0].id = 96;
1163 codecs[2].id = 97; // wideband CN
1164 codecs[4].id = 98; // DTMF
1165 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1166 webrtc::CodecInst gcodec;
1167 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
1168 EXPECT_EQ(96, gcodec.pltype);
1169 EXPECT_STREQ("ISAC", gcodec.plname);
1170 EXPECT_TRUE(voe_.GetVAD(channel_num));
1171 EXPECT_FALSE(voe_.GetFEC(channel_num));
1172 EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false));
1173 EXPECT_EQ(97, voe_.GetSendCNPayloadType(channel_num, true));
1174 EXPECT_EQ(98, voe_.GetSendTelephoneEventPayloadType(channel_num));
1175}
1176
1177// Test that we set up FEC correctly.
1178TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsRED) {
1179 EXPECT_TRUE(SetupEngine());
1180 int channel_num = voe_.GetLastChannel();
1181 std::vector<cricket::AudioCodec> codecs;
1182 codecs.push_back(kRedCodec);
1183 codecs.push_back(kIsacCodec);
1184 codecs.push_back(kPcmuCodec);
1185 codecs[0].id = 127;
1186 codecs[0].params[""] = "96/96";
1187 codecs[1].id = 96;
1188 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1189 webrtc::CodecInst gcodec;
1190 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
1191 EXPECT_EQ(96, gcodec.pltype);
1192 EXPECT_STREQ("ISAC", gcodec.plname);
1193 EXPECT_TRUE(voe_.GetFEC(channel_num));
1194 EXPECT_EQ(127, voe_.GetSendFECPayloadType(channel_num));
1195}
1196
1197// Test that we set up FEC correctly if params are omitted.
1198TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsREDNoParams) {
1199 EXPECT_TRUE(SetupEngine());
1200 int channel_num = voe_.GetLastChannel();
1201 std::vector<cricket::AudioCodec> codecs;
1202 codecs.push_back(kRedCodec);
1203 codecs.push_back(kIsacCodec);
1204 codecs.push_back(kPcmuCodec);
1205 codecs[0].id = 127;
1206 codecs[1].id = 96;
1207 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1208 webrtc::CodecInst gcodec;
1209 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
1210 EXPECT_EQ(96, gcodec.pltype);
1211 EXPECT_STREQ("ISAC", gcodec.plname);
1212 EXPECT_TRUE(voe_.GetFEC(channel_num));
1213 EXPECT_EQ(127, voe_.GetSendFECPayloadType(channel_num));
1214}
1215
1216// Test that we ignore RED if the parameters aren't named the way we expect.
1217TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsBadRED1) {
1218 EXPECT_TRUE(SetupEngine());
1219 int channel_num = voe_.GetLastChannel();
1220 std::vector<cricket::AudioCodec> codecs;
1221 codecs.push_back(kRedCodec);
1222 codecs.push_back(kIsacCodec);
1223 codecs.push_back(kPcmuCodec);
1224 codecs[0].id = 127;
1225 codecs[0].params["ABC"] = "96/96";
1226 codecs[1].id = 96;
1227 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1228 webrtc::CodecInst gcodec;
1229 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
1230 EXPECT_EQ(96, gcodec.pltype);
1231 EXPECT_STREQ("ISAC", gcodec.plname);
1232 EXPECT_FALSE(voe_.GetFEC(channel_num));
1233}
1234
1235// Test that we ignore RED if it uses different primary/secondary encoding.
1236TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsBadRED2) {
1237 EXPECT_TRUE(SetupEngine());
1238 int channel_num = voe_.GetLastChannel();
1239 std::vector<cricket::AudioCodec> codecs;
1240 codecs.push_back(kRedCodec);
1241 codecs.push_back(kIsacCodec);
1242 codecs.push_back(kPcmuCodec);
1243 codecs[0].id = 127;
1244 codecs[0].params[""] = "96/0";
1245 codecs[1].id = 96;
1246 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1247 webrtc::CodecInst gcodec;
1248 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
1249 EXPECT_EQ(96, gcodec.pltype);
1250 EXPECT_STREQ("ISAC", gcodec.plname);
1251 EXPECT_FALSE(voe_.GetFEC(channel_num));
1252}
1253
1254// Test that we ignore RED if it uses more than 2 encodings.
1255TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsBadRED3) {
1256 EXPECT_TRUE(SetupEngine());
1257 int channel_num = voe_.GetLastChannel();
1258 std::vector<cricket::AudioCodec> codecs;
1259 codecs.push_back(kRedCodec);
1260 codecs.push_back(kIsacCodec);
1261 codecs.push_back(kPcmuCodec);
1262 codecs[0].id = 127;
1263 codecs[0].params[""] = "96/96/96";
1264 codecs[1].id = 96;
1265 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1266 webrtc::CodecInst gcodec;
1267 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
1268 EXPECT_EQ(96, gcodec.pltype);
1269 EXPECT_STREQ("ISAC", gcodec.plname);
1270 EXPECT_FALSE(voe_.GetFEC(channel_num));
1271}
1272
1273// Test that we ignore RED if it has bogus codec ids.
1274TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsBadRED4) {
1275 EXPECT_TRUE(SetupEngine());
1276 int channel_num = voe_.GetLastChannel();
1277 std::vector<cricket::AudioCodec> codecs;
1278 codecs.push_back(kRedCodec);
1279 codecs.push_back(kIsacCodec);
1280 codecs.push_back(kPcmuCodec);
1281 codecs[0].id = 127;
1282 codecs[0].params[""] = "ABC/ABC";
1283 codecs[1].id = 96;
1284 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1285 webrtc::CodecInst gcodec;
1286 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
1287 EXPECT_EQ(96, gcodec.pltype);
1288 EXPECT_STREQ("ISAC", gcodec.plname);
1289 EXPECT_FALSE(voe_.GetFEC(channel_num));
1290}
1291
1292// Test that we ignore RED if it refers to a codec that is not present.
1293TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsBadRED5) {
1294 EXPECT_TRUE(SetupEngine());
1295 int channel_num = voe_.GetLastChannel();
1296 std::vector<cricket::AudioCodec> codecs;
1297 codecs.push_back(kRedCodec);
1298 codecs.push_back(kIsacCodec);
1299 codecs.push_back(kPcmuCodec);
1300 codecs[0].id = 127;
1301 codecs[0].params[""] = "97/97";
1302 codecs[1].id = 96;
1303 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1304 webrtc::CodecInst gcodec;
1305 EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
1306 EXPECT_EQ(96, gcodec.pltype);
1307 EXPECT_STREQ("ISAC", gcodec.plname);
1308 EXPECT_FALSE(voe_.GetFEC(channel_num));
1309}
1310
1311// Test that we support setting an empty list of recv header extensions.
1312TEST_F(WebRtcVoiceEngineTestFake, SetRecvRtpHeaderExtensions) {
1313 EXPECT_TRUE(SetupEngine());
1314 std::vector<cricket::RtpHeaderExtension> extensions;
1315 int channel_num = voe_.GetLastChannel();
1316 bool enable = false;
1317 unsigned char id = 0;
1318
1319 // An empty list shouldn't cause audio-level headers to be enabled.
1320 EXPECT_TRUE(channel_->SetRecvRtpHeaderExtensions(extensions));
1321 EXPECT_EQ(0, voe_.GetRTPAudioLevelIndicationStatus(
1322 channel_num, enable, id));
1323 EXPECT_FALSE(enable);
1324
1325 // Nor should indicating we can receive the audio-level header.
1326 extensions.push_back(cricket::RtpHeaderExtension(
1327 "urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8));
1328 EXPECT_TRUE(channel_->SetRecvRtpHeaderExtensions(extensions));
1329 EXPECT_EQ(0, voe_.GetRTPAudioLevelIndicationStatus(
1330 channel_num, enable, id));
1331 EXPECT_FALSE(enable);
1332}
1333
1334// Test that we support setting certain send header extensions.
1335TEST_F(WebRtcVoiceEngineTestFake, SetSendRtpHeaderExtensions) {
1336 EXPECT_TRUE(SetupEngine());
1337 std::vector<cricket::RtpHeaderExtension> extensions;
1338 int channel_num = voe_.GetLastChannel();
1339 bool enable = false;
1340 unsigned char id = 0;
1341
1342 // Ensure audio levels are off by default.
1343 EXPECT_EQ(0, voe_.GetRTPAudioLevelIndicationStatus(
1344 channel_num, enable, id));
1345 EXPECT_FALSE(enable);
1346
1347 // Ensure unknown extentions won't cause an error.
1348 extensions.push_back(cricket::RtpHeaderExtension(
1349 "urn:ietf:params:unknowextention", 1));
1350 EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(extensions));
1351 EXPECT_EQ(0, voe_.GetRTPAudioLevelIndicationStatus(
1352 channel_num, enable, id));
1353 EXPECT_FALSE(enable);
1354
1355 // Ensure audio levels stay off with an empty list of headers.
1356 EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(extensions));
1357 EXPECT_EQ(0, voe_.GetRTPAudioLevelIndicationStatus(
1358 channel_num, enable, id));
1359 EXPECT_FALSE(enable);
1360
1361 // Ensure audio levels are enabled if the audio-level header is specified.
1362 extensions.push_back(cricket::RtpHeaderExtension(
1363 "urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8));
1364 EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(extensions));
1365 EXPECT_EQ(0, voe_.GetRTPAudioLevelIndicationStatus(
1366 channel_num, enable, id));
1367 EXPECT_TRUE(enable);
1368 EXPECT_EQ(8, id);
1369
1370 // Ensure audio levels go back off with an empty list.
1371 extensions.clear();
1372 EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(extensions));
1373 EXPECT_EQ(0, voe_.GetRTPAudioLevelIndicationStatus(
1374 channel_num, enable, id));
1375 EXPECT_FALSE(enable);
1376}
1377
1378// Test that we can create a channel and start sending/playing out on it.
1379TEST_F(WebRtcVoiceEngineTestFake, SendAndPlayout) {
1380 EXPECT_TRUE(SetupEngine());
1381 int channel_num = voe_.GetLastChannel();
1382 std::vector<cricket::AudioCodec> codecs;
1383 codecs.push_back(kPcmuCodec);
1384 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1385 EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE));
1386 EXPECT_TRUE(voe_.GetSend(channel_num));
1387 EXPECT_TRUE(channel_->SetPlayout(true));
1388 EXPECT_TRUE(voe_.GetPlayout(channel_num));
1389 EXPECT_TRUE(channel_->SetSend(cricket::SEND_NOTHING));
1390 EXPECT_FALSE(voe_.GetSend(channel_num));
1391 EXPECT_TRUE(channel_->SetPlayout(false));
1392 EXPECT_FALSE(voe_.GetPlayout(channel_num));
1393}
1394
1395// Test that we can add and remove streams, and do proper send/playout.
1396// We can receive on multiple streams, but will only send on one.
1397TEST_F(WebRtcVoiceEngineTestFake, SendAndPlayoutWithMultipleStreams) {
1398 EXPECT_TRUE(SetupEngine());
1399 int channel_num1 = voe_.GetLastChannel();
1400
1401 // Start playout on the default channel.
1402 EXPECT_TRUE(channel_->SetOptions(options_conference_));
1403 EXPECT_TRUE(channel_->SetPlayout(true));
1404 EXPECT_TRUE(voe_.GetPlayout(channel_num1));
1405
1406 // Adding another stream should disable playout on the default channel.
1407 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
1408 int channel_num2 = voe_.GetLastChannel();
1409 std::vector<cricket::AudioCodec> codecs;
1410 codecs.push_back(kPcmuCodec);
1411 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1412 EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE));
1413 EXPECT_TRUE(voe_.GetSend(channel_num1));
1414 EXPECT_FALSE(voe_.GetSend(channel_num2));
1415
1416 // Make sure only the new channel is played out.
1417 EXPECT_FALSE(voe_.GetPlayout(channel_num1));
1418 EXPECT_TRUE(voe_.GetPlayout(channel_num2));
1419
1420 // Adding yet another stream should have stream 2 and 3 enabled for playout.
1421 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(3)));
1422 int channel_num3 = voe_.GetLastChannel();
1423 EXPECT_FALSE(voe_.GetPlayout(channel_num1));
1424 EXPECT_TRUE(voe_.GetPlayout(channel_num2));
1425 EXPECT_TRUE(voe_.GetPlayout(channel_num3));
1426 EXPECT_FALSE(voe_.GetSend(channel_num3));
1427
1428 // Stop sending.
1429 EXPECT_TRUE(channel_->SetSend(cricket::SEND_NOTHING));
1430 EXPECT_FALSE(voe_.GetSend(channel_num1));
1431 EXPECT_FALSE(voe_.GetSend(channel_num2));
1432 EXPECT_FALSE(voe_.GetSend(channel_num3));
1433
1434 // Stop playout.
1435 EXPECT_TRUE(channel_->SetPlayout(false));
1436 EXPECT_FALSE(voe_.GetPlayout(channel_num1));
1437 EXPECT_FALSE(voe_.GetPlayout(channel_num2));
1438 EXPECT_FALSE(voe_.GetPlayout(channel_num3));
1439
1440 // Restart playout and make sure the default channel still is not played out.
1441 EXPECT_TRUE(channel_->SetPlayout(true));
1442 EXPECT_FALSE(voe_.GetPlayout(channel_num1));
1443 EXPECT_TRUE(voe_.GetPlayout(channel_num2));
1444 EXPECT_TRUE(voe_.GetPlayout(channel_num3));
1445
1446 // Now remove the new streams and verify that the default channel is
1447 // played out again.
1448 EXPECT_TRUE(channel_->RemoveRecvStream(3));
1449 EXPECT_TRUE(channel_->RemoveRecvStream(2));
1450
1451 EXPECT_TRUE(voe_.GetPlayout(channel_num1));
1452}
1453
1454// Test that we can set the devices to use.
1455TEST_F(WebRtcVoiceEngineTestFake, SetDevices) {
1456 EXPECT_TRUE(SetupEngine());
1457 int channel_num = voe_.GetLastChannel();
1458 std::vector<cricket::AudioCodec> codecs;
1459 codecs.push_back(kPcmuCodec);
1460 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1461
1462 cricket::Device default_dev(cricket::kFakeDefaultDeviceName,
1463 cricket::kFakeDefaultDeviceId);
1464 cricket::Device dev(cricket::kFakeDeviceName,
1465 cricket::kFakeDeviceId);
1466
1467 // Test SetDevices() while not sending or playing.
1468 EXPECT_TRUE(engine_.SetDevices(&default_dev, &default_dev));
1469
1470 // Test SetDevices() while sending and playing.
1471 EXPECT_TRUE(engine_.SetLocalMonitor(true));
1472 EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE));
1473 EXPECT_TRUE(channel_->SetPlayout(true));
1474 EXPECT_TRUE(voe_.GetRecordingMicrophone());
1475 EXPECT_TRUE(voe_.GetSend(channel_num));
1476 EXPECT_TRUE(voe_.GetPlayout(channel_num));
1477
1478 EXPECT_TRUE(engine_.SetDevices(&dev, &dev));
1479
1480 EXPECT_TRUE(voe_.GetRecordingMicrophone());
1481 EXPECT_TRUE(voe_.GetSend(channel_num));
1482 EXPECT_TRUE(voe_.GetPlayout(channel_num));
1483
1484 // Test that failure to open newly selected devices does not prevent opening
1485 // ones after that.
1486 voe_.set_fail_start_recording_microphone(true);
1487 voe_.set_playout_fail_channel(channel_num);
1488 voe_.set_send_fail_channel(channel_num);
1489
1490 EXPECT_FALSE(engine_.SetDevices(&default_dev, &default_dev));
1491
1492 EXPECT_FALSE(voe_.GetRecordingMicrophone());
1493 EXPECT_FALSE(voe_.GetSend(channel_num));
1494 EXPECT_FALSE(voe_.GetPlayout(channel_num));
1495
1496 voe_.set_fail_start_recording_microphone(false);
1497 voe_.set_playout_fail_channel(-1);
1498 voe_.set_send_fail_channel(-1);
1499
1500 EXPECT_TRUE(engine_.SetDevices(&dev, &dev));
1501
1502 EXPECT_TRUE(voe_.GetRecordingMicrophone());
1503 EXPECT_TRUE(voe_.GetSend(channel_num));
1504 EXPECT_TRUE(voe_.GetPlayout(channel_num));
1505}
1506
1507// Test that we can set the devices to use even if we failed to
1508// open the initial ones.
1509TEST_F(WebRtcVoiceEngineTestFake, SetDevicesWithInitiallyBadDevices) {
1510 EXPECT_TRUE(SetupEngine());
1511 int channel_num = voe_.GetLastChannel();
1512 std::vector<cricket::AudioCodec> codecs;
1513 codecs.push_back(kPcmuCodec);
1514 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1515
1516 cricket::Device default_dev(cricket::kFakeDefaultDeviceName,
1517 cricket::kFakeDefaultDeviceId);
1518 cricket::Device dev(cricket::kFakeDeviceName,
1519 cricket::kFakeDeviceId);
1520
1521 // Test that failure to open devices selected before starting
1522 // send/play does not prevent opening newly selected ones after that.
1523 voe_.set_fail_start_recording_microphone(true);
1524 voe_.set_playout_fail_channel(channel_num);
1525 voe_.set_send_fail_channel(channel_num);
1526
1527 EXPECT_TRUE(engine_.SetDevices(&default_dev, &default_dev));
1528
1529 EXPECT_FALSE(engine_.SetLocalMonitor(true));
1530 EXPECT_FALSE(channel_->SetSend(cricket::SEND_MICROPHONE));
1531 EXPECT_FALSE(channel_->SetPlayout(true));
1532 EXPECT_FALSE(voe_.GetRecordingMicrophone());
1533 EXPECT_FALSE(voe_.GetSend(channel_num));
1534 EXPECT_FALSE(voe_.GetPlayout(channel_num));
1535
1536 voe_.set_fail_start_recording_microphone(false);
1537 voe_.set_playout_fail_channel(-1);
1538 voe_.set_send_fail_channel(-1);
1539
1540 EXPECT_TRUE(engine_.SetDevices(&dev, &dev));
1541
1542 EXPECT_TRUE(voe_.GetRecordingMicrophone());
1543 EXPECT_TRUE(voe_.GetSend(channel_num));
1544 EXPECT_TRUE(voe_.GetPlayout(channel_num));
1545}
1546
1547// Test that we can create a channel configured for multi-point conferences,
1548// and start sending/playing out on it.
1549TEST_F(WebRtcVoiceEngineTestFake, ConferenceSendAndPlayout) {
1550 EXPECT_TRUE(SetupEngine());
1551 int channel_num = voe_.GetLastChannel();
1552 EXPECT_TRUE(channel_->SetOptions(options_conference_));
1553 std::vector<cricket::AudioCodec> codecs;
1554 codecs.push_back(kPcmuCodec);
1555 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1556 EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE));
1557 EXPECT_TRUE(voe_.GetSend(channel_num));
1558}
1559
1560// Test that we can create a channel configured for Codian bridges,
1561// and start sending/playing out on it.
1562TEST_F(WebRtcVoiceEngineTestFake, CodianSendAndPlayout) {
1563 EXPECT_TRUE(SetupEngine());
1564 int channel_num = voe_.GetLastChannel();
1565 webrtc::AgcConfig agc_config;
1566 EXPECT_EQ(0, voe_.GetAgcConfig(agc_config));
1567 EXPECT_EQ(0, agc_config.targetLeveldBOv);
1568 EXPECT_TRUE(channel_->SetOptions(options_adjust_agc_));
1569 std::vector<cricket::AudioCodec> codecs;
1570 codecs.push_back(kPcmuCodec);
1571 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1572 EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE));
1573 EXPECT_TRUE(voe_.GetSend(channel_num));
1574 EXPECT_EQ(0, voe_.GetAgcConfig(agc_config));
1575 EXPECT_EQ(agc_config.targetLeveldBOv, 10); // level was attenuated
1576 EXPECT_TRUE(channel_->SetPlayout(true));
1577 EXPECT_TRUE(voe_.GetPlayout(channel_num));
1578 EXPECT_TRUE(channel_->SetSend(cricket::SEND_NOTHING));
1579 EXPECT_FALSE(voe_.GetSend(channel_num));
1580 EXPECT_EQ(0, voe_.GetAgcConfig(agc_config));
1581 EXPECT_EQ(0, agc_config.targetLeveldBOv); // level was restored
1582 EXPECT_TRUE(channel_->SetPlayout(false));
1583 EXPECT_FALSE(voe_.GetPlayout(channel_num));
1584}
1585
1586// Test that we can set the outgoing SSRC properly.
1587// SSRC is set in SetupEngine by calling AddSendStream.
1588TEST_F(WebRtcVoiceEngineTestFake, SetSendSsrc) {
1589 EXPECT_TRUE(SetupEngine());
1590 int channel_num = voe_.GetLastChannel();
1591 unsigned int send_ssrc;
1592 EXPECT_EQ(0, voe_.GetLocalSSRC(channel_num, send_ssrc));
1593 EXPECT_NE(0U, send_ssrc);
1594 EXPECT_EQ(0, voe_.GetLocalSSRC(channel_num, send_ssrc));
1595 EXPECT_EQ(kSsrc1, send_ssrc);
1596}
1597
1598TEST_F(WebRtcVoiceEngineTestFake, GetStats) {
1599 // Setup. We need send codec to be set to get all stats.
1600 EXPECT_TRUE(SetupEngine());
1601 std::vector<cricket::AudioCodec> codecs;
1602 codecs.push_back(kPcmuCodec);
1603 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1604
1605 cricket::VoiceMediaInfo info;
1606 EXPECT_EQ(true, channel_->GetStats(&info));
1607 EXPECT_EQ(1u, info.senders.size());
1608 EXPECT_EQ(kSsrc1, info.senders[0].ssrc);
1609 EXPECT_EQ(kPcmuCodec.name, info.senders[0].codec_name);
1610 EXPECT_EQ(cricket::kIntStatValue, info.senders[0].bytes_sent);
1611 EXPECT_EQ(cricket::kIntStatValue, info.senders[0].packets_sent);
1612 EXPECT_EQ(cricket::kIntStatValue, info.senders[0].packets_lost);
1613 EXPECT_EQ(cricket::kFractionLostStatValue, info.senders[0].fraction_lost);
1614 EXPECT_EQ(cricket::kIntStatValue, info.senders[0].ext_seqnum);
1615 EXPECT_EQ(cricket::kIntStatValue, info.senders[0].rtt_ms);
1616 EXPECT_EQ(cricket::kIntStatValue, info.senders[0].jitter_ms);
1617 // TODO(sriniv): Add testing for more fields. These are not populated
1618 // in FakeWebrtcVoiceEngine yet.
1619 // EXPECT_EQ(cricket::kIntStatValue, info.senders[0].audio_level);
1620 // EXPECT_EQ(cricket::kIntStatValue, info.senders[0].echo_delay_median_ms);
1621 // EXPECT_EQ(cricket::kIntStatValue, info.senders[0].echo_delay_std_ms);
1622 // EXPECT_EQ(cricket::kIntStatValue, info.senders[0].echo_return_loss);
1623 // EXPECT_EQ(cricket::kIntStatValue,
1624 // info.senders[0].echo_return_loss_enhancement);
1625
1626 EXPECT_EQ(1u, info.receivers.size());
1627 // TODO(sriniv): Add testing for receiver fields.
1628}
1629
1630// Test that we can set the outgoing SSRC properly with multiple streams.
1631// SSRC is set in SetupEngine by calling AddSendStream.
1632TEST_F(WebRtcVoiceEngineTestFake, SetSendSsrcWithMultipleStreams) {
1633 EXPECT_TRUE(SetupEngine());
1634 EXPECT_TRUE(channel_->SetOptions(options_conference_));
1635 int channel_num1 = voe_.GetLastChannel();
1636 unsigned int send_ssrc;
1637 EXPECT_EQ(0, voe_.GetLocalSSRC(channel_num1, send_ssrc));
1638 EXPECT_EQ(kSsrc1, send_ssrc);
1639
1640 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
1641 int channel_num2 = voe_.GetLastChannel();
1642 EXPECT_EQ(0, voe_.GetLocalSSRC(channel_num2, send_ssrc));
1643 EXPECT_EQ(kSsrc1, send_ssrc);
1644}
1645
1646// Test that the local SSRC is the same on sending and receiving channels if the
1647// receive channel is created before the send channel.
1648TEST_F(WebRtcVoiceEngineTestFake, SetSendSsrcAfterCreatingReceiveChannel) {
1649 EXPECT_TRUE(engine_.Init(talk_base::Thread::Current()));
1650 channel_ = engine_.CreateChannel();
1651 EXPECT_TRUE(channel_->SetOptions(options_conference_));
1652
1653 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1)));
1654 int receive_channel_num = voe_.GetLastChannel();
1655 EXPECT_TRUE(channel_->AddSendStream(
1656 cricket::StreamParams::CreateLegacy(1234)));
1657 int send_channel_num = voe_.GetLastChannel();
1658
1659 unsigned int ssrc = 0;
1660 EXPECT_EQ(0, voe_.GetLocalSSRC(send_channel_num, ssrc));
1661 EXPECT_EQ(1234U, ssrc);
1662 ssrc = 0;
1663 EXPECT_EQ(0, voe_.GetLocalSSRC(receive_channel_num, ssrc));
1664 EXPECT_EQ(1234U, ssrc);
1665}
1666
1667// Test that we can properly receive packets.
1668TEST_F(WebRtcVoiceEngineTestFake, Recv) {
1669 EXPECT_TRUE(SetupEngine());
1670 int channel_num = voe_.GetLastChannel();
1671 DeliverPacket(kPcmuFrame, sizeof(kPcmuFrame));
1672 EXPECT_TRUE(voe_.CheckPacket(channel_num, kPcmuFrame,
1673 sizeof(kPcmuFrame)));
1674}
1675
1676// Test that we can properly receive packets on multiple streams.
1677TEST_F(WebRtcVoiceEngineTestFake, RecvWithMultipleStreams) {
1678 EXPECT_TRUE(SetupEngine());
1679 EXPECT_TRUE(channel_->SetOptions(options_conference_));
1680 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1)));
1681 int channel_num1 = voe_.GetLastChannel();
1682 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
1683 int channel_num2 = voe_.GetLastChannel();
1684 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(3)));
1685 int channel_num3 = voe_.GetLastChannel();
1686 // Create packets with the right SSRCs.
1687 char packets[4][sizeof(kPcmuFrame)];
1688 for (size_t i = 0; i < ARRAY_SIZE(packets); ++i) {
1689 memcpy(packets[i], kPcmuFrame, sizeof(kPcmuFrame));
1690 talk_base::SetBE32(packets[i] + 8, i);
1691 }
1692 EXPECT_TRUE(voe_.CheckNoPacket(channel_num1));
1693 EXPECT_TRUE(voe_.CheckNoPacket(channel_num2));
1694 EXPECT_TRUE(voe_.CheckNoPacket(channel_num3));
1695 DeliverPacket(packets[0], sizeof(packets[0]));
1696 EXPECT_TRUE(voe_.CheckNoPacket(channel_num1));
1697 EXPECT_TRUE(voe_.CheckNoPacket(channel_num2));
1698 EXPECT_TRUE(voe_.CheckNoPacket(channel_num3));
1699 DeliverPacket(packets[1], sizeof(packets[1]));
1700 EXPECT_TRUE(voe_.CheckPacket(channel_num1, packets[1],
1701 sizeof(packets[1])));
1702 EXPECT_TRUE(voe_.CheckNoPacket(channel_num2));
1703 EXPECT_TRUE(voe_.CheckNoPacket(channel_num3));
1704 DeliverPacket(packets[2], sizeof(packets[2]));
1705 EXPECT_TRUE(voe_.CheckNoPacket(channel_num1));
1706 EXPECT_TRUE(voe_.CheckPacket(channel_num2, packets[2],
1707 sizeof(packets[2])));
1708 EXPECT_TRUE(voe_.CheckNoPacket(channel_num3));
1709 DeliverPacket(packets[3], sizeof(packets[3]));
1710 EXPECT_TRUE(voe_.CheckNoPacket(channel_num1));
1711 EXPECT_TRUE(voe_.CheckNoPacket(channel_num2));
1712 EXPECT_TRUE(voe_.CheckPacket(channel_num3, packets[3],
1713 sizeof(packets[3])));
1714 EXPECT_TRUE(channel_->RemoveRecvStream(3));
1715 EXPECT_TRUE(channel_->RemoveRecvStream(2));
1716 EXPECT_TRUE(channel_->RemoveRecvStream(1));
1717}
1718
1719// Test that we properly handle failures to add a stream.
1720TEST_F(WebRtcVoiceEngineTestFake, AddStreamFail) {
1721 EXPECT_TRUE(SetupEngine());
1722 voe_.set_fail_create_channel(true);
1723 EXPECT_TRUE(channel_->SetOptions(options_conference_));
1724 EXPECT_FALSE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
1725
1726 // In 1:1 call, we should not try to create a new channel.
1727 cricket::AudioOptions options_no_conference_;
1728 options_no_conference_.conference_mode.Set(false);
1729 EXPECT_TRUE(channel_->SetOptions(options_no_conference_));
1730 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
1731}
1732
1733// Test that AddRecvStream doesn't create new channel for 1:1 call.
1734TEST_F(WebRtcVoiceEngineTestFake, AddRecvStream1On1) {
1735 EXPECT_TRUE(SetupEngine());
1736 int channel_num = voe_.GetLastChannel();
1737 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1)));
1738 EXPECT_EQ(channel_num, voe_.GetLastChannel());
1739}
1740
1741// Test that after adding a recv stream, we do not decode more codecs than
1742// those previously passed into SetRecvCodecs.
1743TEST_F(WebRtcVoiceEngineTestFake, AddRecvStreamUnsupportedCodec) {
1744 EXPECT_TRUE(SetupEngine());
1745 EXPECT_TRUE(channel_->SetOptions(options_conference_));
1746 std::vector<cricket::AudioCodec> codecs;
1747 codecs.push_back(kIsacCodec);
1748 codecs.push_back(kPcmuCodec);
1749 EXPECT_TRUE(channel_->SetRecvCodecs(codecs));
1750 EXPECT_TRUE(channel_->AddRecvStream(
1751 cricket::StreamParams::CreateLegacy(kSsrc1)));
1752 int channel_num2 = voe_.GetLastChannel();
1753 webrtc::CodecInst gcodec;
1754 talk_base::strcpyn(gcodec.plname, ARRAY_SIZE(gcodec.plname), "CELT");
1755 gcodec.plfreq = 32000;
1756 gcodec.channels = 2;
1757 EXPECT_EQ(-1, voe_.GetRecPayloadType(channel_num2, gcodec));
1758}
1759
1760// Test that we properly clean up any streams that were added, even if
1761// not explicitly removed.
1762TEST_F(WebRtcVoiceEngineTestFake, StreamCleanup) {
1763 EXPECT_TRUE(SetupEngine());
1764 EXPECT_TRUE(channel_->SetOptions(options_conference_));
1765 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1)));
1766 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
1767 EXPECT_EQ(3, voe_.GetNumChannels()); // default channel + 2 added
1768 delete channel_;
1769 channel_ = NULL;
1770 EXPECT_EQ(0, voe_.GetNumChannels());
1771}
1772
1773// Test the InsertDtmf on default send stream.
1774TEST_F(WebRtcVoiceEngineTestFake, InsertDtmfOnDefaultSendStream) {
1775 EXPECT_TRUE(SetupEngine());
1776 int channel_num = voe_.GetLastChannel();
1777 TestInsertDtmf(0, channel_num);
1778}
1779
1780// Test the InsertDtmf on specified send stream.
1781TEST_F(WebRtcVoiceEngineTestFake, InsertDtmfOnSendStream) {
1782 EXPECT_TRUE(SetupEngine());
1783 int channel_num = voe_.GetLastChannel();
1784 TestInsertDtmf(kSsrc1, channel_num);
1785}
1786
1787// Test that we can play a ringback tone properly in a single-stream call.
1788TEST_F(WebRtcVoiceEngineTestFake, PlayRingback) {
1789 EXPECT_TRUE(SetupEngine());
1790 int channel_num = voe_.GetLastChannel();
1791 EXPECT_EQ(0, voe_.IsPlayingFileLocally(channel_num));
1792 // Check we fail if no ringback tone specified.
1793 EXPECT_FALSE(channel_->PlayRingbackTone(0, true, true));
1794 EXPECT_EQ(0, voe_.IsPlayingFileLocally(channel_num));
1795 // Check we can set and play a ringback tone.
1796 EXPECT_TRUE(channel_->SetRingbackTone(kRingbackTone, strlen(kRingbackTone)));
1797 EXPECT_TRUE(channel_->PlayRingbackTone(0, true, true));
1798 EXPECT_EQ(1, voe_.IsPlayingFileLocally(channel_num));
1799 // Check we can stop the tone manually.
1800 EXPECT_TRUE(channel_->PlayRingbackTone(0, false, false));
1801 EXPECT_EQ(0, voe_.IsPlayingFileLocally(channel_num));
1802 // Check we stop the tone if a packet arrives.
1803 EXPECT_TRUE(channel_->PlayRingbackTone(0, true, true));
1804 EXPECT_EQ(1, voe_.IsPlayingFileLocally(channel_num));
1805 DeliverPacket(kPcmuFrame, sizeof(kPcmuFrame));
1806 EXPECT_EQ(0, voe_.IsPlayingFileLocally(channel_num));
1807}
1808
1809// Test that we can play a ringback tone properly in a multi-stream call.
1810TEST_F(WebRtcVoiceEngineTestFake, PlayRingbackWithMultipleStreams) {
1811 EXPECT_TRUE(SetupEngine());
1812 EXPECT_TRUE(channel_->SetOptions(options_conference_));
1813 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1)));
1814 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
1815 int channel_num = voe_.GetLastChannel();
1816 EXPECT_EQ(0, voe_.IsPlayingFileLocally(channel_num));
1817 // Check we fail if no ringback tone specified.
1818 EXPECT_FALSE(channel_->PlayRingbackTone(2, true, true));
1819 EXPECT_EQ(0, voe_.IsPlayingFileLocally(channel_num));
1820 // Check we can set and play a ringback tone on the correct ssrc.
1821 EXPECT_TRUE(channel_->SetRingbackTone(kRingbackTone, strlen(kRingbackTone)));
1822 EXPECT_FALSE(channel_->PlayRingbackTone(77, true, true));
1823 EXPECT_TRUE(channel_->PlayRingbackTone(2, true, true));
1824 EXPECT_EQ(1, voe_.IsPlayingFileLocally(channel_num));
1825 // Check we can stop the tone manually.
1826 EXPECT_TRUE(channel_->PlayRingbackTone(2, false, false));
1827 EXPECT_EQ(0, voe_.IsPlayingFileLocally(channel_num));
1828 // Check we stop the tone if a packet arrives, but only with the right SSRC.
1829 EXPECT_TRUE(channel_->PlayRingbackTone(2, true, true));
1830 EXPECT_EQ(1, voe_.IsPlayingFileLocally(channel_num));
1831 // Send a packet with SSRC 1; the tone should not stop.
1832 DeliverPacket(kPcmuFrame, sizeof(kPcmuFrame));
1833 EXPECT_EQ(1, voe_.IsPlayingFileLocally(channel_num));
1834 // Send a packet with SSRC 2; the tone should stop.
1835 char packet[sizeof(kPcmuFrame)];
1836 memcpy(packet, kPcmuFrame, sizeof(kPcmuFrame));
1837 talk_base::SetBE32(packet + 8, 2);
1838 DeliverPacket(packet, sizeof(packet));
1839 EXPECT_EQ(0, voe_.IsPlayingFileLocally(channel_num));
1840}
1841
1842// Tests creating soundclips, and make sure they come from the right engine.
1843TEST_F(WebRtcVoiceEngineTestFake, CreateSoundclip) {
1844 EXPECT_TRUE(engine_.Init(talk_base::Thread::Current()));
1845 soundclip_ = engine_.CreateSoundclip();
1846 ASSERT_TRUE(soundclip_ != NULL);
1847 EXPECT_EQ(0, voe_.GetNumChannels());
1848 EXPECT_EQ(1, voe_sc_.GetNumChannels());
1849 int channel_num = voe_sc_.GetLastChannel();
1850 EXPECT_TRUE(voe_sc_.GetPlayout(channel_num));
1851 delete soundclip_;
1852 soundclip_ = NULL;
1853 EXPECT_EQ(0, voe_sc_.GetNumChannels());
1854}
1855
1856// Tests playing out a fake sound.
1857TEST_F(WebRtcVoiceEngineTestFake, PlaySoundclip) {
1858 static const char kZeroes[16000] = {};
1859 EXPECT_TRUE(engine_.Init(talk_base::Thread::Current()));
1860 soundclip_ = engine_.CreateSoundclip();
1861 ASSERT_TRUE(soundclip_ != NULL);
1862 EXPECT_TRUE(soundclip_->PlaySound(kZeroes, sizeof(kZeroes), 0));
1863}
1864
1865TEST_F(WebRtcVoiceEngineTestFake, MediaEngineCallbackOnError) {
1866 talk_base::scoped_ptr<ChannelErrorListener> listener;
1867 cricket::WebRtcVoiceMediaChannel* media_channel;
1868 unsigned int ssrc = 0;
1869
1870 EXPECT_TRUE(SetupEngine());
1871 EXPECT_TRUE(channel_->SetOptions(options_conference_));
1872 EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE));
1873
1874 media_channel = static_cast<cricket::WebRtcVoiceMediaChannel*>(channel_);
1875 listener.reset(new ChannelErrorListener(channel_));
1876
1877 // Test on WebRtc VoE channel.
1878 voe_.TriggerCallbackOnError(media_channel->voe_channel(),
1879 VE_SATURATION_WARNING);
1880 EXPECT_EQ(cricket::VoiceMediaChannel::ERROR_REC_DEVICE_SATURATION,
1881 listener->error());
1882 EXPECT_NE(-1, voe_.GetLocalSSRC(voe_.GetLastChannel(), ssrc));
1883 EXPECT_EQ(ssrc, listener->ssrc());
1884
1885 listener->Reset();
1886 voe_.TriggerCallbackOnError(-1, VE_TYPING_NOISE_WARNING);
1887 EXPECT_EQ(cricket::VoiceMediaChannel::ERROR_REC_TYPING_NOISE_DETECTED,
1888 listener->error());
1889 EXPECT_EQ(0U, listener->ssrc());
1890
1891 // Add another stream and test on that.
1892 ++ssrc;
1893 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(
1894 ssrc)));
1895 listener->Reset();
1896 voe_.TriggerCallbackOnError(voe_.GetLastChannel(),
1897 VE_SATURATION_WARNING);
1898 EXPECT_EQ(cricket::VoiceMediaChannel::ERROR_REC_DEVICE_SATURATION,
1899 listener->error());
1900 EXPECT_EQ(ssrc, listener->ssrc());
1901
1902 // Testing a non-existing channel.
1903 listener->Reset();
1904 voe_.TriggerCallbackOnError(voe_.GetLastChannel() + 2,
1905 VE_SATURATION_WARNING);
1906 EXPECT_EQ(0, listener->error());
1907}
1908
1909TEST_F(WebRtcVoiceEngineTestFake, TestSetPlayoutError) {
1910 EXPECT_TRUE(SetupEngine());
1911 EXPECT_TRUE(channel_->SetOptions(options_conference_));
1912 std::vector<cricket::AudioCodec> codecs;
1913 codecs.push_back(kPcmuCodec);
1914 EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1915 EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE));
1916 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
1917 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(3)));
1918 EXPECT_TRUE(channel_->SetPlayout(true));
1919 voe_.set_playout_fail_channel(voe_.GetLastChannel() - 1);
1920 EXPECT_TRUE(channel_->SetPlayout(false));
1921 EXPECT_FALSE(channel_->SetPlayout(true));
1922}
1923
1924// Test that the Registering/Unregistering with the
1925// webrtcvoiceengine works as expected
1926TEST_F(WebRtcVoiceEngineTestFake, RegisterVoiceProcessor) {
1927 EXPECT_TRUE(SetupEngine());
1928 EXPECT_TRUE(channel_->SetOptions(options_conference_));
1929 EXPECT_TRUE(channel_->AddRecvStream(
1930 cricket::StreamParams::CreateLegacy(kSsrc2)));
1931 cricket::FakeMediaProcessor vp_1;
1932 cricket::FakeMediaProcessor vp_2;
1933
1934 EXPECT_FALSE(engine_.RegisterProcessor(kSsrc2, &vp_1, cricket::MPD_TX));
1935 EXPECT_TRUE(engine_.RegisterProcessor(kSsrc2, &vp_1, cricket::MPD_RX));
1936 EXPECT_TRUE(engine_.RegisterProcessor(kSsrc2, &vp_2, cricket::MPD_RX));
1937 voe_.TriggerProcessPacket(cricket::MPD_RX);
1938 voe_.TriggerProcessPacket(cricket::MPD_TX);
1939
1940 EXPECT_TRUE(voe_.IsExternalMediaProcessorRegistered());
1941 EXPECT_EQ(1, vp_1.voice_frame_count());
1942 EXPECT_EQ(1, vp_2.voice_frame_count());
1943
1944 EXPECT_TRUE(engine_.UnregisterProcessor(kSsrc2,
1945 &vp_2,
1946 cricket::MPD_RX));
1947 voe_.TriggerProcessPacket(cricket::MPD_RX);
1948 EXPECT_TRUE(voe_.IsExternalMediaProcessorRegistered());
1949 EXPECT_EQ(1, vp_2.voice_frame_count());
1950 EXPECT_EQ(2, vp_1.voice_frame_count());
1951
1952 EXPECT_TRUE(engine_.UnregisterProcessor(kSsrc2,
1953 &vp_1,
1954 cricket::MPD_RX));
1955 voe_.TriggerProcessPacket(cricket::MPD_RX);
1956 EXPECT_FALSE(voe_.IsExternalMediaProcessorRegistered());
1957 EXPECT_EQ(2, vp_1.voice_frame_count());
1958
1959 EXPECT_FALSE(engine_.RegisterProcessor(kSsrc1, &vp_1, cricket::MPD_RX));
1960 EXPECT_TRUE(engine_.RegisterProcessor(kSsrc1, &vp_1, cricket::MPD_TX));
1961 voe_.TriggerProcessPacket(cricket::MPD_RX);
1962 voe_.TriggerProcessPacket(cricket::MPD_TX);
1963 EXPECT_TRUE(voe_.IsExternalMediaProcessorRegistered());
1964 EXPECT_EQ(3, vp_1.voice_frame_count());
1965
1966 EXPECT_TRUE(engine_.UnregisterProcessor(kSsrc1,
1967 &vp_1,
1968 cricket::MPD_RX_AND_TX));
1969 voe_.TriggerProcessPacket(cricket::MPD_TX);
1970 EXPECT_FALSE(voe_.IsExternalMediaProcessorRegistered());
1971 EXPECT_EQ(3, vp_1.voice_frame_count());
1972 EXPECT_TRUE(channel_->RemoveRecvStream(kSsrc2));
1973 EXPECT_FALSE(engine_.RegisterProcessor(kSsrc2, &vp_1, cricket::MPD_RX));
1974 EXPECT_FALSE(voe_.IsExternalMediaProcessorRegistered());
1975
1976 // Test that we can register a processor on the receive channel on SSRC 0.
1977 // This tests the 1:1 case when the receive SSRC is unknown.
1978 EXPECT_TRUE(engine_.RegisterProcessor(0, &vp_1, cricket::MPD_RX));
1979 voe_.TriggerProcessPacket(cricket::MPD_RX);
1980 EXPECT_TRUE(voe_.IsExternalMediaProcessorRegistered());
1981 EXPECT_EQ(4, vp_1.voice_frame_count());
1982 EXPECT_TRUE(engine_.UnregisterProcessor(0,
1983 &vp_1,
1984 cricket::MPD_RX));
1985
1986 // The following tests test that FindChannelNumFromSsrc is doing
1987 // what we expect.
1988 // pick an invalid ssrc and make sure we can't register
1989 EXPECT_FALSE(engine_.RegisterProcessor(99,
1990 &vp_1,
1991 cricket::MPD_RX));
1992 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1)));
1993 EXPECT_TRUE(engine_.RegisterProcessor(1,
1994 &vp_1,
1995 cricket::MPD_RX));
1996 EXPECT_TRUE(engine_.UnregisterProcessor(1,
1997 &vp_1,
1998 cricket::MPD_RX));
1999 EXPECT_FALSE(engine_.RegisterProcessor(1,
2000 &vp_1,
2001 cricket::MPD_TX));
2002 EXPECT_TRUE(channel_->RemoveRecvStream(1));
2003}
2004
2005TEST_F(WebRtcVoiceEngineTestFake, SetAudioOptions) {
2006 EXPECT_TRUE(SetupEngine());
2007
2008 bool ec_enabled;
2009 webrtc::EcModes ec_mode;
2010 bool ec_metrics_enabled;
2011 webrtc::AecmModes aecm_mode;
2012 bool cng_enabled;
2013 bool agc_enabled;
2014 webrtc::AgcModes agc_mode;
2015 webrtc::AgcConfig agc_config;
2016 bool ns_enabled;
2017 webrtc::NsModes ns_mode;
2018 bool highpass_filter_enabled;
2019 bool stereo_swapping_enabled;
2020 bool typing_detection_enabled;
2021 voe_.GetEcStatus(ec_enabled, ec_mode);
2022 voe_.GetEcMetricsStatus(ec_metrics_enabled);
2023 voe_.GetAecmMode(aecm_mode, cng_enabled);
2024 voe_.GetAgcStatus(agc_enabled, agc_mode);
2025 voe_.GetAgcConfig(agc_config);
2026 voe_.GetNsStatus(ns_enabled, ns_mode);
2027 highpass_filter_enabled = voe_.IsHighPassFilterEnabled();
2028 stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled();
2029 voe_.GetTypingDetectionStatus(typing_detection_enabled);
2030 EXPECT_TRUE(ec_enabled);
2031 EXPECT_TRUE(ec_metrics_enabled);
2032 EXPECT_FALSE(cng_enabled);
2033 EXPECT_TRUE(agc_enabled);
2034 EXPECT_EQ(0, agc_config.targetLeveldBOv);
2035 EXPECT_TRUE(ns_enabled);
2036 EXPECT_TRUE(highpass_filter_enabled);
2037 EXPECT_FALSE(stereo_swapping_enabled);
2038 EXPECT_TRUE(typing_detection_enabled);
2039 EXPECT_EQ(ec_mode, webrtc::kEcConference);
2040 EXPECT_EQ(ns_mode, webrtc::kNsHighSuppression);
2041
2042 // Nothing set, so all ignored.
2043 cricket::AudioOptions options;
2044 ASSERT_TRUE(engine_.SetAudioOptions(options));
2045 voe_.GetEcStatus(ec_enabled, ec_mode);
2046 voe_.GetEcMetricsStatus(ec_metrics_enabled);
2047 voe_.GetAecmMode(aecm_mode, cng_enabled);
2048 voe_.GetAgcStatus(agc_enabled, agc_mode);
2049 voe_.GetAgcConfig(agc_config);
2050 voe_.GetNsStatus(ns_enabled, ns_mode);
2051 highpass_filter_enabled = voe_.IsHighPassFilterEnabled();
2052 stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled();
2053 voe_.GetTypingDetectionStatus(typing_detection_enabled);
2054 EXPECT_TRUE(ec_enabled);
2055 EXPECT_TRUE(ec_metrics_enabled);
2056 EXPECT_FALSE(cng_enabled);
2057 EXPECT_TRUE(agc_enabled);
2058 EXPECT_EQ(0, agc_config.targetLeveldBOv);
2059 EXPECT_TRUE(ns_enabled);
2060 EXPECT_TRUE(highpass_filter_enabled);
2061 EXPECT_FALSE(stereo_swapping_enabled);
2062 EXPECT_TRUE(typing_detection_enabled);
2063 EXPECT_EQ(ec_mode, webrtc::kEcConference);
2064 EXPECT_EQ(ns_mode, webrtc::kNsHighSuppression);
2065
2066 // Turn echo cancellation off
2067 options.echo_cancellation.Set(false);
2068 ASSERT_TRUE(engine_.SetAudioOptions(options));
2069 voe_.GetEcStatus(ec_enabled, ec_mode);
2070 EXPECT_FALSE(ec_enabled);
2071
2072 // Turn echo cancellation back on, with settings, and make sure
2073 // nothing else changed.
2074 options.echo_cancellation.Set(true);
2075 ASSERT_TRUE(engine_.SetAudioOptions(options));
2076 voe_.GetEcStatus(ec_enabled, ec_mode);
2077 voe_.GetEcMetricsStatus(ec_metrics_enabled);
2078 voe_.GetAecmMode(aecm_mode, cng_enabled);
2079 voe_.GetAgcStatus(agc_enabled, agc_mode);
2080 voe_.GetAgcConfig(agc_config);
2081 voe_.GetNsStatus(ns_enabled, ns_mode);
2082 highpass_filter_enabled = voe_.IsHighPassFilterEnabled();
2083 stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled();
2084 voe_.GetTypingDetectionStatus(typing_detection_enabled);
2085 EXPECT_TRUE(ec_enabled);
2086 EXPECT_TRUE(ec_metrics_enabled);
2087 EXPECT_TRUE(agc_enabled);
2088 EXPECT_EQ(0, agc_config.targetLeveldBOv);
2089 EXPECT_TRUE(ns_enabled);
2090 EXPECT_TRUE(highpass_filter_enabled);
2091 EXPECT_FALSE(stereo_swapping_enabled);
2092 EXPECT_TRUE(typing_detection_enabled);
2093 EXPECT_EQ(ec_mode, webrtc::kEcConference);
2094 EXPECT_EQ(ns_mode, webrtc::kNsHighSuppression);
2095
2096 // Turn off AGC
2097 options.auto_gain_control.Set(false);
2098 ASSERT_TRUE(engine_.SetAudioOptions(options));
2099 voe_.GetAgcStatus(agc_enabled, agc_mode);
2100 EXPECT_FALSE(agc_enabled);
2101
2102 // Turn AGC back on
2103 options.auto_gain_control.Set(true);
2104 options.adjust_agc_delta.Clear();
2105 ASSERT_TRUE(engine_.SetAudioOptions(options));
2106 voe_.GetAgcStatus(agc_enabled, agc_mode);
2107 EXPECT_TRUE(agc_enabled);
2108 voe_.GetAgcConfig(agc_config);
2109 EXPECT_EQ(0, agc_config.targetLeveldBOv);
2110
2111 // Turn off other options (and stereo swapping on).
2112 options.noise_suppression.Set(false);
2113 options.highpass_filter.Set(false);
2114 options.typing_detection.Set(false);
2115 options.stereo_swapping.Set(true);
2116 ASSERT_TRUE(engine_.SetAudioOptions(options));
2117 voe_.GetNsStatus(ns_enabled, ns_mode);
2118 highpass_filter_enabled = voe_.IsHighPassFilterEnabled();
2119 stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled();
2120 voe_.GetTypingDetectionStatus(typing_detection_enabled);
2121 EXPECT_FALSE(ns_enabled);
2122 EXPECT_FALSE(highpass_filter_enabled);
2123 EXPECT_FALSE(typing_detection_enabled);
2124 EXPECT_TRUE(stereo_swapping_enabled);
2125
2126 // Turn on "conference mode" to ensure it has no impact.
2127 options.conference_mode.Set(true);
2128 ASSERT_TRUE(engine_.SetAudioOptions(options));
2129 voe_.GetEcStatus(ec_enabled, ec_mode);
2130 voe_.GetNsStatus(ns_enabled, ns_mode);
2131 EXPECT_TRUE(ec_enabled);
2132 EXPECT_EQ(webrtc::kEcConference, ec_mode);
2133 EXPECT_FALSE(ns_enabled);
2134 EXPECT_EQ(webrtc::kNsHighSuppression, ns_mode);
2135}
2136
2137TEST_F(WebRtcVoiceEngineTestFake, SetOptions) {
2138 EXPECT_TRUE(SetupEngine());
2139
2140 bool ec_enabled;
2141 webrtc::EcModes ec_mode;
2142 bool ec_metrics_enabled;
2143 bool agc_enabled;
2144 webrtc::AgcModes agc_mode;
2145 bool ns_enabled;
2146 webrtc::NsModes ns_mode;
2147 bool highpass_filter_enabled;
2148 bool stereo_swapping_enabled;
2149 bool typing_detection_enabled;
2150
2151 ASSERT_TRUE(engine_.SetOptions(0));
2152 voe_.GetEcStatus(ec_enabled, ec_mode);
2153 voe_.GetEcMetricsStatus(ec_metrics_enabled);
2154 voe_.GetAgcStatus(agc_enabled, agc_mode);
2155 voe_.GetNsStatus(ns_enabled, ns_mode);
2156 highpass_filter_enabled = voe_.IsHighPassFilterEnabled();
2157 stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled();
2158 voe_.GetTypingDetectionStatus(typing_detection_enabled);
2159 EXPECT_FALSE(ec_enabled);
2160 EXPECT_FALSE(agc_enabled);
2161 EXPECT_FALSE(ns_enabled);
2162 EXPECT_FALSE(highpass_filter_enabled);
2163 EXPECT_FALSE(stereo_swapping_enabled);
2164 EXPECT_TRUE(typing_detection_enabled);
2165
2166 ASSERT_TRUE(engine_.SetOptions(
2167 cricket::MediaEngineInterface::ECHO_CANCELLATION));
2168 voe_.GetEcStatus(ec_enabled, ec_mode);
2169 voe_.GetEcMetricsStatus(ec_metrics_enabled);
2170 voe_.GetAgcStatus(agc_enabled, agc_mode);
2171 voe_.GetNsStatus(ns_enabled, ns_mode);
2172 highpass_filter_enabled = voe_.IsHighPassFilterEnabled();
2173 stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled();
2174 voe_.GetTypingDetectionStatus(typing_detection_enabled);
2175 EXPECT_TRUE(ec_enabled);
2176 EXPECT_FALSE(agc_enabled);
2177 EXPECT_FALSE(ns_enabled);
2178 EXPECT_FALSE(highpass_filter_enabled);
2179 EXPECT_FALSE(stereo_swapping_enabled);
2180 EXPECT_TRUE(typing_detection_enabled);
2181
2182 ASSERT_TRUE(engine_.SetOptions(
2183 cricket::MediaEngineInterface::AUTO_GAIN_CONTROL));
2184 voe_.GetEcStatus(ec_enabled, ec_mode);
2185 voe_.GetEcMetricsStatus(ec_metrics_enabled);
2186 voe_.GetAgcStatus(agc_enabled, agc_mode);
2187 voe_.GetNsStatus(ns_enabled, ns_mode);
2188 highpass_filter_enabled = voe_.IsHighPassFilterEnabled();
2189 stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled();
2190 voe_.GetTypingDetectionStatus(typing_detection_enabled);
2191 EXPECT_FALSE(ec_enabled);
2192 EXPECT_TRUE(agc_enabled);
2193 EXPECT_FALSE(ns_enabled);
2194 EXPECT_FALSE(highpass_filter_enabled);
2195 EXPECT_FALSE(stereo_swapping_enabled);
2196 EXPECT_TRUE(typing_detection_enabled);
2197
2198 ASSERT_TRUE(engine_.SetOptions(
2199 cricket::MediaEngineInterface::NOISE_SUPPRESSION));
2200 voe_.GetEcStatus(ec_enabled, ec_mode);
2201 voe_.GetEcMetricsStatus(ec_metrics_enabled);
2202 voe_.GetAgcStatus(agc_enabled, agc_mode);
2203 voe_.GetNsStatus(ns_enabled, ns_mode);
2204 highpass_filter_enabled = voe_.IsHighPassFilterEnabled();
2205 stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled();
2206 voe_.GetTypingDetectionStatus(typing_detection_enabled);
2207 EXPECT_FALSE(ec_enabled);
2208 EXPECT_FALSE(agc_enabled);
2209 EXPECT_TRUE(ns_enabled);
2210 EXPECT_FALSE(highpass_filter_enabled);
2211 EXPECT_FALSE(stereo_swapping_enabled);
2212 EXPECT_TRUE(typing_detection_enabled);
2213
2214 ASSERT_TRUE(engine_.SetOptions(
2215 cricket::MediaEngineInterface::HIGHPASS_FILTER));
2216 voe_.GetEcStatus(ec_enabled, ec_mode);
2217 voe_.GetEcMetricsStatus(ec_metrics_enabled);
2218 voe_.GetAgcStatus(agc_enabled, agc_mode);
2219 voe_.GetNsStatus(ns_enabled, ns_mode);
2220 highpass_filter_enabled = voe_.IsHighPassFilterEnabled();
2221 stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled();
2222 voe_.GetTypingDetectionStatus(typing_detection_enabled);
2223 EXPECT_FALSE(ec_enabled);
2224 EXPECT_FALSE(agc_enabled);
2225 EXPECT_FALSE(ns_enabled);
2226 EXPECT_TRUE(highpass_filter_enabled);
2227 EXPECT_FALSE(stereo_swapping_enabled);
2228 EXPECT_TRUE(typing_detection_enabled);
2229
2230 ASSERT_TRUE(engine_.SetOptions(
2231 cricket::MediaEngineInterface::STEREO_FLIPPING));
2232 voe_.GetEcStatus(ec_enabled, ec_mode);
2233 voe_.GetEcMetricsStatus(ec_metrics_enabled);
2234 voe_.GetAgcStatus(agc_enabled, agc_mode);
2235 voe_.GetNsStatus(ns_enabled, ns_mode);
2236 highpass_filter_enabled = voe_.IsHighPassFilterEnabled();
2237 stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled();
2238 voe_.GetTypingDetectionStatus(typing_detection_enabled);
2239 EXPECT_FALSE(ec_enabled);
2240 EXPECT_FALSE(agc_enabled);
2241 EXPECT_FALSE(ns_enabled);
2242 EXPECT_FALSE(highpass_filter_enabled);
2243 EXPECT_TRUE(stereo_swapping_enabled);
2244 EXPECT_TRUE(typing_detection_enabled);
2245
2246 ASSERT_TRUE(engine_.SetOptions(
2247 cricket::MediaEngineInterface::DEFAULT_AUDIO_OPTIONS));
2248 voe_.GetEcStatus(ec_enabled, ec_mode);
2249 voe_.GetEcMetricsStatus(ec_metrics_enabled);
2250 voe_.GetAgcStatus(agc_enabled, agc_mode);
2251 voe_.GetNsStatus(ns_enabled, ns_mode);
2252 highpass_filter_enabled = voe_.IsHighPassFilterEnabled();
2253 stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled();
2254 voe_.GetTypingDetectionStatus(typing_detection_enabled);
2255 EXPECT_TRUE(ec_enabled);
2256 EXPECT_TRUE(agc_enabled);
2257 EXPECT_TRUE(ns_enabled);
2258 EXPECT_TRUE(highpass_filter_enabled);
2259 EXPECT_FALSE(stereo_swapping_enabled);
2260 EXPECT_TRUE(typing_detection_enabled);
2261
2262 ASSERT_TRUE(engine_.SetOptions(
2263 cricket::MediaEngineInterface::ALL_AUDIO_OPTIONS));
2264 voe_.GetEcStatus(ec_enabled, ec_mode);
2265 voe_.GetEcMetricsStatus(ec_metrics_enabled);
2266 voe_.GetAgcStatus(agc_enabled, agc_mode);
2267 voe_.GetNsStatus(ns_enabled, ns_mode);
2268 highpass_filter_enabled = voe_.IsHighPassFilterEnabled();
2269 stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled();
2270 voe_.GetTypingDetectionStatus(typing_detection_enabled);
2271 EXPECT_TRUE(ec_enabled);
2272 EXPECT_TRUE(agc_enabled);
2273 EXPECT_TRUE(ns_enabled);
2274 EXPECT_TRUE(highpass_filter_enabled);
2275 EXPECT_TRUE(stereo_swapping_enabled);
2276 EXPECT_TRUE(typing_detection_enabled);
2277}
2278
2279TEST_F(WebRtcVoiceEngineTestFake, InitDoesNotOverwriteDefaultAgcConfig) {
2280 webrtc::AgcConfig set_config = {0};
2281 set_config.targetLeveldBOv = 3;
2282 set_config.digitalCompressionGaindB = 9;
2283 set_config.limiterEnable = true;
2284 EXPECT_EQ(0, voe_.SetAgcConfig(set_config));
2285 EXPECT_TRUE(engine_.Init(talk_base::Thread::Current()));
2286
2287 webrtc::AgcConfig config = {0};
2288 EXPECT_EQ(0, voe_.GetAgcConfig(config));
2289 EXPECT_EQ(set_config.targetLeveldBOv, config.targetLeveldBOv);
2290 EXPECT_EQ(set_config.digitalCompressionGaindB,
2291 config.digitalCompressionGaindB);
2292 EXPECT_EQ(set_config.limiterEnable, config.limiterEnable);
2293}
2294
2295
2296TEST_F(WebRtcVoiceEngineTestFake, SetOptionOverridesViaChannels) {
2297 EXPECT_TRUE(SetupEngine());
2298 talk_base::scoped_ptr<cricket::VoiceMediaChannel> channel1(
2299 engine_.CreateChannel());
2300 talk_base::scoped_ptr<cricket::VoiceMediaChannel> channel2(
2301 engine_.CreateChannel());
2302
2303 // Have to add a stream to make SetSend work.
2304 cricket::StreamParams stream1;
2305 stream1.ssrcs.push_back(1);
2306 channel1->AddSendStream(stream1);
2307 cricket::StreamParams stream2;
2308 stream2.ssrcs.push_back(2);
2309 channel2->AddSendStream(stream2);
2310
2311 // AEC and AGC and NS
2312 cricket::AudioOptions options_all;
2313 options_all.echo_cancellation.Set(true);
2314 options_all.auto_gain_control.Set(true);
2315 options_all.noise_suppression.Set(true);
2316
2317 ASSERT_TRUE(channel1->SetOptions(options_all));
2318 cricket::AudioOptions expected_options = options_all;
2319 cricket::AudioOptions actual_options;
2320 ASSERT_TRUE(channel1->GetOptions(&actual_options));
2321 EXPECT_EQ(expected_options, actual_options);
2322 ASSERT_TRUE(channel2->SetOptions(options_all));
2323 ASSERT_TRUE(channel2->GetOptions(&actual_options));
2324 EXPECT_EQ(expected_options, actual_options);
2325
2326 // unset NS
2327 cricket::AudioOptions options_no_ns;
2328 options_no_ns.noise_suppression.Set(false);
2329 ASSERT_TRUE(channel1->SetOptions(options_no_ns));
2330
2331 expected_options.echo_cancellation.Set(true);
2332 expected_options.auto_gain_control.Set(true);
2333 expected_options.noise_suppression.Set(false);
2334 ASSERT_TRUE(channel1->GetOptions(&actual_options));
2335 EXPECT_EQ(expected_options, actual_options);
2336
2337 // unset AGC
2338 cricket::AudioOptions options_no_agc;
2339 options_no_agc.auto_gain_control.Set(false);
2340 ASSERT_TRUE(channel2->SetOptions(options_no_agc));
2341
2342 expected_options.echo_cancellation.Set(true);
2343 expected_options.auto_gain_control.Set(false);
2344 expected_options.noise_suppression.Set(true);
2345 ASSERT_TRUE(channel2->GetOptions(&actual_options));
2346 EXPECT_EQ(expected_options, actual_options);
2347
2348 ASSERT_TRUE(engine_.SetAudioOptions(options_all));
2349 bool ec_enabled;
2350 webrtc::EcModes ec_mode;
2351 bool agc_enabled;
2352 webrtc::AgcModes agc_mode;
2353 bool ns_enabled;
2354 webrtc::NsModes ns_mode;
2355 voe_.GetEcStatus(ec_enabled, ec_mode);
2356 voe_.GetAgcStatus(agc_enabled, agc_mode);
2357 voe_.GetNsStatus(ns_enabled, ns_mode);
2358 EXPECT_TRUE(ec_enabled);
2359 EXPECT_TRUE(agc_enabled);
2360 EXPECT_TRUE(ns_enabled);
2361
2362 channel1->SetSend(cricket::SEND_MICROPHONE);
2363 voe_.GetEcStatus(ec_enabled, ec_mode);
2364 voe_.GetAgcStatus(agc_enabled, agc_mode);
2365 voe_.GetNsStatus(ns_enabled, ns_mode);
2366 EXPECT_TRUE(ec_enabled);
2367 EXPECT_TRUE(agc_enabled);
2368 EXPECT_FALSE(ns_enabled);
2369
2370 channel1->SetSend(cricket::SEND_NOTHING);
2371 voe_.GetEcStatus(ec_enabled, ec_mode);
2372 voe_.GetAgcStatus(agc_enabled, agc_mode);
2373 voe_.GetNsStatus(ns_enabled, ns_mode);
2374 EXPECT_TRUE(ec_enabled);
2375 EXPECT_TRUE(agc_enabled);
2376 EXPECT_TRUE(ns_enabled);
2377
2378 channel2->SetSend(cricket::SEND_MICROPHONE);
2379 voe_.GetEcStatus(ec_enabled, ec_mode);
2380 voe_.GetAgcStatus(agc_enabled, agc_mode);
2381 voe_.GetNsStatus(ns_enabled, ns_mode);
2382 EXPECT_TRUE(ec_enabled);
2383 EXPECT_FALSE(agc_enabled);
2384 EXPECT_TRUE(ns_enabled);
2385
2386 channel2->SetSend(cricket::SEND_NOTHING);
2387 voe_.GetEcStatus(ec_enabled, ec_mode);
2388 voe_.GetAgcStatus(agc_enabled, agc_mode);
2389 voe_.GetNsStatus(ns_enabled, ns_mode);
2390 EXPECT_TRUE(ec_enabled);
2391 EXPECT_TRUE(agc_enabled);
2392 EXPECT_TRUE(ns_enabled);
2393
2394 // Make sure settings take effect while we are sending.
2395 ASSERT_TRUE(engine_.SetAudioOptions(options_all));
2396 cricket::AudioOptions options_no_agc_nor_ns;
2397 options_no_agc_nor_ns.auto_gain_control.Set(false);
2398 options_no_agc_nor_ns.noise_suppression.Set(false);
2399 channel2->SetSend(cricket::SEND_MICROPHONE);
2400 channel2->SetOptions(options_no_agc_nor_ns);
2401
2402 expected_options.echo_cancellation.Set(true);
2403 expected_options.auto_gain_control.Set(false);
2404 expected_options.noise_suppression.Set(false);
2405 ASSERT_TRUE(channel2->GetOptions(&actual_options));
2406 EXPECT_EQ(expected_options, actual_options);
2407 voe_.GetEcStatus(ec_enabled, ec_mode);
2408 voe_.GetAgcStatus(agc_enabled, agc_mode);
2409 voe_.GetNsStatus(ns_enabled, ns_mode);
2410 EXPECT_TRUE(ec_enabled);
2411 EXPECT_FALSE(agc_enabled);
2412 EXPECT_FALSE(ns_enabled);
2413}
2414
2415// Test that GetReceiveChannelNum returns the default channel for the first
2416// recv stream in 1-1 calls.
2417TEST_F(WebRtcVoiceEngineTestFake, TestGetReceiveChannelNumIn1To1Calls) {
2418 EXPECT_TRUE(SetupEngine());
2419 cricket::WebRtcVoiceMediaChannel* media_channel =
2420 static_cast<cricket::WebRtcVoiceMediaChannel*>(channel_);
2421 // Test that GetChannelNum returns the default channel if the SSRC is unknown.
2422 EXPECT_EQ(media_channel->voe_channel(),
2423 media_channel->GetReceiveChannelNum(0));
2424 cricket::StreamParams stream;
2425 stream.ssrcs.push_back(kSsrc2);
2426 EXPECT_TRUE(channel_->AddRecvStream(stream));
2427 EXPECT_EQ(media_channel->voe_channel(),
2428 media_channel->GetReceiveChannelNum(kSsrc2));
2429}
2430
2431// Test that GetReceiveChannelNum doesn't return the default channel for the
2432// first recv stream in conference calls.
2433TEST_F(WebRtcVoiceEngineTestFake, TestGetChannelNumInConferenceCalls) {
2434 EXPECT_TRUE(SetupEngine());
2435 EXPECT_TRUE(channel_->SetOptions(options_conference_));
2436 cricket::StreamParams stream;
2437 stream.ssrcs.push_back(kSsrc2);
2438 EXPECT_TRUE(channel_->AddRecvStream(stream));
2439 cricket::WebRtcVoiceMediaChannel* media_channel =
2440 static_cast<cricket::WebRtcVoiceMediaChannel*>(channel_);
2441 EXPECT_LT(media_channel->voe_channel(),
2442 media_channel->GetReceiveChannelNum(kSsrc2));
2443}
2444
2445TEST_F(WebRtcVoiceEngineTestFake, SetOutputScaling) {
2446 EXPECT_TRUE(SetupEngine());
2447 double left, right;
2448 EXPECT_TRUE(channel_->SetOutputScaling(0, 1, 2));
2449 EXPECT_TRUE(channel_->GetOutputScaling(0, &left, &right));
2450 EXPECT_DOUBLE_EQ(1, left);
2451 EXPECT_DOUBLE_EQ(2, right);
2452
2453 EXPECT_FALSE(channel_->SetOutputScaling(kSsrc2, 1, 2));
2454 cricket::StreamParams stream;
2455 stream.ssrcs.push_back(kSsrc2);
2456 EXPECT_TRUE(channel_->AddRecvStream(stream));
2457
2458 EXPECT_TRUE(channel_->SetOutputScaling(kSsrc2, 2, 1));
2459 EXPECT_TRUE(channel_->GetOutputScaling(kSsrc2, &left, &right));
2460 EXPECT_DOUBLE_EQ(2, left);
2461 EXPECT_DOUBLE_EQ(1, right);
2462}
2463
2464
2465// Tests for the actual WebRtc VoE library.
2466
2467// Tests that the library initializes and shuts down properly.
2468TEST(WebRtcVoiceEngineTest, StartupShutdown) {
2469 cricket::WebRtcVoiceEngine engine;
2470 EXPECT_TRUE(engine.Init(talk_base::Thread::Current()));
2471 cricket::VoiceMediaChannel* channel = engine.CreateChannel();
2472 EXPECT_TRUE(channel != NULL);
2473 delete channel;
2474 engine.Terminate();
2475
2476 // Reinit to catch regression where VoiceEngineObserver reference is lost
2477 EXPECT_TRUE(engine.Init(talk_base::Thread::Current()));
2478 engine.Terminate();
2479}
2480
2481// Tests that the logging from the library is cleartext.
2482TEST(WebRtcVoiceEngineTest, DISABLED_HasUnencryptedLogging) {
2483 cricket::WebRtcVoiceEngine engine;
2484 talk_base::scoped_ptr<talk_base::MemoryStream> stream(
2485 new talk_base::MemoryStream);
2486 size_t size = 0;
2487 bool cleartext = true;
2488 talk_base::LogMessage::AddLogToStream(stream.get(), talk_base::LS_VERBOSE);
2489 engine.SetLogging(talk_base::LS_VERBOSE, "");
2490 EXPECT_TRUE(engine.Init(talk_base::Thread::Current()));
2491 EXPECT_TRUE(stream->GetSize(&size));
2492 EXPECT_GT(size, 0U);
2493 engine.Terminate();
2494 talk_base::LogMessage::RemoveLogToStream(stream.get());
2495 const char* buf = stream->GetBuffer();
2496 for (size_t i = 0; i < size && cleartext; ++i) {
2497 int ch = static_cast<int>(buf[i]);
2498 ASSERT_GE(ch, 0) << "Out of bounds character in WebRtc VoE log: "
2499 << std::hex << ch;
2500 cleartext = (isprint(ch) || isspace(ch));
2501 }
2502 EXPECT_TRUE(cleartext);
2503}
2504
2505// Tests we do not see any references to a monitor thread being spun up
2506// when initiating the engine.
2507TEST(WebRtcVoiceEngineTest, HasNoMonitorThread) {
2508 cricket::WebRtcVoiceEngine engine;
2509 talk_base::scoped_ptr<talk_base::MemoryStream> stream(
2510 new talk_base::MemoryStream);
2511 talk_base::LogMessage::AddLogToStream(stream.get(), talk_base::LS_VERBOSE);
2512 engine.SetLogging(talk_base::LS_VERBOSE, "");
2513 EXPECT_TRUE(engine.Init(talk_base::Thread::Current()));
2514 engine.Terminate();
2515 talk_base::LogMessage::RemoveLogToStream(stream.get());
2516
2517 size_t size = 0;
2518 EXPECT_TRUE(stream->GetSize(&size));
2519 EXPECT_GT(size, 0U);
2520 const std::string logs(stream->GetBuffer());
2521 EXPECT_NE(std::string::npos, logs.find("ProcessThread"));
2522}
2523
2524// Tests that the library is configured with the codecs we want.
2525TEST(WebRtcVoiceEngineTest, HasCorrectCodecs) {
2526 cricket::WebRtcVoiceEngine engine;
2527 // Check codecs by name.
2528 EXPECT_TRUE(engine.FindCodec(
2529 cricket::AudioCodec(96, "OPUS", 48000, 0, 2, 0)));
2530 EXPECT_TRUE(engine.FindCodec(
2531 cricket::AudioCodec(96, "ISAC", 16000, 0, 1, 0)));
2532 EXPECT_TRUE(engine.FindCodec(
2533 cricket::AudioCodec(96, "ISAC", 32000, 0, 1, 0)));
2534 // Check that name matching is case-insensitive.
2535 EXPECT_TRUE(engine.FindCodec(
2536 cricket::AudioCodec(96, "ILBC", 8000, 0, 1, 0)));
2537 EXPECT_TRUE(engine.FindCodec(
2538 cricket::AudioCodec(96, "iLBC", 8000, 0, 1, 0)));
2539 EXPECT_TRUE(engine.FindCodec(
2540 cricket::AudioCodec(96, "PCMU", 8000, 0, 1, 0)));
2541 EXPECT_TRUE(engine.FindCodec(
2542 cricket::AudioCodec(96, "PCMA", 8000, 0, 1, 0)));
2543 EXPECT_TRUE(engine.FindCodec(
2544 cricket::AudioCodec(96, "G722", 16000, 0, 1, 0)));
2545 EXPECT_TRUE(engine.FindCodec(
2546 cricket::AudioCodec(96, "red", 8000, 0, 1, 0)));
2547 EXPECT_TRUE(engine.FindCodec(
2548 cricket::AudioCodec(96, "CN", 48000, 0, 1, 0)));
2549 EXPECT_TRUE(engine.FindCodec(
2550 cricket::AudioCodec(96, "CN", 32000, 0, 1, 0)));
2551 EXPECT_TRUE(engine.FindCodec(
2552 cricket::AudioCodec(96, "CN", 16000, 0, 1, 0)));
2553 EXPECT_TRUE(engine.FindCodec(
2554 cricket::AudioCodec(96, "CN", 8000, 0, 1, 0)));
2555 EXPECT_TRUE(engine.FindCodec(
2556 cricket::AudioCodec(96, "telephone-event", 8000, 0, 1, 0)));
2557 // Check codecs with an id by id.
2558 EXPECT_TRUE(engine.FindCodec(
2559 cricket::AudioCodec(0, "", 8000, 0, 1, 0))); // PCMU
2560 EXPECT_TRUE(engine.FindCodec(
2561 cricket::AudioCodec(8, "", 8000, 0, 1, 0))); // PCMA
2562 EXPECT_TRUE(engine.FindCodec(
2563 cricket::AudioCodec(9, "", 16000, 0, 1, 0))); // G722
2564 EXPECT_TRUE(engine.FindCodec(
2565 cricket::AudioCodec(13, "", 8000, 0, 1, 0))); // CN
2566 // Check sample/bitrate matching.
2567 EXPECT_TRUE(engine.FindCodec(
2568 cricket::AudioCodec(0, "PCMU", 8000, 64000, 1, 0)));
2569 // Check that bad codecs fail.
2570 EXPECT_FALSE(engine.FindCodec(cricket::AudioCodec(99, "ABCD", 0, 0, 1, 0)));
2571 EXPECT_FALSE(engine.FindCodec(cricket::AudioCodec(88, "", 0, 0, 1, 0)));
2572 EXPECT_FALSE(engine.FindCodec(cricket::AudioCodec(0, "", 0, 0, 2, 0)));
2573 EXPECT_FALSE(engine.FindCodec(cricket::AudioCodec(0, "", 5000, 0, 1, 0)));
2574 EXPECT_FALSE(engine.FindCodec(cricket::AudioCodec(0, "", 0, 5000, 1, 0)));
2575 // Check that there aren't any extra codecs lying around.
2576 EXPECT_EQ(13U, engine.codecs().size());
2577 // Verify the payload id of common audio codecs, including CN, ISAC, and G722.
2578 for (std::vector<cricket::AudioCodec>::const_iterator it =
2579 engine.codecs().begin(); it != engine.codecs().end(); ++it) {
2580 if (it->name == "CN" && it->clockrate == 16000) {
2581 EXPECT_EQ(105, it->id);
2582 } else if (it->name == "CN" && it->clockrate == 32000) {
2583 EXPECT_EQ(106, it->id);
2584 } else if (it->name == "ISAC" && it->clockrate == 16000) {
2585 EXPECT_EQ(103, it->id);
2586 } else if (it->name == "ISAC" && it->clockrate == 32000) {
2587 EXPECT_EQ(104, it->id);
2588 } else if (it->name == "G722" && it->clockrate == 16000) {
2589 EXPECT_EQ(9, it->id);
2590 } else if (it->name == "telephone-event") {
2591 EXPECT_EQ(126, it->id);
2592 } else if (it->name == "red") {
2593 EXPECT_EQ(127, it->id);
2594 } else if (it->name == "opus") {
2595 EXPECT_EQ(111, it->id);
2596 ASSERT_NE(it->params.find("minptime"), it->params.end());
2597 EXPECT_EQ("10", it->params.find("minptime")->second);
2598 ASSERT_NE(it->params.find("maxptime"), it->params.end());
2599 EXPECT_EQ("60", it->params.find("maxptime")->second);
2600 }
2601 }
2602
2603 engine.Terminate();
2604}
2605
2606// Tests that VoE supports at least 32 channels
2607TEST(WebRtcVoiceEngineTest, Has32Channels) {
2608 cricket::WebRtcVoiceEngine engine;
2609 EXPECT_TRUE(engine.Init(talk_base::Thread::Current()));
2610
2611 cricket::VoiceMediaChannel* channels[32];
2612 int num_channels = 0;
2613
2614 while (num_channels < ARRAY_SIZE(channels)) {
2615 cricket::VoiceMediaChannel* channel = engine.CreateChannel();
2616 if (!channel)
2617 break;
2618
2619 channels[num_channels++] = channel;
2620 }
2621
2622 int expected = ARRAY_SIZE(channels);
2623 EXPECT_EQ(expected, num_channels);
2624
2625 while (num_channels > 0) {
2626 delete channels[--num_channels];
2627 }
2628
2629 engine.Terminate();
2630}
2631
2632// Test that we set our preferred codecs properly.
2633TEST(WebRtcVoiceEngineTest, SetRecvCodecs) {
2634 cricket::WebRtcVoiceEngine engine;
2635 EXPECT_TRUE(engine.Init(talk_base::Thread::Current()));
2636 cricket::WebRtcVoiceMediaChannel channel(&engine);
2637 EXPECT_TRUE(channel.SetRecvCodecs(engine.codecs()));
2638}
2639
2640#ifdef WIN32
2641// Test our workarounds to WebRtc VoE' munging of the coinit count
2642TEST(WebRtcVoiceEngineTest, CoInitialize) {
2643 cricket::WebRtcVoiceEngine* engine = new cricket::WebRtcVoiceEngine();
2644
2645 // Initial refcount should be 0.
2646 EXPECT_EQ(S_OK, CoInitializeEx(NULL, COINIT_MULTITHREADED));
2647
2648 // Engine should start even with COM already inited.
2649 EXPECT_TRUE(engine->Init(talk_base::Thread::Current()));
2650 engine->Terminate();
2651 EXPECT_TRUE(engine->Init(talk_base::Thread::Current()));
2652 engine->Terminate();
2653
2654 // Refcount after terminate should be 1 (in reality 3); test if it is nonzero.
2655 EXPECT_EQ(S_FALSE, CoInitializeEx(NULL, COINIT_MULTITHREADED));
2656 // Decrement refcount to (hopefully) 0.
2657 CoUninitialize();
2658 CoUninitialize();
2659 delete engine;
2660
2661 // Ensure refcount is 0.
2662 EXPECT_EQ(S_OK, CoInitializeEx(NULL, COINIT_MULTITHREADED));
2663 CoUninitialize();
2664}
2665#endif
2666
2667