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 "content/browser/renderer_host/media/video_capture_host.h" | 5 #include "content/browser/renderer_host/media/video_capture_host.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <map> | 9 #include <map> |
10 #include <memory> | 10 #include <memory> |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
77 MOCK_METHOD4(DeviceOpened, void(int render_frame_id, | 77 MOCK_METHOD4(DeviceOpened, void(int render_frame_id, |
78 int page_request_id, | 78 int page_request_id, |
79 const std::string& label, | 79 const std::string& label, |
80 const StreamDeviceInfo& device_info)); | 80 const StreamDeviceInfo& device_info)); |
81 MOCK_METHOD1(DevicesChanged, void(MediaStreamType type)); | 81 MOCK_METHOD1(DevicesChanged, void(MediaStreamType type)); |
82 | 82 |
83 private: | 83 private: |
84 DISALLOW_COPY_AND_ASSIGN(MockMediaStreamRequester); | 84 DISALLOW_COPY_AND_ASSIGN(MockMediaStreamRequester); |
85 }; | 85 }; |
86 | 86 |
87 class MockVideoCaptureHost : public VideoCaptureHost { | |
88 public: | |
89 MockVideoCaptureHost(MediaStreamManager* manager) | |
90 : VideoCaptureHost(manager) {} | |
91 | |
92 MOCK_METHOD4(OnNewBufferCreated, | |
93 void(int device_id, | |
94 base::SharedMemoryHandle handle, | |
95 int length, | |
96 int buffer_id)); | |
97 | |
98 private: | |
99 ~MockVideoCaptureHost() override {} | |
100 | |
101 bool Send(IPC::Message* message) override { | |
102 bool handled = true; | |
103 IPC_BEGIN_MESSAGE_MAP(MockVideoCaptureHost, *message) | |
104 IPC_MESSAGE_HANDLER(VideoCaptureMsg_NewBuffer, OnNewBufferCreated) | |
105 IPC_MESSAGE_UNHANDLED(handled = false) | |
106 IPC_END_MESSAGE_MAP() | |
107 EXPECT_TRUE(handled); | |
108 | |
109 delete message; | |
110 return true; | |
111 } | |
112 }; | |
113 | |
114 ACTION_P2(ExitMessageLoop, task_runner, quit_closure) { | 87 ACTION_P2(ExitMessageLoop, task_runner, quit_closure) { |
115 task_runner->PostTask(FROM_HERE, quit_closure); | 88 task_runner->PostTask(FROM_HERE, quit_closure); |
116 } | 89 } |
117 | 90 |
118 // This is an integration test of VideoCaptureHost in conjunction with | 91 // This is an integration test of VideoCaptureHost in conjunction with |
119 // MediaStreamManager, VideoCaptureManager, VideoCaptureController, and | 92 // MediaStreamManager, VideoCaptureManager, VideoCaptureController, and |
120 // VideoCaptureDevice. | 93 // VideoCaptureDevice. |
121 class VideoCaptureHostTest : public testing::Test, | 94 class VideoCaptureHostTest : public testing::Test, |
122 public mojom::VideoCaptureObserver { | 95 public mojom::VideoCaptureObserver { |
123 public: | 96 public: |
124 VideoCaptureHostTest() | 97 VideoCaptureHostTest() |
125 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), | 98 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), |
126 audio_manager_( | 99 audio_manager_( |
127 new media::MockAudioManager(base::ThreadTaskRunnerHandle::Get())), | 100 new media::MockAudioManager(base::ThreadTaskRunnerHandle::Get())), |
128 task_runner_(base::ThreadTaskRunnerHandle::Get()), | 101 task_runner_(base::ThreadTaskRunnerHandle::Get()), |
129 opened_session_id_(kInvalidMediaCaptureSessionId), | 102 opened_session_id_(kInvalidMediaCaptureSessionId), |
130 observer_binding_(this) {} | 103 observer_binding_(this) {} |
131 | 104 |
132 void SetUp() override { | 105 void SetUp() override { |
133 SetBrowserClientForTesting(&browser_client_); | 106 SetBrowserClientForTesting(&browser_client_); |
134 | 107 |
135 base::CommandLine::ForCurrentProcess()->AppendSwitch( | 108 base::CommandLine::ForCurrentProcess()->AppendSwitch( |
136 switches::kUseFakeDeviceForMediaStream); | 109 switches::kUseFakeDeviceForMediaStream); |
137 base::CommandLine::ForCurrentProcess()->AppendSwitch( | 110 base::CommandLine::ForCurrentProcess()->AppendSwitch( |
138 switches::kUseFakeUIForMediaStream); | 111 switches::kUseFakeUIForMediaStream); |
139 media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get())); | 112 media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get())); |
140 | 113 |
141 // Create a Host and connect it to a simulated IPC channel. | 114 // Create a Host and connect it to a simulated IPC channel. |
142 host_ = new MockVideoCaptureHost(media_stream_manager_.get()); | 115 host_ = new VideoCaptureHost(media_stream_manager_.get()); |
143 host_->OnChannelConnected(base::GetCurrentProcId()); | 116 host_->OnChannelConnected(base::GetCurrentProcId()); |
144 | 117 |
145 OpenSession(); | 118 OpenSession(); |
146 } | 119 } |
147 | 120 |
148 void TearDown() override { | 121 void TearDown() override { |
149 Mock::VerifyAndClearExpectations(host_.get()); | 122 Mock::VerifyAndClearExpectations(host_.get()); |
150 EXPECT_TRUE(host_->controllers_.empty()); | 123 EXPECT_TRUE(host_->controllers_.empty()); |
151 | 124 |
152 CloseSession(); | 125 CloseSession(); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 if (opened_device_label_.empty()) | 194 if (opened_device_label_.empty()) |
222 return; | 195 return; |
223 media_stream_manager_->CancelRequest(opened_device_label_); | 196 media_stream_manager_->CancelRequest(opened_device_label_); |
224 opened_device_label_.clear(); | 197 opened_device_label_.clear(); |
225 opened_session_id_ = kInvalidMediaCaptureSessionId; | 198 opened_session_id_ = kInvalidMediaCaptureSessionId; |
226 } | 199 } |
227 | 200 |
228 protected: | 201 protected: |
229 // mojom::VideoCaptureObserver implementation. | 202 // mojom::VideoCaptureObserver implementation. |
230 MOCK_METHOD1(OnStateChanged, void(mojom::VideoCaptureState)); | 203 MOCK_METHOD1(OnStateChanged, void(mojom::VideoCaptureState)); |
| 204 void OnBufferCreated(int32_t buffer_id, |
| 205 mojo::ScopedSharedBufferHandle handle) override { |
| 206 DoOnBufferCreated(buffer_id); |
| 207 } |
| 208 MOCK_METHOD1(DoOnBufferCreated, void(int32_t)); |
231 void OnBufferReady(int32_t buffer_id, | 209 void OnBufferReady(int32_t buffer_id, |
232 mojom::VideoFrameInfoPtr info) override { | 210 mojom::VideoFrameInfoPtr info) override { |
233 DoOnBufferReady(buffer_id); | 211 DoOnBufferReady(buffer_id); |
234 } | 212 } |
235 MOCK_METHOD1(DoOnBufferReady, void(int32_t)); | 213 MOCK_METHOD1(DoOnBufferReady, void(int32_t)); |
236 MOCK_METHOD1(OnBufferDestroyed, void(int32_t)); | 214 MOCK_METHOD1(OnBufferDestroyed, void(int32_t)); |
237 | 215 |
238 void StartCapture() { | 216 void StartCapture() { |
239 base::RunLoop run_loop; | 217 base::RunLoop run_loop; |
240 media::VideoCaptureParams params; | 218 media::VideoCaptureParams params; |
241 params.requested_format = media::VideoCaptureFormat( | 219 params.requested_format = media::VideoCaptureFormat( |
242 gfx::Size(352, 288), 30, media::PIXEL_FORMAT_I420); | 220 gfx::Size(352, 288), 30, media::PIXEL_FORMAT_I420); |
243 | 221 |
244 EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::STARTED)); | 222 EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::STARTED)); |
245 EXPECT_CALL(*host_.get(), OnNewBufferCreated(kDeviceId, _, _, _)) | 223 EXPECT_CALL(*this, DoOnBufferCreated(_)) |
246 .Times(AnyNumber()) | 224 .Times(AnyNumber()) |
247 .WillRepeatedly(Return()); | 225 .WillRepeatedly(Return()); |
248 EXPECT_CALL(*this, DoOnBufferReady(_)) | 226 EXPECT_CALL(*this, DoOnBufferReady(_)) |
249 .Times(AnyNumber()) | 227 .Times(AnyNumber()) |
250 .WillOnce(ExitMessageLoop(task_runner_, run_loop.QuitClosure())); | 228 .WillRepeatedly(ExitMessageLoop(task_runner_, run_loop.QuitClosure())); |
251 | 229 |
252 host_->Start(kDeviceId, opened_session_id_, params, | 230 host_->Start(kDeviceId, opened_session_id_, params, |
253 observer_binding_.CreateInterfacePtrAndBind()); | 231 observer_binding_.CreateInterfacePtrAndBind()); |
254 | 232 |
255 run_loop.Run(); | 233 run_loop.Run(); |
256 } | 234 } |
257 | 235 |
258 void StartStopCapture() { | 236 void StartAndImmediateStopCapture() { |
259 // Quickly start and then stop capture, without giving much chance for | 237 // Quickly start and then stop capture, without giving much chance for |
260 // asynchronous capture operations to produce frames. | 238 // asynchronous capture operations to produce frames. |
261 InSequence s; | 239 InSequence s; |
262 base::RunLoop run_loop; | 240 base::RunLoop run_loop; |
263 | 241 |
264 media::VideoCaptureParams params; | 242 media::VideoCaptureParams params; |
265 params.requested_format = media::VideoCaptureFormat( | 243 params.requested_format = media::VideoCaptureFormat( |
266 gfx::Size(352, 288), 30, media::PIXEL_FORMAT_I420); | 244 gfx::Size(352, 288), 30, media::PIXEL_FORMAT_I420); |
267 | 245 |
268 EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::STARTED)); | 246 EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::STARTED)); |
269 host_->Start(kDeviceId, opened_session_id_, params, | 247 host_->Start(kDeviceId, opened_session_id_, params, |
270 observer_binding_.CreateInterfacePtrAndBind()); | 248 observer_binding_.CreateInterfacePtrAndBind()); |
271 | 249 |
272 EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::STOPPED)); | 250 EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::STOPPED)); |
273 host_->Stop(kDeviceId); | 251 host_->Stop(kDeviceId); |
274 run_loop.RunUntilIdle(); | 252 run_loop.RunUntilIdle(); |
275 WaitForVideoDeviceThread(); | |
276 } | 253 } |
277 | 254 |
278 void PauseResumeCapture() { | 255 void PauseResumeCapture() { |
279 InSequence s; | 256 InSequence s; |
280 base::RunLoop run_loop; | 257 base::RunLoop run_loop; |
281 | 258 |
282 EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::PAUSED)); | 259 EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::PAUSED)); |
283 host_->Pause(kDeviceId); | 260 host_->Pause(kDeviceId); |
284 | 261 |
285 media::VideoCaptureParams params; | 262 media::VideoCaptureParams params; |
286 params.requested_format = media::VideoCaptureFormat( | 263 params.requested_format = media::VideoCaptureFormat( |
287 gfx::Size(352, 288), 30, media::PIXEL_FORMAT_I420); | 264 gfx::Size(352, 288), 30, media::PIXEL_FORMAT_I420); |
288 | 265 |
289 EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::RESUMED)); | 266 EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::RESUMED)); |
290 host_->Resume(kDeviceId, opened_session_id_, params); | 267 host_->Resume(kDeviceId, opened_session_id_, params); |
291 run_loop.RunUntilIdle(); | 268 run_loop.RunUntilIdle(); |
292 WaitForVideoDeviceThread(); | |
293 } | 269 } |
294 | 270 |
295 void StopCapture() { | 271 void StopCapture() { |
296 base::RunLoop run_loop; | 272 base::RunLoop run_loop; |
297 | 273 |
298 EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::STOPPED)) | 274 EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::STOPPED)) |
299 .WillOnce(ExitMessageLoop(task_runner_, run_loop.QuitClosure())); | 275 .WillOnce(ExitMessageLoop(task_runner_, run_loop.QuitClosure())); |
300 host_->Stop(kDeviceId); | 276 host_->Stop(kDeviceId); |
301 | 277 |
302 run_loop.Run(); | 278 run_loop.Run(); |
(...skipping 11 matching lines...) Expand all Loading... |
314 run_loop.Run(); | 290 run_loop.Run(); |
315 } | 291 } |
316 | 292 |
317 void SimulateError() { | 293 void SimulateError() { |
318 EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::FAILED)); | 294 EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::FAILED)); |
319 VideoCaptureControllerID id(kDeviceId); | 295 VideoCaptureControllerID id(kDeviceId); |
320 host_->OnError(id); | 296 host_->OnError(id); |
321 base::RunLoop().RunUntilIdle(); | 297 base::RunLoop().RunUntilIdle(); |
322 } | 298 } |
323 | 299 |
324 void WaitForVideoDeviceThread() { | |
325 base::RunLoop run_loop; | |
326 media_stream_manager_->video_capture_manager()->device_task_runner() | |
327 ->PostTaskAndReply( | |
328 FROM_HERE, | |
329 base::Bind(&base::DoNothing), | |
330 run_loop.QuitClosure()); | |
331 run_loop.Run(); | |
332 } | |
333 | |
334 scoped_refptr<MockVideoCaptureHost> host_; | |
335 | |
336 private: | 300 private: |
337 // |media_stream_manager_| needs to outlive |thread_bundle_| because it is a | 301 // |media_stream_manager_| needs to outlive |thread_bundle_| because it is a |
338 // MessageLoop::DestructionObserver. | 302 // MessageLoop::DestructionObserver. |
339 StrictMock<MockMediaStreamRequester> stream_requester_; | 303 StrictMock<MockMediaStreamRequester> stream_requester_; |
340 std::unique_ptr<MediaStreamManager> media_stream_manager_; | 304 std::unique_ptr<MediaStreamManager> media_stream_manager_; |
341 const content::TestBrowserThreadBundle thread_bundle_; | 305 const content::TestBrowserThreadBundle thread_bundle_; |
342 // |audio_manager_| needs to outlive |thread_bundle_| because it uses the | 306 // |audio_manager_| needs to outlive |thread_bundle_| because it uses the |
343 // underlying message loop. | 307 // underlying message loop. |
344 media::ScopedAudioManagerPtr audio_manager_; | 308 media::ScopedAudioManagerPtr audio_manager_; |
345 content::TestBrowserContext browser_context_; | 309 content::TestBrowserContext browser_context_; |
346 content::TestContentBrowserClient browser_client_; | 310 content::TestContentBrowserClient browser_client_; |
347 const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | 311 const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
348 int opened_session_id_; | 312 int opened_session_id_; |
349 std::string opened_device_label_; | 313 std::string opened_device_label_; |
350 | 314 |
| 315 scoped_refptr<VideoCaptureHost> host_; |
351 mojo::Binding<mojom::VideoCaptureObserver> observer_binding_; | 316 mojo::Binding<mojom::VideoCaptureObserver> observer_binding_; |
352 | 317 |
353 DISALLOW_COPY_AND_ASSIGN(VideoCaptureHostTest); | 318 DISALLOW_COPY_AND_ASSIGN(VideoCaptureHostTest); |
354 }; | 319 }; |
355 | 320 |
356 TEST_F(VideoCaptureHostTest, CloseSessionWithoutStopping) { | 321 // Construct and destruct all objects. This is a non trivial sequence. |
357 StartCapture(); | 322 TEST_F(VideoCaptureHostTest, ConstructAndDestruct) {} |
358 | 323 |
359 // When the session is closed via the stream without stopping capture, the | 324 TEST_F(VideoCaptureHostTest, StartAndImmediateStop) { |
360 // ENDED event is sent. | 325 StartAndImmediateStopCapture(); |
361 EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::ENDED)); | |
362 CloseSession(); | |
363 base::RunLoop().RunUntilIdle(); | |
364 } | 326 } |
365 | 327 |
366 TEST_F(VideoCaptureHostTest, StopWhileStartPending) { | 328 TEST_F(VideoCaptureHostTest, StartAndCaptureAndStop) { |
367 StartStopCapture(); | |
368 } | |
369 | |
370 TEST_F(VideoCaptureHostTest, StartCapturePlayStop) { | |
371 StartCapture(); | 329 StartCapture(); |
372 WaitForOneCapturedBuffer(); | 330 WaitForOneCapturedBuffer(); |
373 WaitForOneCapturedBuffer(); | 331 WaitForOneCapturedBuffer(); |
374 StopCapture(); | 332 StopCapture(); |
375 } | 333 } |
376 | 334 |
377 TEST_F(VideoCaptureHostTest, StartCaptureErrorStop) { | 335 TEST_F(VideoCaptureHostTest, StartAndErrorAndStop) { |
378 StartCapture(); | 336 StartCapture(); |
379 SimulateError(); | 337 SimulateError(); |
380 StopCapture(); | 338 StopCapture(); |
381 } | 339 } |
382 | 340 |
383 TEST_F(VideoCaptureHostTest, StartCaptureError) { | 341 TEST_F(VideoCaptureHostTest, StartAndCaptureAndError) { |
384 EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::STOPPED)) | 342 EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::STOPPED)) |
385 .Times(0); | 343 .Times(0); |
386 StartCapture(); | 344 StartCapture(); |
387 WaitForOneCapturedBuffer(); | 345 WaitForOneCapturedBuffer(); |
388 SimulateError(); | 346 SimulateError(); |
389 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200)); | 347 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200)); |
390 } | 348 } |
391 | 349 |
392 TEST_F(VideoCaptureHostTest, PauseResumeCapture) { | 350 TEST_F(VideoCaptureHostTest, StartAndPauseAndResumeAndStop) { |
393 StartCapture(); | 351 StartCapture(); |
394 PauseResumeCapture(); | 352 PauseResumeCapture(); |
395 StopCapture(); | 353 StopCapture(); |
396 } | 354 } |
397 | 355 |
| 356 TEST_F(VideoCaptureHostTest, CloseSessionWithoutStopping) { |
| 357 StartCapture(); |
| 358 |
| 359 // When the session is closed via the stream without stopping capture, the |
| 360 // ENDED event is sent. |
| 361 EXPECT_CALL(*this, OnStateChanged(mojom::VideoCaptureState::ENDED)); |
| 362 CloseSession(); |
| 363 base::RunLoop().RunUntilIdle(); |
| 364 } |
| 365 |
398 } // namespace content | 366 } // namespace content |
OLD | NEW |