• 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/bind.h"
7 #include "base/environment.h"
8 #include "base/logging.h"
9 #include "base/memory/ref_counted.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/synchronization/waitable_event.h"
13 #include "media/audio/audio_manager_base.h"
14 #include "media/audio/audio_output_controller.h"
15 #include "media/audio/audio_parameters.h"
16 #include "media/base/audio_bus.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 
20 using ::testing::_;
21 using ::testing::AtLeast;
22 using ::testing::DoAll;
23 using ::testing::Invoke;
24 using ::testing::NotNull;
25 using ::testing::Return;
26 
27 namespace media {
28 
29 static const int kSampleRate = AudioParameters::kAudioCDSampleRate;
30 static const int kBitsPerSample = 16;
31 static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO;
32 static const int kSamplesPerPacket = kSampleRate / 100;
33 static const double kTestVolume = 0.25;
34 
35 class MockAudioOutputControllerEventHandler
36     : public AudioOutputController::EventHandler {
37  public:
MockAudioOutputControllerEventHandler()38   MockAudioOutputControllerEventHandler() {}
39 
40   MOCK_METHOD0(OnCreated, void());
41   MOCK_METHOD0(OnPlaying, void());
42   MOCK_METHOD0(OnPaused, void());
43   MOCK_METHOD0(OnError, void());
44   MOCK_METHOD2(OnDeviceChange, void(int new_buffer_size, int new_sample_rate));
45 
46  private:
47   DISALLOW_COPY_AND_ASSIGN(MockAudioOutputControllerEventHandler);
48 };
49 
50 class MockAudioOutputControllerSyncReader
51     : public AudioOutputController::SyncReader {
52  public:
MockAudioOutputControllerSyncReader()53   MockAudioOutputControllerSyncReader() {}
54 
55   MOCK_METHOD1(UpdatePendingBytes, void(uint32 bytes));
56   MOCK_METHOD1(Read, void(AudioBus* dest));
57   MOCK_METHOD0(Close, void());
58 
59  private:
60   DISALLOW_COPY_AND_ASSIGN(MockAudioOutputControllerSyncReader);
61 };
62 
63 class MockAudioOutputStream : public AudioOutputStream {
64  public:
65   MOCK_METHOD0(Open, bool());
66   MOCK_METHOD1(Start, void(AudioSourceCallback* callback));
67   MOCK_METHOD0(Stop, void());
68   MOCK_METHOD1(SetVolume, void(double volume));
69   MOCK_METHOD1(GetVolume, void(double* volume));
70   MOCK_METHOD0(Close, void());
71 
72   // Set/get the callback passed to Start().
callback() const73   AudioSourceCallback* callback() const { return callback_; }
SetCallback(AudioSourceCallback * asc)74   void SetCallback(AudioSourceCallback* asc) { callback_ = asc; }
75 
76  private:
77   AudioSourceCallback* callback_;
78 };
79 
ACTION_P(SignalEvent,event)80 ACTION_P(SignalEvent, event) {
81   event->Signal();
82 }
83 
84 static const float kBufferNonZeroData = 1.0f;
ACTION(PopulateBuffer)85 ACTION(PopulateBuffer) {
86   arg0->Zero();
87   // Note: To confirm the buffer will be populated in these tests, it's
88   // sufficient that only the first float in channel 0 is set to the value.
89   arg0->channel(0)[0] = kBufferNonZeroData;
90 }
91 
92 class AudioOutputControllerTest : public testing::Test {
93  public:
AudioOutputControllerTest()94   AudioOutputControllerTest()
95       : audio_manager_(AudioManager::CreateForTesting()),
96         create_event_(false, false),
97         play_event_(false, false),
98         read_event_(false, false),
99         pause_event_(false, false) {
100   }
101 
~AudioOutputControllerTest()102   virtual ~AudioOutputControllerTest() {
103   }
104 
105  protected:
Create(int samples_per_packet)106   void Create(int samples_per_packet) {
107     EXPECT_FALSE(create_event_.IsSignaled());
108     EXPECT_FALSE(play_event_.IsSignaled());
109     EXPECT_FALSE(read_event_.IsSignaled());
110     EXPECT_FALSE(pause_event_.IsSignaled());
111 
112     params_ = AudioParameters(
113         AudioParameters::AUDIO_FAKE, kChannelLayout,
114         kSampleRate, kBitsPerSample, samples_per_packet);
115 
116     if (params_.IsValid()) {
117       EXPECT_CALL(mock_event_handler_, OnCreated())
118           .WillOnce(SignalEvent(&create_event_));
119     }
120 
121     controller_ = AudioOutputController::Create(
122         audio_manager_.get(), &mock_event_handler_, params_, std::string(),
123         &mock_sync_reader_);
124     if (controller_.get())
125       controller_->SetVolume(kTestVolume);
126 
127     EXPECT_EQ(params_.IsValid(), controller_.get() != NULL);
128   }
129 
Play()130   void Play() {
131     // Expect the event handler to receive one OnPlaying() call.
132     EXPECT_CALL(mock_event_handler_, OnPlaying())
133         .WillOnce(SignalEvent(&play_event_));
134 
135     // During playback, the mock pretends to provide audio data rendered and
136     // sent from the render process.
137     EXPECT_CALL(mock_sync_reader_, UpdatePendingBytes(_))
138         .Times(AtLeast(1));
139     EXPECT_CALL(mock_sync_reader_, Read(_))
140         .WillRepeatedly(DoAll(PopulateBuffer(),
141                               SignalEvent(&read_event_)));
142     controller_->Play();
143   }
144 
Pause()145   void Pause() {
146     // Expect the event handler to receive one OnPaused() call.
147     EXPECT_CALL(mock_event_handler_, OnPaused())
148         .WillOnce(SignalEvent(&pause_event_));
149 
150     controller_->Pause();
151   }
152 
ChangeDevice()153   void ChangeDevice() {
154     // Expect the event handler to receive one OnPaying() call and no OnPaused()
155     // call.
156     EXPECT_CALL(mock_event_handler_, OnPlaying())
157         .WillOnce(SignalEvent(&play_event_));
158     EXPECT_CALL(mock_event_handler_, OnPaused())
159         .Times(0);
160 
161     // Simulate a device change event to AudioOutputController from the
162     // AudioManager.
163     audio_manager_->GetTaskRunner()->PostTask(
164         FROM_HERE,
165         base::Bind(&AudioOutputController::OnDeviceChange, controller_));
166   }
167 
Divert(bool was_playing,int num_times_to_be_started)168   void Divert(bool was_playing, int num_times_to_be_started) {
169     if (was_playing) {
170       // Expect the handler to receive one OnPlaying() call as a result of the
171       // stream switching.
172       EXPECT_CALL(mock_event_handler_, OnPlaying())
173           .WillOnce(SignalEvent(&play_event_));
174     }
175 
176     EXPECT_CALL(mock_stream_, Open())
177         .WillOnce(Return(true));
178     EXPECT_CALL(mock_stream_, SetVolume(kTestVolume));
179     if (num_times_to_be_started > 0) {
180       EXPECT_CALL(mock_stream_, Start(NotNull()))
181           .Times(num_times_to_be_started)
182           .WillRepeatedly(
183               Invoke(&mock_stream_, &MockAudioOutputStream::SetCallback));
184       EXPECT_CALL(mock_stream_, Stop())
185           .Times(num_times_to_be_started);
186     }
187 
188     controller_->StartDiverting(&mock_stream_);
189   }
190 
ReadDivertedAudioData()191   void ReadDivertedAudioData() {
192     scoped_ptr<AudioBus> dest = AudioBus::Create(params_);
193     ASSERT_TRUE(!!mock_stream_.callback());
194     const int frames_read =
195         mock_stream_.callback()->OnMoreData(dest.get(), AudioBuffersState());
196     EXPECT_LT(0, frames_read);
197     EXPECT_EQ(kBufferNonZeroData, dest->channel(0)[0]);
198   }
199 
Revert(bool was_playing)200   void Revert(bool was_playing) {
201     if (was_playing) {
202       // Expect the handler to receive one OnPlaying() call as a result of the
203       // stream switching back.
204       EXPECT_CALL(mock_event_handler_, OnPlaying())
205           .WillOnce(SignalEvent(&play_event_));
206     }
207 
208     EXPECT_CALL(mock_stream_, Close());
209 
210     controller_->StopDiverting();
211   }
212 
SwitchDevice(bool diverting)213   void SwitchDevice(bool diverting) {
214     if (!diverting) {
215       // Expect the current stream to close and a new stream to start
216       // playing if not diverting. When diverting, nothing happens
217       // until diverting is stopped.
218       EXPECT_CALL(mock_event_handler_, OnPlaying())
219           .WillOnce(SignalEvent(&play_event_));
220     }
221 
222     controller_->SwitchOutputDevice(AudioManagerBase::kDefaultDeviceName,
223                                     base::Bind(&base::DoNothing));
224   }
225 
Close()226   void Close() {
227     EXPECT_CALL(mock_sync_reader_, Close());
228 
229     controller_->Close(base::MessageLoop::QuitClosure());
230     base::MessageLoop::current()->Run();
231   }
232 
233   // These help make test sequences more readable.
DivertNeverPlaying()234   void DivertNeverPlaying() { Divert(false, 0); }
DivertWillEventuallyBeTwicePlayed()235   void DivertWillEventuallyBeTwicePlayed() { Divert(false, 2); }
DivertWhilePlaying()236   void DivertWhilePlaying() { Divert(true, 1); }
RevertWasNotPlaying()237   void RevertWasNotPlaying() { Revert(false); }
RevertWhilePlaying()238   void RevertWhilePlaying() { Revert(true); }
239 
240   // These synchronize the main thread with key events taking place on other
241   // threads.
WaitForCreate()242   void WaitForCreate() { create_event_.Wait(); }
WaitForPlay()243   void WaitForPlay() { play_event_.Wait(); }
WaitForReads()244   void WaitForReads() {
245     // Note: Arbitrarily chosen, but more iterations causes tests to take
246     // significantly more time.
247     static const int kNumIterations = 3;
248     for (int i = 0; i < kNumIterations; ++i) {
249       read_event_.Wait();
250     }
251   }
WaitForPause()252   void WaitForPause() { pause_event_.Wait(); }
253 
254  private:
255   base::MessageLoopForIO message_loop_;
256   scoped_ptr<AudioManager> audio_manager_;
257   MockAudioOutputControllerEventHandler mock_event_handler_;
258   MockAudioOutputControllerSyncReader mock_sync_reader_;
259   MockAudioOutputStream mock_stream_;
260   base::WaitableEvent create_event_;
261   base::WaitableEvent play_event_;
262   base::WaitableEvent read_event_;
263   base::WaitableEvent pause_event_;
264   AudioParameters params_;
265   scoped_refptr<AudioOutputController> controller_;
266 
267   DISALLOW_COPY_AND_ASSIGN(AudioOutputControllerTest);
268 };
269 
TEST_F(AudioOutputControllerTest,CreateAndClose)270 TEST_F(AudioOutputControllerTest, CreateAndClose) {
271   Create(kSamplesPerPacket);
272   Close();
273 }
274 
TEST_F(AudioOutputControllerTest,HardwareBufferTooLarge)275 TEST_F(AudioOutputControllerTest, HardwareBufferTooLarge) {
276   Create(kSamplesPerPacket * 1000);
277 }
278 
TEST_F(AudioOutputControllerTest,PlayAndClose)279 TEST_F(AudioOutputControllerTest, PlayAndClose) {
280   Create(kSamplesPerPacket);
281   WaitForCreate();
282   Play();
283   WaitForPlay();
284   WaitForReads();
285   Close();
286 }
287 
TEST_F(AudioOutputControllerTest,PlayPauseClose)288 TEST_F(AudioOutputControllerTest, PlayPauseClose) {
289   Create(kSamplesPerPacket);
290   WaitForCreate();
291   Play();
292   WaitForPlay();
293   WaitForReads();
294   Pause();
295   WaitForPause();
296   Close();
297 }
298 
TEST_F(AudioOutputControllerTest,PlayPausePlayClose)299 TEST_F(AudioOutputControllerTest, PlayPausePlayClose) {
300   Create(kSamplesPerPacket);
301   WaitForCreate();
302   Play();
303   WaitForPlay();
304   WaitForReads();
305   Pause();
306   WaitForPause();
307   Play();
308   WaitForPlay();
309   Close();
310 }
311 
TEST_F(AudioOutputControllerTest,PlayDeviceChangeClose)312 TEST_F(AudioOutputControllerTest, PlayDeviceChangeClose) {
313   Create(kSamplesPerPacket);
314   WaitForCreate();
315   Play();
316   WaitForPlay();
317   WaitForReads();
318   ChangeDevice();
319   WaitForPlay();
320   WaitForReads();
321   Close();
322 }
323 
TEST_F(AudioOutputControllerTest,PlaySwitchDeviceClose)324 TEST_F(AudioOutputControllerTest, PlaySwitchDeviceClose) {
325   Create(kSamplesPerPacket);
326   WaitForCreate();
327   Play();
328   WaitForPlay();
329   WaitForReads();
330   SwitchDevice(false);
331   WaitForPlay();
332   WaitForReads();
333   Close();
334 }
335 
TEST_F(AudioOutputControllerTest,PlayDivertRevertClose)336 TEST_F(AudioOutputControllerTest, PlayDivertRevertClose) {
337   Create(kSamplesPerPacket);
338   WaitForCreate();
339   Play();
340   WaitForPlay();
341   WaitForReads();
342   DivertWhilePlaying();
343   WaitForPlay();
344   ReadDivertedAudioData();
345   RevertWhilePlaying();
346   WaitForPlay();
347   WaitForReads();
348   Close();
349 }
350 
TEST_F(AudioOutputControllerTest,PlayDivertSwitchDeviceRevertClose)351 TEST_F(AudioOutputControllerTest, PlayDivertSwitchDeviceRevertClose) {
352   Create(kSamplesPerPacket);
353   WaitForCreate();
354   Play();
355   WaitForPlay();
356   WaitForReads();
357   DivertWhilePlaying();
358   WaitForPlay();
359   SwitchDevice(true);
360   ReadDivertedAudioData();
361   RevertWhilePlaying();
362   WaitForPlay();
363   WaitForReads();
364   Close();
365 }
366 
TEST_F(AudioOutputControllerTest,PlayDivertRevertDivertRevertClose)367 TEST_F(AudioOutputControllerTest, PlayDivertRevertDivertRevertClose) {
368   Create(kSamplesPerPacket);
369   WaitForCreate();
370   Play();
371   WaitForPlay();
372   WaitForReads();
373   DivertWhilePlaying();
374   WaitForPlay();
375   ReadDivertedAudioData();
376   RevertWhilePlaying();
377   WaitForPlay();
378   WaitForReads();
379   DivertWhilePlaying();
380   WaitForPlay();
381   ReadDivertedAudioData();
382   RevertWhilePlaying();
383   WaitForPlay();
384   WaitForReads();
385   Close();
386 }
387 
TEST_F(AudioOutputControllerTest,DivertPlayPausePlayRevertClose)388 TEST_F(AudioOutputControllerTest, DivertPlayPausePlayRevertClose) {
389   Create(kSamplesPerPacket);
390   WaitForCreate();
391   DivertWillEventuallyBeTwicePlayed();
392   Play();
393   WaitForPlay();
394   ReadDivertedAudioData();
395   Pause();
396   WaitForPause();
397   Play();
398   WaitForPlay();
399   ReadDivertedAudioData();
400   RevertWhilePlaying();
401   WaitForPlay();
402   WaitForReads();
403   Close();
404 }
405 
TEST_F(AudioOutputControllerTest,DivertRevertClose)406 TEST_F(AudioOutputControllerTest, DivertRevertClose) {
407   Create(kSamplesPerPacket);
408   WaitForCreate();
409   DivertNeverPlaying();
410   RevertWasNotPlaying();
411   Close();
412 }
413 
414 }  // namespace media
415