Home | History | Annotate | Download | only in media
      1 // Copyright 2013 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/message_loop/message_loop.h"
      6 #include "base/run_loop.h"
      7 #include "content/renderer/media/webaudiosourceprovider_impl.h"
      8 #include "media/audio/audio_parameters.h"
      9 #include "media/base/fake_audio_render_callback.h"
     10 #include "media/base/mock_audio_renderer_sink.h"
     11 #include "testing/gmock/include/gmock/gmock.h"
     12 #include "testing/gtest/include/gtest/gtest.h"
     13 #include "third_party/WebKit/public/platform/WebAudioSourceProviderClient.h"
     14 
     15 namespace content {
     16 
     17 namespace {
     18 const float kTestVolume = 0.25;
     19 }  // namespace
     20 
     21 class WebAudioSourceProviderImplTest
     22     : public testing::Test,
     23       public blink::WebAudioSourceProviderClient {
     24  public:
     25   WebAudioSourceProviderImplTest()
     26       : params_(media::AudioParameters::AUDIO_PCM_LINEAR,
     27                 media::CHANNEL_LAYOUT_STEREO, 48000, 16, 64),
     28         fake_callback_(0.1),
     29         mock_sink_(new media::MockAudioRendererSink()),
     30         wasp_impl_(new WebAudioSourceProviderImpl(mock_sink_)) {
     31   }
     32 
     33   virtual ~WebAudioSourceProviderImplTest() {}
     34 
     35   void CallAllSinkMethodsAndVerify(bool verify) {
     36     testing::InSequence s;
     37 
     38     EXPECT_CALL(*mock_sink_.get(), Start()).Times(verify);
     39     wasp_impl_->Start();
     40 
     41     EXPECT_CALL(*mock_sink_.get(), Play()).Times(verify);
     42     wasp_impl_->Play();
     43 
     44     EXPECT_CALL(*mock_sink_.get(), Pause()).Times(verify);
     45     wasp_impl_->Pause();
     46 
     47     EXPECT_CALL(*mock_sink_.get(), SetVolume(kTestVolume)).Times(verify);
     48     wasp_impl_->SetVolume(kTestVolume);
     49 
     50     EXPECT_CALL(*mock_sink_.get(), Stop()).Times(verify);
     51     wasp_impl_->Stop();
     52 
     53     testing::Mock::VerifyAndClear(mock_sink_.get());
     54   }
     55 
     56   void SetClient(blink::WebAudioSourceProviderClient* client) {
     57     testing::InSequence s;
     58 
     59     if (client) {
     60       EXPECT_CALL(*mock_sink_.get(), Stop());
     61       EXPECT_CALL(*this, setFormat(params_.channels(), params_.sample_rate()));
     62     }
     63     wasp_impl_->setClient(client);
     64     base::RunLoop().RunUntilIdle();
     65 
     66     testing::Mock::VerifyAndClear(mock_sink_.get());
     67     testing::Mock::VerifyAndClear(this);
     68   }
     69 
     70   bool CompareBusses(const media::AudioBus* bus1, const media::AudioBus* bus2) {
     71     EXPECT_EQ(bus1->channels(), bus2->channels());
     72     EXPECT_EQ(bus1->frames(), bus2->frames());
     73     for (int ch = 0; ch < bus1->channels(); ++ch) {
     74       if (memcmp(bus1->channel(ch), bus2->channel(ch),
     75                  sizeof(*bus1->channel(ch)) * bus1->frames()) != 0) {
     76         return false;
     77       }
     78     }
     79     return true;
     80   }
     81 
     82   // blink::WebAudioSourceProviderClient implementation.
     83   MOCK_METHOD2(setFormat, void(size_t numberOfChannels, float sampleRate));
     84 
     85  protected:
     86   media::AudioParameters params_;
     87   media::FakeAudioRenderCallback fake_callback_;
     88   scoped_refptr<media::MockAudioRendererSink> mock_sink_;
     89   scoped_refptr<WebAudioSourceProviderImpl> wasp_impl_;
     90   base::MessageLoop message_loop_;
     91 
     92   DISALLOW_COPY_AND_ASSIGN(WebAudioSourceProviderImplTest);
     93 };
     94 
     95 TEST_F(WebAudioSourceProviderImplTest, SetClientBeforeInitialize) {
     96   // setClient() with a NULL client should do nothing if no client is set.
     97   wasp_impl_->setClient(NULL);
     98 
     99   EXPECT_CALL(*mock_sink_.get(), Stop());
    100   wasp_impl_->setClient(this);
    101   base::RunLoop().RunUntilIdle();
    102 
    103   // When Initialize() is called after setClient(), the params should propagate
    104   // to the client via setFormat() during the call.
    105   EXPECT_CALL(*this, setFormat(params_.channels(), params_.sample_rate()));
    106   wasp_impl_->Initialize(params_, &fake_callback_);
    107   base::RunLoop().RunUntilIdle();
    108 
    109   // setClient() with the same client should do nothing.
    110   wasp_impl_->setClient(this);
    111   base::RunLoop().RunUntilIdle();
    112 }
    113 
    114 // Verify AudioRendererSink functionality w/ and w/o a client.
    115 TEST_F(WebAudioSourceProviderImplTest, SinkMethods) {
    116   wasp_impl_->Initialize(params_, &fake_callback_);
    117   ASSERT_EQ(mock_sink_->callback(), &fake_callback_);
    118 
    119   // Without a client all WASP calls should fall through to the underlying sink.
    120   CallAllSinkMethodsAndVerify(true);
    121 
    122   // With a client no calls should reach the Stop()'d sink.  Also, setClient()
    123   // should propagate the params provided during Initialize() at call time.
    124   SetClient(this);
    125   CallAllSinkMethodsAndVerify(false);
    126 
    127   // Removing the client should cause WASP to revert to the underlying sink.
    128   EXPECT_CALL(*mock_sink_.get(), SetVolume(kTestVolume));
    129   SetClient(NULL);
    130   CallAllSinkMethodsAndVerify(true);
    131 }
    132 
    133 // Verify underlying sink state is restored after client removal.
    134 TEST_F(WebAudioSourceProviderImplTest, SinkStateRestored) {
    135   wasp_impl_->Initialize(params_, &fake_callback_);
    136 
    137   // Verify state set before the client is set propagates back afterward.
    138   EXPECT_CALL(*mock_sink_.get(), Start());
    139   wasp_impl_->Start();
    140   SetClient(this);
    141 
    142   EXPECT_CALL(*mock_sink_.get(), SetVolume(1.0));
    143   EXPECT_CALL(*mock_sink_.get(), Start());
    144   SetClient(NULL);
    145 
    146   // Verify state set while the client was attached propagates back afterward.
    147   SetClient(this);
    148   wasp_impl_->Play();
    149   wasp_impl_->SetVolume(kTestVolume);
    150 
    151   EXPECT_CALL(*mock_sink_.get(), SetVolume(kTestVolume));
    152   EXPECT_CALL(*mock_sink_.get(), Start());
    153   EXPECT_CALL(*mock_sink_.get(), Play());
    154   SetClient(NULL);
    155 }
    156 
    157 // Test the AudioRendererSink state machine and its effects on provideInput().
    158 TEST_F(WebAudioSourceProviderImplTest, ProvideInput) {
    159   scoped_ptr<media::AudioBus> bus1 = media::AudioBus::Create(params_);
    160   scoped_ptr<media::AudioBus> bus2 = media::AudioBus::Create(params_);
    161 
    162   // Point the WebVector into memory owned by |bus1|.
    163   blink::WebVector<float*> audio_data(static_cast<size_t>(bus1->channels()));
    164   for (size_t i = 0; i < audio_data.size(); ++i)
    165     audio_data[i] = bus1->channel(i);
    166 
    167   // Verify provideInput() works before Initialize() and returns silence.
    168   bus1->channel(0)[0] = 1;
    169   bus2->Zero();
    170   wasp_impl_->provideInput(audio_data, params_.frames_per_buffer());
    171   ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get()));
    172 
    173   wasp_impl_->Initialize(params_, &fake_callback_);
    174   SetClient(this);
    175 
    176   // Verify provideInput() is muted prior to Start() and no calls to the render
    177   // callback have occurred.
    178   bus1->channel(0)[0] = 1;
    179   bus2->Zero();
    180   wasp_impl_->provideInput(audio_data, params_.frames_per_buffer());
    181   ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get()));
    182   ASSERT_EQ(fake_callback_.last_audio_delay_milliseconds(), -1);
    183 
    184   wasp_impl_->Start();
    185 
    186   // Ditto for Play().
    187   bus1->channel(0)[0] = 1;
    188   wasp_impl_->provideInput(audio_data, params_.frames_per_buffer());
    189   ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get()));
    190   ASSERT_EQ(fake_callback_.last_audio_delay_milliseconds(), -1);
    191 
    192   wasp_impl_->Play();
    193 
    194   // Now we should get real audio data.
    195   wasp_impl_->provideInput(audio_data, params_.frames_per_buffer());
    196   ASSERT_FALSE(CompareBusses(bus1.get(), bus2.get()));
    197 
    198   // Ensure volume adjustment is working.
    199   fake_callback_.reset();
    200   fake_callback_.Render(bus2.get(), 0);
    201   bus2->Scale(kTestVolume);
    202 
    203   fake_callback_.reset();
    204   wasp_impl_->SetVolume(kTestVolume);
    205   wasp_impl_->provideInput(audio_data, params_.frames_per_buffer());
    206   ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get()));
    207 
    208   // Pause should return to silence.
    209   wasp_impl_->Pause();
    210   bus1->channel(0)[0] = 1;
    211   bus2->Zero();
    212   wasp_impl_->provideInput(audio_data, params_.frames_per_buffer());
    213   ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get()));
    214 
    215   wasp_impl_->Play();
    216 
    217   // Play should return real audio data again...
    218   wasp_impl_->provideInput(audio_data, params_.frames_per_buffer());
    219   ASSERT_FALSE(CompareBusses(bus1.get(), bus2.get()));
    220 
    221   // Stop() should return silence.
    222   wasp_impl_->Stop();
    223   bus1->channel(0)[0] = 1;
    224   wasp_impl_->provideInput(audio_data, params_.frames_per_buffer());
    225   ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get()));
    226 }
    227 
    228 }  // namespace content
    229