Chromium Code Reviews| Index: content/renderer/media/video_capture_impl.cc |
| =================================================================== |
| --- content/renderer/media/video_capture_impl.cc (revision 107874) |
| +++ content/renderer/media/video_capture_impl.cc (working copy) |
| @@ -9,15 +9,24 @@ |
| #include "content/common/child_process.h" |
| #include "content/common/media/video_capture_messages.h" |
| -VideoCaptureImpl::DIBBuffer::DIBBuffer( |
| - base::SharedMemory* d, media::VideoCapture::VideoFrameBuffer* ptr) |
| - : dib(d), |
| - mapped_memory(ptr) {} |
| +struct VideoCaptureImpl::DIBBuffer { |
| + public: |
| + DIBBuffer( |
| + base::SharedMemory* d, |
| + media::VideoCapture::VideoFrameBuffer* ptr) |
| + : dib(d), |
| + mapped_memory(ptr), |
| + references(0) { |
| + } |
| + ~DIBBuffer() {} |
| -VideoCaptureImpl::DIBBuffer::~DIBBuffer() { |
| - delete dib; |
| -} |
| + scoped_ptr<base::SharedMemory> dib; |
| + scoped_refptr<media::VideoCapture::VideoFrameBuffer> mapped_memory; |
| + // Number of clients which hold this dib. |
|
scherkus (not reviewing)
2011/11/01 02:26:56
dib -> DIB
wjia(left Chromium)
2011/11/01 17:24:29
Done.
|
| + int references; |
| +}; |
| + |
| bool VideoCaptureImpl::CaptureStarted() { |
| return state_ == kStarted; |
| } |
| @@ -47,8 +56,7 @@ |
| state_(kStopped) { |
| DCHECK(filter); |
| memset(¤t_params_, 0, sizeof(current_params_)); |
| - memset(&new_params_, 0, sizeof(new_params_)); |
| - current_params_.session_id = new_params_.session_id = id; |
| + current_params_.session_id = id; |
| } |
| VideoCaptureImpl::~VideoCaptureImpl() { |
| @@ -147,81 +155,62 @@ |
| const VideoCaptureCapability& capability) { |
| DCHECK(ml_proxy_->BelongsToCurrentThread()); |
| - if (pending_clients_.find(handler) != pending_clients_.end() || |
| + if (state_ == 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() ) { |
| // This client has started. |
| return; |
| } |
| if (!device_id_) { |
| - pending_clients_[handler] = capability; |
| + clients_pending_on_filter_[handler] = capability; |
| return; |
| } |
| - if (capability.resolution_fixed && master_clients_.size()) { |
| - bool matches_current_params = |
| - CapabilityMatchesParameters(capability, current_params_); |
| - bool matches_new_params = |
| - CapabilityMatchesParameters(capability, new_params_); |
| - if ((state_ == kStarted && !matches_current_params) || |
| - (state_ == kStopping && !matches_new_params)) { |
| - // Can't have 2 master clients with different resolutions. |
| - handler->OnError(this, 1); |
| - handler->OnRemoved(this); |
| - return; |
| - } |
| - } |
| - |
| handler->OnStarted(this); |
| - clients_[handler] = capability; |
| - if (capability.resolution_fixed) { |
| - master_clients_.push_back(handler); |
| - if (master_clients_.size() > 1) { |
| - if (device_info_available_) |
| - handler->OnDeviceInfoReceived(this, device_info_); |
| + if (state_ == 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; |
| return; |
| } |
| - } |
| - if (state_ == kStarted) { |
| - // Take the resolution of master client. |
| - if (capability.resolution_fixed && |
| - !CapabilityMatchesParameters(capability, current_params_)) { |
| - new_params_.width = capability.width; |
| - new_params_.height = capability.height; |
| - new_params_.frame_per_second = capability.max_fps; |
| - DLOG(INFO) << "StartCapture: Got master client with new resolution (" |
| - << new_params_.width << ", " << new_params_.height << ") " |
| - << "during started, try to restart."; |
| - StopDevice(); |
| - } else if (device_info_available_) { |
| + if (device_info_available_) { |
| handler->OnDeviceInfoReceived(this, device_info_); |
| } |
| + |
| + clients_[handler] = capability; |
| return; |
| } |
| if (state_ == kStopping) { |
| - if (capability.resolution_fixed || !pending_start()) { |
| - new_params_.width = capability.width; |
| - new_params_.height = capability.height; |
| - new_params_.frame_per_second = capability.max_fps; |
| - DLOG(INFO) << "StartCapture: Got new resolution (" |
| - << new_params_.width << ", " << new_params_.height << ") " |
| - << ", already in stopping."; |
| - } |
| + 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.raw_type; |
| - new_params_.width = 0; |
| - new_params_.height = 0; |
| - new_params_.frame_per_second = 0; |
| current_params_.width = capability.width; |
| current_params_.height = capability.height; |
| current_params_.frame_per_second = capability.max_fps; |
| - DLOG(INFO) << "StartCapture: resolution (" |
| - << current_params_.width << ", " << current_params_.height << ")"; |
| + DVLOG(1) << "StartCapture: starting with first resolution (" |
| + << current_params_.width << ", " << current_params_.height << ")"; |
| StartCaptureInternal(); |
| } |
| @@ -230,13 +219,20 @@ |
| media::VideoCapture::EventHandler* handler) { |
| DCHECK(ml_proxy_->BelongsToCurrentThread()); |
| - ClientInfo::iterator it = pending_clients_.find(handler); |
| - if (it != pending_clients_.end()) { |
| + ClientInfo::iterator it = clients_pending_on_filter_.find(handler); |
| + if (it != clients_pending_on_filter_.end()) { |
| handler->OnStopped(this); |
| handler->OnRemoved(this); |
| - pending_clients_.erase(it); |
| + 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; |
| + } |
| if (clients_.find(handler) == clients_.end()) |
| return; |
| @@ -244,64 +240,15 @@ |
| handler->OnStopped(this); |
| handler->OnRemoved(this); |
| clients_.erase(handler); |
| - master_clients_.remove(handler); |
| - // Still have at least one master client. |
| - if (master_clients_.size() > 0) |
| - return; |
| - |
| - // TODO(wjia): Is it really needed to handle resolution change for non-master |
| - // clients, except no client case? |
| - if (clients_.size() > 0) { |
| - DLOG(INFO) << "StopCapture: No master client."; |
| - int max_width = 0; |
| - int max_height = 0; |
| - int frame_rate = 0; |
| - for (ClientInfo::iterator it = clients_.begin(); |
| - it != clients_.end(); it++) { |
| - if (it->second.width > max_width && it->second.height > max_height) { |
| - max_width = it->second.width; |
| - max_height = it->second.height; |
| - frame_rate = it->second.max_fps; |
| - } |
| - } |
| - |
| - if (state_ == kStarted) { |
| - // Only handle resolution reduction. |
| - if (max_width < current_params_.width && |
| - max_height < current_params_.height) { |
| - new_params_.width = max_width; |
| - new_params_.height = max_height; |
| - new_params_.frame_per_second = frame_rate; |
| - DLOG(INFO) << "StopCapture: New smaller resolution (" |
| - << new_params_.width << ", " << new_params_.height << ") " |
| - << "), stopping ..."; |
| - StopDevice(); |
| - } |
| - return; |
| - } |
| - |
| - if (state_ == kStopping) { |
| - new_params_.width = max_width; |
| - new_params_.height = max_height; |
| - new_params_.frame_per_second = frame_rate; |
| - DLOG(INFO) << "StopCapture: New resolution (" |
| - << new_params_.width << ", " << new_params_.height << ") " |
| - << "), during stopping."; |
| - return; |
| - } |
| - } else { |
| - new_params_.width = current_params_.width = 0; |
| - new_params_.height = current_params_.height = 0; |
| - new_params_.frame_per_second = current_params_.frame_per_second = 0; |
| - DLOG(INFO) << "StopCapture: No more client, stopping ..."; |
| + if (clients_.empty()) { |
| + DVLOG(1) << "StopCapture: No more client, stopping ..."; |
| StopDevice(); |
| } |
| } |
| void VideoCaptureImpl::DoFeedBuffer(scoped_refptr<VideoFrameBuffer> buffer) { |
| DCHECK(ml_proxy_->BelongsToCurrentThread()); |
| - DCHECK(client_side_dibs_.find(buffer) != client_side_dibs_.end()); |
| CachedDIB::iterator it; |
| for (it = cached_dibs_.begin(); it != cached_dibs_.end(); it++) { |
| @@ -310,11 +257,10 @@ |
| } |
| DCHECK(it != cached_dibs_.end()); |
| - if (client_side_dibs_[buffer] <= 1) { |
| - client_side_dibs_.erase(buffer); |
| + DCHECK_GT(it->second->references, 0); |
| + it->second->references--; |
| + if (it->second->references == 0) { |
| Send(new VideoCaptureHostMsg_BufferReady(device_id_, it->first)); |
| - } else { |
| - client_side_dibs_[buffer]--; |
| } |
| } |
| @@ -322,6 +268,7 @@ |
| base::SharedMemoryHandle handle, |
| int length, int buffer_id) { |
| DCHECK(ml_proxy_->BelongsToCurrentThread()); |
| + DCHECK(device_info_available_); |
| media::VideoCapture::VideoFrameBuffer* buffer; |
| DCHECK(cached_dibs_.find(buffer_id) == cached_dibs_.end()); |
| @@ -331,8 +278,9 @@ |
| buffer = new VideoFrameBuffer(); |
| buffer->memory_pointer = static_cast<uint8*>(dib->memory()); |
| buffer->buffer_size = length; |
| - buffer->width = current_params_.width; |
| - buffer->height = current_params_.height; |
| + buffer->width = device_info_.width; |
| + buffer->height = device_info_.height; |
| + buffer->stride = device_info_.width; |
| DIBBuffer* dib_buffer = new DIBBuffer(dib, buffer); |
| cached_dibs_[buffer_id] = dib_buffer; |
| @@ -353,7 +301,7 @@ |
| for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); it++) { |
| it->first->OnBufferReady(this, buffer); |
| } |
| - client_side_dibs_[buffer] = clients_.size(); |
| + cached_dibs_[buffer_id]->references = clients_.size(); |
| } |
| void VideoCaptureImpl::DoStateChanged(const media::VideoCapture::State& state) { |
| @@ -364,9 +312,9 @@ |
| break; |
| case media::VideoCapture::kStopped: |
| state_ = kStopped; |
| - DLOG(INFO) << "OnStateChanged: stopped!, device_id = " << device_id_; |
| + DVLOG(1) << "OnStateChanged: stopped!, device_id = " << device_id_; |
| STLDeleteValues(&cached_dibs_); |
| - if (pending_start()) |
| + if (!clients_.empty() || !clients_pending_on_restart_.empty()) |
| RestartCapture(); |
| break; |
| case media::VideoCapture::kPaused: |
|
perkj_chrome
2011/11/01 09:45:44
What is paused? Ever used?
wjia(left Chromium)
2011/11/01 17:24:29
"Paused" is a state similar to "started" except th
|
| @@ -376,6 +324,7 @@ |
| } |
| break; |
| case media::VideoCapture::kError: |
| + DVLOG(1) << "OnStateChanged: error!, device_id = " << device_id_; |
| for (ClientInfo::iterator it = clients_.begin(); |
| it != clients_.end(); it++) { |
| // TODO(wjia): browser process would send error code. |
| @@ -383,9 +332,7 @@ |
| it->first->OnRemoved(this); |
| } |
| clients_.clear(); |
| - master_clients_.clear(); |
| - state_ = kStopped; |
| - current_params_.width = current_params_.height = 0; |
| + state_ = kError; |
| break; |
| default: |
| break; |
| @@ -395,9 +342,10 @@ |
| void VideoCaptureImpl::DoDeviceInfoReceived( |
| const media::VideoCaptureParams& device_info) { |
| DCHECK(ml_proxy_->BelongsToCurrentThread()); |
| - if (state_ != kStarted) |
| - return; |
| + DCHECK(!ClientHasDIB()); |
| + STLDeleteValues(&cached_dibs_); |
| + |
| device_info_ = device_info; |
| device_info_available_ = true; |
| for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); it++) { |
| @@ -406,15 +354,15 @@ |
| } |
| void VideoCaptureImpl::DoDelegateAdded(int32 device_id) { |
| - DLOG(INFO) << "DoDelegateAdded: device_id " << device_id; |
| + DVLOG(1) << "DoDelegateAdded: device_id " << device_id; |
| DCHECK(ml_proxy_->BelongsToCurrentThread()); |
| device_id_ = device_id; |
| - for (ClientInfo::iterator it = pending_clients_.begin(); |
| - it != pending_clients_.end(); ) { |
| + for (ClientInfo::iterator it = clients_pending_on_filter_.begin(); |
| + it != clients_pending_on_filter_.end(); ) { |
| media::VideoCapture::EventHandler* handler = it->first; |
| const VideoCaptureCapability capability = it->second; |
| - pending_clients_.erase(it++); |
| + clients_pending_on_filter_.erase(it++); |
| StartCapture(handler, capability); |
| } |
| } |
| @@ -434,16 +382,28 @@ |
| DCHECK(ml_proxy_->BelongsToCurrentThread()); |
| DCHECK_EQ(state_, kStopped); |
| - current_params_.width = new_params_.width; |
| - current_params_.height = new_params_.height; |
| - current_params_.frame_per_second = new_params_.frame_per_second; |
| - |
| - new_params_.width = 0; |
| - new_params_.height = 0; |
| - new_params_.frame_per_second = 0; |
| - |
| - DLOG(INFO) << "RestartCapture, " << current_params_.width << ", " |
| - << current_params_.height; |
| + 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; |
| + } |
| + 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; |
| + clients_[it->first] = it->second; |
| + clients_pending_on_restart_.erase(it++); |
| + } |
| + current_params_.width = width; |
| + current_params_.height = height; |
| + DVLOG(1) << "RestartCapture, " << current_params_.width << ", " |
| + << current_params_.height; |
| StartCaptureInternal(); |
| } |
| @@ -473,10 +433,11 @@ |
| message_filter_.get(), message))); |
| } |
| -bool VideoCaptureImpl::CapabilityMatchesParameters( |
| - const VideoCaptureCapability& capability, |
| - const media::VideoCaptureParams& params) { |
| - return (capability.width == params.width && |
| - capability.height == params.height && |
| - capability.max_fps == params.frame_per_second); |
| +bool VideoCaptureImpl::ClientHasDIB() { |
| + CachedDIB::iterator it; |
| + for (it = cached_dibs_.begin(); it != cached_dibs_.end(); it++) { |
| + if (it->second->references > 0) |
| + return true; |
| + } |
| + return false; |
| } |