audio_input_volume_unittest.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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 <cmath> 6 7#include "base/logging.h" 8#include "base/memory/scoped_ptr.h" 9#include "media/audio/audio_io.h" 10#include "media/audio/audio_manager_base.h" 11#include "media/audio/audio_util.h" 12#include "testing/gtest/include/gtest/gtest.h" 13 14#if defined(OS_WIN) 15#include "base/win/scoped_com_initializer.h" 16#include "media/audio/win/core_audio_util_win.h" 17#endif 18 19namespace media { 20 21double GetVolumeAfterSetVolumeOnLinux(AudioInputStream* ais, 22 double target_volume) { 23 // SetVolume() is asynchronous on Linux, we need to keep trying until 24 // the SetVolume() operation is done. 25 static const int kTimesToRun = 10; 26 double volume = 0.0; 27 for (int i = 0; i < kTimesToRun; ++i) { 28 volume = ais->GetVolume(); 29 if (volume == target_volume) 30 break; 31 32 // Sleep 100ms to wait for the operation. 33 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); 34 } 35 36 return volume; 37} 38 39class AudioInputVolumeTest : public ::testing::Test { 40 protected: 41 AudioInputVolumeTest() 42 : audio_manager_(AudioManager::Create()) 43#if defined(OS_WIN) 44 , com_init_(base::win::ScopedCOMInitializer::kMTA) 45#endif 46 { 47 } 48 49 bool CanRunAudioTests() { 50#if defined(OS_WIN) 51 // TODO(henrika): add support for volume control on Windows XP as well. 52 // For now, we might as well signal false already here to avoid running 53 // these tests on Windows XP. 54 if (!CoreAudioUtil::IsSupported()) 55 return false; 56#endif 57 if (!audio_manager_) 58 return false; 59 60 return audio_manager_->HasAudioInputDevices(); 61 } 62 63 // Helper method which checks if the stream has volume support. 64 bool HasDeviceVolumeControl(AudioInputStream* stream) { 65 if (!stream) 66 return false; 67 68 return (stream->GetMaxVolume() != 0.0); 69 } 70 71 AudioInputStream* CreateAndOpenStream(const std::string& device_id) { 72 const AudioParameters& params = 73 audio_manager_->GetInputStreamParameters(device_id); 74 AudioInputStream* ais = audio_manager_->MakeAudioInputStream( 75 params, device_id); 76 EXPECT_TRUE(NULL != ais); 77 78#if defined(OS_LINUX) || defined(OS_OPENBSD) 79 // Some linux devices do not support our settings, we may fail to open 80 // those devices. 81 if (!ais->Open()) { 82 // Default device should always be able to be opened. 83 EXPECT_TRUE(AudioManagerBase::kDefaultDeviceId != device_id); 84 ais->Close(); 85 ais = NULL; 86 } 87#elif defined(OS_WIN) || defined(OS_MACOSX) 88 EXPECT_TRUE(ais->Open()); 89#endif 90 91 return ais; 92 } 93 94 scoped_ptr<AudioManager> audio_manager_; 95 96#if defined(OS_WIN) 97 base::win::ScopedCOMInitializer com_init_; 98#endif 99}; 100 101TEST_F(AudioInputVolumeTest, InputVolumeTest) { 102 if (!CanRunAudioTests()) 103 return; 104 105 // Retrieve a list of all available input devices. 106 AudioDeviceNames device_names; 107 audio_manager_->GetAudioInputDeviceNames(&device_names); 108 if (device_names.empty()) { 109 LOG(WARNING) << "Could not find any available input device"; 110 return; 111 } 112 113 // Scan all available input devices and repeat the same test for all of them. 114 for (AudioDeviceNames::const_iterator it = device_names.begin(); 115 it != device_names.end(); 116 ++it) { 117 AudioInputStream* ais = CreateAndOpenStream(it->unique_id); 118 if (!ais) { 119 DLOG(WARNING) << "Failed to open stream for device " << it->unique_id; 120 continue; 121 } 122 123 if (!HasDeviceVolumeControl(ais)) { 124 DLOG(WARNING) << "Device: " << it->unique_id 125 << ", does not have volume control."; 126 ais->Close(); 127 continue; 128 } 129 130 double max_volume = ais->GetMaxVolume(); 131 EXPECT_GT(max_volume, 0.0); 132 133 // Store the current input-device volume level. 134 double original_volume = ais->GetVolume(); 135 EXPECT_GE(original_volume, 0.0); 136#if defined(OS_WIN) || defined(OS_MACOSX) 137 // Note that |original_volume| can be higher than |max_volume| on Linux. 138 EXPECT_LE(original_volume, max_volume); 139#endif 140 141 // Set the volume to the maxiumum level.. 142 ais->SetVolume(max_volume); 143 double current_volume = ais->GetVolume(); 144 EXPECT_EQ(max_volume, current_volume); 145 146 // Set the volume to the mininum level (=0). 147 double new_volume = 0.0; 148 ais->SetVolume(new_volume); 149#if defined(OS_LINUX) 150 current_volume = GetVolumeAfterSetVolumeOnLinux(ais, new_volume); 151#else 152 current_volume = ais->GetVolume(); 153#endif 154 EXPECT_EQ(new_volume, current_volume); 155 156 // Set the volume to the mid level (50% of max). 157 // Verify that the absolute error is small enough. 158 new_volume = max_volume / 2; 159 ais->SetVolume(new_volume); 160#if defined(OS_LINUX) 161 current_volume = GetVolumeAfterSetVolumeOnLinux(ais, new_volume); 162#else 163 current_volume = ais->GetVolume(); 164#endif 165 EXPECT_LT(current_volume, max_volume); 166 EXPECT_GT(current_volume, 0); 167 EXPECT_NEAR(current_volume, new_volume, 0.25 * max_volume); 168 169 // Restores the volume to the original value. 170 ais->SetVolume(original_volume); 171 current_volume = ais->GetVolume(); 172 EXPECT_EQ(original_volume, current_volume); 173 174 ais->Close(); 175 } 176} 177 178} // namespace media 179