| Index: content/browser/renderer_host/media/video_capture_controller.cc
|
| ===================================================================
|
| --- content/browser/renderer_host/media/video_capture_controller.cc (revision 108126)
|
| +++ content/browser/renderer_host/media/video_capture_controller.cc (working copy)
|
| @@ -11,56 +11,230 @@
|
| #include "content/public/browser/browser_thread.h"
|
| #include "media/base/yuv_convert.h"
|
|
|
| -// The number of TransportDIBs VideoCaptureController allocate.
|
| +// The number of DIBs VideoCaptureController allocate.
|
| static const size_t kNoOfDIBS = 3;
|
|
|
| +struct VideoCaptureController::ControllerClient {
|
| + ControllerClient(
|
| + const VideoCaptureControllerID& id,
|
| + VideoCaptureControllerEventHandler* handler,
|
| + base::ProcessHandle render_process,
|
| + const media::VideoCaptureParams& params)
|
| + : controller_id(id),
|
| + event_handler(handler),
|
| + render_process_handle(render_process),
|
| + parameters(params),
|
| + report_ready_to_delete(false) {
|
| + }
|
| +
|
| + ~ControllerClient() {}
|
| +
|
| + // ID used for identifying this object.
|
| + VideoCaptureControllerID controller_id;
|
| + VideoCaptureControllerEventHandler* event_handler;
|
| +
|
| + // Handle to the render process that will receive the DIBs.
|
| + base::ProcessHandle render_process_handle;
|
| + media::VideoCaptureParams parameters;
|
| +
|
| + // Buffers used by this client.
|
| + std::list<int> buffers;
|
| +
|
| + // Record client's status when it has called StopCapture, but haven't
|
| + // returned all buffers.
|
| + bool report_ready_to_delete;
|
| +};
|
| +
|
| +struct VideoCaptureController::SharedDIB {
|
| + SharedDIB(base::SharedMemory* ptr)
|
| + : shared_memory(ptr),
|
| + references(0) {
|
| + }
|
| +
|
| + ~SharedDIB() {}
|
| +
|
| + // The memory created to be shared with renderer processes.
|
| + scoped_ptr<base::SharedMemory> shared_memory;
|
| +
|
| + // Number of renderer processes which hold this shared memory.
|
| + // renderer process is represented by VidoeCaptureHost.
|
| + int references;
|
| +};
|
| +
|
| VideoCaptureController::VideoCaptureController(
|
| - const VideoCaptureControllerID& id,
|
| - base::ProcessHandle render_process,
|
| - VideoCaptureControllerEventHandler* event_handler,
|
| media_stream::VideoCaptureManager* video_capture_manager)
|
| - : render_handle_(render_process),
|
| - report_ready_to_delete_(false),
|
| - event_handler_(event_handler),
|
| - id_(id),
|
| - video_capture_manager_(video_capture_manager) {
|
| - memset(¶ms_, 0, sizeof(params_));
|
| + : frame_info_available_(false),
|
| + video_capture_manager_(video_capture_manager),
|
| + device_in_use_(false),
|
| + state_(media::VideoCapture::kStopped) {
|
| + memset(¤t_params_, 0, sizeof(current_params_));
|
| }
|
|
|
| VideoCaptureController::~VideoCaptureController() {
|
| - // Delete all TransportDIBs.
|
| + // Delete all DIBs.
|
| STLDeleteContainerPairSecondPointers(owned_dibs_.begin(),
|
| owned_dibs_.end());
|
| + STLDeleteContainerPointers(controller_clients_.begin(),
|
| + controller_clients_.end());
|
| + STLDeleteContainerPointers(pending_clients_.begin(),
|
| + pending_clients_.end());
|
| }
|
|
|
| void VideoCaptureController::StartCapture(
|
| + const VideoCaptureControllerID& id,
|
| + VideoCaptureControllerEventHandler* event_handler,
|
| + base::ProcessHandle render_process,
|
| const media::VideoCaptureParams& params) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + // Signal error in case device is already in error state.
|
| + if (state_ == media::VideoCapture::kError) {
|
| + event_handler->OnError(id);
|
| + return;
|
| + }
|
|
|
| - params_ = params;
|
| + // Do nothing if this client has called StartCapture before.
|
| + if (FindClient(id, event_handler, controller_clients_) ||
|
| + FindClient(id, event_handler, pending_clients_))
|
| + return;
|
| +
|
| + ControllerClient* client = new ControllerClient(id, event_handler,
|
| + render_process, params);
|
| + // In case capture has been started, need to check different condtions.
|
| + if (state_ == media::VideoCapture::kStarted) {
|
| + // This client has higher resolution than what is currently requested.
|
| + // Need restart capturing.
|
| + if (params.width > current_params_.width ||
|
| + params.height > current_params_.height) {
|
| + video_capture_manager_->Stop(current_params_.session_id,
|
| + base::Bind(&VideoCaptureController::OnDeviceStopped, this));
|
| + frame_info_available_ = false;
|
| + state_ = media::VideoCapture::kStopping;
|
| + pending_clients_.push_back(client);
|
| + return;
|
| + }
|
| +
|
| + // This client's resolution is no larger than what's currently requested.
|
| + // When frame_info has been returned by device, send them to client.
|
| + if (frame_info_available_) {
|
| + int buffer_size = (frame_info_.width * frame_info_.height * 3) / 2;
|
| + SendFrameInfoAndBuffers(client, buffer_size);
|
| + }
|
| + controller_clients_.push_back(client);
|
| + return;
|
| + }
|
| +
|
| + // In case the device is in the middle of stopping, put the client in
|
| + // pending queue.
|
| + if (state_ == media::VideoCapture::kStopping) {
|
| + pending_clients_.push_back(client);
|
| + return;
|
| + }
|
| +
|
| + // Fresh start.
|
| + controller_clients_.push_back(client);
|
| + current_params_ = params;
|
| // Order the manager to start the actual capture.
|
| video_capture_manager_->Start(params, this);
|
| + state_ = media::VideoCapture::kStarted;
|
| }
|
|
|
| -void VideoCaptureController::StopCapture(base::Closure stopped_cb) {
|
| +void VideoCaptureController::StopCapture(
|
| + const VideoCaptureControllerID& id,
|
| + VideoCaptureControllerEventHandler* event_handler,
|
| + bool force_buffer_return) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
|
|
| - video_capture_manager_->Stop(params_.session_id,
|
| - base::Bind(&VideoCaptureController::OnDeviceStopped, this, stopped_cb));
|
| + ControllerClient* client = FindClient(id, event_handler, pending_clients_);
|
| + // If the client is still in pending queue, just remove it.
|
| + if (client) {
|
| + client->event_handler->OnReadyToDelete(client->controller_id);
|
| + pending_clients_.remove(client);
|
| + return;
|
| + }
|
| +
|
| + client = FindClient(id, event_handler, controller_clients_);
|
| + DCHECK(client) << "Client should have called StartCapture()";
|
| +
|
| + if (force_buffer_return) {
|
| + // The client requests to return buffers which means it can't return
|
| + // buffers normally. After buffers are returned, client is free to
|
| + // delete itself. No need to call OnReadyToDelete.
|
| +
|
| + // Return all buffers held by the clients.
|
| + for (std::list<int>::iterator buffer_it = client->buffers.begin();
|
| + buffer_it != client->buffers.end(); ++buffer_it) {
|
| + int buffer_id = *buffer_it;
|
| + DIBMap::iterator dib_it = owned_dibs_.find(buffer_id);
|
| + if (dib_it == owned_dibs_.end())
|
| + continue;
|
| +
|
| + {
|
| + base::AutoLock lock(lock_);
|
| + DCHECK_GT(dib_it->second->references, 0)
|
| + << "The buffer is not used by renderer.";
|
| + dib_it->second->references -= 1;
|
| + }
|
| + }
|
| + client->buffers.clear();
|
| + } else {
|
| + // Normal way to stop capture.
|
| + if (!client->buffers.empty()) {
|
| + // There are still some buffers held by the client.
|
| + client->report_ready_to_delete = true;
|
| + return;
|
| + }
|
| + // No buffer is held by the client. Ready to delete.
|
| + client->event_handler->OnReadyToDelete(client->controller_id);
|
| + }
|
| +
|
| + delete client;
|
| + controller_clients_.remove(client);
|
| +
|
| + // No more clients. Stop device.
|
| + if (controller_clients_.empty()) {
|
| + video_capture_manager_->Stop(current_params_.session_id,
|
| + base::Bind(&VideoCaptureController::OnDeviceStopped, this));
|
| + frame_info_available_ = false;
|
| + state_ = media::VideoCapture::kStopping;
|
| + }
|
| }
|
|
|
| -void VideoCaptureController::ReturnBuffer(int buffer_id) {
|
| +void VideoCaptureController::ReturnBuffer(
|
| + const VideoCaptureControllerID& id,
|
| + VideoCaptureControllerEventHandler* event_handler,
|
| + int buffer_id) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
|
|
| - bool ready_to_delete;
|
| + ControllerClient* client = FindClient(id, event_handler,
|
| + controller_clients_);
|
| + DIBMap::iterator dib_it = owned_dibs_.find(buffer_id);
|
| + // If this buffer is not held by this client, or this client doesn't exist
|
| + // in controller, do nothing.
|
| + if (!client || dib_it == owned_dibs_.end())
|
| + return;
|
| +
|
| + client->buffers.remove(buffer_id);
|
| + // If this client has called StopCapture and doesn't hold any buffer after
|
| + // after this return, ready to delete this client.
|
| + if (client->report_ready_to_delete && client->buffers.empty()) {
|
| + client->event_handler->OnReadyToDelete(client->controller_id);
|
| + delete client;
|
| + controller_clients_.remove(client);
|
| + }
|
| {
|
| base::AutoLock lock(lock_);
|
| - free_dibs_.push_back(buffer_id);
|
| - ready_to_delete = (free_dibs_.size() == owned_dibs_.size()) &&
|
| - report_ready_to_delete_;
|
| + DCHECK_GT(dib_it->second->references, 0)
|
| + << "The buffer is not used by renderer.";
|
| + dib_it->second->references -= 1;
|
| + if (dib_it->second->references > 0)
|
| + return;
|
| }
|
| - if (ready_to_delete) {
|
| - event_handler_->OnReadyToDelete(id_);
|
| +
|
| + // When all buffers have been returned by clients and device has been
|
| + // called to stop, check if restart is needed. This could happen when
|
| + // some clients call StopCapture before returning all buffers.
|
| + if (!ClientHasDIB() && state_ == media::VideoCapture::kStopping) {
|
| + PostStopping();
|
| }
|
| }
|
|
|
| @@ -73,22 +247,22 @@
|
| base::Time timestamp) {
|
| int buffer_id = 0;
|
| base::SharedMemory* dib = NULL;
|
| - // Check if there is a TransportDIB to fill.
|
| - bool buffer_exist = false;
|
| {
|
| base::AutoLock lock(lock_);
|
| - if (!report_ready_to_delete_ && free_dibs_.size() > 0) {
|
| - buffer_id = free_dibs_.front();
|
| - free_dibs_.pop_front();
|
| - DIBMap::iterator it = owned_dibs_.find(buffer_id);
|
| - if (it != owned_dibs_.end()) {
|
| - dib = it->second;
|
| - buffer_exist = true;
|
| + for (DIBMap::iterator dib_it = owned_dibs_.begin();
|
| + dib_it != owned_dibs_.end(); dib_it++) {
|
| + if (dib_it->second->references == 0) {
|
| + buffer_id = dib_it->first;
|
| + // Use special value "-1" in order to not be treated as buffer at
|
| + // renderer side.
|
| + dib_it->second->references = -1;
|
| + dib = dib_it->second->shared_memory.get();
|
| + break;
|
| }
|
| }
|
| }
|
|
|
| - if (!buffer_exist) {
|
| + if (!dib) {
|
| return;
|
| }
|
|
|
| @@ -96,6 +270,9 @@
|
| CHECK(dib->created_size() >= static_cast<size_t> (frame_info_.width *
|
| frame_info_.height * 3) /
|
| 2);
|
| + uint8* yplane = target;
|
| + uint8* uplane = target + frame_info_.width * frame_info_.height;
|
| + uint8* vplane = uplane + (frame_info_.width * frame_info_.height) / 4;
|
|
|
| // Do color conversion from the camera format to I420.
|
| switch (frame_info_.color) {
|
| @@ -106,29 +283,18 @@
|
| break;
|
| }
|
| case media::VideoCaptureDevice::kYUY2: {
|
| - uint8* yplane = target;
|
| - uint8* uplane = target + frame_info_.width * frame_info_.height;
|
| - uint8* vplane = uplane + (frame_info_.width * frame_info_.height) / 4;
|
| media::ConvertYUY2ToYUV(data, yplane, uplane, vplane, frame_info_.width,
|
| frame_info_.height);
|
| break;
|
| }
|
| case media::VideoCaptureDevice::kRGB24: {
|
| -#if defined(OS_WIN) // RGB on Windows start at the bottom line.
|
| - uint8* yplane = target;
|
| - uint8* uplane = target + frame_info_.width * frame_info_.height;
|
| - uint8* vplane = uplane + (frame_info_.width * frame_info_.height) / 4;
|
| int ystride = frame_info_.width;
|
| int uvstride = frame_info_.width / 2;
|
| - int rgb_stride = - 3 * frame_info_.width;
|
| +#if defined(OS_WIN) // RGB on Windows start at the bottom line.
|
| + int rgb_stride = -3 * frame_info_.width;
|
| const uint8* rgb_src = data + 3 * frame_info_.width *
|
| (frame_info_.height -1);
|
| #else
|
| - uint8* yplane = target;
|
| - uint8* uplane = target + frame_info_.width * frame_info_.height;
|
| - uint8* vplane = uplane + (frame_info_.width * frame_info_.height) / 4;
|
| - int ystride = frame_info_.width;
|
| - int uvstride = frame_info_.width / 2;
|
| int rgb_stride = 3 * frame_info_.width;
|
| const uint8* rgb_src = data;
|
| #endif
|
| @@ -138,9 +304,6 @@
|
| break;
|
| }
|
| case media::VideoCaptureDevice::kARGB: {
|
| - uint8* yplane = target;
|
| - uint8* uplane = target + frame_info_.width * frame_info_.height;
|
| - uint8* vplane = uplane + (frame_info_.width * frame_info_.height) / 4;
|
| media::ConvertRGB32ToYUV(data, yplane, uplane, vplane, frame_info_.width,
|
| frame_info_.height, frame_info_.width * 4,
|
| frame_info_.width, frame_info_.width / 2);
|
| @@ -150,62 +313,209 @@
|
| NOTREACHED();
|
| }
|
|
|
| - event_handler_->OnBufferReady(id_, buffer_id, timestamp);
|
| + BrowserThread::PostTask(BrowserThread::IO,
|
| + FROM_HERE,
|
| + base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
|
| + this, buffer_id, timestamp));
|
| }
|
|
|
| void VideoCaptureController::OnError() {
|
| - event_handler_->OnError(id_);
|
| - video_capture_manager_->Error(params_.session_id);
|
| + video_capture_manager_->Error(current_params_.session_id);
|
| + BrowserThread::PostTask(BrowserThread::IO,
|
| + FROM_HERE,
|
| + base::Bind(&VideoCaptureController::DoErrorOnIOThread, this));
|
| }
|
|
|
| void VideoCaptureController::OnFrameInfo(
|
| const media::VideoCaptureDevice::Capability& info) {
|
| - DCHECK(owned_dibs_.empty());
|
| + BrowserThread::PostTask(BrowserThread::IO,
|
| + FROM_HERE,
|
| + base::Bind(&VideoCaptureController::DoFrameInfoOnIOThread,
|
| + this, info));
|
| +}
|
| +
|
| +void VideoCaptureController::DoIncomingCapturedFrameOnIOThread(
|
| + int buffer_id, base::Time timestamp) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| +
|
| + int count = 0;
|
| + if (state_ == media::VideoCapture::kStarted) {
|
| + for (ControllerClients::iterator client_it = controller_clients_.begin();
|
| + client_it != controller_clients_.end(); client_it++) {
|
| + if ((*client_it)->report_ready_to_delete)
|
| + continue;
|
| +
|
| + (*client_it)->event_handler->OnBufferReady((*client_it)->controller_id,
|
| + buffer_id, timestamp);
|
| + (*client_it)->buffers.push_back(buffer_id);
|
| + count++;
|
| + }
|
| + }
|
| +
|
| + base::AutoLock lock(lock_);
|
| + DCHECK_EQ(owned_dibs_[buffer_id]->references, -1);
|
| + owned_dibs_[buffer_id]->references = count;
|
| +}
|
| +
|
| +void VideoCaptureController::DoErrorOnIOThread() {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + state_ = media::VideoCapture::kError;
|
| + ControllerClients::iterator client_it;
|
| + for (client_it = controller_clients_.begin();
|
| + client_it != controller_clients_.end(); client_it++) {
|
| + (*client_it)->event_handler->OnError((*client_it)->controller_id);
|
| + }
|
| + for (client_it = pending_clients_.begin();
|
| + client_it != pending_clients_.end(); client_it++) {
|
| + (*client_it)->event_handler->OnError((*client_it)->controller_id);
|
| + }
|
| +}
|
| +
|
| +void VideoCaptureController::DoFrameInfoOnIOThread(
|
| + const media::VideoCaptureDevice::Capability info) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + DCHECK(owned_dibs_.empty())
|
| + << "Device is restarted without releasing shared memory.";
|
| +
|
| bool frames_created = true;
|
| const size_t needed_size = (info.width * info.height * 3) / 2;
|
| - for (size_t i = 1; i <= kNoOfDIBS; ++i) {
|
| - base::SharedMemory* shared_memory = new base::SharedMemory();
|
| - if (!shared_memory->CreateAndMapAnonymous(needed_size)) {
|
| - frames_created = false;
|
| - break;
|
| + {
|
| + base::AutoLock lock(lock_);
|
| + for (size_t i = 1; i <= kNoOfDIBS; ++i) {
|
| + base::SharedMemory* shared_memory = new base::SharedMemory();
|
| + if (!shared_memory->CreateAndMapAnonymous(needed_size)) {
|
| + frames_created = false;
|
| + break;
|
| + }
|
| + SharedDIB* dib = new SharedDIB(shared_memory);
|
| + owned_dibs_.insert(std::make_pair(i, dib));
|
| }
|
| + }
|
| + // Check whether all DIBs were created successfully.
|
| + if (!frames_created) {
|
| + state_ = media::VideoCapture::kError;
|
| + for (ControllerClients::iterator client_it = controller_clients_.begin();
|
| + client_it != controller_clients_.end(); client_it++) {
|
| + (*client_it)->event_handler->OnError((*client_it)->controller_id);
|
| + }
|
| + return;
|
| + }
|
| + frame_info_= info;
|
| + frame_info_available_ = true;
|
| +
|
| + for (ControllerClients::iterator client_it = controller_clients_.begin();
|
| + client_it != controller_clients_.end(); client_it++) {
|
| + SendFrameInfoAndBuffers((*client_it), static_cast<int>(needed_size));
|
| + }
|
| +}
|
| +
|
| +void VideoCaptureController::SendFrameInfoAndBuffers(
|
| + ControllerClient* client, int buffer_size) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + DCHECK(frame_info_available_);
|
| + client->event_handler->OnFrameInfo(client->controller_id,
|
| + frame_info_.width, frame_info_.height,
|
| + frame_info_.frame_rate);
|
| + for (DIBMap::iterator dib_it = owned_dibs_.begin();
|
| + dib_it != owned_dibs_.end(); dib_it++) {
|
| + base::SharedMemory* shared_memory = dib_it->second->shared_memory.get();
|
| + int index = dib_it->first;
|
| base::SharedMemoryHandle remote_handle;
|
| - shared_memory->ShareToProcess(render_handle_, &remote_handle);
|
| + shared_memory->ShareToProcess(client->render_process_handle,
|
| + &remote_handle);
|
| + client->event_handler->OnBufferCreated(client->controller_id,
|
| + remote_handle,
|
| + buffer_size,
|
| + index);
|
| + }
|
| +}
|
|
|
| - base::AutoLock lock(lock_);
|
| - owned_dibs_.insert(std::make_pair(i, shared_memory));
|
| - free_dibs_.push_back(i);
|
| - event_handler_->OnBufferCreated(id_, remote_handle,
|
| - static_cast<int>(needed_size),
|
| - static_cast<int>(i));
|
| +// This function is called when all buffers have been returned to controller,
|
| +// or when device is stopped. It decides whether the device needs to be
|
| +// restarted.
|
| +void VideoCaptureController::PostStopping() {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + DCHECK_EQ(state_, media::VideoCapture::kStopping);
|
| +
|
| + // When clients still have some buffers, or device has not been stopped yet,
|
| + // do nothing.
|
| + if (ClientHasDIB() || device_in_use_)
|
| + return;
|
| +
|
| + // It's safe to free all DIB's on IO thread since device won't send
|
| + // buffer over.
|
| + STLDeleteValues(&owned_dibs_);
|
| +
|
| + // No more client. Therefore the controller is stopped.
|
| + if (controller_clients_.empty() && pending_clients_.empty()) {
|
| + state_ = media::VideoCapture::kStopped;
|
| + return;
|
| }
|
| - frame_info_= info;
|
|
|
| - // Check that all DIBs where created successfully.
|
| - if (!frames_created) {
|
| - event_handler_->OnError(id_);
|
| + // Restart the device.
|
| + current_params_.width = 0;
|
| + current_params_.height = 0;
|
| + ControllerClients::iterator client_it;
|
| + for (client_it = controller_clients_.begin();
|
| + client_it != controller_clients_.end(); client_it++) {
|
| + if (current_params_.width < (*client_it)->parameters.width)
|
| + current_params_.width = (*client_it)->parameters.width;
|
| + if (current_params_.height < (*client_it)->parameters.height)
|
| + current_params_.height = (*client_it)->parameters.height;
|
| }
|
| - event_handler_->OnFrameInfo(id_, info.width, info.height, info.frame_rate);
|
| + for (client_it = pending_clients_.begin();
|
| + client_it != pending_clients_.end(); ) {
|
| + if (current_params_.width < (*client_it)->parameters.width)
|
| + current_params_.width = (*client_it)->parameters.width;
|
| + if (current_params_.height < (*client_it)->parameters.height)
|
| + current_params_.height = (*client_it)->parameters.height;
|
| + controller_clients_.push_back((*client_it));
|
| + pending_clients_.erase(client_it++);
|
| + }
|
| + // Request the manager to start the actual capture.
|
| + video_capture_manager_->Start(current_params_, this);
|
| + state_ = media::VideoCapture::kStarted;
|
| }
|
|
|
| +bool VideoCaptureController::ClientHasDIB() {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + base::AutoLock lock(lock_);
|
| + for (DIBMap::iterator dib_it = owned_dibs_.begin();
|
| + dib_it != owned_dibs_.end(); dib_it++) {
|
| + if (dib_it->second->references > 0)
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +VideoCaptureController::ControllerClient*
|
| +VideoCaptureController::FindClient(
|
| + const VideoCaptureControllerID& id,
|
| + VideoCaptureControllerEventHandler* handler,
|
| + const ControllerClients& clients) {
|
| + for (ControllerClients::const_iterator client_it = clients.begin();
|
| + client_it != clients.end(); client_it++) {
|
| + if ((*client_it)->controller_id == id &&
|
| + (*client_it)->event_handler == handler) {
|
| + return *client_it;
|
| + }
|
| + }
|
| + return NULL;
|
| +}
|
| +
|
| ///////////////////////////////////////////////////////////////////////////////
|
| // Called by VideoCaptureManager when a device have been stopped.
|
| -// This will report to the event handler that this object is ready to be deleted
|
| -// if all DIBS have been returned.
|
| -void VideoCaptureController::OnDeviceStopped(base::Closure stopped_cb) {
|
| - bool ready_to_delete_now;
|
| +void VideoCaptureController::OnDeviceStopped() {
|
| + BrowserThread::PostTask(BrowserThread::IO,
|
| + FROM_HERE,
|
| + base::Bind(&VideoCaptureController::DoDeviceStoppedOnIOThread, this));
|
| +}
|
|
|
| - {
|
| - base::AutoLock lock(lock_);
|
| - // Set flag to indicate we need to report when all DIBs have been returned.
|
| - report_ready_to_delete_ = true;
|
| - ready_to_delete_now = (free_dibs_.size() == owned_dibs_.size());
|
| +void VideoCaptureController::DoDeviceStoppedOnIOThread() {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + device_in_use_ = false;
|
| + if (state_ == media::VideoCapture::kStopping) {
|
| + PostStopping();
|
| }
|
| +}
|
|
|
| - if (ready_to_delete_now) {
|
| - event_handler_->OnReadyToDelete(id_);
|
| - }
|
| -
|
| - if (!stopped_cb.is_null())
|
| - stopped_cb.Run();
|
| -}
|
|
|