| 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_controller.h" | 5 #include "content/browser/renderer_host/media/video_capture_controller.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
| 9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
| 10 #include "content/browser/renderer_host/media/media_stream_manager.h" | 10 #include "content/browser/renderer_host/media/media_stream_manager.h" |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 | 66 |
| 67 VideoCaptureController::VideoCaptureController( | 67 VideoCaptureController::VideoCaptureController( |
| 68 media_stream::VideoCaptureManager* video_capture_manager) | 68 media_stream::VideoCaptureManager* video_capture_manager) |
| 69 : frame_info_available_(false), | 69 : frame_info_available_(false), |
| 70 video_capture_manager_(video_capture_manager), | 70 video_capture_manager_(video_capture_manager), |
| 71 device_in_use_(false), | 71 device_in_use_(false), |
| 72 state_(video_capture::kStopped) { | 72 state_(video_capture::kStopped) { |
| 73 memset(¤t_params_, 0, sizeof(current_params_)); | 73 memset(¤t_params_, 0, sizeof(current_params_)); |
| 74 } | 74 } |
| 75 | 75 |
| 76 VideoCaptureController::~VideoCaptureController() { | |
| 77 // Delete all DIBs. | |
| 78 STLDeleteContainerPairSecondPointers(owned_dibs_.begin(), | |
| 79 owned_dibs_.end()); | |
| 80 STLDeleteContainerPointers(controller_clients_.begin(), | |
| 81 controller_clients_.end()); | |
| 82 STLDeleteContainerPointers(pending_clients_.begin(), | |
| 83 pending_clients_.end()); | |
| 84 } | |
| 85 | |
| 86 void VideoCaptureController::StartCapture( | 76 void VideoCaptureController::StartCapture( |
| 87 const VideoCaptureControllerID& id, | 77 const VideoCaptureControllerID& id, |
| 88 VideoCaptureControllerEventHandler* event_handler, | 78 VideoCaptureControllerEventHandler* event_handler, |
| 89 base::ProcessHandle render_process, | 79 base::ProcessHandle render_process, |
| 90 const media::VideoCaptureParams& params) { | 80 const media::VideoCaptureParams& params) { |
| 91 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 81 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 92 // Signal error in case device is already in error state. | 82 // Signal error in case device is already in error state. |
| 93 if (state_ == video_capture::kError) { | 83 if (state_ == video_capture::kError) { |
| 94 event_handler->OnError(id); | 84 event_handler->OnError(id); |
| 95 return; | 85 return; |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 354 | 344 |
| 355 void VideoCaptureController::OnFrameInfo( | 345 void VideoCaptureController::OnFrameInfo( |
| 356 const media::VideoCaptureDevice::Capability& info) { | 346 const media::VideoCaptureDevice::Capability& info) { |
| 357 frame_info_= info; | 347 frame_info_= info; |
| 358 BrowserThread::PostTask(BrowserThread::IO, | 348 BrowserThread::PostTask(BrowserThread::IO, |
| 359 FROM_HERE, | 349 FROM_HERE, |
| 360 base::Bind(&VideoCaptureController::DoFrameInfoOnIOThread, | 350 base::Bind(&VideoCaptureController::DoFrameInfoOnIOThread, |
| 361 this, info)); | 351 this, info)); |
| 362 } | 352 } |
| 363 | 353 |
| 354 VideoCaptureController::~VideoCaptureController() { |
| 355 // Delete all DIBs. |
| 356 STLDeleteContainerPairSecondPointers(owned_dibs_.begin(), |
| 357 owned_dibs_.end()); |
| 358 STLDeleteContainerPointers(controller_clients_.begin(), |
| 359 controller_clients_.end()); |
| 360 STLDeleteContainerPointers(pending_clients_.begin(), |
| 361 pending_clients_.end()); |
| 362 } |
| 363 |
| 364 // Called by VideoCaptureManager when a device have been stopped. |
| 365 void VideoCaptureController::OnDeviceStopped() { |
| 366 BrowserThread::PostTask(BrowserThread::IO, |
| 367 FROM_HERE, |
| 368 base::Bind(&VideoCaptureController::DoDeviceStoppedOnIOThread, this)); |
| 369 } |
| 370 |
| 364 void VideoCaptureController::DoIncomingCapturedFrameOnIOThread( | 371 void VideoCaptureController::DoIncomingCapturedFrameOnIOThread( |
| 365 int buffer_id, base::Time timestamp) { | 372 int buffer_id, base::Time timestamp) { |
| 366 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 373 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 367 | 374 |
| 368 int count = 0; | 375 int count = 0; |
| 369 if (state_ == video_capture::kStarted) { | 376 if (state_ == video_capture::kStarted) { |
| 370 for (ControllerClients::iterator client_it = controller_clients_.begin(); | 377 for (ControllerClients::iterator client_it = controller_clients_.begin(); |
| 371 client_it != controller_clients_.end(); client_it++) { | 378 client_it != controller_clients_.end(); client_it++) { |
| 372 if ((*client_it)->report_ready_to_delete) | 379 if ((*client_it)->report_ready_to_delete) |
| 373 continue; | 380 continue; |
| 374 | 381 |
| 375 (*client_it)->event_handler->OnBufferReady((*client_it)->controller_id, | 382 (*client_it)->event_handler->OnBufferReady((*client_it)->controller_id, |
| 376 buffer_id, timestamp); | 383 buffer_id, timestamp); |
| 377 (*client_it)->buffers.push_back(buffer_id); | 384 (*client_it)->buffers.push_back(buffer_id); |
| 378 count++; | 385 count++; |
| 379 } | 386 } |
| 380 } | 387 } |
| 381 | 388 |
| 382 base::AutoLock lock(lock_); | 389 base::AutoLock lock(lock_); |
| 383 DCHECK_EQ(owned_dibs_[buffer_id]->references, -1); | 390 DCHECK_EQ(owned_dibs_[buffer_id]->references, -1); |
| 384 owned_dibs_[buffer_id]->references = count; | 391 owned_dibs_[buffer_id]->references = count; |
| 385 } | 392 } |
| 386 | 393 |
| 387 void VideoCaptureController::DoErrorOnIOThread() { | |
| 388 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 389 state_ = video_capture::kError; | |
| 390 ControllerClients::iterator client_it; | |
| 391 for (client_it = controller_clients_.begin(); | |
| 392 client_it != controller_clients_.end(); client_it++) { | |
| 393 (*client_it)->event_handler->OnError((*client_it)->controller_id); | |
| 394 } | |
| 395 for (client_it = pending_clients_.begin(); | |
| 396 client_it != pending_clients_.end(); client_it++) { | |
| 397 (*client_it)->event_handler->OnError((*client_it)->controller_id); | |
| 398 } | |
| 399 } | |
| 400 | |
| 401 void VideoCaptureController::DoFrameInfoOnIOThread( | 394 void VideoCaptureController::DoFrameInfoOnIOThread( |
| 402 const media::VideoCaptureDevice::Capability info) { | 395 const media::VideoCaptureDevice::Capability info) { |
| 403 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 396 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 404 DCHECK(owned_dibs_.empty()) | 397 DCHECK(owned_dibs_.empty()) |
| 405 << "Device is restarted without releasing shared memory."; | 398 << "Device is restarted without releasing shared memory."; |
| 406 | 399 |
| 407 bool frames_created = true; | 400 bool frames_created = true; |
| 408 const size_t needed_size = (info.width * info.height * 3) / 2; | 401 const size_t needed_size = (info.width * info.height * 3) / 2; |
| 409 { | 402 { |
| 410 base::AutoLock lock(lock_); | 403 base::AutoLock lock(lock_); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 428 return; | 421 return; |
| 429 } | 422 } |
| 430 frame_info_available_ = true; | 423 frame_info_available_ = true; |
| 431 | 424 |
| 432 for (ControllerClients::iterator client_it = controller_clients_.begin(); | 425 for (ControllerClients::iterator client_it = controller_clients_.begin(); |
| 433 client_it != controller_clients_.end(); client_it++) { | 426 client_it != controller_clients_.end(); client_it++) { |
| 434 SendFrameInfoAndBuffers((*client_it), static_cast<int>(needed_size)); | 427 SendFrameInfoAndBuffers((*client_it), static_cast<int>(needed_size)); |
| 435 } | 428 } |
| 436 } | 429 } |
| 437 | 430 |
| 431 void VideoCaptureController::DoErrorOnIOThread() { |
| 432 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 433 state_ = video_capture::kError; |
| 434 ControllerClients::iterator client_it; |
| 435 for (client_it = controller_clients_.begin(); |
| 436 client_it != controller_clients_.end(); client_it++) { |
| 437 (*client_it)->event_handler->OnError((*client_it)->controller_id); |
| 438 } |
| 439 for (client_it = pending_clients_.begin(); |
| 440 client_it != pending_clients_.end(); client_it++) { |
| 441 (*client_it)->event_handler->OnError((*client_it)->controller_id); |
| 442 } |
| 443 } |
| 444 |
| 445 void VideoCaptureController::DoDeviceStoppedOnIOThread() { |
| 446 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 447 device_in_use_ = false; |
| 448 if (state_ == video_capture::kStopping) { |
| 449 PostStopping(); |
| 450 } |
| 451 } |
| 452 |
| 438 void VideoCaptureController::SendFrameInfoAndBuffers( | 453 void VideoCaptureController::SendFrameInfoAndBuffers( |
| 439 ControllerClient* client, int buffer_size) { | 454 ControllerClient* client, int buffer_size) { |
| 440 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 455 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 441 DCHECK(frame_info_available_); | 456 DCHECK(frame_info_available_); |
| 442 client->event_handler->OnFrameInfo(client->controller_id, | 457 client->event_handler->OnFrameInfo(client->controller_id, |
| 443 frame_info_.width, frame_info_.height, | 458 frame_info_.width, frame_info_.height, |
| 444 frame_info_.frame_rate); | 459 frame_info_.frame_rate); |
| 445 for (DIBMap::iterator dib_it = owned_dibs_.begin(); | 460 for (DIBMap::iterator dib_it = owned_dibs_.begin(); |
| 446 dib_it != owned_dibs_.end(); dib_it++) { | 461 dib_it != owned_dibs_.end(); dib_it++) { |
| 447 base::SharedMemory* shared_memory = dib_it->second->shared_memory.get(); | 462 base::SharedMemory* shared_memory = dib_it->second->shared_memory.get(); |
| 448 int index = dib_it->first; | 463 int index = dib_it->first; |
| 449 base::SharedMemoryHandle remote_handle; | 464 base::SharedMemoryHandle remote_handle; |
| 450 shared_memory->ShareToProcess(client->render_process_handle, | 465 shared_memory->ShareToProcess(client->render_process_handle, |
| 451 &remote_handle); | 466 &remote_handle); |
| 452 client->event_handler->OnBufferCreated(client->controller_id, | 467 client->event_handler->OnBufferCreated(client->controller_id, |
| 453 remote_handle, | 468 remote_handle, |
| 454 buffer_size, | 469 buffer_size, |
| 455 index); | 470 index); |
| 456 } | 471 } |
| 457 } | 472 } |
| 458 | 473 |
| 474 VideoCaptureController::ControllerClient* |
| 475 VideoCaptureController::FindClient( |
| 476 const VideoCaptureControllerID& id, |
| 477 VideoCaptureControllerEventHandler* handler, |
| 478 const ControllerClients& clients) { |
| 479 for (ControllerClients::const_iterator client_it = clients.begin(); |
| 480 client_it != clients.end(); client_it++) { |
| 481 if ((*client_it)->controller_id == id && |
| 482 (*client_it)->event_handler == handler) { |
| 483 return *client_it; |
| 484 } |
| 485 } |
| 486 return NULL; |
| 487 } |
| 488 |
| 459 // This function is called when all buffers have been returned to controller, | 489 // This function is called when all buffers have been returned to controller, |
| 460 // or when device is stopped. It decides whether the device needs to be | 490 // or when device is stopped. It decides whether the device needs to be |
| 461 // restarted. | 491 // restarted. |
| 462 void VideoCaptureController::PostStopping() { | 492 void VideoCaptureController::PostStopping() { |
| 463 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 493 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 464 DCHECK_EQ(state_, video_capture::kStopping); | 494 DCHECK_EQ(state_, video_capture::kStopping); |
| 465 | 495 |
| 466 // When clients still have some buffers, or device has not been stopped yet, | 496 // When clients still have some buffers, or device has not been stopped yet, |
| 467 // do nothing. | 497 // do nothing. |
| 468 if (ClientHasDIB() || device_in_use_) | 498 if (ClientHasDIB() || device_in_use_) |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 506 bool VideoCaptureController::ClientHasDIB() { | 536 bool VideoCaptureController::ClientHasDIB() { |
| 507 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 537 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 508 base::AutoLock lock(lock_); | 538 base::AutoLock lock(lock_); |
| 509 for (DIBMap::iterator dib_it = owned_dibs_.begin(); | 539 for (DIBMap::iterator dib_it = owned_dibs_.begin(); |
| 510 dib_it != owned_dibs_.end(); dib_it++) { | 540 dib_it != owned_dibs_.end(); dib_it++) { |
| 511 if (dib_it->second->references > 0) | 541 if (dib_it->second->references > 0) |
| 512 return true; | 542 return true; |
| 513 } | 543 } |
| 514 return false; | 544 return false; |
| 515 } | 545 } |
| 516 | |
| 517 VideoCaptureController::ControllerClient* | |
| 518 VideoCaptureController::FindClient( | |
| 519 const VideoCaptureControllerID& id, | |
| 520 VideoCaptureControllerEventHandler* handler, | |
| 521 const ControllerClients& clients) { | |
| 522 for (ControllerClients::const_iterator client_it = clients.begin(); | |
| 523 client_it != clients.end(); client_it++) { | |
| 524 if ((*client_it)->controller_id == id && | |
| 525 (*client_it)->event_handler == handler) { | |
| 526 return *client_it; | |
| 527 } | |
| 528 } | |
| 529 return NULL; | |
| 530 } | |
| 531 | |
| 532 /////////////////////////////////////////////////////////////////////////////// | |
| 533 // Called by VideoCaptureManager when a device have been stopped. | |
| 534 void VideoCaptureController::OnDeviceStopped() { | |
| 535 BrowserThread::PostTask(BrowserThread::IO, | |
| 536 FROM_HERE, | |
| 537 base::Bind(&VideoCaptureController::DoDeviceStoppedOnIOThread, this)); | |
| 538 } | |
| 539 | |
| 540 void VideoCaptureController::DoDeviceStoppedOnIOThread() { | |
| 541 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 542 device_in_use_ = false; | |
| 543 if (state_ == video_capture::kStopping) { | |
| 544 PostStopping(); | |
| 545 } | |
| 546 } | |
| 547 | |
| OLD | NEW |