| 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" | |
| 8 #include "content/renderer/media/webrtc_audio_capturer.h" | 7 #include "content/renderer/media/webrtc_audio_capturer.h" |
| 9 #include "content/renderer/media/webrtc_audio_device_impl.h" | 8 #include "content/renderer/media/webrtc_audio_device_impl.h" |
| 10 #include "content/renderer/media/webrtc_audio_renderer.h" | 9 #include "content/renderer/media/webrtc_audio_renderer.h" |
| 10 #include "content/renderer/render_thread_impl.h" |
| 11 #include "content/test/webrtc_audio_device_test.h" | 11 #include "content/test/webrtc_audio_device_test.h" |
| 12 #include "media/audio/audio_manager.h" | 12 #include "media/audio/audio_manager_base.h" |
| 13 #include "media/audio/audio_util.h" | 13 #include "media/audio/audio_util.h" |
| 14 #include "media/base/audio_hardware_config.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 scoped_ptr<media::AudioHardwareConfig> CreateRealHardwareConfig() { |
| 34 public: | 35 return make_scoped_ptr(new media::AudioHardwareConfig( |
| 35 AudioUtil() {} | 36 media::GetAudioHardwareBufferSize(), media::GetAudioHardwareSampleRate(), |
| 36 | 37 media::GetAudioInputHardwareSampleRate( |
| 37 virtual int GetAudioHardwareSampleRate() OVERRIDE { | 38 media::AudioManagerBase::kDefaultDeviceId), |
| 38 return media::GetAudioHardwareSampleRate(); | 39 media::GetAudioInputHardwareChannelLayout( |
| 39 } | 40 media::AudioManagerBase::kDefaultDeviceId))); |
| 40 virtual int GetAudioInputHardwareSampleRate( | 41 } |
| 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 | |
| 52 class AudioUtilNoHardware : public AudioUtilInterface { | |
| 53 public: | |
| 54 AudioUtilNoHardware(int output_rate, int input_rate, | |
| 55 media::ChannelLayout input_channel_layout) | |
| 56 : output_rate_(output_rate), | |
| 57 input_rate_(input_rate), | |
| 58 input_channel_layout_(input_channel_layout) { | |
| 59 } | |
| 60 | |
| 61 virtual int GetAudioHardwareSampleRate() OVERRIDE { | |
| 62 return output_rate_; | |
| 63 } | |
| 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 } | |
| 72 | |
| 73 private: | |
| 74 int output_rate_; | |
| 75 int input_rate_; | |
| 76 media::ChannelLayout input_channel_layout_; | |
| 77 DISALLOW_COPY_AND_ASSIGN(AudioUtilNoHardware); | |
| 78 }; | |
| 79 | 42 |
| 80 // Return true if at least one element in the array matches |value|. | 43 // Return true if at least one element in the array matches |value|. |
| 81 bool FindElementInArray(int* array, int size, int value) { | 44 bool FindElementInArray(int* array, int size, int value) { |
| 82 return (std::find(&array[0], &array[0] + size, value) != &array[size]); | 45 return (std::find(&array[0], &array[0] + size, value) != &array[size]); |
| 83 } | 46 } |
| 84 | 47 |
| 85 // This method returns false if a non-supported rate is detected on the | 48 // This method returns false if a non-supported rate is detected on the |
| 86 // input or output side. | 49 // input or output side. |
| 87 // TODO(henrika): add support for automatic fallback to Windows Wave audio | 50 // 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 | 51 // 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 | 52 // invalid audio settings by actually trying to open the audio streams instead |
| 90 // of relying on hard coded conditions. | 53 // of relying on hard coded conditions. |
| 91 bool HardwareSampleRatesAreValid() { | 54 bool HardwareSampleRatesAreValid() { |
| 92 // These are the currently supported hardware sample rates in both directions. | 55 // These are the currently supported hardware sample rates in both directions. |
| 93 // The actual WebRTC client can limit these ranges further depending on | 56 // The actual WebRTC client can limit these ranges further depending on |
| 94 // platform but this is the maximum range we support today. | 57 // platform but this is the maximum range we support today. |
| 95 int valid_input_rates[] = {16000, 32000, 44100, 48000, 96000}; | 58 int valid_input_rates[] = {16000, 32000, 44100, 48000, 96000}; |
| 96 int valid_output_rates[] = {44100, 48000, 96000}; | 59 int valid_output_rates[] = {44100, 48000, 96000}; |
| 97 | 60 |
| 61 media::AudioHardwareConfig* hardware_config = |
| 62 RenderThreadImpl::current()->GetAudioHardwareConfig(); |
| 63 |
| 98 // Verify the input sample rate. | 64 // Verify the input sample rate. |
| 99 int input_sample_rate = GetAudioInputSampleRate(); | 65 int input_sample_rate = hardware_config->GetInputSampleRate(); |
| 100 | 66 |
| 101 if (!FindElementInArray(valid_input_rates, arraysize(valid_input_rates), | 67 if (!FindElementInArray(valid_input_rates, arraysize(valid_input_rates), |
| 102 input_sample_rate)) { | 68 input_sample_rate)) { |
| 103 LOG(WARNING) << "Non-supported input sample rate detected."; | 69 LOG(WARNING) << "Non-supported input sample rate detected."; |
| 104 return false; | 70 return false; |
| 105 } | 71 } |
| 106 | 72 |
| 107 // Given that the input rate was OK, verify the output rate as well. | 73 // Given that the input rate was OK, verify the output rate as well. |
| 108 int output_sample_rate = GetAudioOutputSampleRate(); | 74 int output_sample_rate = hardware_config->GetOutputSampleRate(); |
| 109 if (!FindElementInArray(valid_output_rates, arraysize(valid_output_rates), | 75 if (!FindElementInArray(valid_output_rates, arraysize(valid_output_rates), |
| 110 output_sample_rate)) { | 76 output_sample_rate)) { |
| 111 LOG(WARNING) << "Non-supported output sample rate detected."; | 77 LOG(WARNING) << "Non-supported output sample rate detected."; |
| 112 return false; | 78 return false; |
| 113 } | 79 } |
| 114 | 80 |
| 115 return true; | 81 return true; |
| 116 } | 82 } |
| 117 | 83 |
| 118 // Utility method which initializes the audio capturer contained in the | 84 // Utility method which initializes the audio capturer contained in the |
| 119 // WebRTC audio device. This method should be used in tests where | 85 // WebRTC audio device. This method should be used in tests where |
| 120 // HardwareSampleRatesAreValid() has been called and returned true. | 86 // HardwareSampleRatesAreValid() has been called and returned true. |
| 121 bool InitializeCapturer(WebRtcAudioDeviceImpl* webrtc_audio_device) { | 87 bool InitializeCapturer(WebRtcAudioDeviceImpl* webrtc_audio_device) { |
| 122 // Access the capturer owned and created by the audio device. | 88 // Access the capturer owned and created by the audio device. |
| 123 WebRtcAudioCapturer* capturer = webrtc_audio_device->capturer(); | 89 WebRtcAudioCapturer* capturer = webrtc_audio_device->capturer(); |
| 124 if (!capturer) | 90 if (!capturer) |
| 125 return false; | 91 return false; |
| 126 | 92 |
| 93 media::AudioHardwareConfig* hardware_config = |
| 94 RenderThreadImpl::current()->GetAudioHardwareConfig(); |
| 95 |
| 127 // Use native capture sample rate and channel configuration to get some | 96 // Use native capture sample rate and channel configuration to get some |
| 128 // action in this test. | 97 // action in this test. |
| 129 int sample_rate = GetAudioInputSampleRate(); | 98 int sample_rate = hardware_config->GetInputSampleRate(); |
| 130 media::ChannelLayout channel_layout = GetAudioInputChannelLayout(); | 99 media::ChannelLayout channel_layout = |
| 100 hardware_config->GetInputChannelLayout(); |
| 131 if (!capturer->Initialize(channel_layout, sample_rate)) | 101 if (!capturer->Initialize(channel_layout, sample_rate)) |
| 132 return false; | 102 return false; |
| 133 | 103 |
| 134 // Ensures that the default capture device is utilized. | 104 // Ensures that the default capture device is utilized. |
| 135 webrtc_audio_device->capturer()->SetDevice(1); | 105 webrtc_audio_device->capturer()->SetDevice(1); |
| 136 return true; | 106 return true; |
| 137 } | 107 } |
| 138 | 108 |
| 139 | 109 |
| 140 class WebRTCMediaProcessImpl : public webrtc::VoEMediaProcess { | 110 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}; | 209 int invalid_rates[] = {-1, 0, 8000, 11025, 22050, 32000, 192000}; |
| 240 for (size_t i = 0; i < arraysize(invalid_rates); ++i) { | 210 for (size_t i = 0; i < arraysize(invalid_rates); ++i) { |
| 241 EXPECT_FALSE(FindElementInArray(valid_rates, arraysize(valid_rates), | 211 EXPECT_FALSE(FindElementInArray(valid_rates, arraysize(valid_rates), |
| 242 invalid_rates[i])); | 212 invalid_rates[i])); |
| 243 } | 213 } |
| 244 } | 214 } |
| 245 | 215 |
| 246 // Basic test that instantiates and initializes an instance of | 216 // Basic test that instantiates and initializes an instance of |
| 247 // WebRtcAudioDeviceImpl. | 217 // WebRtcAudioDeviceImpl. |
| 248 TEST_F(WebRTCAudioDeviceTest, Construct) { | 218 TEST_F(WebRTCAudioDeviceTest, Construct) { |
| 249 AudioUtilNoHardware audio_util(48000, 48000, media::CHANNEL_LAYOUT_MONO); | 219 media::AudioHardwareConfig audio_config( |
| 250 SetAudioUtilCallback(&audio_util); | 220 480, 48000, 48000, media::CHANNEL_LAYOUT_MONO); |
| 221 SetAudioHardwareConfig(&audio_config); |
| 251 | 222 |
| 252 scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device( | 223 scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device( |
| 253 new WebRtcAudioDeviceImpl()); | 224 new WebRtcAudioDeviceImpl()); |
| 254 | 225 |
| 255 // The capturer is not created until after the WebRtcAudioDeviceImpl has | 226 // The capturer is not created until after the WebRtcAudioDeviceImpl has |
| 256 // been initialized. | 227 // been initialized. |
| 257 EXPECT_FALSE(InitializeCapturer(webrtc_audio_device.get())); | 228 EXPECT_FALSE(InitializeCapturer(webrtc_audio_device.get())); |
| 258 | 229 |
| 259 WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create()); | 230 WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create()); |
| 260 ASSERT_TRUE(engine.valid()); | 231 ASSERT_TRUE(engine.valid()); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 272 // webrtc::VoEExternalMedia implementation to hijack the output audio and | 243 // webrtc::VoEExternalMedia implementation to hijack the output audio and |
| 273 // verify that streaming starts correctly. | 244 // verify that streaming starts correctly. |
| 274 // Disabled when running headless since the bots don't have the required config. | 245 // Disabled when running headless since the bots don't have the required config. |
| 275 // Flaky, http://crbug.com/167299 . | 246 // Flaky, http://crbug.com/167299 . |
| 276 TEST_F(WebRTCAudioDeviceTest, DISABLED_StartPlayout) { | 247 TEST_F(WebRTCAudioDeviceTest, DISABLED_StartPlayout) { |
| 277 if (!has_output_devices_) { | 248 if (!has_output_devices_) { |
| 278 LOG(WARNING) << "No output device detected."; | 249 LOG(WARNING) << "No output device detected."; |
| 279 return; | 250 return; |
| 280 } | 251 } |
| 281 | 252 |
| 282 AudioUtil audio_util; | 253 scoped_ptr<media::AudioHardwareConfig> config = CreateRealHardwareConfig(); |
| 283 SetAudioUtilCallback(&audio_util); | 254 SetAudioHardwareConfig(config.get()); |
| 284 | 255 |
| 285 if (!HardwareSampleRatesAreValid()) | 256 if (!HardwareSampleRatesAreValid()) |
| 286 return; | 257 return; |
| 287 | 258 |
| 288 EXPECT_CALL(media_observer(), | 259 EXPECT_CALL(media_observer(), |
| 289 OnSetAudioStreamStatus(_, 1, StrEq("created"))).Times(1); | 260 OnSetAudioStreamStatus(_, 1, StrEq("created"))).Times(1); |
| 290 EXPECT_CALL(media_observer(), | 261 EXPECT_CALL(media_observer(), |
| 291 OnSetAudioStreamPlaying(_, 1, true)).Times(1); | 262 OnSetAudioStreamPlaying(_, 1, true)).Times(1); |
| 292 EXPECT_CALL(media_observer(), | 263 EXPECT_CALL(media_observer(), |
| 293 OnSetAudioStreamStatus(_, 1, StrEq("closed"))).Times(1); | 264 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 | 321 // 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 | 322 // to send encoded packets to the network. Our main interest here is to ensure |
| 352 // that the audio capturing starts as it should. | 323 // that the audio capturing starts as it should. |
| 353 // Disabled when running headless since the bots don't have the required config. | 324 // Disabled when running headless since the bots don't have the required config. |
| 354 TEST_F(WebRTCAudioDeviceTest, StartRecording) { | 325 TEST_F(WebRTCAudioDeviceTest, StartRecording) { |
| 355 if (!has_input_devices_ || !has_output_devices_) { | 326 if (!has_input_devices_ || !has_output_devices_) { |
| 356 LOG(WARNING) << "Missing audio devices."; | 327 LOG(WARNING) << "Missing audio devices."; |
| 357 return; | 328 return; |
| 358 } | 329 } |
| 359 | 330 |
| 360 AudioUtil audio_util; | 331 scoped_ptr<media::AudioHardwareConfig> config = CreateRealHardwareConfig(); |
| 361 SetAudioUtilCallback(&audio_util); | 332 SetAudioHardwareConfig(config.get()); |
| 362 | 333 |
| 363 if (!HardwareSampleRatesAreValid()) | 334 if (!HardwareSampleRatesAreValid()) |
| 364 return; | 335 return; |
| 365 | 336 |
| 366 // TODO(tommi): extend MediaObserver and MockMediaObserver with support | 337 // TODO(tommi): extend MediaObserver and MockMediaObserver with support |
| 367 // for new interfaces, like OnSetAudioStreamRecording(). When done, add | 338 // for new interfaces, like OnSetAudioStreamRecording(). When done, add |
| 368 // EXPECT_CALL() macros here. | 339 // EXPECT_CALL() macros here. |
| 369 scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device( | 340 scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device( |
| 370 new WebRtcAudioDeviceImpl()); | 341 new WebRtcAudioDeviceImpl()); |
| 371 | 342 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 423 // Flaky, http://crbug.com/167298 . | 394 // Flaky, http://crbug.com/167298 . |
| 424 TEST_F(WebRTCAudioDeviceTest, DISABLED_PlayLocalFile) { | 395 TEST_F(WebRTCAudioDeviceTest, DISABLED_PlayLocalFile) { |
| 425 if (!has_output_devices_) { | 396 if (!has_output_devices_) { |
| 426 LOG(WARNING) << "No output device detected."; | 397 LOG(WARNING) << "No output device detected."; |
| 427 return; | 398 return; |
| 428 } | 399 } |
| 429 | 400 |
| 430 std::string file_path( | 401 std::string file_path( |
| 431 GetTestDataPath(FILE_PATH_LITERAL("speechmusic_mono_16kHz.pcm"))); | 402 GetTestDataPath(FILE_PATH_LITERAL("speechmusic_mono_16kHz.pcm"))); |
| 432 | 403 |
| 433 AudioUtil audio_util; | 404 scoped_ptr<media::AudioHardwareConfig> config = CreateRealHardwareConfig(); |
| 434 SetAudioUtilCallback(&audio_util); | 405 SetAudioHardwareConfig(config.get()); |
| 435 | 406 |
| 436 if (!HardwareSampleRatesAreValid()) | 407 if (!HardwareSampleRatesAreValid()) |
| 437 return; | 408 return; |
| 438 | 409 |
| 439 EXPECT_CALL(media_observer(), | 410 EXPECT_CALL(media_observer(), |
| 440 OnSetAudioStreamStatus(_, 1, StrEq("created"))).Times(1); | 411 OnSetAudioStreamStatus(_, 1, StrEq("created"))).Times(1); |
| 441 EXPECT_CALL(media_observer(), | 412 EXPECT_CALL(media_observer(), |
| 442 OnSetAudioStreamPlaying(_, 1, true)).Times(1); | 413 OnSetAudioStreamPlaying(_, 1, true)).Times(1); |
| 443 EXPECT_CALL(media_observer(), | 414 EXPECT_CALL(media_observer(), |
| 444 OnSetAudioStreamStatus(_, 1, StrEq("closed"))).Times(1); | 415 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. | 465 // 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. | 466 // 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- | 467 // TODO(henrika): improve quality by using a wideband codec, enabling noise- |
| 497 // suppressions etc. | 468 // suppressions etc. |
| 498 TEST_F(WebRTCAudioDeviceTest, FullDuplexAudioWithAGC) { | 469 TEST_F(WebRTCAudioDeviceTest, FullDuplexAudioWithAGC) { |
| 499 if (!has_output_devices_ || !has_input_devices_) { | 470 if (!has_output_devices_ || !has_input_devices_) { |
| 500 LOG(WARNING) << "Missing audio devices."; | 471 LOG(WARNING) << "Missing audio devices."; |
| 501 return; | 472 return; |
| 502 } | 473 } |
| 503 | 474 |
| 504 AudioUtil audio_util; | 475 scoped_ptr<media::AudioHardwareConfig> config = CreateRealHardwareConfig(); |
| 505 SetAudioUtilCallback(&audio_util); | 476 SetAudioHardwareConfig(config.get()); |
| 506 | 477 |
| 507 if (!HardwareSampleRatesAreValid()) | 478 if (!HardwareSampleRatesAreValid()) |
| 508 return; | 479 return; |
| 509 | 480 |
| 510 EXPECT_CALL(media_observer(), | 481 EXPECT_CALL(media_observer(), |
| 511 OnSetAudioStreamStatus(_, 1, StrEq("created"))); | 482 OnSetAudioStreamStatus(_, 1, StrEq("created"))); |
| 512 EXPECT_CALL(media_observer(), | 483 EXPECT_CALL(media_observer(), |
| 513 OnSetAudioStreamPlaying(_, 1, true)); | 484 OnSetAudioStreamPlaying(_, 1, true)); |
| 514 EXPECT_CALL(media_observer(), | 485 EXPECT_CALL(media_observer(), |
| 515 OnSetAudioStreamStatus(_, 1, StrEq("closed"))); | 486 OnSetAudioStreamStatus(_, 1, StrEq("closed"))); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 560 | 531 |
| 561 renderer->Stop(); | 532 renderer->Stop(); |
| 562 EXPECT_EQ(0, base->StopSend(ch)); | 533 EXPECT_EQ(0, base->StopSend(ch)); |
| 563 EXPECT_EQ(0, base->StopPlayout(ch)); | 534 EXPECT_EQ(0, base->StopPlayout(ch)); |
| 564 | 535 |
| 565 EXPECT_EQ(0, base->DeleteChannel(ch)); | 536 EXPECT_EQ(0, base->DeleteChannel(ch)); |
| 566 EXPECT_EQ(0, base->Terminate()); | 537 EXPECT_EQ(0, base->Terminate()); |
| 567 } | 538 } |
| 568 | 539 |
| 569 } // namespace content | 540 } // namespace content |
| OLD | NEW |