15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <mmsystem.h>
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/environment.h"
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
12ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/test/test_timeouts.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_com_initializer.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_io.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_manager_base.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/win/audio_low_latency_input_win.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/audio/win/core_audio_util_win.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/seekable_buffer.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::win::ScopedCOMInitializer;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::_;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::AnyNumber;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::AtLeast;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::Gt;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::NotNull;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ACTION_P3(CheckCountAndPostQuitTask, count, limit, loop) {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (++*count >= limit) {
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockAudioInputCallback : public AudioInputStream::AudioInputCallback {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
416d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  MOCK_METHOD4(OnData,
426d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)               void(AudioInputStream* stream,
436d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                    const AudioBus* src,
446d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                    uint32 hardware_delay_bytes,
456d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                    double volume));
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MOCK_METHOD1(OnError, void(AudioInputStream* stream));
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
49d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)class FakeAudioInputCallback : public AudioInputStream::AudioInputCallback {
50d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) public:
51d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  FakeAudioInputCallback()
526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      : error_(false),
536d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        data_event_(false, false),
546d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        num_received_audio_frames_(0) {}
55d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
56d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  bool error() const { return error_; }
576d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  int num_received_audio_frames() const { return num_received_audio_frames_; }
58d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
59d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Waits until OnData() is called on another thread.
60d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  void WaitForData() {
61d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    data_event_.Wait();
62d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
63d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
64d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  virtual void OnData(AudioInputStream* stream,
656d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                      const AudioBus* src,
666d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                      uint32 hardware_delay_bytes,
676d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                      double volume) OVERRIDE {
686d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    EXPECT_NE(hardware_delay_bytes, 0u);
696d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    num_received_audio_frames_ += src->frames();
70d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    data_event_.Signal();
71d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
72d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
73d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  virtual void OnError(AudioInputStream* stream) OVERRIDE {
74d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    error_ = true;
75d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
76d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
77d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) private:
786d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  int num_received_audio_frames_;
79d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  base::WaitableEvent data_event_;
80d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  bool error_;
81d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
82d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(FakeAudioInputCallback);
83d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)};
84d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This audio sink implementation should be used for manual tests only since
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the recorded data is stored on a raw binary data file.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class WriteToFileAudioSink : public AudioInputStream::AudioInputCallback {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allocate space for ~10 seconds of data @ 48kHz in stereo:
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 2 bytes per sample, 2 channels, 10ms @ 48kHz, 10 seconds <=> 1920000 bytes.
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const size_t kMaxBufferSize = 2 * 2 * 480 * 100 * 10;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
936d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  explicit WriteToFileAudioSink(const char* file_name, int bits_per_sample)
946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      : bits_per_sample_(bits_per_sample),
956d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        buffer_(0, kMaxBufferSize),
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bytes_to_write_(0) {
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath file_path;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(PathService::Get(base::DIR_EXE, &file_path));
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_path = file_path.AppendASCII(file_name);
100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    binary_file_ = base::OpenFile(file_path, "wb");
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG_IF(ERROR, !binary_file_) << "Failed to open binary PCM data file.";
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    VLOG(0) << ">> Output file: " << file_path.value() << " has been created.";
1036d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    VLOG(0) << "bits_per_sample_:" << bits_per_sample_;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~WriteToFileAudioSink() {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t bytes_written = 0;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (bytes_written < bytes_to_write_) {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const uint8* chunk;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int chunk_size;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Stop writing if no more data is available.
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!buffer_.GetCurrentChunk(&chunk, &chunk_size))
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Write recorded data chunk to the file and prepare for next chunk.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fwrite(chunk, 1, chunk_size, binary_file_);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      buffer_.Seek(chunk_size);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bytes_written += chunk_size;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::CloseFile(binary_file_);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // AudioInputStream::AudioInputCallback implementation.
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnData(AudioInputStream* stream,
1266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                      const AudioBus* src,
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      uint32 hardware_delay_bytes,
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      double volume) {
1296d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    EXPECT_EQ(bits_per_sample_, 16);
1306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    const int num_samples = src->frames() * src->channels();
1316d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    scoped_ptr<int16> interleaved(new int16[num_samples]);
1326d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    const int bytes_per_sample = sizeof(*interleaved);
1336d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    src->ToInterleaved(src->frames(), bytes_per_sample, interleaved.get());
1346d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Store data data in a temporary buffer to avoid making blocking
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // fwrite() calls in the audio callback. The complete buffer will be
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // written to file in the destructor.
1386d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    const int size = bytes_per_sample * num_samples;
1396d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (buffer_.Append((const uint8*)interleaved.get(), size)) {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bytes_to_write_ += size;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnError(AudioInputStream* stream) {}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1476d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  int bits_per_sample_;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::SeekableBuffer buffer_;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FILE* binary_file_;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t bytes_to_write_;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Convenience method which ensures that we are not running on the build
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// bots and that at least one valid input device can be found. We also
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// verify that we are not running on XP since the low-latency (WASAPI-
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// based) version requires Windows Vista or higher.
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool CanRunAudioTests(AudioManager* audio_man) {
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!CoreAudioUtil::IsSupported()) {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "This tests requires Windows Vista or higher.";
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(henrika): note that we use Wave today to query the number of
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // existing input devices.
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool input = audio_man->HasAudioInputDevices();
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG_IF(WARNING, !input) << "No input device detected.";
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return input;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Convenience method which creates a default AudioInputStream object but
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// also allows the user to modify the default settings.
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AudioInputStreamWrapper {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit AudioInputStreamWrapper(AudioManager* audio_manager)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : com_init_(ScopedCOMInitializer::kMTA),
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        audio_man_(audio_manager),
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        default_params_(
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            audio_manager->GetInputStreamParameters(
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                  AudioManagerBase::kDefaultDeviceId)) {
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(format(), AudioParameters::AUDIO_PCM_LOW_LATENCY);
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    frames_per_buffer_ = default_params_.frames_per_buffer();
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // We expect the default buffer size to be a 10ms buffer.
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(frames_per_buffer_, sample_rate() / 100);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~AudioInputStreamWrapper() {}
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Creates AudioInputStream object using default parameters.
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioInputStream* Create() {
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return CreateInputStream();
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Creates AudioInputStream object using non-default parameters where the
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // frame size is modified.
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AudioInputStream* Create(int frames_per_buffer) {
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    frames_per_buffer_ = frames_per_buffer;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return CreateInputStream();
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AudioParameters::Format format() const { return default_params_.format(); }
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int channels() const {
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return ChannelLayoutToChannelCount(default_params_.channel_layout());
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int bits_per_sample() const { return default_params_.bits_per_sample(); }
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int sample_rate() const { return default_params_.sample_rate(); }
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int frames_per_buffer() const { return frames_per_buffer_; }
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioInputStream* CreateInputStream() {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AudioInputStream* ais = audio_man_->MakeAudioInputStream(
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        AudioParameters(format(), default_params_.channel_layout(),
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        sample_rate(), bits_per_sample(), frames_per_buffer_,
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        default_params_.effects()),
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        AudioManagerBase::kDefaultDeviceId);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(ais);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ais;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedCOMInitializer com_init_;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioManager* audio_man_;
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const AudioParameters default_params_;
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int frames_per_buffer_;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Convenience method which creates a default AudioInputStream object.
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static AudioInputStream* CreateDefaultAudioInputStream(
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AudioManager* audio_manager) {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioInputStreamWrapper aisw(audio_manager);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioInputStream* ais = aisw.Create();
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ais;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
232d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)class ScopedAudioInputStream {
233d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) public:
234d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  explicit ScopedAudioInputStream(AudioInputStream* stream)
235d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      : stream_(stream) {}
236d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
237d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ~ScopedAudioInputStream() {
238d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (stream_)
239d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      stream_->Close();
240d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
241d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
242d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  void Close() {
243d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (stream_)
244d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      stream_->Close();
245d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    stream_ = NULL;
246d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
247d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
248d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  AudioInputStream* operator->() {
249d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return stream_;
250d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
251d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
252d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  AudioInputStream* get() const { return stream_; }
253d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
254d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  void Reset(AudioInputStream* new_stream) {
255d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    Close();
256d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    stream_ = new_stream;
257d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
258d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
259d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) private:
260d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  AudioInputStream* stream_;
261d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
262d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ScopedAudioInputStream);
263d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)};
264d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify that we can retrieve the current hardware/mixing sample rate
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for all available input devices.
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioInputTest, WASAPIAudioInputStreamHardwareSampleRate) {
268a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanRunAudioTests(audio_manager.get()))
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedCOMInitializer com_init(ScopedCOMInitializer::kMTA);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Retrieve a list of all available input devices.
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::AudioDeviceNames device_names;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_manager->GetAudioInputDeviceNames(&device_names);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Scan all available input devices and repeat the same test for all of them.
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (media::AudioDeviceNames::const_iterator it = device_names.begin();
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != device_names.end(); ++it) {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Retrieve the hardware sample rate given a specified audio input device.
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AudioParameters params = WASAPIAudioInputStream::GetInputStreamParameters(
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        it->unique_id);
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_GE(params.sample_rate(), 0);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test Create(), Close() calling sequence.
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioInputTest, WASAPIAudioInputStreamCreateAndClose) {
290a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanRunAudioTests(audio_manager.get()))
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
293d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ScopedAudioInputStream ais(
294d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      CreateDefaultAudioInputStream(audio_manager.get()));
295d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ais.Close();
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test Open(), Close() calling sequence.
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioInputTest, WASAPIAudioInputStreamOpenAndClose) {
300a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanRunAudioTests(audio_manager.get()))
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
303d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ScopedAudioInputStream ais(
304d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      CreateDefaultAudioInputStream(audio_manager.get()));
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ais->Open());
306d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ais.Close();
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test Open(), Start(), Close() calling sequence.
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioInputTest, WASAPIAudioInputStreamOpenStartAndClose) {
311a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanRunAudioTests(audio_manager.get()))
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
314d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ScopedAudioInputStream ais(
315d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      CreateDefaultAudioInputStream(audio_manager.get()));
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ais->Open());
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockAudioInputCallback sink;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Start(&sink);
319d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ais.Close();
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test Open(), Start(), Stop(), Close() calling sequence.
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioInputTest, WASAPIAudioInputStreamOpenStartStopAndClose) {
324a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanRunAudioTests(audio_manager.get()))
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
327d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ScopedAudioInputStream ais(
328d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      CreateDefaultAudioInputStream(audio_manager.get()));
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ais->Open());
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockAudioInputCallback sink;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Start(&sink);
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Stop();
333d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ais.Close();
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test some additional calling sequences.
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioInputTest, WASAPIAudioInputStreamMiscCallingSequences) {
338a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanRunAudioTests(audio_manager.get()))
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
341d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ScopedAudioInputStream ais(
342d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      CreateDefaultAudioInputStream(audio_manager.get()));
343d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  WASAPIAudioInputStream* wais =
344d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      static_cast<WASAPIAudioInputStream*>(ais.get());
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Open(), Open() should fail the second time.
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ais->Open());
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(ais->Open());
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockAudioInputCallback sink;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start(), Start() is a valid calling sequence (second call does nothing).
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Start(&sink);
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(wais->started());
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Start(&sink);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(wais->started());
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Stop(), Stop() is a valid calling sequence (second call does nothing).
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Stop();
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(wais->started());
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Stop();
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(wais->started());
363d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ais.Close();
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioInputTest, WASAPIAudioInputStreamTestPacketSizes) {
367a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanRunAudioTests(audio_manager.get()))
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int count = 0;
372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoopForUI loop;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 10 ms packet size.
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create default WASAPI input stream which records in stereo using
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the shared mixing rate. The default buffer size is 10ms.
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioInputStreamWrapper aisw(audio_manager.get());
379d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ScopedAudioInputStream ais(aisw.Create());
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ais->Open());
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockAudioInputCallback sink;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Derive the expected size in bytes of each recorded packet.
3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  uint32 bytes_per_packet = aisw.channels() * aisw.frames_per_buffer() *
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (aisw.bits_per_sample() / 8);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We use 10ms packets and will run the test until ten packets are received.
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // All should contain valid packets of the same size and a valid delay
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // estimate.
3916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  EXPECT_CALL(sink, OnData(ais.get(), NotNull(), Gt(bytes_per_packet), _))
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Times(AtLeast(10))
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &loop));
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Start(&sink);
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop.Run();
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Stop();
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Store current packet size (to be used in the subsequent tests).
3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int frames_per_buffer_10ms = aisw.frames_per_buffer();
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
401d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ais.Close();
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 20 ms packet size.
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  count = 0;
4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ais.Reset(aisw.Create(2 * frames_per_buffer_10ms));
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ais->Open());
4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bytes_per_packet = aisw.channels() * aisw.frames_per_buffer() *
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (aisw.bits_per_sample() / 8);
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4116d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  EXPECT_CALL(sink, OnData(ais.get(), NotNull(), Gt(bytes_per_packet), _))
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Times(AtLeast(10))
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &loop));
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Start(&sink);
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop.Run();
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Stop();
417d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ais.Close();
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 5 ms packet size.
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  count = 0;
4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ais.Reset(aisw.Create(frames_per_buffer_10ms / 2));
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ais->Open());
4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bytes_per_packet = aisw.channels() * aisw.frames_per_buffer() *
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (aisw.bits_per_sample() / 8);
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  EXPECT_CALL(sink, OnData(ais.get(), NotNull(), Gt(bytes_per_packet), _))
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Times(AtLeast(10))
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &loop));
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Start(&sink);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop.Run();
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Stop();
433d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ais.Close();
434d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
435d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
4366d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)// Test that we can capture a stream in loopback.
437d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)TEST(WinAudioInputTest, WASAPIAudioInputStreamLoopback) {
438a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
439d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (!audio_manager->HasAudioOutputDevices() || !CoreAudioUtil::IsSupported())
440d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return;
441d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
442d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  AudioParameters params = audio_manager->GetInputStreamParameters(
443d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      AudioManagerBase::kLoopbackInputDeviceId);
4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(params.effects(), 0);
445d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
446d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  AudioParameters output_params =
447d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      audio_manager->GetOutputStreamParameters(std::string());
448d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(params.sample_rate(), output_params.sample_rate());
449d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(params.channel_layout(), output_params.channel_layout());
450d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
451d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ScopedAudioInputStream stream(audio_manager->MakeAudioInputStream(
452d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      params, AudioManagerBase::kLoopbackInputDeviceId));
453d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_TRUE(stream->Open());
454d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  FakeAudioInputCallback sink;
455d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  stream->Start(&sink);
456d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_FALSE(sink.error());
457d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
458d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  sink.WaitForData();
459d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  stream.Close();
460d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
4616d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  EXPECT_GT(sink.num_received_audio_frames(), 0);
462d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_FALSE(sink.error());
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This test is intended for manual tests and should only be enabled
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// when it is required to store the captured data on a local file.
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// By default, GTest will print out YOU HAVE 1 DISABLED TEST.
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// To include disabled tests in test execution, just invoke the test program
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// with --gtest_also_run_disabled_tests or set the GTEST_ALSO_RUN_DISABLED_TESTS
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// environment variable to a value greater than 0.
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioInputTest, DISABLED_WASAPIAudioInputStreamRecordToFile) {
472a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanRunAudioTests(audio_manager.get()))
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Name of the output PCM file containing captured data. The output file
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // will be stored in the directory containing 'media_unittests.exe'.
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Example of full name: \src\build\Debug\out_stereo_10sec.pcm.
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* file_name = "out_stereo_10sec.pcm";
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioInputStreamWrapper aisw(audio_manager.get());
482d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ScopedAudioInputStream ais(aisw.Create());
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ais->Open());
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  VLOG(0) << ">> Sample rate: " << aisw.sample_rate() << " [Hz]";
4866d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  WriteToFileAudioSink file_sink(file_name, aisw.bits_per_sample());
487f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  VLOG(0) << ">> Speak into the default microphone while recording.";
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Start(&file_sink);
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::PlatformThread::Sleep(TestTimeouts::action_timeout());
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Stop();
491f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  VLOG(0) << ">> Recording has stopped.";
492d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ais.Close();
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
496