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

Side by Side Diff: media/audio/audio_output_controller_unittest.cc

Issue 11413078: Tab Audio Capture: Browser-side connect/disconnect functionality. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove WCAudioInputStream changes (split into another change). Created 8 years 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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/basictypes.h"
5 #include "base/bind.h" 6 #include "base/bind.h"
6 #include "base/environment.h" 7 #include "base/environment.h"
7 #include "base/basictypes.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/memory/ref_counted.h"
10 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop.h" 11 #include "base/message_loop.h"
10 #include "base/synchronization/waitable_event.h" 12 #include "base/synchronization/waitable_event.h"
11 #include "media/audio/audio_output_controller.h" 13 #include "media/audio/audio_output_controller.h"
14 #include "media/audio/audio_parameters.h"
15 #include "media/base/audio_bus.h"
12 #include "testing/gmock/include/gmock/gmock.h" 16 #include "testing/gmock/include/gmock/gmock.h"
13 #include "testing/gtest/include/gtest/gtest.h" 17 #include "testing/gtest/include/gtest/gtest.h"
14 18
15 // TODO(vrk): These tests need to be rewritten! (crbug.com/112500)
16
17 using ::testing::_; 19 using ::testing::_;
18 using ::testing::AtLeast; 20 using ::testing::AtLeast;
19 using ::testing::DoAll; 21 using ::testing::DoAll;
20 using ::testing::Exactly;
21 using ::testing::InvokeWithoutArgs;
22 using ::testing::NotNull; 22 using ::testing::NotNull;
23 using ::testing::Return; 23 using ::testing::Return;
24 24
25 namespace media { 25 namespace media {
26 26
27 static const int kSampleRate = AudioParameters::kAudioCDSampleRate; 27 static const int kSampleRate = AudioParameters::kAudioCDSampleRate;
28 static const int kBitsPerSample = 16; 28 static const int kBitsPerSample = 16;
29 static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO; 29 static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO;
30 static const int kSamplesPerPacket = kSampleRate / 10; 30 static const int kSamplesPerPacket = kSampleRate / 10;
31 static const int kHardwareBufferSize = kSamplesPerPacket * 31 static const int kHardwareBufferSize = kSamplesPerPacket *
(...skipping 25 matching lines...) Expand all
57 MOCK_METHOD0(DataReady, bool()); 57 MOCK_METHOD0(DataReady, bool());
58 58
59 private: 59 private:
60 DISALLOW_COPY_AND_ASSIGN(MockAudioOutputControllerSyncReader); 60 DISALLOW_COPY_AND_ASSIGN(MockAudioOutputControllerSyncReader);
61 }; 61 };
62 62
63 ACTION_P(SignalEvent, event) { 63 ACTION_P(SignalEvent, event) {
64 event->Signal(); 64 event->Signal();
65 } 65 }
66 66
67 // Custom action to clear a memory buffer. 67 static const float kBufferZeroData = 0.0f;
68 ACTION(ClearBuffer) { 68 static const float kBufferNonZeroData = 1.0f;
69 arg1->Zero(); 69 ACTION_P(PopulateBuffer, value) {
70 } 70 // Note: To confirm the buffer will be populated in these tests, it's
71 71 // sufficient that only the first float in channel 0 is set to the value.
72 // Closes AudioOutputController synchronously. 72 arg1->channel(0)[0] = value;
73 static void CloseAudioController(AudioOutputController* controller) {
74 controller->Close(MessageLoop::QuitClosure());
75 MessageLoop::current()->Run();
76 } 73 }
77 74
78 class AudioOutputControllerTest : public testing::Test { 75 class AudioOutputControllerTest : public testing::Test {
79 public: 76 public:
80 AudioOutputControllerTest() {} 77 AudioOutputControllerTest()
81 virtual ~AudioOutputControllerTest() {} 78 : audio_manager_(AudioManager::Create()),
79 create_event_(false, false),
80 play_event_(false, false),
81 read_event_(false, false),
82 pause_event_(false, false),
83 diverted_callback_(NULL) {
84 if (ShouldSkipTest()) {
DaleCurtis 2012/12/05 23:35:14 Shouldn't be necessary anymore since we have FakeA
miu 2012/12/11 02:30:45 Done.
85 DLOG(WARNING)
86 << "Skipping tests because OS provides no audio output devices.";
87 }
88 }
89
90 virtual ~AudioOutputControllerTest() {
91 ASSERT_FALSE(diverted_callback_);
92 }
82 93
83 protected: 94 protected:
95 bool ShouldSkipTest() {
96 return !audio_manager_->HasAudioOutputDevices();
97 }
98
99 // Returns true if a controller was successfully created.
100 bool Create(int samples_per_packet) {
101 params_ = AudioParameters(
102 AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout,
103 kSampleRate, kBitsPerSample, samples_per_packet);
104 controller_ = AudioOutputController::Create(
105 audio_manager_.get(), &mock_event_handler_, params_,
106 &mock_sync_reader_);
107
108 if (controller_) {
109 EXPECT_FALSE(create_event_.IsSignaled());
110 EXPECT_CALL(mock_event_handler_, OnCreated(NotNull()))
111 .WillOnce(SignalEvent(&create_event_));
112 EXPECT_CALL(mock_sync_reader_, Close());
113 } else {
114 EXPECT_CALL(mock_event_handler_, OnCreated(NotNull()))
115 .Times(0);
116 EXPECT_CALL(mock_sync_reader_, Close())
117 .Times(0);
118 }
119
120 EXPECT_FALSE(play_event_.IsSignaled());
121 EXPECT_FALSE(read_event_.IsSignaled());
122 EXPECT_FALSE(pause_event_.IsSignaled());
123
124 return controller_ != NULL;
125 }
126
127 void Play() {
128 // Expect the event handler to receive one OnPlaying() call.
129 EXPECT_CALL(mock_event_handler_, OnPlaying(NotNull()))
130 .WillOnce(SignalEvent(&play_event_));
131
132 // During playback, the mock pretends to provide audio data rendered and
133 // sent from the render process.
134 EXPECT_CALL(mock_sync_reader_, UpdatePendingBytes(_))
135 .Times(AtLeast(2));
136 EXPECT_CALL(mock_sync_reader_, Read(_, _))
137 .WillRepeatedly(DoAll(PopulateBuffer(kBufferNonZeroData),
138 SignalEvent(&read_event_),
139 Return(params_.frames_per_buffer())));
140 EXPECT_CALL(mock_sync_reader_, DataReady())
141 .WillRepeatedly(Return(true));
142
143 controller_->Play();
144 }
145
146 void Pause() {
147 // Expect the event handler to receive one OnPaused() call.
148 EXPECT_CALL(mock_event_handler_, OnPaused(NotNull()))
149 .WillOnce(SignalEvent(&pause_event_));
150
151 controller_->Pause();
152 }
153
154 void ChangeDevice() {
155 // Expect the event handler to receive one OnPaying() call and no OnPaused()
156 // call.
157 EXPECT_CALL(mock_event_handler_, OnPlaying(NotNull()))
158 .WillOnce(SignalEvent(&play_event_));
159 EXPECT_CALL(mock_event_handler_, OnPaused(NotNull()))
160 .Times(0);
161
162 // Simulate a device change event to AudioOutputController from the
163 // AudioManager.
164 audio_manager_->GetMessageLoop()->PostTask(
165 FROM_HERE,
166 base::Bind(&AudioOutputController::OnDeviceChange, controller_));
167 }
168
169 void Divert() {
170 EXPECT_FALSE(diverted_callback_);
171 diverted_callback_ = controller_->Divert();
172 EXPECT_TRUE(diverted_callback_);
173 }
174
175 // |expected_buffer_data| is used to differentiate between: 1) expecting to
176 // see audio data rendered from the render process; versus 2) expecting
177 // AudioOutputController to be filling-in zeros (i.e., it is not in a playback
178 // state).
179 void ReadDivertedAudioData(float expected_buffer_data) {
180 ASSERT_TRUE(diverted_callback_);
181 scoped_ptr<AudioBus> dest = AudioBus::Create(params_);
182 const int frames_read =
183 diverted_callback_->OnMoreData(dest.get(), AudioBuffersState());
184 EXPECT_EQ(dest->frames(), frames_read);
185 EXPECT_EQ(expected_buffer_data, dest->channel(0)[0]);
186 }
187
188 // |expect_playback_restored| is true if the revert happened during the
189 // playback state. In this case, we expect event handler to receive one call
190 // to OnPlaying().
191 void Revert(bool expect_playback_restored) {
192 EXPECT_TRUE(diverted_callback_);
193 if (expect_playback_restored) {
194 EXPECT_CALL(mock_event_handler_, OnPlaying(NotNull()))
195 .WillOnce(SignalEvent(&play_event_));
196 } else {
197 EXPECT_CALL(mock_event_handler_, OnPlaying(NotNull()))
198 .Times(0);
199 }
200 controller_->Revert(diverted_callback_);
201 diverted_callback_ = NULL;
202 }
203
204 void Close() {
205 controller_->Close(MessageLoop::QuitClosure());
206 MessageLoop::current()->Run();
207 }
208
209 // These synchronize the main thread with key events taking place on other
210 // threads.
211 void WaitForCreate() { create_event_.Wait(); }
212 void WaitForPlay() { play_event_.Wait(); }
213 void WaitForReads() {
214 // Note: Arbitrarily chosen, but more iterations causes tests to take
215 // significantly more time.
216 static const int kNumIterations = 3;
217 for (int i = 0; i < kNumIterations; ++i) {
218 read_event_.Wait();
219 }
220 }
221 void WaitForPause() { pause_event_.Wait(); }
222
223 private:
84 MessageLoopForIO message_loop_; 224 MessageLoopForIO message_loop_;
85 225 scoped_ptr<AudioManager> audio_manager_;
86 private: 226 MockAudioOutputControllerEventHandler mock_event_handler_;
227 MockAudioOutputControllerSyncReader mock_sync_reader_;
228 base::WaitableEvent create_event_;
229 base::WaitableEvent play_event_;
230 base::WaitableEvent read_event_;
231 base::WaitableEvent pause_event_;
232 AudioParameters params_;
233 scoped_refptr<AudioOutputController> controller_;
234 AudioOutputStream::AudioSourceCallback* diverted_callback_;
235
87 DISALLOW_COPY_AND_ASSIGN(AudioOutputControllerTest); 236 DISALLOW_COPY_AND_ASSIGN(AudioOutputControllerTest);
88 }; 237 };
89 238
90 TEST_F(AudioOutputControllerTest, CreateAndClose) { 239 TEST_F(AudioOutputControllerTest, CreateAndClose) {
91 scoped_ptr<AudioManager> audio_manager(AudioManager::Create()); 240 if (ShouldSkipTest())
92 if (!audio_manager->HasAudioOutputDevices()) 241 return;
93 return; 242 ASSERT_TRUE(Create(kSamplesPerPacket));
94 243 Close();
95 MockAudioOutputControllerEventHandler event_handler; 244 }
96 245
97 EXPECT_CALL(event_handler, OnCreated(NotNull())) 246 TEST_F(AudioOutputControllerTest, HardwareBufferTooLarge) {
98 .Times(1); 247 if (ShouldSkipTest())
99 248 return;
100 MockAudioOutputControllerSyncReader sync_reader; 249 EXPECT_FALSE(Create(kSamplesPerPacket * 1000));
101 EXPECT_CALL(sync_reader, Close()); 250 }
102 251
103 AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, 252 TEST_F(AudioOutputControllerTest, PlayAndClose) {
104 kSampleRate, kBitsPerSample, kSamplesPerPacket); 253 if (ShouldSkipTest())
105 scoped_refptr<AudioOutputController> controller = 254 return;
106 AudioOutputController::Create( 255 ASSERT_TRUE(Create(kSamplesPerPacket));
107 audio_manager.get(), &event_handler, params, &sync_reader); 256 WaitForCreate();
108 ASSERT_TRUE(controller.get()); 257 Play();
109 258 WaitForPlay();
110 // Close the controller immediately. 259 WaitForReads();
111 CloseAudioController(controller); 260 Close();
112 } 261 }
113 262
114 TEST_F(AudioOutputControllerTest, PlayPauseClose) { 263 TEST_F(AudioOutputControllerTest, PlayPauseClose) {
115 scoped_ptr<AudioManager> audio_manager(AudioManager::Create()); 264 if (ShouldSkipTest())
116 if (!audio_manager->HasAudioOutputDevices()) 265 return;
117 return; 266 ASSERT_TRUE(Create(kSamplesPerPacket));
118 267 WaitForCreate();
119 MockAudioOutputControllerEventHandler event_handler; 268 Play();
120 base::WaitableEvent event(false, false); 269 WaitForPlay();
121 base::WaitableEvent pause_event(false, false); 270 WaitForReads();
122 271 Pause();
123 // If OnCreated is called then signal the event. 272 WaitForPause();
124 EXPECT_CALL(event_handler, OnCreated(NotNull())) 273 Close();
125 .WillOnce(InvokeWithoutArgs(&event, &base::WaitableEvent::Signal));
126
127 // OnPlaying() will be called only once.
128 EXPECT_CALL(event_handler, OnPlaying(NotNull()));
129
130 MockAudioOutputControllerSyncReader sync_reader;
131 EXPECT_CALL(sync_reader, UpdatePendingBytes(_))
132 .Times(AtLeast(2));
133 EXPECT_CALL(sync_reader, Read(_, _))
134 .WillRepeatedly(DoAll(ClearBuffer(), SignalEvent(&event),
135 Return(4)));
136 EXPECT_CALL(sync_reader, DataReady())
137 .WillRepeatedly(Return(true));
138 EXPECT_CALL(event_handler, OnPaused(NotNull()))
139 .WillOnce(InvokeWithoutArgs(&pause_event, &base::WaitableEvent::Signal));
140 EXPECT_CALL(sync_reader, Close());
141
142 AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout,
143 kSampleRate, kBitsPerSample, kSamplesPerPacket);
144 scoped_refptr<AudioOutputController> controller =
145 AudioOutputController::Create(
146 audio_manager.get(), &event_handler, params, &sync_reader);
147 ASSERT_TRUE(controller.get());
148
149 // Wait for OnCreated() to be called.
150 event.Wait();
151
152 ASSERT_FALSE(pause_event.IsSignaled());
153 controller->Play();
154 controller->Pause();
155 pause_event.Wait();
156
157 // Now stop the controller.
158 CloseAudioController(controller);
159 }
160
161 TEST_F(AudioOutputControllerTest, HardwareBufferTooLarge) {
162 scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
163 if (!audio_manager->HasAudioOutputDevices())
164 return;
165
166 // Create an audio device with a very large hardware buffer size.
167 MockAudioOutputControllerEventHandler event_handler;
168
169 MockAudioOutputControllerSyncReader sync_reader;
170 AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout,
171 kSampleRate, kBitsPerSample,
172 kSamplesPerPacket * 1000);
173 scoped_refptr<AudioOutputController> controller =
174 AudioOutputController::Create(
175 audio_manager.get(), &event_handler, params, &sync_reader);
176
177 // Use assert because we don't stop the device and assume we can't
178 // create one.
179 ASSERT_FALSE(controller);
180 } 274 }
181 275
182 TEST_F(AudioOutputControllerTest, PlayPausePlayClose) { 276 TEST_F(AudioOutputControllerTest, PlayPausePlayClose) {
183 scoped_ptr<AudioManager> audio_manager(AudioManager::Create()); 277 if (ShouldSkipTest())
184 if (!audio_manager->HasAudioOutputDevices()) 278 return;
185 return; 279 ASSERT_TRUE(Create(kSamplesPerPacket));
186 280 WaitForCreate();
187 MockAudioOutputControllerEventHandler event_handler; 281 Play();
188 base::WaitableEvent event(false, false); 282 WaitForPlay();
189 EXPECT_CALL(event_handler, OnCreated(NotNull())) 283 WaitForReads();
190 .WillOnce(InvokeWithoutArgs(&event, &base::WaitableEvent::Signal)); 284 Pause();
191 285 WaitForPause();
192 // OnPlaying() will be called only once. 286 Play();
193 base::WaitableEvent play_event(false, false); 287 WaitForPlay();
194 EXPECT_CALL(event_handler, OnPlaying(NotNull())) 288 Close();
195 .WillOnce(InvokeWithoutArgs(&play_event, &base::WaitableEvent::Signal)); 289 }
196 290
197 // OnPaused() should never be called since the pause during kStarting is 291 TEST_F(AudioOutputControllerTest, PlayDeviceChangeClose) {
198 // dropped when the second play comes in. 292 if (ShouldSkipTest())
199 EXPECT_CALL(event_handler, OnPaused(NotNull())) 293 return;
200 .Times(0); 294 ASSERT_TRUE(Create(kSamplesPerPacket));
201 295 WaitForCreate();
202 MockAudioOutputControllerSyncReader sync_reader; 296 Play();
203 EXPECT_CALL(sync_reader, UpdatePendingBytes(_)) 297 WaitForPlay();
204 .Times(AtLeast(1)); 298 WaitForReads();
205 EXPECT_CALL(sync_reader, Read(_, _)) 299 ChangeDevice();
206 .WillRepeatedly(DoAll(ClearBuffer(), SignalEvent(&event), Return(4))); 300 WaitForPlay();
207 EXPECT_CALL(sync_reader, DataReady()) 301 WaitForReads();
208 .WillRepeatedly(Return(true)); 302 Close();
209 EXPECT_CALL(sync_reader, Close()); 303 }
210 304
211 AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, 305 TEST_F(AudioOutputControllerTest, PlayDivertRevertClose) {
212 kSampleRate, kBitsPerSample, kSamplesPerPacket); 306 if (ShouldSkipTest())
213 scoped_refptr<AudioOutputController> controller = 307 return;
214 AudioOutputController::Create( 308 ASSERT_TRUE(Create(kSamplesPerPacket));
215 audio_manager.get(), &event_handler, params, &sync_reader); 309 WaitForCreate();
216 ASSERT_TRUE(controller.get()); 310 Play();
217 311 WaitForPlay();
218 // Wait for OnCreated() to be called. 312 WaitForReads();
219 event.Wait(); 313 Divert();
220 314 ReadDivertedAudioData(kBufferNonZeroData);
221 ASSERT_FALSE(play_event.IsSignaled()); 315 Revert(true);
222 controller->Play(); 316 WaitForPlay();
223 controller->Pause(); 317 WaitForReads();
224 controller->Play(); 318 Close();
225 play_event.Wait(); 319 }
226 320
227 // Now stop the controller. 321 TEST_F(AudioOutputControllerTest, DivertPlayPausePlayRevertClose) {
228 CloseAudioController(controller); 322 if (ShouldSkipTest())
229 } 323 return;
230 324 ASSERT_TRUE(Create(kSamplesPerPacket));
231 // Ensure state change events are handled. 325 WaitForCreate();
232 TEST_F(AudioOutputControllerTest, PlayStateChangeClose) { 326 Divert();
233 scoped_ptr<AudioManager> audio_manager(AudioManager::Create()); 327 // Read back zeros before playback starts.
234 if (!audio_manager->HasAudioOutputDevices()) 328 ReadDivertedAudioData(kBufferZeroData);
235 return; 329 Play();
236 330 WaitForPlay();
237 MockAudioOutputControllerEventHandler event_handler; 331 // Normal read of audio data from renderer.
238 base::WaitableEvent event(false, false); 332 ReadDivertedAudioData(kBufferNonZeroData);
239 EXPECT_CALL(event_handler, OnCreated(NotNull())) 333 Pause();
240 .WillOnce(InvokeWithoutArgs(&event, &base::WaitableEvent::Signal)); 334 WaitForPause();
241 335 // Read back zeros while paused.
242 // OnPlaying() will be called once normally and once after being recreated. 336 ReadDivertedAudioData(kBufferZeroData);
243 base::WaitableEvent play_event(false, false); 337 Play();
244 EXPECT_CALL(event_handler, OnPlaying(NotNull())) 338 WaitForPlay();
245 .Times(2) 339 // Normal read of audio data from renderer again.
246 .WillRepeatedly(InvokeWithoutArgs( 340 ReadDivertedAudioData(kBufferNonZeroData);
247 &play_event, &base::WaitableEvent::Signal)); 341 Revert(true);
248 342 WaitForPlay();
249 // OnPaused() should not be called during the state change event. 343 WaitForReads();
250 EXPECT_CALL(event_handler, OnPaused(NotNull())) 344 Close();
251 .Times(0); 345 }
252 346
253 MockAudioOutputControllerSyncReader sync_reader; 347 TEST_F(AudioOutputControllerTest, DivertRevertClose) {
254 EXPECT_CALL(sync_reader, UpdatePendingBytes(_)) 348 if (ShouldSkipTest())
255 .Times(AtLeast(1)); 349 return;
256 EXPECT_CALL(sync_reader, Read(_, _)) 350 ASSERT_TRUE(Create(kSamplesPerPacket));
257 .WillRepeatedly(DoAll(ClearBuffer(), SignalEvent(&event), Return(4))); 351 WaitForCreate();
258 EXPECT_CALL(sync_reader, DataReady()) 352 Divert();
259 .WillRepeatedly(Return(true)); 353 // Read back zeros since playback was not requested.
260 EXPECT_CALL(sync_reader, Close()); 354 ReadDivertedAudioData(kBufferZeroData);
261 355 Revert(false);
262 AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, 356 Close();
263 kSampleRate, kBitsPerSample, kSamplesPerPacket);
264 scoped_refptr<AudioOutputController> controller =
265 AudioOutputController::Create(
266 audio_manager.get(), &event_handler, params, &sync_reader);
267 ASSERT_TRUE(controller.get());
268
269 // Wait for OnCreated() to be called.
270 event.Wait();
271
272 ASSERT_FALSE(play_event.IsSignaled());
273 controller->Play();
274 play_event.Wait();
275
276 // Force a state change and wait for the stream to come back to playing state.
277 play_event.Reset();
278 audio_manager->GetMessageLoop()->PostTask(FROM_HERE,
279 base::Bind(&AudioOutputController::OnDeviceChange, controller));
280 play_event.Wait();
281
282 // Now stop the controller.
283 CloseAudioController(controller);
284 } 357 }
285 358
286 } // namespace media 359 } // namespace media
OLDNEW
« media/audio/audio_output_controller.cc ('K') | « media/audio/audio_output_controller.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698