| Index: content/renderer/media/video_capture_impl.cc
|
| diff --git a/content/renderer/media/video_capture_impl.cc b/content/renderer/media/video_capture_impl.cc
|
| index bda203a41dc211014b6c1a71c234a4c7cae00d2b..b9a61f3d05b4db4a0b24afebb01adde58acd056a 100644
|
| --- a/content/renderer/media/video_capture_impl.cc
|
| +++ b/content/renderer/media/video_capture_impl.cc
|
| @@ -1,13 +1,6 @@
|
| // Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
| -//
|
| -// Notes about usage of this object by VideoCaptureImplManager.
|
| -//
|
| -// VideoCaptureImplManager access this object by using a Unretained()
|
| -// binding and tasks on the IO thread. It is then important that
|
| -// VideoCaptureImpl never post task to itself. All operations must be
|
| -// synchronous.
|
|
|
| #include "content/renderer/media/video_capture_impl.h"
|
|
|
| @@ -39,81 +32,130 @@
|
| DISALLOW_COPY_AND_ASSIGN(ClientBuffer);
|
| };
|
|
|
| -VideoCaptureImpl::ClientInfo::ClientInfo() {}
|
| -VideoCaptureImpl::ClientInfo::~ClientInfo() {}
|
| +bool VideoCaptureImpl::CaptureStarted() {
|
| + return state_ == VIDEO_CAPTURE_STATE_STARTED;
|
| +}
|
| +
|
| +int VideoCaptureImpl::CaptureFrameRate() {
|
| + return last_frame_format_.frame_rate;
|
| +}
|
|
|
| VideoCaptureImpl::VideoCaptureImpl(
|
| const media::VideoCaptureSessionId session_id,
|
| VideoCaptureMessageFilter* filter)
|
| - : message_filter_(filter),
|
| + : VideoCapture(),
|
| + message_filter_(filter),
|
| + io_message_loop_proxy_(ChildProcess::current()->io_message_loop_proxy()),
|
| device_id_(0),
|
| session_id_(session_id),
|
| suspended_(false),
|
| state_(VIDEO_CAPTURE_STATE_STOPPED),
|
| weak_factory_(this) {
|
| DCHECK(filter);
|
| - thread_checker_.DetachFromThread();
|
| -}
|
| -
|
| -VideoCaptureImpl::~VideoCaptureImpl() {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| -}
|
| +}
|
| +
|
| +VideoCaptureImpl::~VideoCaptureImpl() {}
|
|
|
| void VideoCaptureImpl::Init() {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| + io_message_loop_proxy_->PostTask(FROM_HERE,
|
| + base::Bind(&VideoCaptureImpl::InitOnIOThread,
|
| + base::Unretained(this)));
|
| +}
|
| +
|
| +void VideoCaptureImpl::DeInit(base::Closure done_cb) {
|
| + io_message_loop_proxy_->PostTask(FROM_HERE,
|
| + base::Bind(&VideoCaptureImpl::DeInitOnIOThread,
|
| + base::Unretained(this),
|
| + done_cb));
|
| +}
|
| +
|
| +void VideoCaptureImpl::SuspendCapture(bool suspend) {
|
| + io_message_loop_proxy_->PostTask(FROM_HERE,
|
| + base::Bind(&VideoCaptureImpl::SuspendCaptureOnIOThread,
|
| + base::Unretained(this),
|
| + suspend));
|
| +}
|
| +
|
| +void VideoCaptureImpl::StartCapture(
|
| + media::VideoCapture::EventHandler* handler,
|
| + const media::VideoCaptureParams& params) {
|
| + io_message_loop_proxy_->PostTask(FROM_HERE,
|
| + base::Bind(&VideoCaptureImpl::StartCaptureOnIOThread,
|
| + base::Unretained(this), handler, params));
|
| +}
|
| +
|
| +void VideoCaptureImpl::StopCapture(
|
| + media::VideoCapture::EventHandler* handler) {
|
| + io_message_loop_proxy_->PostTask(FROM_HERE,
|
| + base::Bind(&VideoCaptureImpl::StopCaptureOnIOThread,
|
| + base::Unretained(this), handler));
|
| +}
|
| +
|
| +void VideoCaptureImpl::GetDeviceSupportedFormats(
|
| + const DeviceFormatsCallback& callback) {
|
| + DCHECK(!callback.is_null());
|
| + io_message_loop_proxy_->PostTask(FROM_HERE,
|
| + base::Bind(&VideoCaptureImpl::GetDeviceSupportedFormatsOnIOThread,
|
| + base::Unretained(this), media::BindToCurrentLoop(callback)));
|
| +}
|
| +
|
| +void VideoCaptureImpl::GetDeviceFormatsInUse(
|
| + const DeviceFormatsInUseCallback& callback) {
|
| + DCHECK(!callback.is_null());
|
| + io_message_loop_proxy_->PostTask(FROM_HERE,
|
| + base::Bind(&VideoCaptureImpl::GetDeviceFormatsInUseOnIOThread,
|
| + base::Unretained(this), media::BindToCurrentLoop(callback)));
|
| +}
|
| +
|
| +void VideoCaptureImpl::InitOnIOThread() {
|
| + DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
|
| message_filter_->AddDelegate(this);
|
| }
|
|
|
| -void VideoCaptureImpl::DeInit() {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| +void VideoCaptureImpl::DeInitOnIOThread(base::Closure done_cb) {
|
| + DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
|
| if (state_ == VIDEO_CAPTURE_STATE_STARTED)
|
| Send(new VideoCaptureHostMsg_Stop(device_id_));
|
| message_filter_->RemoveDelegate(this);
|
| -}
|
| -
|
| -void VideoCaptureImpl::SuspendCapture(bool suspend) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| + done_cb.Run();
|
| +}
|
| +
|
| +void VideoCaptureImpl::SuspendCaptureOnIOThread(bool suspend) {
|
| + DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
|
| suspended_ = suspend;
|
| }
|
|
|
| -void VideoCaptureImpl::StartCapture(
|
| - int client_id,
|
| - const media::VideoCaptureParams& params,
|
| - const VideoCaptureStateUpdateCB& state_update_cb,
|
| - const VideoCaptureDeliverFrameCB& deliver_frame_cb) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - ClientInfo client_info;
|
| - client_info.params = params;
|
| - client_info.state_update_cb = state_update_cb;
|
| - client_info.deliver_frame_cb = deliver_frame_cb;
|
| -
|
| +void VideoCaptureImpl::StartCaptureOnIOThread(
|
| + media::VideoCapture::EventHandler* handler,
|
| + const media::VideoCaptureParams& params) {
|
| + DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
|
| if (state_ == VIDEO_CAPTURE_STATE_ERROR) {
|
| - state_update_cb.Run(VIDEO_CAPTURE_STATE_ERROR);
|
| - } else if (clients_pending_on_filter_.count(client_id) ||
|
| - clients_pending_on_restart_.count(client_id) ||
|
| - clients_.count(client_id)) {
|
| - LOG(FATAL) << "This client has already started.";
|
| + handler->OnError(this, 1);
|
| + handler->OnRemoved(this);
|
| + } else if ((clients_pending_on_filter_.find(handler) !=
|
| + clients_pending_on_filter_.end()) ||
|
| + (clients_pending_on_restart_.find(handler) !=
|
| + clients_pending_on_restart_.end()) ||
|
| + clients_.find(handler) != clients_.end() ) {
|
| + // This client has started.
|
| } else if (!device_id_) {
|
| - clients_pending_on_filter_[client_id] = client_info;
|
| + clients_pending_on_filter_[handler] = params;
|
| } else {
|
| - // Note: |state_| might not be started at this point. But we tell
|
| - // client that we have started.
|
| - state_update_cb.Run(VIDEO_CAPTURE_STATE_STARTED);
|
| + handler->OnStarted(this);
|
| if (state_ == VIDEO_CAPTURE_STATE_STARTED) {
|
| - clients_[client_id] = client_info;
|
| + clients_[handler] = params;
|
| // TODO(sheu): Allowing resolution change will require that all
|
| // outstanding clients of a capture session support resolution change.
|
| DCHECK_EQ(params_.allow_resolution_change,
|
| params.allow_resolution_change);
|
| } else if (state_ == VIDEO_CAPTURE_STATE_STOPPING) {
|
| - clients_pending_on_restart_[client_id] = client_info;
|
| + clients_pending_on_restart_[handler] = params;
|
| DVLOG(1) << "StartCapture: Got new resolution "
|
| << params.requested_format.frame_size.ToString()
|
| << " during stopping.";
|
| } else {
|
| - clients_[client_id] = client_info;
|
| - if (state_ == VIDEO_CAPTURE_STATE_STARTED)
|
| - return;
|
| + clients_[handler] = params;
|
| + DCHECK_EQ(1ul, clients_.size());
|
| params_ = params;
|
| if (params_.requested_format.frame_rate >
|
| media::limits::kMaxFramesPerSecond) {
|
| @@ -128,18 +170,16 @@
|
| }
|
| }
|
|
|
| -void VideoCaptureImpl::StopCapture(int client_id) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| -
|
| - // A client ID can be in only one client list.
|
| - // If this ID is in any client list, we can just remove it from
|
| +void VideoCaptureImpl::StopCaptureOnIOThread(
|
| + media::VideoCapture::EventHandler* handler) {
|
| + DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
|
| +
|
| + // A handler can be in only one client list.
|
| + // If this handler is in any client list, we can just remove it from
|
| // that client list and don't have to run the other following RemoveClient().
|
| - if (!RemoveClient(client_id, &clients_pending_on_filter_)) {
|
| - if (!RemoveClient(client_id, &clients_pending_on_restart_)) {
|
| - bool removed = RemoveClient(client_id, &clients_);
|
| - DCHECK(removed) << "Removing a non-existent client.";
|
| - }
|
| - }
|
| + RemoveClient(handler, &clients_pending_on_filter_) ||
|
| + RemoveClient(handler, &clients_pending_on_restart_) ||
|
| + RemoveClient(handler, &clients_);
|
|
|
| if (clients_.empty()) {
|
| DVLOG(1) << "StopCapture: No more client, stopping ...";
|
| @@ -149,20 +189,20 @@
|
| }
|
| }
|
|
|
| -void VideoCaptureImpl::GetDeviceSupportedFormats(
|
| - const VideoCaptureDeviceFormatsCB& callback) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - device_formats_cb_queue_.push_back(callback);
|
| - if (device_formats_cb_queue_.size() == 1)
|
| +void VideoCaptureImpl::GetDeviceSupportedFormatsOnIOThread(
|
| + const DeviceFormatsCallback& callback) {
|
| + DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
|
| + device_formats_callback_queue_.push_back(callback);
|
| + if (device_formats_callback_queue_.size() == 1)
|
| Send(new VideoCaptureHostMsg_GetDeviceSupportedFormats(device_id_,
|
| session_id_));
|
| }
|
|
|
| -void VideoCaptureImpl::GetDeviceFormatsInUse(
|
| - const VideoCaptureDeviceFormatsCB& callback) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - device_formats_in_use_cb_queue_.push_back(callback);
|
| - if (device_formats_in_use_cb_queue_.size() == 1)
|
| +void VideoCaptureImpl::GetDeviceFormatsInUseOnIOThread(
|
| + const DeviceFormatsInUseCallback& callback) {
|
| + DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
|
| + device_formats_in_use_callback_queue_.push_back(callback);
|
| + if (device_formats_in_use_callback_queue_.size() == 1)
|
| Send(
|
| new VideoCaptureHostMsg_GetDeviceFormatsInUse(device_id_, session_id_));
|
| }
|
| @@ -170,7 +210,7 @@
|
| void VideoCaptureImpl::OnBufferCreated(
|
| base::SharedMemoryHandle handle,
|
| int length, int buffer_id) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| + DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
|
|
|
| // In case client calls StopCapture before the arrival of created buffer,
|
| // just close this buffer and return.
|
| @@ -194,7 +234,7 @@
|
| }
|
|
|
| void VideoCaptureImpl::OnBufferDestroyed(int buffer_id) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| + DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
|
|
|
| ClientBufferMap::iterator iter = client_buffers_.find(buffer_id);
|
| if (iter == client_buffers_.end())
|
| @@ -208,7 +248,7 @@
|
| void VideoCaptureImpl::OnBufferReceived(int buffer_id,
|
| const media::VideoCaptureFormat& format,
|
| base::TimeTicks timestamp) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| + DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
|
|
|
| // The capture pipeline supports only I420 for now.
|
| DCHECK_EQ(format.pixel_format, media::PIXEL_FORMAT_I420);
|
| @@ -249,10 +289,8 @@
|
| buffer,
|
| base::Passed(scoped_ptr<gpu::MailboxHolder>().Pass()))));
|
|
|
| - for (ClientInfoMap::iterator it = clients_.begin(); it != clients_.end();
|
| - ++it) {
|
| - it->second.deliver_frame_cb.Run(frame, format);
|
| - }
|
| + for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); ++it)
|
| + it->first->OnFrameReady(this, frame);
|
| }
|
|
|
| static void NullReadPixelsCB(const SkBitmap& bitmap) { NOTIMPLEMENTED(); }
|
| @@ -262,7 +300,7 @@
|
| const gpu::MailboxHolder& mailbox_holder,
|
| const media::VideoCaptureFormat& format,
|
| base::TimeTicks timestamp) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| + DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
|
|
|
| if (state_ != VIDEO_CAPTURE_STATE_STARTED || suspended_) {
|
| Send(new VideoCaptureHostMsg_BufferReady(
|
| @@ -287,28 +325,24 @@
|
| timestamp - first_frame_timestamp_,
|
| base::Bind(&NullReadPixelsCB));
|
|
|
| - for (ClientInfoMap::iterator it = clients_.begin(); it != clients_.end();
|
| - ++it) {
|
| - it->second.deliver_frame_cb.Run(frame, format);
|
| - }
|
| + for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); ++it)
|
| + it->first->OnFrameReady(this, frame);
|
| }
|
|
|
| void VideoCaptureImpl::OnClientBufferFinished(
|
| int buffer_id,
|
| const scoped_refptr<ClientBuffer>& /* ignored_buffer */,
|
| scoped_ptr<gpu::MailboxHolder> mailbox_holder) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| + DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
|
| const uint32 sync_point = (mailbox_holder ? mailbox_holder->sync_point : 0);
|
| Send(new VideoCaptureHostMsg_BufferReady(device_id_, buffer_id, sync_point));
|
| }
|
|
|
| void VideoCaptureImpl::OnStateChanged(VideoCaptureState state) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| + DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
|
|
|
| switch (state) {
|
| case VIDEO_CAPTURE_STATE_STARTED:
|
| - // Camera has started in the browser process. Since we have already
|
| - // told all clients that we have started there's nothing to do.
|
| break;
|
| case VIDEO_CAPTURE_STATE_STOPPED:
|
| state_ = VIDEO_CAPTURE_STATE_STOPPED;
|
| @@ -319,26 +353,27 @@
|
| RestartCapture();
|
| break;
|
| case VIDEO_CAPTURE_STATE_PAUSED:
|
| - for (ClientInfoMap::iterator it = clients_.begin();
|
| + for (ClientInfo::iterator it = clients_.begin();
|
| it != clients_.end(); ++it) {
|
| - it->second.state_update_cb.Run(VIDEO_CAPTURE_STATE_PAUSED);
|
| + it->first->OnPaused(this);
|
| }
|
| break;
|
| case VIDEO_CAPTURE_STATE_ERROR:
|
| DVLOG(1) << "OnStateChanged: error!, device_id = " << device_id_;
|
| - for (ClientInfoMap::iterator it = clients_.begin();
|
| + for (ClientInfo::iterator it = clients_.begin();
|
| it != clients_.end(); ++it) {
|
| - it->second.state_update_cb.Run(VIDEO_CAPTURE_STATE_ERROR);
|
| + // TODO(wjia): browser process would send error code.
|
| + it->first->OnError(this, 1);
|
| + it->first->OnRemoved(this);
|
| }
|
| clients_.clear();
|
| state_ = VIDEO_CAPTURE_STATE_ERROR;
|
| break;
|
| case VIDEO_CAPTURE_STATE_ENDED:
|
| DVLOG(1) << "OnStateChanged: ended!, device_id = " << device_id_;
|
| - for (ClientInfoMap::iterator it = clients_.begin();
|
| + for (ClientInfo::iterator it = clients_.begin();
|
| it != clients_.end(); ++it) {
|
| - // We'll only notify the client that the stream has stopped.
|
| - it->second.state_update_cb.Run(VIDEO_CAPTURE_STATE_STOPPED);
|
| + it->first->OnRemoved(this);
|
| }
|
| clients_.clear();
|
| state_ = VIDEO_CAPTURE_STATE_ENDED;
|
| @@ -350,41 +385,36 @@
|
|
|
| void VideoCaptureImpl::OnDeviceSupportedFormatsEnumerated(
|
| const media::VideoCaptureFormats& supported_formats) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - for (size_t i = 0; i < device_formats_cb_queue_.size(); ++i)
|
| - device_formats_cb_queue_[i].Run(supported_formats);
|
| - device_formats_cb_queue_.clear();
|
| + DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
|
| + for (size_t i = 0; i < device_formats_callback_queue_.size(); ++i)
|
| + device_formats_callback_queue_[i].Run(supported_formats);
|
| + device_formats_callback_queue_.clear();
|
| }
|
|
|
| void VideoCaptureImpl::OnDeviceFormatsInUseReceived(
|
| const media::VideoCaptureFormats& formats_in_use) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - for (size_t i = 0; i < device_formats_in_use_cb_queue_.size(); ++i)
|
| - device_formats_in_use_cb_queue_[i].Run(formats_in_use);
|
| - device_formats_in_use_cb_queue_.clear();
|
| + DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
|
| + for (size_t i = 0; i < device_formats_in_use_callback_queue_.size(); ++i)
|
| + device_formats_in_use_callback_queue_[i].Run(formats_in_use);
|
| + device_formats_in_use_callback_queue_.clear();
|
| }
|
|
|
| void VideoCaptureImpl::OnDelegateAdded(int32 device_id) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| DVLOG(1) << "OnDelegateAdded: device_id " << device_id;
|
| + DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
|
|
|
| device_id_ = device_id;
|
| - for (ClientInfoMap::iterator it = clients_pending_on_filter_.begin();
|
| + for (ClientInfo::iterator it = clients_pending_on_filter_.begin();
|
| it != clients_pending_on_filter_.end(); ) {
|
| - int client_id = it->first;
|
| - VideoCaptureStateUpdateCB state_update_cb =
|
| - it->second.state_update_cb;
|
| - VideoCaptureDeliverFrameCB deliver_frame_cb =
|
| - it->second.deliver_frame_cb;
|
| - const media::VideoCaptureParams params = it->second.params;
|
| + media::VideoCapture::EventHandler* handler = it->first;
|
| + const media::VideoCaptureParams params = it->second;
|
| clients_pending_on_filter_.erase(it++);
|
| - StartCapture(client_id, params, state_update_cb,
|
| - deliver_frame_cb);
|
| + StartCapture(handler, params);
|
| }
|
| }
|
|
|
| void VideoCaptureImpl::StopDevice() {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| + DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
|
|
|
| if (state_ == VIDEO_CAPTURE_STATE_STARTED) {
|
| state_ = VIDEO_CAPTURE_STATE_STOPPING;
|
| @@ -394,20 +424,22 @@
|
| }
|
|
|
| void VideoCaptureImpl::RestartCapture() {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| + DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
|
| DCHECK_EQ(state_, VIDEO_CAPTURE_STATE_STOPPED);
|
|
|
| int width = 0;
|
| int height = 0;
|
| - clients_.insert(clients_pending_on_restart_.begin(),
|
| - clients_pending_on_restart_.end());
|
| - clients_pending_on_restart_.clear();
|
| - for (ClientInfoMap::iterator it = clients_.begin();
|
| + for (ClientInfo::iterator it = clients_.begin();
|
| it != clients_.end(); ++it) {
|
| - width = std::max(width,
|
| - it->second.params.requested_format.frame_size.width());
|
| - height = std::max(height,
|
| - it->second.params.requested_format.frame_size.height());
|
| + width = std::max(width, it->second.requested_format.frame_size.width());
|
| + height = std::max(height, it->second.requested_format.frame_size.height());
|
| + }
|
| + for (ClientInfo::iterator it = clients_pending_on_restart_.begin();
|
| + it != clients_pending_on_restart_.end(); ) {
|
| + width = std::max(width, it->second.requested_format.frame_size.width());
|
| + height = std::max(height, it->second.requested_format.frame_size.height());
|
| + clients_[it->first] = it->second;
|
| + clients_pending_on_restart_.erase(it++);
|
| }
|
| params_.requested_format.frame_size.SetSize(width, height);
|
| DVLOG(1) << "RestartCapture, "
|
| @@ -416,7 +448,7 @@
|
| }
|
|
|
| void VideoCaptureImpl::StartCaptureInternal() {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| + DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
|
| DCHECK(device_id_);
|
|
|
| Send(new VideoCaptureHostMsg_Start(device_id_, session_id_, params_));
|
| @@ -424,17 +456,21 @@
|
| }
|
|
|
| void VideoCaptureImpl::Send(IPC::Message* message) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - message_filter_->Send(message);
|
| -}
|
| -
|
| -bool VideoCaptureImpl::RemoveClient(int client_id, ClientInfoMap* clients) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| + io_message_loop_proxy_->PostTask(FROM_HERE,
|
| + base::Bind(base::IgnoreResult(&VideoCaptureMessageFilter::Send),
|
| + message_filter_.get(), message));
|
| +}
|
| +
|
| +bool VideoCaptureImpl::RemoveClient(
|
| + media::VideoCapture::EventHandler* handler,
|
| + ClientInfo* clients) {
|
| + DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
|
| bool found = false;
|
|
|
| - ClientInfoMap::iterator it = clients->find(client_id);
|
| + ClientInfo::iterator it = clients->find(handler);
|
| if (it != clients->end()) {
|
| - it->second.state_update_cb.Run(VIDEO_CAPTURE_STATE_STOPPED);
|
| + handler->OnStopped(this);
|
| + handler->OnRemoved(this);
|
| clients->erase(it);
|
| found = true;
|
| }
|
|
|