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