| 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 |