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