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 "base/basictypes.h" 6 #include "base/environment.h" 7 #include "base/memory/scoped_ptr.h" 8 #include "base/message_loop/message_loop.h" 9 #include "base/run_loop.h" 10 #include "base/synchronization/waitable_event.h" 11 #include "base/threading/platform_thread.h" 12 #include "media/audio/audio_io.h" 13 #include "media/audio/audio_manager_base.h" 14 #include "testing/gtest/include/gtest/gtest.h" 15 16 namespace media { 17 18 // This class allows to find out if the callbacks are occurring as 19 // expected and if any error has been reported. 20 class TestInputCallback : public AudioInputStream::AudioInputCallback { 21 public: 22 explicit TestInputCallback() 23 : callback_count_(0), 24 had_error_(0) { 25 } 26 virtual void OnData(AudioInputStream* stream, 27 const AudioBus* source, 28 uint32 hardware_delay_bytes, 29 double volume) OVERRIDE { 30 ++callback_count_; 31 } 32 virtual void OnError(AudioInputStream* stream) OVERRIDE { 33 ++had_error_; 34 } 35 // Returns how many times OnData() has been called. 36 int callback_count() const { 37 return callback_count_; 38 } 39 // Returns how many times the OnError callback was called. 40 int had_error() const { 41 return had_error_; 42 } 43 44 private: 45 int callback_count_; 46 int had_error_; 47 }; 48 49 class AudioInputTest : public testing::Test { 50 public: 51 AudioInputTest() : 52 message_loop_(base::MessageLoop::TYPE_UI), 53 audio_manager_(AudioManager::CreateForTesting()), 54 audio_input_stream_(NULL) { 55 // Wait for the AudioManager to finish any initialization on the audio loop. 56 base::RunLoop().RunUntilIdle(); 57 } 58 59 virtual ~AudioInputTest() { 60 base::RunLoop().RunUntilIdle(); 61 } 62 63 protected: 64 AudioManager* audio_manager() { return audio_manager_.get(); } 65 66 bool CanRunAudioTests() { 67 bool has_input = audio_manager()->HasAudioInputDevices(); 68 LOG_IF(WARNING, !has_input) << "No input devices detected"; 69 return has_input; 70 } 71 72 void MakeAudioInputStreamOnAudioThread() { 73 RunOnAudioThread( 74 base::Bind(&AudioInputTest::MakeAudioInputStream, 75 base::Unretained(this))); 76 } 77 78 void CloseAudioInputStreamOnAudioThread() { 79 RunOnAudioThread( 80 base::Bind(&AudioInputStream::Close, 81 base::Unretained(audio_input_stream_))); 82 audio_input_stream_ = NULL; 83 } 84 85 void OpenAndCloseAudioInputStreamOnAudioThread() { 86 RunOnAudioThread( 87 base::Bind(&AudioInputTest::OpenAndClose, 88 base::Unretained(this))); 89 } 90 91 void OpenStopAndCloseAudioInputStreamOnAudioThread() { 92 RunOnAudioThread( 93 base::Bind(&AudioInputTest::OpenStopAndClose, 94 base::Unretained(this))); 95 } 96 97 void OpenAndStartAudioInputStreamOnAudioThread( 98 AudioInputStream::AudioInputCallback* sink) { 99 RunOnAudioThread( 100 base::Bind(&AudioInputTest::OpenAndStart, 101 base::Unretained(this), 102 sink)); 103 } 104 105 void StopAndCloseAudioInputStreamOnAudioThread() { 106 RunOnAudioThread( 107 base::Bind(&AudioInputTest::StopAndClose, 108 base::Unretained(this))); 109 } 110 111 void MakeAudioInputStream() { 112 DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread()); 113 AudioParameters params = audio_manager()->GetInputStreamParameters( 114 AudioManagerBase::kDefaultDeviceId); 115 audio_input_stream_ = audio_manager()->MakeAudioInputStream(params, 116 AudioManagerBase::kDefaultDeviceId); 117 EXPECT_TRUE(audio_input_stream_); 118 } 119 120 void OpenAndClose() { 121 DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread()); 122 EXPECT_TRUE(audio_input_stream_->Open()); 123 audio_input_stream_->Close(); 124 audio_input_stream_ = NULL; 125 } 126 127 void OpenAndStart(AudioInputStream::AudioInputCallback* sink) { 128 DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread()); 129 EXPECT_TRUE(audio_input_stream_->Open()); 130 audio_input_stream_->Start(sink); 131 } 132 133 void OpenStopAndClose() { 134 DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread()); 135 EXPECT_TRUE(audio_input_stream_->Open()); 136 audio_input_stream_->Stop(); 137 audio_input_stream_->Close(); 138 audio_input_stream_ = NULL; 139 } 140 141 void StopAndClose() { 142 DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread()); 143 audio_input_stream_->Stop(); 144 audio_input_stream_->Close(); 145 audio_input_stream_ = NULL; 146 } 147 148 // Synchronously runs the provided callback/closure on the audio thread. 149 void RunOnAudioThread(const base::Closure& closure) { 150 if (!audio_manager()->GetTaskRunner()->BelongsToCurrentThread()) { 151 base::WaitableEvent event(false, false); 152 audio_manager()->GetTaskRunner()->PostTask( 153 FROM_HERE, 154 base::Bind(&AudioInputTest::RunOnAudioThreadImpl, 155 base::Unretained(this), 156 closure, 157 &event)); 158 event.Wait(); 159 } else { 160 closure.Run(); 161 } 162 } 163 164 void RunOnAudioThreadImpl(const base::Closure& closure, 165 base::WaitableEvent* event) { 166 DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread()); 167 closure.Run(); 168 event->Signal(); 169 } 170 171 base::MessageLoop message_loop_; 172 scoped_ptr<AudioManager> audio_manager_; 173 AudioInputStream* audio_input_stream_; 174 175 private: 176 DISALLOW_COPY_AND_ASSIGN(AudioInputTest); 177 }; 178 179 // Test create and close of an AudioInputStream without recording audio. 180 TEST_F(AudioInputTest, CreateAndClose) { 181 if (!CanRunAudioTests()) 182 return; 183 MakeAudioInputStreamOnAudioThread(); 184 CloseAudioInputStreamOnAudioThread(); 185 } 186 187 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY) 188 // This test is failing on ARM linux: http://crbug.com/238490 189 #define MAYBE_OpenAndClose DISABLED_OpenAndClose 190 #else 191 #define MAYBE_OpenAndClose OpenAndClose 192 #endif 193 // Test create, open and close of an AudioInputStream without recording audio. 194 TEST_F(AudioInputTest, MAYBE_OpenAndClose) { 195 if (!CanRunAudioTests()) 196 return; 197 MakeAudioInputStreamOnAudioThread(); 198 OpenAndCloseAudioInputStreamOnAudioThread(); 199 } 200 201 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY) 202 // This test is failing on ARM linux: http://crbug.com/238490 203 #define MAYBE_OpenStopAndClose DISABLED_OpenStopAndClose 204 #else 205 #define MAYBE_OpenStopAndClose OpenStopAndClose 206 #endif 207 // Test create, open, stop and close of an AudioInputStream without recording. 208 TEST_F(AudioInputTest, MAYBE_OpenStopAndClose) { 209 if (!CanRunAudioTests()) 210 return; 211 MakeAudioInputStreamOnAudioThread(); 212 OpenStopAndCloseAudioInputStreamOnAudioThread(); 213 } 214 215 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY) 216 // This test is failing on ARM linux: http://crbug.com/238490 217 #define MAYBE_Record DISABLED_Record 218 #else 219 #define MAYBE_Record Record 220 #endif 221 // Test a normal recording sequence using an AudioInputStream. 222 // Very simple test which starts capturing during half a second and verifies 223 // that recording starts. 224 TEST_F(AudioInputTest, MAYBE_Record) { 225 if (!CanRunAudioTests()) 226 return; 227 MakeAudioInputStreamOnAudioThread(); 228 229 TestInputCallback test_callback; 230 OpenAndStartAudioInputStreamOnAudioThread(&test_callback); 231 232 message_loop_.PostDelayedTask( 233 FROM_HERE, 234 base::MessageLoop::QuitClosure(), 235 base::TimeDelta::FromMilliseconds(500)); 236 message_loop_.Run(); 237 EXPECT_GE(test_callback.callback_count(), 2); 238 EXPECT_FALSE(test_callback.had_error()); 239 240 StopAndCloseAudioInputStreamOnAudioThread(); 241 } 242 243 } // namespace media 244