blob: 6746ab650aa87657b60f91d8248b9d6a7f516976 [file] [log] [blame]
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Ben Murdochbb1529c2013-08-08 10:24:53 +01005#include <vector>
6
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007#include "base/environment.h"
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01008#include "base/file_util.h"
9#include "base/files/file_path.h"
10#include "base/path_service.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010011#include "base/strings/stringprintf.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000012#include "base/test/test_timeouts.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000013#include "content/renderer/media/webrtc_audio_capturer.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000014#include "content/renderer/media/webrtc_audio_device_impl.h"
15#include "content/renderer/media/webrtc_audio_renderer.h"
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010016#include "content/renderer/media/webrtc_local_audio_track.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000017#include "content/renderer/render_thread_impl.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000018#include "content/test/webrtc_audio_device_test.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000019#include "media/audio/audio_manager_base.h"
20#include "media/base/audio_hardware_config.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000021#include "testing/gmock/include/gmock/gmock.h"
22#include "third_party/webrtc/voice_engine/include/voe_audio_processing.h"
23#include "third_party/webrtc/voice_engine/include/voe_base.h"
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010024#include "third_party/webrtc/voice_engine/include/voe_codec.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000025#include "third_party/webrtc/voice_engine/include/voe_external_media.h"
26#include "third_party/webrtc/voice_engine/include/voe_file.h"
27#include "third_party/webrtc/voice_engine/include/voe_network.h"
28
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010029#if defined(OS_WIN)
30#include "base/win/windows_version.h"
31#endif
32
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000033using media::AudioParameters;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010034using media::CHANNEL_LAYOUT_STEREO;
Torne (Richard Coles)58218062012-11-14 11:43:16 +000035using testing::_;
36using testing::AnyNumber;
37using testing::InvokeWithoutArgs;
38using testing::Return;
39using testing::StrEq;
40
41namespace content {
42
43namespace {
44
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000045const int kRenderViewId = 1;
Torne (Richard Coles)58218062012-11-14 11:43:16 +000046
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010047// The number of packers that RunWebRtcLoopbackTimeTest() uses for measurement.
48const int kNumberOfPacketsForLoopbackTest = 100;
49
50// The hardware latency we feed to WebRtc.
51const int kHardwareLatencyInMs = 50;
52
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000053scoped_ptr<media::AudioHardwareConfig> CreateRealHardwareConfig(
54 media::AudioManager* manager) {
55 const AudioParameters output_parameters =
56 manager->GetDefaultOutputStreamParameters();
57 const AudioParameters input_parameters =
58 manager->GetInputStreamParameters(
59 media::AudioManagerBase::kDefaultDeviceId);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010060
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000061 return make_scoped_ptr(new media::AudioHardwareConfig(
62 input_parameters, output_parameters));
63}
Torne (Richard Coles)58218062012-11-14 11:43:16 +000064
65// Return true if at least one element in the array matches |value|.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000066bool FindElementInArray(const int* array, int size, int value) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +000067 return (std::find(&array[0], &array[0] + size, value) != &array[size]);
68}
69
70// This method returns false if a non-supported rate is detected on the
71// input or output side.
72// TODO(henrika): add support for automatic fallback to Windows Wave audio
73// if a non-supported rate is detected. It is probably better to detect
74// invalid audio settings by actually trying to open the audio streams instead
75// of relying on hard coded conditions.
76bool HardwareSampleRatesAreValid() {
77 // These are the currently supported hardware sample rates in both directions.
78 // The actual WebRTC client can limit these ranges further depending on
79 // platform but this is the maximum range we support today.
80 int valid_input_rates[] = {16000, 32000, 44100, 48000, 96000};
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000081 int valid_output_rates[] = {16000, 32000, 44100, 48000, 96000};
82
83 media::AudioHardwareConfig* hardware_config =
84 RenderThreadImpl::current()->GetAudioHardwareConfig();
Torne (Richard Coles)58218062012-11-14 11:43:16 +000085
86 // Verify the input sample rate.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000087 int input_sample_rate = hardware_config->GetInputSampleRate();
Torne (Richard Coles)58218062012-11-14 11:43:16 +000088
89 if (!FindElementInArray(valid_input_rates, arraysize(valid_input_rates),
90 input_sample_rate)) {
91 LOG(WARNING) << "Non-supported input sample rate detected.";
92 return false;
93 }
94
95 // Given that the input rate was OK, verify the output rate as well.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000096 int output_sample_rate = hardware_config->GetOutputSampleRate();
Torne (Richard Coles)58218062012-11-14 11:43:16 +000097 if (!FindElementInArray(valid_output_rates, arraysize(valid_output_rates),
98 output_sample_rate)) {
99 LOG(WARNING) << "Non-supported output sample rate detected.";
100 return false;
101 }
102
103 return true;
104}
105
Ben Murdochbb1529c2013-08-08 10:24:53 +0100106// Utility method which creates and initializes the audio capturer and adds it
107// to WebRTC audio device. This method should be used in tests where
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000108// HardwareSampleRatesAreValid() has been called and returned true.
Ben Murdochbb1529c2013-08-08 10:24:53 +0100109bool CreateAndInitializeCapturer(WebRtcAudioDeviceImpl* webrtc_audio_device) {
110 DCHECK(webrtc_audio_device);
111 scoped_refptr<WebRtcAudioCapturer> capturer(
112 WebRtcAudioCapturer::CreateCapturer());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000113
114 media::AudioHardwareConfig* hardware_config =
115 RenderThreadImpl::current()->GetAudioHardwareConfig();
116
117 // Use native capture sample rate and channel configuration to get some
118 // action in this test.
119 int sample_rate = hardware_config->GetInputSampleRate();
120 media::ChannelLayout channel_layout =
121 hardware_config->GetInputChannelLayout();
Ben Murdochbb1529c2013-08-08 10:24:53 +0100122 if (!capturer->Initialize(kRenderViewId, channel_layout, sample_rate, 1,
123 media::AudioManagerBase::kDefaultDeviceId)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000124 return false;
Ben Murdochbb1529c2013-08-08 10:24:53 +0100125 }
126
127 // Add the capturer to the WebRtcAudioDeviceImpl.
128 webrtc_audio_device->AddAudioCapturer(capturer);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000129
130 return true;
131}
132
Ben Murdochbb1529c2013-08-08 10:24:53 +0100133// Create and start a local audio track. Starting the audio track will connect
134// the audio track to the capturer and also start the source of the capturer.
135// Also, connect the sink to the audio track.
136scoped_refptr<WebRtcLocalAudioTrack>
137CreateAndStartLocalAudioTrack(WebRtcAudioCapturer* capturer,
138 WebRtcAudioCapturerSink* sink) {
139 scoped_refptr<WebRtcLocalAudioTrack> local_audio_track(
140 WebRtcLocalAudioTrack::Create(std::string(), capturer, NULL));
141 local_audio_track->AddSink(sink);
142 local_audio_track->Start();
143 return local_audio_track;
144}
145
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000146class WebRTCMediaProcessImpl : public webrtc::VoEMediaProcess {
147 public:
148 explicit WebRTCMediaProcessImpl(base::WaitableEvent* event)
149 : event_(event),
150 channel_id_(-1),
151 type_(webrtc::kPlaybackPerChannel),
152 packet_size_(0),
153 sample_rate_(0),
154 channels_(0) {
155 }
156 virtual ~WebRTCMediaProcessImpl() {}
157
158 // TODO(henrika): Refactor in WebRTC and convert to Chrome coding style.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100159 virtual void Process(int channel,
160 webrtc::ProcessingTypes type,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100161 int16_t audio_10ms[],
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100162 int length,
163 int sampling_freq,
164 bool is_stereo) OVERRIDE {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000165 base::AutoLock auto_lock(lock_);
166 channel_id_ = channel;
167 type_ = type;
168 packet_size_ = length;
169 sample_rate_ = sampling_freq;
170 channels_ = (is_stereo ? 2 : 1);
171 if (event_) {
172 // Signal that a new callback has been received.
173 event_->Signal();
174 }
175 }
176
177 int channel_id() const {
178 base::AutoLock auto_lock(lock_);
179 return channel_id_;
180 }
181
182 int type() const {
183 base::AutoLock auto_lock(lock_);
184 return type_;
185 }
186
187 int packet_size() const {
188 base::AutoLock auto_lock(lock_);
189 return packet_size_;
190 }
191
192 int sample_rate() const {
193 base::AutoLock auto_lock(lock_);
194 return sample_rate_;
195 }
196
197 private:
198 base::WaitableEvent* event_;
199 int channel_id_;
200 webrtc::ProcessingTypes type_;
201 int packet_size_;
202 int sample_rate_;
203 int channels_;
204 mutable base::Lock lock_;
205 DISALLOW_COPY_AND_ASSIGN(WebRTCMediaProcessImpl);
206};
207
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100208class MockWebRtcAudioCapturerSink : public WebRtcAudioCapturerSink {
209 public:
210 explicit MockWebRtcAudioCapturerSink(base::WaitableEvent* event)
211 : event_(event) {
212 DCHECK(event_);
213 }
214 virtual ~MockWebRtcAudioCapturerSink() {}
215
216 // WebRtcAudioCapturerSink implementation.
Ben Murdochbb1529c2013-08-08 10:24:53 +0100217 virtual int CaptureData(const std::vector<int>& channels,
218 const int16* audio_data,
219 int sample_rate,
220 int number_of_channels,
221 int number_of_frames,
222 int audio_delay_milliseconds,
223 int current_volume,
224 bool need_audio_processing) OVERRIDE {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100225 // Signal that a callback has been received.
226 event_->Signal();
Ben Murdochbb1529c2013-08-08 10:24:53 +0100227 return 0;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100228 }
229
230 // Set the format for the capture audio parameters.
231 virtual void SetCaptureFormat(
232 const media::AudioParameters& params) OVERRIDE {}
233
234 private:
235 base::WaitableEvent* event_;
236
237 DISALLOW_COPY_AND_ASSIGN(MockWebRtcAudioCapturerSink);
238};
239
240class MockWebRtcAudioRendererSource : public WebRtcAudioRendererSource {
241 public:
242 explicit MockWebRtcAudioRendererSource(base::WaitableEvent* event)
243 : event_(event) {
244 DCHECK(event_);
245 }
246 virtual ~MockWebRtcAudioRendererSource() {}
247
248 // WebRtcAudioRendererSource implementation.
249 virtual void RenderData(uint8* audio_data,
250 int number_of_channels,
251 int number_of_frames,
252 int audio_delay_milliseconds) OVERRIDE {
253 // Signal that a callback has been received.
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100254 // Initialize the memory to zero to avoid uninitialized warning from
255 // Valgrind.
256 memset(audio_data, 0,
257 sizeof(int16) * number_of_channels * number_of_frames);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100258 event_->Signal();
259 }
260
261 virtual void SetRenderFormat(const media::AudioParameters& params) OVERRIDE {
262 }
263
264 virtual void RemoveAudioRenderer(WebRtcAudioRenderer* renderer) OVERRIDE {};
265
266 private:
267 base::WaitableEvent* event_;
268
269 DISALLOW_COPY_AND_ASSIGN(MockWebRtcAudioRendererSource);
270};
271
272// Prints numerical information to stdout in a controlled format so we can plot
273// the result.
274void PrintPerfResultMs(const char* graph, const char* trace, float time_ms) {
275 std::string times;
276 base::StringAppendF(&times, "%.2f,", time_ms);
277 std::string result = base::StringPrintf(
278 "%sRESULT %s%s: %s= %s%s%s %s\n", "*", graph, "",
279 trace, "[", times.c_str(), "]", "ms");
280
281 fflush(stdout);
282 printf("%s", result.c_str());
283 fflush(stdout);
284}
285
286void ReadDataFromSpeechFile(char* data, int length) {
287 base::FilePath data_file;
288 CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &data_file));
289 data_file =
290 data_file.Append(FILE_PATH_LITERAL("media"))
291 .Append(FILE_PATH_LITERAL("test"))
292 .Append(FILE_PATH_LITERAL("data"))
293 .Append(FILE_PATH_LITERAL("speech_16b_stereo_48kHz.raw"));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100294 DCHECK(base::PathExists(data_file));
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100295 int64 data_file_size64 = 0;
296 DCHECK(file_util::GetFileSize(data_file, &data_file_size64));
297 EXPECT_EQ(length, file_util::ReadFile(data_file, data, length));
298 DCHECK(data_file_size64 > length);
299}
300
301void SetChannelCodec(webrtc::VoiceEngine* engine, int channel) {
302 // TODO(xians): move the codec as an input param to this function, and add
303 // tests for different codecs, also add support to Android and IOS.
304#if !defined(OS_ANDROID) && !defined(OS_IOS)
305 webrtc::CodecInst isac;
306 strcpy(isac.plname, "ISAC");
307 isac.pltype = 104;
308 isac.pacsize = 960;
309 isac.plfreq = 32000;
310 isac.channels = 1;
311 isac.rate = -1;
312 ScopedWebRTCPtr<webrtc::VoECodec> codec(engine);
313 EXPECT_EQ(0, codec->SetRecPayloadType(channel, isac));
314 EXPECT_EQ(0, codec->SetSendCodec(channel, isac));
315#endif
316}
317
318// Returns the time in millisecond for sending packets to WebRtc for encoding,
319// signal processing, decoding and receiving them back.
320int RunWebRtcLoopbackTimeTest(media::AudioManager* manager,
321 bool enable_apm) {
322 scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
323 new WebRtcAudioDeviceImpl());
324 WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create());
325 EXPECT_TRUE(engine.valid());
326 ScopedWebRTCPtr<webrtc::VoEBase> base(engine.get());
327 EXPECT_TRUE(base.valid());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100328 int err = base->Init(webrtc_audio_device.get());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100329 EXPECT_EQ(0, err);
330
331 // We use SetCaptureFormat() and SetRenderFormat() to configure the audio
332 // parameters so that this test can run on machine without hardware device.
333 const media::AudioParameters params = media::AudioParameters(
334 media::AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
335 48000, 2, 480);
336 WebRtcAudioCapturerSink* capturer_sink =
337 static_cast<WebRtcAudioCapturerSink*>(webrtc_audio_device.get());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100338 WebRtcAudioRendererSource* renderer_source =
339 static_cast<WebRtcAudioRendererSource*>(webrtc_audio_device.get());
340 renderer_source->SetRenderFormat(params);
341
342 // Turn on/off all the signal processing components like AGC, AEC and NS.
343 ScopedWebRTCPtr<webrtc::VoEAudioProcessing> audio_processing(engine.get());
344 EXPECT_TRUE(audio_processing.valid());
345 audio_processing->SetAgcStatus(enable_apm);
346 audio_processing->SetNsStatus(enable_apm);
347 audio_processing->SetEcStatus(enable_apm);
348
349 // Create a voice channel for the WebRtc.
350 int channel = base->CreateChannel();
351 EXPECT_NE(-1, channel);
352 SetChannelCodec(engine.get(), channel);
353
354 // Use our fake network transmission and start playout and recording.
355 ScopedWebRTCPtr<webrtc::VoENetwork> network(engine.get());
356 EXPECT_TRUE(network.valid());
357 scoped_ptr<WebRTCTransportImpl> transport(
358 new WebRTCTransportImpl(network.get()));
359 EXPECT_EQ(0, network->RegisterExternalTransport(channel, *transport.get()));
360 EXPECT_EQ(0, base->StartPlayout(channel));
361 EXPECT_EQ(0, base->StartSend(channel));
362
363 // Read speech data from a speech test file.
Ben Murdochbb1529c2013-08-08 10:24:53 +0100364 const int input_packet_size =
365 params.frames_per_buffer() * 2 * params.channels();
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100366 const int num_output_channels = webrtc_audio_device->output_channels();
367 const int output_packet_size = webrtc_audio_device->output_buffer_size() * 2 *
368 num_output_channels;
369 const size_t length = input_packet_size * kNumberOfPacketsForLoopbackTest;
370 scoped_ptr<char[]> capture_data(new char[length]);
371 ReadDataFromSpeechFile(capture_data.get(), length);
372
373 // Start the timer.
374 scoped_ptr<uint8[]> buffer(new uint8[output_packet_size]);
375 base::Time start_time = base::Time::Now();
376 int delay = 0;
Ben Murdochbb1529c2013-08-08 10:24:53 +0100377 std::vector<int> voe_channels;
378 voe_channels.push_back(channel);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100379 for (int j = 0; j < kNumberOfPacketsForLoopbackTest; ++j) {
380 // Sending fake capture data to WebRtc.
381 capturer_sink->CaptureData(
Ben Murdochbb1529c2013-08-08 10:24:53 +0100382 voe_channels,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100383 reinterpret_cast<int16*>(capture_data.get() + input_packet_size * j),
Ben Murdochbb1529c2013-08-08 10:24:53 +0100384 params.sample_rate(), params.channels(), params.frames_per_buffer(),
385 kHardwareLatencyInMs, 1.0, enable_apm);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100386
387 // Receiving data from WebRtc.
388 renderer_source->RenderData(
389 reinterpret_cast<uint8*>(buffer.get()),
390 num_output_channels, webrtc_audio_device->output_buffer_size(),
391 kHardwareLatencyInMs + delay);
392 delay = (base::Time::Now() - start_time).InMilliseconds();
393 }
394
395 int latency = (base::Time::Now() - start_time).InMilliseconds();
396
397 EXPECT_EQ(0, base->StopSend(channel));
398 EXPECT_EQ(0, base->StopPlayout(channel));
399 EXPECT_EQ(0, base->DeleteChannel(channel));
400 EXPECT_EQ(0, base->Terminate());
401
402 return latency;
403}
404
405} // namespace
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000406
407// Trivial test which verifies that one part of the test harness
408// (HardwareSampleRatesAreValid()) works as intended for all supported
409// hardware input sample rates.
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100410TEST_F(MAYBE_WebRTCAudioDeviceTest, TestValidInputRates) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000411 int valid_rates[] = {16000, 32000, 44100, 48000, 96000};
412
413 // Verify that we will approve all rates listed in |valid_rates|.
414 for (size_t i = 0; i < arraysize(valid_rates); ++i) {
415 EXPECT_TRUE(FindElementInArray(valid_rates, arraysize(valid_rates),
416 valid_rates[i]));
417 }
418
419 // Verify that any value outside the valid range results in negative
420 // find results.
421 int invalid_rates[] = {-1, 0, 8000, 11025, 22050, 192000};
422 for (size_t i = 0; i < arraysize(invalid_rates); ++i) {
423 EXPECT_FALSE(FindElementInArray(valid_rates, arraysize(valid_rates),
424 invalid_rates[i]));
425 }
426}
427
428// Trivial test which verifies that one part of the test harness
429// (HardwareSampleRatesAreValid()) works as intended for all supported
430// hardware output sample rates.
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100431TEST_F(MAYBE_WebRTCAudioDeviceTest, TestValidOutputRates) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000432 int valid_rates[] = {44100, 48000, 96000};
433
434 // Verify that we will approve all rates listed in |valid_rates|.
435 for (size_t i = 0; i < arraysize(valid_rates); ++i) {
436 EXPECT_TRUE(FindElementInArray(valid_rates, arraysize(valid_rates),
437 valid_rates[i]));
438 }
439
440 // Verify that any value outside the valid range results in negative
441 // find results.
442 int invalid_rates[] = {-1, 0, 8000, 11025, 22050, 32000, 192000};
443 for (size_t i = 0; i < arraysize(invalid_rates); ++i) {
444 EXPECT_FALSE(FindElementInArray(valid_rates, arraysize(valid_rates),
445 invalid_rates[i]));
446 }
447}
448
449// Basic test that instantiates and initializes an instance of
450// WebRtcAudioDeviceImpl.
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100451TEST_F(MAYBE_WebRTCAudioDeviceTest, Construct) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100452#if defined(OS_WIN)
453 // This test crashes on Win XP bots.
454 if (base::win::GetVersion() <= base::win::VERSION_XP)
455 return;
456#endif
457
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000458 AudioParameters input_params(
459 AudioParameters::AUDIO_PCM_LOW_LATENCY,
460 media::CHANNEL_LAYOUT_MONO,
461 48000,
462 16,
463 480);
464
465 AudioParameters output_params(
466 AudioParameters::AUDIO_PCM_LOW_LATENCY,
467 media::CHANNEL_LAYOUT_STEREO,
468 48000,
469 16,
470 480);
471
472 media::AudioHardwareConfig audio_config(input_params, output_params);
473 SetAudioHardwareConfig(&audio_config);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000474
475 scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
476 new WebRtcAudioDeviceImpl());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000477
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000478 WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create());
479 ASSERT_TRUE(engine.valid());
480
481 ScopedWebRTCPtr<webrtc::VoEBase> base(engine.get());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100482 int err = base->Init(webrtc_audio_device.get());
Ben Murdochbb1529c2013-08-08 10:24:53 +0100483 EXPECT_TRUE(CreateAndInitializeCapturer(webrtc_audio_device.get()));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000484 EXPECT_EQ(0, err);
485 EXPECT_EQ(0, base->Terminate());
486}
487
488// Verify that a call to webrtc::VoEBase::StartPlayout() starts audio output
489// with the correct set of parameters. A WebRtcAudioDeviceImpl instance will
490// be utilized to implement the actual audio path. The test registers a
491// webrtc::VoEExternalMedia implementation to hijack the output audio and
492// verify that streaming starts correctly.
493// Disabled when running headless since the bots don't have the required config.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000494// Flaky, http://crbug.com/167299 .
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100495TEST_F(MAYBE_WebRTCAudioDeviceTest, DISABLED_StartPlayout) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000496 if (!has_output_devices_) {
497 LOG(WARNING) << "No output device detected.";
498 return;
499 }
500
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000501 scoped_ptr<media::AudioHardwareConfig> config =
502 CreateRealHardwareConfig(audio_manager_.get());
503 SetAudioHardwareConfig(config.get());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000504
505 if (!HardwareSampleRatesAreValid())
506 return;
507
508 EXPECT_CALL(media_observer(),
509 OnSetAudioStreamStatus(_, 1, StrEq("created"))).Times(1);
510 EXPECT_CALL(media_observer(),
511 OnSetAudioStreamPlaying(_, 1, true)).Times(1);
512 EXPECT_CALL(media_observer(),
513 OnSetAudioStreamStatus(_, 1, StrEq("closed"))).Times(1);
514 EXPECT_CALL(media_observer(),
515 OnDeleteAudioStream(_, 1)).Times(AnyNumber());
516
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000517 scoped_refptr<WebRtcAudioRenderer> renderer =
518 new WebRtcAudioRenderer(kRenderViewId);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000519 scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
520 new WebRtcAudioDeviceImpl());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100521 EXPECT_TRUE(webrtc_audio_device->SetAudioRenderer(renderer.get()));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000522
523 WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create());
524 ASSERT_TRUE(engine.valid());
525
526 ScopedWebRTCPtr<webrtc::VoEBase> base(engine.get());
527 ASSERT_TRUE(base.valid());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100528 int err = base->Init(webrtc_audio_device.get());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000529 ASSERT_EQ(0, err);
530
531 int ch = base->CreateChannel();
532 EXPECT_NE(-1, ch);
533
534 ScopedWebRTCPtr<webrtc::VoEExternalMedia> external_media(engine.get());
535 ASSERT_TRUE(external_media.valid());
536
537 base::WaitableEvent event(false, false);
538 scoped_ptr<WebRTCMediaProcessImpl> media_process(
539 new WebRTCMediaProcessImpl(&event));
540 EXPECT_EQ(0, external_media->RegisterExternalMediaProcessing(
541 ch, webrtc::kPlaybackPerChannel, *media_process.get()));
542
543 EXPECT_EQ(0, base->StartPlayout(ch));
544 renderer->Play();
545
546 EXPECT_TRUE(event.TimedWait(TestTimeouts::action_timeout()));
547 WaitForIOThreadCompletion();
548
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000549 EXPECT_TRUE(webrtc_audio_device->Playing());
550 EXPECT_FALSE(webrtc_audio_device->Recording());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000551 EXPECT_EQ(ch, media_process->channel_id());
552 EXPECT_EQ(webrtc::kPlaybackPerChannel, media_process->type());
553 EXPECT_EQ(80, media_process->packet_size());
554 EXPECT_EQ(8000, media_process->sample_rate());
555
556 EXPECT_EQ(0, external_media->DeRegisterExternalMediaProcessing(
557 ch, webrtc::kPlaybackPerChannel));
558 EXPECT_EQ(0, base->StopPlayout(ch));
559 renderer->Stop();
560
561 EXPECT_EQ(0, base->DeleteChannel(ch));
562 EXPECT_EQ(0, base->Terminate());
563}
564
565// Verify that a call to webrtc::VoEBase::StartRecording() starts audio input
566// with the correct set of parameters. A WebRtcAudioDeviceImpl instance will
567// be utilized to implement the actual audio path. The test registers a
568// webrtc::VoEExternalMedia implementation to hijack the input audio and
569// verify that streaming starts correctly. An external transport implementation
570// is also required to ensure that "sending" can start without actually trying
571// to send encoded packets to the network. Our main interest here is to ensure
572// that the audio capturing starts as it should.
573// Disabled when running headless since the bots don't have the required config.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000574
575// TODO(leozwang): Because ExternalMediaProcessing is disabled in webrtc,
576// disable this unit test on Android for now.
577#if defined(OS_ANDROID)
578#define MAYBE_StartRecording DISABLED_StartRecording
Ben Murdocheb525c52013-07-10 11:40:50 +0100579#elif defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
580// This test is failing on ARM linux: http://crbug.com/238490
581#define MAYBE_StartRecording DISABLED_StartRecording
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000582#else
Ben Murdoch2385ea32013-08-06 11:01:04 +0100583// Flakily hangs on all other platforms as well: crbug.com/268376.
584// When the flakiness has been fixed, you probably want to leave it disabled
585// on the above platforms.
586#define MAYBE_StartRecording DISABLED_StartRecording
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000587#endif
Ben Murdoch2385ea32013-08-06 11:01:04 +0100588
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100589TEST_F(MAYBE_WebRTCAudioDeviceTest, MAYBE_StartRecording) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000590 if (!has_input_devices_ || !has_output_devices_) {
591 LOG(WARNING) << "Missing audio devices.";
592 return;
593 }
594
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000595 scoped_ptr<media::AudioHardwareConfig> config =
596 CreateRealHardwareConfig(audio_manager_.get());
597 SetAudioHardwareConfig(config.get());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000598
599 if (!HardwareSampleRatesAreValid())
600 return;
601
602 // TODO(tommi): extend MediaObserver and MockMediaObserver with support
603 // for new interfaces, like OnSetAudioStreamRecording(). When done, add
604 // EXPECT_CALL() macros here.
605 scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
606 new WebRtcAudioDeviceImpl());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000607
608 WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create());
609 ASSERT_TRUE(engine.valid());
610
611 ScopedWebRTCPtr<webrtc::VoEBase> base(engine.get());
612 ASSERT_TRUE(base.valid());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100613 int err = base->Init(webrtc_audio_device.get());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000614 ASSERT_EQ(0, err);
615
616 int ch = base->CreateChannel();
617 EXPECT_NE(-1, ch);
618
619 ScopedWebRTCPtr<webrtc::VoEExternalMedia> external_media(engine.get());
620 ASSERT_TRUE(external_media.valid());
621
622 base::WaitableEvent event(false, false);
623 scoped_ptr<WebRTCMediaProcessImpl> media_process(
624 new WebRTCMediaProcessImpl(&event));
625 EXPECT_EQ(0, external_media->RegisterExternalMediaProcessing(
626 ch, webrtc::kRecordingPerChannel, *media_process.get()));
627
628 // We must add an external transport implementation to be able to start
629 // recording without actually sending encoded packets to the network. All
630 // we want to do here is to verify that audio capturing starts as it should.
631 ScopedWebRTCPtr<webrtc::VoENetwork> network(engine.get());
632 scoped_ptr<WebRTCTransportImpl> transport(
633 new WebRTCTransportImpl(network.get()));
634 EXPECT_EQ(0, network->RegisterExternalTransport(ch, *transport.get()));
635 EXPECT_EQ(0, base->StartSend(ch));
636
Ben Murdochbb1529c2013-08-08 10:24:53 +0100637 // Create and initialize the capturer which starts the source of the data
638 // flow.
639 EXPECT_TRUE(CreateAndInitializeCapturer(webrtc_audio_device.get()));
640
641 // Create and start a local audio track which is bridging the data flow
642 // between the capturer and WebRtcAudioDeviceImpl.
643 scoped_refptr<WebRtcLocalAudioTrack> local_audio_track(
644 CreateAndStartLocalAudioTrack(webrtc_audio_device->GetDefaultCapturer(),
645 webrtc_audio_device));
646 // connect the VoE voice channel to the audio track
647 static_cast<webrtc::AudioTrackInterface*>(local_audio_track.get())->
648 GetRenderer()->AddChannel(ch);
649
650 // Verify we get the data flow.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000651 EXPECT_TRUE(event.TimedWait(TestTimeouts::action_timeout()));
652 WaitForIOThreadCompletion();
653
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000654 EXPECT_FALSE(webrtc_audio_device->Playing());
655 EXPECT_TRUE(webrtc_audio_device->Recording());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000656 EXPECT_EQ(ch, media_process->channel_id());
657 EXPECT_EQ(webrtc::kRecordingPerChannel, media_process->type());
658 EXPECT_EQ(80, media_process->packet_size());
659 EXPECT_EQ(8000, media_process->sample_rate());
660
661 EXPECT_EQ(0, external_media->DeRegisterExternalMediaProcessing(
662 ch, webrtc::kRecordingPerChannel));
663 EXPECT_EQ(0, base->StopSend(ch));
664
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100665 local_audio_track->Stop();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000666 EXPECT_EQ(0, base->DeleteChannel(ch));
667 EXPECT_EQ(0, base->Terminate());
668}
669
670// Uses WebRtcAudioDeviceImpl to play a local wave file.
671// Disabled when running headless since the bots don't have the required config.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000672// Flaky, http://crbug.com/167298 .
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100673TEST_F(MAYBE_WebRTCAudioDeviceTest, DISABLED_PlayLocalFile) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000674 if (!has_output_devices_) {
675 LOG(WARNING) << "No output device detected.";
676 return;
677 }
678
679 std::string file_path(
680 GetTestDataPath(FILE_PATH_LITERAL("speechmusic_mono_16kHz.pcm")));
681
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000682 scoped_ptr<media::AudioHardwareConfig> config =
683 CreateRealHardwareConfig(audio_manager_.get());
684 SetAudioHardwareConfig(config.get());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000685
686 if (!HardwareSampleRatesAreValid())
687 return;
688
689 EXPECT_CALL(media_observer(),
690 OnSetAudioStreamStatus(_, 1, StrEq("created"))).Times(1);
691 EXPECT_CALL(media_observer(),
692 OnSetAudioStreamPlaying(_, 1, true)).Times(1);
693 EXPECT_CALL(media_observer(),
694 OnSetAudioStreamStatus(_, 1, StrEq("closed"))).Times(1);
695 EXPECT_CALL(media_observer(),
696 OnDeleteAudioStream(_, 1)).Times(AnyNumber());
697
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000698 scoped_refptr<WebRtcAudioRenderer> renderer =
699 new WebRtcAudioRenderer(kRenderViewId);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000700 scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
701 new WebRtcAudioDeviceImpl());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100702 EXPECT_TRUE(webrtc_audio_device->SetAudioRenderer(renderer.get()));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000703
704 WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create());
705 ASSERT_TRUE(engine.valid());
706
707 ScopedWebRTCPtr<webrtc::VoEBase> base(engine.get());
708 ASSERT_TRUE(base.valid());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100709 int err = base->Init(webrtc_audio_device.get());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000710 ASSERT_EQ(0, err);
711
712 int ch = base->CreateChannel();
713 EXPECT_NE(-1, ch);
714 EXPECT_EQ(0, base->StartPlayout(ch));
715 renderer->Play();
716
717 ScopedWebRTCPtr<webrtc::VoEFile> file(engine.get());
718 ASSERT_TRUE(file.valid());
719 int duration = 0;
720 EXPECT_EQ(0, file->GetFileDuration(file_path.c_str(), duration,
721 webrtc::kFileFormatPcm16kHzFile));
722 EXPECT_NE(0, duration);
723
724 EXPECT_EQ(0, file->StartPlayingFileLocally(ch, file_path.c_str(), false,
725 webrtc::kFileFormatPcm16kHzFile));
726
727 // Play 2 seconds worth of audio and then quit.
728 message_loop_.PostDelayedTask(FROM_HERE,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100729 base::MessageLoop::QuitClosure(),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000730 base::TimeDelta::FromSeconds(6));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000731 message_loop_.Run();
732
733 renderer->Stop();
734 EXPECT_EQ(0, base->StopSend(ch));
735 EXPECT_EQ(0, base->StopPlayout(ch));
736 EXPECT_EQ(0, base->DeleteChannel(ch));
737 EXPECT_EQ(0, base->Terminate());
738}
739
740// Uses WebRtcAudioDeviceImpl to play out recorded audio in loopback.
741// An external transport implementation is utilized to feed back RTP packets
742// which are recorded, encoded, packetized into RTP packets and finally
743// "transmitted". The RTP packets are then fed back into the VoiceEngine
744// where they are decoded and played out on the default audio output device.
745// Disabled when running headless since the bots don't have the required config.
746// TODO(henrika): improve quality by using a wideband codec, enabling noise-
747// suppressions etc.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000748// FullDuplexAudioWithAGC is flaky on Android, disable it for now.
Ben Murdochbb1529c2013-08-08 10:24:53 +0100749// Also flakily hangs on Windows: crbug.com/269348.
750#if defined(OS_ANDROID) || defined(OS_WIN)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000751#define MAYBE_FullDuplexAudioWithAGC DISABLED_FullDuplexAudioWithAGC
752#else
753#define MAYBE_FullDuplexAudioWithAGC FullDuplexAudioWithAGC
754#endif
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100755TEST_F(MAYBE_WebRTCAudioDeviceTest, MAYBE_FullDuplexAudioWithAGC) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000756 if (!has_output_devices_ || !has_input_devices_) {
757 LOG(WARNING) << "Missing audio devices.";
758 return;
759 }
760
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000761 scoped_ptr<media::AudioHardwareConfig> config =
762 CreateRealHardwareConfig(audio_manager_.get());
763 SetAudioHardwareConfig(config.get());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000764
765 if (!HardwareSampleRatesAreValid())
766 return;
767
768 EXPECT_CALL(media_observer(),
769 OnSetAudioStreamStatus(_, 1, StrEq("created")));
770 EXPECT_CALL(media_observer(),
771 OnSetAudioStreamPlaying(_, 1, true));
772 EXPECT_CALL(media_observer(),
773 OnSetAudioStreamStatus(_, 1, StrEq("closed")));
774 EXPECT_CALL(media_observer(),
775 OnDeleteAudioStream(_, 1)).Times(AnyNumber());
776
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000777 scoped_refptr<WebRtcAudioRenderer> renderer =
778 new WebRtcAudioRenderer(kRenderViewId);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000779 scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
780 new WebRtcAudioDeviceImpl());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100781 EXPECT_TRUE(webrtc_audio_device->SetAudioRenderer(renderer.get()));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000782
783 WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create());
784 ASSERT_TRUE(engine.valid());
785
786 ScopedWebRTCPtr<webrtc::VoEBase> base(engine.get());
787 ASSERT_TRUE(base.valid());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100788 int err = base->Init(webrtc_audio_device.get());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000789 ASSERT_EQ(0, err);
790
791 ScopedWebRTCPtr<webrtc::VoEAudioProcessing> audio_processing(engine.get());
792 ASSERT_TRUE(audio_processing.valid());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000793#if defined(OS_ANDROID)
794 // On Android, by default AGC is off.
795 bool enabled = true;
796 webrtc::AgcModes agc_mode = webrtc::kAgcDefault;
797 EXPECT_EQ(0, audio_processing->GetAgcStatus(enabled, agc_mode));
798 EXPECT_FALSE(enabled);
799#else
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000800 bool enabled = false;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000801 webrtc::AgcModes agc_mode = webrtc::kAgcDefault;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000802 EXPECT_EQ(0, audio_processing->GetAgcStatus(enabled, agc_mode));
803 EXPECT_TRUE(enabled);
804 EXPECT_EQ(agc_mode, webrtc::kAgcAdaptiveAnalog);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000805#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000806
807 int ch = base->CreateChannel();
808 EXPECT_NE(-1, ch);
809
Ben Murdochbb1529c2013-08-08 10:24:53 +0100810 EXPECT_TRUE(CreateAndInitializeCapturer(webrtc_audio_device.get()));
811 scoped_refptr<WebRtcLocalAudioTrack> local_audio_track(
812 CreateAndStartLocalAudioTrack(webrtc_audio_device->GetDefaultCapturer(),
813 webrtc_audio_device));
814 // connect the VoE voice channel to the audio track
815 static_cast<webrtc::AudioTrackInterface*>(local_audio_track.get())->
816 GetRenderer()->AddChannel(ch);
817
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000818 ScopedWebRTCPtr<webrtc::VoENetwork> network(engine.get());
819 ASSERT_TRUE(network.valid());
820 scoped_ptr<WebRTCTransportImpl> transport(
821 new WebRTCTransportImpl(network.get()));
822 EXPECT_EQ(0, network->RegisterExternalTransport(ch, *transport.get()));
823 EXPECT_EQ(0, base->StartPlayout(ch));
824 EXPECT_EQ(0, base->StartSend(ch));
825 renderer->Play();
826
827 LOG(INFO) << ">> You should now be able to hear yourself in loopback...";
828 message_loop_.PostDelayedTask(FROM_HERE,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100829 base::MessageLoop::QuitClosure(),
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000830 base::TimeDelta::FromSeconds(2));
831 message_loop_.Run();
832
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100833 local_audio_track->Stop();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000834 renderer->Stop();
835 EXPECT_EQ(0, base->StopSend(ch));
836 EXPECT_EQ(0, base->StopPlayout(ch));
837
838 EXPECT_EQ(0, base->DeleteChannel(ch));
839 EXPECT_EQ(0, base->Terminate());
840}
841
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100842// Test times out on bots, see http://crbug.com/247447
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100843TEST_F(MAYBE_WebRTCAudioDeviceTest, DISABLED_WebRtcRecordingSetupTime) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100844 if (!has_input_devices_) {
845 LOG(WARNING) << "Missing audio capture devices.";
846 return;
847 }
848
849 scoped_ptr<media::AudioHardwareConfig> config =
850 CreateRealHardwareConfig(audio_manager_.get());
851 SetAudioHardwareConfig(config.get());
852
853 if (!HardwareSampleRatesAreValid())
854 return;
855
856 scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
857 new WebRtcAudioDeviceImpl());
858
859 WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create());
860 ASSERT_TRUE(engine.valid());
861
862 ScopedWebRTCPtr<webrtc::VoEBase> base(engine.get());
863 ASSERT_TRUE(base.valid());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100864 int err = base->Init(webrtc_audio_device.get());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100865 ASSERT_EQ(0, err);
866
Ben Murdochbb1529c2013-08-08 10:24:53 +0100867 int ch = base->CreateChannel();
868 EXPECT_NE(-1, ch);
869
870 EXPECT_TRUE(CreateAndInitializeCapturer(webrtc_audio_device.get()));
871 base::WaitableEvent event(false, false);
872 scoped_ptr<MockWebRtcAudioCapturerSink> sink(
873 new MockWebRtcAudioCapturerSink(&event));
874
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100875 // Create and start a local audio track. Starting the audio track will connect
876 // the audio track to the capturer and also start the source of the capturer.
877 scoped_refptr<WebRtcLocalAudioTrack> local_audio_track(
Ben Murdochbb1529c2013-08-08 10:24:53 +0100878 CreateAndStartLocalAudioTrack(
879 webrtc_audio_device->GetDefaultCapturer().get(), sink.get()));
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100880
Ben Murdochbb1529c2013-08-08 10:24:53 +0100881 // connect the VoE voice channel to the audio track.
882 static_cast<webrtc::AudioTrackInterface*>(local_audio_track.get())->
883 GetRenderer()->AddChannel(ch);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100884
885 base::Time start_time = base::Time::Now();
886 EXPECT_EQ(0, base->StartSend(ch));
887
888 EXPECT_TRUE(event.TimedWait(TestTimeouts::action_timeout()));
889 int delay = (base::Time::Now() - start_time).InMilliseconds();
890 PrintPerfResultMs("webrtc_recording_setup_c", "t", delay);
891
Ben Murdochbb1529c2013-08-08 10:24:53 +0100892 local_audio_track->RemoveSink(sink.get());
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100893 local_audio_track->Stop();
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100894 EXPECT_EQ(0, base->StopSend(ch));
895 EXPECT_EQ(0, base->DeleteChannel(ch));
896 EXPECT_EQ(0, base->Terminate());
897}
898
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100899TEST_F(MAYBE_WebRTCAudioDeviceTest, WebRtcPlayoutSetupTime) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100900 if (!has_output_devices_) {
901 LOG(WARNING) << "No output device detected.";
902 return;
903 }
904
905 scoped_ptr<media::AudioHardwareConfig> config =
906 CreateRealHardwareConfig(audio_manager_.get());
907 SetAudioHardwareConfig(config.get());
908
909 if (!HardwareSampleRatesAreValid())
910 return;
911
912 EXPECT_CALL(media_observer(),
913 OnSetAudioStreamStatus(_, 1, _)).Times(AnyNumber());
914 EXPECT_CALL(media_observer(),
915 OnSetAudioStreamPlaying(_, 1, true));
916 EXPECT_CALL(media_observer(),
917 OnDeleteAudioStream(_, 1)).Times(AnyNumber());
918
919 base::WaitableEvent event(false, false);
920 scoped_ptr<MockWebRtcAudioRendererSource> renderer_source(
921 new MockWebRtcAudioRendererSource(&event));
922 scoped_refptr<WebRtcAudioRenderer> renderer =
923 new WebRtcAudioRenderer(kRenderViewId);
924 renderer->Initialize(renderer_source.get());
925
926 // Start the timer and playout.
927 base::Time start_time = base::Time::Now();
928 renderer->Play();
929 EXPECT_TRUE(event.TimedWait(TestTimeouts::action_timeout()));
930 int delay = (base::Time::Now() - start_time).InMilliseconds();
931 PrintPerfResultMs("webrtc_playout_setup_c", "t", delay);
932
933 renderer->Stop();
934}
935
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100936#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
937// Timing out on ARM linux bot: http://crbug.com/238490
938#define MAYBE_WebRtcLoopbackTimeWithoutSignalProcessing \
939 DISABLED_WebRtcLoopbackTimeWithoutSignalProcessing
940#else
941#define MAYBE_WebRtcLoopbackTimeWithoutSignalProcessing \
942 WebRtcLoopbackTimeWithoutSignalProcessing
943#endif
944
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100945TEST_F(MAYBE_WebRTCAudioDeviceTest,
946 MAYBE_WebRtcLoopbackTimeWithoutSignalProcessing) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100947 int latency = RunWebRtcLoopbackTimeTest(audio_manager_.get(), false);
948 PrintPerfResultMs("webrtc_loopback_without_sigal_processing (100 packets)",
949 "t", latency);
950}
951
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100952#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
953// Timing out on ARM linux bot: http://crbug.com/238490
954#define MAYBE_WebRtcLoopbackTimeWithSignalProcessing \
955 DISABLED_WebRtcLoopbackTimeWithSignalProcessing
956#else
957#define MAYBE_WebRtcLoopbackTimeWithSignalProcessing \
958 WebRtcLoopbackTimeWithSignalProcessing
959#endif
960
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100961TEST_F(MAYBE_WebRTCAudioDeviceTest,
962 MAYBE_WebRtcLoopbackTimeWithSignalProcessing) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100963 int latency = RunWebRtcLoopbackTimeTest(audio_manager_.get(), true);
964 PrintPerfResultMs("webrtc_loopback_with_signal_processing (100 packets)",
965 "t", latency);
966}
967
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000968} // namespace content