Home | History | Annotate | Download | only in win
      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 <windows.h>
      6 #include <mmsystem.h>
      7 
      8 #include "base/basictypes.h"
      9 #include "base/base_paths.h"
     10 #include "base/memory/aligned_memory.h"
     11 #include "base/path_service.h"
     12 #include "base/sync_socket.h"
     13 #include "base/win/scoped_com_initializer.h"
     14 #include "base/win/windows_version.h"
     15 #include "media/base/limits.h"
     16 #include "media/audio/audio_io.h"
     17 #include "media/audio/audio_manager.h"
     18 #include "media/audio/mock_audio_source_callback.h"
     19 #include "media/audio/simple_sources.h"
     20 #include "testing/gmock/include/gmock/gmock.h"
     21 #include "testing/gtest/include/gtest/gtest.h"
     22 
     23 using ::testing::_;
     24 using ::testing::AnyNumber;
     25 using ::testing::DoAll;
     26 using ::testing::Field;
     27 using ::testing::Invoke;
     28 using ::testing::InSequence;
     29 using ::testing::NiceMock;
     30 using ::testing::NotNull;
     31 using ::testing::Return;
     32 
     33 using base::win::ScopedCOMInitializer;
     34 
     35 namespace media {
     36 
     37 static const wchar_t kAudioFile1_16b_m_16K[]
     38     = L"media\\test\\data\\sweep02_16b_mono_16KHz.raw";
     39 
     40 static int ClearData(AudioBus* audio_bus, AudioBuffersState buffers_state) {
     41   audio_bus->Zero();
     42   return audio_bus->frames();
     43 }
     44 
     45 // This class allows to find out if the callbacks are occurring as
     46 // expected and if any error has been reported.
     47 class TestSourceBasic : public AudioOutputStream::AudioSourceCallback {
     48  public:
     49   explicit TestSourceBasic()
     50       : callback_count_(0),
     51         had_error_(0) {
     52   }
     53   // AudioSourceCallback::OnMoreData implementation:
     54   virtual int OnMoreData(AudioBus* audio_bus,
     55                          AudioBuffersState buffers_state) {
     56     ++callback_count_;
     57     // Touch the channel memory value to make sure memory is good.
     58     audio_bus->Zero();
     59     return audio_bus->frames();
     60   }
     61   // AudioSourceCallback::OnError implementation:
     62   virtual void OnError(AudioOutputStream* stream) {
     63     ++had_error_;
     64   }
     65   // Returns how many times OnMoreData() has been called.
     66   int callback_count() const {
     67     return callback_count_;
     68   }
     69   // Returns how many times the OnError callback was called.
     70   int had_error() const {
     71     return had_error_;
     72   }
     73 
     74   void set_error(bool error) {
     75     had_error_ += error ? 1 : 0;
     76   }
     77 
     78  private:
     79   int callback_count_;
     80   int had_error_;
     81 };
     82 
     83 const int kMaxNumBuffers = 3;
     84 // Specializes TestSourceBasic to simulate a source that blocks for some time
     85 // in the OnMoreData callback.
     86 class TestSourceLaggy : public TestSourceBasic {
     87  public:
     88   TestSourceLaggy(int laggy_after_buffer, int lag_in_ms)
     89       : laggy_after_buffer_(laggy_after_buffer), lag_in_ms_(lag_in_ms) {
     90   }
     91   virtual int OnMoreData(AudioBus* audio_bus,
     92                          AudioBuffersState buffers_state) {
     93     // Call the base, which increments the callback_count_.
     94     TestSourceBasic::OnMoreData(audio_bus, buffers_state);
     95     if (callback_count() > kMaxNumBuffers) {
     96       ::Sleep(lag_in_ms_);
     97     }
     98     return audio_bus->frames();
     99   }
    100  private:
    101   int laggy_after_buffer_;
    102   int lag_in_ms_;
    103 };
    104 
    105 // Helper class to memory map an entire file. The mapping is read-only. Don't
    106 // use for gigabyte-sized files. Attempts to write to this memory generate
    107 // memory access violations.
    108 class ReadOnlyMappedFile {
    109  public:
    110   explicit ReadOnlyMappedFile(const wchar_t* file_name)
    111       : fmap_(NULL), start_(NULL), size_(0) {
    112     HANDLE file = ::CreateFileW(file_name, GENERIC_READ, FILE_SHARE_READ, NULL,
    113                                 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    114     if (INVALID_HANDLE_VALUE == file)
    115       return;
    116     fmap_ = ::CreateFileMappingW(file, NULL, PAGE_READONLY, 0, 0, NULL);
    117     ::CloseHandle(file);
    118     if (!fmap_)
    119       return;
    120     start_ = reinterpret_cast<char*>(::MapViewOfFile(fmap_, FILE_MAP_READ,
    121                                                      0, 0, 0));
    122     if (!start_)
    123       return;
    124     MEMORY_BASIC_INFORMATION mbi = {0};
    125     ::VirtualQuery(start_, &mbi, sizeof(mbi));
    126     size_ = mbi.RegionSize;
    127   }
    128   ~ReadOnlyMappedFile() {
    129     if (start_) {
    130       ::UnmapViewOfFile(start_);
    131       ::CloseHandle(fmap_);
    132     }
    133   }
    134   // Returns true if the file was successfully mapped.
    135   bool is_valid() const {
    136     return ((start_ > 0) && (size_ > 0));
    137   }
    138   // Returns the size in bytes of the mapped memory.
    139   uint32 size() const {
    140     return size_;
    141   }
    142   // Returns the memory backing the file.
    143   const void* GetChunkAt(uint32 offset) {
    144     return &start_[offset];
    145   }
    146 
    147  private:
    148   HANDLE fmap_;
    149   char* start_;
    150   uint32 size_;
    151 };
    152 
    153 // ===========================================================================
    154 // Validation of AudioManager::AUDIO_PCM_LINEAR
    155 //
    156 // NOTE:
    157 // The tests can fail on the build bots when somebody connects to them via
    158 // remote-desktop and the rdp client installs an audio device that fails to open
    159 // at some point, possibly when the connection goes idle.
    160 
    161 // Test that can it be created and closed.
    162 TEST(WinAudioTest, PCMWaveStreamGetAndClose) {
    163   scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
    164   if (!audio_man->HasAudioOutputDevices()) {
    165     LOG(WARNING) << "No output device detected.";
    166     return;
    167   }
    168 
    169   AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
    170       AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO,
    171                       8000, 16, 256),
    172       std::string());
    173   ASSERT_TRUE(NULL != oas);
    174   oas->Close();
    175 }
    176 
    177 // Test that can it be cannot be created with invalid parameters.
    178 TEST(WinAudioTest, SanityOnMakeParams) {
    179   scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
    180   if (!audio_man->HasAudioOutputDevices()) {
    181     LOG(WARNING) << "No output device detected.";
    182     return;
    183   }
    184 
    185   AudioParameters::Format fmt = AudioParameters::AUDIO_PCM_LINEAR;
    186   EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
    187       AudioParameters(fmt, CHANNEL_LAYOUT_UNSUPPORTED, 8000, 16, 256),
    188       std::string()));
    189   EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
    190       AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 1024 * 1024, 16, 256),
    191       std::string()));
    192   EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
    193       AudioParameters(fmt, CHANNEL_LAYOUT_STEREO, 8000, 80, 256),
    194       std::string()));
    195   EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
    196       AudioParameters(fmt, CHANNEL_LAYOUT_UNSUPPORTED, 8000, 16, 256),
    197       std::string()));
    198   EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
    199       AudioParameters(fmt, CHANNEL_LAYOUT_STEREO, -8000, 16, 256),
    200       std::string()));
    201   EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
    202       AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16, -100),
    203       std::string()));
    204   EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
    205       AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16, 0),
    206       std::string()));
    207   EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
    208       AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16,
    209                       media::limits::kMaxSamplesPerPacket + 1),
    210       std::string()));
    211 }
    212 
    213 // Test that it can be opened and closed.
    214 TEST(WinAudioTest, PCMWaveStreamOpenAndClose) {
    215   scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
    216   if (!audio_man->HasAudioOutputDevices()) {
    217     LOG(WARNING) << "No output device detected.";
    218     return;
    219   }
    220 
    221   AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
    222       AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO,
    223                       8000, 16, 256),
    224       std::string());
    225   ASSERT_TRUE(NULL != oas);
    226   EXPECT_TRUE(oas->Open());
    227   oas->Close();
    228 }
    229 
    230 // Test that it has a maximum packet size.
    231 TEST(WinAudioTest, PCMWaveStreamOpenLimit) {
    232   scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
    233   if (!audio_man->HasAudioOutputDevices()) {
    234     LOG(WARNING) << "No output device detected.";
    235     return;
    236   }
    237 
    238   AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
    239       AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO,
    240                       8000, 16, 1024 * 1024 * 1024),
    241       std::string());
    242   EXPECT_TRUE(NULL == oas);
    243   if (oas)
    244     oas->Close();
    245 }
    246 
    247 // Test potential deadlock situation if the source is slow or blocks for some
    248 // time. The actual EXPECT_GT are mostly meaningless and the real test is that
    249 // the test completes in reasonable time.
    250 TEST(WinAudioTest, PCMWaveSlowSource) {
    251   scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
    252   if (!audio_man->HasAudioOutputDevices()) {
    253     LOG(WARNING) << "No output device detected.";
    254     return;
    255   }
    256 
    257   AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
    258       AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
    259                       16000, 16, 256),
    260       std::string());
    261   ASSERT_TRUE(NULL != oas);
    262   TestSourceLaggy test_laggy(2, 90);
    263   EXPECT_TRUE(oas->Open());
    264   // The test parameters cause a callback every 32 ms and the source is
    265   // sleeping for 90 ms, so it is guaranteed that we run out of ready buffers.
    266   oas->Start(&test_laggy);
    267   ::Sleep(500);
    268   EXPECT_GT(test_laggy.callback_count(), 2);
    269   EXPECT_FALSE(test_laggy.had_error());
    270   oas->Stop();
    271   ::Sleep(500);
    272   oas->Close();
    273 }
    274 
    275 // Test another potential deadlock situation if the thread that calls Start()
    276 // gets paused. This test is best when run over RDP with audio enabled. See
    277 // bug 19276 for more details.
    278 TEST(WinAudioTest, PCMWaveStreamPlaySlowLoop) {
    279   scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
    280   if (!audio_man->HasAudioOutputDevices()) {
    281     LOG(WARNING) << "No output device detected.";
    282     return;
    283   }
    284 
    285   uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
    286   AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
    287       AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
    288                       AudioParameters::kAudioCDSampleRate, 16, samples_100_ms),
    289       std::string());
    290   ASSERT_TRUE(NULL != oas);
    291 
    292   SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate);
    293 
    294   EXPECT_TRUE(oas->Open());
    295   oas->SetVolume(1.0);
    296 
    297   for (int ix = 0; ix != 5; ++ix) {
    298     oas->Start(&source);
    299     ::Sleep(10);
    300     oas->Stop();
    301   }
    302   oas->Close();
    303 }
    304 
    305 
    306 // This test produces actual audio for .5 seconds on the default wave
    307 // device at 44.1K s/sec. Parameters have been chosen carefully so you should
    308 // not hear pops or noises while the sound is playing.
    309 TEST(WinAudioTest, PCMWaveStreamPlay200HzTone44Kss) {
    310   scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
    311   if (!audio_man->HasAudioOutputDevices()) {
    312     LOG(WARNING) << "No output device detected.";
    313     return;
    314   }
    315 
    316   uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
    317   AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
    318       AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
    319                       AudioParameters::kAudioCDSampleRate, 16, samples_100_ms),
    320       std::string());
    321   ASSERT_TRUE(NULL != oas);
    322 
    323   SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate);
    324 
    325   EXPECT_TRUE(oas->Open());
    326   oas->SetVolume(1.0);
    327   oas->Start(&source);
    328   ::Sleep(500);
    329   oas->Stop();
    330   oas->Close();
    331 }
    332 
    333 // This test produces actual audio for for .5 seconds on the default wave
    334 // device at 22K s/sec. Parameters have been chosen carefully so you should
    335 // not hear pops or noises while the sound is playing. The audio also should
    336 // sound with a lower volume than PCMWaveStreamPlay200HzTone44Kss.
    337 TEST(WinAudioTest, PCMWaveStreamPlay200HzTone22Kss) {
    338   scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
    339   if (!audio_man->HasAudioOutputDevices()) {
    340     LOG(WARNING) << "No output device detected.";
    341     return;
    342   }
    343 
    344   uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 20;
    345   AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
    346       AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
    347                       AudioParameters::kAudioCDSampleRate / 2, 16,
    348                       samples_100_ms),
    349       std::string());
    350   ASSERT_TRUE(NULL != oas);
    351 
    352   SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate/2);
    353 
    354   EXPECT_TRUE(oas->Open());
    355 
    356   oas->SetVolume(0.5);
    357   oas->Start(&source);
    358   ::Sleep(500);
    359 
    360   // Test that the volume is within the set limits.
    361   double volume = 0.0;
    362   oas->GetVolume(&volume);
    363   EXPECT_LT(volume, 0.51);
    364   EXPECT_GT(volume, 0.49);
    365   oas->Stop();
    366   oas->Close();
    367 }
    368 
    369 // Uses a restricted source to play ~2 seconds of audio for about 5 seconds. We
    370 // try hard to generate situation where the two threads are accessing the
    371 // object roughly at the same time.
    372 TEST(WinAudioTest, PushSourceFile16KHz)  {
    373   scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
    374   if (!audio_man->HasAudioOutputDevices()) {
    375     LOG(WARNING) << "No output device detected.";
    376     return;
    377   }
    378 
    379   static const int kSampleRate = 16000;
    380   SineWaveAudioSource source(1, 200.0, kSampleRate);
    381   // Compute buffer size for 100ms of audio.
    382   const uint32 kSamples100ms = (kSampleRate / 1000) * 100;
    383   // Restrict SineWaveAudioSource to 100ms of samples.
    384   source.CapSamples(kSamples100ms);
    385 
    386   AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
    387       AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
    388                       kSampleRate, 16, kSamples100ms),
    389       std::string());
    390   ASSERT_TRUE(NULL != oas);
    391 
    392   EXPECT_TRUE(oas->Open());
    393 
    394   oas->SetVolume(1.0);
    395   oas->Start(&source);
    396 
    397   // We buffer and play at the same time, buffering happens every ~10ms and the
    398   // consuming of the buffer happens every ~100ms. We do 100 buffers which
    399   // effectively wrap around the file more than once.
    400   for (uint32 ix = 0; ix != 100; ++ix) {
    401     ::Sleep(10);
    402     source.Reset();
    403   }
    404 
    405   // Play a little bit more of the file.
    406   ::Sleep(500);
    407 
    408   oas->Stop();
    409   oas->Close();
    410 }
    411 
    412 // This test is to make sure an AudioOutputStream can be started after it was
    413 // stopped. You will here two .5 seconds wave signal separated by 0.5 seconds
    414 // of silence.
    415 TEST(WinAudioTest, PCMWaveStreamPlayTwice200HzTone44Kss) {
    416   scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
    417   if (!audio_man->HasAudioOutputDevices()) {
    418     LOG(WARNING) << "No output device detected.";
    419     return;
    420   }
    421 
    422   uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
    423   AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
    424       AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
    425                       AudioParameters::kAudioCDSampleRate, 16, samples_100_ms),
    426       std::string());
    427   ASSERT_TRUE(NULL != oas);
    428 
    429   SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate);
    430   EXPECT_TRUE(oas->Open());
    431   oas->SetVolume(1.0);
    432 
    433   // Play the wave for .5 seconds.
    434   oas->Start(&source);
    435   ::Sleep(500);
    436   oas->Stop();
    437 
    438   // Sleep to give silence after stopping the AudioOutputStream.
    439   ::Sleep(250);
    440 
    441   // Start again and play for .5 seconds.
    442   oas->Start(&source);
    443   ::Sleep(500);
    444   oas->Stop();
    445 
    446   oas->Close();
    447 }
    448 
    449 // With the low latency mode, WASAPI is utilized by default for Vista and
    450 // higher and Wave is used for XP and lower. It is possible to utilize a
    451 // smaller buffer size for WASAPI than for Wave.
    452 TEST(WinAudioTest, PCMWaveStreamPlay200HzToneLowLatency) {
    453   scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
    454   if (!audio_man->HasAudioOutputDevices()) {
    455     LOG(WARNING) << "No output device detected.";
    456     return;
    457   }
    458 
    459   // The WASAPI API requires a correct COM environment.
    460   ScopedCOMInitializer com_init(ScopedCOMInitializer::kMTA);
    461 
    462   // Use 10 ms buffer size for WASAPI and 50 ms buffer size for Wave.
    463   // Take the existing native sample rate into account.
    464   const AudioParameters params = audio_man->GetDefaultOutputStreamParameters();
    465   int sample_rate = params.sample_rate();
    466   uint32 samples_10_ms = sample_rate / 100;
    467   int n = 1;
    468   (base::win::GetVersion() <= base::win::VERSION_XP) ? n = 5 : n = 1;
    469   AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
    470       AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
    471                       CHANNEL_LAYOUT_MONO, sample_rate,
    472                       16, n * samples_10_ms),
    473       std::string());
    474   ASSERT_TRUE(NULL != oas);
    475 
    476   SineWaveAudioSource source(1, 200, sample_rate);
    477 
    478   bool opened = oas->Open();
    479   if (!opened) {
    480     // It was not possible to open this audio device in mono.
    481     // No point in continuing the test so let's break here.
    482     LOG(WARNING) << "Mono is not supported. Skipping test.";
    483     oas->Close();
    484     return;
    485   }
    486   oas->SetVolume(1.0);
    487 
    488   // Play the wave for .8 seconds.
    489   oas->Start(&source);
    490   ::Sleep(800);
    491   oas->Stop();
    492   oas->Close();
    493 }
    494 
    495 // Check that the pending bytes value is correct what the stream starts.
    496 TEST(WinAudioTest, PCMWaveStreamPendingBytes) {
    497   scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
    498   if (!audio_man->HasAudioOutputDevices()) {
    499     LOG(WARNING) << "No output device detected.";
    500     return;
    501   }
    502 
    503   uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
    504   AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
    505       AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
    506                       AudioParameters::kAudioCDSampleRate, 16, samples_100_ms),
    507       std::string());
    508   ASSERT_TRUE(NULL != oas);
    509 
    510   NiceMock<MockAudioSourceCallback> source;
    511   EXPECT_TRUE(oas->Open());
    512 
    513   uint32 bytes_100_ms = samples_100_ms * 2;
    514 
    515   // Audio output stream has either a double or triple buffer scheme.
    516   // We expect the amount of pending bytes will reaching up to 2 times of
    517   // |bytes_100_ms| depending on number of buffers used.
    518   // From that it would decrease as we are playing the data but not providing
    519   // new one. And then we will try to provide zero data so the amount of
    520   // pending bytes will go down and eventually read zero.
    521   InSequence s;
    522 
    523   EXPECT_CALL(source, OnMoreData(NotNull(),
    524                                  Field(&AudioBuffersState::pending_bytes, 0)))
    525       .WillOnce(Invoke(ClearData));
    526 
    527   // Note: If AudioManagerWin::NumberOfWaveOutBuffers() ever changes, or if this
    528   // test is run on Vista, these expectations will fail.
    529   EXPECT_CALL(source, OnMoreData(NotNull(),
    530                                  Field(&AudioBuffersState::pending_bytes,
    531                                        bytes_100_ms)))
    532       .WillOnce(Invoke(ClearData));
    533   EXPECT_CALL(source, OnMoreData(NotNull(),
    534                                  Field(&AudioBuffersState::pending_bytes,
    535                                        2 * bytes_100_ms)))
    536       .WillOnce(Invoke(ClearData));
    537   EXPECT_CALL(source, OnMoreData(NotNull(),
    538                                  Field(&AudioBuffersState::pending_bytes,
    539                                        2 * bytes_100_ms)))
    540       .Times(AnyNumber())
    541       .WillRepeatedly(Return(0));
    542   EXPECT_CALL(source, OnMoreData(NotNull(),
    543                                  Field(&AudioBuffersState::pending_bytes,
    544                                        bytes_100_ms)))
    545       .Times(AnyNumber())
    546       .WillRepeatedly(Return(0));
    547   EXPECT_CALL(source, OnMoreData(NotNull(),
    548                                  Field(&AudioBuffersState::pending_bytes, 0)))
    549       .Times(AnyNumber())
    550       .WillRepeatedly(Return(0));
    551 
    552   oas->Start(&source);
    553   ::Sleep(500);
    554   oas->Stop();
    555   oas->Close();
    556 }
    557 
    558 // Simple source that uses a SyncSocket to retrieve the audio data
    559 // from a potentially remote thread.
    560 class SyncSocketSource : public AudioOutputStream::AudioSourceCallback {
    561  public:
    562   SyncSocketSource(base::SyncSocket* socket, const AudioParameters& params)
    563       : socket_(socket) {
    564     // Setup AudioBus wrapping data we'll receive over the sync socket.
    565     data_size_ = AudioBus::CalculateMemorySize(params);
    566     data_.reset(static_cast<float*>(
    567         base::AlignedAlloc(data_size_, AudioBus::kChannelAlignment)));
    568     audio_bus_ = AudioBus::WrapMemory(params, data_.get());
    569   }
    570   ~SyncSocketSource() {}
    571 
    572   // AudioSourceCallback::OnMoreData implementation:
    573   virtual int OnMoreData(AudioBus* audio_bus,
    574                          AudioBuffersState buffers_state) {
    575     socket_->Send(&buffers_state, sizeof(buffers_state));
    576     uint32 size = socket_->Receive(data_.get(), data_size_);
    577     DCHECK_EQ(static_cast<size_t>(size) % sizeof(*audio_bus_->channel(0)), 0U);
    578     audio_bus_->CopyTo(audio_bus);
    579     return audio_bus_->frames();
    580   }
    581   virtual int OnMoreIOData(AudioBus* source,
    582                            AudioBus* dest,
    583                            AudioBuffersState buffers_state) {
    584     NOTREACHED();
    585     return 0;
    586   }
    587   // AudioSourceCallback::OnError implementation:
    588   virtual void OnError(AudioOutputStream* stream) {
    589   }
    590 
    591  private:
    592   base::SyncSocket* socket_;
    593   int data_size_;
    594   scoped_ptr<float, base::AlignedFreeDeleter> data_;
    595   scoped_ptr<AudioBus> audio_bus_;
    596 };
    597 
    598 struct SyncThreadContext {
    599   base::SyncSocket* socket;
    600   int sample_rate;
    601   int channels;
    602   int frames;
    603   double sine_freq;
    604   uint32 packet_size_bytes;
    605 };
    606 
    607 // This thread provides the data that the SyncSocketSource above needs
    608 // using the other end of a SyncSocket. The protocol is as follows:
    609 //
    610 // SyncSocketSource ---send 4 bytes ------------> SyncSocketThread
    611 //                  <--- audio packet ----------
    612 //
    613 DWORD __stdcall SyncSocketThread(void* context) {
    614   SyncThreadContext& ctx = *(reinterpret_cast<SyncThreadContext*>(context));
    615 
    616   // Setup AudioBus wrapping data we'll pass over the sync socket.
    617   scoped_ptr<float, base::AlignedFreeDeleter> data(static_cast<float*>(
    618       base::AlignedAlloc(ctx.packet_size_bytes, AudioBus::kChannelAlignment)));
    619   scoped_ptr<AudioBus> audio_bus = AudioBus::WrapMemory(
    620       ctx.channels, ctx.frames, data.get());
    621 
    622   SineWaveAudioSource sine(1, ctx.sine_freq, ctx.sample_rate);
    623   const int kTwoSecFrames = ctx.sample_rate * 2;
    624 
    625   AudioBuffersState buffers_state;
    626   int times = 0;
    627   for (int ix = 0; ix < kTwoSecFrames; ix += ctx.frames) {
    628     if (ctx.socket->Receive(&buffers_state, sizeof(buffers_state)) == 0)
    629       break;
    630     if ((times > 0) && (buffers_state.pending_bytes < 1000)) __debugbreak();
    631     sine.OnMoreData(audio_bus.get(), buffers_state);
    632     ctx.socket->Send(data.get(), ctx.packet_size_bytes);
    633     ++times;
    634   }
    635 
    636   return 0;
    637 }
    638 
    639 // Test the basic operation of AudioOutputStream used with a SyncSocket.
    640 // The emphasis is to verify that it is possible to feed data to the audio
    641 // layer using a source based on SyncSocket. In a real situation we would
    642 // go for the low-latency version in combination with SyncSocket, but to keep
    643 // the test more simple, AUDIO_PCM_LINEAR is utilized instead. The main
    644 // principle of the test still remains and we avoid the additional complexity
    645 // related to the two different audio-layers for AUDIO_PCM_LOW_LATENCY.
    646 // In this test you should hear a continuous 200Hz tone for 2 seconds.
    647 TEST(WinAudioTest, SyncSocketBasic) {
    648   scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
    649   if (!audio_man->HasAudioOutputDevices()) {
    650     LOG(WARNING) << "No output device detected.";
    651     return;
    652   }
    653 
    654   static const int sample_rate = AudioParameters::kAudioCDSampleRate;
    655   static const uint32 kSamples20ms = sample_rate / 50;
    656   AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
    657                          CHANNEL_LAYOUT_MONO, sample_rate, 16, kSamples20ms);
    658 
    659 
    660   AudioOutputStream* oas = audio_man->MakeAudioOutputStream(params,
    661       std::string());
    662   ASSERT_TRUE(NULL != oas);
    663 
    664   ASSERT_TRUE(oas->Open());
    665 
    666   base::SyncSocket sockets[2];
    667   ASSERT_TRUE(base::SyncSocket::CreatePair(&sockets[0], &sockets[1]));
    668 
    669   SyncSocketSource source(&sockets[0], params);
    670 
    671   SyncThreadContext thread_context;
    672   thread_context.sample_rate = params.sample_rate();
    673   thread_context.sine_freq = 200.0;
    674   thread_context.packet_size_bytes = AudioBus::CalculateMemorySize(params);
    675   thread_context.frames = params.frames_per_buffer();
    676   thread_context.channels = params.channels();
    677   thread_context.socket = &sockets[1];
    678 
    679   HANDLE thread = ::CreateThread(NULL, 0, SyncSocketThread,
    680                                  &thread_context, 0, NULL);
    681 
    682   oas->Start(&source);
    683 
    684   ::WaitForSingleObject(thread, INFINITE);
    685   ::CloseHandle(thread);
    686 
    687   oas->Stop();
    688   oas->Close();
    689 }
    690 
    691 }  // namespace media
    692