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