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 0fe2789b17f91c5d3df42de12f8424114f3798b0..804d492573b7c5af1caf3521deca45ae200074a7 100644 |
--- a/content/renderer/media/video_capture_impl.cc |
+++ b/content/renderer/media/video_capture_impl.cc |
@@ -17,20 +17,11 @@ class VideoCaptureImpl::ClientBuffer |
: public base::RefCountedThreadSafe<ClientBuffer> { |
public: |
ClientBuffer(scoped_ptr<base::SharedMemory> buffer, |
- size_t buffer_size, |
- int frame_width, |
- int frame_height, |
- int frame_stride) |
+ size_t buffer_size) |
: buffer(buffer.Pass()), |
- buffer_size(buffer_size), |
- frame_width(frame_width), |
- frame_height(frame_height), |
- frame_stride(frame_stride) {} |
+ buffer_size(buffer_size) {} |
const scoped_ptr<base::SharedMemory> buffer; |
const size_t buffer_size; |
- const int frame_width; // In pixels. |
- const int frame_height; // In pixels. |
- const int frame_stride; // In pixels. |
private: |
friend class base::RefCountedThreadSafe<ClientBuffer>; |
@@ -45,19 +36,19 @@ bool VideoCaptureImpl::CaptureStarted() { |
} |
int VideoCaptureImpl::CaptureWidth() { |
- return capture_format_.width; |
+ return requested_params_.width; |
} |
int VideoCaptureImpl::CaptureHeight() { |
- return capture_format_.height; |
+ return requested_params_.height; |
} |
int VideoCaptureImpl::CaptureFrameRate() { |
- return capture_format_.frame_rate; |
+ return requested_params_.frame_rate; |
} |
VideoCaptureImpl::VideoCaptureImpl( |
- const media::VideoCaptureSessionId id, |
+ const media::VideoCaptureSessionId session_id, |
base::MessageLoopProxy* capture_message_loop_proxy, |
VideoCaptureMessageFilter* filter) |
: VideoCapture(), |
@@ -65,13 +56,11 @@ VideoCaptureImpl::VideoCaptureImpl( |
capture_message_loop_proxy_(capture_message_loop_proxy), |
io_message_loop_proxy_(ChildProcess::current()->io_message_loop_proxy()), |
device_id_(0), |
+ session_id_(session_id), |
client_buffer_weak_this_factory_(this), |
- video_type_(media::PIXEL_FORMAT_I420), |
- device_info_available_(false), |
suspended_(false), |
state_(VIDEO_CAPTURE_STATE_STOPPED) { |
DCHECK(filter); |
- capture_format_.session_id = id; |
} |
VideoCaptureImpl::~VideoCaptureImpl() {} |
@@ -94,12 +83,10 @@ void VideoCaptureImpl::DeInit(base::Closure task) { |
void VideoCaptureImpl::StartCapture( |
media::VideoCapture::EventHandler* handler, |
- const media::VideoCaptureCapability& capability) { |
- DCHECK_EQ(capability.color, media::PIXEL_FORMAT_I420); |
- |
+ const media::VideoCaptureParams& params) { |
capture_message_loop_proxy_->PostTask(FROM_HERE, |
base::Bind(&VideoCaptureImpl::DoStartCaptureOnCaptureThread, |
- base::Unretained(this), handler, capability)); |
+ base::Unretained(this), handler, params)); |
} |
void VideoCaptureImpl::StopCapture(media::VideoCapture::EventHandler* handler) { |
@@ -116,10 +103,19 @@ void VideoCaptureImpl::OnBufferCreated( |
base::Unretained(this), handle, length, buffer_id)); |
} |
-void VideoCaptureImpl::OnBufferReceived(int buffer_id, base::Time timestamp) { |
+void VideoCaptureImpl::OnBufferDestroyed(int buffer_id) { |
+ capture_message_loop_proxy_->PostTask(FROM_HERE, |
+ base::Bind(&VideoCaptureImpl::DoBufferDestroyedOnCaptureThread, |
+ base::Unretained(this), buffer_id)); |
+} |
+ |
+void VideoCaptureImpl::OnBufferReceived( |
+ int buffer_id, |
+ base::Time timestamp, |
+ const media::VideoCaptureFormat& format) { |
capture_message_loop_proxy_->PostTask(FROM_HERE, |
base::Bind(&VideoCaptureImpl::DoBufferReceivedOnCaptureThread, |
- base::Unretained(this), buffer_id, timestamp)); |
+ base::Unretained(this), buffer_id, timestamp, format)); |
} |
void VideoCaptureImpl::OnStateChanged(VideoCaptureState state) { |
@@ -128,20 +124,6 @@ void VideoCaptureImpl::OnStateChanged(VideoCaptureState state) { |
base::Unretained(this), state)); |
} |
-void VideoCaptureImpl::OnDeviceInfoReceived( |
- const media::VideoCaptureParams& device_info) { |
- capture_message_loop_proxy_->PostTask(FROM_HERE, |
- base::Bind(&VideoCaptureImpl::DoDeviceInfoReceivedOnCaptureThread, |
- base::Unretained(this), device_info)); |
-} |
- |
-void VideoCaptureImpl::OnDeviceInfoChanged( |
- const media::VideoCaptureParams& device_info) { |
- capture_message_loop_proxy_->PostTask(FROM_HERE, |
- base::Bind(&VideoCaptureImpl::DoDeviceInfoChangedOnCaptureThread, |
- base::Unretained(this), device_info)); |
-} |
- |
void VideoCaptureImpl::OnDelegateAdded(int32 device_id) { |
capture_message_loop_proxy_->PostTask(FROM_HERE, |
base::Bind(&VideoCaptureImpl::DoDelegateAddedOnCaptureThread, |
@@ -165,7 +147,7 @@ void VideoCaptureImpl::DoDeInitOnCaptureThread(base::Closure task) { |
void VideoCaptureImpl::DoStartCaptureOnCaptureThread( |
media::VideoCapture::EventHandler* handler, |
- const media::VideoCaptureCapability& capability) { |
+ const media::VideoCaptureParams& params) { |
DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
if (state_ == VIDEO_CAPTURE_STATE_ERROR) { |
@@ -178,46 +160,31 @@ void VideoCaptureImpl::DoStartCaptureOnCaptureThread( |
clients_.find(handler) != clients_.end() ) { |
// This client has started. |
} else if (!device_id_) { |
- clients_pending_on_filter_[handler] = capability; |
+ clients_pending_on_filter_[handler] = params; |
} else { |
handler->OnStarted(this); |
if (state_ == VIDEO_CAPTURE_STATE_STARTED) { |
- // TODO(wjia): Temporarily disable restarting till client supports |
- // resampling. |
-#if 0 |
- if (capability.width > capture_format_.width || |
- capability.height > capture_format_.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 { |
-#endif |
- { |
- if (device_info_available_) { |
- handler->OnDeviceInfoReceived(this, device_info_); |
- } |
- |
- clients_[handler] = capability; |
+ if (last_device_info_.IsValid()) { |
+ handler->OnDeviceInfoReceived(this, last_device_info_); |
} |
+ |
+ clients_[handler] = params; |
} else if (state_ == VIDEO_CAPTURE_STATE_STOPPING) { |
- clients_pending_on_restart_[handler] = capability; |
+ clients_pending_on_restart_[handler] = params; |
DVLOG(1) << "StartCapture: Got new resolution (" |
- << capability.width << ", " << capability.height << ") " |
+ << params.width << ", " << params.height << ") " |
<< ", during stopping."; |
} else { |
- clients_[handler] = capability; |
+ DCHECK_EQ(params.session_id, 0); |
+ clients_[handler] = params; |
DCHECK_EQ(1ul, clients_.size()); |
- video_type_ = capability.color; |
- int session_id = capture_format_.session_id; |
- DCHECK_EQ(capability.session_id, 0); |
- capture_format_ = capability; |
- capture_format_.session_id = session_id; |
- if (capture_format_.frame_rate > media::limits::kMaxFramesPerSecond) |
- capture_format_.frame_rate = media::limits::kMaxFramesPerSecond; |
+ requested_params_ = params; |
+ requested_params_.session_id = session_id_; |
+ if (requested_params_.frame_rate > media::limits::kMaxFramesPerSecond) |
+ requested_params_.frame_rate = media::limits::kMaxFramesPerSecond; |
DVLOG(1) << "StartCapture: starting with first resolution (" |
- << capture_format_.width << "," << capture_format_.height << ")"; |
+ << requested_params_.width << "," |
+ << requested_params_.height << ")"; |
StartCaptureInternal(); |
} |
@@ -255,8 +222,6 @@ void VideoCaptureImpl::DoBufferCreatedOnCaptureThread( |
return; |
} |
- DCHECK(device_info_available_); |
- |
scoped_ptr<base::SharedMemory> shm(new base::SharedMemory(handle, false)); |
if (!shm->Map(length)) { |
DLOG(ERROR) << "DoBufferCreatedOnCaptureThread: Map() failed."; |
@@ -267,15 +232,26 @@ void VideoCaptureImpl::DoBufferCreatedOnCaptureThread( |
client_buffers_.insert(std::make_pair( |
buffer_id, |
new ClientBuffer(shm.Pass(), |
- length, |
- device_info_.width, |
- device_info_.height, |
- device_info_.width))).second; |
+ length))).second; |
DCHECK(inserted); |
} |
+void VideoCaptureImpl::DoBufferDestroyedOnCaptureThread(int buffer_id) { |
+ DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
+ |
+ ClientBufferMap::iterator iter = client_buffers_.find(buffer_id); |
+ if (iter == client_buffers_.end()) |
+ return; |
+ |
+ DCHECK(!iter->second || iter->second->HasOneRef()) |
+ << "Instructed to delete buffer we are still using."; |
+ client_buffers_.erase(iter); |
+} |
+ |
void VideoCaptureImpl::DoBufferReceivedOnCaptureThread( |
- int buffer_id, base::Time timestamp) { |
+ int buffer_id, |
+ base::Time timestamp, |
+ const media::VideoCaptureFormat& format) { |
DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
if (state_ != VIDEO_CAPTURE_STATE_STARTED || suspended_) { |
@@ -283,15 +259,29 @@ void VideoCaptureImpl::DoBufferReceivedOnCaptureThread( |
return; |
} |
+ // Synthesize deviceinfo notifications for listeners when the resolution |
+ // changes. |
+ if (!last_device_info_.IsValid()) { |
+ for (ClientInfo::iterator i = clients_.begin(); i != clients_.end(); ++i) { |
+ i->first->OnDeviceInfoReceived(this, format); |
+ } |
+ } else if (last_device_info_.width != format.width || |
+ last_device_info_.height != format.height) { |
+ for (ClientInfo::iterator i = clients_.begin(); i != clients_.end(); ++i) { |
+ i->first->OnDeviceInfoChanged(this, format); |
+ } |
+ } |
+ last_device_info_ = format; |
+ |
+ gfx::Size size(last_device_info_.width, last_device_info_.height); |
+ |
ClientBufferMap::iterator iter = client_buffers_.find(buffer_id); |
DCHECK(iter != client_buffers_.end()); |
scoped_refptr<ClientBuffer> buffer = iter->second; |
scoped_refptr<media::VideoFrame> frame = |
media::VideoFrame::WrapExternalSharedMemory( |
media::VideoFrame::I420, |
- gfx::Size(buffer->frame_stride, buffer->frame_height), |
- gfx::Rect(0, 0, buffer->frame_width, buffer->frame_height), |
- gfx::Size(buffer->frame_width, buffer->frame_height), |
+ size, gfx::Rect(size), size, |
reinterpret_cast<uint8*>(buffer->buffer->memory()), |
buffer->buffer_size, |
buffer->buffer->handle(), |
@@ -362,27 +352,6 @@ void VideoCaptureImpl::DoStateChangedOnCaptureThread(VideoCaptureState state) { |
} |
} |
-void VideoCaptureImpl::DoDeviceInfoReceivedOnCaptureThread( |
- const media::VideoCaptureParams& device_info) { |
- DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
- DCHECK(client_buffers_.empty()); |
- |
- device_info_ = device_info; |
- device_info_available_ = true; |
- for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); ++it) { |
- it->first->OnDeviceInfoReceived(this, device_info); |
- } |
-} |
- |
-void VideoCaptureImpl::DoDeviceInfoChangedOnCaptureThread( |
- const media::VideoCaptureParams& device_info) { |
- DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
- |
- for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); ++it) { |
- it->first->OnDeviceInfoChanged(this, device_info); |
- } |
-} |
- |
void VideoCaptureImpl::DoDelegateAddedOnCaptureThread(int32 device_id) { |
DVLOG(1) << "DoDelegateAdded: device_id " << device_id; |
DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
@@ -391,9 +360,9 @@ void VideoCaptureImpl::DoDelegateAddedOnCaptureThread(int32 device_id) { |
for (ClientInfo::iterator it = clients_pending_on_filter_.begin(); |
it != clients_pending_on_filter_.end(); ) { |
media::VideoCapture::EventHandler* handler = it->first; |
- const media::VideoCaptureCapability capability = it->second; |
+ const media::VideoCaptureParams params = it->second; |
clients_pending_on_filter_.erase(it++); |
- StartCapture(handler, capability); |
+ StartCapture(handler, params); |
} |
} |
@@ -407,11 +376,11 @@ void VideoCaptureImpl::DoSuspendCaptureOnCaptureThread(bool suspend) { |
void VideoCaptureImpl::StopDevice() { |
DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
- device_info_available_ = false; |
+ last_device_info_ = media::VideoCaptureParams(); |
if (state_ == VIDEO_CAPTURE_STATE_STARTED) { |
state_ = VIDEO_CAPTURE_STATE_STOPPING; |
Send(new VideoCaptureHostMsg_Stop(device_id_)); |
- capture_format_.width = capture_format_.height = 0; |
+ requested_params_.width = requested_params_.height = 0; |
} |
} |
@@ -433,10 +402,10 @@ void VideoCaptureImpl::RestartCapture() { |
clients_[it->first] = it->second; |
clients_pending_on_restart_.erase(it++); |
} |
- capture_format_.width = width; |
- capture_format_.height = height; |
- DVLOG(1) << "RestartCapture, " << capture_format_.width << ", " |
- << capture_format_.height; |
+ requested_params_.width = width; |
+ requested_params_.height = height; |
+ DVLOG(1) << "RestartCapture, " << requested_params_.width << ", " |
+ << requested_params_.height; |
StartCaptureInternal(); |
} |
@@ -444,13 +413,7 @@ void VideoCaptureImpl::StartCaptureInternal() { |
DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
DCHECK(device_id_); |
- media::VideoCaptureParams capability_as_params_copy; |
- capability_as_params_copy.width = capture_format_.width; |
- capability_as_params_copy.height = capture_format_.height; |
- capability_as_params_copy.frame_rate = capture_format_.frame_rate; |
- capability_as_params_copy.session_id = capture_format_.session_id; |
- capability_as_params_copy.frame_size_type = capture_format_.frame_size_type; |
- Send(new VideoCaptureHostMsg_Start(device_id_, capability_as_params_copy)); |
+ Send(new VideoCaptureHostMsg_Start(device_id_, requested_params_)); |
state_ = VIDEO_CAPTURE_STATE_STARTED; |
} |