OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/bind.h" | 5 #include "base/bind.h" |
6 #include "base/environment.h" | 6 #include "base/environment.h" |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/synchronization/waitable_event.h" | 9 #include "base/synchronization/waitable_event.h" |
10 #include "media/audio/audio_output_controller.h" | 10 #include "media/audio/audio_output_controller.h" |
11 #include "testing/gmock/include/gmock/gmock.h" | 11 #include "testing/gmock/include/gmock/gmock.h" |
12 #include "testing/gtest/include/gtest/gtest.h" | 12 #include "testing/gtest/include/gtest/gtest.h" |
13 | 13 |
| 14 // TODO(vrk): These tests need to be rewritten! (crbug.com/112500) |
| 15 |
14 using ::testing::_; | 16 using ::testing::_; |
15 using ::testing::AtLeast; | 17 using ::testing::AtLeast; |
16 using ::testing::DoAll; | 18 using ::testing::DoAll; |
17 using ::testing::Exactly; | 19 using ::testing::Exactly; |
18 using ::testing::InvokeWithoutArgs; | 20 using ::testing::InvokeWithoutArgs; |
19 using ::testing::NotNull; | 21 using ::testing::NotNull; |
20 using ::testing::Return; | 22 using ::testing::Return; |
21 | 23 |
22 static const int kSampleRate = AudioParameters::kAudioCDSampleRate; | 24 static const int kSampleRate = AudioParameters::kAudioCDSampleRate; |
23 static const int kBitsPerSample = 16; | 25 static const int kBitsPerSample = 16; |
24 static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO; | 26 static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO; |
25 static const int kSamplesPerPacket = kSampleRate / 10; | 27 static const int kSamplesPerPacket = kSampleRate / 10; |
26 static const int kHardwareBufferSize = kSamplesPerPacket * | 28 static const int kHardwareBufferSize = kSamplesPerPacket * |
27 ChannelLayoutToChannelCount(kChannelLayout) * kBitsPerSample / 8; | 29 ChannelLayoutToChannelCount(kChannelLayout) * kBitsPerSample / 8; |
28 static const int kBufferCapacity = 3 * kHardwareBufferSize; | |
29 | 30 |
30 namespace media { | 31 namespace media { |
31 | 32 |
32 class MockAudioOutputControllerEventHandler | 33 class MockAudioOutputControllerEventHandler |
33 : public AudioOutputController::EventHandler { | 34 : public AudioOutputController::EventHandler { |
34 public: | 35 public: |
35 MockAudioOutputControllerEventHandler() {} | 36 MockAudioOutputControllerEventHandler() {} |
36 | 37 |
37 MOCK_METHOD1(OnCreated, void(AudioOutputController* controller)); | 38 MOCK_METHOD1(OnCreated, void(AudioOutputController* controller)); |
38 MOCK_METHOD1(OnPlaying, void(AudioOutputController* controller)); | 39 MOCK_METHOD1(OnPlaying, void(AudioOutputController* controller)); |
39 MOCK_METHOD1(OnPaused, void(AudioOutputController* controller)); | 40 MOCK_METHOD1(OnPaused, void(AudioOutputController* controller)); |
40 MOCK_METHOD2(OnError, void(AudioOutputController* controller, | 41 MOCK_METHOD2(OnError, void(AudioOutputController* controller, |
41 int error_code)); | 42 int error_code)); |
42 MOCK_METHOD2(OnMoreData, void(AudioOutputController* controller, | |
43 AudioBuffersState buffers_state)); | |
44 | 43 |
45 private: | 44 private: |
46 DISALLOW_COPY_AND_ASSIGN(MockAudioOutputControllerEventHandler); | 45 DISALLOW_COPY_AND_ASSIGN(MockAudioOutputControllerEventHandler); |
47 }; | 46 }; |
48 | 47 |
49 class MockAudioOutputControllerSyncReader | 48 class MockAudioOutputControllerSyncReader |
50 : public AudioOutputController::SyncReader { | 49 : public AudioOutputController::SyncReader { |
51 public: | 50 public: |
52 MockAudioOutputControllerSyncReader() {} | 51 MockAudioOutputControllerSyncReader() {} |
53 | 52 |
(...skipping 20 matching lines...) Expand all Loading... |
74 | 73 |
75 TEST(AudioOutputControllerTest, CreateAndClose) { | 74 TEST(AudioOutputControllerTest, CreateAndClose) { |
76 scoped_refptr<AudioManager> audio_manager(AudioManager::Create()); | 75 scoped_refptr<AudioManager> audio_manager(AudioManager::Create()); |
77 if (!audio_manager->HasAudioOutputDevices()) | 76 if (!audio_manager->HasAudioOutputDevices()) |
78 return; | 77 return; |
79 | 78 |
80 MockAudioOutputControllerEventHandler event_handler; | 79 MockAudioOutputControllerEventHandler event_handler; |
81 | 80 |
82 EXPECT_CALL(event_handler, OnCreated(NotNull())) | 81 EXPECT_CALL(event_handler, OnCreated(NotNull())) |
83 .Times(1); | 82 .Times(1); |
84 EXPECT_CALL(event_handler, OnMoreData(NotNull(), _)); | 83 |
| 84 MockAudioOutputControllerSyncReader sync_reader; |
| 85 EXPECT_CALL(sync_reader, Close()); |
85 | 86 |
86 AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, | 87 AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, |
87 kSampleRate, kBitsPerSample, kSamplesPerPacket); | 88 kSampleRate, kBitsPerSample, kSamplesPerPacket); |
88 scoped_refptr<AudioOutputController> controller = | 89 scoped_refptr<AudioOutputController> controller = |
89 AudioOutputController::Create(audio_manager, &event_handler, params, | 90 AudioOutputController::Create( |
90 kBufferCapacity); | 91 audio_manager, &event_handler, params, &sync_reader); |
91 ASSERT_TRUE(controller.get()); | 92 ASSERT_TRUE(controller.get()); |
92 | 93 |
93 // Close the controller immediately. | 94 // Close the controller immediately. |
94 CloseAudioController(controller); | 95 CloseAudioController(controller); |
95 } | 96 } |
96 | 97 |
97 TEST(AudioOutputControllerTest, PlayAndClose) { | |
98 scoped_refptr<AudioManager> audio_manager(AudioManager::Create()); | |
99 if (!audio_manager->HasAudioOutputDevices()) | |
100 return; | |
101 | |
102 MockAudioOutputControllerEventHandler event_handler; | |
103 base::WaitableEvent event(false, false); | |
104 | |
105 // If OnCreated is called then signal the event. | |
106 EXPECT_CALL(event_handler, OnCreated(NotNull())) | |
107 .WillOnce(SignalEvent(&event)); | |
108 | |
109 // OnPlaying() will be called only once. | |
110 EXPECT_CALL(event_handler, OnPlaying(NotNull())) | |
111 .Times(Exactly(1)); | |
112 | |
113 // If OnMoreData is called enough then signal the event. | |
114 EXPECT_CALL(event_handler, OnMoreData(NotNull(), _)) | |
115 .Times(AtLeast(10)) | |
116 .WillRepeatedly(SignalEvent(&event)); | |
117 | |
118 AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, | |
119 kSampleRate, kBitsPerSample, kSamplesPerPacket); | |
120 scoped_refptr<AudioOutputController> controller = | |
121 AudioOutputController::Create(audio_manager, &event_handler, params, | |
122 kBufferCapacity); | |
123 ASSERT_TRUE(controller.get()); | |
124 | |
125 // Wait for OnCreated() to be called. | |
126 event.Wait(); | |
127 | |
128 controller->Play(); | |
129 | |
130 // Wait until the date is requested at least 10 times. | |
131 for (int i = 0; i < 10; i++) { | |
132 event.Wait(); | |
133 uint8 buf[1]; | |
134 controller->EnqueueData(buf, 0); | |
135 } | |
136 | |
137 // Now stop the controller. | |
138 CloseAudioController(controller); | |
139 } | |
140 | |
141 TEST(AudioOutputControllerTest, PlayAndCloseLowLatency) { | |
142 scoped_refptr<AudioManager> audio_manager(AudioManager::Create()); | |
143 if (!audio_manager->HasAudioOutputDevices()) | |
144 return; | |
145 | |
146 MockAudioOutputControllerEventHandler event_handler; | |
147 base::WaitableEvent event(false, false); | |
148 | |
149 // If OnCreated is called then signal the event. | |
150 EXPECT_CALL(event_handler, OnCreated(NotNull())) | |
151 .WillOnce(SignalEvent(&event)); | |
152 | |
153 // OnPlaying() will be called only once. | |
154 EXPECT_CALL(event_handler, OnPlaying(NotNull())) | |
155 .Times(Exactly(1)); | |
156 | |
157 MockAudioOutputControllerSyncReader sync_reader; | |
158 EXPECT_CALL(sync_reader, UpdatePendingBytes(_)) | |
159 .Times(AtLeast(10)); | |
160 EXPECT_CALL(sync_reader, DataReady()) | |
161 .WillOnce(Return(false)) | |
162 .WillOnce(Return(false)) | |
163 .WillRepeatedly(Return(true)); | |
164 EXPECT_CALL(sync_reader, Read(_, kHardwareBufferSize)) | |
165 .Times(AtLeast(10)) | |
166 .WillRepeatedly(DoAll(SignalEvent(&event), | |
167 Return(4))); | |
168 EXPECT_CALL(sync_reader, Close()); | |
169 | |
170 AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, | |
171 kSampleRate, kBitsPerSample, kSamplesPerPacket); | |
172 scoped_refptr<AudioOutputController> controller = | |
173 AudioOutputController::CreateLowLatency(audio_manager, | |
174 &event_handler, | |
175 params, | |
176 &sync_reader); | |
177 ASSERT_TRUE(controller.get()); | |
178 | |
179 // Wait for OnCreated() to be called. | |
180 event.Wait(); | |
181 | |
182 controller->Play(); | |
183 | |
184 // Wait until the date is requested at least 10 times. | |
185 for (int i = 0; i < 10; i++) { | |
186 event.Wait(); | |
187 uint8 buf[1]; | |
188 controller->EnqueueData(buf, 0); | |
189 } | |
190 | |
191 // Now stop the controller. | |
192 CloseAudioController(controller); | |
193 } | |
194 | |
195 TEST(AudioOutputControllerTest, PlayPauseClose) { | 98 TEST(AudioOutputControllerTest, PlayPauseClose) { |
196 scoped_refptr<AudioManager> audio_manager(AudioManager::Create()); | 99 scoped_refptr<AudioManager> audio_manager(AudioManager::Create()); |
197 if (!audio_manager->HasAudioOutputDevices()) | 100 if (!audio_manager->HasAudioOutputDevices()) |
198 return; | 101 return; |
199 | 102 |
200 MockAudioOutputControllerEventHandler event_handler; | 103 MockAudioOutputControllerEventHandler event_handler; |
201 base::WaitableEvent event(false, false); | 104 base::WaitableEvent event(false, false); |
202 base::WaitableEvent pause_event(false, false); | 105 base::WaitableEvent pause_event(false, false); |
203 | 106 |
204 // If OnCreated is called then signal the event. | 107 // If OnCreated is called then signal the event. |
205 EXPECT_CALL(event_handler, OnCreated(NotNull())) | 108 EXPECT_CALL(event_handler, OnCreated(NotNull())) |
206 .Times(Exactly(1)) | |
207 .WillOnce(InvokeWithoutArgs(&event, &base::WaitableEvent::Signal)); | |
208 | |
209 // OnPlaying() will be called only once. | |
210 EXPECT_CALL(event_handler, OnPlaying(NotNull())) | |
211 .Times(Exactly(1)); | |
212 | |
213 // If OnMoreData is called enough then signal the event. | |
214 EXPECT_CALL(event_handler, OnMoreData(NotNull(), _)) | |
215 .Times(AtLeast(10)) | |
216 .WillRepeatedly(SignalEvent(&event)); | |
217 | |
218 // And then OnPaused() will be called. | |
219 EXPECT_CALL(event_handler, OnPaused(NotNull())) | |
220 .Times(Exactly(1)) | |
221 .WillOnce(InvokeWithoutArgs(&pause_event, &base::WaitableEvent::Signal)); | |
222 | |
223 AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, | |
224 kSampleRate, kBitsPerSample, kSamplesPerPacket); | |
225 scoped_refptr<AudioOutputController> controller = | |
226 AudioOutputController::Create(audio_manager, &event_handler, params, | |
227 kBufferCapacity); | |
228 ASSERT_TRUE(controller.get()); | |
229 | |
230 // Wait for OnCreated() to be called. | |
231 event.Wait(); | |
232 | |
233 controller->Play(); | |
234 | |
235 // Wait until the date is requested at least 10 times. | |
236 for (int i = 0; i < 10; i++) { | |
237 event.Wait(); | |
238 uint8 buf[1]; | |
239 controller->EnqueueData(buf, 0); | |
240 } | |
241 | |
242 // And then wait for pause to complete. | |
243 ASSERT_FALSE(pause_event.IsSignaled()); | |
244 controller->Pause(); | |
245 pause_event.Wait(); | |
246 | |
247 // Now stop the controller. | |
248 CloseAudioController(controller); | |
249 } | |
250 | |
251 TEST(AudioOutputControllerTest, PlayPauseCloseLowLatency) { | |
252 scoped_refptr<AudioManager> audio_manager(AudioManager::Create()); | |
253 if (!audio_manager->HasAudioOutputDevices()) | |
254 return; | |
255 | |
256 MockAudioOutputControllerEventHandler event_handler; | |
257 base::WaitableEvent event(false, false); | |
258 base::WaitableEvent pause_event(false, false); | |
259 | |
260 // If OnCreated is called then signal the event. | |
261 EXPECT_CALL(event_handler, OnCreated(NotNull())) | |
262 .WillOnce(InvokeWithoutArgs(&event, &base::WaitableEvent::Signal)); | 109 .WillOnce(InvokeWithoutArgs(&event, &base::WaitableEvent::Signal)); |
263 | 110 |
264 // OnPlaying() will be called only once. | 111 // OnPlaying() will be called only once. |
265 EXPECT_CALL(event_handler, OnPlaying(NotNull())); | 112 EXPECT_CALL(event_handler, OnPlaying(NotNull())); |
266 | 113 |
267 MockAudioOutputControllerSyncReader sync_reader; | 114 MockAudioOutputControllerSyncReader sync_reader; |
268 EXPECT_CALL(sync_reader, UpdatePendingBytes(_)) | 115 EXPECT_CALL(sync_reader, UpdatePendingBytes(_)) |
269 .Times(AtLeast(2)); | 116 .Times(AtLeast(2)); |
270 EXPECT_CALL(sync_reader, Read(_, kHardwareBufferSize)) | 117 EXPECT_CALL(sync_reader, Read(_, kHardwareBufferSize)) |
271 .WillRepeatedly(DoAll(SignalEvent(&event), | 118 .WillRepeatedly(DoAll(SignalEvent(&event), |
272 Return(4))); | 119 Return(4))); |
273 EXPECT_CALL(event_handler, OnPaused(NotNull())) | 120 EXPECT_CALL(event_handler, OnPaused(NotNull())) |
274 .WillOnce(InvokeWithoutArgs(&pause_event, &base::WaitableEvent::Signal)); | 121 .WillOnce(InvokeWithoutArgs(&pause_event, &base::WaitableEvent::Signal)); |
275 EXPECT_CALL(sync_reader, Close()); | 122 EXPECT_CALL(sync_reader, Close()); |
276 | 123 |
277 AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, | 124 AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, |
278 kSampleRate, kBitsPerSample, kSamplesPerPacket); | 125 kSampleRate, kBitsPerSample, kSamplesPerPacket); |
279 scoped_refptr<AudioOutputController> controller = | 126 scoped_refptr<AudioOutputController> controller = |
280 AudioOutputController::CreateLowLatency(audio_manager, | 127 AudioOutputController::Create( |
281 &event_handler, | 128 audio_manager, &event_handler, params, &sync_reader); |
282 params, | |
283 &sync_reader); | |
284 ASSERT_TRUE(controller.get()); | 129 ASSERT_TRUE(controller.get()); |
285 | 130 |
286 // Wait for OnCreated() to be called. | 131 // Wait for OnCreated() to be called. |
287 event.Wait(); | 132 event.Wait(); |
288 | 133 |
289 ASSERT_FALSE(pause_event.IsSignaled()); | 134 ASSERT_FALSE(pause_event.IsSignaled()); |
290 controller->Play(); | 135 controller->Play(); |
291 controller->Pause(); | 136 controller->Pause(); |
292 pause_event.Wait(); | 137 pause_event.Wait(); |
293 | 138 |
294 // Now stop the controller. | 139 // Now stop the controller. |
295 CloseAudioController(controller); | 140 CloseAudioController(controller); |
296 } | 141 } |
297 | 142 |
298 TEST(AudioOutputControllerTest, PlayPausePlay) { | |
299 scoped_refptr<AudioManager> audio_manager(AudioManager::Create()); | |
300 if (!audio_manager->HasAudioOutputDevices()) | |
301 return; | |
302 | |
303 MockAudioOutputControllerEventHandler event_handler; | |
304 base::WaitableEvent event(false, false); | |
305 base::WaitableEvent pause_event(false, false); | |
306 | |
307 // If OnCreated is called then signal the event. | |
308 EXPECT_CALL(event_handler, OnCreated(NotNull())) | |
309 .Times(Exactly(1)) | |
310 .WillOnce(InvokeWithoutArgs(&event, &base::WaitableEvent::Signal)); | |
311 | |
312 // OnPlaying() will be called only once. | |
313 EXPECT_CALL(event_handler, OnPlaying(NotNull())) | |
314 .Times(Exactly(1)) | |
315 .RetiresOnSaturation(); | |
316 | |
317 // If OnMoreData() is called enough then signal the event. | |
318 EXPECT_CALL(event_handler, OnMoreData(NotNull(), _)) | |
319 .Times(AtLeast(1)) | |
320 .WillRepeatedly(SignalEvent(&event)); | |
321 | |
322 // And then OnPaused() will be called. | |
323 EXPECT_CALL(event_handler, OnPaused(NotNull())) | |
324 .Times(Exactly(1)) | |
325 .WillOnce(InvokeWithoutArgs(&pause_event, &base::WaitableEvent::Signal)); | |
326 | |
327 // OnPlaying() will be called only once. | |
328 EXPECT_CALL(event_handler, OnPlaying(NotNull())) | |
329 .Times(Exactly(1)) | |
330 .RetiresOnSaturation(); | |
331 | |
332 AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, | |
333 kSampleRate, kBitsPerSample, kSamplesPerPacket); | |
334 scoped_refptr<AudioOutputController> controller = | |
335 AudioOutputController::Create(audio_manager, &event_handler, params, | |
336 kBufferCapacity); | |
337 ASSERT_TRUE(controller.get()); | |
338 | |
339 // Wait for OnCreated() to be called. | |
340 event.Wait(); | |
341 | |
342 controller->Play(); | |
343 | |
344 // Wait until the date is requested at least 10 times. | |
345 for (int i = 0; i < 10; i++) { | |
346 event.Wait(); | |
347 uint8 buf[1]; | |
348 controller->EnqueueData(buf, 0); | |
349 } | |
350 | |
351 // And then wait for pause to complete. | |
352 ASSERT_FALSE(pause_event.IsSignaled()); | |
353 controller->Pause(); | |
354 pause_event.Wait(); | |
355 | |
356 // Then we play again. | |
357 controller->Play(); | |
358 | |
359 // Wait until the date is requested at least 10 times. | |
360 for (int i = 0; i < 10; i++) { | |
361 event.Wait(); | |
362 uint8 buf[1]; | |
363 controller->EnqueueData(buf, 0); | |
364 } | |
365 | |
366 // Now stop the controller. | |
367 CloseAudioController(controller); | |
368 } | |
369 | 143 |
370 TEST(AudioOutputControllerTest, HardwareBufferTooLarge) { | 144 TEST(AudioOutputControllerTest, HardwareBufferTooLarge) { |
371 scoped_refptr<AudioManager> audio_manager(AudioManager::Create()); | 145 scoped_refptr<AudioManager> audio_manager(AudioManager::Create()); |
372 if (!audio_manager->HasAudioOutputDevices()) | 146 if (!audio_manager->HasAudioOutputDevices()) |
373 return; | 147 return; |
374 | 148 |
375 // Create an audio device with a very large hardware buffer size. | 149 // Create an audio device with a very large hardware buffer size. |
376 MockAudioOutputControllerEventHandler event_handler; | 150 MockAudioOutputControllerEventHandler event_handler; |
| 151 |
| 152 MockAudioOutputControllerSyncReader sync_reader; |
377 AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, | 153 AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, |
378 kSampleRate, kBitsPerSample, | 154 kSampleRate, kBitsPerSample, |
379 kSamplesPerPacket * 1000); | 155 kSamplesPerPacket * 1000); |
380 scoped_refptr<AudioOutputController> controller = | 156 scoped_refptr<AudioOutputController> controller = |
381 AudioOutputController::Create(audio_manager, &event_handler, params, | 157 AudioOutputController::Create( |
382 kBufferCapacity); | 158 audio_manager, &event_handler, params, &sync_reader); |
383 | 159 |
384 // Use assert because we don't stop the device and assume we can't | 160 // Use assert because we don't stop the device and assume we can't |
385 // create one. | 161 // create one. |
386 ASSERT_FALSE(controller); | 162 ASSERT_FALSE(controller); |
387 } | 163 } |
388 | 164 |
389 TEST(AudioOutputControllerTest, CloseTwice) { | |
390 scoped_refptr<AudioManager> audio_manager(AudioManager::Create()); | |
391 if (!audio_manager->HasAudioOutputDevices()) | |
392 return; | |
393 | |
394 MockAudioOutputControllerEventHandler event_handler; | |
395 base::WaitableEvent event(false, false); | |
396 | |
397 // If OnCreated is called then signal the event. | |
398 EXPECT_CALL(event_handler, OnCreated(NotNull())) | |
399 .WillOnce(SignalEvent(&event)); | |
400 | |
401 // One OnMoreData() is expected. | |
402 EXPECT_CALL(event_handler, OnMoreData(NotNull(), _)) | |
403 .Times(AtLeast(1)) | |
404 .WillRepeatedly(SignalEvent(&event)); | |
405 | |
406 AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, | |
407 kSampleRate, kBitsPerSample, kSamplesPerPacket); | |
408 scoped_refptr<AudioOutputController> controller = | |
409 AudioOutputController::Create(audio_manager, &event_handler, params, | |
410 kBufferCapacity); | |
411 ASSERT_TRUE(controller.get()); | |
412 | |
413 // Wait for OnCreated() to be called. | |
414 event.Wait(); | |
415 | |
416 // Wait for OnMoreData() to be called. | |
417 event.Wait(); | |
418 | |
419 base::WaitableEvent closed_event_1(true, false); | |
420 controller->Close(base::Bind(&base::WaitableEvent::Signal, | |
421 base::Unretained(&closed_event_1))); | |
422 | |
423 base::WaitableEvent closed_event_2(true, false); | |
424 controller->Close(base::Bind(&base::WaitableEvent::Signal, | |
425 base::Unretained(&closed_event_2))); | |
426 | |
427 closed_event_1.Wait(); | |
428 closed_event_2.Wait(); | |
429 } | |
430 | |
431 } // namespace media | 165 } // namespace media |
OLD | NEW |