Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(535)

Side by Side Diff: content/renderer/media/video_capture_impl.cc

Issue 2721113002: getUserMedia: handle the device starting status report. (Closed)
Patch Set: address comments on PS#3 Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698