Index: content/renderer/media/video_capture_impl.cc |
=================================================================== |
--- content/renderer/media/video_capture_impl.cc (revision 145737) |
+++ content/renderer/media/video_capture_impl.cc (working copy) |
@@ -50,6 +50,7 @@ |
: VideoCapture(), |
message_filter_(filter), |
capture_message_loop_proxy_(capture_message_loop_proxy), |
+ io_message_loop_proxy_(ChildProcess::current()->io_message_loop_proxy()), |
device_id_(0), |
video_type_(media::VideoCaptureCapability::kI420), |
device_info_available_(false), |
@@ -61,56 +62,44 @@ |
} |
VideoCaptureImpl::~VideoCaptureImpl() { |
- STLDeleteContainerPairSecondPointers(cached_dibs_.begin(), |
- cached_dibs_.end()); |
+ STLDeleteValues(&cached_dibs_); |
} |
void VideoCaptureImpl::Init() { |
- io_message_loop_proxy_ = ChildProcess::current()->io_message_loop_proxy(); |
if (!io_message_loop_proxy_->BelongsToCurrentThread()) { |
io_message_loop_proxy_->PostTask(FROM_HERE, |
base::Bind(&VideoCaptureImpl::AddDelegateOnIOThread, |
base::Unretained(this))); |
- return; |
+ } else { |
+ AddDelegateOnIOThread(); |
} |
- |
- AddDelegateOnIOThread(); |
} |
void VideoCaptureImpl::DeInit(base::Closure task) { |
capture_message_loop_proxy_->PostTask(FROM_HERE, |
- base::Bind(&VideoCaptureImpl::DoDeInit, |
+ base::Bind(&VideoCaptureImpl::DoDeInitOnCaptureThread, |
base::Unretained(this), task)); |
} |
-void VideoCaptureImpl::DoDeInit(base::Closure task) { |
- if (state_ == video_capture::kStarted) |
- Send(new VideoCaptureHostMsg_Stop(device_id_)); |
- |
- io_message_loop_proxy_->PostTask(FROM_HERE, |
- base::Bind(&VideoCaptureImpl::RemoveDelegateOnIOThread, |
- base::Unretained(this), task)); |
-} |
- |
void VideoCaptureImpl::StartCapture( |
media::VideoCapture::EventHandler* handler, |
const media::VideoCaptureCapability& capability) { |
DCHECK_EQ(capability.color, media::VideoCaptureCapability::kI420); |
capture_message_loop_proxy_->PostTask(FROM_HERE, |
- base::Bind(&VideoCaptureImpl::DoStartCapture, |
+ base::Bind(&VideoCaptureImpl::DoStartCaptureOnCaptureThread, |
base::Unretained(this), handler, capability)); |
} |
void VideoCaptureImpl::StopCapture(media::VideoCapture::EventHandler* handler) { |
capture_message_loop_proxy_->PostTask(FROM_HERE, |
- base::Bind(&VideoCaptureImpl::DoStopCapture, |
+ base::Bind(&VideoCaptureImpl::DoStopCaptureOnCaptureThread, |
base::Unretained(this), handler)); |
} |
void VideoCaptureImpl::FeedBuffer(scoped_refptr<VideoFrameBuffer> buffer) { |
capture_message_loop_proxy_->PostTask(FROM_HERE, |
- base::Bind(&VideoCaptureImpl::DoFeedBuffer, |
+ base::Bind(&VideoCaptureImpl::DoFeedBufferOnCaptureThread, |
base::Unretained(this), buffer)); |
} |
@@ -118,36 +107,45 @@ |
base::SharedMemoryHandle handle, |
int length, int buffer_id) { |
capture_message_loop_proxy_->PostTask(FROM_HERE, |
- base::Bind(&VideoCaptureImpl::DoBufferCreated, |
+ base::Bind(&VideoCaptureImpl::DoBufferCreatedOnCaptureThread, |
base::Unretained(this), handle, length, buffer_id)); |
} |
void VideoCaptureImpl::OnBufferReceived(int buffer_id, base::Time timestamp) { |
capture_message_loop_proxy_->PostTask(FROM_HERE, |
- base::Bind(&VideoCaptureImpl::DoBufferReceived, |
+ base::Bind(&VideoCaptureImpl::DoBufferReceivedOnCaptureThread, |
base::Unretained(this), buffer_id, timestamp)); |
} |
void VideoCaptureImpl::OnStateChanged(video_capture::State state) { |
capture_message_loop_proxy_->PostTask(FROM_HERE, |
- base::Bind(&VideoCaptureImpl::DoStateChanged, |
+ base::Bind(&VideoCaptureImpl::DoStateChangedOnCaptureThread, |
base::Unretained(this), state)); |
} |
void VideoCaptureImpl::OnDeviceInfoReceived( |
const media::VideoCaptureParams& device_info) { |
capture_message_loop_proxy_->PostTask(FROM_HERE, |
- base::Bind(&VideoCaptureImpl::DoDeviceInfoReceived, |
+ base::Bind(&VideoCaptureImpl::DoDeviceInfoReceivedOnCaptureThread, |
base::Unretained(this), device_info)); |
} |
void VideoCaptureImpl::OnDelegateAdded(int32 device_id) { |
capture_message_loop_proxy_->PostTask(FROM_HERE, |
- base::Bind(&VideoCaptureImpl::DoDelegateAdded, |
+ base::Bind(&VideoCaptureImpl::DoDelegateAddedOnCaptureThread, |
base::Unretained(this), device_id)); |
} |
-void VideoCaptureImpl::DoStartCapture( |
+void VideoCaptureImpl::DoDeInitOnCaptureThread(base::Closure task) { |
+ if (state_ == video_capture::kStarted) |
+ Send(new VideoCaptureHostMsg_Stop(device_id_)); |
+ |
+ io_message_loop_proxy_->PostTask(FROM_HERE, |
+ base::Bind(&VideoCaptureImpl::RemoveDelegateOnIOThread, |
+ base::Unretained(this), task)); |
+} |
+ |
+void VideoCaptureImpl::DoStartCaptureOnCaptureThread( |
media::VideoCapture::EventHandler* handler, |
const media::VideoCaptureCapability& capability) { |
DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
@@ -155,113 +153,88 @@ |
if (state_ == video_capture::kError) { |
handler->OnError(this, 1); |
handler->OnRemoved(this); |
- return; |
- } |
- |
- ClientInfo::iterator it1 = clients_pending_on_filter_.find(handler); |
- ClientInfo::iterator it2 = clients_pending_on_restart_.find(handler); |
- if (it1 != clients_pending_on_filter_.end() || |
- it2 != clients_pending_on_restart_.end() || |
- clients_.find(handler) != clients_.end() ) { |
+ } 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. |
- return; |
- } |
- |
- if (!device_id_) { |
+ } else if (!device_id_) { |
clients_pending_on_filter_[handler] = capability; |
- return; |
- } |
+ } else { |
+ handler->OnStarted(this); |
+ if (state_ == video_capture::kStarted) { |
+ if (capability.width > current_params_.width || |
+ capability.height > current_params_.height) { |
+ StopDevice(); |
+ DVLOG(1) << "StartCapture: Got client with higher resolution (" |
+ << capability.width << ", " << capability.height << ") " |
+ << "after started, try to restart."; |
+ clients_pending_on_restart_[handler] = capability; |
+ } else { |
+ if (device_info_available_) { |
+ handler->OnDeviceInfoReceived(this, device_info_); |
+ } |
- handler->OnStarted(this); |
- if (state_ == video_capture::kStarted) { |
- if (capability.width > current_params_.width || |
- capability.height > current_params_.height) { |
- StopDevice(); |
- DVLOG(1) << "StartCapture: Got client with higher resolution (" |
- << capability.width << ", " << capability.height << ") " |
- << "after started, try to restart."; |
+ clients_[handler] = capability; |
+ } |
+ } else if (state_ == video_capture::kStopping) { |
clients_pending_on_restart_[handler] = capability; |
- return; |
- } |
+ DVLOG(1) << "StartCapture: Got new resolution (" |
+ << capability.width << ", " << capability.height << ") " |
+ << ", during stopping."; |
+ } else { |
+ clients_[handler] = capability; |
+ DCHECK_EQ(1ul, clients_.size()); |
+ video_type_ = capability.color; |
+ current_params_.width = capability.width; |
+ current_params_.height = capability.height; |
+ current_params_.frame_per_second = capability.frame_rate; |
+ DVLOG(1) << "StartCapture: starting with first resolution (" |
+ << current_params_.width << "," << current_params_.height << ")"; |
- if (device_info_available_) { |
- handler->OnDeviceInfoReceived(this, device_info_); |
+ StartCaptureInternal(); |
} |
- |
- clients_[handler] = capability; |
- return; |
} |
- |
- if (state_ == video_capture::kStopping) { |
- clients_pending_on_restart_[handler] = capability; |
- DVLOG(1) << "StartCapture: Got new resolution (" |
- << capability.width << ", " << capability.height << ") " |
- << ", during stopping."; |
- return; |
- } |
- |
- clients_[handler] = capability; |
- DCHECK_EQ(clients_.size(), 1ul); |
- video_type_ = capability.color; |
- current_params_.width = capability.width; |
- current_params_.height = capability.height; |
- current_params_.frame_per_second = capability.frame_rate; |
- DVLOG(1) << "StartCapture: starting with first resolution (" |
- << current_params_.width << ", " << current_params_.height << ")"; |
- |
- StartCaptureInternal(); |
} |
-void VideoCaptureImpl::DoStopCapture( |
+void VideoCaptureImpl::DoStopCaptureOnCaptureThread( |
media::VideoCapture::EventHandler* handler) { |
DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
- ClientInfo::iterator it = clients_pending_on_filter_.find(handler); |
- if (it != clients_pending_on_filter_.end()) { |
- handler->OnStopped(this); |
- handler->OnRemoved(this); |
- clients_pending_on_filter_.erase(it); |
- return; |
- } |
- it = clients_pending_on_restart_.find(handler); |
- if (it != clients_pending_on_restart_.end()) { |
- handler->OnStopped(this); |
- handler->OnRemoved(this); |
- clients_pending_on_filter_.erase(it); |
- return; |
- } |
+ // 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(). |
+ RemoveClient(handler, &clients_pending_on_filter_) || |
+ RemoveClient(handler, &clients_pending_on_restart_) || |
+ RemoveClient(handler, &clients_); |
- if (clients_.find(handler) == clients_.end()) |
- return; |
- |
- clients_.erase(handler); |
- |
if (clients_.empty()) { |
DVLOG(1) << "StopCapture: No more client, stopping ..."; |
StopDevice(); |
} |
- handler->OnStopped(this); |
- handler->OnRemoved(this); |
} |
-void VideoCaptureImpl::DoFeedBuffer(scoped_refptr<VideoFrameBuffer> buffer) { |
+void VideoCaptureImpl::DoFeedBufferOnCaptureThread( |
+ scoped_refptr<VideoFrameBuffer> buffer) { |
DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
CachedDIB::iterator it; |
- for (it = cached_dibs_.begin(); it != cached_dibs_.end(); it++) { |
+ for (it = cached_dibs_.begin(); it != cached_dibs_.end(); ++it) { |
if (buffer == it->second->mapped_memory) |
break; |
} |
- DCHECK(it != cached_dibs_.end()); |
- DCHECK_GT(it->second->references, 0); |
- it->second->references--; |
- if (it->second->references == 0) { |
- Send(new VideoCaptureHostMsg_BufferReady(device_id_, it->first)); |
+ if (it != cached_dibs_.end() && it->second) { |
+ DCHECK_GT(it->second->references, 0); |
+ --it->second->references; |
+ if (it->second->references == 0) { |
+ Send(new VideoCaptureHostMsg_BufferReady(device_id_, it->first)); |
+ } |
} |
} |
-void VideoCaptureImpl::DoBufferCreated( |
+void VideoCaptureImpl::DoBufferCreatedOnCaptureThread( |
base::SharedMemoryHandle handle, |
int length, int buffer_id) { |
DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
@@ -283,7 +256,8 @@ |
cached_dibs_[buffer_id] = dib_buffer; |
} |
-void VideoCaptureImpl::DoBufferReceived(int buffer_id, base::Time timestamp) { |
+void VideoCaptureImpl::DoBufferReceivedOnCaptureThread( |
+ int buffer_id, base::Time timestamp) { |
DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
if (state_ != video_capture::kStarted) { |
@@ -296,13 +270,14 @@ |
buffer = cached_dibs_[buffer_id]->mapped_memory; |
buffer->timestamp = timestamp; |
- for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); it++) { |
+ for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); ++it) { |
it->first->OnBufferReady(this, buffer); |
} |
cached_dibs_[buffer_id]->references = clients_.size(); |
} |
-void VideoCaptureImpl::DoStateChanged(video_capture::State state) { |
+void VideoCaptureImpl::DoStateChangedOnCaptureThread( |
+ video_capture::State state) { |
DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
switch (state) { |
@@ -317,14 +292,14 @@ |
break; |
case video_capture::kPaused: |
for (ClientInfo::iterator it = clients_.begin(); |
- it != clients_.end(); it++) { |
+ it != clients_.end(); ++it) { |
it->first->OnPaused(this); |
} |
break; |
case video_capture::kError: |
DVLOG(1) << "OnStateChanged: error!, device_id = " << device_id_; |
for (ClientInfo::iterator it = clients_.begin(); |
- it != clients_.end(); it++) { |
+ it != clients_.end(); ++it) { |
// TODO(wjia): browser process would send error code. |
it->first->OnError(this, 1); |
it->first->OnRemoved(this); |
@@ -337,7 +312,7 @@ |
} |
} |
-void VideoCaptureImpl::DoDeviceInfoReceived( |
+void VideoCaptureImpl::DoDeviceInfoReceivedOnCaptureThread( |
const media::VideoCaptureParams& device_info) { |
DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
DCHECK(!ClientHasDIB()); |
@@ -346,12 +321,12 @@ |
device_info_ = device_info; |
device_info_available_ = true; |
- for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); it++) { |
+ for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); ++it) { |
it->first->OnDeviceInfoReceived(this, device_info); |
} |
} |
-void VideoCaptureImpl::DoDelegateAdded(int32 device_id) { |
+void VideoCaptureImpl::DoDelegateAddedOnCaptureThread(int32 device_id) { |
DVLOG(1) << "DoDelegateAdded: device_id " << device_id; |
DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
@@ -383,18 +358,14 @@ |
int width = 0; |
int height = 0; |
for (ClientInfo::iterator it = clients_.begin(); |
- it != clients_.end(); it++) { |
- if (it->second.width > width) |
- width = it->second.width; |
- if (it->second.height > height) |
- height = it->second.height; |
+ it != clients_.end(); ++it) { |
+ width = std::max(width, it->second.width); |
+ height = std::max(height, it->second.height); |
} |
for (ClientInfo::iterator it = clients_pending_on_restart_.begin(); |
it != clients_pending_on_restart_.end(); ) { |
- if (it->second.width > width) |
- width = it->second.width; |
- if (it->second.height > height) |
- height = it->second.height; |
+ width = std::max(width, it->second.width); |
+ height = std::max(height, it->second.height); |
clients_[it->first] = it->second; |
clients_pending_on_restart_.erase(it++); |
} |
@@ -430,11 +401,28 @@ |
message_filter_.get(), message)); |
} |
-bool VideoCaptureImpl::ClientHasDIB() { |
- CachedDIB::iterator it; |
- for (it = cached_dibs_.begin(); it != cached_dibs_.end(); it++) { |
+bool VideoCaptureImpl::ClientHasDIB() const { |
+ DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
+ for (CachedDIB::const_iterator it = cached_dibs_.begin(); |
+ it != cached_dibs_.end(); ++it) { |
if (it->second->references > 0) |
return true; |
} |
return false; |
} |
+ |
+bool VideoCaptureImpl::RemoveClient( |
+ media::VideoCapture::EventHandler* handler, |
+ ClientInfo* clients) { |
+ DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
+ bool found = false; |
+ |
+ ClientInfo::iterator it = clients->find(handler); |
+ if (it != clients->end()) { |
+ handler->OnStopped(this); |
+ handler->OnRemoved(this); |
+ clients->erase(it); |
+ found = true; |
+ } |
+ return found; |
+} |