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 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 63 | 63 |
| 64 VideoCaptureDeliverFrameCB deliver_frame_cb; | 64 VideoCaptureDeliverFrameCB deliver_frame_cb; |
| 65 }; | 65 }; |
| 66 | 66 |
| 67 VideoCaptureImpl::VideoCaptureImpl(media::VideoCaptureSessionId session_id) | 67 VideoCaptureImpl::VideoCaptureImpl(media::VideoCaptureSessionId session_id) |
| 68 : device_id_(session_id), | 68 : device_id_(session_id), |
| 69 session_id_(session_id), | 69 session_id_(session_id), |
| 70 video_capture_host_for_testing_(nullptr), | 70 video_capture_host_for_testing_(nullptr), |
| 71 observer_binding_(this), | 71 observer_binding_(this), |
| 72 state_(VIDEO_CAPTURE_STATE_STOPPED), | 72 state_(VIDEO_CAPTURE_STATE_STOPPED), |
| 73 should_request_refresh_frame_on_started_(false), | |
| 73 weak_factory_(this) { | 74 weak_factory_(this) { |
| 74 io_thread_checker_.DetachFromThread(); | 75 io_thread_checker_.DetachFromThread(); |
| 75 | 76 |
| 76 if (ChildThread::Get()) { // This will be null in unit tests. | 77 if (ChildThread::Get()) { // This will be null in unit tests. |
| 77 mojom::VideoCaptureHostPtr temp_video_capture_host; | 78 mojom::VideoCaptureHostPtr temp_video_capture_host; |
| 78 ChildThread::Get()->GetRemoteInterfaces()->GetInterface( | 79 ChildThread::Get()->GetRemoteInterfaces()->GetInterface( |
| 79 mojo::MakeRequest(&temp_video_capture_host)); | 80 mojo::MakeRequest(&temp_video_capture_host)); |
| 80 video_capture_host_info_ = temp_video_capture_host.PassInterface(); | 81 video_capture_host_info_ = temp_video_capture_host.PassInterface(); |
| 81 } | 82 } |
| 82 } | 83 } |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 100 const media::VideoCaptureParams& params, | 101 const media::VideoCaptureParams& params, |
| 101 const VideoCaptureStateUpdateCB& state_update_cb, | 102 const VideoCaptureStateUpdateCB& state_update_cb, |
| 102 const VideoCaptureDeliverFrameCB& deliver_frame_cb) { | 103 const VideoCaptureDeliverFrameCB& deliver_frame_cb) { |
| 103 DVLOG(1) << __func__ << " |device_id_| = " << device_id_; | 104 DVLOG(1) << __func__ << " |device_id_| = " << device_id_; |
| 104 DCHECK(io_thread_checker_.CalledOnValidThread()); | 105 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 105 ClientInfo client_info; | 106 ClientInfo client_info; |
| 106 client_info.params = params; | 107 client_info.params = params; |
| 107 client_info.state_update_cb = state_update_cb; | 108 client_info.state_update_cb = state_update_cb; |
| 108 client_info.deliver_frame_cb = deliver_frame_cb; | 109 client_info.deliver_frame_cb = deliver_frame_cb; |
| 109 | 110 |
| 110 if (state_ == VIDEO_CAPTURE_STATE_ERROR) { | 111 if (state_ == VIDEO_CAPTURE_STATE_ERROR) { |
|
miu
2017/03/06 22:37:33
Can we re-organize this complex logic into a flatt
braveyao
2017/03/08 22:02:52
Done.
By my understanding, the check,
"if (client
miu
2017/03/10 23:56:56
Yes, that's my understanding too. :)
braveyao
2017/03/13 19:04:44
Acknowledged.
| |
| 111 state_update_cb.Run(VIDEO_CAPTURE_STATE_ERROR); | 112 state_update_cb.Run(VIDEO_CAPTURE_STATE_ERROR); |
| 112 } else if (clients_pending_on_restart_.count(client_id) || | 113 } else if (clients_pending_on_restart_.count(client_id) || |
| 113 clients_.count(client_id)) { | 114 clients_.count(client_id)) { |
| 114 DLOG(FATAL) << __func__ << " This client has already started."; | 115 DLOG(FATAL) << __func__ << " This client has already started."; |
| 115 } else { | 116 } 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); | |
|
miu
2017/03/06 22:37:33
Per my earlier comment, how about keeping this, bu
braveyao
2017/03/08 22:02:52
This does no good and will cause troubles to the u
| |
| 119 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { | 117 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { |
| 120 clients_[client_id] = client_info; | 118 clients_[client_id] = client_info; |
| 121 // TODO(sheu): Allowing resolution change will require that all | 119 // TODO(sheu): Allowing resolution change will require that all |
| 122 // outstanding clients of a capture session support resolution change. | 120 // outstanding clients of a capture session support resolution change. |
| 123 DCHECK_EQ(params_.resolution_change_policy, | 121 DCHECK_EQ(params_.resolution_change_policy, |
| 124 params.resolution_change_policy); | 122 params.resolution_change_policy); |
| 125 } else if (state_ == VIDEO_CAPTURE_STATE_STOPPING) { | 123 } else if (state_ == VIDEO_CAPTURE_STATE_STOPPING) { |
| 126 clients_pending_on_restart_[client_id] = client_info; | 124 clients_pending_on_restart_[client_id] = client_info; |
| 127 DVLOG(1) << __func__ << " Got new resolution while stopping: " | 125 DVLOG(1) << __func__ << " Got new resolution while stopping: " |
| 128 << params.requested_format.frame_size.ToString(); | 126 << params.requested_format.frame_size.ToString(); |
| 129 } else { | 127 } else { |
| 130 clients_[client_id] = client_info; | 128 clients_[client_id] = client_info; |
| 131 if (state_ == VIDEO_CAPTURE_STATE_STARTED) | 129 if (state_ == VIDEO_CAPTURE_STATE_STARTED) |
|
miu
2017/03/06 22:37:33
Note: Here's one reason I suggest the switch-state
braveyao
2017/03/08 22:02:52
Done.
Also found the STARTING state is necessary f
| |
| 132 return; | 130 return; |
| 133 params_ = params; | 131 params_ = params; |
| 134 params_.requested_format.frame_rate = | 132 params_.requested_format.frame_rate = |
| 135 std::min(params_.requested_format.frame_rate, | 133 std::min(params_.requested_format.frame_rate, |
| 136 static_cast<float>(media::limits::kMaxFramesPerSecond)); | 134 static_cast<float>(media::limits::kMaxFramesPerSecond)); |
| 137 | 135 |
| 138 DVLOG(1) << "StartCapture: starting with first resolution " | 136 DVLOG(1) << "StartCapture: starting with first resolution " |
| 139 << params_.requested_format.frame_size.ToString(); | 137 << params_.requested_format.frame_size.ToString(); |
| 140 StartCaptureInternal(); | 138 StartCaptureInternal(); |
| 141 } | 139 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 181 base::Bind(&VideoCaptureImpl::OnDeviceFormatsInUse, | 179 base::Bind(&VideoCaptureImpl::OnDeviceFormatsInUse, |
| 182 weak_factory_.GetWeakPtr(), callback)); | 180 weak_factory_.GetWeakPtr(), callback)); |
| 183 } | 181 } |
| 184 | 182 |
| 185 void VideoCaptureImpl::OnStateChanged(mojom::VideoCaptureState state) { | 183 void VideoCaptureImpl::OnStateChanged(mojom::VideoCaptureState state) { |
| 186 DVLOG(1) << __func__ << " state: " << state; | 184 DVLOG(1) << __func__ << " state: " << state; |
| 187 DCHECK(io_thread_checker_.CalledOnValidThread()); | 185 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 188 | 186 |
| 189 switch (state) { | 187 switch (state) { |
| 190 case mojom::VideoCaptureState::STARTED: | 188 case mojom::VideoCaptureState::STARTED: |
| 191 // Capture has started in the browser process. Since we have already | 189 state_ = VIDEO_CAPTURE_STATE_STARTED; |
| 192 // told all clients that we have started there's nothing to do. | 190 for (const auto& client : clients_) |
| 191 client.second.state_update_cb.Run(VIDEO_CAPTURE_STATE_STARTED); | |
| 192 if (should_request_refresh_frame_on_started_) { | |
|
miu
2017/03/06 22:37:33
Suggestion: Instead of this logic, what if VideoCa
braveyao
2017/03/08 22:02:52
Done.
Good to know!
But it will cause many GMock W
miu
2017/03/10 23:56:56
Yes, this should be fine. It's up to you, but it w
braveyao
2017/03/13 19:04:44
Acknowledged.
| |
| 193 RequestRefreshFrame(); | |
| 194 should_request_refresh_frame_on_started_ = false; | |
| 195 } | |
| 193 break; | 196 break; |
| 194 case mojom::VideoCaptureState::STOPPED: | 197 case mojom::VideoCaptureState::STOPPED: |
| 195 state_ = VIDEO_CAPTURE_STATE_STOPPED; | 198 state_ = VIDEO_CAPTURE_STATE_STOPPED; |
| 196 client_buffers_.clear(); | 199 client_buffers_.clear(); |
| 197 weak_factory_.InvalidateWeakPtrs(); | 200 weak_factory_.InvalidateWeakPtrs(); |
| 198 if (!clients_.empty() || !clients_pending_on_restart_.empty()) | 201 if (!clients_.empty() || !clients_pending_on_restart_.empty()) |
| 199 RestartCapture(); | 202 RestartCapture(); |
| 200 break; | 203 break; |
| 201 case mojom::VideoCaptureState::PAUSED: | 204 case mojom::VideoCaptureState::PAUSED: |
| 202 for (const auto& client : clients_) | 205 for (const auto& client : clients_) |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 221 break; | 224 break; |
| 222 } | 225 } |
| 223 } | 226 } |
| 224 | 227 |
| 225 void VideoCaptureImpl::OnBufferCreated(int32_t buffer_id, | 228 void VideoCaptureImpl::OnBufferCreated(int32_t buffer_id, |
| 226 mojo::ScopedSharedBufferHandle handle) { | 229 mojo::ScopedSharedBufferHandle handle) { |
| 227 DVLOG(1) << __func__ << " buffer_id: " << buffer_id; | 230 DVLOG(1) << __func__ << " buffer_id: " << buffer_id; |
| 228 DCHECK(io_thread_checker_.CalledOnValidThread()); | 231 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 229 DCHECK(handle.is_valid()); | 232 DCHECK(handle.is_valid()); |
| 230 | 233 |
| 231 if (state_ != VIDEO_CAPTURE_STATE_STARTED) | |
| 232 return; | |
| 233 | |
| 234 base::SharedMemoryHandle memory_handle; | 234 base::SharedMemoryHandle memory_handle; |
| 235 size_t memory_size = 0; | 235 size_t memory_size = 0; |
| 236 bool read_only_flag = false; | 236 bool read_only_flag = false; |
| 237 | 237 |
| 238 const MojoResult result = mojo::UnwrapSharedMemoryHandle( | 238 const MojoResult result = mojo::UnwrapSharedMemoryHandle( |
| 239 std::move(handle), &memory_handle, &memory_size, &read_only_flag); | 239 std::move(handle), &memory_handle, &memory_size, &read_only_flag); |
| 240 DCHECK_EQ(MOJO_RESULT_OK, result); | 240 DCHECK_EQ(MOJO_RESULT_OK, result); |
| 241 DCHECK_GT(memory_size, 0u); | 241 DCHECK_GT(memory_size, 0u); |
| 242 | 242 |
| 243 std::unique_ptr<base::SharedMemory> shm( | 243 std::unique_ptr<base::SharedMemory> shm( |
| 244 new base::SharedMemory(memory_handle, true /* read_only */)); | 244 new base::SharedMemory(memory_handle, true /* read_only */)); |
| 245 if (!shm->Map(memory_size)) { | 245 if (!shm->Map(memory_size)) { |
| 246 DLOG(ERROR) << "OnBufferCreated: Map failed."; | 246 DLOG(ERROR) << "OnBufferCreated: Map failed."; |
| 247 return; | 247 return; |
| 248 } | 248 } |
| 249 const bool inserted = | 249 const bool inserted = |
| 250 client_buffers_ | 250 client_buffers_ |
| 251 .insert(std::make_pair(buffer_id, | 251 .insert(std::make_pair(buffer_id, |
| 252 new ClientBuffer(std::move(shm), memory_size))) | 252 new ClientBuffer(std::move(shm), memory_size))) |
| 253 .second; | 253 .second; |
| 254 DCHECK(inserted); | 254 DCHECK(inserted); |
| 255 } | 255 } |
| 256 | 256 |
| 257 void VideoCaptureImpl::OnBufferReady(int32_t buffer_id, | 257 void VideoCaptureImpl::OnBufferReady(int32_t buffer_id, |
| 258 media::mojom::VideoFrameInfoPtr info) { | 258 media::mojom::VideoFrameInfoPtr info) { |
| 259 DVLOG(1) << __func__ << " buffer_id: " << buffer_id; | 259 DVLOG(1) << __func__ << " buffer_id: " << buffer_id; |
| 260 DCHECK(io_thread_checker_.CalledOnValidThread()); | 260 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 261 | 261 |
| 262 bool consume_buffer = state_ == VIDEO_CAPTURE_STATE_STARTED; | 262 bool consume_buffer = state_ == VIDEO_CAPTURE_STATE_STARTED; |
| 263 if (!consume_buffer && first_frame_ref_time_.is_null()) | |
| 264 should_request_refresh_frame_on_started_ = true; | |
| 263 if ((info->pixel_format != media::PIXEL_FORMAT_I420 && | 265 if ((info->pixel_format != media::PIXEL_FORMAT_I420 && |
| 264 info->pixel_format != media::PIXEL_FORMAT_Y16) || | 266 info->pixel_format != media::PIXEL_FORMAT_Y16) || |
| 265 info->storage_type != media::PIXEL_STORAGE_CPU) { | 267 info->storage_type != media::PIXEL_STORAGE_CPU) { |
| 266 consume_buffer = false; | 268 consume_buffer = false; |
| 267 LOG(DFATAL) << "Wrong pixel format or storage, got pixel format:" | 269 LOG(DFATAL) << "Wrong pixel format or storage, got pixel format:" |
| 268 << VideoPixelFormatToString(info->pixel_format) | 270 << VideoPixelFormatToString(info->pixel_format) |
| 269 << ", storage:" << info->storage_type; | 271 << ", storage:" << info->storage_type; |
| 270 } | 272 } |
| 271 if (!consume_buffer) { | 273 if (!consume_buffer) { |
| 272 GetVideoCaptureHost()->ReleaseBuffer(device_id_, buffer_id, -1.0); | 274 GetVideoCaptureHost()->ReleaseBuffer(device_id_, buffer_id, -1.0); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 375 params_.requested_format.frame_size.SetSize(width, height); | 377 params_.requested_format.frame_size.SetSize(width, height); |
| 376 DVLOG(1) << __func__ << " " << params_.requested_format.frame_size.ToString(); | 378 DVLOG(1) << __func__ << " " << params_.requested_format.frame_size.ToString(); |
| 377 StartCaptureInternal(); | 379 StartCaptureInternal(); |
| 378 } | 380 } |
| 379 | 381 |
| 380 void VideoCaptureImpl::StartCaptureInternal() { | 382 void VideoCaptureImpl::StartCaptureInternal() { |
| 381 DCHECK(io_thread_checker_.CalledOnValidThread()); | 383 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 382 | 384 |
| 383 GetVideoCaptureHost()->Start(device_id_, session_id_, params_, | 385 GetVideoCaptureHost()->Start(device_id_, session_id_, params_, |
| 384 observer_binding_.CreateInterfacePtrAndBind()); | 386 observer_binding_.CreateInterfacePtrAndBind()); |
| 385 state_ = VIDEO_CAPTURE_STATE_STARTED; | |
|
miu
2017/03/06 22:37:33
Retain this, but it should be changed to:
state
braveyao
2017/03/08 22:02:52
Done.
| |
| 386 } | 387 } |
| 387 | 388 |
| 388 void VideoCaptureImpl::OnDeviceSupportedFormats( | 389 void VideoCaptureImpl::OnDeviceSupportedFormats( |
| 389 const VideoCaptureDeviceFormatsCB& callback, | 390 const VideoCaptureDeviceFormatsCB& callback, |
| 390 const media::VideoCaptureFormats& supported_formats) { | 391 const media::VideoCaptureFormats& supported_formats) { |
| 391 DCHECK(io_thread_checker_.CalledOnValidThread()); | 392 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 392 callback.Run(supported_formats); | 393 callback.Run(supported_formats); |
| 393 } | 394 } |
| 394 | 395 |
| 395 void VideoCaptureImpl::OnDeviceFormatsInUse( | 396 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. | 430 // destructor. |metadata| is still valid for read-access at this point. |
| 430 double consumer_resource_utilization = -1.0; | 431 double consumer_resource_utilization = -1.0; |
| 431 if (!metadata->GetDouble(media::VideoFrameMetadata::RESOURCE_UTILIZATION, | 432 if (!metadata->GetDouble(media::VideoFrameMetadata::RESOURCE_UTILIZATION, |
| 432 &consumer_resource_utilization)) { | 433 &consumer_resource_utilization)) { |
| 433 consumer_resource_utilization = -1.0; | 434 consumer_resource_utilization = -1.0; |
| 434 } | 435 } |
| 435 callback_to_io_thread.Run(consumer_resource_utilization); | 436 callback_to_io_thread.Run(consumer_resource_utilization); |
| 436 } | 437 } |
| 437 | 438 |
| 438 } // namespace content | 439 } // namespace content |
| OLD | NEW |