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

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

Issue 2407623002: VideoCapture: migrate last Renderer-->Host msg and start Host-->Renderer migration (Closed)
Patch Set: chfremer@ comments Created 4 years, 2 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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 VideoCaptureImpl::ClientInfo::~ClientInfo() {} 52 VideoCaptureImpl::ClientInfo::~ClientInfo() {}
53 53
54 VideoCaptureImpl::VideoCaptureImpl( 54 VideoCaptureImpl::VideoCaptureImpl(
55 media::VideoCaptureSessionId session_id, 55 media::VideoCaptureSessionId session_id,
56 VideoCaptureMessageFilter* filter, 56 VideoCaptureMessageFilter* filter,
57 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) 57 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
58 : message_filter_(filter), 58 : message_filter_(filter),
59 device_id_(0), 59 device_id_(0),
60 session_id_(session_id), 60 session_id_(session_id),
61 video_capture_host_for_testing_(nullptr), 61 video_capture_host_for_testing_(nullptr),
62 observer_binding_(this),
62 state_(VIDEO_CAPTURE_STATE_STOPPED), 63 state_(VIDEO_CAPTURE_STATE_STOPPED),
63 io_task_runner_(std::move(io_task_runner)), 64 io_task_runner_(std::move(io_task_runner)),
64 weak_factory_(this) { 65 weak_factory_(this) {
65 DCHECK(filter); 66 DCHECK(filter);
66 io_task_runner_->PostTask(FROM_HERE, 67 io_task_runner_->PostTask(FROM_HERE,
67 base::Bind(&VideoCaptureMessageFilter::AddDelegate, 68 base::Bind(&VideoCaptureMessageFilter::AddDelegate,
68 message_filter_, this)); 69 message_filter_, this));
69 } 70 }
70 71
71 VideoCaptureImpl::~VideoCaptureImpl() { 72 VideoCaptureImpl::~VideoCaptureImpl() {
(...skipping 20 matching lines...) Expand all
92 ClientInfo client_info; 93 ClientInfo client_info;
93 client_info.params = params; 94 client_info.params = params;
94 client_info.state_update_cb = state_update_cb; 95 client_info.state_update_cb = state_update_cb;
95 client_info.deliver_frame_cb = deliver_frame_cb; 96 client_info.deliver_frame_cb = deliver_frame_cb;
96 97
97 if (state_ == VIDEO_CAPTURE_STATE_ERROR) { 98 if (state_ == VIDEO_CAPTURE_STATE_ERROR) {
98 state_update_cb.Run(VIDEO_CAPTURE_STATE_ERROR); 99 state_update_cb.Run(VIDEO_CAPTURE_STATE_ERROR);
99 } else if (clients_pending_on_filter_.count(client_id) || 100 } else if (clients_pending_on_filter_.count(client_id) ||
100 clients_pending_on_restart_.count(client_id) || 101 clients_pending_on_restart_.count(client_id) ||
101 clients_.count(client_id)) { 102 clients_.count(client_id)) {
102 LOG(FATAL) << "This client has already started."; 103 DLOG(FATAL) << __func__ << " This client has already started.";
103 } else if (!device_id_) { 104 } else if (!device_id_) {
104 clients_pending_on_filter_[client_id] = client_info; 105 clients_pending_on_filter_[client_id] = client_info;
105 } else { 106 } else {
106 // Note: |state_| might not be started at this point. But we tell 107 // Note: |state_| might not be started at this point. But we tell
107 // client that we have started. 108 // client that we have started.
108 state_update_cb.Run(VIDEO_CAPTURE_STATE_STARTED); 109 state_update_cb.Run(VIDEO_CAPTURE_STATE_STARTED);
109 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { 110 if (state_ == VIDEO_CAPTURE_STATE_STARTED) {
110 clients_[client_id] = client_info; 111 clients_[client_id] = client_info;
111 // TODO(sheu): Allowing resolution change will require that all 112 // TODO(sheu): Allowing resolution change will require that all
112 // outstanding clients of a capture session support resolution change. 113 // outstanding clients of a capture session support resolution change.
113 DCHECK_EQ(params_.resolution_change_policy, 114 DCHECK_EQ(params_.resolution_change_policy,
114 params.resolution_change_policy); 115 params.resolution_change_policy);
115 } else if (state_ == VIDEO_CAPTURE_STATE_STOPPING) { 116 } else if (state_ == VIDEO_CAPTURE_STATE_STOPPING) {
116 clients_pending_on_restart_[client_id] = client_info; 117 clients_pending_on_restart_[client_id] = client_info;
117 DVLOG(1) << "StartCapture: Got new resolution " 118 DVLOG(1) << __func__ << " Got new resolution while stopping: "
118 << params.requested_format.frame_size.ToString() 119 << params.requested_format.frame_size.ToString();
119 << " during stopping.";
120 } else { 120 } else {
121 clients_[client_id] = client_info; 121 clients_[client_id] = client_info;
122 if (state_ == VIDEO_CAPTURE_STATE_STARTED) 122 if (state_ == VIDEO_CAPTURE_STATE_STARTED)
123 return; 123 return;
124 params_ = params; 124 params_ = params;
125 if (params_.requested_format.frame_rate > 125 params_.requested_format.frame_rate =
126 media::limits::kMaxFramesPerSecond) { 126 std::min(params_.requested_format.frame_rate,
127 params_.requested_format.frame_rate = 127 static_cast<float>(media::limits::kMaxFramesPerSecond));
128 media::limits::kMaxFramesPerSecond; 128
129 }
130 DVLOG(1) << "StartCapture: starting with first resolution " 129 DVLOG(1) << "StartCapture: starting with first resolution "
131 << params_.requested_format.frame_size.ToString(); 130 << params_.requested_format.frame_size.ToString();
132 StartCaptureInternal(); 131 StartCaptureInternal();
133 } 132 }
134 } 133 }
135 } 134 }
136 135
137 void VideoCaptureImpl::StopCapture(int client_id) { 136 void VideoCaptureImpl::StopCapture(int client_id) {
138 DCHECK(io_task_runner_->BelongsToCurrentThread()); 137 DCHECK(io_task_runner_->BelongsToCurrentThread());
139 // A client ID can be in only one client list. 138 // A client ID can be in only one client list.
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 214
216 void VideoCaptureImpl::OnBufferReceived( 215 void VideoCaptureImpl::OnBufferReceived(
217 int buffer_id, 216 int buffer_id,
218 base::TimeDelta timestamp, 217 base::TimeDelta timestamp,
219 const base::DictionaryValue& metadata, 218 const base::DictionaryValue& metadata,
220 media::VideoPixelFormat pixel_format, 219 media::VideoPixelFormat pixel_format,
221 media::VideoFrame::StorageType storage_type, 220 media::VideoFrame::StorageType storage_type,
222 const gfx::Size& coded_size, 221 const gfx::Size& coded_size,
223 const gfx::Rect& visible_rect) { 222 const gfx::Rect& visible_rect) {
224 DCHECK(io_task_runner_->BelongsToCurrentThread()); 223 DCHECK(io_task_runner_->BelongsToCurrentThread());
225 // Crash in debug builds since the host should not have provided a buffer
226 // with an unsupported pixel format or storage type.
227 DCHECK_EQ(media::PIXEL_FORMAT_I420, pixel_format); 224 DCHECK_EQ(media::PIXEL_FORMAT_I420, pixel_format);
228 DCHECK(storage_type == media::VideoFrame::STORAGE_SHMEM); 225 DCHECK_EQ(media::VideoFrame::STORAGE_SHMEM, storage_type);
226
229 if (state_ != VIDEO_CAPTURE_STATE_STARTED || 227 if (state_ != VIDEO_CAPTURE_STATE_STARTED ||
230 pixel_format != media::PIXEL_FORMAT_I420 || 228 pixel_format != media::PIXEL_FORMAT_I420 ||
231 storage_type != media::VideoFrame::STORAGE_SHMEM) { 229 storage_type != media::VideoFrame::STORAGE_SHMEM) {
232 Send(new VideoCaptureHostMsg_BufferReady(device_id_, buffer_id, 230 GetVideoCaptureHost()->ReleaseBuffer(device_id_, buffer_id,
233 gpu::SyncToken(), -1.0)); 231 gpu::SyncToken(), -1.0);
234 return; 232 return;
235 } 233 }
236 234
237 base::TimeTicks reference_time; 235 base::TimeTicks reference_time;
238 media::VideoFrameMetadata frame_metadata; 236 media::VideoFrameMetadata frame_metadata;
239 frame_metadata.MergeInternalValuesFrom(metadata); 237 frame_metadata.MergeInternalValuesFrom(metadata);
240 const bool success = frame_metadata.GetTimeTicks( 238 const bool success = frame_metadata.GetTimeTicks(
241 media::VideoFrameMetadata::REFERENCE_TIME, &reference_time); 239 media::VideoFrameMetadata::REFERENCE_TIME, &reference_time);
242 DCHECK(success); 240 DCHECK(success);
243 241
(...skipping 19 matching lines...) Expand all
263 DCHECK(iter != client_buffers_.end()); 261 DCHECK(iter != client_buffers_.end());
264 const scoped_refptr<ClientBuffer> buffer = iter->second; 262 const scoped_refptr<ClientBuffer> buffer = iter->second;
265 scoped_refptr<media::VideoFrame> frame = 263 scoped_refptr<media::VideoFrame> frame =
266 media::VideoFrame::WrapExternalSharedMemory( 264 media::VideoFrame::WrapExternalSharedMemory(
267 pixel_format, coded_size, visible_rect, 265 pixel_format, coded_size, visible_rect,
268 gfx::Size(visible_rect.width(), visible_rect.height()), 266 gfx::Size(visible_rect.width(), visible_rect.height()),
269 reinterpret_cast<uint8_t*>(buffer->buffer()->memory()), 267 reinterpret_cast<uint8_t*>(buffer->buffer()->memory()),
270 buffer->buffer_size(), buffer->buffer()->handle(), 268 buffer->buffer_size(), buffer->buffer()->handle(),
271 0 /* shared_memory_offset */, timestamp); 269 0 /* shared_memory_offset */, timestamp);
272 if (!frame) { 270 if (!frame) {
273 Send(new VideoCaptureHostMsg_BufferReady(device_id_, buffer_id, 271 GetVideoCaptureHost()->ReleaseBuffer(device_id_, buffer_id,
274 gpu::SyncToken(), -1.0)); 272 gpu::SyncToken(), -1.0);
275 return; 273 return;
276 } 274 }
277 275
278 BufferFinishedCallback buffer_finished_callback = media::BindToCurrentLoop( 276 BufferFinishedCallback buffer_finished_callback = media::BindToCurrentLoop(
279 base::Bind(&VideoCaptureImpl::OnClientBufferFinished, 277 base::Bind(&VideoCaptureImpl::OnClientBufferFinished,
280 weak_factory_.GetWeakPtr(), buffer_id, buffer)); 278 weak_factory_.GetWeakPtr(), buffer_id, buffer));
281 std::unique_ptr<gpu::SyncToken> release_sync_token(new gpu::SyncToken); 279 std::unique_ptr<gpu::SyncToken> release_sync_token(new gpu::SyncToken);
282 frame->AddDestructionObserver( 280 frame->AddDestructionObserver(
283 base::Bind(&VideoCaptureImpl::DidFinishConsumingFrame, frame->metadata(), 281 base::Bind(&VideoCaptureImpl::DidFinishConsumingFrame, frame->metadata(),
284 base::Passed(&release_sync_token), buffer_finished_callback)); 282 base::Passed(&release_sync_token), buffer_finished_callback));
285 283
286 frame->metadata()->MergeInternalValuesFrom(metadata); 284 frame->metadata()->MergeInternalValuesFrom(metadata);
287 285
288 // TODO(qiangchen): Dive into the full code path to let frame metadata hold 286 // TODO(qiangchen): Dive into the full code path to let frame metadata hold
289 // reference time rather than using an extra parameter. 287 // reference time rather than using an extra parameter.
290 for (const auto& client : clients_) 288 for (const auto& client : clients_)
291 client.second.deliver_frame_cb.Run(frame, reference_time); 289 client.second.deliver_frame_cb.Run(frame, reference_time);
292 } 290 }
293 291
294 void VideoCaptureImpl::OnClientBufferFinished(
295 int buffer_id,
296 const scoped_refptr<ClientBuffer>& /* ignored_buffer */,
297 const gpu::SyncToken& release_sync_token,
298 double consumer_resource_utilization) {
299 DCHECK(io_task_runner_->BelongsToCurrentThread());
300 Send(new VideoCaptureHostMsg_BufferReady(device_id_, buffer_id,
301 release_sync_token,
302 consumer_resource_utilization));
303 }
304
305 void VideoCaptureImpl::OnStateChanged(VideoCaptureState state) {
306 DCHECK(io_task_runner_->BelongsToCurrentThread());
307
308 switch (state) {
309 case VIDEO_CAPTURE_STATE_STARTED:
310 // Camera has started in the browser process. Since we have already
311 // told all clients that we have started there's nothing to do.
312 break;
313 case VIDEO_CAPTURE_STATE_STOPPED:
314 state_ = VIDEO_CAPTURE_STATE_STOPPED;
315 DVLOG(1) << "OnStateChanged: stopped!, device_id = " << device_id_;
316 client_buffers_.clear();
317 weak_factory_.InvalidateWeakPtrs();
318 if (!clients_.empty() || !clients_pending_on_restart_.empty())
319 RestartCapture();
320 break;
321 case VIDEO_CAPTURE_STATE_PAUSED:
322 case VIDEO_CAPTURE_STATE_RESUMED:
323 for (const auto& client : clients_)
324 client.second.state_update_cb.Run(state);
325 break;
326 case VIDEO_CAPTURE_STATE_ERROR:
327 DVLOG(1) << "OnStateChanged: error!, device_id = " << device_id_;
328 for (const auto& client : clients_)
329 client.second.state_update_cb.Run(VIDEO_CAPTURE_STATE_ERROR);
330 clients_.clear();
331 state_ = VIDEO_CAPTURE_STATE_ERROR;
332 break;
333 case VIDEO_CAPTURE_STATE_ENDED:
334 DVLOG(1) << "OnStateChanged: ended!, device_id = " << device_id_;
335 for (const auto& client : clients_) {
336 // We'll only notify the client that the stream has stopped.
337 client.second.state_update_cb.Run(VIDEO_CAPTURE_STATE_STOPPED);
338 }
339 clients_.clear();
340 state_ = VIDEO_CAPTURE_STATE_ENDED;
341 break;
342 default:
343 break;
344 }
345 }
346
347 void VideoCaptureImpl::OnDelegateAdded(int32_t device_id) { 292 void VideoCaptureImpl::OnDelegateAdded(int32_t device_id) {
348 DVLOG(1) << __func__ << " " << device_id; 293 DVLOG(1) << __func__ << " " << device_id;
349 DCHECK(io_task_runner_->BelongsToCurrentThread()); 294 DCHECK(io_task_runner_->BelongsToCurrentThread());
350 295
351 device_id_ = device_id; 296 device_id_ = device_id;
352 ClientInfoMap::iterator it = clients_pending_on_filter_.begin(); 297 ClientInfoMap::iterator it = clients_pending_on_filter_.begin();
353 while (it != clients_pending_on_filter_.end()) { 298 while (it != clients_pending_on_filter_.end()) {
354 const int client_id = it->first; 299 const int client_id = it->first;
355 const ClientInfo client_info = it->second; 300 const ClientInfo client_info = it->second;
356 clients_pending_on_filter_.erase(it++); 301 clients_pending_on_filter_.erase(it++);
357 StartCapture(client_id, client_info.params, client_info.state_update_cb, 302 StartCapture(client_id, client_info.params, client_info.state_update_cb,
358 client_info.deliver_frame_cb); 303 client_info.deliver_frame_cb);
359 } 304 }
360 } 305 }
361 306
307 void VideoCaptureImpl::OnStateChanged(mojom::VideoCaptureState state) {
308 DVLOG(1) << __func__ << " state: " << state;
309 DCHECK(io_task_runner_->BelongsToCurrentThread());
310
311 switch (state) {
312 case mojom::VideoCaptureState::STARTED:
313 // Capture has started in the browser process. Since we have already
314 // told all clients that we have started there's nothing to do.
315 break;
316 case mojom::VideoCaptureState::STOPPED:
317 state_ = VIDEO_CAPTURE_STATE_STOPPED;
318 client_buffers_.clear();
319 weak_factory_.InvalidateWeakPtrs();
320 if (!clients_.empty() || !clients_pending_on_restart_.empty())
321 RestartCapture();
322 break;
323 case mojom::VideoCaptureState::PAUSED:
324 for (const auto& client : clients_)
325 client.second.state_update_cb.Run(VIDEO_CAPTURE_STATE_PAUSED);
326 break;
327 case mojom::VideoCaptureState::RESUMED:
328 for (const auto& client : clients_)
329 client.second.state_update_cb.Run(VIDEO_CAPTURE_STATE_RESUMED);
330 break;
331 case mojom::VideoCaptureState::FAILED:
332 for (const auto& client : clients_)
333 client.second.state_update_cb.Run(VIDEO_CAPTURE_STATE_ERROR);
334 clients_.clear();
335 state_ = VIDEO_CAPTURE_STATE_ERROR;
336 break;
337 case mojom::VideoCaptureState::ENDED:
338 // We'll only notify the client that the stream has stopped.
339 for (const auto& client : clients_)
340 client.second.state_update_cb.Run(VIDEO_CAPTURE_STATE_STOPPED);
341 clients_.clear();
342 state_ = VIDEO_CAPTURE_STATE_ENDED;
343 break;
344 }
345 }
346
347 void VideoCaptureImpl::OnClientBufferFinished(
348 int buffer_id,
349 const scoped_refptr<ClientBuffer>& /* ignored_buffer */,
350 const gpu::SyncToken& release_sync_token,
351 double consumer_resource_utilization) {
352 DCHECK(io_task_runner_->BelongsToCurrentThread());
353 GetVideoCaptureHost()->ReleaseBuffer(
354 device_id_, buffer_id, release_sync_token, consumer_resource_utilization);
355 }
356
362 void VideoCaptureImpl::StopDevice() { 357 void VideoCaptureImpl::StopDevice() {
363 DCHECK(io_task_runner_->BelongsToCurrentThread()); 358 DCHECK(io_task_runner_->BelongsToCurrentThread());
364 if (state_ != VIDEO_CAPTURE_STATE_STARTED) 359 if (state_ != VIDEO_CAPTURE_STATE_STARTED)
365 return; 360 return;
366 state_ = VIDEO_CAPTURE_STATE_STOPPING; 361 state_ = VIDEO_CAPTURE_STATE_STOPPING;
367 GetVideoCaptureHost()->Stop(device_id_); 362 GetVideoCaptureHost()->Stop(device_id_);
368 params_.requested_format.frame_size.SetSize(0, 0); 363 params_.requested_format.frame_size.SetSize(0, 0);
369 } 364 }
370 365
371 void VideoCaptureImpl::RestartCapture() { 366 void VideoCaptureImpl::RestartCapture() {
372 DCHECK(io_task_runner_->BelongsToCurrentThread()); 367 DCHECK(io_task_runner_->BelongsToCurrentThread());
373 DCHECK_EQ(state_, VIDEO_CAPTURE_STATE_STOPPED); 368 DCHECK_EQ(state_, VIDEO_CAPTURE_STATE_STOPPED);
374 369
375 int width = 0; 370 int width = 0;
376 int height = 0; 371 int height = 0;
377 clients_.insert(clients_pending_on_restart_.begin(), 372 clients_.insert(clients_pending_on_restart_.begin(),
378 clients_pending_on_restart_.end()); 373 clients_pending_on_restart_.end());
379 clients_pending_on_restart_.clear(); 374 clients_pending_on_restart_.clear();
380 for (const auto& client : clients_) { 375 for (const auto& client : clients_) {
381 width = std::max(width, 376 width = std::max(width,
382 client.second.params.requested_format.frame_size.width()); 377 client.second.params.requested_format.frame_size.width());
383 height = std::max( 378 height = std::max(
384 height, client.second.params.requested_format.frame_size.height()); 379 height, client.second.params.requested_format.frame_size.height());
385 } 380 }
386 params_.requested_format.frame_size.SetSize(width, height); 381 params_.requested_format.frame_size.SetSize(width, height);
387 DVLOG(1) << "RestartCapture, " 382 DVLOG(1) << __func__ << " " << params_.requested_format.frame_size.ToString();
388 << params_.requested_format.frame_size.ToString();
389 StartCaptureInternal(); 383 StartCaptureInternal();
390 } 384 }
391 385
392 void VideoCaptureImpl::StartCaptureInternal() { 386 void VideoCaptureImpl::StartCaptureInternal() {
393 DCHECK(io_task_runner_->BelongsToCurrentThread()); 387 DCHECK(io_task_runner_->BelongsToCurrentThread());
394 DCHECK(device_id_); 388 DCHECK(device_id_);
395 389
396 GetVideoCaptureHost()->Start(device_id_, session_id_, params_); 390 GetVideoCaptureHost()->Start(device_id_, session_id_, params_,
391 observer_binding_.CreateInterfacePtrAndBind());
397 state_ = VIDEO_CAPTURE_STATE_STARTED; 392 state_ = VIDEO_CAPTURE_STATE_STARTED;
398 } 393 }
399 394
400 void VideoCaptureImpl::OnDeviceSupportedFormats( 395 void VideoCaptureImpl::OnDeviceSupportedFormats(
401 const VideoCaptureDeviceFormatsCB& callback, 396 const VideoCaptureDeviceFormatsCB& callback,
402 const media::VideoCaptureFormats& supported_formats) { 397 const media::VideoCaptureFormats& supported_formats) {
403 DCHECK(io_task_runner_->BelongsToCurrentThread()); 398 DCHECK(io_task_runner_->BelongsToCurrentThread());
404 callback.Run(supported_formats); 399 callback.Run(supported_formats);
405 } 400 }
406 401
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 double consumer_resource_utilization = -1.0; 449 double consumer_resource_utilization = -1.0;
455 if (!metadata->GetDouble(media::VideoFrameMetadata::RESOURCE_UTILIZATION, 450 if (!metadata->GetDouble(media::VideoFrameMetadata::RESOURCE_UTILIZATION,
456 &consumer_resource_utilization)) { 451 &consumer_resource_utilization)) {
457 consumer_resource_utilization = -1.0; 452 consumer_resource_utilization = -1.0;
458 } 453 }
459 454
460 callback_to_io_thread.Run(*release_sync_token, consumer_resource_utilization); 455 callback_to_io_thread.Run(*release_sync_token, consumer_resource_utilization);
461 } 456 }
462 457
463 } // namespace content 458 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/media/video_capture_impl.h ('k') | content/renderer/media/video_capture_impl_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698