1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <unistd.h> 6 7#include <string> 8 9#include "base/synchronization/waitable_event.h" 10#include "base/test/test_timeouts.h" 11#include "base/time/time.h" 12#include "media/audio/cras/audio_manager_cras.h" 13#include "media/audio/cras/cras_input.h" 14#include "testing/gmock/include/gmock/gmock.h" 15#include "testing/gtest/include/gtest/gtest.h" 16 17using testing::_; 18using testing::AtLeast; 19using testing::Ge; 20using testing::InvokeWithoutArgs; 21using testing::StrictMock; 22 23namespace media { 24 25class MockAudioInputCallback : public AudioInputStream::AudioInputCallback { 26 public: 27 MOCK_METHOD5(OnData, void( 28 AudioInputStream*, const uint8*, uint32, uint32, double)); 29 MOCK_METHOD1(OnError, void(AudioInputStream*)); 30 MOCK_METHOD1(OnClose, void(AudioInputStream*)); 31}; 32 33class MockAudioManagerCrasInput : public AudioManagerCras { 34 public: 35 // We need to override this function in order to skip checking the number 36 // of active output streams. It is because the number of active streams 37 // is managed inside MakeAudioInputStream, and we don't use 38 // MakeAudioInputStream to create the stream in the tests. 39 virtual void ReleaseInputStream(AudioInputStream* stream) OVERRIDE { 40 DCHECK(stream); 41 delete stream; 42 } 43}; 44 45class CrasInputStreamTest : public testing::Test { 46 protected: 47 CrasInputStreamTest() { 48 mock_manager_.reset(new StrictMock<MockAudioManagerCrasInput>()); 49 } 50 51 virtual ~CrasInputStreamTest() { 52 } 53 54 CrasInputStream* CreateStream(ChannelLayout layout) { 55 return CreateStream(layout, kTestFramesPerPacket); 56 } 57 58 CrasInputStream* CreateStream(ChannelLayout layout, 59 int32 samples_per_packet) { 60 AudioParameters params(kTestFormat, 61 layout, 62 kTestSampleRate, 63 kTestBitsPerSample, 64 samples_per_packet); 65 return new CrasInputStream(params, mock_manager_.get(), 66 AudioManagerBase::kDefaultDeviceId); 67 } 68 69 void CaptureSomeFrames(const AudioParameters ¶ms, 70 unsigned int duration_ms) { 71 CrasInputStream* test_stream = new CrasInputStream( 72 params, mock_manager_.get(), AudioManagerBase::kDefaultDeviceId); 73 74 ASSERT_TRUE(test_stream->Open()); 75 76 // Allow 8 frames variance for SRC in the callback. Different numbers of 77 // samples can be provided when doing non-integer SRC. For example 78 // converting from 192k to 44.1k is a ratio of 4.35 to 1. 79 MockAudioInputCallback mock_callback; 80 unsigned int expected_size = (kTestFramesPerPacket - 8) * 81 params.channels() * 82 params.bits_per_sample() / 8; 83 84 base::WaitableEvent event(false, false); 85 86 EXPECT_CALL(mock_callback, 87 OnData(test_stream, _, Ge(expected_size), _, _)) 88 .WillOnce(InvokeWithoutArgs(&event, &base::WaitableEvent::Signal)); 89 90 test_stream->Start(&mock_callback); 91 92 // Wait for samples to be captured. 93 EXPECT_TRUE(event.TimedWait(TestTimeouts::action_timeout())); 94 95 test_stream->Stop(); 96 97 EXPECT_CALL(mock_callback, OnClose(test_stream)).Times(1); 98 test_stream->Close(); 99 } 100 101 static const unsigned int kTestBitsPerSample; 102 static const unsigned int kTestCaptureDurationMs; 103 static const ChannelLayout kTestChannelLayout; 104 static const AudioParameters::Format kTestFormat; 105 static const uint32 kTestFramesPerPacket; 106 static const int kTestSampleRate; 107 108 scoped_ptr<StrictMock<MockAudioManagerCrasInput> > mock_manager_; 109 110 private: 111 DISALLOW_COPY_AND_ASSIGN(CrasInputStreamTest); 112}; 113 114const unsigned int CrasInputStreamTest::kTestBitsPerSample = 16; 115const unsigned int CrasInputStreamTest::kTestCaptureDurationMs = 250; 116const ChannelLayout CrasInputStreamTest::kTestChannelLayout = 117 CHANNEL_LAYOUT_STEREO; 118const AudioParameters::Format CrasInputStreamTest::kTestFormat = 119 AudioParameters::AUDIO_PCM_LINEAR; 120const uint32 CrasInputStreamTest::kTestFramesPerPacket = 1000; 121const int CrasInputStreamTest::kTestSampleRate = 44100; 122 123TEST_F(CrasInputStreamTest, OpenMono) { 124 CrasInputStream* test_stream = CreateStream(CHANNEL_LAYOUT_MONO); 125 EXPECT_TRUE(test_stream->Open()); 126 test_stream->Close(); 127} 128 129TEST_F(CrasInputStreamTest, OpenStereo) { 130 CrasInputStream* test_stream = CreateStream(CHANNEL_LAYOUT_STEREO); 131 EXPECT_TRUE(test_stream->Open()); 132 test_stream->Close(); 133} 134 135TEST_F(CrasInputStreamTest, BadBitsPerSample) { 136 AudioParameters bad_bps_params(kTestFormat, 137 kTestChannelLayout, 138 kTestSampleRate, 139 kTestBitsPerSample - 1, 140 kTestFramesPerPacket); 141 CrasInputStream* test_stream = new CrasInputStream( 142 bad_bps_params, mock_manager_.get(), AudioManagerBase::kDefaultDeviceId); 143 EXPECT_FALSE(test_stream->Open()); 144 test_stream->Close(); 145} 146 147TEST_F(CrasInputStreamTest, BadFormat) { 148 AudioParameters bad_format_params(AudioParameters::AUDIO_LAST_FORMAT, 149 kTestChannelLayout, 150 kTestSampleRate, 151 kTestBitsPerSample, 152 kTestFramesPerPacket); 153 CrasInputStream* test_stream = new CrasInputStream( 154 bad_format_params, mock_manager_.get(), 155 AudioManagerBase::kDefaultDeviceId); 156 EXPECT_FALSE(test_stream->Open()); 157 test_stream->Close(); 158} 159 160TEST_F(CrasInputStreamTest, BadSampleRate) { 161 AudioParameters bad_rate_params(kTestFormat, 162 kTestChannelLayout, 163 0, 164 kTestBitsPerSample, 165 kTestFramesPerPacket); 166 CrasInputStream* test_stream = new CrasInputStream( 167 bad_rate_params, mock_manager_.get(), AudioManagerBase::kDefaultDeviceId); 168 EXPECT_FALSE(test_stream->Open()); 169 test_stream->Close(); 170} 171 172TEST_F(CrasInputStreamTest, SetGetVolume) { 173 CrasInputStream* test_stream = CreateStream(CHANNEL_LAYOUT_MONO); 174 EXPECT_TRUE(test_stream->Open()); 175 176 double max_volume = test_stream->GetMaxVolume(); 177 EXPECT_GE(max_volume, 1.0); 178 179 test_stream->SetVolume(max_volume / 2); 180 181 double new_volume = test_stream->GetVolume(); 182 183 EXPECT_GE(new_volume, 0.0); 184 EXPECT_LE(new_volume, max_volume); 185 186 test_stream->Close(); 187} 188 189TEST_F(CrasInputStreamTest, CaptureFrames) { 190 const unsigned int rates[] = 191 {8000, 16000, 22050, 32000, 44100, 48000, 96000, 192000}; 192 193 for (unsigned int i = 0; i < ARRAY_SIZE(rates); i++) { 194 SCOPED_TRACE(testing::Message() << "Mono " << rates[i] << "Hz"); 195 AudioParameters params_mono(kTestFormat, 196 CHANNEL_LAYOUT_MONO, 197 rates[i], 198 kTestBitsPerSample, 199 kTestFramesPerPacket); 200 CaptureSomeFrames(params_mono, kTestCaptureDurationMs); 201 } 202 203 for (unsigned int i = 0; i < ARRAY_SIZE(rates); i++) { 204 SCOPED_TRACE(testing::Message() << "Stereo " << rates[i] << "Hz"); 205 AudioParameters params_stereo(kTestFormat, 206 CHANNEL_LAYOUT_STEREO, 207 rates[i], 208 kTestBitsPerSample, 209 kTestFramesPerPacket); 210 CaptureSomeFrames(params_stereo, kTestCaptureDurationMs); 211 } 212} 213 214} // namespace media 215