OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/environment.h" | 5 #include "base/environment.h" |
6 #include "base/test/test_timeouts.h" | 6 #include "base/test/test_timeouts.h" |
7 #include "content/renderer/media/audio_hardware.h" | 7 #include "content/renderer/media/renderer_audio_hardware_config.h" |
8 #include "content/renderer/media/webrtc_audio_capturer.h" | 8 #include "content/renderer/media/webrtc_audio_capturer.h" |
9 #include "content/renderer/media/webrtc_audio_device_impl.h" | 9 #include "content/renderer/media/webrtc_audio_device_impl.h" |
10 #include "content/renderer/media/webrtc_audio_renderer.h" | 10 #include "content/renderer/media/webrtc_audio_renderer.h" |
11 #include "content/renderer/render_thread_impl.h" | |
11 #include "content/test/webrtc_audio_device_test.h" | 12 #include "content/test/webrtc_audio_device_test.h" |
12 #include "media/audio/audio_manager.h" | 13 #include "media/audio/audio_manager_base.h" |
13 #include "media/audio/audio_util.h" | 14 #include "media/audio/audio_util.h" |
14 #include "testing/gmock/include/gmock/gmock.h" | 15 #include "testing/gmock/include/gmock/gmock.h" |
15 #include "third_party/webrtc/voice_engine/include/voe_audio_processing.h" | 16 #include "third_party/webrtc/voice_engine/include/voe_audio_processing.h" |
16 #include "third_party/webrtc/voice_engine/include/voe_base.h" | 17 #include "third_party/webrtc/voice_engine/include/voe_base.h" |
17 #include "third_party/webrtc/voice_engine/include/voe_external_media.h" | 18 #include "third_party/webrtc/voice_engine/include/voe_external_media.h" |
18 #include "third_party/webrtc/voice_engine/include/voe_file.h" | 19 #include "third_party/webrtc/voice_engine/include/voe_file.h" |
19 #include "third_party/webrtc/voice_engine/include/voe_network.h" | 20 #include "third_party/webrtc/voice_engine/include/voe_network.h" |
20 | 21 |
21 using testing::_; | 22 using testing::_; |
22 using testing::AnyNumber; | 23 using testing::AnyNumber; |
23 using testing::InvokeWithoutArgs; | 24 using testing::InvokeWithoutArgs; |
24 using testing::Return; | 25 using testing::Return; |
25 using testing::StrEq; | 26 using testing::StrEq; |
26 | 27 |
27 namespace content { | 28 namespace content { |
28 | 29 |
29 namespace { | 30 namespace { |
30 | 31 |
31 const int kRenderViewId = 1; | 32 const int kRenderViewId = 1; |
32 | 33 |
33 class AudioUtil : public AudioUtilInterface { | 34 class RealAudioHardwareConfig : public media::AudioHardwareConfig { |
34 public: | 35 public: |
35 AudioUtil() {} | 36 RealAudioHardwareConfig() {} |
37 virtual ~RealAudioHardwareConfig() {} | |
36 | 38 |
37 virtual int GetAudioHardwareSampleRate() OVERRIDE { | 39 virtual int GetOutputBufferSize() OVERRIDE { |
40 return media::GetAudioHardwareBufferSize(); | |
41 } | |
42 | |
43 virtual int GetOutputSampleRate() OVERRIDE { | |
38 return media::GetAudioHardwareSampleRate(); | 44 return media::GetAudioHardwareSampleRate(); |
39 } | 45 } |
40 virtual int GetAudioInputHardwareSampleRate( | |
41 const std::string& device_id) OVERRIDE { | |
42 return media::GetAudioInputHardwareSampleRate(device_id); | |
43 } | |
44 virtual media::ChannelLayout GetAudioInputHardwareChannelLayout( | |
45 const std::string& device_id) OVERRIDE { | |
46 return media::GetAudioInputHardwareChannelLayout(device_id); | |
47 } | |
48 private: | |
49 DISALLOW_COPY_AND_ASSIGN(AudioUtil); | |
50 }; | |
51 | 46 |
52 class AudioUtilNoHardware : public AudioUtilInterface { | 47 virtual int GetInputSampleRate() OVERRIDE { |
53 public: | 48 return media::GetAudioInputHardwareSampleRate( |
54 AudioUtilNoHardware(int output_rate, int input_rate, | 49 media::AudioManagerBase::kDefaultDeviceId); |
55 media::ChannelLayout input_channel_layout) | |
56 : output_rate_(output_rate), | |
57 input_rate_(input_rate), | |
58 input_channel_layout_(input_channel_layout) { | |
59 } | 50 } |
60 | 51 |
61 virtual int GetAudioHardwareSampleRate() OVERRIDE { | 52 virtual media::ChannelLayout GetInputChannelLayout() OVERRIDE { |
62 return output_rate_; | 53 return media::GetAudioInputHardwareChannelLayout( |
63 } | 54 media::AudioManagerBase::kDefaultDeviceId); |
64 virtual int GetAudioInputHardwareSampleRate( | |
65 const std::string& device_id) OVERRIDE { | |
66 return input_rate_; | |
67 } | |
68 virtual media::ChannelLayout GetAudioInputHardwareChannelLayout( | |
69 const std::string& device_id) OVERRIDE { | |
70 return input_channel_layout_; | |
71 } | 55 } |
72 | 56 |
73 private: | 57 private: |
74 int output_rate_; | 58 DISALLOW_COPY_AND_ASSIGN(RealAudioHardwareConfig); |
75 int input_rate_; | |
76 media::ChannelLayout input_channel_layout_; | |
77 DISALLOW_COPY_AND_ASSIGN(AudioUtilNoHardware); | |
78 }; | 59 }; |
79 | 60 |
80 // Return true if at least one element in the array matches |value|. | 61 // Return true if at least one element in the array matches |value|. |
81 bool FindElementInArray(int* array, int size, int value) { | 62 bool FindElementInArray(int* array, int size, int value) { |
82 return (std::find(&array[0], &array[0] + size, value) != &array[size]); | 63 return (std::find(&array[0], &array[0] + size, value) != &array[size]); |
83 } | 64 } |
84 | 65 |
85 // This method returns false if a non-supported rate is detected on the | 66 // This method returns false if a non-supported rate is detected on the |
86 // input or output side. | 67 // input or output side. |
87 // TODO(henrika): add support for automatic fallback to Windows Wave audio | 68 // TODO(henrika): add support for automatic fallback to Windows Wave audio |
88 // if a non-supported rate is detected. It is probably better to detect | 69 // if a non-supported rate is detected. It is probably better to detect |
89 // invalid audio settings by actually trying to open the audio streams instead | 70 // invalid audio settings by actually trying to open the audio streams instead |
90 // of relying on hard coded conditions. | 71 // of relying on hard coded conditions. |
91 bool HardwareSampleRatesAreValid() { | 72 bool HardwareSampleRatesAreValid() { |
92 // These are the currently supported hardware sample rates in both directions. | 73 // These are the currently supported hardware sample rates in both directions. |
93 // The actual WebRTC client can limit these ranges further depending on | 74 // The actual WebRTC client can limit these ranges further depending on |
94 // platform but this is the maximum range we support today. | 75 // platform but this is the maximum range we support today. |
95 int valid_input_rates[] = {16000, 32000, 44100, 48000, 96000}; | 76 int valid_input_rates[] = {16000, 32000, 44100, 48000, 96000}; |
96 int valid_output_rates[] = {44100, 48000, 96000}; | 77 int valid_output_rates[] = {44100, 48000, 96000}; |
97 | 78 |
79 RendererAudioHardwareConfig* hardware_config = | |
miu
2013/01/29 04:55:43
Possible root cause of crash on Mac: If GetAudioHa
DaleCurtis
2013/01/30 01:31:06
Crash is in Chrome not tests, may be related to ht
| |
80 RenderThreadImpl::current()->GetAudioHardwareConfig(); | |
81 | |
98 // Verify the input sample rate. | 82 // Verify the input sample rate. |
99 int input_sample_rate = GetAudioInputSampleRate(); | 83 int input_sample_rate = hardware_config->GetInputSampleRate(); |
100 | 84 |
101 if (!FindElementInArray(valid_input_rates, arraysize(valid_input_rates), | 85 if (!FindElementInArray(valid_input_rates, arraysize(valid_input_rates), |
102 input_sample_rate)) { | 86 input_sample_rate)) { |
103 LOG(WARNING) << "Non-supported input sample rate detected."; | 87 LOG(WARNING) << "Non-supported input sample rate detected."; |
104 return false; | 88 return false; |
105 } | 89 } |
106 | 90 |
107 // Given that the input rate was OK, verify the output rate as well. | 91 // Given that the input rate was OK, verify the output rate as well. |
108 int output_sample_rate = GetAudioOutputSampleRate(); | 92 int output_sample_rate = hardware_config->GetOutputSampleRate(); |
109 if (!FindElementInArray(valid_output_rates, arraysize(valid_output_rates), | 93 if (!FindElementInArray(valid_output_rates, arraysize(valid_output_rates), |
110 output_sample_rate)) { | 94 output_sample_rate)) { |
111 LOG(WARNING) << "Non-supported output sample rate detected."; | 95 LOG(WARNING) << "Non-supported output sample rate detected."; |
112 return false; | 96 return false; |
113 } | 97 } |
114 | 98 |
115 return true; | 99 return true; |
116 } | 100 } |
117 | 101 |
118 // Utility method which initializes the audio capturer contained in the | 102 // Utility method which initializes the audio capturer contained in the |
119 // WebRTC audio device. This method should be used in tests where | 103 // WebRTC audio device. This method should be used in tests where |
120 // HardwareSampleRatesAreValid() has been called and returned true. | 104 // HardwareSampleRatesAreValid() has been called and returned true. |
121 bool InitializeCapturer(WebRtcAudioDeviceImpl* webrtc_audio_device) { | 105 bool InitializeCapturer(WebRtcAudioDeviceImpl* webrtc_audio_device) { |
122 // Access the capturer owned and created by the audio device. | 106 // Access the capturer owned and created by the audio device. |
123 WebRtcAudioCapturer* capturer = webrtc_audio_device->capturer(); | 107 WebRtcAudioCapturer* capturer = webrtc_audio_device->capturer(); |
124 if (!capturer) | 108 if (!capturer) |
125 return false; | 109 return false; |
126 | 110 |
111 RendererAudioHardwareConfig* hardware_config = | |
112 RenderThreadImpl::current()->GetAudioHardwareConfig(); | |
113 | |
127 // Use native capture sample rate and channel configuration to get some | 114 // Use native capture sample rate and channel configuration to get some |
128 // action in this test. | 115 // action in this test. |
129 int sample_rate = GetAudioInputSampleRate(); | 116 int sample_rate = hardware_config->GetInputSampleRate(); |
130 media::ChannelLayout channel_layout = GetAudioInputChannelLayout(); | 117 media::ChannelLayout channel_layout = |
118 hardware_config->GetInputChannelLayout(); | |
131 if (!capturer->Initialize(channel_layout, sample_rate)) | 119 if (!capturer->Initialize(channel_layout, sample_rate)) |
132 return false; | 120 return false; |
133 | 121 |
134 // Ensures that the default capture device is utilized. | 122 // Ensures that the default capture device is utilized. |
135 webrtc_audio_device->capturer()->SetDevice(1); | 123 webrtc_audio_device->capturer()->SetDevice(1); |
136 return true; | 124 return true; |
137 } | 125 } |
138 | 126 |
139 | 127 |
140 class WebRTCMediaProcessImpl : public webrtc::VoEMediaProcess { | 128 class WebRTCMediaProcessImpl : public webrtc::VoEMediaProcess { |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
239 int invalid_rates[] = {-1, 0, 8000, 11025, 22050, 32000, 192000}; | 227 int invalid_rates[] = {-1, 0, 8000, 11025, 22050, 32000, 192000}; |
240 for (size_t i = 0; i < arraysize(invalid_rates); ++i) { | 228 for (size_t i = 0; i < arraysize(invalid_rates); ++i) { |
241 EXPECT_FALSE(FindElementInArray(valid_rates, arraysize(valid_rates), | 229 EXPECT_FALSE(FindElementInArray(valid_rates, arraysize(valid_rates), |
242 invalid_rates[i])); | 230 invalid_rates[i])); |
243 } | 231 } |
244 } | 232 } |
245 | 233 |
246 // Basic test that instantiates and initializes an instance of | 234 // Basic test that instantiates and initializes an instance of |
247 // WebRtcAudioDeviceImpl. | 235 // WebRtcAudioDeviceImpl. |
248 TEST_F(WebRTCAudioDeviceTest, Construct) { | 236 TEST_F(WebRTCAudioDeviceTest, Construct) { |
249 AudioUtilNoHardware audio_util(48000, 48000, media::CHANNEL_LAYOUT_MONO); | 237 RendererAudioHardwareConfig audio_config( |
250 SetAudioUtilCallback(&audio_util); | 238 480, 48000, 48000, media::CHANNEL_LAYOUT_MONO); |
239 SetAudioHardwareConfig(&audio_config); | |
251 | 240 |
252 scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device( | 241 scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device( |
253 new WebRtcAudioDeviceImpl()); | 242 new WebRtcAudioDeviceImpl()); |
254 | 243 |
255 // The capturer is not created until after the WebRtcAudioDeviceImpl has | 244 // The capturer is not created until after the WebRtcAudioDeviceImpl has |
256 // been initialized. | 245 // been initialized. |
257 EXPECT_FALSE(InitializeCapturer(webrtc_audio_device.get())); | 246 EXPECT_FALSE(InitializeCapturer(webrtc_audio_device.get())); |
258 | 247 |
259 WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create()); | 248 WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create()); |
260 ASSERT_TRUE(engine.valid()); | 249 ASSERT_TRUE(engine.valid()); |
(...skipping 11 matching lines...) Expand all Loading... | |
272 // webrtc::VoEExternalMedia implementation to hijack the output audio and | 261 // webrtc::VoEExternalMedia implementation to hijack the output audio and |
273 // verify that streaming starts correctly. | 262 // verify that streaming starts correctly. |
274 // Disabled when running headless since the bots don't have the required config. | 263 // Disabled when running headless since the bots don't have the required config. |
275 // Flaky, http://crbug.com/167299 . | 264 // Flaky, http://crbug.com/167299 . |
276 TEST_F(WebRTCAudioDeviceTest, DISABLED_StartPlayout) { | 265 TEST_F(WebRTCAudioDeviceTest, DISABLED_StartPlayout) { |
277 if (!has_output_devices_) { | 266 if (!has_output_devices_) { |
278 LOG(WARNING) << "No output device detected."; | 267 LOG(WARNING) << "No output device detected."; |
279 return; | 268 return; |
280 } | 269 } |
281 | 270 |
282 AudioUtil audio_util; | 271 RealAudioHardwareConfig audio_config; |
283 SetAudioUtilCallback(&audio_util); | 272 SetAudioHardwareConfig(&audio_config); |
284 | 273 |
285 if (!HardwareSampleRatesAreValid()) | 274 if (!HardwareSampleRatesAreValid()) |
286 return; | 275 return; |
287 | 276 |
288 EXPECT_CALL(media_observer(), | 277 EXPECT_CALL(media_observer(), |
289 OnSetAudioStreamStatus(_, 1, StrEq("created"))).Times(1); | 278 OnSetAudioStreamStatus(_, 1, StrEq("created"))).Times(1); |
290 EXPECT_CALL(media_observer(), | 279 EXPECT_CALL(media_observer(), |
291 OnSetAudioStreamPlaying(_, 1, true)).Times(1); | 280 OnSetAudioStreamPlaying(_, 1, true)).Times(1); |
292 EXPECT_CALL(media_observer(), | 281 EXPECT_CALL(media_observer(), |
293 OnSetAudioStreamStatus(_, 1, StrEq("closed"))).Times(1); | 282 OnSetAudioStreamStatus(_, 1, StrEq("closed"))).Times(1); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
350 // is also required to ensure that "sending" can start without actually trying | 339 // is also required to ensure that "sending" can start without actually trying |
351 // to send encoded packets to the network. Our main interest here is to ensure | 340 // to send encoded packets to the network. Our main interest here is to ensure |
352 // that the audio capturing starts as it should. | 341 // that the audio capturing starts as it should. |
353 // Disabled when running headless since the bots don't have the required config. | 342 // Disabled when running headless since the bots don't have the required config. |
354 TEST_F(WebRTCAudioDeviceTest, StartRecording) { | 343 TEST_F(WebRTCAudioDeviceTest, StartRecording) { |
355 if (!has_input_devices_ || !has_output_devices_) { | 344 if (!has_input_devices_ || !has_output_devices_) { |
356 LOG(WARNING) << "Missing audio devices."; | 345 LOG(WARNING) << "Missing audio devices."; |
357 return; | 346 return; |
358 } | 347 } |
359 | 348 |
360 AudioUtil audio_util; | 349 RealAudioHardwareConfig audio_config; |
361 SetAudioUtilCallback(&audio_util); | 350 SetAudioHardwareConfig(&audio_config); |
362 | 351 |
363 if (!HardwareSampleRatesAreValid()) | 352 if (!HardwareSampleRatesAreValid()) |
364 return; | 353 return; |
365 | 354 |
366 // TODO(tommi): extend MediaObserver and MockMediaObserver with support | 355 // TODO(tommi): extend MediaObserver and MockMediaObserver with support |
367 // for new interfaces, like OnSetAudioStreamRecording(). When done, add | 356 // for new interfaces, like OnSetAudioStreamRecording(). When done, add |
368 // EXPECT_CALL() macros here. | 357 // EXPECT_CALL() macros here. |
369 scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device( | 358 scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device( |
370 new WebRtcAudioDeviceImpl()); | 359 new WebRtcAudioDeviceImpl()); |
371 | 360 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
423 // Flaky, http://crbug.com/167298 . | 412 // Flaky, http://crbug.com/167298 . |
424 TEST_F(WebRTCAudioDeviceTest, DISABLED_PlayLocalFile) { | 413 TEST_F(WebRTCAudioDeviceTest, DISABLED_PlayLocalFile) { |
425 if (!has_output_devices_) { | 414 if (!has_output_devices_) { |
426 LOG(WARNING) << "No output device detected."; | 415 LOG(WARNING) << "No output device detected."; |
427 return; | 416 return; |
428 } | 417 } |
429 | 418 |
430 std::string file_path( | 419 std::string file_path( |
431 GetTestDataPath(FILE_PATH_LITERAL("speechmusic_mono_16kHz.pcm"))); | 420 GetTestDataPath(FILE_PATH_LITERAL("speechmusic_mono_16kHz.pcm"))); |
432 | 421 |
433 AudioUtil audio_util; | 422 RealAudioHardwareConfig audio_config; |
434 SetAudioUtilCallback(&audio_util); | 423 SetAudioHardwareConfig(&audio_config); |
435 | 424 |
436 if (!HardwareSampleRatesAreValid()) | 425 if (!HardwareSampleRatesAreValid()) |
437 return; | 426 return; |
438 | 427 |
439 EXPECT_CALL(media_observer(), | 428 EXPECT_CALL(media_observer(), |
440 OnSetAudioStreamStatus(_, 1, StrEq("created"))).Times(1); | 429 OnSetAudioStreamStatus(_, 1, StrEq("created"))).Times(1); |
441 EXPECT_CALL(media_observer(), | 430 EXPECT_CALL(media_observer(), |
442 OnSetAudioStreamPlaying(_, 1, true)).Times(1); | 431 OnSetAudioStreamPlaying(_, 1, true)).Times(1); |
443 EXPECT_CALL(media_observer(), | 432 EXPECT_CALL(media_observer(), |
444 OnSetAudioStreamStatus(_, 1, StrEq("closed"))).Times(1); | 433 OnSetAudioStreamStatus(_, 1, StrEq("closed"))).Times(1); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
494 // where they are decoded and played out on the default audio output device. | 483 // where they are decoded and played out on the default audio output device. |
495 // Disabled when running headless since the bots don't have the required config. | 484 // Disabled when running headless since the bots don't have the required config. |
496 // TODO(henrika): improve quality by using a wideband codec, enabling noise- | 485 // TODO(henrika): improve quality by using a wideband codec, enabling noise- |
497 // suppressions etc. | 486 // suppressions etc. |
498 TEST_F(WebRTCAudioDeviceTest, FullDuplexAudioWithAGC) { | 487 TEST_F(WebRTCAudioDeviceTest, FullDuplexAudioWithAGC) { |
499 if (!has_output_devices_ || !has_input_devices_) { | 488 if (!has_output_devices_ || !has_input_devices_) { |
500 LOG(WARNING) << "Missing audio devices."; | 489 LOG(WARNING) << "Missing audio devices."; |
501 return; | 490 return; |
502 } | 491 } |
503 | 492 |
504 AudioUtil audio_util; | 493 RealAudioHardwareConfig audio_config; |
505 SetAudioUtilCallback(&audio_util); | 494 SetAudioHardwareConfig(&audio_config); |
506 | 495 |
507 if (!HardwareSampleRatesAreValid()) | 496 if (!HardwareSampleRatesAreValid()) |
508 return; | 497 return; |
509 | 498 |
510 EXPECT_CALL(media_observer(), | 499 EXPECT_CALL(media_observer(), |
511 OnSetAudioStreamStatus(_, 1, StrEq("created"))); | 500 OnSetAudioStreamStatus(_, 1, StrEq("created"))); |
512 EXPECT_CALL(media_observer(), | 501 EXPECT_CALL(media_observer(), |
513 OnSetAudioStreamPlaying(_, 1, true)); | 502 OnSetAudioStreamPlaying(_, 1, true)); |
514 EXPECT_CALL(media_observer(), | 503 EXPECT_CALL(media_observer(), |
515 OnSetAudioStreamStatus(_, 1, StrEq("closed"))); | 504 OnSetAudioStreamStatus(_, 1, StrEq("closed"))); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
560 | 549 |
561 renderer->Stop(); | 550 renderer->Stop(); |
562 EXPECT_EQ(0, base->StopSend(ch)); | 551 EXPECT_EQ(0, base->StopSend(ch)); |
563 EXPECT_EQ(0, base->StopPlayout(ch)); | 552 EXPECT_EQ(0, base->StopPlayout(ch)); |
564 | 553 |
565 EXPECT_EQ(0, base->DeleteChannel(ch)); | 554 EXPECT_EQ(0, base->DeleteChannel(ch)); |
566 EXPECT_EQ(0, base->Terminate()); | 555 EXPECT_EQ(0, base->Terminate()); |
567 } | 556 } |
568 | 557 |
569 } // namespace content | 558 } // namespace content |
OLD | NEW |