Index: content/renderer/media/video_capture_impl.cc |
=================================================================== |
--- content/renderer/media/video_capture_impl.cc (revision 106642) |
+++ 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,6 +153,12 @@ |
const VideoCaptureCapability& capability) { |
DCHECK(ml_proxy_->BelongsToCurrentThread()); |
+ if (state_ == kError) { |
+ handler->OnError(this, 1); |
+ handler->OnRemoved(this); |
+ return; |
+ } |
+ |
if (pending_clients_.find(handler) != pending_clients_.end() || |
clients_.find(handler) != clients_.end() ) { |
// This client has started. |
@@ -158,69 +170,39 @@ |
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_); |
+ handler->OnStarted(this); |
+ if (state_ == kStarted) { |
+ if (!device_info_available_) { |
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."; |
+ if (capability.width > device_info_.width || |
+ capability.height > device_info_.height) { |
StopDevice(); |
- } else if (device_info_available_) { |
- handler->OnDeviceInfoReceived(this, device_info_); |
+ DLOG(INFO) << "StartCapture: Got client with higher resolution (" |
+ << capability.width << ", " << capability.height << ") " |
+ << "after started, try to restart."; |
+ return; |
} |
+ |
+ handler->OnDeviceInfoReceived(this, device_info_); |
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."; |
- } |
+ DLOG(INFO) << "StartCapture: Got new resolution (" |
+ << capability.width << ", " << capability.height << ") " |
+ << ", during stopping."; |
return; |
} |
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(); |
@@ -244,56 +226,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 +256,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 +266,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 +302,7 @@ |
state_ = kStopped; |
DLOG(INFO) << "OnStateChanged: stopped!, device_id = " << device_id_; |
STLDeleteValues(&cached_dibs_); |
- if (pending_start()) |
+ if (clients_.size() > 0) |
RestartCapture(); |
break; |
case media::VideoCapture::kPaused: |
@@ -376,6 +312,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 +320,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,8 +330,16 @@ |
void VideoCaptureImpl::DoDeviceInfoReceived( |
const media::VideoCaptureParams& device_info) { |
DCHECK(ml_proxy_->BelongsToCurrentThread()); |
- if (state_ != kStarted) |
+ DCHECK(!ClientHasDIB()); |
+ |
+ STLDeleteValues(&cached_dibs_); |
+ |
+ GetMaxWidthHeight(current_params_.width, current_params_.height); |
+ if (current_params_.width > device_info.width || |
+ current_params_.height > device_info.height) { |
+ StopDevice(); |
return; |
+ } |
device_info_ = device_info; |
device_info_available_ = true; |
@@ -434,14 +377,7 @@ |
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; |
- |
+ GetMaxWidthHeight(current_params_.width, current_params_.height); |
DLOG(INFO) << "RestartCapture, " << current_params_.width << ", " |
<< current_params_.height; |
StartCaptureInternal(); |
@@ -473,10 +409,22 @@ |
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; |
} |
+ |
+void VideoCaptureImpl::GetMaxWidthHeight(int& width, int& height) { |
+ width = 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; |
+ } |
+} |