| Index: content/renderer/media/video_capture_impl.cc
|
| ===================================================================
|
| --- content/renderer/media/video_capture_impl.cc (revision 107671)
|
| +++ content/renderer/media/video_capture_impl.cc (working copy)
|
| @@ -9,14 +9,21 @@
|
| #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) {
|
| + }
|
| + ~DIBBuffer() {
|
| + delete dib;
|
| + }
|
|
|
| -VideoCaptureImpl::DIBBuffer::~DIBBuffer() {
|
| - delete dib;
|
| -}
|
| + base::SharedMemory* dib;
|
| + scoped_refptr<media::VideoCapture::VideoFrameBuffer> mapped_memory;
|
| +};
|
|
|
| bool VideoCaptureImpl::CaptureStarted() {
|
| return state_ == kStarted;
|
| @@ -47,8 +54,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,80 +153,61 @@
|
| 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();
|
| + DLOG(INFO) << "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;
|
| + DLOG(INFO) << "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 ("
|
| + DLOG(INFO) << "StartCapture: starting with first resolution ("
|
| << current_params_.width << ", " << current_params_.height << ")";
|
|
|
| StartCaptureInternal();
|
| @@ -230,13 +217,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,56 +238,8 @@
|
| 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;
|
| + if (clients_.size() == 0) {
|
| DLOG(INFO) << "StopCapture: No more client, stopping ...";
|
| StopDevice();
|
| }
|
| @@ -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;
|
| @@ -366,7 +314,7 @@
|
| state_ = kStopped;
|
| DLOG(INFO) << "OnStateChanged: stopped!, device_id = " << device_id_;
|
| STLDeleteValues(&cached_dibs_);
|
| - if (pending_start())
|
| + if (clients_.size() + clients_pending_on_restart_.size() > 0)
|
| RestartCapture();
|
| break;
|
| case media::VideoCapture::kPaused:
|
| @@ -376,6 +324,7 @@
|
| }
|
| break;
|
| case media::VideoCapture::kError:
|
| + DLOG(INFO) << "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++) {
|
| @@ -410,11 +358,11 @@
|
| 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,14 +382,26 @@
|
| 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;
|
| -
|
| + 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;
|
| DLOG(INFO) << "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() {
|
| + for (ClientSideDIB::iterator dit = client_side_dibs_.begin();
|
| + dit != client_side_dibs_.end(); dit++) {
|
| + if (dit->second > 0)
|
| + return true;
|
| + }
|
| + return false;
|
| }
|
|
|