Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(28)

Side by Side Diff: content/renderer/media/webrtc_audio_device_unittest.cc

Issue 194813002: Removing WebRTCAudioDeviceTest test suite (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: xians@ Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « content/content_tests.gypi ('k') | content/test/webrtc_audio_device_test.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // 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
5 #include <vector>
6
7 #include "base/environment.h"
8 #include "base/file_util.h"
9 #include "base/files/file_path.h"
10 #include "base/path_service.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/test/test_timeouts.h"
13 #include "content/renderer/media/mock_media_stream_dependency_factory.h"
14 #include "content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h"
15 #include "content/renderer/media/webrtc_audio_capturer.h"
16 #include "content/renderer/media/webrtc_audio_device_impl.h"
17 #include "content/renderer/media/webrtc_audio_renderer.h"
18 #include "content/renderer/media/webrtc_local_audio_track.h"
19 #include "content/renderer/render_thread_impl.h"
20 #include "content/test/webrtc_audio_device_test.h"
21 #include "media/audio/audio_manager_base.h"
22 #include "media/base/audio_hardware_config.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "third_party/WebKit/public/platform/WebMediaConstraints.h"
25 #include "third_party/webrtc/voice_engine/include/voe_audio_processing.h"
26 #include "third_party/webrtc/voice_engine/include/voe_base.h"
27 #include "third_party/webrtc/voice_engine/include/voe_codec.h"
28 #include "third_party/webrtc/voice_engine/include/voe_external_media.h"
29 #include "third_party/webrtc/voice_engine/include/voe_file.h"
30 #include "third_party/webrtc/voice_engine/include/voe_network.h"
31
32 #if defined(OS_WIN)
33 #include "base/win/windows_version.h"
34 #endif
35
36 using media::AudioParameters;
37 using media::CHANNEL_LAYOUT_STEREO;
38 using testing::_;
39 using testing::AnyNumber;
40 using testing::InvokeWithoutArgs;
41 using testing::Return;
42 using testing::StrEq;
43
44 namespace content {
45
46 namespace {
47
48 const int kRenderViewId = 1;
49
50 // The number of packers that RunWebRtcLoopbackTimeTest() uses for measurement.
51 const int kNumberOfPacketsForLoopbackTest = 100;
52
53 // The hardware latency we feed to WebRtc.
54 const int kHardwareLatencyInMs = 50;
55
56 scoped_ptr<media::AudioHardwareConfig> CreateRealHardwareConfig(
57 media::AudioManager* manager) {
58 const AudioParameters output_parameters =
59 manager->GetDefaultOutputStreamParameters();
60 const AudioParameters input_parameters =
61 manager->GetInputStreamParameters(
62 media::AudioManagerBase::kDefaultDeviceId);
63
64 return make_scoped_ptr(new media::AudioHardwareConfig(
65 input_parameters, output_parameters));
66 }
67
68 // Return true if at least one element in the array matches |value|.
69 bool FindElementInArray(const int* array, int size, int value) {
70 return (std::find(&array[0], &array[0] + size, value) != &array[size]);
71 }
72
73 // This method returns false if a non-supported rate is detected on the
74 // input or output side.
75 // TODO(henrika): add support for automatic fallback to Windows Wave audio
76 // if a non-supported rate is detected. It is probably better to detect
77 // invalid audio settings by actually trying to open the audio streams instead
78 // of relying on hard coded conditions.
79 bool HardwareSampleRatesAreValid() {
80 // These are the currently supported hardware sample rates in both directions.
81 // The actual WebRTC client can limit these ranges further depending on
82 // platform but this is the maximum range we support today.
83 int valid_input_rates[] = {16000, 32000, 44100, 48000, 96000};
84 int valid_output_rates[] = {16000, 32000, 44100, 48000, 96000};
85
86 media::AudioHardwareConfig* hardware_config =
87 RenderThreadImpl::current()->GetAudioHardwareConfig();
88
89 // Verify the input sample rate.
90 int input_sample_rate = hardware_config->GetInputSampleRate();
91
92 if (!FindElementInArray(valid_input_rates, arraysize(valid_input_rates),
93 input_sample_rate)) {
94 LOG(WARNING) << "Non-supported input sample rate detected.";
95 return false;
96 }
97
98 // Given that the input rate was OK, verify the output rate as well.
99 int output_sample_rate = hardware_config->GetOutputSampleRate();
100 if (!FindElementInArray(valid_output_rates, arraysize(valid_output_rates),
101 output_sample_rate)) {
102 LOG(WARNING) << "Non-supported output sample rate detected.";
103 return false;
104 }
105
106 return true;
107 }
108
109 // Utility method which creates the audio capturer, it returns a scoped
110 // reference of the capturer if it is created successfully, otherwise it returns
111 // NULL. This method should be used in tests where
112 // HardwareSampleRatesAreValid() has been called and returned true.
113 scoped_refptr<WebRtcAudioCapturer> CreateAudioCapturer(
114 WebRtcAudioDeviceImpl* webrtc_audio_device) {
115 media::AudioHardwareConfig* hardware_config =
116 RenderThreadImpl::current()->GetAudioHardwareConfig();
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();
122 blink::WebMediaConstraints constraints;
123 StreamDeviceInfo device(MEDIA_DEVICE_AUDIO_CAPTURE,
124 media::AudioManagerBase::kDefaultDeviceName,
125 media::AudioManagerBase::kDefaultDeviceId,
126 sample_rate, channel_layout, 0);
127 device.session_id = 1;
128 return WebRtcAudioCapturer::CreateCapturer(kRenderViewId, device,
129 constraints,
130 webrtc_audio_device);
131 }
132
133 // 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.
136 scoped_ptr<WebRtcLocalAudioTrack>
137 CreateAndStartLocalAudioTrack(WebRtcLocalAudioTrackAdapter* adapter,
138 WebRtcAudioCapturer* capturer,
139 PeerConnectionAudioSink* sink) {
140 scoped_ptr<WebRtcLocalAudioTrack> local_audio_track(
141 new WebRtcLocalAudioTrack(adapter, capturer, NULL));
142
143 local_audio_track->AddSink(sink);
144 local_audio_track->Start();
145 return local_audio_track.Pass();
146 }
147
148 class WebRTCMediaProcessImpl : public webrtc::VoEMediaProcess {
149 public:
150 explicit WebRTCMediaProcessImpl(base::WaitableEvent* event)
151 : event_(event),
152 channel_id_(-1),
153 type_(webrtc::kPlaybackPerChannel),
154 packet_size_(0),
155 sample_rate_(0),
156 channels_(0) {
157 }
158 virtual ~WebRTCMediaProcessImpl() {}
159
160 // TODO(henrika): Refactor in WebRTC and convert to Chrome coding style.
161 virtual void Process(int channel,
162 webrtc::ProcessingTypes type,
163 int16_t audio_10ms[],
164 int length,
165 int sampling_freq,
166 bool is_stereo) OVERRIDE {
167 base::AutoLock auto_lock(lock_);
168 channel_id_ = channel;
169 type_ = type;
170 packet_size_ = length;
171 sample_rate_ = sampling_freq;
172 channels_ = (is_stereo ? 2 : 1);
173 if (event_) {
174 // Signal that a new callback has been received.
175 event_->Signal();
176 }
177 }
178
179 int channel_id() const {
180 base::AutoLock auto_lock(lock_);
181 return channel_id_;
182 }
183
184 int type() const {
185 base::AutoLock auto_lock(lock_);
186 return type_;
187 }
188
189 int packet_size() const {
190 base::AutoLock auto_lock(lock_);
191 return packet_size_;
192 }
193
194 int sample_rate() const {
195 base::AutoLock auto_lock(lock_);
196 return sample_rate_;
197 }
198
199 private:
200 base::WaitableEvent* event_;
201 int channel_id_;
202 webrtc::ProcessingTypes type_;
203 int packet_size_;
204 int sample_rate_;
205 int channels_;
206 mutable base::Lock lock_;
207 DISALLOW_COPY_AND_ASSIGN(WebRTCMediaProcessImpl);
208 };
209
210 // TODO(xians): Use MediaStreamAudioSink.
211 class MockMediaStreamAudioSink : public PeerConnectionAudioSink {
212 public:
213 explicit MockMediaStreamAudioSink(base::WaitableEvent* event)
214 : event_(event) {
215 DCHECK(event_);
216 }
217 virtual ~MockMediaStreamAudioSink() {}
218
219 // PeerConnectionAudioSink implementation.
220 virtual int OnData(const int16* audio_data,
221 int sample_rate,
222 int number_of_channels,
223 int number_of_frames,
224 const std::vector<int>& channels,
225 int audio_delay_milliseconds,
226 int current_volume,
227 bool need_audio_processing,
228 bool key_pressed) OVERRIDE {
229 // Signal that a callback has been received.
230 event_->Signal();
231 return 0;
232 }
233
234 // Set the format for the capture audio parameters.
235 virtual void OnSetFormat(
236 const media::AudioParameters& params) OVERRIDE {}
237
238 private:
239 base::WaitableEvent* event_;
240
241 DISALLOW_COPY_AND_ASSIGN(MockMediaStreamAudioSink);
242 };
243
244 class MockWebRtcAudioRendererSource : public WebRtcAudioRendererSource {
245 public:
246 explicit MockWebRtcAudioRendererSource(base::WaitableEvent* event)
247 : event_(event) {
248 DCHECK(event_);
249 }
250 virtual ~MockWebRtcAudioRendererSource() {}
251
252 // WebRtcAudioRendererSource implementation.
253 virtual void RenderData(media::AudioBus* audio_bus,
254 int sample_rate,
255 int audio_delay_milliseconds) OVERRIDE {
256 // Signal that a callback has been received.
257 // Initialize the memory to zero to avoid uninitialized warning from
258 // Valgrind.
259 audio_bus->Zero();
260 event_->Signal();
261 }
262
263 virtual void RemoveAudioRenderer(WebRtcAudioRenderer* renderer) OVERRIDE {};
264
265 private:
266 base::WaitableEvent* event_;
267
268 DISALLOW_COPY_AND_ASSIGN(MockWebRtcAudioRendererSource);
269 };
270
271 // Prints numerical information to stdout in a controlled format so we can plot
272 // the result.
273 void PrintPerfResultMs(const char* graph, const char* trace, float time_ms) {
274 std::string times;
275 base::StringAppendF(&times, "%.2f,", time_ms);
276 std::string result = base::StringPrintf(
277 "%sRESULT %s%s: %s= %s%s%s %s\n", "*", graph, "",
278 trace, "[", times.c_str(), "]", "ms");
279
280 fflush(stdout);
281 printf("%s", result.c_str());
282 fflush(stdout);
283 }
284
285 void ReadDataFromSpeechFile(char* data, int length) {
286 base::FilePath data_file;
287 CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &data_file));
288 data_file =
289 data_file.Append(FILE_PATH_LITERAL("media"))
290 .Append(FILE_PATH_LITERAL("test"))
291 .Append(FILE_PATH_LITERAL("data"))
292 .Append(FILE_PATH_LITERAL("speech_16b_stereo_48kHz.raw"));
293 DCHECK(base::PathExists(data_file));
294 int64 data_file_size64 = 0;
295 DCHECK(base::GetFileSize(data_file, &data_file_size64));
296 EXPECT_EQ(length, base::ReadFile(data_file, data, length));
297 DCHECK(data_file_size64 > length);
298 }
299
300 void SetChannelCodec(webrtc::VoiceEngine* engine, int channel) {
301 // TODO(xians): move the codec as an input param to this function, and add
302 // tests for different codecs, also add support to Android and IOS.
303 #if !defined(OS_ANDROID) && !defined(OS_IOS)
304 webrtc::CodecInst isac;
305 strcpy(isac.plname, "ISAC");
306 isac.pltype = 104;
307 isac.pacsize = 960;
308 isac.plfreq = 32000;
309 isac.channels = 1;
310 isac.rate = -1;
311 ScopedWebRTCPtr<webrtc::VoECodec> codec(engine);
312 EXPECT_EQ(0, codec->SetRecPayloadType(channel, isac));
313 EXPECT_EQ(0, codec->SetSendCodec(channel, isac));
314 #endif
315 }
316
317 // Returns the time in millisecond for sending packets to WebRtc for encoding,
318 // signal processing, decoding and receiving them back.
319 int RunWebRtcLoopbackTimeTest(media::AudioManager* manager,
320 bool enable_apm) {
321 scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
322 new WebRtcAudioDeviceImpl());
323 WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create());
324 EXPECT_TRUE(engine.valid());
325 ScopedWebRTCPtr<webrtc::VoEBase> base(engine.get());
326 EXPECT_TRUE(base.valid());
327 int err = base->Init(webrtc_audio_device.get());
328 EXPECT_EQ(0, err);
329
330 // We use OnSetFormat() to configure the audio parameters so that this
331 // test can run on machine without hardware device.
332 const media::AudioParameters params = media::AudioParameters(
333 media::AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
334 48000, 2, 480);
335 PeerConnectionAudioSink* capturer_sink =
336 static_cast<PeerConnectionAudioSink*>(webrtc_audio_device.get());
337 WebRtcAudioRendererSource* renderer_source =
338 static_cast<WebRtcAudioRendererSource*>(webrtc_audio_device.get());
339
340 // Turn on/off all the signal processing components like AGC, AEC and NS.
341 ScopedWebRTCPtr<webrtc::VoEAudioProcessing> audio_processing(engine.get());
342 EXPECT_TRUE(audio_processing.valid());
343 audio_processing->SetAgcStatus(enable_apm);
344 audio_processing->SetNsStatus(enable_apm);
345 audio_processing->SetEcStatus(enable_apm);
346
347 // Create a voice channel for the WebRtc.
348 int channel = base->CreateChannel();
349 EXPECT_NE(-1, channel);
350 SetChannelCodec(engine.get(), channel);
351
352 // Use our fake network transmission and start playout and recording.
353 ScopedWebRTCPtr<webrtc::VoENetwork> network(engine.get());
354 EXPECT_TRUE(network.valid());
355 scoped_ptr<WebRTCTransportImpl> transport(
356 new WebRTCTransportImpl(network.get()));
357 EXPECT_EQ(0, network->RegisterExternalTransport(channel, *transport.get()));
358 EXPECT_EQ(0, base->StartPlayout(channel));
359 EXPECT_EQ(0, base->StartSend(channel));
360
361 // Read speech data from a speech test file.
362 const int input_packet_size =
363 params.frames_per_buffer() * 2 * params.channels();
364 const size_t length = input_packet_size * kNumberOfPacketsForLoopbackTest;
365 scoped_ptr<char[]> capture_data(new char[length]);
366 ReadDataFromSpeechFile(capture_data.get(), length);
367
368 // Start the timer.
369 scoped_ptr<media::AudioBus> render_audio_bus(media::AudioBus::Create(params));
370 base::Time start_time = base::Time::Now();
371 int delay = 0;
372 std::vector<int> voe_channels;
373 voe_channels.push_back(channel);
374 for (int j = 0; j < kNumberOfPacketsForLoopbackTest; ++j) {
375 // Sending fake capture data to WebRtc.
376 capturer_sink->OnData(
377 reinterpret_cast<int16*>(capture_data.get() + input_packet_size * j),
378 params.sample_rate(),
379 params.channels(),
380 params.frames_per_buffer(),
381 voe_channels,
382 kHardwareLatencyInMs,
383 1.0,
384 enable_apm,
385 false);
386
387 // Receiving data from WebRtc.
388 renderer_source->RenderData(
389 render_audio_bus.get(), params.sample_rate(),
390 kHardwareLatencyInMs + delay);
391 delay = (base::Time::Now() - start_time).InMilliseconds();
392 }
393
394 int latency = (base::Time::Now() - start_time).InMilliseconds();
395
396 EXPECT_EQ(0, base->StopSend(channel));
397 EXPECT_EQ(0, base->StopPlayout(channel));
398 EXPECT_EQ(0, base->DeleteChannel(channel));
399 EXPECT_EQ(0, base->Terminate());
400
401 return latency;
402 }
403
404 } // namespace
405
406 // Trivial test which verifies that one part of the test harness
407 // (HardwareSampleRatesAreValid()) works as intended for all supported
408 // hardware input sample rates.
409 TEST_F(MAYBE_WebRTCAudioDeviceTest, TestValidInputRates) {
410 int valid_rates[] = {16000, 32000, 44100, 48000, 96000};
411
412 // Verify that we will approve all rates listed in |valid_rates|.
413 for (size_t i = 0; i < arraysize(valid_rates); ++i) {
414 EXPECT_TRUE(FindElementInArray(valid_rates, arraysize(valid_rates),
415 valid_rates[i]));
416 }
417
418 // Verify that any value outside the valid range results in negative
419 // find results.
420 int invalid_rates[] = {-1, 0, 8000, 11025, 22050, 192000};
421 for (size_t i = 0; i < arraysize(invalid_rates); ++i) {
422 EXPECT_FALSE(FindElementInArray(valid_rates, arraysize(valid_rates),
423 invalid_rates[i]));
424 }
425 }
426
427 // Trivial test which verifies that one part of the test harness
428 // (HardwareSampleRatesAreValid()) works as intended for all supported
429 // hardware output sample rates.
430 TEST_F(MAYBE_WebRTCAudioDeviceTest, TestValidOutputRates) {
431 int valid_rates[] = {44100, 48000, 96000};
432
433 // Verify that we will approve all rates listed in |valid_rates|.
434 for (size_t i = 0; i < arraysize(valid_rates); ++i) {
435 EXPECT_TRUE(FindElementInArray(valid_rates, arraysize(valid_rates),
436 valid_rates[i]));
437 }
438
439 // Verify that any value outside the valid range results in negative
440 // find results.
441 int invalid_rates[] = {-1, 0, 8000, 11025, 22050, 32000, 192000};
442 for (size_t i = 0; i < arraysize(invalid_rates); ++i) {
443 EXPECT_FALSE(FindElementInArray(valid_rates, arraysize(valid_rates),
444 invalid_rates[i]));
445 }
446 }
447
448 // Basic test that instantiates and initializes an instance of
449 // WebRtcAudioDeviceImpl.
450 TEST_F(MAYBE_WebRTCAudioDeviceTest, Construct) {
451 #if defined(OS_WIN)
452 // This test crashes on Win XP bots.
453 if (base::win::GetVersion() <= base::win::VERSION_XP)
454 return;
455 #endif
456
457 AudioParameters input_params(
458 AudioParameters::AUDIO_PCM_LOW_LATENCY,
459 media::CHANNEL_LAYOUT_MONO,
460 48000,
461 16,
462 480);
463
464 AudioParameters output_params(
465 AudioParameters::AUDIO_PCM_LOW_LATENCY,
466 media::CHANNEL_LAYOUT_STEREO,
467 48000,
468 16,
469 480);
470
471 media::AudioHardwareConfig audio_config(input_params, output_params);
472 SetAudioHardwareConfig(&audio_config);
473
474 scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
475 new WebRtcAudioDeviceImpl());
476
477 WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create());
478 ASSERT_TRUE(engine.valid());
479
480 ScopedWebRTCPtr<webrtc::VoEBase> base(engine.get());
481 int err = base->Init(webrtc_audio_device.get());
482 EXPECT_TRUE(CreateAudioCapturer(webrtc_audio_device) != NULL);
483 EXPECT_EQ(0, err);
484 EXPECT_EQ(0, base->Terminate());
485 }
486
487 // Verify that a call to webrtc::VoEBase::StartPlayout() starts audio output
488 // with the correct set of parameters. A WebRtcAudioDeviceImpl instance will
489 // be utilized to implement the actual audio path. The test registers a
490 // webrtc::VoEExternalMedia implementation to hijack the output audio and
491 // verify that streaming starts correctly.
492 // TODO(henrika): include on Android as well as soon as alla race conditions
493 // in OpenSLES are resolved.
494 #if defined(OS_ANDROID)
495 #define MAYBE_StartPlayout DISABLED_StartPlayout
496 #else
497 #define MAYBE_StartPlayout StartPlayout
498 #endif
499 TEST_F(MAYBE_WebRTCAudioDeviceTest, MAYBE_StartPlayout) {
500 if (!has_output_devices_) {
501 LOG(WARNING) << "No output device detected.";
502 return;
503 }
504
505 scoped_ptr<media::AudioHardwareConfig> config =
506 CreateRealHardwareConfig(audio_manager_.get());
507 SetAudioHardwareConfig(config.get());
508
509 if (!HardwareSampleRatesAreValid())
510 return;
511
512 WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create());
513 ASSERT_TRUE(engine.valid());
514 ScopedWebRTCPtr<webrtc::VoEBase> base(engine.get());
515 ASSERT_TRUE(base.valid());
516
517 scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
518 new WebRtcAudioDeviceImpl());
519 int err = base->Init(webrtc_audio_device.get());
520 ASSERT_EQ(0, err);
521
522 ScopedWebRTCPtr<webrtc::VoEExternalMedia> external_media(engine.get());
523 ASSERT_TRUE(external_media.valid());
524 base::WaitableEvent event(false, false);
525 scoped_ptr<WebRTCMediaProcessImpl> media_process(
526 new WebRTCMediaProcessImpl(&event));
527 int ch = base->CreateChannel();
528 EXPECT_NE(-1, ch);
529 EXPECT_EQ(0, external_media->RegisterExternalMediaProcessing(
530 ch, webrtc::kPlaybackPerChannel, *media_process.get()));
531
532 scoped_refptr<webrtc::MediaStreamInterface> media_stream(
533 new talk_base::RefCountedObject<MockMediaStream>("label"));
534
535 EXPECT_EQ(0, base->StartPlayout(ch));
536 scoped_refptr<WebRtcAudioRenderer> renderer(
537 CreateDefaultWebRtcAudioRenderer(kRenderViewId, media_stream));
538 scoped_refptr<MediaStreamAudioRenderer> proxy(
539 renderer->CreateSharedAudioRendererProxy(media_stream));
540 EXPECT_TRUE(webrtc_audio_device->SetAudioRenderer(renderer.get()));
541 proxy->Start();
542 proxy->Play();
543
544 EXPECT_TRUE(event.TimedWait(TestTimeouts::action_timeout()));
545 WaitForIOThreadCompletion();
546
547 EXPECT_TRUE(webrtc_audio_device->Playing());
548 EXPECT_FALSE(webrtc_audio_device->Recording());
549 EXPECT_EQ(ch, media_process->channel_id());
550 EXPECT_EQ(webrtc::kPlaybackPerChannel, media_process->type());
551 EXPECT_EQ(80, media_process->packet_size());
552 EXPECT_EQ(8000, media_process->sample_rate());
553
554 EXPECT_EQ(0, external_media->DeRegisterExternalMediaProcessing(
555 ch, webrtc::kPlaybackPerChannel));
556 EXPECT_EQ(0, base->StopPlayout(ch));
557 proxy->Stop();
558 EXPECT_EQ(0, base->DeleteChannel(ch));
559 EXPECT_EQ(0, base->Terminate());
560 }
561
562 // Verify that a call to webrtc::VoEBase::StartRecording() starts audio input
563 // with the correct set of parameters. A WebRtcAudioDeviceImpl instance will
564 // be utilized to implement the actual audio path. The test registers a
565 // webrtc::VoEExternalMedia implementation to hijack the input audio and
566 // verify that streaming starts correctly. An external transport implementation
567 // is also required to ensure that "sending" can start without actually trying
568 // to send encoded packets to the network. Our main interest here is to ensure
569 // that the audio capturing starts as it should.
570 // Disabled when running headless since the bots don't have the required config.
571
572 // TODO(leozwang): Because ExternalMediaProcessing is disabled in webrtc,
573 // disable this unit test on Android for now.
574 #if defined(OS_ANDROID)
575 #define MAYBE_StartRecording DISABLED_StartRecording
576 #elif defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
577 // This test is failing on ARM linux: http://crbug.com/238490
578 #define MAYBE_StartRecording DISABLED_StartRecording
579 #else
580 // Flakily hangs on all other platforms as well: crbug.com/268376.
581 // When the flakiness has been fixed, you probably want to leave it disabled
582 // on the above platforms.
583 #define MAYBE_StartRecording DISABLED_StartRecording
584 #endif
585
586 TEST_F(MAYBE_WebRTCAudioDeviceTest, MAYBE_StartRecording) {
587 if (!has_input_devices_ || !has_output_devices_) {
588 LOG(WARNING) << "Missing audio devices.";
589 return;
590 }
591
592 scoped_ptr<media::AudioHardwareConfig> config =
593 CreateRealHardwareConfig(audio_manager_.get());
594 SetAudioHardwareConfig(config.get());
595
596 if (!HardwareSampleRatesAreValid())
597 return;
598
599 // TODO(tommi): extend MediaObserver and MockMediaObserver with support
600 // for new interfaces, like OnSetAudioStreamRecording(). When done, add
601 // EXPECT_CALL() macros here.
602 scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
603 new WebRtcAudioDeviceImpl());
604
605 WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create());
606 ASSERT_TRUE(engine.valid());
607
608 ScopedWebRTCPtr<webrtc::VoEBase> base(engine.get());
609 ASSERT_TRUE(base.valid());
610 int err = base->Init(webrtc_audio_device.get());
611 ASSERT_EQ(0, err);
612
613 int ch = base->CreateChannel();
614 EXPECT_NE(-1, ch);
615
616 ScopedWebRTCPtr<webrtc::VoEExternalMedia> external_media(engine.get());
617 ASSERT_TRUE(external_media.valid());
618
619 base::WaitableEvent event(false, false);
620 scoped_ptr<WebRTCMediaProcessImpl> media_process(
621 new WebRTCMediaProcessImpl(&event));
622 EXPECT_EQ(0, external_media->RegisterExternalMediaProcessing(
623 ch, webrtc::kRecordingPerChannel, *media_process.get()));
624
625 // We must add an external transport implementation to be able to start
626 // recording without actually sending encoded packets to the network. All
627 // we want to do here is to verify that audio capturing starts as it should.
628 ScopedWebRTCPtr<webrtc::VoENetwork> network(engine.get());
629 scoped_ptr<WebRTCTransportImpl> transport(
630 new WebRTCTransportImpl(network.get()));
631 EXPECT_EQ(0, network->RegisterExternalTransport(ch, *transport.get()));
632 EXPECT_EQ(0, base->StartSend(ch));
633
634 // Create the capturer which starts the source of the data flow.
635 scoped_refptr<WebRtcAudioCapturer> capturer(
636 CreateAudioCapturer(webrtc_audio_device));
637 EXPECT_TRUE(capturer);
638
639 // Create and start a local audio track which is bridging the data flow
640 // between the capturer and WebRtcAudioDeviceImpl.
641 scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
642 WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
643 scoped_ptr<WebRtcLocalAudioTrack> local_audio_track(
644 CreateAndStartLocalAudioTrack(adapter, capturer, webrtc_audio_device));
645 // connect the VoE voice channel to the audio track
646 static_cast<webrtc::AudioTrackInterface*>(
647 adapter.get())->GetRenderer()->AddChannel(ch);
648
649 // Verify we get the data flow.
650 EXPECT_TRUE(event.TimedWait(TestTimeouts::action_timeout()));
651 WaitForIOThreadCompletion();
652
653 EXPECT_FALSE(webrtc_audio_device->Playing());
654 EXPECT_TRUE(webrtc_audio_device->Recording());
655 EXPECT_EQ(ch, media_process->channel_id());
656 EXPECT_EQ(webrtc::kRecordingPerChannel, media_process->type());
657 EXPECT_EQ(80, media_process->packet_size());
658 EXPECT_EQ(8000, media_process->sample_rate());
659
660 EXPECT_EQ(0, external_media->DeRegisterExternalMediaProcessing(
661 ch, webrtc::kRecordingPerChannel));
662 EXPECT_EQ(0, base->StopSend(ch));
663
664 capturer->Stop();
665 EXPECT_EQ(0, base->DeleteChannel(ch));
666 EXPECT_EQ(0, base->Terminate());
667 }
668
669 // Uses WebRtcAudioDeviceImpl to play a local wave file.
670 // TODO(henrika): include on Android as well as soon as alla race conditions
671 // in OpenSLES are resolved.
672 #if defined(OS_ANDROID)
673 #define MAYBE_PlayLocalFile DISABLED_PlayLocalFile
674 #else
675 #define MAYBE_PlayLocalFile PlayLocalFile
676 #endif
677 TEST_F(MAYBE_WebRTCAudioDeviceTest, MAYBE_PlayLocalFile) {
678 if (!has_output_devices_) {
679 LOG(WARNING) << "No output device detected.";
680 return;
681 }
682
683 std::string file_path(
684 GetTestDataPath(FILE_PATH_LITERAL("speechmusic_mono_16kHz.pcm")));
685
686 scoped_ptr<media::AudioHardwareConfig> config =
687 CreateRealHardwareConfig(audio_manager_.get());
688 SetAudioHardwareConfig(config.get());
689
690 if (!HardwareSampleRatesAreValid())
691 return;
692
693 WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create());
694 ASSERT_TRUE(engine.valid());
695 ScopedWebRTCPtr<webrtc::VoEBase> base(engine.get());
696 ASSERT_TRUE(base.valid());
697
698 scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
699 new WebRtcAudioDeviceImpl());
700 int err = base->Init(webrtc_audio_device.get());
701 ASSERT_EQ(0, err);
702 int ch = base->CreateChannel();
703 EXPECT_NE(-1, ch);
704 EXPECT_EQ(0, base->StartPlayout(ch));
705 scoped_refptr<webrtc::MediaStreamInterface> media_stream(
706 new talk_base::RefCountedObject<MockMediaStream>("label"));
707 scoped_refptr<WebRtcAudioRenderer> renderer(
708 CreateDefaultWebRtcAudioRenderer(kRenderViewId, media_stream));
709 scoped_refptr<MediaStreamAudioRenderer> proxy(
710 renderer->CreateSharedAudioRendererProxy(media_stream));
711 EXPECT_TRUE(webrtc_audio_device->SetAudioRenderer(renderer.get()));
712 proxy->Start();
713 proxy->Play();
714
715 ScopedWebRTCPtr<webrtc::VoEFile> file(engine.get());
716 ASSERT_TRUE(file.valid());
717 int duration = 0;
718 EXPECT_EQ(0, file->GetFileDuration(file_path.c_str(), duration,
719 webrtc::kFileFormatPcm16kHzFile));
720 EXPECT_NE(0, duration);
721
722 EXPECT_EQ(0, file->StartPlayingFileLocally(ch, file_path.c_str(), false,
723 webrtc::kFileFormatPcm16kHzFile));
724
725 // Play 2 seconds worth of audio and then quit.
726 message_loop_.PostDelayedTask(FROM_HERE,
727 base::MessageLoop::QuitClosure(),
728 base::TimeDelta::FromSeconds(2));
729 message_loop_.Run();
730
731 proxy->Stop();
732 EXPECT_EQ(0, base->StopSend(ch));
733 EXPECT_EQ(0, base->StopPlayout(ch));
734 EXPECT_EQ(0, base->DeleteChannel(ch));
735 EXPECT_EQ(0, base->Terminate());
736 }
737
738 // Uses WebRtcAudioDeviceImpl to play out recorded audio in loopback.
739 // An external transport implementation is utilized to feed back RTP packets
740 // which are recorded, encoded, packetized into RTP packets and finally
741 // "transmitted". The RTP packets are then fed back into the VoiceEngine
742 // where they are decoded and played out on the default audio output device.
743 // Disabled when running headless since the bots don't have the required config.
744 // TODO(henrika): improve quality by using a wideband codec, enabling noise-
745 // suppressions etc.
746 // FullDuplexAudioWithAGC is flaky on Android, disable it for now.
747 // Also flakily hangs on Windows: crbug.com/269348.
748 #if defined(OS_ANDROID) || defined(OS_WIN)
749 #define MAYBE_FullDuplexAudioWithAGC DISABLED_FullDuplexAudioWithAGC
750 #else
751 #define MAYBE_FullDuplexAudioWithAGC FullDuplexAudioWithAGC
752 #endif
753 TEST_F(MAYBE_WebRTCAudioDeviceTest, MAYBE_FullDuplexAudioWithAGC) {
754 if (!has_output_devices_ || !has_input_devices_) {
755 LOG(WARNING) << "Missing audio devices.";
756 return;
757 }
758
759 scoped_ptr<media::AudioHardwareConfig> config =
760 CreateRealHardwareConfig(audio_manager_.get());
761 SetAudioHardwareConfig(config.get());
762
763 if (!HardwareSampleRatesAreValid())
764 return;
765
766 WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create());
767 ASSERT_TRUE(engine.valid());
768 ScopedWebRTCPtr<webrtc::VoEBase> base(engine.get());
769 ASSERT_TRUE(base.valid());
770
771 scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
772 new WebRtcAudioDeviceImpl());
773 int err = base->Init(webrtc_audio_device.get());
774 ASSERT_EQ(0, err);
775
776 ScopedWebRTCPtr<webrtc::VoEAudioProcessing> audio_processing(engine.get());
777 ASSERT_TRUE(audio_processing.valid());
778 #if defined(OS_ANDROID)
779 // On Android, by default AGC is off.
780 bool enabled = true;
781 webrtc::AgcModes agc_mode = webrtc::kAgcDefault;
782 EXPECT_EQ(0, audio_processing->GetAgcStatus(enabled, agc_mode));
783 EXPECT_FALSE(enabled);
784 #else
785 bool enabled = false;
786 webrtc::AgcModes agc_mode = webrtc::kAgcDefault;
787 EXPECT_EQ(0, audio_processing->GetAgcStatus(enabled, agc_mode));
788 EXPECT_TRUE(enabled);
789 EXPECT_EQ(agc_mode, webrtc::kAgcAdaptiveAnalog);
790 #endif
791
792 int ch = base->CreateChannel();
793 EXPECT_NE(-1, ch);
794
795 scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
796 WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
797 scoped_refptr<WebRtcAudioCapturer> capturer(
798 CreateAudioCapturer(webrtc_audio_device));
799 EXPECT_TRUE(capturer);
800 scoped_ptr<WebRtcLocalAudioTrack> local_audio_track(
801 CreateAndStartLocalAudioTrack(adapter, capturer, webrtc_audio_device));
802 // connect the VoE voice channel to the audio track adapter.
803 static_cast<webrtc::AudioTrackInterface*>(
804 adapter.get())->GetRenderer()->AddChannel(ch);
805
806 ScopedWebRTCPtr<webrtc::VoENetwork> network(engine.get());
807 ASSERT_TRUE(network.valid());
808 scoped_ptr<WebRTCTransportImpl> transport(
809 new WebRTCTransportImpl(network.get()));
810 EXPECT_EQ(0, network->RegisterExternalTransport(ch, *transport.get()));
811 EXPECT_EQ(0, base->StartPlayout(ch));
812 EXPECT_EQ(0, base->StartSend(ch));
813 scoped_refptr<webrtc::MediaStreamInterface> media_stream(
814 new talk_base::RefCountedObject<MockMediaStream>("label"));
815 scoped_refptr<WebRtcAudioRenderer> renderer(
816 CreateDefaultWebRtcAudioRenderer(kRenderViewId, media_stream));
817 scoped_refptr<MediaStreamAudioRenderer> proxy(
818 renderer->CreateSharedAudioRendererProxy(media_stream));
819 EXPECT_TRUE(webrtc_audio_device->SetAudioRenderer(renderer.get()));
820 proxy->Start();
821 proxy->Play();
822
823 VLOG(0) << ">> You should now be able to hear yourself in loopback...";
824 message_loop_.PostDelayedTask(FROM_HERE,
825 base::MessageLoop::QuitClosure(),
826 base::TimeDelta::FromSeconds(2));
827 message_loop_.Run();
828
829 capturer->Stop();
830 proxy->Stop();
831 EXPECT_EQ(0, base->StopSend(ch));
832 EXPECT_EQ(0, base->StopPlayout(ch));
833
834 EXPECT_EQ(0, base->DeleteChannel(ch));
835 EXPECT_EQ(0, base->Terminate());
836 }
837
838 // Test times out on bots, see http://crbug.com/247447
839 TEST_F(MAYBE_WebRTCAudioDeviceTest, DISABLED_WebRtcRecordingSetupTime) {
840 if (!has_input_devices_) {
841 LOG(WARNING) << "Missing audio capture devices.";
842 return;
843 }
844
845 scoped_ptr<media::AudioHardwareConfig> config =
846 CreateRealHardwareConfig(audio_manager_.get());
847 SetAudioHardwareConfig(config.get());
848
849 if (!HardwareSampleRatesAreValid())
850 return;
851
852 scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
853 new WebRtcAudioDeviceImpl());
854
855 WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create());
856 ASSERT_TRUE(engine.valid());
857
858 ScopedWebRTCPtr<webrtc::VoEBase> base(engine.get());
859 ASSERT_TRUE(base.valid());
860 int err = base->Init(webrtc_audio_device.get());
861 ASSERT_EQ(0, err);
862
863 int ch = base->CreateChannel();
864 EXPECT_NE(-1, ch);
865
866 scoped_refptr<WebRtcAudioCapturer> capturer(
867 CreateAudioCapturer(webrtc_audio_device));
868 EXPECT_TRUE(capturer);
869 base::WaitableEvent event(false, false);
870 scoped_ptr<MockMediaStreamAudioSink> sink(
871 new MockMediaStreamAudioSink(&event));
872
873 // Create and start a local audio track. Starting the audio track will connect
874 // the audio track to the capturer and also start the source of the capturer.
875 scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
876 WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
877 scoped_ptr<WebRtcLocalAudioTrack> local_audio_track(
878 CreateAndStartLocalAudioTrack(adapter, capturer, sink.get()));
879
880 // connect the VoE voice channel to the audio track adapter.
881 static_cast<webrtc::AudioTrackInterface*>(
882 adapter.get())->GetRenderer()->AddChannel(ch);
883
884 base::Time start_time = base::Time::Now();
885 EXPECT_EQ(0, base->StartSend(ch));
886
887 EXPECT_TRUE(event.TimedWait(TestTimeouts::action_timeout()));
888 int delay = (base::Time::Now() - start_time).InMilliseconds();
889 PrintPerfResultMs("webrtc_recording_setup_c", "t", delay);
890
891 capturer->Stop();
892 EXPECT_EQ(0, base->StopSend(ch));
893 EXPECT_EQ(0, base->DeleteChannel(ch));
894 EXPECT_EQ(0, base->Terminate());
895 }
896
897
898 // TODO(henrika): include on Android as well as soon as alla race conditions
899 // in OpenSLES are resolved.
900 #if defined(OS_ANDROID)
901 #define MAYBE_WebRtcPlayoutSetupTime DISABLED_WebRtcPlayoutSetupTime
902 #else
903 #define MAYBE_WebRtcPlayoutSetupTime WebRtcPlayoutSetupTime
904 #endif
905 TEST_F(MAYBE_WebRTCAudioDeviceTest, MAYBE_WebRtcPlayoutSetupTime) {
906 if (!has_output_devices_) {
907 LOG(WARNING) << "No output device detected.";
908 return;
909 }
910
911 scoped_ptr<media::AudioHardwareConfig> config =
912 CreateRealHardwareConfig(audio_manager_.get());
913 SetAudioHardwareConfig(config.get());
914
915 if (!HardwareSampleRatesAreValid())
916 return;
917
918 base::WaitableEvent event(false, false);
919 scoped_ptr<MockWebRtcAudioRendererSource> renderer_source(
920 new MockWebRtcAudioRendererSource(&event));
921
922 scoped_refptr<webrtc::MediaStreamInterface> media_stream(
923 new talk_base::RefCountedObject<MockMediaStream>("label"));
924 scoped_refptr<WebRtcAudioRenderer> renderer(
925 CreateDefaultWebRtcAudioRenderer(kRenderViewId, media_stream));
926 renderer->Initialize(renderer_source.get());
927 scoped_refptr<MediaStreamAudioRenderer> proxy(
928 renderer->CreateSharedAudioRendererProxy(media_stream));
929 proxy->Start();
930
931 // Start the timer and playout.
932 base::Time start_time = base::Time::Now();
933 proxy->Play();
934 EXPECT_TRUE(event.TimedWait(TestTimeouts::action_timeout()));
935 int delay = (base::Time::Now() - start_time).InMilliseconds();
936 PrintPerfResultMs("webrtc_playout_setup_c", "t", delay);
937
938 proxy->Stop();
939 }
940
941 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
942 // Timing out on ARM linux bot: http://crbug.com/238490
943 #define MAYBE_WebRtcLoopbackTimeWithoutSignalProcessing \
944 DISABLED_WebRtcLoopbackTimeWithoutSignalProcessing
945 #else
946 #define MAYBE_WebRtcLoopbackTimeWithoutSignalProcessing \
947 WebRtcLoopbackTimeWithoutSignalProcessing
948 #endif
949
950 TEST_F(MAYBE_WebRTCAudioDeviceTest,
951 MAYBE_WebRtcLoopbackTimeWithoutSignalProcessing) {
952 #if defined(OS_WIN)
953 // This test hangs on WinXP: see http://crbug.com/318189.
954 if (base::win::GetVersion() <= base::win::VERSION_XP) {
955 LOG(WARNING) << "Test disabled due to the test hangs on WinXP.";
956 return;
957 }
958 #endif
959 int latency = RunWebRtcLoopbackTimeTest(audio_manager_.get(), false);
960 PrintPerfResultMs("webrtc_loopback_without_sigal_processing (100 packets)",
961 "t", latency);
962 }
963
964 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
965 // Timing out on ARM linux bot: http://crbug.com/238490
966 #define MAYBE_WebRtcLoopbackTimeWithSignalProcessing \
967 DISABLED_WebRtcLoopbackTimeWithSignalProcessing
968 #else
969 #define MAYBE_WebRtcLoopbackTimeWithSignalProcessing \
970 WebRtcLoopbackTimeWithSignalProcessing
971 #endif
972
973 TEST_F(MAYBE_WebRTCAudioDeviceTest,
974 MAYBE_WebRtcLoopbackTimeWithSignalProcessing) {
975 #if defined(OS_WIN)
976 // This test hangs on WinXP: see http://crbug.com/318189.
977 if (base::win::GetVersion() <= base::win::VERSION_XP) {
978 LOG(WARNING) << "Test disabled due to the test hangs on WinXP.";
979 return;
980 }
981 #endif
982 int latency = RunWebRtcLoopbackTimeTest(audio_manager_.get(), true);
983 PrintPerfResultMs("webrtc_loopback_with_signal_processing (100 packets)",
984 "t", latency);
985 }
986
987 } // namespace content
OLDNEW
« no previous file with comments | « content/content_tests.gypi ('k') | content/test/webrtc_audio_device_test.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698