audio_low_latency_input_mac_unittest.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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)); 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MOCK_METHOD1(OnError, void(AudioInputStream* stream)); 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, 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32 hardware_delay_bytes, double volume) OVERRIDE { 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) 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnClose(AudioInputStream* stream) OVERRIDE {} 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnError(AudioInputStream* stream) OVERRIDE {} 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