| 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 #include "media/base/video_frame.h" |
| 13 | 14 |
| 14 namespace content { | 15 namespace content { |
| 15 | 16 |
| 16 class VideoCaptureImpl::ClientBuffer | 17 class VideoCaptureImpl::ClientBuffer |
| 17 : public base::RefCountedThreadSafe<ClientBuffer> { | 18 : public base::RefCountedThreadSafe<ClientBuffer> { |
| 18 public: | 19 public: |
| 19 ClientBuffer(scoped_ptr<base::SharedMemory> buffer, | 20 ClientBuffer(scoped_ptr<base::SharedMemory> buffer, |
| 20 size_t buffer_size) | 21 size_t buffer_size) |
| 21 : buffer(buffer.Pass()), | 22 : buffer(buffer.Pass()), |
| 22 buffer_size(buffer_size) {} | 23 buffer_size(buffer_size) {} |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 152 clients_.find(handler) != clients_.end() ) { | 153 clients_.find(handler) != clients_.end() ) { |
| 153 // This client has started. | 154 // This client has started. |
| 154 } else if (!device_id_) { | 155 } else if (!device_id_) { |
| 155 clients_pending_on_filter_[handler] = params; | 156 clients_pending_on_filter_[handler] = params; |
| 156 } else { | 157 } else { |
| 157 handler->OnStarted(this); | 158 handler->OnStarted(this); |
| 158 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { | 159 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { |
| 159 clients_[handler] = params; | 160 clients_[handler] = params; |
| 160 } else if (state_ == VIDEO_CAPTURE_STATE_STOPPING) { | 161 } else if (state_ == VIDEO_CAPTURE_STATE_STOPPING) { |
| 161 clients_pending_on_restart_[handler] = params; | 162 clients_pending_on_restart_[handler] = params; |
| 162 DVLOG(1) << "StartCapture: Got new resolution (" | 163 DVLOG(1) << "StartCapture: Got new resolution " |
| 163 << params.requested_format.width << ", " | 164 << params.requested_format.frame_size.ToString() |
| 164 << params.requested_format.height << ") " | 165 << " during stopping."; |
| 165 << ", during stopping."; | |
| 166 } else { | 166 } else { |
| 167 DCHECK_EQ(params.session_id, 0); | 167 // TODO(sheu): Allowing resolution change will require that all |
| 168 // outstanding clients of a capture session support resolution change. |
| 169 DCHECK(!params.allow_resolution_change); |
| 168 clients_[handler] = params; | 170 clients_[handler] = params; |
| 169 DCHECK_EQ(1ul, clients_.size()); | 171 DCHECK_EQ(1ul, clients_.size()); |
| 170 params_ = params; | 172 params_ = params; |
| 171 params_.session_id = session_id_; | |
| 172 if (params_.requested_format.frame_rate > | 173 if (params_.requested_format.frame_rate > |
| 173 media::limits::kMaxFramesPerSecond) { | 174 media::limits::kMaxFramesPerSecond) { |
| 174 params_.requested_format.frame_rate = | 175 params_.requested_format.frame_rate = |
| 175 media::limits::kMaxFramesPerSecond; | 176 media::limits::kMaxFramesPerSecond; |
| 176 } | 177 } |
| 177 DVLOG(1) << "StartCapture: starting with first resolution (" | 178 DVLOG(1) << "StartCapture: starting with first resolution " |
| 178 << params_.requested_format.width << "," | 179 << params_.requested_format.frame_size.ToString(); |
| 179 << params_.requested_format.height << ")"; | |
| 180 | 180 |
| 181 StartCaptureInternal(); | 181 StartCaptureInternal(); |
| 182 } | 182 } |
| 183 } | 183 } |
| 184 } | 184 } |
| 185 | 185 |
| 186 void VideoCaptureImpl::DoStopCaptureOnCaptureThread( | 186 void VideoCaptureImpl::DoStopCaptureOnCaptureThread( |
| 187 media::VideoCapture::EventHandler* handler) { | 187 media::VideoCapture::EventHandler* handler) { |
| 188 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); | 188 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
| 189 | 189 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 base::Time timestamp, | 245 base::Time timestamp, |
| 246 const media::VideoCaptureFormat& format) { | 246 const media::VideoCaptureFormat& format) { |
| 247 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); | 247 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
| 248 | 248 |
| 249 if (state_ != VIDEO_CAPTURE_STATE_STARTED || suspended_) { | 249 if (state_ != VIDEO_CAPTURE_STATE_STARTED || suspended_) { |
| 250 Send(new VideoCaptureHostMsg_BufferReady(device_id_, buffer_id)); | 250 Send(new VideoCaptureHostMsg_BufferReady(device_id_, buffer_id)); |
| 251 return; | 251 return; |
| 252 } | 252 } |
| 253 | 253 |
| 254 last_frame_format_ = format; | 254 last_frame_format_ = format; |
| 255 gfx::Size size(format.width, format.height); | |
| 256 | 255 |
| 257 ClientBufferMap::iterator iter = client_buffers_.find(buffer_id); | 256 ClientBufferMap::iterator iter = client_buffers_.find(buffer_id); |
| 258 DCHECK(iter != client_buffers_.end()); | 257 DCHECK(iter != client_buffers_.end()); |
| 259 scoped_refptr<ClientBuffer> buffer = iter->second; | 258 scoped_refptr<ClientBuffer> buffer = iter->second; |
| 260 scoped_refptr<media::VideoFrame> frame = | 259 scoped_refptr<media::VideoFrame> frame = |
| 261 media::VideoFrame::WrapExternalPackedMemory( | 260 media::VideoFrame::WrapExternalPackedMemory( |
| 262 media::VideoFrame::I420, | 261 media::VideoFrame::I420, |
| 263 size, | 262 last_frame_format_.frame_size, |
| 264 gfx::Rect(size), | 263 gfx::Rect(last_frame_format_.frame_size), |
| 265 size, | 264 last_frame_format_.frame_size, |
| 266 reinterpret_cast<uint8*>(buffer->buffer->memory()), | 265 reinterpret_cast<uint8*>(buffer->buffer->memory()), |
| 267 buffer->buffer_size, | 266 buffer->buffer_size, |
| 268 buffer->buffer->handle(), | 267 buffer->buffer->handle(), |
| 269 // TODO(sheu): convert VideoCaptureMessageFilter::Delegate to use | 268 // TODO(sheu): convert VideoCaptureMessageFilter::Delegate to use |
| 270 // base::TimeTicks instead of base::Time. http://crbug.com/249215 | 269 // base::TimeTicks instead of base::Time. http://crbug.com/249215 |
| 271 timestamp - base::Time::UnixEpoch(), | 270 timestamp - base::Time::UnixEpoch(), |
| 272 media::BindToLoop( | 271 media::BindToLoop( |
| 273 capture_message_loop_proxy_, | 272 capture_message_loop_proxy_, |
| 274 base::Bind( | 273 base::Bind( |
| 275 &VideoCaptureImpl::DoClientBufferFinishedOnCaptureThread, | 274 &VideoCaptureImpl::DoClientBufferFinishedOnCaptureThread, |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 353 | 352 |
| 354 suspended_ = suspend; | 353 suspended_ = suspend; |
| 355 } | 354 } |
| 356 | 355 |
| 357 void VideoCaptureImpl::StopDevice() { | 356 void VideoCaptureImpl::StopDevice() { |
| 358 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); | 357 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
| 359 | 358 |
| 360 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { | 359 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { |
| 361 state_ = VIDEO_CAPTURE_STATE_STOPPING; | 360 state_ = VIDEO_CAPTURE_STATE_STOPPING; |
| 362 Send(new VideoCaptureHostMsg_Stop(device_id_)); | 361 Send(new VideoCaptureHostMsg_Stop(device_id_)); |
| 363 params_.requested_format.width = params_.requested_format.height = 0; | 362 params_.requested_format.frame_size.SetSize(0, 0); |
| 364 } | 363 } |
| 365 } | 364 } |
| 366 | 365 |
| 367 void VideoCaptureImpl::RestartCapture() { | 366 void VideoCaptureImpl::RestartCapture() { |
| 368 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); | 367 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
| 369 DCHECK_EQ(state_, VIDEO_CAPTURE_STATE_STOPPED); | 368 DCHECK_EQ(state_, VIDEO_CAPTURE_STATE_STOPPED); |
| 370 | 369 |
| 371 int width = 0; | 370 int width = 0; |
| 372 int height = 0; | 371 int height = 0; |
| 373 for (ClientInfo::iterator it = clients_.begin(); | 372 for (ClientInfo::iterator it = clients_.begin(); |
| 374 it != clients_.end(); ++it) { | 373 it != clients_.end(); ++it) { |
| 375 width = std::max(width, it->second.requested_format.width); | 374 width = std::max(width, it->second.requested_format.frame_size.width()); |
| 376 height = std::max(height, it->second.requested_format.height); | 375 height = std::max(height, it->second.requested_format.frame_size.height()); |
| 377 } | 376 } |
| 378 for (ClientInfo::iterator it = clients_pending_on_restart_.begin(); | 377 for (ClientInfo::iterator it = clients_pending_on_restart_.begin(); |
| 379 it != clients_pending_on_restart_.end(); ) { | 378 it != clients_pending_on_restart_.end(); ) { |
| 380 width = std::max(width, it->second.requested_format.width); | 379 width = std::max(width, it->second.requested_format.frame_size.width()); |
| 381 height = std::max(height, it->second.requested_format.height); | 380 height = std::max(height, it->second.requested_format.frame_size.height()); |
| 382 clients_[it->first] = it->second; | 381 clients_[it->first] = it->second; |
| 383 clients_pending_on_restart_.erase(it++); | 382 clients_pending_on_restart_.erase(it++); |
| 384 } | 383 } |
| 385 params_.requested_format.width = width; | 384 params_.requested_format.frame_size.SetSize(width, height); |
| 386 params_.requested_format.height = height; | 385 DVLOG(1) << "RestartCapture, " |
| 387 DVLOG(1) << "RestartCapture, " << params_.requested_format.width << ", " | 386 << params_.requested_format.frame_size.ToString(); |
| 388 << params_.requested_format.height; | |
| 389 StartCaptureInternal(); | 387 StartCaptureInternal(); |
| 390 } | 388 } |
| 391 | 389 |
| 392 void VideoCaptureImpl::StartCaptureInternal() { | 390 void VideoCaptureImpl::StartCaptureInternal() { |
| 393 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); | 391 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); |
| 394 DCHECK(device_id_); | 392 DCHECK(device_id_); |
| 395 | 393 |
| 396 Send(new VideoCaptureHostMsg_Start(device_id_, params_)); | 394 Send(new VideoCaptureHostMsg_Start(device_id_, session_id_, params_)); |
| 397 state_ = VIDEO_CAPTURE_STATE_STARTED; | 395 state_ = VIDEO_CAPTURE_STATE_STARTED; |
| 398 } | 396 } |
| 399 | 397 |
| 400 void VideoCaptureImpl::AddDelegateOnIOThread() { | 398 void VideoCaptureImpl::AddDelegateOnIOThread() { |
| 401 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); | 399 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); |
| 402 message_filter_->AddDelegate(this); | 400 message_filter_->AddDelegate(this); |
| 403 } | 401 } |
| 404 | 402 |
| 405 void VideoCaptureImpl::RemoveDelegateOnIOThread(base::Closure task) { | 403 void VideoCaptureImpl::RemoveDelegateOnIOThread(base::Closure task) { |
| 406 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); | 404 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 424 if (it != clients->end()) { | 422 if (it != clients->end()) { |
| 425 handler->OnStopped(this); | 423 handler->OnStopped(this); |
| 426 handler->OnRemoved(this); | 424 handler->OnRemoved(this); |
| 427 clients->erase(it); | 425 clients->erase(it); |
| 428 found = true; | 426 found = true; |
| 429 } | 427 } |
| 430 return found; | 428 return found; |
| 431 } | 429 } |
| 432 | 430 |
| 433 } // namespace content | 431 } // namespace content |
| OLD | NEW |