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:
TestInputCallback()22 explicit TestInputCallback()
23 : callback_count_(0),
24 had_error_(0) {
25 }
OnData(AudioInputStream * stream,const AudioBus * source,uint32 hardware_delay_bytes,double volume)26 virtual void OnData(AudioInputStream* stream,
27 const AudioBus* source,
28 uint32 hardware_delay_bytes,
29 double volume) OVERRIDE {
30 ++callback_count_;
31 }
OnError(AudioInputStream * stream)32 virtual void OnError(AudioInputStream* stream) OVERRIDE {
33 ++had_error_;
34 }
35 // Returns how many times OnData() has been called.
callback_count() const36 int callback_count() const {
37 return callback_count_;
38 }
39 // Returns how many times the OnError callback was called.
had_error() const40 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:
AudioInputTest()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
~AudioInputTest()59 virtual ~AudioInputTest() {
60 base::RunLoop().RunUntilIdle();
61 }
62
63 protected:
audio_manager()64 AudioManager* audio_manager() { return audio_manager_.get(); }
65
CanRunAudioTests()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
MakeAudioInputStreamOnAudioThread()72 void MakeAudioInputStreamOnAudioThread() {
73 RunOnAudioThread(
74 base::Bind(&AudioInputTest::MakeAudioInputStream,
75 base::Unretained(this)));
76 }
77
CloseAudioInputStreamOnAudioThread()78 void CloseAudioInputStreamOnAudioThread() {
79 RunOnAudioThread(
80 base::Bind(&AudioInputStream::Close,
81 base::Unretained(audio_input_stream_)));
82 audio_input_stream_ = NULL;
83 }
84
OpenAndCloseAudioInputStreamOnAudioThread()85 void OpenAndCloseAudioInputStreamOnAudioThread() {
86 RunOnAudioThread(
87 base::Bind(&AudioInputTest::OpenAndClose,
88 base::Unretained(this)));
89 }
90
OpenStopAndCloseAudioInputStreamOnAudioThread()91 void OpenStopAndCloseAudioInputStreamOnAudioThread() {
92 RunOnAudioThread(
93 base::Bind(&AudioInputTest::OpenStopAndClose,
94 base::Unretained(this)));
95 }
96
OpenAndStartAudioInputStreamOnAudioThread(AudioInputStream::AudioInputCallback * sink)97 void OpenAndStartAudioInputStreamOnAudioThread(
98 AudioInputStream::AudioInputCallback* sink) {
99 RunOnAudioThread(
100 base::Bind(&AudioInputTest::OpenAndStart,
101 base::Unretained(this),
102 sink));
103 }
104
StopAndCloseAudioInputStreamOnAudioThread()105 void StopAndCloseAudioInputStreamOnAudioThread() {
106 RunOnAudioThread(
107 base::Bind(&AudioInputTest::StopAndClose,
108 base::Unretained(this)));
109 }
110
MakeAudioInputStream()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
OpenAndClose()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
OpenAndStart(AudioInputStream::AudioInputCallback * sink)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
OpenStopAndClose()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
StopAndClose()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.
RunOnAudioThread(const base::Closure & closure)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
RunOnAudioThreadImpl(const base::Closure & closure,base::WaitableEvent * event)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.
TEST_F(AudioInputTest,CreateAndClose)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.
TEST_F(AudioInputTest,MAYBE_OpenAndClose)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.
TEST_F(AudioInputTest,MAYBE_OpenStopAndClose)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.
TEST_F(AudioInputTest,MAYBE_Record)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