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 17 matching lines...) Expand all Loading... |
28 | 28 |
29 namespace media { | 29 namespace media { |
30 | 30 |
31 namespace { | 31 namespace { |
32 | 32 |
33 class MockRenderCallback : public AudioRendererSink::RenderCallback { | 33 class MockRenderCallback : public AudioRendererSink::RenderCallback { |
34 public: | 34 public: |
35 MockRenderCallback() {} | 35 MockRenderCallback() {} |
36 virtual ~MockRenderCallback() {} | 36 virtual ~MockRenderCallback() {} |
37 | 37 |
38 MOCK_METHOD2(Render, int(AudioBus* audio_bus, int audio_delay_milliseconds)); | 38 MOCK_METHOD2(Render, int(AudioBus* dest, int audio_delay_milliseconds)); |
| 39 MOCK_METHOD3(RenderIO, void(AudioBus* source, |
| 40 AudioBus* dest, |
| 41 int audio_delay_milliseconds)); |
39 MOCK_METHOD0(OnRenderError, void()); | 42 MOCK_METHOD0(OnRenderError, void()); |
40 }; | 43 }; |
41 | 44 |
42 class MockAudioOutputIPC : public AudioOutputIPC { | 45 class MockAudioOutputIPC : public AudioOutputIPC { |
43 public: | 46 public: |
44 MockAudioOutputIPC() {} | 47 MockAudioOutputIPC() {} |
45 virtual ~MockAudioOutputIPC() {} | 48 virtual ~MockAudioOutputIPC() {} |
46 | 49 |
47 MOCK_METHOD1(AddDelegate, int(AudioOutputIPCDelegate* delegate)); | 50 MOCK_METHOD1(AddDelegate, int(AudioOutputIPCDelegate* delegate)); |
48 MOCK_METHOD1(RemoveDelegate, void(int stream_id)); | 51 MOCK_METHOD1(RemoveDelegate, void(int stream_id)); |
49 | 52 |
50 MOCK_METHOD2(CreateStream, | 53 MOCK_METHOD3(CreateStream, |
51 void(int stream_id, const AudioParameters& params)); | 54 void(int stream_id, const AudioParameters& params, int input_channels)); |
52 MOCK_METHOD1(PlayStream, void(int stream_id)); | 55 MOCK_METHOD1(PlayStream, void(int stream_id)); |
53 MOCK_METHOD1(CloseStream, void(int stream_id)); | 56 MOCK_METHOD1(CloseStream, void(int stream_id)); |
54 MOCK_METHOD2(SetVolume, void(int stream_id, double volume)); | 57 MOCK_METHOD2(SetVolume, void(int stream_id, double volume)); |
55 MOCK_METHOD1(PauseStream, void(int stream_id)); | 58 MOCK_METHOD1(PauseStream, void(int stream_id)); |
56 MOCK_METHOD1(FlushStream, void(int stream_id)); | 59 MOCK_METHOD1(FlushStream, void(int stream_id)); |
57 }; | 60 }; |
58 | 61 |
59 // Creates a copy of a SyncSocket handle that we can give to AudioOutputDevice. | 62 // Creates a copy of a SyncSocket handle that we can give to AudioOutputDevice. |
60 // On Windows this means duplicating the pipe handle so that AudioOutputDevice | 63 // On Windows this means duplicating the pipe handle so that AudioOutputDevice |
61 // can call CloseHandle() (since ownership has been transferred), but on other | 64 // can call CloseHandle() (since ownership has been transferred), but on other |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
96 stream_id_(-1) { | 99 stream_id_(-1) { |
97 } | 100 } |
98 | 101 |
99 ~AudioOutputDeviceTest() {} | 102 ~AudioOutputDeviceTest() {} |
100 | 103 |
101 AudioOutputDevice* CreateAudioDevice() { | 104 AudioOutputDevice* CreateAudioDevice() { |
102 return new AudioOutputDevice( | 105 return new AudioOutputDevice( |
103 &audio_output_ipc_, io_loop_.message_loop_proxy()); | 106 &audio_output_ipc_, io_loop_.message_loop_proxy()); |
104 } | 107 } |
105 | 108 |
| 109 void TestCreateStream(bool synchronized_io); |
| 110 |
106 void set_stream_id(int stream_id) { stream_id_ = stream_id; } | 111 void set_stream_id(int stream_id) { stream_id_ = stream_id; } |
107 | 112 |
108 protected: | 113 protected: |
109 // Used to clean up TLS pointers that the test(s) will initialize. | 114 // Used to clean up TLS pointers that the test(s) will initialize. |
110 // Must remain the first member of this class. | 115 // Must remain the first member of this class. |
111 base::ShadowingAtExitManager at_exit_manager_; | 116 base::ShadowingAtExitManager at_exit_manager_; |
112 MessageLoopForIO io_loop_; | 117 MessageLoopForIO io_loop_; |
113 const AudioParameters default_audio_parameters_; | 118 const AudioParameters default_audio_parameters_; |
114 MockRenderCallback callback_; | 119 MockRenderCallback callback_; |
115 MockAudioOutputIPC audio_output_ipc_; | 120 MockAudioOutputIPC audio_output_ipc_; |
116 int stream_id_; | 121 int stream_id_; |
117 }; | 122 }; |
118 | 123 |
119 // The simplest test for AudioOutputDevice. Used to test construction of | 124 // The simplest test for AudioOutputDevice. Used to test construction of |
120 // AudioOutputDevice and that the runtime environment is set up correctly. | 125 // AudioOutputDevice and that the runtime environment is set up correctly. |
121 TEST_F(AudioOutputDeviceTest, Initialize) { | 126 TEST_F(AudioOutputDeviceTest, Initialize) { |
122 scoped_refptr<AudioOutputDevice> audio_device(CreateAudioDevice()); | 127 scoped_refptr<AudioOutputDevice> audio_device(CreateAudioDevice()); |
123 audio_device->Initialize(default_audio_parameters_, &callback_); | 128 audio_device->Initialize(default_audio_parameters_, &callback_); |
124 io_loop_.RunAllPending(); | 129 io_loop_.RunAllPending(); |
125 } | 130 } |
126 | 131 |
| 132 // Similar to Initialize() test, but using synchronized I/O. |
| 133 TEST_F(AudioOutputDeviceTest, InitializeIO) { |
| 134 scoped_refptr<AudioOutputDevice> audio_device(CreateAudioDevice()); |
| 135 const int input_channels = 2; // test stereo synchronized input |
| 136 audio_device->InitializeIO(default_audio_parameters_, |
| 137 input_channels, |
| 138 &callback_); |
| 139 io_loop_.RunAllPending(); |
| 140 } |
| 141 |
127 // Calls Start() followed by an immediate Stop() and check for the basic message | 142 // Calls Start() followed by an immediate Stop() and check for the basic message |
128 // filter messages being sent in that case. | 143 // filter messages being sent in that case. |
129 TEST_F(AudioOutputDeviceTest, StartStop) { | 144 TEST_F(AudioOutputDeviceTest, StartStop) { |
130 scoped_refptr<AudioOutputDevice> audio_device(CreateAudioDevice()); | 145 scoped_refptr<AudioOutputDevice> audio_device(CreateAudioDevice()); |
131 audio_device->Initialize(default_audio_parameters_, &callback_); | 146 audio_device->Initialize(default_audio_parameters_, &callback_); |
132 | 147 |
133 EXPECT_CALL(audio_output_ipc_, AddDelegate(audio_device.get())) | 148 EXPECT_CALL(audio_output_ipc_, AddDelegate(audio_device.get())) |
134 .WillOnce(Return(1)); | 149 .WillOnce(Return(1)); |
135 EXPECT_CALL(audio_output_ipc_, RemoveDelegate(1)).WillOnce(Return()); | 150 EXPECT_CALL(audio_output_ipc_, RemoveDelegate(1)).WillOnce(Return()); |
136 | 151 |
137 audio_device->Start(); | 152 audio_device->Start(); |
138 audio_device->Stop(); | 153 audio_device->Stop(); |
139 | 154 |
140 EXPECT_CALL(audio_output_ipc_, CreateStream(_, _)); | 155 EXPECT_CALL(audio_output_ipc_, CreateStream(_, _, _)); |
141 EXPECT_CALL(audio_output_ipc_, CloseStream(_)); | 156 EXPECT_CALL(audio_output_ipc_, CloseStream(_)); |
142 | 157 |
143 io_loop_.RunAllPending(); | 158 io_loop_.RunAllPending(); |
144 } | 159 } |
145 | 160 |
146 // Starts an audio stream, creates a shared memory section + SyncSocket pair | 161 // Starts an audio stream, creates a shared memory section + SyncSocket pair |
147 // that AudioOutputDevice must use for audio data. It then sends a request for | 162 // that AudioOutputDevice must use for audio data. It then sends a request for |
148 // a single audio packet and quits when the packet has been sent. | 163 // a single audio packet and quits when the packet has been sent. |
149 TEST_F(AudioOutputDeviceTest, CreateStream) { | 164 void AudioOutputDeviceTest::TestCreateStream(bool synchronized_io) { |
| 165 int input_channels = synchronized_io ? 2 : 0; |
| 166 |
150 scoped_refptr<AudioOutputDevice> audio_device(CreateAudioDevice()); | 167 scoped_refptr<AudioOutputDevice> audio_device(CreateAudioDevice()); |
151 audio_device->Initialize(default_audio_parameters_, &callback_); | 168 if (synchronized_io) { |
| 169 // Request output and synchronized input. |
| 170 audio_device->InitializeIO(default_audio_parameters_, |
| 171 input_channels, |
| 172 &callback_); |
| 173 } else { |
| 174 // Output only. |
| 175 audio_device->Initialize(default_audio_parameters_, &callback_); |
| 176 } |
152 | 177 |
153 EXPECT_CALL(audio_output_ipc_, AddDelegate(audio_device.get())) | 178 EXPECT_CALL(audio_output_ipc_, AddDelegate(audio_device.get())) |
154 .WillOnce(Return(1)); | 179 .WillOnce(Return(1)); |
155 EXPECT_CALL(audio_output_ipc_, RemoveDelegate(1)).WillOnce(Return()); | 180 EXPECT_CALL(audio_output_ipc_, RemoveDelegate(1)).WillOnce(Return()); |
156 | 181 |
157 audio_device->Start(); | 182 audio_device->Start(); |
158 | 183 |
159 EXPECT_CALL(audio_output_ipc_, CreateStream(_, _)) | 184 EXPECT_CALL(audio_output_ipc_, CreateStream(_, _, _)) |
160 .WillOnce(WithArgs<0>( | 185 .WillOnce(WithArgs<0>( |
161 Invoke(this, &AudioOutputDeviceTest::set_stream_id))); | 186 Invoke(this, &AudioOutputDeviceTest::set_stream_id))); |
162 | 187 |
163 | 188 |
164 EXPECT_EQ(stream_id_, -1); | 189 EXPECT_EQ(stream_id_, -1); |
165 io_loop_.RunAllPending(); | 190 io_loop_.RunAllPending(); |
166 | 191 |
167 // OnCreateStream() must have been called and we should have a valid | 192 // OnCreateStream() must have been called and we should have a valid |
168 // stream id. | 193 // stream id. |
169 ASSERT_NE(stream_id_, -1); | 194 ASSERT_NE(stream_id_, -1); |
170 | 195 |
| 196 // Calculate output and input memory size. |
| 197 int output_memory_size = |
| 198 AudioBus::CalculateMemorySize(default_audio_parameters_); |
| 199 |
| 200 int frames = default_audio_parameters_.frames_per_buffer(); |
| 201 int input_memory_size = |
| 202 AudioBus::CalculateMemorySize(input_channels, frames); |
| 203 |
| 204 int io_buffer_size = output_memory_size + input_memory_size; |
| 205 |
171 // 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 |
172 // AudioOutputDevice and its browser side counter part includes a bit more | 207 // AudioOutputDevice and its browser side counter part includes a bit more |
173 // than just the audio data, so we must call TotalSharedMemorySizeInBytes() | 208 // than just the audio data, so we must call TotalSharedMemorySizeInBytes() |
174 // to get the actual size needed to fit the audio data plus the extra data. | 209 // to get the actual size needed to fit the audio data plus the extra data. |
175 int memory_size = TotalSharedMemorySizeInBytes( | 210 int memory_size = TotalSharedMemorySizeInBytes(io_buffer_size); |
176 AudioBus::CalculateMemorySize(default_audio_parameters_)); | 211 |
177 SharedMemory shared_memory; | 212 SharedMemory shared_memory; |
178 ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(memory_size)); | 213 ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(memory_size)); |
179 memset(shared_memory.memory(), 0xff, memory_size); | 214 memset(shared_memory.memory(), 0xff, memory_size); |
180 | 215 |
181 CancelableSyncSocket browser_socket, renderer_socket; | 216 CancelableSyncSocket browser_socket, renderer_socket; |
182 ASSERT_TRUE(CancelableSyncSocket::CreatePair(&browser_socket, | 217 ASSERT_TRUE(CancelableSyncSocket::CreatePair(&browser_socket, |
183 &renderer_socket)); | 218 &renderer_socket)); |
184 | 219 |
185 // Create duplicates of the handles we pass to AudioOutputDevice since | 220 // Create duplicates of the handles we pass to AudioOutputDevice since |
186 // ownership will be transferred and AudioOutputDevice is responsible for | 221 // ownership will be transferred and AudioOutputDevice is responsible for |
(...skipping 13 matching lines...) Expand all Loading... |
200 .WillOnce(SendPendingBytes(&browser_socket, memory_size)); | 235 .WillOnce(SendPendingBytes(&browser_socket, memory_size)); |
201 | 236 |
202 // 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 |
203 // of frames written to the memory section. | 238 // of frames written to the memory section. |
204 // 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 |
205 // know (without using a sleep loop!) when the AudioOutputDevice has finished | 240 // know (without using a sleep loop!) when the AudioOutputDevice has finished |
206 // writing the interleaved audio data into the shared memory section. | 241 // writing the interleaved audio data into the shared memory section. |
207 // 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 |
208 // of success and quit the loop. | 243 // of success and quit the loop. |
209 | 244 |
210 const int kNumberOfFramesToProcess = 0; | 245 if (synchronized_io) { |
211 | 246 // For synchronized I/O, we expect RenderIO(). |
212 EXPECT_CALL(callback_, Render(_, _)) | 247 EXPECT_CALL(callback_, RenderIO(_, _, _)) |
213 .WillOnce(DoAll( | 248 .WillOnce(QuitLoop(io_loop_.message_loop_proxy())); |
214 QuitLoop(io_loop_.message_loop_proxy()), | 249 } else { |
215 Return(kNumberOfFramesToProcess))); | 250 // For output only we expect Render(). |
| 251 const int kNumberOfFramesToProcess = 0; |
| 252 EXPECT_CALL(callback_, Render(_, _)) |
| 253 .WillOnce(DoAll( |
| 254 QuitLoop(io_loop_.message_loop_proxy()), |
| 255 Return(kNumberOfFramesToProcess))); |
| 256 } |
216 | 257 |
217 audio_device->OnStreamCreated(duplicated_memory_handle, audio_device_socket, | 258 audio_device->OnStreamCreated(duplicated_memory_handle, audio_device_socket, |
218 PacketSizeInBytes(memory_size)); | 259 PacketSizeInBytes(memory_size)); |
219 | 260 |
220 io_loop_.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), | 261 io_loop_.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), |
221 TestTimeouts::action_timeout()); | 262 TestTimeouts::action_timeout()); |
222 io_loop_.Run(); | 263 io_loop_.Run(); |
223 | 264 |
224 // Close the stream sequence. | 265 // Close the stream sequence. |
225 EXPECT_CALL(audio_output_ipc_, CloseStream(stream_id_)); | 266 EXPECT_CALL(audio_output_ipc_, CloseStream(stream_id_)); |
226 | 267 |
227 audio_device->Stop(); | 268 audio_device->Stop(); |
228 io_loop_.RunAllPending(); | 269 io_loop_.RunAllPending(); |
229 } | 270 } |
230 | 271 |
| 272 // Full test with output only. |
| 273 TEST_F(AudioOutputDeviceTest, CreateStream) { |
| 274 TestCreateStream(false); |
| 275 } |
| 276 |
| 277 // Same as CreateStream() test, but also tests synchronized I/O. |
| 278 TEST_F(AudioOutputDeviceTest, CreateStreamWithInput) { |
| 279 TestCreateStream(true); |
| 280 } |
| 281 |
231 } // namespace media. | 282 } // namespace media. |
OLD | NEW |