OLD | NEW |
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 <vector> | 5 #include <vector> |
6 | 6 |
7 #include "base/at_exit.h" | 7 #include "base/at_exit.h" |
8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
9 #include "base/process_util.h" | 9 #include "base/process_util.h" |
10 #include "base/shared_memory.h" | 10 #include "base/shared_memory.h" |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 ACTION_P2(SendPendingBytes, socket, pending_bytes) { | 104 ACTION_P2(SendPendingBytes, socket, pending_bytes) { |
105 socket->Send(&pending_bytes, sizeof(pending_bytes)); | 105 socket->Send(&pending_bytes, sizeof(pending_bytes)); |
106 } | 106 } |
107 | 107 |
108 // Used to terminate a loop from a different thread than the loop belongs to. | 108 // Used to terminate a loop from a different thread than the loop belongs to. |
109 // |loop| should be a MessageLoopProxy. | 109 // |loop| should be a MessageLoopProxy. |
110 ACTION_P(QuitLoop, loop) { | 110 ACTION_P(QuitLoop, loop) { |
111 loop->PostTask(FROM_HERE, MessageLoop::QuitClosure()); | 111 loop->PostTask(FROM_HERE, MessageLoop::QuitClosure()); |
112 } | 112 } |
113 | 113 |
| 114 // Zeros out |number_of_frames| in all channel buffers pointed to by |
| 115 // the |audio_data| vector. |
| 116 void ZeroAudioData(int number_of_frames, |
| 117 const std::vector<float*>& audio_data) { |
| 118 std::vector<float*>::const_iterator it = audio_data.begin(); |
| 119 for (; it != audio_data.end(); ++it) { |
| 120 float* channel = *it; |
| 121 for (int j = 0; j < number_of_frames; ++j) { |
| 122 channel[j] = 0.0f; |
| 123 } |
| 124 } |
| 125 } |
| 126 |
114 } // namespace. | 127 } // namespace. |
115 | 128 |
116 class AudioDeviceTest : public testing::Test { | 129 class AudioDeviceTest : public testing::Test { |
117 public: | 130 public: |
118 AudioDeviceTest() | 131 AudioDeviceTest() |
119 : default_audio_parameters_(media::AudioParameters::AUDIO_PCM_LINEAR, | 132 : default_audio_parameters_(media::AudioParameters::AUDIO_PCM_LINEAR, |
120 CHANNEL_LAYOUT_STEREO, | 133 CHANNEL_LAYOUT_STEREO, |
121 48000, 16, 1024), | 134 48000, 16, 1024), |
122 stream_id_(-1) { | 135 stream_id_(-1) { |
123 } | 136 } |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 // stream id. | 203 // stream id. |
191 ASSERT_NE(stream_id_, -1); | 204 ASSERT_NE(stream_id_, -1); |
192 | 205 |
193 // This is where it gets a bit hacky. The shared memory contract between | 206 // This is where it gets a bit hacky. The shared memory contract between |
194 // AudioDevice and its browser side counter part includes a bit more than | 207 // AudioDevice and its browser side counter part includes a bit more than |
195 // just the audio data, so we must call TotalSharedMemorySizeInBytes() to get | 208 // just the audio data, so we must call TotalSharedMemorySizeInBytes() to get |
196 // the actual size needed to fit the audio data plus the extra data. | 209 // the actual size needed to fit the audio data plus the extra data. |
197 int memory_size = media::TotalSharedMemorySizeInBytes( | 210 int memory_size = media::TotalSharedMemorySizeInBytes( |
198 default_audio_parameters_.GetBytesPerBuffer()); | 211 default_audio_parameters_.GetBytesPerBuffer()); |
199 SharedMemory shared_memory; | 212 SharedMemory shared_memory; |
200 ASSERT_TRUE(shared_memory.CreateAnonymous(memory_size)); | 213 ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(memory_size)); |
| 214 // Initialize the memory. |
| 215 memset(shared_memory.memory(), 0xff, memory_size); |
201 | 216 |
202 CancelableSyncSocket browser_socket, renderer_socket; | 217 CancelableSyncSocket browser_socket, renderer_socket; |
203 ASSERT_TRUE(CancelableSyncSocket::CreatePair(&browser_socket, | 218 ASSERT_TRUE(CancelableSyncSocket::CreatePair(&browser_socket, |
204 &renderer_socket)); | 219 &renderer_socket)); |
205 | 220 |
206 // Create duplicates of the handles we pass to AudioDevice since ownership | 221 // Create duplicates of the handles we pass to AudioDevice since ownership |
207 // will be transferred and AudioDevice is responsible for freeing. | 222 // will be transferred and AudioDevice is responsible for freeing. |
208 SyncSocket::Handle audio_device_socket = SyncSocket::kInvalidHandle; | 223 SyncSocket::Handle audio_device_socket = SyncSocket::kInvalidHandle; |
209 ASSERT_TRUE(DuplicateSocketHandle(renderer_socket.handle(), | 224 ASSERT_TRUE(DuplicateSocketHandle(renderer_socket.handle(), |
210 &audio_device_socket)); | 225 &audio_device_socket)); |
211 base::SharedMemoryHandle duplicated_memory_handle; | 226 base::SharedMemoryHandle duplicated_memory_handle; |
212 ASSERT_TRUE(shared_memory.ShareToProcess(base::GetCurrentProcessHandle(), | 227 ASSERT_TRUE(shared_memory.ShareToProcess(base::GetCurrentProcessHandle(), |
213 &duplicated_memory_handle)); | 228 &duplicated_memory_handle)); |
214 | 229 |
215 // We should get a 'play' notification when we call OnStreamCreated(). | 230 // We should get a 'play' notification when we call OnStreamCreated(). |
216 // Respond by asking for some audio data. This should ask our callback | 231 // Respond by asking for some audio data. This should ask our callback |
217 // to provide some audio data that AudioDevice then writes into the shared | 232 // to provide some audio data that AudioDevice then writes into the shared |
218 // memory section. | 233 // memory section. |
219 EXPECT_CALL(*audio_message_filter_, OnPlayStream(stream_id_)) | 234 EXPECT_CALL(*audio_message_filter_, OnPlayStream(stream_id_)) |
220 .WillOnce(SendPendingBytes(&browser_socket, memory_size)); | 235 .WillOnce(SendPendingBytes(&browser_socket, memory_size)); |
221 | 236 |
222 // We expect calls to our audio renderer callback, which returns the number | 237 // We expect calls to our audio renderer callback, which returns the number |
223 // of frames written to the memory section. | 238 // of frames written to the memory section. |
224 // Here's the second place where it gets hacky: There's no way for us to | 239 // Here's the second place where it gets hacky: There's no way for us to |
225 // know (without using a sleep loop!) when the AudioDevice has finished | 240 // know (without using a sleep loop!) when the AudioDevice has finished |
226 // writing the interleaved audio data into the shared memory section. | 241 // writing the interleaved audio data into the shared memory section. |
227 // So, for the sake of this test, we consider the call to Render a sign | 242 // So, for the sake of this test, we consider the call to Render a sign |
228 // of success and quit the loop. | 243 // of success and quit the loop. |
| 244 |
| 245 // A note on the call to ZeroAudioData(): |
| 246 // Valgrind caught a bug in AudioDevice::AudioThreadCallback::Process() |
| 247 // whereby we always interleaved all the frames in the buffer regardless |
| 248 // of how many were actually rendered. So to keep the benefits of that |
| 249 // test, we explicitly pass 0 in here as the number of frames to |
| 250 // ZeroAudioData(). Other tests might want to pass the requested number |
| 251 // by using WithArgs<1, 0>(Invoke(&ZeroAudioData)) and set the return |
| 252 // value accordingly. |
| 253 const int kNumberOfFramesToProcess = 0; |
| 254 |
229 EXPECT_CALL(callback_, Render(_, _, _)) | 255 EXPECT_CALL(callback_, Render(_, _, _)) |
230 .WillOnce(DoAll( | 256 .WillOnce(DoAll( |
| 257 WithArgs<0>(Invoke( |
| 258 testing::CreateFunctor(&ZeroAudioData, |
| 259 kNumberOfFramesToProcess))), |
231 QuitLoop(io_loop_.message_loop_proxy()), | 260 QuitLoop(io_loop_.message_loop_proxy()), |
232 Return(1))); | 261 Return(kNumberOfFramesToProcess))); |
233 | 262 |
234 audio_device->OnStreamCreated(duplicated_memory_handle, audio_device_socket, | 263 audio_device->OnStreamCreated(duplicated_memory_handle, audio_device_socket, |
235 memory_size); | 264 memory_size); |
236 | 265 |
237 io_loop_.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), | 266 io_loop_.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), |
238 TestTimeouts::action_timeout()); | 267 TestTimeouts::action_timeout()); |
239 io_loop_.Run(); | 268 io_loop_.Run(); |
240 | 269 |
241 // Close the stream sequence. | 270 // Close the stream sequence. |
242 | 271 |
243 EXPECT_CALL(*audio_message_filter_, OnCloseStream(stream_id_)); | 272 EXPECT_CALL(*audio_message_filter_, OnCloseStream(stream_id_)); |
244 | 273 |
245 audio_device->Stop(); | 274 audio_device->Stop(); |
246 io_loop_.RunAllPending(); | 275 io_loop_.RunAllPending(); |
247 } | 276 } |
OLD | NEW |