| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/renderer/media/video_capture_impl.h" | 5 #include "content/renderer/media/video_capture_impl.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/stl_util.h" | 8 #include "base/stl_util.h" |
| 9 #include "content/child/child_process.h" | 9 #include "content/child/child_process.h" |
| 10 #include "content/common/media/video_capture_messages.h" | 10 #include "content/common/media/video_capture_messages.h" |
| 11 #include "media/base/bind_to_loop.h" | 11 #include "media/base/bind_to_loop.h" |
| 12 #include "media/base/limits.h" | 12 #include "media/base/limits.h" |
| 13 | 13 |
| 14 namespace content { | 14 namespace content { |
| 15 | 15 |
| 16 class VideoCaptureImpl::ClientBuffer | 16 class VideoCaptureImpl::ClientBuffer |
| 17 : public base::RefCountedThreadSafe<ClientBuffer> { | 17 : public base::RefCountedThreadSafe<ClientBuffer> { |
| 18 public: | 18 public: |
| 19 ClientBuffer(scoped_ptr<base::SharedMemory> buffer, | 19 ClientBuffer(scoped_ptr<base::SharedMemory> buffer, |
| 20 size_t buffer_size, | 20 size_t buffer_size) |
| 21 int frame_width, | |
| 22 int frame_height, | |
| 23 int frame_stride) | |
| 24 : buffer(buffer.Pass()), | 21 : buffer(buffer.Pass()), |
| 25 buffer_size(buffer_size), | 22 buffer_size(buffer_size) {} |
| 26 frame_width(frame_width), | |
| 27 frame_height(frame_height), | |
| 28 frame_stride(frame_stride) {} | |
| 29 const scoped_ptr<base::SharedMemory> buffer; | 23 const scoped_ptr<base::SharedMemory> buffer; |
| 30 const size_t buffer_size; | 24 const size_t buffer_size; |
| 31 const int frame_width; // In pixels. | |
| 32 const int frame_height; // In pixels. | |
| 33 const int frame_stride; // In pixels. | |
| 34 | 25 |
| 35 private: | 26 private: |
| 36 friend class base::RefCountedThreadSafe<ClientBuffer>; | 27 friend class base::RefCountedThreadSafe<ClientBuffer>; |
| 37 | 28 |
| 38 virtual ~ClientBuffer() {} | 29 virtual ~ClientBuffer() {} |
| 39 | 30 |
| 40 DISALLOW_COPY_AND_ASSIGN(ClientBuffer); | 31 DISALLOW_COPY_AND_ASSIGN(ClientBuffer); |
| 41 }; | 32 }; |
| 42 | 33 |
| 43 bool VideoCaptureImpl::CaptureStarted() { | 34 bool VideoCaptureImpl::CaptureStarted() { |
| 44 return state_ == VIDEO_CAPTURE_STATE_STARTED; | 35 return state_ == VIDEO_CAPTURE_STATE_STARTED; |
| 45 } | 36 } |
| 46 | 37 |
| 47 int VideoCaptureImpl::CaptureWidth() { | 38 int VideoCaptureImpl::CaptureWidth() { |
| 48 return capture_format_.width; | 39 return requested_params_.width; |
| 49 } | 40 } |
| 50 | 41 |
| 51 int VideoCaptureImpl::CaptureHeight() { | 42 int VideoCaptureImpl::CaptureHeight() { |
| 52 return capture_format_.height; | 43 return requested_params_.height; |
| 53 } | 44 } |
| 54 | 45 |
| 55 int VideoCaptureImpl::CaptureFrameRate() { | 46 int VideoCaptureImpl::CaptureFrameRate() { |
| 56 return capture_format_.frame_rate; | 47 return requested_params_.frame_rate; |
| 57 } | 48 } |
| 58 | 49 |
| 59 VideoCaptureImpl::VideoCaptureImpl( | 50 VideoCaptureImpl::VideoCaptureImpl( |
| 60 const media::VideoCaptureSessionId id, | 51 const media::VideoCaptureSessionId session_id, |
| 61 base::MessageLoopProxy* capture_message_loop_proxy, | 52 base::MessageLoopProxy* capture_message_loop_proxy, |
| 62 VideoCaptureMessageFilter* filter) | 53 VideoCaptureMessageFilter* filter) |
| 63 : VideoCapture(), | 54 : VideoCapture(), |
| 64 message_filter_(filter), | 55 message_filter_(filter), |
| 65 capture_message_loop_proxy_(capture_message_loop_proxy), | 56 capture_message_loop_proxy_(capture_message_loop_proxy), |
| 66 io_message_loop_proxy_(ChildProcess::current()->io_message_loop_proxy()), | 57 io_message_loop_proxy_(ChildProcess::current()->io_message_loop_proxy()), |
| 67 device_id_(0), | 58 device_id_(0), |
| 59 session_id_(session_id), |
| 68 client_buffer_weak_this_factory_(this), | 60 client_buffer_weak_this_factory_(this), |
| 69 video_type_(media::PIXEL_FORMAT_I420), | |
| 70 device_info_available_(false), | |
| 71 suspended_(false), | 61 suspended_(false), |
| 72 state_(VIDEO_CAPTURE_STATE_STOPPED) { | 62 state_(VIDEO_CAPTURE_STATE_STOPPED) { |
| 73 DCHECK(filter); | 63 DCHECK(filter); |
| 74 capture_format_.session_id = id; | |
| 75 } | 64 } |
| 76 | 65 |
| 77 VideoCaptureImpl::~VideoCaptureImpl() {} | 66 VideoCaptureImpl::~VideoCaptureImpl() {} |
| 78 | 67 |
| 79 void VideoCaptureImpl::Init() { | 68 void VideoCaptureImpl::Init() { |
| 80 if (!io_message_loop_proxy_->BelongsToCurrentThread()) { | 69 if (!io_message_loop_proxy_->BelongsToCurrentThread()) { |
| 81 io_message_loop_proxy_->PostTask(FROM_HERE, | 70 io_message_loop_proxy_->PostTask(FROM_HERE, |
| 82 base::Bind(&VideoCaptureImpl::AddDelegateOnIOThread, | 71 base::Bind(&VideoCaptureImpl::AddDelegateOnIOThread, |
| 83 base::Unretained(this))); | 72 base::Unretained(this))); |
| 84 } else { | 73 } else { |
| 85 AddDelegateOnIOThread(); | 74 AddDelegateOnIOThread(); |
| 86 } | 75 } |
| 87 } | 76 } |
| 88 | 77 |
| 89 void VideoCaptureImpl::DeInit(base::Closure task) { | 78 void VideoCaptureImpl::DeInit(base::Closure task) { |
| 90 capture_message_loop_proxy_->PostTask(FROM_HERE, | 79 capture_message_loop_proxy_->PostTask(FROM_HERE, |
| 91 base::Bind(&VideoCaptureImpl::DoDeInitOnCaptureThread, | 80 base::Bind(&VideoCaptureImpl::DoDeInitOnCaptureThread, |
| 92 base::Unretained(this), task)); | 81 base::Unretained(this), task)); |
| 93 } | 82 } |
| 94 | 83 |
| 95 void VideoCaptureImpl::StartCapture( | 84 void VideoCaptureImpl::StartCapture( |
| 96 media::VideoCapture::EventHandler* handler, | 85 media::VideoCapture::EventHandler* handler, |
| 97 const media::VideoCaptureCapability& capability) { | 86 const media::VideoCaptureParams& params) { |
| 98 DCHECK_EQ(capability.color, media::PIXEL_FORMAT_I420); | |
| 99 | |
| 100 capture_message_loop_proxy_->PostTask(FROM_HERE, | 87 capture_message_loop_proxy_->PostTask(FROM_HERE, |
| 101 base::Bind(&VideoCaptureImpl::DoStartCaptureOnCaptureThread, | 88 base::Bind(&VideoCaptureImpl::DoStartCaptureOnCaptureThread, |
| 102 base::Unretained(this), handler, capability)); | 89 base::Unretained(this), handler, params)); |
| 103 } | 90 } |
| 104 | 91 |
| 105 void VideoCaptureImpl::StopCapture(media::VideoCapture::EventHandler* handler) { | 92 void VideoCaptureImpl::StopCapture(media::VideoCapture::EventHandler* handler) { |
| 106 capture_message_loop_proxy_->PostTask(FROM_HERE, | 93 capture_message_loop_proxy_->PostTask(FROM_HERE, |
| 107 base::Bind(&VideoCaptureImpl::DoStopCaptureOnCaptureThread, | 94 base::Bind(&VideoCaptureImpl::DoStopCaptureOnCaptureThread, |
| 108 base::Unretained(this), handler)); | 95 base::Unretained(this), handler)); |
| 109 } | 96 } |
| 110 | 97 |
| 111 void VideoCaptureImpl::OnBufferCreated( | 98 void VideoCaptureImpl::OnBufferCreated( |
| 112 base::SharedMemoryHandle handle, | 99 base::SharedMemoryHandle handle, |
| 113 int length, int buffer_id) { | 100 int length, int buffer_id) { |
| 114 capture_message_loop_proxy_->PostTask(FROM_HERE, | 101 capture_message_loop_proxy_->PostTask(FROM_HERE, |
| 115 base::Bind(&VideoCaptureImpl::DoBufferCreatedOnCaptureThread, | 102 base::Bind(&VideoCaptureImpl::DoBufferCreatedOnCaptureThread, |
| 116 base::Unretained(this), handle, length, buffer_id)); | 103 base::Unretained(this), handle, length, buffer_id)); |
| 117 } | 104 } |
| 118 | 105 |
| 119 void VideoCaptureImpl::OnBufferReceived(int buffer_id, base::Time timestamp) { | 106 void VideoCaptureImpl::OnBufferDestroyed(int buffer_id) { |
| 107 capture_message_loop_proxy_->PostTask(FROM_HERE, |
| 108 base::Bind(&VideoCaptureImpl::DoBufferDestroyedOnCaptureThread, |
| 109 base::Unretained(this), buffer_id)); |
| 110 } |
| 111 |
| 112 void VideoCaptureImpl::OnBufferReceived( |
| 113 int buffer_id, |
| 114 base::Time timestamp, |
| 115 const media::VideoCaptureFormat& format) { |
| 120 capture_message_loop_proxy_->PostTask(FROM_HERE, | 116 capture_message_loop_proxy_->PostTask(FROM_HERE, |
| 121 base::Bind(&VideoCaptureImpl::DoBufferReceivedOnCaptureThread, | 117 base::Bind(&VideoCaptureImpl::DoBufferReceivedOnCaptureThread, |
| 122 base::Unretained(this), buffer_id, timestamp)); | 118 base::Unretained(this), buffer_id, timestamp, format)); |
| 123 } | 119 } |
| 124 | 120 |
| 125 void VideoCaptureImpl::OnStateChanged(VideoCaptureState state) { | 121 void VideoCaptureImpl::OnStateChanged(VideoCaptureState state) { |
| 126 capture_message_loop_proxy_->PostTask(FROM_HERE, | 122 capture_message_loop_proxy_->PostTask(FROM_HERE, |
| 127 base::Bind(&VideoCaptureImpl::DoStateChangedOnCaptureThread, | 123 base::Bind(&VideoCaptureImpl::DoStateChangedOnCaptureThread, |
| 128 base::Unretained(this), state)); | 124 base::Unretained(this), state)); |
| 129 } | 125 } |
| 130 | 126 |
| 131 void VideoCaptureImpl::OnDeviceInfoReceived( | |
| 132 const media::VideoCaptureParams& device_info) { | |
| 133 capture_message_loop_proxy_->PostTask(FROM_HERE, | |
| 134 base::Bind(&VideoCaptureImpl::DoDeviceInfoReceivedOnCaptureThread, | |
| 135 base::Unretained(this), device_info)); | |
| 136 } | |
| 137 | |
| 138 void VideoCaptureImpl::OnDeviceInfoChanged( | |
| 139 const media::VideoCaptureParams& device_info) { | |
| 140 capture_message_loop_proxy_->PostTask(FROM_HERE, | |
| 141 base::Bind(&VideoCaptureImpl::DoDeviceInfoChangedOnCaptureThread, | |
| 142 base::Unretained(this), device_info)); | |
| 143 } | |
| 144 | |
| 145 void VideoCaptureImpl::OnDelegateAdded(int32 device_id) { | 127 void VideoCaptureImpl::OnDelegateAdded(int32 device_id) { |
| 146 capture_message_loop_proxy_->PostTask(FROM_HERE, | 128 capture_message_loop_proxy_->PostTask(FROM_HERE, |
| 147 base::Bind(&VideoCaptureImpl::DoDelegateAddedOnCaptureThread, | 129 base::Bind(&VideoCaptureImpl::DoDelegateAddedOnCaptureThread, |
| 148 base::Unretained(this), device_id)); | 130 base::Unretained(this), device_id)); |
| 149 } | 131 } |
| 150 | 132 |
| 151 void VideoCaptureImpl::SuspendCapture(bool suspend) { | 133 void VideoCaptureImpl::SuspendCapture(bool suspend) { |
| 152 capture_message_loop_proxy_->PostTask(FROM_HERE, | 134 capture_message_loop_proxy_->PostTask(FROM_HERE, |
| 153 base::Bind(&VideoCaptureImpl::DoSuspendCaptureOnCaptureThread, | 135 base::Bind(&VideoCaptureImpl::DoSuspendCaptureOnCaptureThread, |
| 154 base::Unretained(this), suspend)); | 136 base::Unretained(this), suspend)); |
| 155 } | 137 } |
| 156 | 138 |
| 157 void VideoCaptureImpl::DoDeInitOnCaptureThread(base::Closure task) { | 139 void VideoCaptureImpl::DoDeInitOnCaptureThread(base::Closure task) { |
| 158 if (state_ == VIDEO_CAPTURE_STATE_STARTED) | 140 if (state_ == VIDEO_CAPTURE_STATE_STARTED) |
| 159 Send(new VideoCaptureHostMsg_Stop(device_id_)); | 141 Send(new VideoCaptureHostMsg_Stop(device_id_)); |
| 160 | 142 |
| 161 io_message_loop_proxy_->PostTask(FROM_HERE, | 143 io_message_loop_proxy_->PostTask(FROM_HERE, |
| 162 base::Bind(&VideoCaptureImpl::RemoveDelegateOnIOThread, | 144 base::Bind(&VideoCaptureImpl::RemoveDelegateOnIOThread, |
| 163 base::Unretained(this), task)); | 145 base::Unretained(this), task)); |
| 164 } | 146 } |
| 165 | 147 |
| 166 void VideoCaptureImpl::DoStartCaptureOnCaptureThread( | 148 void VideoCaptureImpl::DoStartCaptureOnCaptureThread( |
| 167 media::VideoCapture::EventHandler* handler, | 149 media::VideoCapture::EventHandler* handler, |
| 168 const media::VideoCaptureCapability& capability) { | 150 const media::VideoCaptureParams& params) { |
| 169 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); | 151 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
| 170 | 152 |
| 171 if (state_ == VIDEO_CAPTURE_STATE_ERROR) { | 153 if (state_ == VIDEO_CAPTURE_STATE_ERROR) { |
| 172 handler->OnError(this, 1); | 154 handler->OnError(this, 1); |
| 173 handler->OnRemoved(this); | 155 handler->OnRemoved(this); |
| 174 } else if ((clients_pending_on_filter_.find(handler) != | 156 } else if ((clients_pending_on_filter_.find(handler) != |
| 175 clients_pending_on_filter_.end()) || | 157 clients_pending_on_filter_.end()) || |
| 176 (clients_pending_on_restart_.find(handler) != | 158 (clients_pending_on_restart_.find(handler) != |
| 177 clients_pending_on_restart_.end()) || | 159 clients_pending_on_restart_.end()) || |
| 178 clients_.find(handler) != clients_.end() ) { | 160 clients_.find(handler) != clients_.end() ) { |
| 179 // This client has started. | 161 // This client has started. |
| 180 } else if (!device_id_) { | 162 } else if (!device_id_) { |
| 181 clients_pending_on_filter_[handler] = capability; | 163 clients_pending_on_filter_[handler] = params; |
| 182 } else { | 164 } else { |
| 183 handler->OnStarted(this); | 165 handler->OnStarted(this); |
| 184 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { | 166 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { |
| 185 // TODO(wjia): Temporarily disable restarting till client supports | 167 if (last_device_info_.IsValid()) { |
| 186 // resampling. | 168 handler->OnDeviceInfoReceived(this, last_device_info_); |
| 187 #if 0 | 169 } |
| 188 if (capability.width > capture_format_.width || | |
| 189 capability.height > capture_format_.height) { | |
| 190 StopDevice(); | |
| 191 DVLOG(1) << "StartCapture: Got client with higher resolution (" | |
| 192 << capability.width << ", " << capability.height << ") " | |
| 193 << "after started, try to restart."; | |
| 194 clients_pending_on_restart_[handler] = capability; | |
| 195 } else { | |
| 196 #endif | |
| 197 { | |
| 198 if (device_info_available_) { | |
| 199 handler->OnDeviceInfoReceived(this, device_info_); | |
| 200 } | |
| 201 | 170 |
| 202 clients_[handler] = capability; | 171 clients_[handler] = params; |
| 203 } | |
| 204 } else if (state_ == VIDEO_CAPTURE_STATE_STOPPING) { | 172 } else if (state_ == VIDEO_CAPTURE_STATE_STOPPING) { |
| 205 clients_pending_on_restart_[handler] = capability; | 173 clients_pending_on_restart_[handler] = params; |
| 206 DVLOG(1) << "StartCapture: Got new resolution (" | 174 DVLOG(1) << "StartCapture: Got new resolution (" |
| 207 << capability.width << ", " << capability.height << ") " | 175 << params.width << ", " << params.height << ") " |
| 208 << ", during stopping."; | 176 << ", during stopping."; |
| 209 } else { | 177 } else { |
| 210 clients_[handler] = capability; | 178 DCHECK_EQ(params.session_id, 0); |
| 179 clients_[handler] = params; |
| 211 DCHECK_EQ(1ul, clients_.size()); | 180 DCHECK_EQ(1ul, clients_.size()); |
| 212 video_type_ = capability.color; | 181 requested_params_ = params; |
| 213 int session_id = capture_format_.session_id; | 182 requested_params_.session_id = session_id_; |
| 214 DCHECK_EQ(capability.session_id, 0); | 183 if (requested_params_.frame_rate > media::limits::kMaxFramesPerSecond) |
| 215 capture_format_ = capability; | 184 requested_params_.frame_rate = media::limits::kMaxFramesPerSecond; |
| 216 capture_format_.session_id = session_id; | |
| 217 if (capture_format_.frame_rate > media::limits::kMaxFramesPerSecond) | |
| 218 capture_format_.frame_rate = media::limits::kMaxFramesPerSecond; | |
| 219 DVLOG(1) << "StartCapture: starting with first resolution (" | 185 DVLOG(1) << "StartCapture: starting with first resolution (" |
| 220 << capture_format_.width << "," << capture_format_.height << ")"; | 186 << requested_params_.width << "," |
| 187 << requested_params_.height << ")"; |
| 221 | 188 |
| 222 StartCaptureInternal(); | 189 StartCaptureInternal(); |
| 223 } | 190 } |
| 224 } | 191 } |
| 225 } | 192 } |
| 226 | 193 |
| 227 void VideoCaptureImpl::DoStopCaptureOnCaptureThread( | 194 void VideoCaptureImpl::DoStopCaptureOnCaptureThread( |
| 228 media::VideoCapture::EventHandler* handler) { | 195 media::VideoCapture::EventHandler* handler) { |
| 229 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); | 196 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
| 230 | 197 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 248 int length, int buffer_id) { | 215 int length, int buffer_id) { |
| 249 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); | 216 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
| 250 | 217 |
| 251 // In case client calls StopCapture before the arrival of created buffer, | 218 // In case client calls StopCapture before the arrival of created buffer, |
| 252 // just close this buffer and return. | 219 // just close this buffer and return. |
| 253 if (state_ != VIDEO_CAPTURE_STATE_STARTED) { | 220 if (state_ != VIDEO_CAPTURE_STATE_STARTED) { |
| 254 base::SharedMemory::CloseHandle(handle); | 221 base::SharedMemory::CloseHandle(handle); |
| 255 return; | 222 return; |
| 256 } | 223 } |
| 257 | 224 |
| 258 DCHECK(device_info_available_); | |
| 259 | |
| 260 scoped_ptr<base::SharedMemory> shm(new base::SharedMemory(handle, false)); | 225 scoped_ptr<base::SharedMemory> shm(new base::SharedMemory(handle, false)); |
| 261 if (!shm->Map(length)) { | 226 if (!shm->Map(length)) { |
| 262 DLOG(ERROR) << "DoBufferCreatedOnCaptureThread: Map() failed."; | 227 DLOG(ERROR) << "DoBufferCreatedOnCaptureThread: Map() failed."; |
| 263 return; | 228 return; |
| 264 } | 229 } |
| 265 | 230 |
| 266 bool inserted = | 231 bool inserted = |
| 267 client_buffers_.insert(std::make_pair( | 232 client_buffers_.insert(std::make_pair( |
| 268 buffer_id, | 233 buffer_id, |
| 269 new ClientBuffer(shm.Pass(), | 234 new ClientBuffer(shm.Pass(), |
| 270 length, | 235 length))).second; |
| 271 device_info_.width, | |
| 272 device_info_.height, | |
| 273 device_info_.width))).second; | |
| 274 DCHECK(inserted); | 236 DCHECK(inserted); |
| 275 } | 237 } |
| 276 | 238 |
| 239 void VideoCaptureImpl::DoBufferDestroyedOnCaptureThread(int buffer_id) { |
| 240 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
| 241 |
| 242 ClientBufferMap::iterator iter = client_buffers_.find(buffer_id); |
| 243 if (iter == client_buffers_.end()) |
| 244 return; |
| 245 |
| 246 DCHECK(!iter->second || iter->second->HasOneRef()) |
| 247 << "Instructed to delete buffer we are still using."; |
| 248 client_buffers_.erase(iter); |
| 249 } |
| 250 |
| 277 void VideoCaptureImpl::DoBufferReceivedOnCaptureThread( | 251 void VideoCaptureImpl::DoBufferReceivedOnCaptureThread( |
| 278 int buffer_id, base::Time timestamp) { | 252 int buffer_id, |
| 253 base::Time timestamp, |
| 254 const media::VideoCaptureFormat& format) { |
| 279 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); | 255 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
| 280 | 256 |
| 281 if (state_ != VIDEO_CAPTURE_STATE_STARTED || suspended_) { | 257 if (state_ != VIDEO_CAPTURE_STATE_STARTED || suspended_) { |
| 282 Send(new VideoCaptureHostMsg_BufferReady(device_id_, buffer_id)); | 258 Send(new VideoCaptureHostMsg_BufferReady(device_id_, buffer_id)); |
| 283 return; | 259 return; |
| 284 } | 260 } |
| 285 | 261 |
| 262 // Synthesize deviceinfo notifications for listeners when the resolution |
| 263 // changes. |
| 264 if (!last_device_info_.IsValid()) { |
| 265 for (ClientInfo::iterator i = clients_.begin(); i != clients_.end(); ++i) { |
| 266 i->first->OnDeviceInfoReceived(this, format); |
| 267 } |
| 268 } else if (last_device_info_.width != format.width || |
| 269 last_device_info_.height != format.height) { |
| 270 for (ClientInfo::iterator i = clients_.begin(); i != clients_.end(); ++i) { |
| 271 i->first->OnDeviceInfoChanged(this, format); |
| 272 } |
| 273 } |
| 274 last_device_info_ = format; |
| 275 |
| 276 gfx::Size size(last_device_info_.width, last_device_info_.height); |
| 277 |
| 286 ClientBufferMap::iterator iter = client_buffers_.find(buffer_id); | 278 ClientBufferMap::iterator iter = client_buffers_.find(buffer_id); |
| 287 DCHECK(iter != client_buffers_.end()); | 279 DCHECK(iter != client_buffers_.end()); |
| 288 scoped_refptr<ClientBuffer> buffer = iter->second; | 280 scoped_refptr<ClientBuffer> buffer = iter->second; |
| 289 scoped_refptr<media::VideoFrame> frame = | 281 scoped_refptr<media::VideoFrame> frame = |
| 290 media::VideoFrame::WrapExternalSharedMemory( | 282 media::VideoFrame::WrapExternalSharedMemory( |
| 291 media::VideoFrame::I420, | 283 media::VideoFrame::I420, |
| 292 gfx::Size(buffer->frame_stride, buffer->frame_height), | 284 size, gfx::Rect(size), size, |
| 293 gfx::Rect(0, 0, buffer->frame_width, buffer->frame_height), | |
| 294 gfx::Size(buffer->frame_width, buffer->frame_height), | |
| 295 reinterpret_cast<uint8*>(buffer->buffer->memory()), | 285 reinterpret_cast<uint8*>(buffer->buffer->memory()), |
| 296 buffer->buffer_size, | 286 buffer->buffer_size, |
| 297 buffer->buffer->handle(), | 287 buffer->buffer->handle(), |
| 298 // TODO(sheu): convert VideoCaptureMessageFilter::Delegate to use | 288 // TODO(sheu): convert VideoCaptureMessageFilter::Delegate to use |
| 299 // base::TimeTicks instead of base::Time. http://crbug.com/249215 | 289 // base::TimeTicks instead of base::Time. http://crbug.com/249215 |
| 300 timestamp - base::Time::UnixEpoch(), | 290 timestamp - base::Time::UnixEpoch(), |
| 301 media::BindToLoop( | 291 media::BindToLoop( |
| 302 capture_message_loop_proxy_, | 292 capture_message_loop_proxy_, |
| 303 base::Bind( | 293 base::Bind( |
| 304 &VideoCaptureImpl::DoClientBufferFinishedOnCaptureThread, | 294 &VideoCaptureImpl::DoClientBufferFinishedOnCaptureThread, |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 355 it->first->OnRemoved(this); | 345 it->first->OnRemoved(this); |
| 356 } | 346 } |
| 357 clients_.clear(); | 347 clients_.clear(); |
| 358 state_ = VIDEO_CAPTURE_STATE_ENDED; | 348 state_ = VIDEO_CAPTURE_STATE_ENDED; |
| 359 break; | 349 break; |
| 360 default: | 350 default: |
| 361 break; | 351 break; |
| 362 } | 352 } |
| 363 } | 353 } |
| 364 | 354 |
| 365 void VideoCaptureImpl::DoDeviceInfoReceivedOnCaptureThread( | |
| 366 const media::VideoCaptureParams& device_info) { | |
| 367 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); | |
| 368 DCHECK(client_buffers_.empty()); | |
| 369 | |
| 370 device_info_ = device_info; | |
| 371 device_info_available_ = true; | |
| 372 for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); ++it) { | |
| 373 it->first->OnDeviceInfoReceived(this, device_info); | |
| 374 } | |
| 375 } | |
| 376 | |
| 377 void VideoCaptureImpl::DoDeviceInfoChangedOnCaptureThread( | |
| 378 const media::VideoCaptureParams& device_info) { | |
| 379 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); | |
| 380 | |
| 381 for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); ++it) { | |
| 382 it->first->OnDeviceInfoChanged(this, device_info); | |
| 383 } | |
| 384 } | |
| 385 | |
| 386 void VideoCaptureImpl::DoDelegateAddedOnCaptureThread(int32 device_id) { | 355 void VideoCaptureImpl::DoDelegateAddedOnCaptureThread(int32 device_id) { |
| 387 DVLOG(1) << "DoDelegateAdded: device_id " << device_id; | 356 DVLOG(1) << "DoDelegateAdded: device_id " << device_id; |
| 388 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); | 357 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
| 389 | 358 |
| 390 device_id_ = device_id; | 359 device_id_ = device_id; |
| 391 for (ClientInfo::iterator it = clients_pending_on_filter_.begin(); | 360 for (ClientInfo::iterator it = clients_pending_on_filter_.begin(); |
| 392 it != clients_pending_on_filter_.end(); ) { | 361 it != clients_pending_on_filter_.end(); ) { |
| 393 media::VideoCapture::EventHandler* handler = it->first; | 362 media::VideoCapture::EventHandler* handler = it->first; |
| 394 const media::VideoCaptureCapability capability = it->second; | 363 const media::VideoCaptureParams params = it->second; |
| 395 clients_pending_on_filter_.erase(it++); | 364 clients_pending_on_filter_.erase(it++); |
| 396 StartCapture(handler, capability); | 365 StartCapture(handler, params); |
| 397 } | 366 } |
| 398 } | 367 } |
| 399 | 368 |
| 400 void VideoCaptureImpl::DoSuspendCaptureOnCaptureThread(bool suspend) { | 369 void VideoCaptureImpl::DoSuspendCaptureOnCaptureThread(bool suspend) { |
| 401 DVLOG(1) << "DoSuspendCapture: suspend " << (suspend ? "yes" : "no"); | 370 DVLOG(1) << "DoSuspendCapture: suspend " << (suspend ? "yes" : "no"); |
| 402 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); | 371 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
| 403 | 372 |
| 404 suspended_ = suspend; | 373 suspended_ = suspend; |
| 405 } | 374 } |
| 406 | 375 |
| 407 void VideoCaptureImpl::StopDevice() { | 376 void VideoCaptureImpl::StopDevice() { |
| 408 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); | 377 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
| 409 | 378 |
| 410 device_info_available_ = false; | 379 last_device_info_ = media::VideoCaptureParams(); |
| 411 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { | 380 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { |
| 412 state_ = VIDEO_CAPTURE_STATE_STOPPING; | 381 state_ = VIDEO_CAPTURE_STATE_STOPPING; |
| 413 Send(new VideoCaptureHostMsg_Stop(device_id_)); | 382 Send(new VideoCaptureHostMsg_Stop(device_id_)); |
| 414 capture_format_.width = capture_format_.height = 0; | 383 requested_params_.width = requested_params_.height = 0; |
| 415 } | 384 } |
| 416 } | 385 } |
| 417 | 386 |
| 418 void VideoCaptureImpl::RestartCapture() { | 387 void VideoCaptureImpl::RestartCapture() { |
| 419 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); | 388 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
| 420 DCHECK_EQ(state_, VIDEO_CAPTURE_STATE_STOPPED); | 389 DCHECK_EQ(state_, VIDEO_CAPTURE_STATE_STOPPED); |
| 421 | 390 |
| 422 int width = 0; | 391 int width = 0; |
| 423 int height = 0; | 392 int height = 0; |
| 424 for (ClientInfo::iterator it = clients_.begin(); | 393 for (ClientInfo::iterator it = clients_.begin(); |
| 425 it != clients_.end(); ++it) { | 394 it != clients_.end(); ++it) { |
| 426 width = std::max(width, it->second.width); | 395 width = std::max(width, it->second.width); |
| 427 height = std::max(height, it->second.height); | 396 height = std::max(height, it->second.height); |
| 428 } | 397 } |
| 429 for (ClientInfo::iterator it = clients_pending_on_restart_.begin(); | 398 for (ClientInfo::iterator it = clients_pending_on_restart_.begin(); |
| 430 it != clients_pending_on_restart_.end(); ) { | 399 it != clients_pending_on_restart_.end(); ) { |
| 431 width = std::max(width, it->second.width); | 400 width = std::max(width, it->second.width); |
| 432 height = std::max(height, it->second.height); | 401 height = std::max(height, it->second.height); |
| 433 clients_[it->first] = it->second; | 402 clients_[it->first] = it->second; |
| 434 clients_pending_on_restart_.erase(it++); | 403 clients_pending_on_restart_.erase(it++); |
| 435 } | 404 } |
| 436 capture_format_.width = width; | 405 requested_params_.width = width; |
| 437 capture_format_.height = height; | 406 requested_params_.height = height; |
| 438 DVLOG(1) << "RestartCapture, " << capture_format_.width << ", " | 407 DVLOG(1) << "RestartCapture, " << requested_params_.width << ", " |
| 439 << capture_format_.height; | 408 << requested_params_.height; |
| 440 StartCaptureInternal(); | 409 StartCaptureInternal(); |
| 441 } | 410 } |
| 442 | 411 |
| 443 void VideoCaptureImpl::StartCaptureInternal() { | 412 void VideoCaptureImpl::StartCaptureInternal() { |
| 444 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); | 413 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
| 445 DCHECK(device_id_); | 414 DCHECK(device_id_); |
| 446 | 415 |
| 447 media::VideoCaptureParams capability_as_params_copy; | 416 Send(new VideoCaptureHostMsg_Start(device_id_, requested_params_)); |
| 448 capability_as_params_copy.width = capture_format_.width; | |
| 449 capability_as_params_copy.height = capture_format_.height; | |
| 450 capability_as_params_copy.frame_rate = capture_format_.frame_rate; | |
| 451 capability_as_params_copy.session_id = capture_format_.session_id; | |
| 452 capability_as_params_copy.frame_size_type = capture_format_.frame_size_type; | |
| 453 Send(new VideoCaptureHostMsg_Start(device_id_, capability_as_params_copy)); | |
| 454 state_ = VIDEO_CAPTURE_STATE_STARTED; | 417 state_ = VIDEO_CAPTURE_STATE_STARTED; |
| 455 } | 418 } |
| 456 | 419 |
| 457 void VideoCaptureImpl::AddDelegateOnIOThread() { | 420 void VideoCaptureImpl::AddDelegateOnIOThread() { |
| 458 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); | 421 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); |
| 459 message_filter_->AddDelegate(this); | 422 message_filter_->AddDelegate(this); |
| 460 } | 423 } |
| 461 | 424 |
| 462 void VideoCaptureImpl::RemoveDelegateOnIOThread(base::Closure task) { | 425 void VideoCaptureImpl::RemoveDelegateOnIOThread(base::Closure task) { |
| 463 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); | 426 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 481 if (it != clients->end()) { | 444 if (it != clients->end()) { |
| 482 handler->OnStopped(this); | 445 handler->OnStopped(this); |
| 483 handler->OnRemoved(this); | 446 handler->OnRemoved(this); |
| 484 clients->erase(it); | 447 clients->erase(it); |
| 485 found = true; | 448 found = true; |
| 486 } | 449 } |
| 487 return found; | 450 return found; |
| 488 } | 451 } |
| 489 | 452 |
| 490 } // namespace content | 453 } // namespace content |
| OLD | NEW |