• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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