Chromium Code Reviews| 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 // Notes about usage of this object by VideoCaptureImplManager. | 5 // Notes about usage of this object by VideoCaptureImplManager. |
| 6 // | 6 // |
| 7 // VideoCaptureImplManager access this object by using a Unretained() | 7 // VideoCaptureImplManager access this object by using a Unretained() |
| 8 // binding and tasks on the IO thread. It is then important that | 8 // binding and tasks on the IO thread. It is then important that |
| 9 // VideoCaptureImpl never post task to itself. All operations must be | 9 // VideoCaptureImpl never post task to itself. All operations must be |
| 10 // synchronous. | 10 // synchronous. |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 76 if (ChildThread::Get()) { // This will be null in unit tests. | 76 if (ChildThread::Get()) { // This will be null in unit tests. |
| 77 mojom::VideoCaptureHostPtr temp_video_capture_host; | 77 mojom::VideoCaptureHostPtr temp_video_capture_host; |
| 78 ChildThread::Get()->GetRemoteInterfaces()->GetInterface( | 78 ChildThread::Get()->GetRemoteInterfaces()->GetInterface( |
| 79 mojo::MakeRequest(&temp_video_capture_host)); | 79 mojo::MakeRequest(&temp_video_capture_host)); |
| 80 video_capture_host_info_ = temp_video_capture_host.PassInterface(); | 80 video_capture_host_info_ = temp_video_capture_host.PassInterface(); |
| 81 } | 81 } |
| 82 } | 82 } |
| 83 | 83 |
| 84 VideoCaptureImpl::~VideoCaptureImpl() { | 84 VideoCaptureImpl::~VideoCaptureImpl() { |
| 85 DCHECK(io_thread_checker_.CalledOnValidThread()); | 85 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 86 if (state_ == VIDEO_CAPTURE_STATE_STARTED && GetVideoCaptureHost()) | 86 if ((state_ == VIDEO_CAPTURE_STATE_STARTING || |
| 87 state_ == VIDEO_CAPTURE_STATE_STARTED) && | |
| 88 GetVideoCaptureHost()) | |
| 87 GetVideoCaptureHost()->Stop(device_id_); | 89 GetVideoCaptureHost()->Stop(device_id_); |
| 88 } | 90 } |
| 89 | 91 |
| 90 void VideoCaptureImpl::SuspendCapture(bool suspend) { | 92 void VideoCaptureImpl::SuspendCapture(bool suspend) { |
| 91 DCHECK(io_thread_checker_.CalledOnValidThread()); | 93 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 92 if (suspend) | 94 if (suspend) |
| 93 GetVideoCaptureHost()->Pause(device_id_); | 95 GetVideoCaptureHost()->Pause(device_id_); |
| 94 else | 96 else |
| 95 GetVideoCaptureHost()->Resume(device_id_, session_id_, params_); | 97 GetVideoCaptureHost()->Resume(device_id_, session_id_, params_); |
| 96 } | 98 } |
| 97 | 99 |
| 98 void VideoCaptureImpl::StartCapture( | 100 void VideoCaptureImpl::StartCapture( |
| 99 int client_id, | 101 int client_id, |
| 100 const media::VideoCaptureParams& params, | 102 const media::VideoCaptureParams& params, |
| 101 const VideoCaptureStateUpdateCB& state_update_cb, | 103 const VideoCaptureStateUpdateCB& state_update_cb, |
| 102 const VideoCaptureDeliverFrameCB& deliver_frame_cb) { | 104 const VideoCaptureDeliverFrameCB& deliver_frame_cb) { |
| 103 DVLOG(1) << __func__ << " |device_id_| = " << device_id_; | 105 DVLOG(1) << __func__ << " |device_id_| = " << device_id_; |
| 104 DCHECK(io_thread_checker_.CalledOnValidThread()); | 106 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 105 ClientInfo client_info; | 107 ClientInfo client_info; |
| 106 client_info.params = params; | 108 client_info.params = params; |
| 107 client_info.state_update_cb = state_update_cb; | 109 client_info.state_update_cb = state_update_cb; |
| 108 client_info.deliver_frame_cb = deliver_frame_cb; | 110 client_info.deliver_frame_cb = deliver_frame_cb; |
| 109 | 111 |
| 110 if (state_ == VIDEO_CAPTURE_STATE_ERROR) { | 112 switch (state_) { |
| 111 state_update_cb.Run(VIDEO_CAPTURE_STATE_ERROR); | 113 case VIDEO_CAPTURE_STATE_STARTING: |
| 112 } else if (clients_pending_on_restart_.count(client_id) || | 114 case VIDEO_CAPTURE_STATE_STARTED: |
| 113 clients_.count(client_id)) { | |
| 114 DLOG(FATAL) << __func__ << " This client has already started."; | |
| 115 } else { | |
| 116 // Note: |state_| might not be started at this point. But we tell | |
| 117 // client that we have started. | |
| 118 state_update_cb.Run(VIDEO_CAPTURE_STATE_STARTED); | |
| 119 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { | |
| 120 clients_[client_id] = client_info; | 115 clients_[client_id] = client_info; |
| 121 // TODO(sheu): Allowing resolution change will require that all | 116 // TODO(sheu): Allowing resolution change will require that all |
| 122 // outstanding clients of a capture session support resolution change. | 117 // outstanding clients of a capture session support resolution change. |
| 123 DCHECK_EQ(params_.resolution_change_policy, | 118 DCHECK_EQ(params_.resolution_change_policy, |
| 124 params.resolution_change_policy); | 119 params.resolution_change_policy); |
| 125 } else if (state_ == VIDEO_CAPTURE_STATE_STOPPING) { | 120 return; |
| 121 case VIDEO_CAPTURE_STATE_STOPPING: | |
| 126 clients_pending_on_restart_[client_id] = client_info; | 122 clients_pending_on_restart_[client_id] = client_info; |
| 127 DVLOG(1) << __func__ << " Got new resolution while stopping: " | 123 DVLOG(1) << __func__ << " Got new resolution while stopping: " |
| 128 << params.requested_format.frame_size.ToString(); | 124 << params.requested_format.frame_size.ToString(); |
| 129 } else { | 125 return; |
| 126 case VIDEO_CAPTURE_STATE_STOPPED: | |
| 127 case VIDEO_CAPTURE_STATE_ENDED: | |
| 130 clients_[client_id] = client_info; | 128 clients_[client_id] = client_info; |
| 131 if (state_ == VIDEO_CAPTURE_STATE_STARTED) | |
| 132 return; | |
| 133 params_ = params; | 129 params_ = params; |
| 134 params_.requested_format.frame_rate = | 130 params_.requested_format.frame_rate = |
| 135 std::min(params_.requested_format.frame_rate, | 131 std::min(params_.requested_format.frame_rate, |
| 136 static_cast<float>(media::limits::kMaxFramesPerSecond)); | 132 static_cast<float>(media::limits::kMaxFramesPerSecond)); |
| 137 | 133 |
| 138 DVLOG(1) << "StartCapture: starting with first resolution " | 134 DVLOG(1) << "StartCapture: starting with first resolution " |
| 139 << params_.requested_format.frame_size.ToString(); | 135 << params_.requested_format.frame_size.ToString(); |
| 140 StartCaptureInternal(); | 136 StartCaptureInternal(); |
| 141 } | 137 return; |
| 138 case VIDEO_CAPTURE_STATE_ERROR: | |
| 139 state_update_cb.Run(VIDEO_CAPTURE_STATE_ERROR); | |
| 140 return; | |
| 141 case VIDEO_CAPTURE_STATE_PAUSED: | |
| 142 case VIDEO_CAPTURE_STATE_RESUMED: | |
| 143 // Do nothing becase these states aren't taken here. | |
|
miu
2017/03/10 23:56:56
nit: Please add NOT_REACHED() here for safety. The
braveyao
2017/03/13 19:04:44
Done.
| |
| 144 return; | |
| 142 } | 145 } |
| 143 } | 146 } |
| 144 | 147 |
| 145 void VideoCaptureImpl::StopCapture(int client_id) { | 148 void VideoCaptureImpl::StopCapture(int client_id) { |
| 146 DCHECK(io_thread_checker_.CalledOnValidThread()); | 149 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 147 // A client ID can be in only one client list. | 150 // A client ID can be in only one client list. |
| 148 // If this ID is in any client list, we can just remove it from | 151 // If this ID is in any client list, we can just remove it from |
| 149 // that client list and don't have to run the other following RemoveClient(). | 152 // that client list and don't have to run the other following RemoveClient(). |
| 150 if (!RemoveClient(client_id, &clients_pending_on_restart_)) { | 153 if (!RemoveClient(client_id, &clients_pending_on_restart_)) { |
| 151 RemoveClient(client_id, &clients_); | 154 RemoveClient(client_id, &clients_); |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 181 base::Bind(&VideoCaptureImpl::OnDeviceFormatsInUse, | 184 base::Bind(&VideoCaptureImpl::OnDeviceFormatsInUse, |
| 182 weak_factory_.GetWeakPtr(), callback)); | 185 weak_factory_.GetWeakPtr(), callback)); |
| 183 } | 186 } |
| 184 | 187 |
| 185 void VideoCaptureImpl::OnStateChanged(mojom::VideoCaptureState state) { | 188 void VideoCaptureImpl::OnStateChanged(mojom::VideoCaptureState state) { |
| 186 DVLOG(1) << __func__ << " state: " << state; | 189 DVLOG(1) << __func__ << " state: " << state; |
| 187 DCHECK(io_thread_checker_.CalledOnValidThread()); | 190 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 188 | 191 |
| 189 switch (state) { | 192 switch (state) { |
| 190 case mojom::VideoCaptureState::STARTED: | 193 case mojom::VideoCaptureState::STARTED: |
| 191 // Capture has started in the browser process. Since we have already | 194 state_ = VIDEO_CAPTURE_STATE_STARTED; |
| 192 // told all clients that we have started there's nothing to do. | 195 for (const auto& client : clients_) |
| 196 client.second.state_update_cb.Run(VIDEO_CAPTURE_STATE_STARTED); | |
| 197 // In case there is any frame dropped before STARTED, always request for | |
| 198 // a frame refresh to start the video call with. | |
| 199 // Capture device will make a decision if it should refresh a frame. | |
| 200 RequestRefreshFrame(); | |
| 193 break; | 201 break; |
| 194 case mojom::VideoCaptureState::STOPPED: | 202 case mojom::VideoCaptureState::STOPPED: |
| 195 state_ = VIDEO_CAPTURE_STATE_STOPPED; | 203 state_ = VIDEO_CAPTURE_STATE_STOPPED; |
| 196 client_buffers_.clear(); | 204 client_buffers_.clear(); |
| 197 weak_factory_.InvalidateWeakPtrs(); | 205 weak_factory_.InvalidateWeakPtrs(); |
| 198 if (!clients_.empty() || !clients_pending_on_restart_.empty()) | 206 if (!clients_.empty() || !clients_pending_on_restart_.empty()) |
| 199 RestartCapture(); | 207 RestartCapture(); |
| 200 break; | 208 break; |
| 201 case mojom::VideoCaptureState::PAUSED: | 209 case mojom::VideoCaptureState::PAUSED: |
| 202 for (const auto& client : clients_) | 210 for (const auto& client : clients_) |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 221 break; | 229 break; |
| 222 } | 230 } |
| 223 } | 231 } |
| 224 | 232 |
| 225 void VideoCaptureImpl::OnBufferCreated(int32_t buffer_id, | 233 void VideoCaptureImpl::OnBufferCreated(int32_t buffer_id, |
| 226 mojo::ScopedSharedBufferHandle handle) { | 234 mojo::ScopedSharedBufferHandle handle) { |
| 227 DVLOG(1) << __func__ << " buffer_id: " << buffer_id; | 235 DVLOG(1) << __func__ << " buffer_id: " << buffer_id; |
| 228 DCHECK(io_thread_checker_.CalledOnValidThread()); | 236 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 229 DCHECK(handle.is_valid()); | 237 DCHECK(handle.is_valid()); |
| 230 | 238 |
| 231 if (state_ != VIDEO_CAPTURE_STATE_STARTED) | |
| 232 return; | |
| 233 | |
| 234 base::SharedMemoryHandle memory_handle; | 239 base::SharedMemoryHandle memory_handle; |
| 235 size_t memory_size = 0; | 240 size_t memory_size = 0; |
| 236 bool read_only_flag = false; | 241 bool read_only_flag = false; |
| 237 | 242 |
| 238 const MojoResult result = mojo::UnwrapSharedMemoryHandle( | 243 const MojoResult result = mojo::UnwrapSharedMemoryHandle( |
| 239 std::move(handle), &memory_handle, &memory_size, &read_only_flag); | 244 std::move(handle), &memory_handle, &memory_size, &read_only_flag); |
| 240 DCHECK_EQ(MOJO_RESULT_OK, result); | 245 DCHECK_EQ(MOJO_RESULT_OK, result); |
| 241 DCHECK_GT(memory_size, 0u); | 246 DCHECK_GT(memory_size, 0u); |
| 242 | 247 |
| 243 std::unique_ptr<base::SharedMemory> shm( | 248 std::unique_ptr<base::SharedMemory> shm( |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 343 int buffer_id, | 348 int buffer_id, |
| 344 const scoped_refptr<ClientBuffer>& /* ignored_buffer */, | 349 const scoped_refptr<ClientBuffer>& /* ignored_buffer */, |
| 345 double consumer_resource_utilization) { | 350 double consumer_resource_utilization) { |
| 346 DCHECK(io_thread_checker_.CalledOnValidThread()); | 351 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 347 GetVideoCaptureHost()->ReleaseBuffer( | 352 GetVideoCaptureHost()->ReleaseBuffer( |
| 348 device_id_, buffer_id, consumer_resource_utilization); | 353 device_id_, buffer_id, consumer_resource_utilization); |
| 349 } | 354 } |
| 350 | 355 |
| 351 void VideoCaptureImpl::StopDevice() { | 356 void VideoCaptureImpl::StopDevice() { |
| 352 DCHECK(io_thread_checker_.CalledOnValidThread()); | 357 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 353 if (state_ != VIDEO_CAPTURE_STATE_STARTED) | 358 if (state_ != VIDEO_CAPTURE_STATE_STARTING && |
| 359 state_ != VIDEO_CAPTURE_STATE_STARTED) | |
| 354 return; | 360 return; |
| 355 state_ = VIDEO_CAPTURE_STATE_STOPPING; | 361 state_ = VIDEO_CAPTURE_STATE_STOPPING; |
| 356 GetVideoCaptureHost()->Stop(device_id_); | 362 GetVideoCaptureHost()->Stop(device_id_); |
| 357 params_.requested_format.frame_size.SetSize(0, 0); | 363 params_.requested_format.frame_size.SetSize(0, 0); |
| 358 } | 364 } |
| 359 | 365 |
| 360 void VideoCaptureImpl::RestartCapture() { | 366 void VideoCaptureImpl::RestartCapture() { |
| 361 DCHECK(io_thread_checker_.CalledOnValidThread()); | 367 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 362 DCHECK_EQ(state_, VIDEO_CAPTURE_STATE_STOPPED); | 368 DCHECK_EQ(state_, VIDEO_CAPTURE_STATE_STOPPED); |
| 363 | 369 |
| 364 int width = 0; | 370 int width = 0; |
| 365 int height = 0; | 371 int height = 0; |
| 366 clients_.insert(clients_pending_on_restart_.begin(), | 372 clients_.insert(clients_pending_on_restart_.begin(), |
| 367 clients_pending_on_restart_.end()); | 373 clients_pending_on_restart_.end()); |
| 368 clients_pending_on_restart_.clear(); | 374 clients_pending_on_restart_.clear(); |
| 369 for (const auto& client : clients_) { | 375 for (const auto& client : clients_) { |
| 370 width = std::max(width, | 376 width = std::max(width, |
| 371 client.second.params.requested_format.frame_size.width()); | 377 client.second.params.requested_format.frame_size.width()); |
| 372 height = std::max( | 378 height = std::max( |
| 373 height, client.second.params.requested_format.frame_size.height()); | 379 height, client.second.params.requested_format.frame_size.height()); |
| 374 } | 380 } |
| 375 params_.requested_format.frame_size.SetSize(width, height); | 381 params_.requested_format.frame_size.SetSize(width, height); |
| 376 DVLOG(1) << __func__ << " " << params_.requested_format.frame_size.ToString(); | 382 DVLOG(1) << __func__ << " " << params_.requested_format.frame_size.ToString(); |
| 377 StartCaptureInternal(); | 383 StartCaptureInternal(); |
| 378 } | 384 } |
| 379 | 385 |
| 380 void VideoCaptureImpl::StartCaptureInternal() { | 386 void VideoCaptureImpl::StartCaptureInternal() { |
| 381 DCHECK(io_thread_checker_.CalledOnValidThread()); | 387 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 388 state_ = VIDEO_CAPTURE_STATE_STARTING; | |
| 382 | 389 |
| 383 GetVideoCaptureHost()->Start(device_id_, session_id_, params_, | 390 GetVideoCaptureHost()->Start(device_id_, session_id_, params_, |
| 384 observer_binding_.CreateInterfacePtrAndBind()); | 391 observer_binding_.CreateInterfacePtrAndBind()); |
| 385 state_ = VIDEO_CAPTURE_STATE_STARTED; | |
| 386 } | 392 } |
| 387 | 393 |
| 388 void VideoCaptureImpl::OnDeviceSupportedFormats( | 394 void VideoCaptureImpl::OnDeviceSupportedFormats( |
| 389 const VideoCaptureDeviceFormatsCB& callback, | 395 const VideoCaptureDeviceFormatsCB& callback, |
| 390 const media::VideoCaptureFormats& supported_formats) { | 396 const media::VideoCaptureFormats& supported_formats) { |
| 391 DCHECK(io_thread_checker_.CalledOnValidThread()); | 397 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 392 callback.Run(supported_formats); | 398 callback.Run(supported_formats); |
| 393 } | 399 } |
| 394 | 400 |
| 395 void VideoCaptureImpl::OnDeviceFormatsInUse( | 401 void VideoCaptureImpl::OnDeviceFormatsInUse( |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 429 // destructor. |metadata| is still valid for read-access at this point. | 435 // destructor. |metadata| is still valid for read-access at this point. |
| 430 double consumer_resource_utilization = -1.0; | 436 double consumer_resource_utilization = -1.0; |
| 431 if (!metadata->GetDouble(media::VideoFrameMetadata::RESOURCE_UTILIZATION, | 437 if (!metadata->GetDouble(media::VideoFrameMetadata::RESOURCE_UTILIZATION, |
| 432 &consumer_resource_utilization)) { | 438 &consumer_resource_utilization)) { |
| 433 consumer_resource_utilization = -1.0; | 439 consumer_resource_utilization = -1.0; |
| 434 } | 440 } |
| 435 callback_to_io_thread.Run(consumer_resource_utilization); | 441 callback_to_io_thread.Run(consumer_resource_utilization); |
| 436 } | 442 } |
| 437 | 443 |
| 438 } // namespace content | 444 } // namespace content |
| OLD | NEW |