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