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_METHOD2(OnPowerMeasured, void(float power_dbfs, bool clipped));
     43   MOCK_METHOD0(OnPaused, void());
     44   MOCK_METHOD0(OnError, void());
     45   MOCK_METHOD2(OnDeviceChange, void(int new_buffer_size, int new_sample_rate));
     46 
     47  private:
     48   DISALLOW_COPY_AND_ASSIGN(MockAudioOutputControllerEventHandler);
     49 };
     50 
     51 class MockAudioOutputControllerSyncReader
     52     : public AudioOutputController::SyncReader {
     53  public:
     54   MockAudioOutputControllerSyncReader() {}
     55 
     56   MOCK_METHOD1(UpdatePendingBytes, void(uint32 bytes));
     57   MOCK_METHOD2(Read, void(const AudioBus* source, AudioBus* dest));
     58   MOCK_METHOD0(Close, void());
     59 
     60  private:
     61   DISALLOW_COPY_AND_ASSIGN(MockAudioOutputControllerSyncReader);
     62 };
     63 
     64 class MockAudioOutputStream : public AudioOutputStream {
     65  public:
     66   MOCK_METHOD0(Open, bool());
     67   MOCK_METHOD1(Start, void(AudioSourceCallback* callback));
     68   MOCK_METHOD0(Stop, void());
     69   MOCK_METHOD1(SetVolume, void(double volume));
     70   MOCK_METHOD1(GetVolume, void(double* volume));
     71   MOCK_METHOD0(Close, void());
     72 
     73   // Set/get the callback passed to Start().
     74   AudioSourceCallback* callback() const { return callback_; }
     75   void SetCallback(AudioSourceCallback* asc) { callback_ = asc; }
     76 
     77  private:
     78   AudioSourceCallback* callback_;
     79 };
     80 
     81 ACTION_P(SignalEvent, event) {
     82   event->Signal();
     83 }
     84 
     85 static const float kBufferNonZeroData = 1.0f;
     86 ACTION(PopulateBuffer) {
     87   arg1->Zero();
     88   // Note: To confirm the buffer will be populated in these tests, it's
     89   // sufficient that only the first float in channel 0 is set to the value.
     90   arg1->channel(0)[0] = kBufferNonZeroData;
     91 }
     92 
     93 class AudioOutputControllerTest : public testing::Test {
     94  public:
     95   AudioOutputControllerTest()
     96       : audio_manager_(AudioManager::CreateForTesting()),
     97         create_event_(false, false),
     98         play_event_(false, false),
     99         read_event_(false, false),
    100         pause_event_(false, false) {
    101   }
    102 
    103   virtual ~AudioOutputControllerTest() {
    104   }
    105 
    106  protected:
    107   void Create(int samples_per_packet) {
    108     EXPECT_FALSE(create_event_.IsSignaled());
    109     EXPECT_FALSE(play_event_.IsSignaled());
    110     EXPECT_FALSE(read_event_.IsSignaled());
    111     EXPECT_FALSE(pause_event_.IsSignaled());
    112 
    113     params_ = AudioParameters(
    114         AudioParameters::AUDIO_FAKE, kChannelLayout,
    115         kSampleRate, kBitsPerSample, samples_per_packet);
    116 
    117     if (params_.IsValid()) {
    118       EXPECT_CALL(mock_event_handler_, OnCreated())
    119           .WillOnce(SignalEvent(&create_event_));
    120     }
    121 
    122     controller_ = AudioOutputController::Create(
    123         audio_manager_.get(), &mock_event_handler_, params_, std::string(),
    124         std::string(), &mock_sync_reader_);
    125     if (controller_.get())
    126       controller_->SetVolume(kTestVolume);
    127 
    128     EXPECT_EQ(params_.IsValid(), controller_.get() != NULL);
    129   }
    130 
    131   void Play() {
    132     // Expect the event handler to receive one OnPlaying() call and one or more
    133     // OnPowerMeasured() calls.
    134     EXPECT_CALL(mock_event_handler_, OnPlaying())
    135         .WillOnce(SignalEvent(&play_event_));
    136 #if defined(AUDIO_POWER_MONITORING)
    137     EXPECT_CALL(mock_event_handler_, OnPowerMeasured(_, false))
    138         .Times(AtLeast(1));
    139 #endif
    140 
    141     // During playback, the mock pretends to provide audio data rendered and
    142     // sent from the render process.
    143     EXPECT_CALL(mock_sync_reader_, UpdatePendingBytes(_))
    144         .Times(AtLeast(1));
    145     EXPECT_CALL(mock_sync_reader_, Read(_, _))
    146         .WillRepeatedly(DoAll(PopulateBuffer(),
    147                               SignalEvent(&read_event_)));
    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 SwitchDevice(bool diverting) {
    220     if (!diverting) {
    221       // Expect the current stream to close and a new stream to start
    222       // playing if not diverting. When diverting, nothing happens
    223       // until diverting is stopped.
    224       EXPECT_CALL(mock_event_handler_, OnPlaying())
    225           .WillOnce(SignalEvent(&play_event_));
    226     }
    227 
    228     controller_->SwitchOutputDevice(AudioManagerBase::kDefaultDeviceName,
    229                                     base::Bind(&base::DoNothing));
    230   }
    231 
    232   void Close() {
    233     EXPECT_CALL(mock_sync_reader_, Close());
    234 
    235     controller_->Close(base::MessageLoop::QuitClosure());
    236     base::MessageLoop::current()->Run();
    237   }
    238 
    239   // These help make test sequences more readable.
    240   void DivertNeverPlaying() { Divert(false, 0); }
    241   void DivertWillEventuallyBeTwicePlayed() { Divert(false, 2); }
    242   void DivertWhilePlaying() { Divert(true, 1); }
    243   void RevertWasNotPlaying() { Revert(false); }
    244   void RevertWhilePlaying() { Revert(true); }
    245 
    246   // These synchronize the main thread with key events taking place on other
    247   // threads.
    248   void WaitForCreate() { create_event_.Wait(); }
    249   void WaitForPlay() { play_event_.Wait(); }
    250   void WaitForReads() {
    251     // Note: Arbitrarily chosen, but more iterations causes tests to take
    252     // significantly more time.
    253     static const int kNumIterations = 3;
    254     for (int i = 0; i < kNumIterations; ++i) {
    255       read_event_.Wait();
    256     }
    257   }
    258   void WaitForPause() { pause_event_.Wait(); }
    259 
    260  private:
    261   base::MessageLoopForIO message_loop_;
    262   scoped_ptr<AudioManager> audio_manager_;
    263   MockAudioOutputControllerEventHandler mock_event_handler_;
    264   MockAudioOutputControllerSyncReader mock_sync_reader_;
    265   MockAudioOutputStream mock_stream_;
    266   base::WaitableEvent create_event_;
    267   base::WaitableEvent play_event_;
    268   base::WaitableEvent read_event_;
    269   base::WaitableEvent pause_event_;
    270   AudioParameters params_;
    271   scoped_refptr<AudioOutputController> controller_;
    272 
    273   DISALLOW_COPY_AND_ASSIGN(AudioOutputControllerTest);
    274 };
    275 
    276 TEST_F(AudioOutputControllerTest, CreateAndClose) {
    277   Create(kSamplesPerPacket);
    278   Close();
    279 }
    280 
    281 TEST_F(AudioOutputControllerTest, HardwareBufferTooLarge) {
    282   Create(kSamplesPerPacket * 1000);
    283 }
    284 
    285 TEST_F(AudioOutputControllerTest, PlayAndClose) {
    286   Create(kSamplesPerPacket);
    287   WaitForCreate();
    288   Play();
    289   WaitForPlay();
    290   WaitForReads();
    291   Close();
    292 }
    293 
    294 TEST_F(AudioOutputControllerTest, PlayPauseClose) {
    295   Create(kSamplesPerPacket);
    296   WaitForCreate();
    297   Play();
    298   WaitForPlay();
    299   WaitForReads();
    300   Pause();
    301   WaitForPause();
    302   Close();
    303 }
    304 
    305 TEST_F(AudioOutputControllerTest, PlayPausePlayClose) {
    306   Create(kSamplesPerPacket);
    307   WaitForCreate();
    308   Play();
    309   WaitForPlay();
    310   WaitForReads();
    311   Pause();
    312   WaitForPause();
    313   Play();
    314   WaitForPlay();
    315   Close();
    316 }
    317 
    318 TEST_F(AudioOutputControllerTest, PlayDeviceChangeClose) {
    319   Create(kSamplesPerPacket);
    320   WaitForCreate();
    321   Play();
    322   WaitForPlay();
    323   WaitForReads();
    324   ChangeDevice();
    325   WaitForPlay();
    326   WaitForReads();
    327   Close();
    328 }
    329 
    330 TEST_F(AudioOutputControllerTest, PlaySwitchDeviceClose) {
    331   Create(kSamplesPerPacket);
    332   WaitForCreate();
    333   Play();
    334   WaitForPlay();
    335   WaitForReads();
    336   SwitchDevice(false);
    337   WaitForPlay();
    338   WaitForReads();
    339   Close();
    340 }
    341 
    342 TEST_F(AudioOutputControllerTest, PlayDivertRevertClose) {
    343   Create(kSamplesPerPacket);
    344   WaitForCreate();
    345   Play();
    346   WaitForPlay();
    347   WaitForReads();
    348   DivertWhilePlaying();
    349   WaitForPlay();
    350   ReadDivertedAudioData();
    351   RevertWhilePlaying();
    352   WaitForPlay();
    353   WaitForReads();
    354   Close();
    355 }
    356 
    357 TEST_F(AudioOutputControllerTest, PlayDivertSwitchDeviceRevertClose) {
    358   Create(kSamplesPerPacket);
    359   WaitForCreate();
    360   Play();
    361   WaitForPlay();
    362   WaitForReads();
    363   DivertWhilePlaying();
    364   WaitForPlay();
    365   SwitchDevice(true);
    366   ReadDivertedAudioData();
    367   RevertWhilePlaying();
    368   WaitForPlay();
    369   WaitForReads();
    370   Close();
    371 }
    372 
    373 TEST_F(AudioOutputControllerTest, PlayDivertRevertDivertRevertClose) {
    374   Create(kSamplesPerPacket);
    375   WaitForCreate();
    376   Play();
    377   WaitForPlay();
    378   WaitForReads();
    379   DivertWhilePlaying();
    380   WaitForPlay();
    381   ReadDivertedAudioData();
    382   RevertWhilePlaying();
    383   WaitForPlay();
    384   WaitForReads();
    385   DivertWhilePlaying();
    386   WaitForPlay();
    387   ReadDivertedAudioData();
    388   RevertWhilePlaying();
    389   WaitForPlay();
    390   WaitForReads();
    391   Close();
    392 }
    393 
    394 TEST_F(AudioOutputControllerTest, DivertPlayPausePlayRevertClose) {
    395   Create(kSamplesPerPacket);
    396   WaitForCreate();
    397   DivertWillEventuallyBeTwicePlayed();
    398   Play();
    399   WaitForPlay();
    400   ReadDivertedAudioData();
    401   Pause();
    402   WaitForPause();
    403   Play();
    404   WaitForPlay();
    405   ReadDivertedAudioData();
    406   RevertWhilePlaying();
    407   WaitForPlay();
    408   WaitForReads();
    409   Close();
    410 }
    411 
    412 TEST_F(AudioOutputControllerTest, DivertRevertClose) {
    413   Create(kSamplesPerPacket);
    414   WaitForCreate();
    415   DivertNeverPlaying();
    416   RevertWasNotPlaying();
    417   Close();
    418 }
    419 
    420 }  // namespace media
    421