Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(458)

Side by Side Diff: media/audio/linux/alsa_output_unittest.cc

Issue 275022: Move Alsa device opening into the audio thread, and add in support for multi-channel audio. (Closed)
Patch Set: Fix up the unittests since we not only downmix for a very small set of channels. Created 11 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/audio/linux/alsa_output.cc ('k') | media/audio/linux/alsa_wrapper.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/logging.h" 5 #include "base/logging.h"
6 #include "base/string_util.h"
6 #include "media/audio/linux/alsa_output.h" 7 #include "media/audio/linux/alsa_output.h"
7 #include "media/audio/linux/alsa_wrapper.h" 8 #include "media/audio/linux/alsa_wrapper.h"
8 #include "media/audio/linux/audio_manager_linux.h" 9 #include "media/audio/linux/audio_manager_linux.h"
9 #include "testing/gmock/include/gmock/gmock.h" 10 #include "testing/gmock/include/gmock/gmock.h"
10 #include "testing/gtest/include/gtest/gtest.h" 11 #include "testing/gtest/include/gtest/gtest.h"
11 12
12 using testing::_; 13 using testing::_;
13 using testing::DoAll; 14 using testing::DoAll;
14 using testing::Eq; 15 using testing::Eq;
16 using testing::InSequence;
17 using testing::Invoke;
18 using testing::Mock;
19 using testing::MockFunction;
15 using testing::Return; 20 using testing::Return;
16 using testing::SetArgumentPointee; 21 using testing::SetArgumentPointee;
17 using testing::StrictMock; 22 using testing::StrictMock;
18 using testing::StrEq; 23 using testing::StrEq;
24 using testing::Unused;
19 25
20 class MockAlsaWrapper : public AlsaWrapper { 26 class MockAlsaWrapper : public AlsaWrapper {
21 public: 27 public:
28 MOCK_METHOD3(DeviceNameHint, int(int card,
29 const char* iface,
30 void*** hints));
31 MOCK_METHOD2(DeviceNameGetHint, char*(const void* hint, const char* id));
32 MOCK_METHOD1(DeviceNameFreeHint, int(void** hints));
33
22 MOCK_METHOD4(PcmOpen, int(snd_pcm_t** handle, const char* name, 34 MOCK_METHOD4(PcmOpen, int(snd_pcm_t** handle, const char* name,
23 snd_pcm_stream_t stream, int mode)); 35 snd_pcm_stream_t stream, int mode));
24 MOCK_METHOD1(PcmClose, int(snd_pcm_t* handle)); 36 MOCK_METHOD1(PcmClose, int(snd_pcm_t* handle));
25 MOCK_METHOD1(PcmPrepare, int(snd_pcm_t* handle)); 37 MOCK_METHOD1(PcmPrepare, int(snd_pcm_t* handle));
26 MOCK_METHOD1(PcmDrop, int(snd_pcm_t* handle)); 38 MOCK_METHOD1(PcmDrop, int(snd_pcm_t* handle));
27 MOCK_METHOD2(PcmDelay, int(snd_pcm_t* handle, snd_pcm_sframes_t* delay)); 39 MOCK_METHOD2(PcmDelay, int(snd_pcm_t* handle, snd_pcm_sframes_t* delay));
28 MOCK_METHOD3(PcmWritei, snd_pcm_sframes_t(snd_pcm_t* handle, 40 MOCK_METHOD3(PcmWritei, snd_pcm_sframes_t(snd_pcm_t* handle,
29 const void* buffer, 41 const void* buffer,
30 snd_pcm_uframes_t size)); 42 snd_pcm_uframes_t size));
31 MOCK_METHOD3(PcmRecover, int(snd_pcm_t* handle, int err, int silent)); 43 MOCK_METHOD3(PcmRecover, int(snd_pcm_t* handle, int err, int silent));
(...skipping 25 matching lines...) Expand all
57 MOCK_METHOD0(MuteAll, void()); 69 MOCK_METHOD0(MuteAll, void());
58 MOCK_METHOD0(UnMuteAll, void()); 70 MOCK_METHOD0(UnMuteAll, void());
59 71
60 MOCK_METHOD1(ReleaseStream, void(AlsaPcmOutputStream* stream)); 72 MOCK_METHOD1(ReleaseStream, void(AlsaPcmOutputStream* stream));
61 }; 73 };
62 74
63 class AlsaPcmOutputStreamTest : public testing::Test { 75 class AlsaPcmOutputStreamTest : public testing::Test {
64 protected: 76 protected:
65 AlsaPcmOutputStreamTest() 77 AlsaPcmOutputStreamTest()
66 : packet_(kTestPacketSize + 1) { 78 : packet_(kTestPacketSize + 1) {
67 test_stream_ = new AlsaPcmOutputStream(kTestDeviceName, 79 test_stream_ = CreateStreamWithChannels(kTestChannels);
68 kTestFormat,
69 kTestChannels,
70 kTestSampleRate,
71 kTestBitsPerSample,
72 &mock_alsa_wrapper_,
73 &mock_manager_,
74 &message_loop_);
75
76 packet_.size = kTestPacketSize; 80 packet_.size = kTestPacketSize;
77 } 81 }
78 82
79 virtual ~AlsaPcmOutputStreamTest() { 83 virtual ~AlsaPcmOutputStreamTest() {
80 test_stream_ = NULL; 84 test_stream_ = NULL;
81 } 85 }
82 86
87 AlsaPcmOutputStream* CreateStreamWithChannels(int channels) {
88 return new AlsaPcmOutputStream(kTestDeviceName,
89 kTestFormat,
90 channels,
91 kTestSampleRate,
92 kTestBitsPerSample,
93 &mock_alsa_wrapper_,
94 &mock_manager_,
95 &message_loop_);
96 }
97
98 // Helper function to malloc the string returned by DeviceNameHint for NAME.
99 static char* EchoHint(const void* name, Unused) {
100 return strdup(static_cast<const char*>(name));
101 }
102
103 // Helper function to malloc the string returned by DeviceNameHint for IOID.
104 static char* OutputHint(Unused, Unused) {
105 return strdup("Output");
106 }
107
83 static const int kTestChannels; 108 static const int kTestChannels;
84 static const int kTestSampleRate; 109 static const int kTestSampleRate;
85 static const int kTestBitsPerSample; 110 static const int kTestBitsPerSample;
86 static const int kTestBytesPerFrame; 111 static const int kTestBytesPerFrame;
87 static const AudioManager::Format kTestFormat; 112 static const AudioManager::Format kTestFormat;
88 static const char kTestDeviceName[]; 113 static const char kTestDeviceName[];
89 static const char kDummyMessage[]; 114 static const char kDummyMessage[];
90 static const int kTestFramesPerPacket; 115 static const int kTestFramesPerPacket;
91 static const size_t kTestPacketSize; 116 static const size_t kTestPacketSize;
92 static const int kTestFailedErrno; 117 static const int kTestFailedErrno;
93 static snd_pcm_t* const kFakeHandle; 118 static snd_pcm_t* const kFakeHandle;
94 119
120 // Used to simulate DeviceNameHint.
121 static char kSurround40[];
122 static char kSurround41[];
123 static char kSurround50[];
124 static char kSurround51[];
125 static char kSurround70[];
126 static char kSurround71[];
127 static void* kFakeHints[];
128
95 StrictMock<MockAlsaWrapper> mock_alsa_wrapper_; 129 StrictMock<MockAlsaWrapper> mock_alsa_wrapper_;
96 StrictMock<MockAudioManagerLinux> mock_manager_; 130 StrictMock<MockAudioManagerLinux> mock_manager_;
97 MessageLoop message_loop_; 131 MessageLoop message_loop_;
98 scoped_refptr<AlsaPcmOutputStream> test_stream_; 132 scoped_refptr<AlsaPcmOutputStream> test_stream_;
99 AlsaPcmOutputStream::Packet packet_; 133 AlsaPcmOutputStream::Packet packet_;
100 134
101 private: 135 private:
102 DISALLOW_COPY_AND_ASSIGN(AlsaPcmOutputStreamTest); 136 DISALLOW_COPY_AND_ASSIGN(AlsaPcmOutputStreamTest);
103 }; 137 };
104 138
105 const int AlsaPcmOutputStreamTest::kTestChannels = 2; 139 const int AlsaPcmOutputStreamTest::kTestChannels = 2;
106 const int AlsaPcmOutputStreamTest::kTestSampleRate = 140 const int AlsaPcmOutputStreamTest::kTestSampleRate =
107 AudioManager::kAudioCDSampleRate; 141 AudioManager::kAudioCDSampleRate;
108 const int AlsaPcmOutputStreamTest::kTestBitsPerSample = 8; 142 const int AlsaPcmOutputStreamTest::kTestBitsPerSample = 8;
109 const int AlsaPcmOutputStreamTest::kTestBytesPerFrame = 143 const int AlsaPcmOutputStreamTest::kTestBytesPerFrame =
110 AlsaPcmOutputStreamTest::kTestBitsPerSample / 8 * 144 AlsaPcmOutputStreamTest::kTestBitsPerSample / 8 *
111 AlsaPcmOutputStreamTest::kTestChannels; 145 AlsaPcmOutputStreamTest::kTestChannels;
112 const AudioManager::Format AlsaPcmOutputStreamTest::kTestFormat = 146 const AudioManager::Format AlsaPcmOutputStreamTest::kTestFormat =
113 AudioManager::AUDIO_PCM_LINEAR; 147 AudioManager::AUDIO_PCM_LINEAR;
114 const char AlsaPcmOutputStreamTest::kTestDeviceName[] = "TestDevice"; 148 const char AlsaPcmOutputStreamTest::kTestDeviceName[] = "TestDevice";
115 const char AlsaPcmOutputStreamTest::kDummyMessage[] = "dummy"; 149 const char AlsaPcmOutputStreamTest::kDummyMessage[] = "dummy";
116 const int AlsaPcmOutputStreamTest::kTestFramesPerPacket = 100; 150 const int AlsaPcmOutputStreamTest::kTestFramesPerPacket = 1000;
117 const size_t AlsaPcmOutputStreamTest::kTestPacketSize = 151 const size_t AlsaPcmOutputStreamTest::kTestPacketSize =
118 AlsaPcmOutputStreamTest::kTestFramesPerPacket * 152 AlsaPcmOutputStreamTest::kTestFramesPerPacket *
119 AlsaPcmOutputStreamTest::kTestBytesPerFrame; 153 AlsaPcmOutputStreamTest::kTestBytesPerFrame;
120 const int AlsaPcmOutputStreamTest::kTestFailedErrno = -EACCES; 154 const int AlsaPcmOutputStreamTest::kTestFailedErrno = -EACCES;
121 snd_pcm_t* const AlsaPcmOutputStreamTest::kFakeHandle = 155 snd_pcm_t* const AlsaPcmOutputStreamTest::kFakeHandle =
122 reinterpret_cast<snd_pcm_t*>(1); 156 reinterpret_cast<snd_pcm_t*>(1);
123 157
158 char AlsaPcmOutputStreamTest::kSurround40[] = "surround40:CARD=foo,DEV=0";
159 char AlsaPcmOutputStreamTest::kSurround41[] = "surround41:CARD=foo,DEV=0";
160 char AlsaPcmOutputStreamTest::kSurround50[] = "surround50:CARD=foo,DEV=0";
161 char AlsaPcmOutputStreamTest::kSurround51[] = "surround51:CARD=foo,DEV=0";
162 char AlsaPcmOutputStreamTest::kSurround70[] = "surround70:CARD=foo,DEV=0";
163 char AlsaPcmOutputStreamTest::kSurround71[] = "surround71:CARD=foo,DEV=0";
164 void* AlsaPcmOutputStreamTest::kFakeHints[] = {
165 kSurround40, kSurround41, kSurround50, kSurround51,
166 kSurround70, kSurround71, NULL };
167
124 TEST_F(AlsaPcmOutputStreamTest, ConstructedState) { 168 TEST_F(AlsaPcmOutputStreamTest, ConstructedState) {
125 EXPECT_EQ(AlsaPcmOutputStream::kCreated, 169 EXPECT_EQ(AlsaPcmOutputStream::kCreated,
126 test_stream_->shared_data_.state()); 170 test_stream_->shared_data_.state());
127 171
128 // Should support mono. 172 // Should support mono.
129 test_stream_ = new AlsaPcmOutputStream(kTestDeviceName, 173 test_stream_ = CreateStreamWithChannels(1);
130 kTestFormat,
131 1, // Channels.
132 kTestSampleRate,
133 kTestBitsPerSample,
134 &mock_alsa_wrapper_,
135 &mock_manager_,
136 &message_loop_);
137 EXPECT_EQ(AlsaPcmOutputStream::kCreated, 174 EXPECT_EQ(AlsaPcmOutputStream::kCreated,
138 test_stream_->shared_data_.state()); 175 test_stream_->shared_data_.state());
139 176
140 // Should not support multi-channel. 177 // Should support multi-channel.
141 test_stream_ = new AlsaPcmOutputStream(kTestDeviceName, 178 test_stream_ = CreateStreamWithChannels(3);
142 kTestFormat, 179 EXPECT_EQ(AlsaPcmOutputStream::kCreated,
143 3, // Channels.
144 kTestSampleRate,
145 kTestBitsPerSample,
146 &mock_alsa_wrapper_,
147 &mock_manager_,
148 &message_loop_);
149 EXPECT_EQ(AlsaPcmOutputStream::kInError,
150 test_stream_->shared_data_.state()); 180 test_stream_->shared_data_.state());
151 181
152 // Bad bits per sample. 182 // Bad bits per sample.
153 test_stream_ = new AlsaPcmOutputStream(kTestDeviceName, 183 test_stream_ = new AlsaPcmOutputStream(kTestDeviceName,
154 kTestFormat, 184 kTestFormat,
155 kTestChannels, 185 kTestChannels,
156 kTestSampleRate, 186 kTestSampleRate,
157 kTestBitsPerSample - 1, 187 kTestBitsPerSample - 1,
158 &mock_alsa_wrapper_, 188 &mock_alsa_wrapper_,
159 &mock_manager_, 189 &mock_manager_,
160 &message_loop_); 190 &message_loop_);
161 EXPECT_EQ(AlsaPcmOutputStream::kInError, 191 EXPECT_EQ(AlsaPcmOutputStream::kInError,
162 test_stream_->shared_data_.state()); 192 test_stream_->shared_data_.state());
163 193
164 // Bad format. 194 // Bad format.
165 test_stream_ = new AlsaPcmOutputStream(kTestDeviceName, 195 test_stream_ = new AlsaPcmOutputStream(kTestDeviceName,
166 AudioManager::AUDIO_PCM_DELTA, 196 AudioManager::AUDIO_PCM_DELTA,
167 kTestChannels, 197 kTestChannels,
168 kTestSampleRate, 198 kTestSampleRate,
169 kTestBitsPerSample, 199 kTestBitsPerSample,
170 &mock_alsa_wrapper_, 200 &mock_alsa_wrapper_,
171 &mock_manager_, 201 &mock_manager_,
172 &message_loop_); 202 &message_loop_);
173 EXPECT_EQ(AlsaPcmOutputStream::kInError, 203 EXPECT_EQ(AlsaPcmOutputStream::kInError,
174 test_stream_->shared_data_.state()); 204 test_stream_->shared_data_.state());
175 } 205 }
176 206
207 TEST_F(AlsaPcmOutputStreamTest, LatencyFloor) {
208 const double kMicrosPerFrame =
209 static_cast<double>(1000000) / kTestSampleRate;
210 const double kPacketFramesInMinLatency =
211 AlsaPcmOutputStream::kMinLatencyMicros / kMicrosPerFrame / 2.0;
212 const int kMinLatencyPacketSize =
213 static_cast<int>(kPacketFramesInMinLatency * kTestBytesPerFrame);
214
215 // Test that packets which would cause a latency under less than
216 // AlsaPcmOutputStream::kMinLatencyMicros will get clipped to
217 // AlsaPcmOutputStream::kMinLatencyMicros,
218 EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, _, _, _))
219 .WillOnce(DoAll(SetArgumentPointee<0>(kFakeHandle),
220 Return(0)));
221 EXPECT_CALL(mock_alsa_wrapper_,
222 PcmSetParams(_, _, _, _, _, _,
223 AlsaPcmOutputStream::kMinLatencyMicros))
224 .WillOnce(Return(0));
225
226 ASSERT_TRUE(test_stream_->Open(kMinLatencyPacketSize));
227 message_loop_.RunAllPending();
228
229 // Now close it and test that everything was released.
230 EXPECT_CALL(mock_alsa_wrapper_, PcmClose(kFakeHandle)) .WillOnce(Return(0));
231 EXPECT_CALL(mock_manager_, ReleaseStream(test_stream_.get()));
232 test_stream_->Close();
233 message_loop_.RunAllPending();
234
235 Mock::VerifyAndClear(&mock_alsa_wrapper_);
236 Mock::VerifyAndClear(&mock_manager_);
237
238 // Test that having more packets ends up with a latency based on packet size.
239 const int kOverMinLatencyPacketSize =
240 (kPacketFramesInMinLatency + 1) * kTestBytesPerFrame;
241 int64 expected_micros = 2 *
242 AlsaPcmOutputStream::FramesToMicros(
243 kOverMinLatencyPacketSize / kTestBytesPerFrame,
244 kTestSampleRate);
245
246 // Recreate the stream to reset the state.
247 test_stream_ = CreateStreamWithChannels(kTestChannels);
248
249 EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, _, _, _))
250 .WillOnce(DoAll(SetArgumentPointee<0>(kFakeHandle), Return(0)));
251 EXPECT_CALL(mock_alsa_wrapper_,
252 PcmSetParams(_, _, _, _, _, _, expected_micros))
253 .WillOnce(Return(0));
254
255 ASSERT_TRUE(test_stream_->Open(kOverMinLatencyPacketSize));
256 message_loop_.RunAllPending();
257
258 // Now close it and test that everything was released.
259 EXPECT_CALL(mock_alsa_wrapper_, PcmClose(kFakeHandle))
260 .WillOnce(Return(0));
261 EXPECT_CALL(mock_manager_, ReleaseStream(test_stream_.get()));
262 test_stream_->Close();
263 message_loop_.RunAllPending();
264
265 Mock::VerifyAndClear(&mock_alsa_wrapper_);
266 Mock::VerifyAndClear(&mock_manager_);
267 }
268
177 TEST_F(AlsaPcmOutputStreamTest, OpenClose) { 269 TEST_F(AlsaPcmOutputStreamTest, OpenClose) {
178 int64 expected_micros = 2 * 270 int64 expected_micros = 2 *
179 AlsaPcmOutputStream::FramesToMicros(kTestPacketSize / kTestBytesPerFrame, 271 AlsaPcmOutputStream::FramesToMicros(kTestPacketSize / kTestBytesPerFrame,
180 kTestSampleRate); 272 kTestSampleRate);
181 273
182 // Open() call opens the playback device, sets the parameters, posts a task 274 // Open() call opens the playback device, sets the parameters, posts a task
183 // with the resulting configuration data, and transitions the object state to 275 // with the resulting configuration data, and transitions the object state to
184 // kIsOpened. 276 // kIsOpened.
185 EXPECT_CALL(mock_alsa_wrapper_, 277 EXPECT_CALL(mock_alsa_wrapper_,
186 PcmOpen(_, StrEq(kTestDeviceName), 278 PcmOpen(_, StrEq(kTestDeviceName),
187 SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) 279 SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK))
188 .WillOnce(DoAll(SetArgumentPointee<0>(kFakeHandle), 280 .WillOnce(DoAll(SetArgumentPointee<0>(kFakeHandle),
189 Return(0))); 281 Return(0)));
190 EXPECT_CALL(mock_alsa_wrapper_, 282 EXPECT_CALL(mock_alsa_wrapper_,
191 PcmSetParams(kFakeHandle, 283 PcmSetParams(kFakeHandle,
192 SND_PCM_FORMAT_S8, 284 SND_PCM_FORMAT_U8,
193 SND_PCM_ACCESS_RW_INTERLEAVED, 285 SND_PCM_ACCESS_RW_INTERLEAVED,
194 kTestChannels, 286 kTestChannels,
195 kTestSampleRate, 287 kTestSampleRate,
196 1, 288 1,
197 expected_micros)) 289 expected_micros))
198 .WillOnce(Return(0)); 290 .WillOnce(Return(0));
199 291
200 // Open the stream. 292 // Open the stream.
201 ASSERT_TRUE(test_stream_->Open(kTestPacketSize)); 293 ASSERT_TRUE(test_stream_->Open(kTestPacketSize));
202 message_loop_.RunAllPending(); 294 message_loop_.RunAllPending();
(...skipping 16 matching lines...) Expand all
219 EXPECT_FALSE(test_stream_->packet_.get()); 311 EXPECT_FALSE(test_stream_->packet_.get());
220 EXPECT_TRUE(test_stream_->stop_stream_); 312 EXPECT_TRUE(test_stream_->stop_stream_);
221 } 313 }
222 314
223 TEST_F(AlsaPcmOutputStreamTest, PcmOpenFailed) { 315 TEST_F(AlsaPcmOutputStreamTest, PcmOpenFailed) {
224 EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, _, _, _)) 316 EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, _, _, _))
225 .WillOnce(Return(kTestFailedErrno)); 317 .WillOnce(Return(kTestFailedErrno));
226 EXPECT_CALL(mock_alsa_wrapper_, StrError(kTestFailedErrno)) 318 EXPECT_CALL(mock_alsa_wrapper_, StrError(kTestFailedErrno))
227 .WillOnce(Return(kDummyMessage)); 319 .WillOnce(Return(kDummyMessage));
228 320
229 // If open fails, the stream stays in kCreated because it has effectively had 321 // Open still succeeds since PcmOpen is delegated to another thread.
230 // no changes. 322 ASSERT_TRUE(test_stream_->Open(kTestPacketSize));
231 ASSERT_FALSE(test_stream_->Open(kTestPacketSize)); 323 ASSERT_EQ(AlsaPcmOutputStream::kIsOpened,
232 EXPECT_EQ(AlsaPcmOutputStream::kCreated,
233 test_stream_->shared_data_.state()); 324 test_stream_->shared_data_.state());
325 ASSERT_FALSE(test_stream_->stop_stream_);
326 message_loop_.RunAllPending();
327
328 // Ensure internal state is set for a no-op stream if PcmOpen() failes.
329 EXPECT_EQ(AlsaPcmOutputStream::kIsOpened,
330 test_stream_->shared_data_.state());
331 EXPECT_TRUE(test_stream_->stop_stream_);
332 EXPECT_TRUE(test_stream_->playback_handle_ == NULL);
333 EXPECT_FALSE(test_stream_->packet_.get());
334
335 // Close the stream since we opened it to make destruction happy.
336 EXPECT_CALL(mock_manager_, ReleaseStream(test_stream_.get()));
337 test_stream_->Close();
338 message_loop_.RunAllPending();
234 } 339 }
235 340
236 TEST_F(AlsaPcmOutputStreamTest, PcmSetParamsFailed) { 341 TEST_F(AlsaPcmOutputStreamTest, PcmSetParamsFailed) {
237 EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, _, _, _)) 342 EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, _, _, _))
238 .WillOnce(DoAll(SetArgumentPointee<0>(kFakeHandle), 343 .WillOnce(DoAll(SetArgumentPointee<0>(kFakeHandle),
239 Return(0))); 344 Return(0)));
240 EXPECT_CALL(mock_alsa_wrapper_, PcmSetParams(_, _, _, _, _, _, _)) 345 EXPECT_CALL(mock_alsa_wrapper_, PcmSetParams(_, _, _, _, _, _, _))
241 .WillOnce(Return(kTestFailedErrno)); 346 .WillOnce(Return(kTestFailedErrno));
242 EXPECT_CALL(mock_alsa_wrapper_, PcmClose(kFakeHandle)) 347 EXPECT_CALL(mock_alsa_wrapper_, PcmClose(kFakeHandle))
243 .WillOnce(Return(0)); 348 .WillOnce(Return(0));
244 EXPECT_CALL(mock_alsa_wrapper_, StrError(kTestFailedErrno)) 349 EXPECT_CALL(mock_alsa_wrapper_, StrError(kTestFailedErrno))
245 .WillOnce(Return(kDummyMessage)); 350 .WillOnce(Return(kDummyMessage));
246 351
247 // If open fails, the stream stays in kCreated because it has effectively had 352 // If open fails, the stream stays in kCreated because it has effectively had
248 // no changes. 353 // no changes.
249 ASSERT_FALSE(test_stream_->Open(kTestPacketSize)); 354 ASSERT_TRUE(test_stream_->Open(kTestPacketSize));
250 EXPECT_EQ(AlsaPcmOutputStream::kCreated, 355 EXPECT_EQ(AlsaPcmOutputStream::kIsOpened,
251 test_stream_->shared_data_.state()); 356 test_stream_->shared_data_.state());
357 ASSERT_FALSE(test_stream_->stop_stream_);
358 message_loop_.RunAllPending();
359
360 // Ensure internal state is set for a no-op stream if PcmSetParams() failes.
361 EXPECT_EQ(AlsaPcmOutputStream::kIsOpened,
362 test_stream_->shared_data_.state());
363 EXPECT_TRUE(test_stream_->stop_stream_);
364 EXPECT_TRUE(test_stream_->playback_handle_ == NULL);
365 EXPECT_FALSE(test_stream_->packet_.get());
366
367 // Close the stream since we opened it to make destruction happy.
368 EXPECT_CALL(mock_manager_, ReleaseStream(test_stream_.get()));
369 test_stream_->Close();
370 message_loop_.RunAllPending();
252 } 371 }
253 372
254 TEST_F(AlsaPcmOutputStreamTest, StartStop) { 373 TEST_F(AlsaPcmOutputStreamTest, StartStop) {
255 // Open() call opens the playback device, sets the parameters, posts a task 374 // Open() call opens the playback device, sets the parameters, posts a task
256 // with the resulting configuration data, and transitions the object state to 375 // with the resulting configuration data, and transitions the object state to
257 // kIsOpened. 376 // kIsOpened.
258 EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, _, _, _)) 377 EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, _, _, _))
259 .WillOnce(DoAll(SetArgumentPointee<0>(kFakeHandle), 378 .WillOnce(DoAll(SetArgumentPointee<0>(kFakeHandle),
260 Return(0))); 379 Return(0)));
261 EXPECT_CALL(mock_alsa_wrapper_, PcmSetParams(_, _, _, _, _, _, _)) 380 EXPECT_CALL(mock_alsa_wrapper_, PcmSetParams(_, _, _, _, _, _, _))
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 EXPECT_EQ(10u, packet_.size); 498 EXPECT_EQ(10u, packet_.size);
380 } 499 }
381 500
382 TEST_F(AlsaPcmOutputStreamTest, BufferPacket_UnfinishedPacket) { 501 TEST_F(AlsaPcmOutputStreamTest, BufferPacket_UnfinishedPacket) {
383 // No expectations set on the strict mock because nothing should be called. 502 // No expectations set on the strict mock because nothing should be called.
384 test_stream_->BufferPacket(&packet_); 503 test_stream_->BufferPacket(&packet_);
385 EXPECT_EQ(0u, packet_.used); 504 EXPECT_EQ(0u, packet_.used);
386 EXPECT_EQ(kTestPacketSize, packet_.size); 505 EXPECT_EQ(kTestPacketSize, packet_.size);
387 } 506 }
388 507
508 TEST_F(AlsaPcmOutputStreamTest, AutoSelectDevice_DeviceSelect) {
509 // Try channels from 1 -> 9. and see that we get the more specific surroundXX
510 // device opened for channels 4-8. For all other channels, the device should
511 // default to |AlsaPcmOutputStream::kDefaultDevice|. We should also not
512 // downmix any channel in this case because downmixing is only defined for
513 // channels 4-8, which we are guaranteeing to work.
514 //
515 // Note that the loop starts at "1", so the first parameter is ignored in
516 // these arrays.
517 const char* kExpectedDeviceName[] = { NULL,
518 AlsaPcmOutputStream::kDefaultDevice,
519 AlsaPcmOutputStream::kDefaultDevice,
520 AlsaPcmOutputStream::kDefaultDevice,
521 kSurround40, kSurround50, kSurround51,
522 kSurround70, kSurround71,
523 AlsaPcmOutputStream::kDefaultDevice };
524 bool kExpectedDownmix[] = { false, false, false, false, false, false,
525 false, false, false, false };
526
527 for (int i = 1; i <= 9; ++i) {
528 SCOPED_TRACE(StringPrintf("Attempting %d Channel", i));
529
530 // Hints will only be grabbed for channel numbers that have non-default
531 // devices associated with them.
532 if (kExpectedDeviceName[i] != AlsaPcmOutputStream::kDefaultDevice) {
533 // The DeviceNameHint and DeviceNameFreeHint need to be paired to avoid a
534 // memory leak.
535 EXPECT_CALL(mock_alsa_wrapper_, DeviceNameHint(_, _, _))
536 .WillOnce(DoAll(SetArgumentPointee<2>(&kFakeHints[0]), Return(0)));
537 EXPECT_CALL(mock_alsa_wrapper_, DeviceNameFreeHint(&kFakeHints[0]))
538 .Times(1);
539 }
540
541 EXPECT_CALL(mock_alsa_wrapper_,
542 PcmOpen(_, StrEq(kExpectedDeviceName[i]), _, _))
543 .WillOnce(DoAll(SetArgumentPointee<0>(kFakeHandle), Return(0)));
544 EXPECT_CALL(mock_alsa_wrapper_,
545 PcmSetParams(kFakeHandle, _, _, i, _, _, _))
546 .WillOnce(Return(0));
547
548 // The parameters are specified by ALSA documentation, and are in constants
549 // in the implementation files.
550 EXPECT_CALL(mock_alsa_wrapper_, DeviceNameGetHint(_, StrEq("IOID")))
551 .WillRepeatedly(Invoke(OutputHint));
552 EXPECT_CALL(mock_alsa_wrapper_, DeviceNameGetHint(_, StrEq("NAME")))
553 .WillRepeatedly(Invoke(EchoHint));
554
555
556 test_stream_ = CreateStreamWithChannels(i);
557 EXPECT_TRUE(test_stream_->AutoSelectDevice(i));
558 EXPECT_EQ(kExpectedDownmix[i], test_stream_->should_downmix_);
559
560 Mock::VerifyAndClearExpectations(&mock_alsa_wrapper_);
561 Mock::VerifyAndClearExpectations(&mock_manager_);
562 }
563 }
564
565 TEST_F(AlsaPcmOutputStreamTest, AutoSelectDevice_FallbackDevices) {
566 using std::string;
567
568 // If there are problems opening a multi-channel device, it the fallbacks
569 // operations should be as follows. Assume the multi-channel device name is
570 // surround50:
571 //
572 // 1) Try open "surround50"
573 // 2) Try open "plug:surround50".
574 // 3) Try open "default".
575 // 4) Try open "plug:default".
576 // 5) Give up trying to open.
577 //
578 const string first_try = kSurround50;
579 const string second_try = string(AlsaPcmOutputStream::kPlugPrefix) +
580 kSurround50;
581 const string third_try = AlsaPcmOutputStream::kDefaultDevice;
582 const string fourth_try = string(AlsaPcmOutputStream::kPlugPrefix) +
583 AlsaPcmOutputStream::kDefaultDevice;
584
585 EXPECT_CALL(mock_alsa_wrapper_, DeviceNameHint(_, _, _))
586 .WillOnce(DoAll(SetArgumentPointee<2>(&kFakeHints[0]), Return(0)));
587 EXPECT_CALL(mock_alsa_wrapper_, DeviceNameFreeHint(&kFakeHints[0]))
588 .Times(1);
589 EXPECT_CALL(mock_alsa_wrapper_, DeviceNameGetHint(_, StrEq("IOID")))
590 .WillRepeatedly(Invoke(OutputHint));
591 EXPECT_CALL(mock_alsa_wrapper_, DeviceNameGetHint(_, StrEq("NAME")))
592 .WillRepeatedly(Invoke(EchoHint));
593 EXPECT_CALL(mock_alsa_wrapper_, StrError(kTestFailedErrno))
594 .WillRepeatedly(Return(kDummyMessage));
595
596 InSequence s;
597 EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, StrEq(first_try.c_str()), _, _))
598 .WillOnce(Return(kTestFailedErrno));
599 EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, StrEq(second_try.c_str()), _, _))
600 .WillOnce(Return(kTestFailedErrno));
601 EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, StrEq(third_try.c_str()), _, _))
602 .WillOnce(Return(kTestFailedErrno));
603 EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, StrEq(fourth_try.c_str()), _, _))
604 .WillOnce(Return(kTestFailedErrno));
605
606 test_stream_ = CreateStreamWithChannels(5);
607 EXPECT_FALSE(test_stream_->AutoSelectDevice(5));
608 }
609
610 TEST_F(AlsaPcmOutputStreamTest, AutoSelectDevice_HintFail) {
611 // Should get |kDefaultDevice|, and force a 2-channel downmix on a failure to
612 // enumerate devices.
613 EXPECT_CALL(mock_alsa_wrapper_, DeviceNameHint(_, _, _))
614 .WillRepeatedly(Return(kTestFailedErrno));
615 EXPECT_CALL(mock_alsa_wrapper_,
616 PcmOpen(_, StrEq(AlsaPcmOutputStream::kDefaultDevice), _, _))
617 .WillOnce(DoAll(SetArgumentPointee<0>(kFakeHandle), Return(0)));
618 EXPECT_CALL(mock_alsa_wrapper_,
619 PcmSetParams(kFakeHandle, _, _, 2, _, _, _))
620 .WillOnce(Return(0));
621 EXPECT_CALL(mock_alsa_wrapper_, StrError(kTestFailedErrno))
622 .WillOnce(Return(kDummyMessage));
623
624 test_stream_ = CreateStreamWithChannels(5);
625 EXPECT_TRUE(test_stream_->AutoSelectDevice(5));
626 EXPECT_TRUE(test_stream_->should_downmix_);
627 }
628
389 TEST_F(AlsaPcmOutputStreamTest, BufferPacket_StopStream) { 629 TEST_F(AlsaPcmOutputStreamTest, BufferPacket_StopStream) {
390 test_stream_->stop_stream_ = true; 630 test_stream_->stop_stream_ = true;
391 test_stream_->BufferPacket(&packet_); 631 test_stream_->BufferPacket(&packet_);
392 EXPECT_EQ(0u, packet_.used); 632 EXPECT_EQ(0u, packet_.used);
393 EXPECT_EQ(0u, packet_.size); 633 EXPECT_EQ(0u, packet_.size);
394 } 634 }
395 635
396 TEST_F(AlsaPcmOutputStreamTest, ScheduleNextWrite) { 636 TEST_F(AlsaPcmOutputStreamTest, ScheduleNextWrite) {
397 test_stream_->shared_data_.TransitionTo(AlsaPcmOutputStream::kIsOpened); 637 test_stream_->shared_data_.TransitionTo(AlsaPcmOutputStream::kIsOpened);
398 test_stream_->shared_data_.TransitionTo(AlsaPcmOutputStream::kIsPlaying); 638 test_stream_->shared_data_.TransitionTo(AlsaPcmOutputStream::kIsPlaying);
(...skipping 11 matching lines...) Expand all
410 650
411 test_stream_->stop_stream_ = true; 651 test_stream_->stop_stream_ = true;
412 test_stream_->ScheduleNextWrite(&packet_); 652 test_stream_->ScheduleNextWrite(&packet_);
413 653
414 // TODO(ajwong): Find a way to test whether or not another task has been 654 // TODO(ajwong): Find a way to test whether or not another task has been
415 // posted so we can verify that the Alsa code will indeed break the task 655 // posted so we can verify that the Alsa code will indeed break the task
416 // posting loop. 656 // posting loop.
417 657
418 test_stream_->shared_data_.TransitionTo(AlsaPcmOutputStream::kIsClosed); 658 test_stream_->shared_data_.TransitionTo(AlsaPcmOutputStream::kIsClosed);
419 } 659 }
OLDNEW
« no previous file with comments | « media/audio/linux/alsa_output.cc ('k') | media/audio/linux/alsa_wrapper.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698