| 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 <set> | 7 #include <set> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| 11 #include "base/stl_util.h" | 11 #include "base/stl_util.h" |
| 12 #include "content/browser/renderer_host/media/media_stream_manager.h" | 12 #include "content/browser/renderer_host/media/media_stream_manager.h" |
| 13 #include "content/browser/renderer_host/media/video_capture_manager.h" | 13 #include "content/browser/renderer_host/media/video_capture_manager.h" |
| 14 #include "content/public/browser/browser_thread.h" | 14 #include "content/public/browser/browser_thread.h" |
| 15 #include "media/base/yuv_convert.h" | 15 #include "media/base/yuv_convert.h" |
| 16 | 16 |
| 17 using content::BrowserThread; | 17 namespace content { |
| 18 | 18 |
| 19 // The number of DIBs VideoCaptureController allocate. | 19 // The number of DIBs VideoCaptureController allocate. |
| 20 static const size_t kNoOfDIBS = 3; | 20 static const size_t kNoOfDIBS = 3; |
| 21 | 21 |
| 22 struct VideoCaptureController::ControllerClient { | 22 struct VideoCaptureController::ControllerClient { |
| 23 ControllerClient( | 23 ControllerClient( |
| 24 const VideoCaptureControllerID& id, | 24 const VideoCaptureControllerID& id, |
| 25 VideoCaptureControllerEventHandler* handler, | 25 VideoCaptureControllerEventHandler* handler, |
| 26 base::ProcessHandle render_process, | 26 base::ProcessHandle render_process, |
| 27 const media::VideoCaptureParams& params) | 27 const media::VideoCaptureParams& params) |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 59 | 59 |
| 60 // The memory created to be shared with renderer processes. | 60 // The memory created to be shared with renderer processes. |
| 61 scoped_ptr<base::SharedMemory> shared_memory; | 61 scoped_ptr<base::SharedMemory> shared_memory; |
| 62 | 62 |
| 63 // Number of renderer processes which hold this shared memory. | 63 // Number of renderer processes which hold this shared memory. |
| 64 // renderer process is represented by VidoeCaptureHost. | 64 // renderer process is represented by VidoeCaptureHost. |
| 65 int references; | 65 int references; |
| 66 }; | 66 }; |
| 67 | 67 |
| 68 VideoCaptureController::VideoCaptureController( | 68 VideoCaptureController::VideoCaptureController( |
| 69 media_stream::VideoCaptureManager* video_capture_manager) | 69 VideoCaptureManager* video_capture_manager) |
| 70 : chopped_width_(0), | 70 : chopped_width_(0), |
| 71 chopped_height_(0), | 71 chopped_height_(0), |
| 72 frame_info_available_(false), | 72 frame_info_available_(false), |
| 73 video_capture_manager_(video_capture_manager), | 73 video_capture_manager_(video_capture_manager), |
| 74 device_in_use_(false), | 74 device_in_use_(false), |
| 75 state_(video_capture::kStopped) { | 75 state_(VIDEO_CAPTURE_STATE_STOPPED) { |
| 76 memset(¤t_params_, 0, sizeof(current_params_)); | 76 memset(¤t_params_, 0, sizeof(current_params_)); |
| 77 } | 77 } |
| 78 | 78 |
| 79 void VideoCaptureController::StartCapture( | 79 void VideoCaptureController::StartCapture( |
| 80 const VideoCaptureControllerID& id, | 80 const VideoCaptureControllerID& id, |
| 81 VideoCaptureControllerEventHandler* event_handler, | 81 VideoCaptureControllerEventHandler* event_handler, |
| 82 base::ProcessHandle render_process, | 82 base::ProcessHandle render_process, |
| 83 const media::VideoCaptureParams& params) { | 83 const media::VideoCaptureParams& params) { |
| 84 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 84 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 85 DVLOG(1) << "VideoCaptureController::StartCapture, id " << id.device_id | 85 DVLOG(1) << "VideoCaptureController::StartCapture, id " << id.device_id |
| 86 << ", (" << params.width | 86 << ", (" << params.width |
| 87 << ", " << params.height | 87 << ", " << params.height |
| 88 << ", " << params.frame_per_second | 88 << ", " << params.frame_per_second |
| 89 << ", " << params.session_id | 89 << ", " << params.session_id |
| 90 << ")"; | 90 << ")"; |
| 91 | 91 |
| 92 // Signal error in case device is already in error state. | 92 // Signal error in case device is already in error state. |
| 93 if (state_ == video_capture::kError) { | 93 if (state_ == VIDEO_CAPTURE_STATE_ERROR) { |
| 94 event_handler->OnError(id); | 94 event_handler->OnError(id); |
| 95 return; | 95 return; |
| 96 } | 96 } |
| 97 | 97 |
| 98 // Do nothing if this client has called StartCapture before. | 98 // Do nothing if this client has called StartCapture before. |
| 99 if (FindClient(id, event_handler, controller_clients_) || | 99 if (FindClient(id, event_handler, controller_clients_) || |
| 100 FindClient(id, event_handler, pending_clients_)) | 100 FindClient(id, event_handler, pending_clients_)) |
| 101 return; | 101 return; |
| 102 | 102 |
| 103 ControllerClient* client = new ControllerClient(id, event_handler, | 103 ControllerClient* client = new ControllerClient(id, event_handler, |
| 104 render_process, params); | 104 render_process, params); |
| 105 // In case capture has been started, need to check different condtions. | 105 // In case capture has been started, need to check different condtions. |
| 106 if (state_ == video_capture::kStarted) { | 106 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { |
| 107 // TODO(wjia): Temporarily disable restarting till client supports resampling. | 107 // TODO(wjia): Temporarily disable restarting till client supports resampling. |
| 108 #if 0 | 108 #if 0 |
| 109 // This client has higher resolution than what is currently requested. | 109 // This client has higher resolution than what is currently requested. |
| 110 // Need restart capturing. | 110 // Need restart capturing. |
| 111 if (params.width > current_params_.width || | 111 if (params.width > current_params_.width || |
| 112 params.height > current_params_.height) { | 112 params.height > current_params_.height) { |
| 113 video_capture_manager_->Stop(current_params_.session_id, | 113 video_capture_manager_->Stop(current_params_.session_id, |
| 114 base::Bind(&VideoCaptureController::OnDeviceStopped, this)); | 114 base::Bind(&VideoCaptureController::OnDeviceStopped, this)); |
| 115 frame_info_available_ = false; | 115 frame_info_available_ = false; |
| 116 state_ = video_capture::kStopping; | 116 state_ = VIDEO_CAPTURE_STATE_STOPPING; |
| 117 pending_clients_.push_back(client); | 117 pending_clients_.push_back(client); |
| 118 return; | 118 return; |
| 119 } | 119 } |
| 120 #endif | 120 #endif |
| 121 | 121 |
| 122 // This client's resolution is no larger than what's currently requested. | 122 // This client's resolution is no larger than what's currently requested. |
| 123 // When frame_info has been returned by device, send them to client. | 123 // When frame_info has been returned by device, send them to client. |
| 124 if (frame_info_available_) { | 124 if (frame_info_available_) { |
| 125 int buffer_size = (frame_info_.width * frame_info_.height * 3) / 2; | 125 int buffer_size = (frame_info_.width * frame_info_.height * 3) / 2; |
| 126 SendFrameInfoAndBuffers(client, buffer_size); | 126 SendFrameInfoAndBuffers(client, buffer_size); |
| 127 } | 127 } |
| 128 controller_clients_.push_back(client); | 128 controller_clients_.push_back(client); |
| 129 return; | 129 return; |
| 130 } | 130 } |
| 131 | 131 |
| 132 // In case the device is in the middle of stopping, put the client in | 132 // In case the device is in the middle of stopping, put the client in |
| 133 // pending queue. | 133 // pending queue. |
| 134 if (state_ == video_capture::kStopping) { | 134 if (state_ == VIDEO_CAPTURE_STATE_STOPPING) { |
| 135 pending_clients_.push_back(client); | 135 pending_clients_.push_back(client); |
| 136 return; | 136 return; |
| 137 } | 137 } |
| 138 | 138 |
| 139 // Fresh start. | 139 // Fresh start. |
| 140 controller_clients_.push_back(client); | 140 controller_clients_.push_back(client); |
| 141 current_params_ = params; | 141 current_params_ = params; |
| 142 // Order the manager to start the actual capture. | 142 // Order the manager to start the actual capture. |
| 143 video_capture_manager_->Start(params, this); | 143 video_capture_manager_->Start(params, this); |
| 144 state_ = video_capture::kStarted; | 144 state_ = VIDEO_CAPTURE_STATE_STARTED; |
| 145 device_in_use_ = true; | 145 device_in_use_ = true; |
| 146 } | 146 } |
| 147 | 147 |
| 148 void VideoCaptureController::StopCapture( | 148 void VideoCaptureController::StopCapture( |
| 149 const VideoCaptureControllerID& id, | 149 const VideoCaptureControllerID& id, |
| 150 VideoCaptureControllerEventHandler* event_handler) { | 150 VideoCaptureControllerEventHandler* event_handler) { |
| 151 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 151 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 152 DVLOG(1) << "VideoCaptureController::StopCapture, id " << id.device_id; | 152 DVLOG(1) << "VideoCaptureController::StopCapture, id " << id.device_id; |
| 153 | 153 |
| 154 ControllerClient* client = FindClient(id, event_handler, pending_clients_); | 154 ControllerClient* client = FindClient(id, event_handler, pending_clients_); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 177 dib_it->second->references -= 1; | 177 dib_it->second->references -= 1; |
| 178 } | 178 } |
| 179 } | 179 } |
| 180 client->buffers.clear(); | 180 client->buffers.clear(); |
| 181 | 181 |
| 182 int session_id = client->parameters.session_id; | 182 int session_id = client->parameters.session_id; |
| 183 delete client; | 183 delete client; |
| 184 controller_clients_.remove(client); | 184 controller_clients_.remove(client); |
| 185 | 185 |
| 186 // No more clients. Stop device. | 186 // No more clients. Stop device. |
| 187 if (controller_clients_.empty() && state_ == video_capture::kStarted) { | 187 if (controller_clients_.empty() && state_ == VIDEO_CAPTURE_STATE_STARTED) { |
| 188 video_capture_manager_->Stop(session_id, | 188 video_capture_manager_->Stop(session_id, |
| 189 base::Bind(&VideoCaptureController::OnDeviceStopped, this)); | 189 base::Bind(&VideoCaptureController::OnDeviceStopped, this)); |
| 190 frame_info_available_ = false; | 190 frame_info_available_ = false; |
| 191 state_ = video_capture::kStopping; | 191 state_ = VIDEO_CAPTURE_STATE_STOPPING; |
| 192 } | 192 } |
| 193 } | 193 } |
| 194 | 194 |
| 195 void VideoCaptureController::StopSession( | 195 void VideoCaptureController::StopSession( |
| 196 int session_id) { | 196 int session_id) { |
| 197 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 197 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 198 DVLOG(1) << "VideoCaptureController::StopSession, id " << session_id; | 198 DVLOG(1) << "VideoCaptureController::StopSession, id " << session_id; |
| 199 | 199 |
| 200 ControllerClient* client = FindClient(session_id, pending_clients_); | 200 ControllerClient* client = FindClient(session_id, pending_clients_); |
| 201 if (!client) | 201 if (!client) |
| (...skipping 27 matching lines...) Expand all Loading... |
| 229 DCHECK_GT(dib_it->second->references, 0) | 229 DCHECK_GT(dib_it->second->references, 0) |
| 230 << "The buffer is not used by renderer."; | 230 << "The buffer is not used by renderer."; |
| 231 dib_it->second->references -= 1; | 231 dib_it->second->references -= 1; |
| 232 if (dib_it->second->references > 0) | 232 if (dib_it->second->references > 0) |
| 233 return; | 233 return; |
| 234 } | 234 } |
| 235 | 235 |
| 236 // When all buffers have been returned by clients and device has been | 236 // When all buffers have been returned by clients and device has been |
| 237 // called to stop, check if restart is needed. This could happen when | 237 // called to stop, check if restart is needed. This could happen when |
| 238 // capture needs to be restarted due to resolution change. | 238 // capture needs to be restarted due to resolution change. |
| 239 if (!ClientHasDIB() && state_ == video_capture::kStopping) { | 239 if (!ClientHasDIB() && state_ == VIDEO_CAPTURE_STATE_STOPPING) { |
| 240 PostStopping(); | 240 PostStopping(); |
| 241 } | 241 } |
| 242 } | 242 } |
| 243 | 243 |
| 244 /////////////////////////////////////////////////////////////////////////////// | 244 /////////////////////////////////////////////////////////////////////////////// |
| 245 // Implements VideoCaptureDevice::EventHandler. | 245 // Implements VideoCaptureDevice::EventHandler. |
| 246 // OnIncomingCapturedFrame is called the thread running the capture device. | 246 // OnIncomingCapturedFrame is called the thread running the capture device. |
| 247 // I.e.- DirectShow thread on windows and v4l2_thread on Linux. | 247 // I.e.- DirectShow thread on windows and v4l2_thread on Linux. |
| 248 void VideoCaptureController::OnIncomingCapturedFrame(const uint8* data, | 248 void VideoCaptureController::OnIncomingCapturedFrame(const uint8* data, |
| 249 int length, | 249 int length, |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 383 BrowserThread::PostTask(BrowserThread::IO, | 383 BrowserThread::PostTask(BrowserThread::IO, |
| 384 FROM_HERE, | 384 FROM_HERE, |
| 385 base::Bind(&VideoCaptureController::DoDeviceStoppedOnIOThread, this)); | 385 base::Bind(&VideoCaptureController::DoDeviceStoppedOnIOThread, this)); |
| 386 } | 386 } |
| 387 | 387 |
| 388 void VideoCaptureController::DoIncomingCapturedFrameOnIOThread( | 388 void VideoCaptureController::DoIncomingCapturedFrameOnIOThread( |
| 389 int buffer_id, base::Time timestamp) { | 389 int buffer_id, base::Time timestamp) { |
| 390 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 390 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 391 | 391 |
| 392 int count = 0; | 392 int count = 0; |
| 393 if (state_ == video_capture::kStarted) { | 393 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { |
| 394 for (ControllerClients::iterator client_it = controller_clients_.begin(); | 394 for (ControllerClients::iterator client_it = controller_clients_.begin(); |
| 395 client_it != controller_clients_.end(); client_it++) { | 395 client_it != controller_clients_.end(); client_it++) { |
| 396 if ((*client_it)->session_closed) | 396 if ((*client_it)->session_closed) |
| 397 continue; | 397 continue; |
| 398 | 398 |
| 399 (*client_it)->event_handler->OnBufferReady((*client_it)->controller_id, | 399 (*client_it)->event_handler->OnBufferReady((*client_it)->controller_id, |
| 400 buffer_id, timestamp); | 400 buffer_id, timestamp); |
| 401 (*client_it)->buffers.insert(buffer_id); | 401 (*client_it)->buffers.insert(buffer_id); |
| 402 count++; | 402 count++; |
| 403 } | 403 } |
| 404 } | 404 } |
| 405 | 405 |
| 406 base::AutoLock lock(lock_); | 406 base::AutoLock lock(lock_); |
| 407 if (owned_dibs_.find(buffer_id) != owned_dibs_.end()) { | 407 if (owned_dibs_.find(buffer_id) != owned_dibs_.end()) { |
| 408 DCHECK_EQ(owned_dibs_[buffer_id]->references, -1); | 408 DCHECK_EQ(owned_dibs_[buffer_id]->references, -1); |
| 409 owned_dibs_[buffer_id]->references = count; | 409 owned_dibs_[buffer_id]->references = count; |
| 410 } | 410 } |
| 411 } | 411 } |
| 412 | 412 |
| 413 void VideoCaptureController::DoFrameInfoOnIOThread() { | 413 void VideoCaptureController::DoFrameInfoOnIOThread() { |
| 414 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 414 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 415 DCHECK(owned_dibs_.empty()) | 415 DCHECK(owned_dibs_.empty()) |
| 416 << "Device is restarted without releasing shared memory."; | 416 << "Device is restarted without releasing shared memory."; |
| 417 | 417 |
| 418 // Allocate memory only when device has been started. | 418 // Allocate memory only when device has been started. |
| 419 if (state_ != video_capture::kStarted) | 419 if (state_ != VIDEO_CAPTURE_STATE_STARTED) |
| 420 return; | 420 return; |
| 421 | 421 |
| 422 bool frames_created = true; | 422 bool frames_created = true; |
| 423 const size_t needed_size = (frame_info_.width * frame_info_.height * 3) / 2; | 423 const size_t needed_size = (frame_info_.width * frame_info_.height * 3) / 2; |
| 424 { | 424 { |
| 425 base::AutoLock lock(lock_); | 425 base::AutoLock lock(lock_); |
| 426 for (size_t i = 1; i <= kNoOfDIBS; ++i) { | 426 for (size_t i = 1; i <= kNoOfDIBS; ++i) { |
| 427 scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory()); | 427 scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory()); |
| 428 if (!shared_memory->CreateAndMapAnonymous(needed_size)) { | 428 if (!shared_memory->CreateAndMapAnonymous(needed_size)) { |
| 429 frames_created = false; | 429 frames_created = false; |
| 430 break; | 430 break; |
| 431 } | 431 } |
| 432 SharedDIB* dib = new SharedDIB(shared_memory.release()); | 432 SharedDIB* dib = new SharedDIB(shared_memory.release()); |
| 433 owned_dibs_.insert(std::make_pair(i, dib)); | 433 owned_dibs_.insert(std::make_pair(i, dib)); |
| 434 } | 434 } |
| 435 } | 435 } |
| 436 // Check whether all DIBs were created successfully. | 436 // Check whether all DIBs were created successfully. |
| 437 if (!frames_created) { | 437 if (!frames_created) { |
| 438 state_ = video_capture::kError; | 438 state_ = VIDEO_CAPTURE_STATE_ERROR; |
| 439 for (ControllerClients::iterator client_it = controller_clients_.begin(); | 439 for (ControllerClients::iterator client_it = controller_clients_.begin(); |
| 440 client_it != controller_clients_.end(); client_it++) { | 440 client_it != controller_clients_.end(); client_it++) { |
| 441 (*client_it)->event_handler->OnError((*client_it)->controller_id); | 441 (*client_it)->event_handler->OnError((*client_it)->controller_id); |
| 442 } | 442 } |
| 443 return; | 443 return; |
| 444 } | 444 } |
| 445 frame_info_available_ = true; | 445 frame_info_available_ = true; |
| 446 | 446 |
| 447 for (ControllerClients::iterator client_it = controller_clients_.begin(); | 447 for (ControllerClients::iterator client_it = controller_clients_.begin(); |
| 448 client_it != controller_clients_.end(); client_it++) { | 448 client_it != controller_clients_.end(); client_it++) { |
| 449 SendFrameInfoAndBuffers((*client_it), static_cast<int>(needed_size)); | 449 SendFrameInfoAndBuffers((*client_it), static_cast<int>(needed_size)); |
| 450 } | 450 } |
| 451 } | 451 } |
| 452 | 452 |
| 453 void VideoCaptureController::DoErrorOnIOThread() { | 453 void VideoCaptureController::DoErrorOnIOThread() { |
| 454 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 454 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 455 state_ = video_capture::kError; | 455 state_ = VIDEO_CAPTURE_STATE_ERROR; |
| 456 ControllerClients::iterator client_it; | 456 ControllerClients::iterator client_it; |
| 457 for (client_it = controller_clients_.begin(); | 457 for (client_it = controller_clients_.begin(); |
| 458 client_it != controller_clients_.end(); client_it++) { | 458 client_it != controller_clients_.end(); client_it++) { |
| 459 (*client_it)->event_handler->OnError((*client_it)->controller_id); | 459 (*client_it)->event_handler->OnError((*client_it)->controller_id); |
| 460 } | 460 } |
| 461 for (client_it = pending_clients_.begin(); | 461 for (client_it = pending_clients_.begin(); |
| 462 client_it != pending_clients_.end(); client_it++) { | 462 client_it != pending_clients_.end(); client_it++) { |
| 463 (*client_it)->event_handler->OnError((*client_it)->controller_id); | 463 (*client_it)->event_handler->OnError((*client_it)->controller_id); |
| 464 } | 464 } |
| 465 } | 465 } |
| 466 | 466 |
| 467 void VideoCaptureController::DoDeviceStoppedOnIOThread() { | 467 void VideoCaptureController::DoDeviceStoppedOnIOThread() { |
| 468 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 468 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 469 device_in_use_ = false; | 469 device_in_use_ = false; |
| 470 if (state_ == video_capture::kStopping) { | 470 if (state_ == VIDEO_CAPTURE_STATE_STOPPING) { |
| 471 PostStopping(); | 471 PostStopping(); |
| 472 } | 472 } |
| 473 } | 473 } |
| 474 | 474 |
| 475 void VideoCaptureController::SendFrameInfoAndBuffers( | 475 void VideoCaptureController::SendFrameInfoAndBuffers( |
| 476 ControllerClient* client, int buffer_size) { | 476 ControllerClient* client, int buffer_size) { |
| 477 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 477 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 478 DCHECK(frame_info_available_); | 478 DCHECK(frame_info_available_); |
| 479 client->event_handler->OnFrameInfo(client->controller_id, | 479 client->event_handler->OnFrameInfo(client->controller_id, |
| 480 frame_info_.width, frame_info_.height, | 480 frame_info_.width, frame_info_.height, |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 519 } | 519 } |
| 520 } | 520 } |
| 521 return NULL; | 521 return NULL; |
| 522 } | 522 } |
| 523 | 523 |
| 524 // This function is called when all buffers have been returned to controller, | 524 // This function is called when all buffers have been returned to controller, |
| 525 // or when device is stopped. It decides whether the device needs to be | 525 // or when device is stopped. It decides whether the device needs to be |
| 526 // restarted. | 526 // restarted. |
| 527 void VideoCaptureController::PostStopping() { | 527 void VideoCaptureController::PostStopping() { |
| 528 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 528 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 529 DCHECK_EQ(state_, video_capture::kStopping); | 529 DCHECK_EQ(state_, VIDEO_CAPTURE_STATE_STOPPING); |
| 530 | 530 |
| 531 // When clients still have some buffers, or device has not been stopped yet, | 531 // When clients still have some buffers, or device has not been stopped yet, |
| 532 // do nothing. | 532 // do nothing. |
| 533 if (ClientHasDIB() || device_in_use_) | 533 if (ClientHasDIB() || device_in_use_) |
| 534 return; | 534 return; |
| 535 | 535 |
| 536 { | 536 { |
| 537 base::AutoLock lock(lock_); | 537 base::AutoLock lock(lock_); |
| 538 STLDeleteValues(&owned_dibs_); | 538 STLDeleteValues(&owned_dibs_); |
| 539 } | 539 } |
| 540 | 540 |
| 541 // No more client. Therefore the controller is stopped. | 541 // No more client. Therefore the controller is stopped. |
| 542 if (controller_clients_.empty() && pending_clients_.empty()) { | 542 if (controller_clients_.empty() && pending_clients_.empty()) { |
| 543 state_ = video_capture::kStopped; | 543 state_ = VIDEO_CAPTURE_STATE_STOPPED; |
| 544 return; | 544 return; |
| 545 } | 545 } |
| 546 | 546 |
| 547 // Restart the device. | 547 // Restart the device. |
| 548 current_params_.width = 0; | 548 current_params_.width = 0; |
| 549 current_params_.height = 0; | 549 current_params_.height = 0; |
| 550 ControllerClients::iterator client_it; | 550 ControllerClients::iterator client_it; |
| 551 for (client_it = controller_clients_.begin(); | 551 for (client_it = controller_clients_.begin(); |
| 552 client_it != controller_clients_.end(); client_it++) { | 552 client_it != controller_clients_.end(); client_it++) { |
| 553 if (current_params_.width < (*client_it)->parameters.width) | 553 if (current_params_.width < (*client_it)->parameters.width) |
| 554 current_params_.width = (*client_it)->parameters.width; | 554 current_params_.width = (*client_it)->parameters.width; |
| 555 if (current_params_.height < (*client_it)->parameters.height) | 555 if (current_params_.height < (*client_it)->parameters.height) |
| 556 current_params_.height = (*client_it)->parameters.height; | 556 current_params_.height = (*client_it)->parameters.height; |
| 557 } | 557 } |
| 558 for (client_it = pending_clients_.begin(); | 558 for (client_it = pending_clients_.begin(); |
| 559 client_it != pending_clients_.end(); ) { | 559 client_it != pending_clients_.end(); ) { |
| 560 if (current_params_.width < (*client_it)->parameters.width) | 560 if (current_params_.width < (*client_it)->parameters.width) |
| 561 current_params_.width = (*client_it)->parameters.width; | 561 current_params_.width = (*client_it)->parameters.width; |
| 562 if (current_params_.height < (*client_it)->parameters.height) | 562 if (current_params_.height < (*client_it)->parameters.height) |
| 563 current_params_.height = (*client_it)->parameters.height; | 563 current_params_.height = (*client_it)->parameters.height; |
| 564 controller_clients_.push_back((*client_it)); | 564 controller_clients_.push_back((*client_it)); |
| 565 pending_clients_.erase(client_it++); | 565 pending_clients_.erase(client_it++); |
| 566 } | 566 } |
| 567 // Request the manager to start the actual capture. | 567 // Request the manager to start the actual capture. |
| 568 video_capture_manager_->Start(current_params_, this); | 568 video_capture_manager_->Start(current_params_, this); |
| 569 state_ = video_capture::kStarted; | 569 state_ = VIDEO_CAPTURE_STATE_STARTED; |
| 570 device_in_use_ = true; | 570 device_in_use_ = true; |
| 571 } | 571 } |
| 572 | 572 |
| 573 bool VideoCaptureController::ClientHasDIB() { | 573 bool VideoCaptureController::ClientHasDIB() { |
| 574 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 574 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 575 base::AutoLock lock(lock_); | 575 base::AutoLock lock(lock_); |
| 576 for (DIBMap::iterator dib_it = owned_dibs_.begin(); | 576 for (DIBMap::iterator dib_it = owned_dibs_.begin(); |
| 577 dib_it != owned_dibs_.end(); dib_it++) { | 577 dib_it != owned_dibs_.end(); dib_it++) { |
| 578 if (dib_it->second->references > 0) | 578 if (dib_it->second->references > 0) |
| 579 return true; | 579 return true; |
| 580 } | 580 } |
| 581 return false; | 581 return false; |
| 582 } | 582 } |
| 583 |
| 584 } // namespace content |
| OLD | NEW |