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 "base/basictypes.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/environment.h"
7ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
80529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/run_loop.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/test/test_timeouts.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/platform_thread.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_io.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_manager_base.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/mac/audio_low_latency_input_mac.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/seekable_buffer.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::_;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::AnyNumber;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::AtLeast;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::Ge;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::NotNull;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
260529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochACTION_P4(CheckCountAndPostQuitTask, count, limit, loop, closure) {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (++*count >= limit) {
280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    loop->PostTask(FROM_HERE, closure);
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockAudioInputCallback : public AudioInputStream::AudioInputCallback {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
346d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  MOCK_METHOD4(OnData,
356d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)               void(AudioInputStream* stream,
366d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                    const AudioBus* src,
376d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                    uint32 hardware_delay_bytes,
386d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                    double volume));
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MOCK_METHOD1(OnError, void(AudioInputStream* stream));
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This audio sink implementation should be used for manual tests only since
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the recorded data is stored on a raw binary data file.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The last test (WriteToFileAudioSink) - which is disabled by default -
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// can use this audio sink to store the captured data on a file for offline
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// analysis.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class WriteToFileAudioSink : public AudioInputStream::AudioInputCallback {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allocate space for ~10 seconds of data @ 48kHz in stereo:
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 2 bytes per sample, 2 channels, 10ms @ 48kHz, 10 seconds <=> 1920000 bytes.
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kMaxBufferSize = 2 * 2 * 480 * 100 * 10;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit WriteToFileAudioSink(const char* file_name)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : buffer_(0, kMaxBufferSize),
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        file_(fopen(file_name, "wb")),
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bytes_to_write_(0) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~WriteToFileAudioSink() {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int bytes_written = 0;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (bytes_written < bytes_to_write_) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const uint8* chunk;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int chunk_size;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Stop writing if no more data is available.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!buffer_.GetCurrentChunk(&chunk, &chunk_size))
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Write recorded data chunk to the file and prepare for next chunk.
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fwrite(chunk, 1, chunk_size, file_);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      buffer_.Seek(chunk_size);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bytes_written += chunk_size;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fclose(file_);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // AudioInputStream::AudioInputCallback implementation.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnData(AudioInputStream* stream,
796d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                      const AudioBus* src,
806d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                      uint32 hardware_delay_bytes,
816d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                      double volume) OVERRIDE {
826d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    const int num_samples = src->frames() * src->channels();
836d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    scoped_ptr<int16> interleaved(new int16[num_samples]);
846d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    const int bytes_per_sample = sizeof(*interleaved);
856d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    src->ToInterleaved(src->frames(), bytes_per_sample, interleaved.get());
866d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Store data data in a temporary buffer to avoid making blocking
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // fwrite() calls in the audio callback. The complete buffer will be
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // written to file in the destructor.
906d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    const int size = bytes_per_sample * num_samples;
916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (buffer_.Append((const uint8*)interleaved.get(), size)) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bytes_to_write_ += size;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnError(AudioInputStream* stream) OVERRIDE {}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::SeekableBuffer buffer_;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FILE* file_;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int bytes_to_write_;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MacAudioInputTest : public testing::Test {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
1060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  MacAudioInputTest()
1070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      : message_loop_(base::MessageLoop::TYPE_UI),
1080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        audio_manager_(AudioManager::CreateForTesting()) {
1090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    // Wait for the AudioManager to finish any initialization on the audio loop.
1100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    base::RunLoop().RunUntilIdle();
1110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
1120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  virtual ~MacAudioInputTest() {
1140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    base::RunLoop().RunUntilIdle();
1150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Convenience method which ensures that we are not running on the build
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bots and that at least one valid input device can be found.
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool CanRunAudioTests() {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool has_input = audio_manager_->HasAudioInputDevices();
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!has_input)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "No input devices detected";
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return has_input;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Convenience method which creates a default AudioInputStream object using
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a 10ms frame size and a sample rate which is set to the hardware sample
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // rate.
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioInputStream* CreateDefaultAudioInputStream() {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int fs = static_cast<int>(AUAudioInputStream::HardwareSampleRate());
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int samples_per_packet = fs / 100;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AudioInputStream* ais = audio_manager_->MakeAudioInputStream(
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CHANNEL_LAYOUT_STEREO, fs, 16, samples_per_packet),
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AudioManagerBase::kDefaultDeviceId);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(ais);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ais;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Convenience method which creates an AudioInputStream object with a
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // specified channel layout.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioInputStream* CreateAudioInputStream(ChannelLayout channel_layout) {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int fs = static_cast<int>(AUAudioInputStream::HardwareSampleRate());
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int samples_per_packet = fs / 100;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AudioInputStream* ais = audio_manager_->MakeAudioInputStream(
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        channel_layout, fs, 16, samples_per_packet),
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AudioManagerBase::kDefaultDeviceId);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(ais);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ais;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  base::MessageLoop message_loop_;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioManager> audio_manager_;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test Create(), Close().
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(MacAudioInputTest, AUAudioInputStreamCreateAndClose) {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanRunAudioTests())
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioInputStream* ais = CreateDefaultAudioInputStream();
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Close();
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test Open(), Close().
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(MacAudioInputTest, AUAudioInputStreamOpenAndClose) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanRunAudioTests())
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioInputStream* ais = CreateDefaultAudioInputStream();
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ais->Open());
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Close();
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test Open(), Start(), Close().
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(MacAudioInputTest, AUAudioInputStreamOpenStartAndClose) {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanRunAudioTests())
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioInputStream* ais = CreateDefaultAudioInputStream();
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ais->Open());
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockAudioInputCallback sink;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Start(&sink);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Close();
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test Open(), Start(), Stop(), Close().
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(MacAudioInputTest, AUAudioInputStreamOpenStartStopAndClose) {
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanRunAudioTests())
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioInputStream* ais = CreateDefaultAudioInputStream();
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ais->Open());
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockAudioInputCallback sink;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Start(&sink);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Stop();
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Close();
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test some additional calling sequences.
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(MacAudioInputTest, AUAudioInputStreamMiscCallingSequences) {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanRunAudioTests())
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioInputStream* ais = CreateDefaultAudioInputStream();
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AUAudioInputStream* auais = static_cast<AUAudioInputStream*>(ais);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Open(), Open() should fail the second time.
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ais->Open());
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(ais->Open());
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockAudioInputCallback sink;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start(), Start() is a valid calling sequence (second call does nothing).
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Start(&sink);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(auais->started());
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Start(&sink);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(auais->started());
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Stop(), Stop() is a valid calling sequence (second call does nothing).
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Stop();
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(auais->started());
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Stop();
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(auais->started());
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Close();
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify that recording starts and stops correctly in mono using mocked sink.
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(MacAudioInputTest, AUAudioInputStreamVerifyMonoRecording) {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanRunAudioTests())
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int count = 0;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create an audio input stream which records in mono.
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioInputStream* ais = CreateAudioInputStream(CHANNEL_LAYOUT_MONO);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ais->Open());
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockAudioInputCallback sink;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We use 10ms packets and will run the test until ten packets are received.
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // All should contain valid packets of the same size and a valid delay
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // estimate.
2410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  base::RunLoop run_loop;
2426d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  EXPECT_CALL(sink, OnData(ais, NotNull(), _, _))
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Times(AtLeast(10))
2440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      .WillRepeatedly(CheckCountAndPostQuitTask(
2450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          &count, 10, &message_loop_, run_loop.QuitClosure()));
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Start(&sink);
2470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  run_loop.Run();
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Stop();
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Close();
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify that recording starts and stops correctly in mono using mocked sink.
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(MacAudioInputTest, AUAudioInputStreamVerifyStereoRecording) {
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanRunAudioTests())
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int count = 0;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create an audio input stream which records in stereo.
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioInputStream* ais = CreateAudioInputStream(CHANNEL_LAYOUT_STEREO);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ais->Open());
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockAudioInputCallback sink;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We use 10ms packets and will run the test until ten packets are received.
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // All should contain valid packets of the same size and a valid delay
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // estimate.
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(henrika): http://crbug.com/154352 forced us to run the capture side
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // using a native buffer size of 128 audio frames and combine it with a FIFO
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to match the requested size by the client. This change might also have
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // modified the delay estimates since the existing Ge(bytes_per_packet) for
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // parameter #4 does no longer pass. I am removing this restriction here to
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ensure that we can land the patch but will revisit this test again when
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // more analysis of the delay estimates are done.
2750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  base::RunLoop run_loop;
2766d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  EXPECT_CALL(sink, OnData(ais, NotNull(), _, _))
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Times(AtLeast(10))
2780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      .WillRepeatedly(CheckCountAndPostQuitTask(
2790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          &count, 10, &message_loop_, run_loop.QuitClosure()));
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Start(&sink);
2810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  run_loop.Run();
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Stop();
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Close();
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This test is intended for manual tests and should only be enabled
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// when it is required to store the captured data on a local file.
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// By default, GTest will print out YOU HAVE 1 DISABLED TEST.
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// To include disabled tests in test execution, just invoke the test program
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// with --gtest_also_run_disabled_tests or set the GTEST_ALSO_RUN_DISABLED_TESTS
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// environment variable to a value greater than 0.
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(MacAudioInputTest, DISABLED_AUAudioInputStreamRecordToFile) {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanRunAudioTests())
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* file_name = "out_stereo_10sec.pcm";
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int fs = static_cast<int>(AUAudioInputStream::HardwareSampleRate());
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioInputStream* ais = CreateDefaultAudioInputStream();
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ais->Open());
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fprintf(stderr, "               File name  : %s\n", file_name);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fprintf(stderr, "               Sample rate: %d\n", fs);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WriteToFileAudioSink file_sink(file_name);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fprintf(stderr, "               >> Speak into the mic while recording...\n");
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Start(&file_sink);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::PlatformThread::Sleep(TestTimeouts::action_timeout());
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Stop();
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fprintf(stderr, "               >> Recording has stopped.\n");
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ais->Close();
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
313