Home | History | Annotate | Download | only in audio
      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:
     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:
     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().
     73   AudioSourceCallback* callback() const { return callback_; }
     74   void SetCallback(AudioSourceCallback* asc) { callback_ = asc; }
     75 
     76  private:
     77   AudioSourceCallback* callback_;
     78 };
     79 
     80 ACTION_P(SignalEvent, event) {
     81   event->Signal();
     82 }
     83 
     84 static const float kBufferNonZeroData = 1.0f;
     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:
     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 
    102   virtual ~AudioOutputControllerTest() {
    103   }
    104 
    105  protected:
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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.
    234   void DivertNeverPlaying() { Divert(false, 0); }
    235   void DivertWillEventuallyBeTwicePlayed() { Divert(false, 2); }
    236   void DivertWhilePlaying() { Divert(true, 1); }
    237   void RevertWasNotPlaying() { Revert(false); }
    238   void RevertWhilePlaying() { Revert(true); }
    239 
    240   // These synchronize the main thread with key events taking place on other
    241   // threads.
    242   void WaitForCreate() { create_event_.Wait(); }
    243   void WaitForPlay() { play_event_.Wait(); }
    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   }
    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 
    270 TEST_F(AudioOutputControllerTest, CreateAndClose) {
    271   Create(kSamplesPerPacket);
    272   Close();
    273 }
    274 
    275 TEST_F(AudioOutputControllerTest, HardwareBufferTooLarge) {
    276   Create(kSamplesPerPacket * 1000);
    277 }
    278 
    279 TEST_F(AudioOutputControllerTest, PlayAndClose) {
    280   Create(kSamplesPerPacket);
    281   WaitForCreate();
    282   Play();
    283   WaitForPlay();
    284   WaitForReads();
    285   Close();
    286 }
    287 
    288 TEST_F(AudioOutputControllerTest, PlayPauseClose) {
    289   Create(kSamplesPerPacket);
    290   WaitForCreate();
    291   Play();
    292   WaitForPlay();
    293   WaitForReads();
    294   Pause();
    295   WaitForPause();
    296   Close();
    297 }
    298 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    406 TEST_F(AudioOutputControllerTest, DivertRevertClose) {
    407   Create(kSamplesPerPacket);
    408   WaitForCreate();
    409   DivertNeverPlaying();
    410   RevertWasNotPlaying();
    411   Close();
    412 }
    413 
    414 }  // namespace media
    415