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