1
// Copyright 2008 Google Inc. All Rights Reserved.
3
// Author: Justin Uberti (juberti@google.com)
5
#include "talk/base/byteorder.h"
6
#include "talk/base/gunit.h"
7
#include "talk/p2p/base/fakesession.h"
8
#include "talk/session/phone/channel.h"
9
#include "talk/session/phone/fakemediaengine.h"
10
#include "talk/session/phone/fakemediaprocessor.h"
11
#include "talk/session/phone/fakertp.h"
12
#include "talk/session/phone/fakewebrtcvoiceengine.h"
13
#include "talk/session/phone/webrtcvoiceengine.h"
15
// Tests for the WebRtcVoiceEngine/VoiceChannel code.
17
static const cricket::AudioCodec kPcmuCodec(0, "PCMU", 8000, 64000, 1, 0);
18
static const cricket::AudioCodec kIsacCodec(103, "ISAC", 16000, 32000, 1, 0);
19
static const cricket::AudioCodec kRedCodec(117, "red", 8000, 0, 1, 0);
20
static const cricket::AudioCodec kCn8000Codec(13, "CN", 8000, 0, 1, 0);
21
static const cricket::AudioCodec kCn16000Codec(105, "CN", 16000, 0, 1, 0);
22
static const cricket::AudioCodec
23
kTelephoneEventCodec(106, "telephone-event", 8000, 0, 1, 0);
24
static const cricket::AudioCodec* const kAudioCodecs[] = {
25
&kPcmuCodec, &kIsacCodec, &kRedCodec, &kCn8000Codec, &kCn16000Codec,
26
&kTelephoneEventCodec,
28
const char kRingbackTone[] = "RIFF____WAVE____ABCD1234";
29
static uint32 kSsrc1 = 0x99;
31
class FakeVoEWrapper : public cricket::VoEWrapper {
33
explicit FakeVoEWrapper(cricket::FakeWebRtcVoiceEngine* engine)
34
: cricket::VoEWrapper(engine, // processing
49
class NullVoETraceWrapper : public cricket::VoETraceWrapper {
51
virtual int SetTraceFilter(const unsigned int filter) {
54
virtual int SetTraceFile(const char* fileNameUTF8) {
57
virtual int SetTraceCallback(webrtc::TraceCallback* callback) {
62
class WebRtcVoiceEngineTestFake : public testing::Test {
64
class ChannelErrorListener : public sigslot::has_slots<> {
66
explicit ChannelErrorListener(cricket::VoiceMediaChannel* channel)
67
: ssrc_(0), error_(cricket::VoiceMediaChannel::ERROR_NONE) {
68
ASSERT(channel != NULL);
69
channel->SignalMediaError.connect(
70
this, &ChannelErrorListener::OnVoiceChannelError);
72
void OnVoiceChannelError(uint32 ssrc,
73
cricket::VoiceMediaChannel::Error error) {
79
error_ = cricket::VoiceMediaChannel::ERROR_NONE;
84
cricket::VoiceMediaChannel::Error error() const {
90
cricket::VoiceMediaChannel::Error error_;
93
WebRtcVoiceEngineTestFake()
94
: voe_(kAudioCodecs, ARRAY_SIZE(kAudioCodecs)),
95
voe_sc_(kAudioCodecs, ARRAY_SIZE(kAudioCodecs)),
96
engine_(new FakeVoEWrapper(&voe_),
97
new FakeVoEWrapper(&voe_sc_),
98
new NullVoETraceWrapper()),
99
channel_(NULL), soundclip_(NULL) {
102
bool result = engine_.Init();
104
channel_ = engine_.CreateChannel();
105
result = (channel_ != NULL);
108
result = channel_->AddSendStream(
109
cricket::StreamParams::CreateLegacy(kSsrc1));
113
void DeliverPacket(const void* data, int len) {
114
talk_base::Buffer packet(data, len);
115
channel_->OnPacketReceived(&packet);
117
virtual void TearDown() {
124
cricket::FakeWebRtcVoiceEngine voe_;
125
cricket::FakeWebRtcVoiceEngine voe_sc_;
126
cricket::WebRtcVoiceEngine engine_;
127
cricket::VoiceMediaChannel* channel_;
128
cricket::SoundclipMedia* soundclip_;
131
// Tests that our stub library "works".
132
TEST_F(WebRtcVoiceEngineTestFake, StartupShutdown) {
133
EXPECT_FALSE(voe_.IsInited());
134
EXPECT_FALSE(voe_sc_.IsInited());
135
EXPECT_TRUE(engine_.Init());
136
EXPECT_TRUE(voe_.IsInited());
137
EXPECT_TRUE(voe_sc_.IsInited());
139
EXPECT_FALSE(voe_.IsInited());
140
EXPECT_FALSE(voe_sc_.IsInited());
143
// Tests that we can create and destroy a channel.
144
TEST_F(WebRtcVoiceEngineTestFake, CreateChannel) {
145
EXPECT_TRUE(engine_.Init());
146
channel_ = engine_.CreateChannel();
147
EXPECT_TRUE(channel_ != NULL);
150
// Tests that we properly handle failures in CreateChannel.
151
TEST_F(WebRtcVoiceEngineTestFake, CreateChannelFail) {
152
voe_.set_fail_create_channel(true);
153
EXPECT_TRUE(engine_.Init());
154
channel_ = engine_.CreateChannel();
155
EXPECT_TRUE(channel_ == NULL);
158
// Tests that the list of supported codecs is created properly and ordered
160
TEST_F(WebRtcVoiceEngineTestFake, CodecPreference) {
161
const std::vector<cricket::AudioCodec>& codecs = engine_.codecs();
162
ASSERT_FALSE(codecs.empty());
163
EXPECT_EQ("ISAC", codecs[0].name);
164
EXPECT_EQ(16000, codecs[0].clockrate);
165
EXPECT_EQ(0, codecs[0].bitrate);
166
int pref = codecs[0].preference;
167
for (size_t i = 1; i < codecs.size(); ++i) {
168
EXPECT_GT(pref, codecs[i].preference);
169
pref = codecs[i].preference;
173
// Tests that we can find codecs by name or id, and that we interpret the
174
// clockrate and bitrate fields properly.
175
TEST_F(WebRtcVoiceEngineTestFake, FindCodec) {
176
cricket::AudioCodec codec;
177
webrtc::CodecInst codec_inst;
178
// Find PCMU with explicit clockrate and bitrate.
179
EXPECT_TRUE(engine_.FindWebRtcCodec(kPcmuCodec, &codec_inst));
180
// Find ISAC with explicit clockrate and 0 bitrate.
181
EXPECT_TRUE(engine_.FindWebRtcCodec(kIsacCodec, &codec_inst));
182
// Find telephone-event with explicit clockrate and 0 bitrate.
183
EXPECT_TRUE(engine_.FindWebRtcCodec(kTelephoneEventCodec, &codec_inst));
184
// Find ISAC with a different payload id.
187
EXPECT_TRUE(engine_.FindWebRtcCodec(codec, &codec_inst));
188
EXPECT_EQ(codec.id, codec_inst.pltype);
189
// Find PCMU with a 0 clockrate.
192
EXPECT_TRUE(engine_.FindWebRtcCodec(codec, &codec_inst));
193
EXPECT_EQ(codec.id, codec_inst.pltype);
194
EXPECT_EQ(8000, codec_inst.plfreq);
195
// Find PCMU with a 0 bitrate.
198
EXPECT_TRUE(engine_.FindWebRtcCodec(codec, &codec_inst));
199
EXPECT_EQ(codec.id, codec_inst.pltype);
200
EXPECT_EQ(64000, codec_inst.rate);
201
// Find ISAC with an explicit bitrate.
203
codec.bitrate = 32000;
204
EXPECT_TRUE(engine_.FindWebRtcCodec(codec, &codec_inst));
205
EXPECT_EQ(codec.id, codec_inst.pltype);
206
EXPECT_EQ(32000, codec_inst.rate);
209
// Test that we set our inbound codecs properly, including changing PT.
210
TEST_F(WebRtcVoiceEngineTestFake, SetRecvCodecs) {
211
EXPECT_TRUE(SetupEngine());
212
int channel_num = voe_.GetLastChannel();
213
std::vector<cricket::AudioCodec> codecs;
214
codecs.push_back(kIsacCodec);
215
codecs.push_back(kPcmuCodec);
216
codecs.push_back(kTelephoneEventCodec);
217
codecs[0].id = 106; // collide with existing telephone-event
219
EXPECT_TRUE(channel_->SetRecvCodecs(codecs));
220
webrtc::CodecInst gcodec;
221
talk_base::strcpyn(gcodec.plname, ARRAY_SIZE(gcodec.plname), "ISAC");
222
gcodec.plfreq = 16000;
223
EXPECT_EQ(0, voe_.GetRecPayloadType(channel_num, gcodec));
224
EXPECT_EQ(106, gcodec.pltype);
225
EXPECT_STREQ("ISAC", gcodec.plname);
226
talk_base::strcpyn(gcodec.plname, ARRAY_SIZE(gcodec.plname),
228
gcodec.plfreq = 8000;
229
EXPECT_EQ(0, voe_.GetRecPayloadType(channel_num, gcodec));
230
EXPECT_EQ(126, gcodec.pltype);
231
EXPECT_STREQ("telephone-event", gcodec.plname);
234
// Test that we fail to set an unknown inbound codec.
235
TEST_F(WebRtcVoiceEngineTestFake, SetRecvCodecsUnsupportedCodec) {
236
EXPECT_TRUE(SetupEngine());
237
std::vector<cricket::AudioCodec> codecs;
238
codecs.push_back(kIsacCodec);
239
codecs.push_back(cricket::AudioCodec(127, "XYZ", 32000, 0, 1, 0));
240
EXPECT_FALSE(channel_->SetRecvCodecs(codecs));
243
// Test that we fail if we have duplicate types in the inbound list.
244
TEST_F(WebRtcVoiceEngineTestFake, SetRecvCodecsDuplicatePayloadType) {
245
EXPECT_TRUE(SetupEngine());
246
std::vector<cricket::AudioCodec> codecs;
247
codecs.push_back(kIsacCodec);
248
codecs.push_back(kCn16000Codec);
249
codecs[1].id = kIsacCodec.id;
250
EXPECT_FALSE(channel_->SetRecvCodecs(codecs));
253
// Test that changes to recv codecs are applied to all streams.
254
TEST_F(WebRtcVoiceEngineTestFake, SetRecvCodecsWithMultipleStreams) {
255
EXPECT_TRUE(SetupEngine());
256
EXPECT_TRUE(channel_->SetOptions(cricket::OPT_CONFERENCE));
257
std::vector<cricket::AudioCodec> codecs;
258
codecs.push_back(kIsacCodec);
259
codecs.push_back(kPcmuCodec);
260
codecs.push_back(kTelephoneEventCodec);
261
codecs[0].id = 106; // collide with existing telephone-event
263
EXPECT_TRUE(channel_->SetRecvCodecs(codecs));
264
EXPECT_TRUE(channel_->AddRecvStream(
265
cricket::StreamParams::CreateLegacy(kSsrc1)));
266
int channel_num2 = voe_.GetLastChannel();
267
webrtc::CodecInst gcodec;
268
talk_base::strcpyn(gcodec.plname, ARRAY_SIZE(gcodec.plname), "ISAC");
269
gcodec.plfreq = 16000;
270
EXPECT_EQ(0, voe_.GetRecPayloadType(channel_num2, gcodec));
271
EXPECT_EQ(106, gcodec.pltype);
272
EXPECT_STREQ("ISAC", gcodec.plname);
273
talk_base::strcpyn(gcodec.plname, ARRAY_SIZE(gcodec.plname),
275
gcodec.plfreq = 8000;
276
EXPECT_EQ(0, voe_.GetRecPayloadType(channel_num2, gcodec));
277
EXPECT_EQ(126, gcodec.pltype);
278
EXPECT_STREQ("telephone-event", gcodec.plname);
281
TEST_F(WebRtcVoiceEngineTestFake, SetRecvCodecsAfterAddingStreams) {
282
EXPECT_TRUE(SetupEngine());
283
EXPECT_TRUE(channel_->SetOptions(cricket::OPT_CONFERENCE));
284
std::vector<cricket::AudioCodec> codecs;
285
codecs.push_back(kIsacCodec);
286
codecs[0].id = 106; // collide with existing telephone-event
288
EXPECT_TRUE(channel_->AddRecvStream(
289
cricket::StreamParams::CreateLegacy(kSsrc1)));
290
EXPECT_TRUE(channel_->SetRecvCodecs(codecs));
292
int channel_num2 = voe_.GetLastChannel();
293
webrtc::CodecInst gcodec;
294
talk_base::strcpyn(gcodec.plname, ARRAY_SIZE(gcodec.plname), "ISAC");
295
gcodec.plfreq = 16000;
296
EXPECT_EQ(0, voe_.GetRecPayloadType(channel_num2, gcodec));
297
EXPECT_EQ(106, gcodec.pltype);
298
EXPECT_STREQ("ISAC", gcodec.plname);
301
// Test that we apply codecs properly.
302
TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecs) {
303
EXPECT_TRUE(SetupEngine());
304
int channel_num = voe_.GetLastChannel();
305
std::vector<cricket::AudioCodec> codecs;
306
codecs.push_back(kIsacCodec);
307
codecs.push_back(kPcmuCodec);
308
codecs.push_back(kRedCodec);
310
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
311
webrtc::CodecInst gcodec;
312
EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
313
EXPECT_EQ(96, gcodec.pltype);
314
EXPECT_STREQ("ISAC", gcodec.plname);
315
EXPECT_FALSE(voe_.GetVAD(channel_num));
316
EXPECT_FALSE(voe_.GetFEC(channel_num));
317
EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false));
318
EXPECT_EQ(105, voe_.GetSendCNPayloadType(channel_num, true));
319
EXPECT_EQ(106, voe_.GetSendTelephoneEventPayloadType(channel_num));
322
// Test that we handle various ways of specifying bitrate.
323
TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsBitrate) {
324
EXPECT_TRUE(SetupEngine());
325
int channel_num = voe_.GetLastChannel();
326
std::vector<cricket::AudioCodec> codecs;
327
codecs.push_back(kIsacCodec); // bitrate == 32000
328
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
329
webrtc::CodecInst gcodec;
330
EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
331
EXPECT_EQ(103, gcodec.pltype);
332
EXPECT_STREQ("ISAC", gcodec.plname);
333
EXPECT_EQ(32000, gcodec.rate);
334
codecs[0].bitrate = 0; // bitrate == default
335
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
336
EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
337
EXPECT_EQ(103, gcodec.pltype);
338
EXPECT_STREQ("ISAC", gcodec.plname);
339
EXPECT_EQ(-1, gcodec.rate);
340
codecs[0].bitrate = 28000; // bitrate == 28000
341
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
342
EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
343
EXPECT_EQ(103, gcodec.pltype);
344
EXPECT_STREQ("ISAC", gcodec.plname);
345
EXPECT_EQ(28000, gcodec.rate);
346
codecs[0] = kPcmuCodec; // bitrate == 64000
347
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
348
EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
349
EXPECT_EQ(0, gcodec.pltype);
350
EXPECT_STREQ("PCMU", gcodec.plname);
351
EXPECT_EQ(64000, gcodec.rate);
352
codecs[0].bitrate = 0; // bitrate == default
353
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
354
EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
355
EXPECT_EQ(0, gcodec.pltype);
356
EXPECT_STREQ("PCMU", gcodec.plname);
357
EXPECT_EQ(64000, gcodec.rate);
360
// Test that we fall back to PCMU if no codecs are specified.
361
TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsNoCodecs) {
362
EXPECT_TRUE(SetupEngine());
363
int channel_num = voe_.GetLastChannel();
364
std::vector<cricket::AudioCodec> codecs;
365
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
366
webrtc::CodecInst gcodec;
367
EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
368
EXPECT_EQ(0, gcodec.pltype);
369
EXPECT_STREQ("PCMU", gcodec.plname);
370
EXPECT_FALSE(voe_.GetVAD(channel_num));
371
EXPECT_FALSE(voe_.GetFEC(channel_num));
372
EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false));
373
EXPECT_EQ(105, voe_.GetSendCNPayloadType(channel_num, true));
374
EXPECT_EQ(106, voe_.GetSendTelephoneEventPayloadType(channel_num));
377
// Test that we set VAD and DTMF types correctly.
378
TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsCNandDTMF) {
379
EXPECT_TRUE(SetupEngine());
380
int channel_num = voe_.GetLastChannel();
381
std::vector<cricket::AudioCodec> codecs;
382
codecs.push_back(kIsacCodec);
383
codecs.push_back(kPcmuCodec);
385
codecs.push_back(kCn16000Codec);
386
codecs.push_back(kCn8000Codec);
387
codecs.push_back(kTelephoneEventCodec);
388
codecs.push_back(kRedCodec);
390
codecs[2].id = 97; // wideband CN
391
codecs[4].id = 98; // DTMF
392
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
393
webrtc::CodecInst gcodec;
394
EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
395
EXPECT_EQ(96, gcodec.pltype);
396
EXPECT_STREQ("ISAC", gcodec.plname);
397
EXPECT_TRUE(voe_.GetVAD(channel_num));
398
EXPECT_FALSE(voe_.GetFEC(channel_num));
399
EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false));
400
EXPECT_EQ(97, voe_.GetSendCNPayloadType(channel_num, true));
401
EXPECT_EQ(98, voe_.GetSendTelephoneEventPayloadType(channel_num));
404
// Test that we perform case-insensitive matching of codec names.
405
TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsCaseInsensitive) {
406
EXPECT_TRUE(SetupEngine());
407
int channel_num = voe_.GetLastChannel();
408
std::vector<cricket::AudioCodec> codecs;
409
codecs.push_back(kIsacCodec);
410
codecs.push_back(kPcmuCodec);
411
codecs.push_back(kCn16000Codec);
412
codecs.push_back(kCn8000Codec);
413
codecs.push_back(kTelephoneEventCodec);
414
codecs.push_back(kRedCodec);
415
codecs[0].name = "iSaC";
417
codecs[2].id = 97; // wideband CN
418
codecs[4].id = 98; // DTMF
419
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
420
webrtc::CodecInst gcodec;
421
EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
422
EXPECT_EQ(96, gcodec.pltype);
423
EXPECT_STREQ("ISAC", gcodec.plname);
424
EXPECT_TRUE(voe_.GetVAD(channel_num));
425
EXPECT_FALSE(voe_.GetFEC(channel_num));
426
EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false));
427
EXPECT_EQ(97, voe_.GetSendCNPayloadType(channel_num, true));
428
EXPECT_EQ(98, voe_.GetSendTelephoneEventPayloadType(channel_num));
431
// Test that we set up FEC correctly.
432
TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsRED) {
433
EXPECT_TRUE(SetupEngine());
434
int channel_num = voe_.GetLastChannel();
435
std::vector<cricket::AudioCodec> codecs;
436
codecs.push_back(kRedCodec);
437
codecs.push_back(kIsacCodec);
438
codecs.push_back(kPcmuCodec);
440
codecs[0].params[""] = "96/96";
442
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
443
webrtc::CodecInst gcodec;
444
EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
445
EXPECT_EQ(96, gcodec.pltype);
446
EXPECT_STREQ("ISAC", gcodec.plname);
447
EXPECT_TRUE(voe_.GetFEC(channel_num));
448
EXPECT_EQ(127, voe_.GetSendFECPayloadType(channel_num));
451
// Test that we set up FEC correctly if params are omitted.
452
TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsREDNoParams) {
453
EXPECT_TRUE(SetupEngine());
454
int channel_num = voe_.GetLastChannel();
455
std::vector<cricket::AudioCodec> codecs;
456
codecs.push_back(kRedCodec);
457
codecs.push_back(kIsacCodec);
458
codecs.push_back(kPcmuCodec);
461
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
462
webrtc::CodecInst gcodec;
463
EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
464
EXPECT_EQ(96, gcodec.pltype);
465
EXPECT_STREQ("ISAC", gcodec.plname);
466
EXPECT_TRUE(voe_.GetFEC(channel_num));
467
EXPECT_EQ(127, voe_.GetSendFECPayloadType(channel_num));
470
// Test that we ignore RED if the parameters aren't named the way we expect.
471
TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsBadRED1) {
472
EXPECT_TRUE(SetupEngine());
473
int channel_num = voe_.GetLastChannel();
474
std::vector<cricket::AudioCodec> codecs;
475
codecs.push_back(kRedCodec);
476
codecs.push_back(kIsacCodec);
477
codecs.push_back(kPcmuCodec);
479
codecs[0].params["ABC"] = "96/96";
481
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
482
webrtc::CodecInst gcodec;
483
EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
484
EXPECT_EQ(96, gcodec.pltype);
485
EXPECT_STREQ("ISAC", gcodec.plname);
486
EXPECT_FALSE(voe_.GetFEC(channel_num));
489
// Test that we ignore RED if it uses different primary/secondary encoding.
490
TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsBadRED2) {
491
EXPECT_TRUE(SetupEngine());
492
int channel_num = voe_.GetLastChannel();
493
std::vector<cricket::AudioCodec> codecs;
494
codecs.push_back(kRedCodec);
495
codecs.push_back(kIsacCodec);
496
codecs.push_back(kPcmuCodec);
498
codecs[0].params[""] = "96/0";
500
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
501
webrtc::CodecInst gcodec;
502
EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
503
EXPECT_EQ(96, gcodec.pltype);
504
EXPECT_STREQ("ISAC", gcodec.plname);
505
EXPECT_FALSE(voe_.GetFEC(channel_num));
508
// Test that we ignore RED if it uses more than 2 encodings.
509
TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsBadRED3) {
510
EXPECT_TRUE(SetupEngine());
511
int channel_num = voe_.GetLastChannel();
512
std::vector<cricket::AudioCodec> codecs;
513
codecs.push_back(kRedCodec);
514
codecs.push_back(kIsacCodec);
515
codecs.push_back(kPcmuCodec);
517
codecs[0].params[""] = "96/96/96";
519
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
520
webrtc::CodecInst gcodec;
521
EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
522
EXPECT_EQ(96, gcodec.pltype);
523
EXPECT_STREQ("ISAC", gcodec.plname);
524
EXPECT_FALSE(voe_.GetFEC(channel_num));
527
// Test that we ignore RED if it has bogus codec ids.
528
TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsBadRED4) {
529
EXPECT_TRUE(SetupEngine());
530
int channel_num = voe_.GetLastChannel();
531
std::vector<cricket::AudioCodec> codecs;
532
codecs.push_back(kRedCodec);
533
codecs.push_back(kIsacCodec);
534
codecs.push_back(kPcmuCodec);
536
codecs[0].params[""] = "ABC/ABC";
538
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
539
webrtc::CodecInst gcodec;
540
EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
541
EXPECT_EQ(96, gcodec.pltype);
542
EXPECT_STREQ("ISAC", gcodec.plname);
543
EXPECT_FALSE(voe_.GetFEC(channel_num));
546
// Test that we ignore RED if it refers to a codec that is not present.
547
TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsBadRED5) {
548
EXPECT_TRUE(SetupEngine());
549
int channel_num = voe_.GetLastChannel();
550
std::vector<cricket::AudioCodec> codecs;
551
codecs.push_back(kRedCodec);
552
codecs.push_back(kIsacCodec);
553
codecs.push_back(kPcmuCodec);
555
codecs[0].params[""] = "97/97";
557
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
558
webrtc::CodecInst gcodec;
559
EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
560
EXPECT_EQ(96, gcodec.pltype);
561
EXPECT_STREQ("ISAC", gcodec.plname);
562
EXPECT_FALSE(voe_.GetFEC(channel_num));
565
// Test that we support setting an empty list of recv header extensions.
566
TEST_F(WebRtcVoiceEngineTestFake, SetRecvRtpHeaderExtensions) {
567
EXPECT_TRUE(SetupEngine());
568
std::vector<cricket::RtpHeaderExtension> extensions;
569
int channel_num = voe_.GetLastChannel();
571
unsigned char id = 0;
573
// An empty list shouldn't cause audio-level headers to be enabled.
574
EXPECT_TRUE(channel_->SetRecvRtpHeaderExtensions(extensions));
575
EXPECT_EQ(0, voe_.GetRTPAudioLevelIndicationStatus(
576
channel_num, enable, id));
577
EXPECT_FALSE(enable);
579
// Nor should indicating we can receive the audio-level header.
580
extensions.push_back(cricket::RtpHeaderExtension(
581
"urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8));
582
EXPECT_TRUE(channel_->SetRecvRtpHeaderExtensions(extensions));
583
EXPECT_EQ(0, voe_.GetRTPAudioLevelIndicationStatus(
584
channel_num, enable, id));
585
EXPECT_FALSE(enable);
588
// Test that we support setting certain send header extensions.
589
TEST_F(WebRtcVoiceEngineTestFake, SetSendRtpHeaderExtensions) {
590
EXPECT_TRUE(SetupEngine());
591
std::vector<cricket::RtpHeaderExtension> extensions;
592
int channel_num = voe_.GetLastChannel();
594
unsigned char id = 0;
596
// Ensure audio levels are off by default.
597
EXPECT_EQ(0, voe_.GetRTPAudioLevelIndicationStatus(
598
channel_num, enable, id));
599
EXPECT_FALSE(enable);
601
// Ensure audio levels stay off with an empty list of headers.
602
EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(extensions));
603
EXPECT_EQ(0, voe_.GetRTPAudioLevelIndicationStatus(
604
channel_num, enable, id));
605
EXPECT_FALSE(enable);
607
// Ensure audio levels are enabled if the audio-level header is specified.
608
extensions.push_back(cricket::RtpHeaderExtension(
609
"urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8));
610
EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(extensions));
611
EXPECT_EQ(0, voe_.GetRTPAudioLevelIndicationStatus(
612
channel_num, enable, id));
616
// Ensure audio levels go back off with an empty list.
618
EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(extensions));
619
EXPECT_EQ(0, voe_.GetRTPAudioLevelIndicationStatus(
620
channel_num, enable, id));
621
EXPECT_FALSE(enable);
624
// Test that we can create a channel and start sending/playing out on it.
625
TEST_F(WebRtcVoiceEngineTestFake, SendAndPlayout) {
626
EXPECT_TRUE(SetupEngine());
627
int channel_num = voe_.GetLastChannel();
628
std::vector<cricket::AudioCodec> codecs;
629
codecs.push_back(kPcmuCodec);
630
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
631
EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE));
632
EXPECT_TRUE(voe_.GetSend(channel_num));
633
EXPECT_TRUE(channel_->SetPlayout(true));
634
EXPECT_TRUE(voe_.GetPlayout(channel_num));
635
EXPECT_TRUE(channel_->SetSend(cricket::SEND_NOTHING));
636
EXPECT_FALSE(voe_.GetSend(channel_num));
637
EXPECT_TRUE(channel_->SetPlayout(false));
638
EXPECT_FALSE(voe_.GetPlayout(channel_num));
641
// Test that we can add and remove streams, and do proper send/playout.
642
// We can receive on multiple streams, but will only send on one.
643
TEST_F(WebRtcVoiceEngineTestFake, SendAndPlayoutWithMultipleStreams) {
644
EXPECT_TRUE(SetupEngine());
645
int channel_num1 = voe_.GetLastChannel();
647
// Start playout on the default channel.
648
EXPECT_TRUE(channel_->SetOptions(cricket::OPT_CONFERENCE));
649
EXPECT_TRUE(channel_->SetPlayout(true));
650
EXPECT_TRUE(voe_.GetPlayout(channel_num1));
652
// Adding another stream should disable playout on the default channel.
653
EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
654
int channel_num2 = voe_.GetLastChannel();
655
std::vector<cricket::AudioCodec> codecs;
656
codecs.push_back(kPcmuCodec);
657
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
658
EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE));
659
EXPECT_TRUE(voe_.GetSend(channel_num1));
660
EXPECT_FALSE(voe_.GetSend(channel_num2));
662
// Make sure only the new channel is played out.
663
EXPECT_FALSE(voe_.GetPlayout(channel_num1));
664
EXPECT_TRUE(voe_.GetPlayout(channel_num2));
666
// Adding yet another stream should have stream 2 and 3 enabled for playout.
667
EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(3)));
668
int channel_num3 = voe_.GetLastChannel();
669
EXPECT_FALSE(voe_.GetPlayout(channel_num1));
670
EXPECT_TRUE(voe_.GetPlayout(channel_num2));
671
EXPECT_TRUE(voe_.GetPlayout(channel_num3));
672
EXPECT_FALSE(voe_.GetSend(channel_num3));
675
EXPECT_TRUE(channel_->SetSend(cricket::SEND_NOTHING));
676
EXPECT_FALSE(voe_.GetSend(channel_num1));
677
EXPECT_FALSE(voe_.GetSend(channel_num2));
678
EXPECT_FALSE(voe_.GetSend(channel_num3));
681
EXPECT_TRUE(channel_->SetPlayout(false));
682
EXPECT_FALSE(voe_.GetPlayout(channel_num1));
683
EXPECT_FALSE(voe_.GetPlayout(channel_num2));
684
EXPECT_FALSE(voe_.GetPlayout(channel_num3));
686
// Restart playout and make sure the default channel still is not played out.
687
EXPECT_TRUE(channel_->SetPlayout(true));
688
EXPECT_FALSE(voe_.GetPlayout(channel_num1));
689
EXPECT_TRUE(voe_.GetPlayout(channel_num2));
690
EXPECT_TRUE(voe_.GetPlayout(channel_num3));
692
// Now remove the new streams and verify that the default channel is
694
EXPECT_TRUE(channel_->RemoveRecvStream(3));
695
EXPECT_TRUE(channel_->RemoveRecvStream(2));
697
EXPECT_TRUE(voe_.GetPlayout(channel_num1));
700
// Test that we can set the devices to use.
701
TEST_F(WebRtcVoiceEngineTestFake, SetDevices) {
702
EXPECT_TRUE(SetupEngine());
703
int channel_num = voe_.GetLastChannel();
704
std::vector<cricket::AudioCodec> codecs;
705
codecs.push_back(kPcmuCodec);
706
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
708
cricket::Device default_dev(cricket::kFakeDefaultDeviceName,
709
cricket::kFakeDefaultDeviceId);
710
cricket::Device dev(cricket::kFakeDeviceName,
711
cricket::kFakeDeviceId);
713
// Test SetDevices() while not sending or playing.
714
EXPECT_TRUE(engine_.SetDevices(&default_dev, &default_dev));
716
// Test SetDevices() while sending and playing.
717
EXPECT_TRUE(engine_.SetLocalMonitor(true));
718
EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE));
719
EXPECT_TRUE(channel_->SetPlayout(true));
720
EXPECT_TRUE(voe_.GetRecordingMicrophone());
721
EXPECT_TRUE(voe_.GetSend(channel_num));
722
EXPECT_TRUE(voe_.GetPlayout(channel_num));
724
EXPECT_TRUE(engine_.SetDevices(&dev, &dev));
726
EXPECT_TRUE(voe_.GetRecordingMicrophone());
727
EXPECT_TRUE(voe_.GetSend(channel_num));
728
EXPECT_TRUE(voe_.GetPlayout(channel_num));
730
// Test that failure to open newly selected devices does not prevent opening
732
voe_.set_fail_start_recording_microphone(true);
733
voe_.set_playout_fail_channel(channel_num);
734
voe_.set_send_fail_channel(channel_num);
736
EXPECT_FALSE(engine_.SetDevices(&default_dev, &default_dev));
738
EXPECT_FALSE(voe_.GetRecordingMicrophone());
739
EXPECT_FALSE(voe_.GetSend(channel_num));
740
EXPECT_FALSE(voe_.GetPlayout(channel_num));
742
voe_.set_fail_start_recording_microphone(false);
743
voe_.set_playout_fail_channel(-1);
744
voe_.set_send_fail_channel(-1);
746
EXPECT_TRUE(engine_.SetDevices(&dev, &dev));
748
EXPECT_TRUE(voe_.GetRecordingMicrophone());
749
EXPECT_TRUE(voe_.GetSend(channel_num));
750
EXPECT_TRUE(voe_.GetPlayout(channel_num));
753
// Test that we can set the devices to use even if we failed to
754
// open the initial ones.
755
TEST_F(WebRtcVoiceEngineTestFake, SetDevicesWithInitiallyBadDevices) {
756
EXPECT_TRUE(SetupEngine());
757
int channel_num = voe_.GetLastChannel();
758
std::vector<cricket::AudioCodec> codecs;
759
codecs.push_back(kPcmuCodec);
760
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
762
cricket::Device default_dev(cricket::kFakeDefaultDeviceName,
763
cricket::kFakeDefaultDeviceId);
764
cricket::Device dev(cricket::kFakeDeviceName,
765
cricket::kFakeDeviceId);
767
// Test that failure to open devices selected before starting
768
// send/play does not prevent opening newly selected ones after that.
769
voe_.set_fail_start_recording_microphone(true);
770
voe_.set_playout_fail_channel(channel_num);
771
voe_.set_send_fail_channel(channel_num);
773
EXPECT_TRUE(engine_.SetDevices(&default_dev, &default_dev));
775
EXPECT_FALSE(engine_.SetLocalMonitor(true));
776
EXPECT_FALSE(channel_->SetSend(cricket::SEND_MICROPHONE));
777
EXPECT_FALSE(channel_->SetPlayout(true));
778
EXPECT_FALSE(voe_.GetRecordingMicrophone());
779
EXPECT_FALSE(voe_.GetSend(channel_num));
780
EXPECT_FALSE(voe_.GetPlayout(channel_num));
782
voe_.set_fail_start_recording_microphone(false);
783
voe_.set_playout_fail_channel(-1);
784
voe_.set_send_fail_channel(-1);
786
EXPECT_TRUE(engine_.SetDevices(&dev, &dev));
788
EXPECT_TRUE(voe_.GetRecordingMicrophone());
789
EXPECT_TRUE(voe_.GetSend(channel_num));
790
EXPECT_TRUE(voe_.GetPlayout(channel_num));
793
// Test that we can create a channel configured for multi-point conferences,
794
// and start sending/playing out on it.
795
TEST_F(WebRtcVoiceEngineTestFake, ConferenceSendAndPlayout) {
796
EXPECT_TRUE(SetupEngine());
797
int channel_num = voe_.GetLastChannel();
798
EXPECT_TRUE(channel_->SetOptions(cricket::OPT_CONFERENCE));
799
std::vector<cricket::AudioCodec> codecs;
800
codecs.push_back(kPcmuCodec);
801
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
802
EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE));
803
EXPECT_TRUE(voe_.GetSend(channel_num));
806
webrtc::EcModes ec_mode;
807
webrtc::NsModes ns_mode;
808
EXPECT_EQ(0, voe_.GetEcStatus(enabled, ec_mode));
810
EXPECT_EQ(webrtc::kEcDefault, ec_mode);
812
EXPECT_EQ(webrtc::kEcConference, ec_mode);
814
EXPECT_EQ(0, voe_.GetNsStatus(enabled, ns_mode));
815
EXPECT_TRUE(enabled);
817
EXPECT_EQ(webrtc::kNsDefault, ns_mode);
819
EXPECT_EQ(webrtc::kNsConference, ns_mode);
822
EXPECT_TRUE(channel_->SetPlayout(true));
823
EXPECT_TRUE(voe_.GetPlayout(channel_num));
824
EXPECT_TRUE(channel_->SetSend(cricket::SEND_NOTHING));
825
EXPECT_FALSE(voe_.GetSend(channel_num));
827
EXPECT_EQ(0, voe_.GetEcStatus(enabled, ec_mode));
828
EXPECT_EQ(webrtc::kEcDefault, ec_mode);
829
EXPECT_EQ(0, voe_.GetNsStatus(enabled, ns_mode));
830
EXPECT_EQ(webrtc::kNsDefault, ns_mode);
832
EXPECT_TRUE(channel_->SetPlayout(false));
833
EXPECT_FALSE(voe_.GetPlayout(channel_num));
836
// Test that we can create a channel configured for Codian bridges,
837
// and start sending/playing out on it.
838
TEST_F(WebRtcVoiceEngineTestFake, CodianSendAndPlayout) {
839
EXPECT_TRUE(SetupEngine());
840
int channel_num = voe_.GetLastChannel();
841
webrtc::AgcConfig agc_config;
842
EXPECT_EQ(0, voe_.GetAgcConfig(agc_config));
843
EXPECT_EQ(0, agc_config.targetLeveldBOv);
844
EXPECT_TRUE(channel_->SetOptions(cricket::OPT_AGC_MINUS_10DB));
845
std::vector<cricket::AudioCodec> codecs;
846
codecs.push_back(kPcmuCodec);
847
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
848
EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE));
849
EXPECT_TRUE(voe_.GetSend(channel_num));
850
EXPECT_EQ(0, voe_.GetAgcConfig(agc_config));
851
EXPECT_GT(agc_config.targetLeveldBOv, 0); // level was attenuated
852
EXPECT_TRUE(channel_->SetPlayout(true));
853
EXPECT_TRUE(voe_.GetPlayout(channel_num));
854
EXPECT_TRUE(channel_->SetSend(cricket::SEND_NOTHING));
855
EXPECT_FALSE(voe_.GetSend(channel_num));
856
EXPECT_EQ(0, voe_.GetAgcConfig(agc_config));
857
EXPECT_EQ(0, agc_config.targetLeveldBOv); // level was restored
858
EXPECT_TRUE(channel_->SetPlayout(false));
859
EXPECT_FALSE(voe_.GetPlayout(channel_num));
862
// Test that we can set the outgoing SSRC properly.
863
// SSRC is set in SetupEngine by calling AddSendStream.
864
TEST_F(WebRtcVoiceEngineTestFake, SetSendSsrc) {
865
EXPECT_TRUE(SetupEngine());
866
int channel_num = voe_.GetLastChannel();
867
unsigned int send_ssrc;
868
EXPECT_EQ(0, voe_.GetLocalSSRC(channel_num, send_ssrc));
869
EXPECT_NE(0U, send_ssrc);
870
EXPECT_EQ(0, voe_.GetLocalSSRC(channel_num, send_ssrc));
871
EXPECT_EQ(kSsrc1, send_ssrc);
874
// Test that we can set the outgoing SSRC properly with multiple streams.
875
// SSRC is set in SetupEngine by calling AddSendStream.
876
TEST_F(WebRtcVoiceEngineTestFake, SetSendSsrcWithMultipleStreams) {
877
EXPECT_TRUE(SetupEngine());
878
EXPECT_TRUE(channel_->SetOptions(cricket::OPT_CONFERENCE));
879
int channel_num1 = voe_.GetLastChannel();
880
unsigned int send_ssrc;
881
EXPECT_EQ(0, voe_.GetLocalSSRC(channel_num1, send_ssrc));
882
EXPECT_EQ(kSsrc1, send_ssrc);
884
EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
885
int channel_num2 = voe_.GetLastChannel();
886
EXPECT_EQ(0, voe_.GetLocalSSRC(channel_num2, send_ssrc));
887
EXPECT_EQ(kSsrc1, send_ssrc);
890
// Test that the local SSRC is the same on sending and receiving channels if the
891
// receive channel is created before the send channel.
892
TEST_F(WebRtcVoiceEngineTestFake, SetSendSsrcAfterCreatingReceiveChannel) {
893
EXPECT_TRUE(engine_.Init());
894
channel_ = engine_.CreateChannel();
895
EXPECT_TRUE(channel_->SetOptions(cricket::OPT_CONFERENCE));
897
EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1)));
898
int receive_channel_num = voe_.GetLastChannel();
899
EXPECT_TRUE(channel_->AddSendStream(
900
cricket::StreamParams::CreateLegacy(1234)));
901
int send_channel_num = voe_.GetLastChannel();
903
unsigned int ssrc = 0;
904
EXPECT_EQ(0, voe_.GetLocalSSRC(send_channel_num, ssrc));
905
EXPECT_EQ(1234U, ssrc);
907
EXPECT_EQ(0, voe_.GetLocalSSRC(receive_channel_num, ssrc));
908
EXPECT_EQ(1234U, ssrc);
911
// Test that we can properly receive packets.
912
TEST_F(WebRtcVoiceEngineTestFake, Recv) {
913
EXPECT_TRUE(SetupEngine());
914
int channel_num = voe_.GetLastChannel();
915
DeliverPacket(kPcmuFrame, sizeof(kPcmuFrame));
916
EXPECT_TRUE(voe_.CheckPacket(channel_num, kPcmuFrame,
917
sizeof(kPcmuFrame)));
920
// Test that we can properly receive packets on multiple streams.
921
TEST_F(WebRtcVoiceEngineTestFake, RecvWithMultipleStreams) {
922
EXPECT_TRUE(SetupEngine());
923
EXPECT_TRUE(channel_->SetOptions(cricket::OPT_CONFERENCE));
924
EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1)));
925
int channel_num1 = voe_.GetLastChannel();
926
EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
927
int channel_num2 = voe_.GetLastChannel();
928
EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(3)));
929
int channel_num3 = voe_.GetLastChannel();
930
// Create packets with the right SSRCs.
931
char packets[4][sizeof(kPcmuFrame)];
932
for (size_t i = 0; i < ARRAY_SIZE(packets); ++i) {
933
memcpy(packets[i], kPcmuFrame, sizeof(kPcmuFrame));
934
talk_base::SetBE32(packets[i] + 8, i);
936
EXPECT_TRUE(voe_.CheckNoPacket(channel_num1));
937
EXPECT_TRUE(voe_.CheckNoPacket(channel_num2));
938
EXPECT_TRUE(voe_.CheckNoPacket(channel_num3));
939
DeliverPacket(packets[0], sizeof(packets[0]));
940
EXPECT_TRUE(voe_.CheckNoPacket(channel_num1));
941
EXPECT_TRUE(voe_.CheckNoPacket(channel_num2));
942
EXPECT_TRUE(voe_.CheckNoPacket(channel_num3));
943
DeliverPacket(packets[1], sizeof(packets[1]));
944
EXPECT_TRUE(voe_.CheckPacket(channel_num1, packets[1],
945
sizeof(packets[1])));
946
EXPECT_TRUE(voe_.CheckNoPacket(channel_num2));
947
EXPECT_TRUE(voe_.CheckNoPacket(channel_num3));
948
DeliverPacket(packets[2], sizeof(packets[2]));
949
EXPECT_TRUE(voe_.CheckNoPacket(channel_num1));
950
EXPECT_TRUE(voe_.CheckPacket(channel_num2, packets[2],
951
sizeof(packets[2])));
952
EXPECT_TRUE(voe_.CheckNoPacket(channel_num3));
953
DeliverPacket(packets[3], sizeof(packets[3]));
954
EXPECT_TRUE(voe_.CheckNoPacket(channel_num1));
955
EXPECT_TRUE(voe_.CheckNoPacket(channel_num2));
956
EXPECT_TRUE(voe_.CheckPacket(channel_num3, packets[3],
957
sizeof(packets[3])));
958
EXPECT_TRUE(channel_->RemoveRecvStream(3));
959
EXPECT_TRUE(channel_->RemoveRecvStream(2));
960
EXPECT_TRUE(channel_->RemoveRecvStream(1));
963
// Test that we properly handle failures to add a stream.
964
TEST_F(WebRtcVoiceEngineTestFake, AddStreamFail) {
965
EXPECT_TRUE(SetupEngine());
966
voe_.set_fail_create_channel(true);
967
EXPECT_TRUE(channel_->SetOptions(cricket::OPT_CONFERENCE));
968
EXPECT_FALSE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
970
// In 1:1 call, we should not try to create a new channel.
971
EXPECT_TRUE(channel_->SetOptions(0));
972
EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
975
// Test that AddRecvStream doesn't create new channel for 1:1 call.
976
TEST_F(WebRtcVoiceEngineTestFake, AddRecvStream1On1) {
977
EXPECT_TRUE(SetupEngine());
978
int channel_num = voe_.GetLastChannel();
979
EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1)));
980
EXPECT_EQ(channel_num, voe_.GetLastChannel());
983
// Test that we properly clean up any streams that were added, even if
984
// not explicitly removed.
985
TEST_F(WebRtcVoiceEngineTestFake, StreamCleanup) {
986
EXPECT_TRUE(SetupEngine());
987
EXPECT_TRUE(channel_->SetOptions(cricket::OPT_CONFERENCE));
988
EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1)));
989
EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
990
EXPECT_EQ(3, voe_.GetNumChannels()); // default channel + 2 added
993
EXPECT_EQ(0, voe_.GetNumChannels());
996
// Test that we can send DTMF properly, but only if the other side supports
998
TEST_F(WebRtcVoiceEngineTestFake, SendDtmf) {
999
EXPECT_TRUE(SetupEngine());
1000
std::vector<cricket::AudioCodec> codecs;
1001
codecs.push_back(kPcmuCodec);
1002
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1003
EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE));
1004
EXPECT_FALSE(channel_->PressDTMF(1, true));
1005
codecs.push_back(kTelephoneEventCodec);
1006
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1007
EXPECT_TRUE(channel_->PressDTMF(1, true));
1010
// Test that we can play a ringback tone properly in a single-stream call.
1011
TEST_F(WebRtcVoiceEngineTestFake, PlayRingback) {
1012
EXPECT_TRUE(SetupEngine());
1013
int channel_num = voe_.GetLastChannel();
1014
EXPECT_EQ(0, voe_.IsPlayingFileLocally(channel_num));
1015
// Check we fail if no ringback tone specified.
1016
EXPECT_FALSE(channel_->PlayRingbackTone(0, true, true));
1017
EXPECT_EQ(0, voe_.IsPlayingFileLocally(channel_num));
1018
// Check we can set and play a ringback tone.
1019
EXPECT_TRUE(channel_->SetRingbackTone(kRingbackTone, strlen(kRingbackTone)));
1020
EXPECT_TRUE(channel_->PlayRingbackTone(0, true, true));
1021
EXPECT_EQ(1, voe_.IsPlayingFileLocally(channel_num));
1022
// Check we can stop the tone manually.
1023
EXPECT_TRUE(channel_->PlayRingbackTone(0, false, false));
1024
EXPECT_EQ(0, voe_.IsPlayingFileLocally(channel_num));
1025
// Check we stop the tone if a packet arrives.
1026
EXPECT_TRUE(channel_->PlayRingbackTone(0, true, true));
1027
EXPECT_EQ(1, voe_.IsPlayingFileLocally(channel_num));
1028
DeliverPacket(kPcmuFrame, sizeof(kPcmuFrame));
1029
EXPECT_EQ(0, voe_.IsPlayingFileLocally(channel_num));
1032
// Test that we can play a ringback tone properly in a multi-stream call.
1033
TEST_F(WebRtcVoiceEngineTestFake, PlayRingbackWithMultipleStreams) {
1034
EXPECT_TRUE(SetupEngine());
1035
EXPECT_TRUE(channel_->SetOptions(cricket::OPT_CONFERENCE));
1036
EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1)));
1037
EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
1038
int channel_num = voe_.GetLastChannel();
1039
EXPECT_EQ(0, voe_.IsPlayingFileLocally(channel_num));
1040
// Check we fail if no ringback tone specified.
1041
EXPECT_FALSE(channel_->PlayRingbackTone(2, true, true));
1042
EXPECT_EQ(0, voe_.IsPlayingFileLocally(channel_num));
1043
// Check we can set and play a ringback tone on the correct ssrc.
1044
EXPECT_TRUE(channel_->SetRingbackTone(kRingbackTone, strlen(kRingbackTone)));
1045
EXPECT_FALSE(channel_->PlayRingbackTone(77, true, true));
1046
EXPECT_TRUE(channel_->PlayRingbackTone(2, true, true));
1047
EXPECT_EQ(1, voe_.IsPlayingFileLocally(channel_num));
1048
// Check we can stop the tone manually.
1049
EXPECT_TRUE(channel_->PlayRingbackTone(2, false, false));
1050
EXPECT_EQ(0, voe_.IsPlayingFileLocally(channel_num));
1051
// Check we stop the tone if a packet arrives, but only with the right SSRC.
1052
EXPECT_TRUE(channel_->PlayRingbackTone(2, true, true));
1053
EXPECT_EQ(1, voe_.IsPlayingFileLocally(channel_num));
1054
// Send a packet with SSRC 1; the tone should not stop.
1055
DeliverPacket(kPcmuFrame, sizeof(kPcmuFrame));
1056
EXPECT_EQ(1, voe_.IsPlayingFileLocally(channel_num));
1057
// Send a packet with SSRC 2; the tone should stop.
1058
char packet[sizeof(kPcmuFrame)];
1059
memcpy(packet, kPcmuFrame, sizeof(kPcmuFrame));
1060
talk_base::SetBE32(packet + 8, 2);
1061
DeliverPacket(packet, sizeof(packet));
1062
EXPECT_EQ(0, voe_.IsPlayingFileLocally(channel_num));
1065
// Tests creating soundclips, and make sure they come from the right engine.
1066
TEST_F(WebRtcVoiceEngineTestFake, CreateSoundclip) {
1067
EXPECT_TRUE(engine_.Init());
1068
soundclip_ = engine_.CreateSoundclip();
1069
ASSERT_TRUE(soundclip_ != NULL);
1070
EXPECT_EQ(0, voe_.GetNumChannels());
1071
EXPECT_EQ(1, voe_sc_.GetNumChannels());
1072
int channel_num = voe_sc_.GetLastChannel();
1073
EXPECT_TRUE(voe_sc_.GetPlayout(channel_num));
1076
EXPECT_EQ(0, voe_sc_.GetNumChannels());
1079
// Tests playing out a fake sound.
1080
TEST_F(WebRtcVoiceEngineTestFake, PlaySoundclip) {
1081
static const char kZeroes[16000] = {};
1082
EXPECT_TRUE(engine_.Init());
1083
soundclip_ = engine_.CreateSoundclip();
1084
ASSERT_TRUE(soundclip_ != NULL);
1085
EXPECT_TRUE(soundclip_->PlaySound(kZeroes, sizeof(kZeroes), 0));
1088
TEST_F(WebRtcVoiceEngineTestFake, MediaEngineCallbackOnError) {
1089
talk_base::scoped_ptr<ChannelErrorListener> listener;
1090
cricket::WebRtcVoiceMediaChannel* media_channel;
1091
unsigned int ssrc = 0;
1093
EXPECT_TRUE(SetupEngine());
1094
EXPECT_TRUE(channel_->SetOptions(cricket::OPT_CONFERENCE));
1095
EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE));
1097
media_channel = reinterpret_cast<cricket::WebRtcVoiceMediaChannel*>(channel_);
1098
listener.reset(new ChannelErrorListener(channel_));
1100
// Test on WebRtc VoE channel.
1101
voe_.TriggerCallbackOnError(media_channel->voe_channel(),
1102
VE_SATURATION_WARNING);
1103
EXPECT_EQ(cricket::VoiceMediaChannel::ERROR_REC_DEVICE_SATURATION,
1105
EXPECT_NE(-1, voe_.GetLocalSSRC(voe_.GetLastChannel(), ssrc));
1106
EXPECT_EQ(ssrc, listener->ssrc());
1109
voe_.TriggerCallbackOnError(-1, VE_TYPING_NOISE_WARNING);
1110
EXPECT_EQ(cricket::VoiceMediaChannel::ERROR_REC_TYPING_NOISE_DETECTED,
1112
EXPECT_EQ(0U, listener->ssrc());
1114
// Add another stream and test on that.
1116
EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(
1119
voe_.TriggerCallbackOnError(voe_.GetLastChannel(),
1120
VE_SATURATION_WARNING);
1121
EXPECT_EQ(cricket::VoiceMediaChannel::ERROR_REC_DEVICE_SATURATION,
1123
EXPECT_EQ(ssrc, listener->ssrc());
1125
// Testing a non-existing channel.
1127
voe_.TriggerCallbackOnError(voe_.GetLastChannel() + 2,
1128
VE_SATURATION_WARNING);
1129
EXPECT_EQ(0, listener->error());
1132
TEST_F(WebRtcVoiceEngineTestFake, TestSetPlayoutError) {
1133
EXPECT_TRUE(SetupEngine());
1134
EXPECT_TRUE(channel_->SetOptions(cricket::OPT_CONFERENCE));
1135
std::vector<cricket::AudioCodec> codecs;
1136
codecs.push_back(kPcmuCodec);
1137
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
1138
EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE));
1139
EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
1140
EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(3)));
1141
EXPECT_TRUE(channel_->SetPlayout(true));
1142
voe_.set_playout_fail_channel(voe_.GetLastChannel() - 1);
1143
EXPECT_TRUE(channel_->SetPlayout(false));
1144
EXPECT_FALSE(channel_->SetPlayout(true));
1147
// Test that the Registering/Unregistering with the
1148
// webrtcvoiceengine works as expected
1149
TEST_F(WebRtcVoiceEngineTestFake, RegisterVoiceProcessor) {
1150
EXPECT_TRUE(SetupEngine());
1151
EXPECT_TRUE(channel_->SetOptions(cricket::OPT_CONFERENCE));
1152
EXPECT_TRUE(channel_->AddRecvStream(
1153
cricket::StreamParams::CreateLegacy(kSsrc1)));
1155
voe_.GetLocalSSRC(0, ssrc);
1156
cricket::FakeMediaProcessor vp_1;
1157
cricket::FakeMediaProcessor vp_2;
1159
EXPECT_TRUE(engine_.RegisterProcessor(ssrc, &vp_1, cricket::MPD_RX));
1160
EXPECT_TRUE(engine_.RegisterProcessor(ssrc, &vp_2, cricket::MPD_RX));
1161
voe_.TriggerProcessPacket(cricket::MPD_RX);
1162
voe_.TriggerProcessPacket(cricket::MPD_TX);
1164
EXPECT_TRUE(voe_.IsExternalMediaProcessorRegistered());
1165
EXPECT_EQ(1, vp_1.voice_frame_count());
1166
EXPECT_EQ(1, vp_2.voice_frame_count());
1168
EXPECT_TRUE(engine_.UnregisterProcessor(ssrc,
1171
voe_.TriggerProcessPacket(cricket::MPD_RX);
1172
EXPECT_TRUE(voe_.IsExternalMediaProcessorRegistered());
1173
EXPECT_EQ(1, vp_2.voice_frame_count());
1174
EXPECT_EQ(2, vp_1.voice_frame_count());
1176
EXPECT_TRUE(engine_.UnregisterProcessor(ssrc,
1179
voe_.TriggerProcessPacket(cricket::MPD_RX);
1180
EXPECT_FALSE(voe_.IsExternalMediaProcessorRegistered());
1181
EXPECT_EQ(2, vp_1.voice_frame_count());
1183
EXPECT_TRUE(engine_.RegisterProcessor(ssrc, &vp_1, cricket::MPD_TX));
1184
voe_.TriggerProcessPacket(cricket::MPD_RX);
1185
voe_.TriggerProcessPacket(cricket::MPD_TX);
1186
EXPECT_TRUE(voe_.IsExternalMediaProcessorRegistered());
1187
EXPECT_EQ(3, vp_1.voice_frame_count());
1189
EXPECT_TRUE(engine_.UnregisterProcessor(ssrc,
1191
cricket::MPD_RX_AND_TX));
1192
voe_.TriggerProcessPacket(cricket::MPD_TX);
1193
EXPECT_FALSE(voe_.IsExternalMediaProcessorRegistered());
1194
EXPECT_EQ(3, vp_1.voice_frame_count());
1195
EXPECT_TRUE(channel_->RemoveRecvStream(kSsrc1));
1197
// Test that after removing the recvstream we can we can still register
1198
// the processor. This tests the 1:1 case.
1199
EXPECT_TRUE(engine_.RegisterProcessor(ssrc, &vp_1, cricket::MPD_RX));
1200
EXPECT_TRUE(engine_.UnregisterProcessor(ssrc, &vp_1, cricket::MPD_RX_AND_TX));
1202
// The following tests test that FindChannelNumFromSsrc is doing
1204
// pick an invalid ssrc and make sure we can't register
1205
EXPECT_FALSE(engine_.RegisterProcessor(0,
1208
EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1)));
1209
EXPECT_TRUE(engine_.RegisterProcessor(1,
1212
EXPECT_TRUE(engine_.UnregisterProcessor(1,
1215
EXPECT_FALSE(engine_.RegisterProcessor(1,
1218
EXPECT_TRUE(channel_->RemoveRecvStream(1));
1221
// Tests for the actual WebRtc VoE library.
1223
// Tests that the library initializes and shuts down properly.
1224
TEST(WebRtcVoiceEngineTest, StartupShutdown) {
1225
cricket::WebRtcVoiceEngine engine;
1226
EXPECT_TRUE(engine.Init());
1227
cricket::VoiceMediaChannel* channel = engine.CreateChannel();
1228
EXPECT_TRUE(channel != NULL);
1232
// Reinit to catch regression where VoiceEngineObserver reference is lost
1233
EXPECT_TRUE(engine.Init());
1237
// Tests that the logging from the library is cleartext.
1238
TEST(WebRtcVoiceEngineTest, DISABLED_HasUnencryptedLogging) {
1239
cricket::WebRtcVoiceEngine engine;
1240
talk_base::scoped_ptr<talk_base::MemoryStream> stream(
1241
new talk_base::MemoryStream);
1243
bool cleartext = true;
1244
talk_base::LogMessage::AddLogToStream(stream.get(), talk_base::LS_VERBOSE);
1245
engine.SetLogging(talk_base::LS_VERBOSE, "");
1246
EXPECT_TRUE(engine.Init());
1247
EXPECT_TRUE(stream->GetSize(&size));
1248
EXPECT_GT(size, 0U);
1250
talk_base::LogMessage::RemoveLogToStream(stream.get());
1251
const char* buf = stream->GetBuffer();
1252
for (size_t i = 0; i < size && cleartext; ++i) {
1253
int ch = static_cast<int>(buf[i]);
1254
ASSERT_GE(ch, 0) << "Out of bounds character in WebRtc VoE log: "
1256
cleartext = (isprint(ch) || isspace(ch));
1258
EXPECT_TRUE(cleartext);
1261
// Tests we do not see any references to a monitor thread being spun up
1262
// when initiating the engine.
1263
TEST(WebRtcVoiceEngineTest, HasNoMonitorThread) {
1264
cricket::WebRtcVoiceEngine engine;
1265
talk_base::scoped_ptr<talk_base::MemoryStream> stream(
1266
new talk_base::MemoryStream);
1267
talk_base::LogMessage::AddLogToStream(stream.get(), talk_base::LS_VERBOSE);
1268
engine.SetLogging(talk_base::LS_VERBOSE, "");
1269
EXPECT_TRUE(engine.Init());
1271
talk_base::LogMessage::RemoveLogToStream(stream.get());
1274
EXPECT_TRUE(stream->GetSize(&size));
1275
EXPECT_GT(size, 0U);
1276
const std::string logs(stream->GetBuffer());
1277
EXPECT_NE(std::string::npos, logs.find("ProcessThread"));
1280
// Tests that the library is configured with the codecs we want.
1281
TEST(WebRtcVoiceEngineTest, HasCorrectCodecs) {
1282
cricket::WebRtcVoiceEngine engine;
1283
// Check codecs by name.
1284
EXPECT_TRUE(engine.FindCodec(
1285
cricket::AudioCodec(96, "ISAC", 16000, 0, 1, 0)));
1286
EXPECT_TRUE(engine.FindCodec(
1287
cricket::AudioCodec(96, "ISAC", 32000, 0, 1, 0)));
1288
// Check that name matching is case-insensitive.
1289
EXPECT_TRUE(engine.FindCodec(
1290
cricket::AudioCodec(96, "ILBC", 8000, 0, 1, 0)));
1291
EXPECT_TRUE(engine.FindCodec(
1292
cricket::AudioCodec(96, "iLBC", 8000, 0, 1, 0)));
1293
EXPECT_TRUE(engine.FindCodec(
1294
cricket::AudioCodec(96, "PCMU", 8000, 0, 1, 0)));
1295
EXPECT_TRUE(engine.FindCodec(
1296
cricket::AudioCodec(96, "PCMA", 8000, 0, 1, 0)));
1297
EXPECT_TRUE(engine.FindCodec(
1298
cricket::AudioCodec(96, "speex", 16000, 0, 1, 0)));
1299
EXPECT_TRUE(engine.FindCodec(
1300
cricket::AudioCodec(96, "speex", 8000, 0, 1, 0)));
1301
EXPECT_TRUE(engine.FindCodec(
1302
cricket::AudioCodec(96, "G722", 16000, 0, 1, 0)));
1303
EXPECT_TRUE(engine.FindCodec(
1304
cricket::AudioCodec(96, "red", 8000, 0, 1, 0)));
1305
EXPECT_TRUE(engine.FindCodec(
1306
cricket::AudioCodec(96, "CN", 32000, 0, 1, 0)));
1307
EXPECT_TRUE(engine.FindCodec(
1308
cricket::AudioCodec(96, "CN", 16000, 0, 1, 0)));
1309
EXPECT_TRUE(engine.FindCodec(
1310
cricket::AudioCodec(96, "CN", 8000, 0, 1, 0)));
1311
EXPECT_TRUE(engine.FindCodec(
1312
cricket::AudioCodec(96, "telephone-event", 8000, 0, 1, 0)));
1313
// Check codecs with an id by id.
1314
EXPECT_TRUE(engine.FindCodec(
1315
cricket::AudioCodec(0, "", 8000, 0, 1, 0))); // PCMU
1316
EXPECT_TRUE(engine.FindCodec(
1317
cricket::AudioCodec(8, "", 8000, 0, 1, 0))); // PCMA
1318
EXPECT_TRUE(engine.FindCodec(
1319
cricket::AudioCodec(9, "", 16000, 0, 1, 0))); // G722
1320
EXPECT_TRUE(engine.FindCodec(
1321
cricket::AudioCodec(13, "", 8000, 0, 1, 0))); // CN
1322
// Check sample/bitrate matching.
1323
EXPECT_TRUE(engine.FindCodec(
1324
cricket::AudioCodec(0, "PCMU", 8000, 64000, 1, 0)));
1325
// Check that bad codecs fail.
1326
EXPECT_FALSE(engine.FindCodec(cricket::AudioCodec(99, "ABCD", 0, 0, 1, 0)));
1327
EXPECT_FALSE(engine.FindCodec(cricket::AudioCodec(88, "", 0, 0, 1, 0)));
1328
EXPECT_FALSE(engine.FindCodec(cricket::AudioCodec(0, "", 0, 0, 2, 0)));
1329
EXPECT_FALSE(engine.FindCodec(cricket::AudioCodec(0, "", 5000, 0, 1, 0)));
1330
EXPECT_FALSE(engine.FindCodec(cricket::AudioCodec(0, "", 0, 5000, 1, 0)));
1331
// Check that there aren't any extra codecs lying around.
1332
EXPECT_EQ(13U, engine.codecs().size());
1333
// Verify the payload id of common audio codecs, including CN, ISAC, and G722.
1334
for (std::vector<cricket::AudioCodec>::const_iterator it =
1335
engine.codecs().begin(); it != engine.codecs().end(); ++it) {
1336
if (it->name == "CN" && it->clockrate == 16000) {
1337
EXPECT_EQ(105, it->id);
1338
} else if (it->name == "CN" && it->clockrate == 32000) {
1339
EXPECT_EQ(106, it->id);
1340
} else if (it->name == "ISAC" && it->clockrate == 16000) {
1341
EXPECT_EQ(103, it->id);
1342
} else if (it->name == "ISAC" && it->clockrate == 32000) {
1343
EXPECT_EQ(104, it->id);
1344
} else if (it->name == "G722" && it->clockrate == 16000) {
1345
EXPECT_EQ(9, it->id);
1346
} else if (it->name == "telephone-event") {
1347
EXPECT_EQ(126, it->id);
1348
} else if (it->name == "red") {
1349
EXPECT_EQ(127, it->id);
1356
// Tests that VoE supports at least 32 channels
1357
TEST(WebRtcVoiceEngineTest, Has32Channels) {
1358
cricket::WebRtcVoiceEngine engine;
1359
EXPECT_TRUE(engine.Init());
1361
cricket::VoiceMediaChannel* channels[32];
1362
int num_channels = 0;
1364
while (num_channels < ARRAY_SIZE(channels)) {
1365
cricket::VoiceMediaChannel* channel = engine.CreateChannel();
1369
channels[num_channels++] = channel;
1372
int expected = ARRAY_SIZE(channels);
1373
EXPECT_EQ(expected, num_channels);
1375
while (num_channels > 0) {
1376
delete channels[--num_channels];
1383
// Test our workarounds to WebRtc VoE' munging of the coinit count
1384
TEST(WebRtcVoiceEngineTest, CoInitialize) {
1385
cricket::WebRtcVoiceEngine* engine = new cricket::WebRtcVoiceEngine();
1387
// Initial refcount should be 0.
1388
EXPECT_EQ(S_OK, CoInitializeEx(NULL, COINIT_MULTITHREADED));
1390
// Engine should start even with COM already inited.
1391
EXPECT_TRUE(engine->Init());
1392
engine->Terminate();
1393
EXPECT_TRUE(engine->Init());
1394
engine->Terminate();
1396
// Refcount after terminate should be 1 (in reality 3); test if it is nonzero.
1397
EXPECT_EQ(S_FALSE, CoInitializeEx(NULL, COINIT_MULTITHREADED));
1398
// Decrement refcount to (hopefully) 0.
1403
// Ensure refcount is 0.
1404
EXPECT_EQ(S_OK, CoInitializeEx(NULL, COINIT_MULTITHREADED));