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