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

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

Issue 10830268: Allow audio system to handle synchronized low-latency audio I/O (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 3 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 | Annotate | Revision Log
« no previous file with comments | « media/audio/audio_output_device.cc ('k') | media/audio/audio_output_ipc.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) 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
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
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
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.
OLDNEW
« no previous file with comments | « media/audio/audio_output_device.cc ('k') | media/audio/audio_output_ipc.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698