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. |
11 | 11 |
12 #include "content/renderer/media/video_capture_impl.h" | 12 #include "content/renderer/media/video_capture_impl.h" |
13 | 13 |
14 #include "base/bind.h" | 14 #include "base/bind.h" |
15 #include "base/stl_util.h" | 15 #include "base/stl_util.h" |
16 #include "base/thread_task_runner_handle.h" | 16 #include "base/thread_task_runner_handle.h" |
17 #include "content/child/child_process.h" | 17 #include "content/child/child_process.h" |
18 #include "content/common/gpu/client/gpu_memory_buffer_impl.h" | 18 #include "content/common/gpu/client/gpu_memory_buffer_impl.h" |
19 #include "content/common/media/video_capture_messages.h" | 19 #include "content/common/media/video_capture_messages.h" |
20 #include "media/base/bind_to_current_loop.h" | 20 #include "media/base/bind_to_current_loop.h" |
21 #include "media/base/limits.h" | 21 #include "media/base/limits.h" |
22 #include "media/base/video_frame.h" | 22 #include "media/base/video_frame.h" |
23 | 23 |
24 namespace content { | 24 namespace content { |
25 | 25 |
26 namespace { | 26 namespace { |
27 | 27 |
28 // This is called on an unknown thread when the VideoFrame destructor executes. | 28 // This is called on an unknown thread when the VideoFrame destructor executes. |
29 // As of this writing, this callback mechanism is the only interface in | 29 // As of this writing, this callback mechanism is the only interface in |
30 // VideoFrame to provide the final value for |release_sync_point|. | 30 // VideoFrame to provide the final value for |release_sync_token|. |
31 // VideoCaptureImpl::DidFinishConsumingFrame() will read the value saved here, | 31 // VideoCaptureImpl::DidFinishConsumingFrame() will read the value saved here, |
32 // and pass it back to the IO thread to pass back to the host via the | 32 // and pass it back to the IO thread to pass back to the host via the |
33 // BufferReady IPC. | 33 // BufferReady IPC. |
34 void SaveReleaseSyncPoint(uint32* storage, uint32 release_sync_point) { | 34 void SaveReleaseSyncToken(gpu::SyncToken* sync_token_storage, |
35 *storage = release_sync_point; | 35 const gpu::SyncToken& release_sync_token) { |
| 36 *sync_token_storage = release_sync_token; |
36 } | 37 } |
37 | 38 |
38 } // namespace | 39 } // namespace |
39 | 40 |
40 // A holder of a memory-backed buffer and accessors to it. | 41 // A holder of a memory-backed buffer and accessors to it. |
41 class VideoCaptureImpl::ClientBuffer | 42 class VideoCaptureImpl::ClientBuffer |
42 : public base::RefCountedThreadSafe<ClientBuffer> { | 43 : public base::RefCountedThreadSafe<ClientBuffer> { |
43 public: | 44 public: |
44 ClientBuffer(scoped_ptr<base::SharedMemory> buffer, size_t buffer_size) | 45 ClientBuffer(scoped_ptr<base::SharedMemory> buffer, size_t buffer_size) |
45 : buffer_(buffer.Pass()), buffer_size_(buffer_size) {} | 46 : buffer_(buffer.Pass()), buffer_size_(buffer_size) {} |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 int buffer_id, | 309 int buffer_id, |
309 base::TimeTicks timestamp, | 310 base::TimeTicks timestamp, |
310 const base::DictionaryValue& metadata, | 311 const base::DictionaryValue& metadata, |
311 media::VideoPixelFormat pixel_format, | 312 media::VideoPixelFormat pixel_format, |
312 media::VideoFrame::StorageType storage_type, | 313 media::VideoFrame::StorageType storage_type, |
313 const gfx::Size& coded_size, | 314 const gfx::Size& coded_size, |
314 const gfx::Rect& visible_rect, | 315 const gfx::Rect& visible_rect, |
315 const gpu::MailboxHolder& mailbox_holder) { | 316 const gpu::MailboxHolder& mailbox_holder) { |
316 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 317 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
317 if (state_ != VIDEO_CAPTURE_STATE_STARTED || suspended_) { | 318 if (state_ != VIDEO_CAPTURE_STATE_STARTED || suspended_) { |
318 Send(new VideoCaptureHostMsg_BufferReady(device_id_, buffer_id, 0, -1.0)); | 319 Send(new VideoCaptureHostMsg_BufferReady(device_id_, buffer_id, |
| 320 gpu::SyncToken(), -1.0)); |
319 return; | 321 return; |
320 } | 322 } |
321 if (first_frame_timestamp_.is_null()) | 323 if (first_frame_timestamp_.is_null()) |
322 first_frame_timestamp_ = timestamp; | 324 first_frame_timestamp_ = timestamp; |
323 | 325 |
324 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc | 326 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc |
325 TRACE_EVENT_INSTANT2("cast_perf_test", "OnBufferReceived", | 327 TRACE_EVENT_INSTANT2("cast_perf_test", "OnBufferReceived", |
326 TRACE_EVENT_SCOPE_THREAD, "timestamp", | 328 TRACE_EVENT_SCOPE_THREAD, "timestamp", |
327 timestamp.ToInternalValue(), "time_delta", | 329 timestamp.ToInternalValue(), "time_delta", |
328 (timestamp - first_frame_timestamp_).ToInternalValue()); | 330 (timestamp - first_frame_timestamp_).ToInternalValue()); |
329 | 331 |
330 scoped_refptr<media::VideoFrame> frame; | 332 scoped_refptr<media::VideoFrame> frame; |
331 base::Callback<void(uint32, double)> buffer_finished_callback; | 333 BufferFinishedCallback buffer_finished_callback; |
332 uint32* release_sync_point_storage = new uint32(0); | 334 gpu::SyncToken* release_sync_token_storage = new gpu::SyncToken; |
333 if (storage_type == media::VideoFrame::STORAGE_GPU_MEMORY_BUFFERS) { | 335 if (storage_type == media::VideoFrame::STORAGE_GPU_MEMORY_BUFFERS) { |
334 DCHECK_EQ(media::PIXEL_FORMAT_I420, pixel_format); | 336 DCHECK_EQ(media::PIXEL_FORMAT_I420, pixel_format); |
335 const auto& iter = client_buffer2s_.find(buffer_id); | 337 const auto& iter = client_buffer2s_.find(buffer_id); |
336 DCHECK(iter != client_buffer2s_.end()); | 338 DCHECK(iter != client_buffer2s_.end()); |
337 scoped_refptr<ClientBuffer2> buffer = iter->second; | 339 scoped_refptr<ClientBuffer2> buffer = iter->second; |
338 const auto& handles = buffer->gpu_memory_buffer_handles(); | 340 const auto& handles = buffer->gpu_memory_buffer_handles(); |
339 frame = media::VideoFrame::WrapExternalYuvGpuMemoryBuffers( | 341 frame = media::VideoFrame::WrapExternalYuvGpuMemoryBuffers( |
340 media::PIXEL_FORMAT_I420, | 342 media::PIXEL_FORMAT_I420, |
341 coded_size, | 343 coded_size, |
342 gfx::Rect(coded_size), | 344 gfx::Rect(coded_size), |
(...skipping 28 matching lines...) Expand all Loading... |
371 reinterpret_cast<uint8*>(buffer->buffer()->memory()), | 373 reinterpret_cast<uint8*>(buffer->buffer()->memory()), |
372 buffer->buffer_size(), | 374 buffer->buffer_size(), |
373 buffer->buffer()->handle(), | 375 buffer->buffer()->handle(), |
374 0 /* shared_memory_offset */, | 376 0 /* shared_memory_offset */, |
375 timestamp - first_frame_timestamp_); | 377 timestamp - first_frame_timestamp_); |
376 } else { | 378 } else { |
377 DCHECK_EQ(storage_type, media::VideoFrame::STORAGE_OPAQUE); | 379 DCHECK_EQ(storage_type, media::VideoFrame::STORAGE_OPAQUE); |
378 DCHECK(mailbox_holder.mailbox.Verify()); | 380 DCHECK(mailbox_holder.mailbox.Verify()); |
379 DCHECK_EQ(media::PIXEL_FORMAT_ARGB, pixel_format); | 381 DCHECK_EQ(media::PIXEL_FORMAT_ARGB, pixel_format); |
380 frame = media::VideoFrame::WrapNativeTexture( | 382 frame = media::VideoFrame::WrapNativeTexture( |
381 pixel_format, | 383 pixel_format, mailbox_holder, |
382 mailbox_holder, | 384 base::Bind(&SaveReleaseSyncToken, release_sync_token_storage), |
383 base::Bind(&SaveReleaseSyncPoint, release_sync_point_storage), | 385 coded_size, gfx::Rect(coded_size), coded_size, |
384 coded_size, | |
385 gfx::Rect(coded_size), | |
386 coded_size, | |
387 timestamp - first_frame_timestamp_); | 386 timestamp - first_frame_timestamp_); |
388 } | 387 } |
389 buffer_finished_callback = media::BindToCurrentLoop( | 388 buffer_finished_callback = media::BindToCurrentLoop( |
390 base::Bind(&VideoCaptureImpl::OnClientBufferFinished, | 389 base::Bind(&VideoCaptureImpl::OnClientBufferFinished, |
391 weak_factory_.GetWeakPtr(), buffer_id, buffer)); | 390 weak_factory_.GetWeakPtr(), buffer_id, buffer)); |
392 } | 391 } |
393 frame->metadata()->SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME, | 392 frame->metadata()->SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME, |
394 timestamp); | 393 timestamp); |
395 frame->AddDestructionObserver( | 394 frame->AddDestructionObserver( |
396 base::Bind(&VideoCaptureImpl::DidFinishConsumingFrame, frame->metadata(), | 395 base::Bind(&VideoCaptureImpl::DidFinishConsumingFrame, frame->metadata(), |
397 release_sync_point_storage, buffer_finished_callback)); | 396 release_sync_token_storage, buffer_finished_callback)); |
398 | 397 |
399 frame->metadata()->MergeInternalValuesFrom(metadata); | 398 frame->metadata()->MergeInternalValuesFrom(metadata); |
400 | 399 |
401 for (const auto& client : clients_) | 400 for (const auto& client : clients_) |
402 client.second.deliver_frame_cb.Run(frame, timestamp); | 401 client.second.deliver_frame_cb.Run(frame, timestamp); |
403 } | 402 } |
404 | 403 |
405 void VideoCaptureImpl::OnClientBufferFinished( | 404 void VideoCaptureImpl::OnClientBufferFinished( |
406 int buffer_id, | 405 int buffer_id, |
407 const scoped_refptr<ClientBuffer>& /* ignored_buffer */, | 406 const scoped_refptr<ClientBuffer>& /* ignored_buffer */, |
408 uint32 release_sync_point, | 407 const gpu::SyncToken& release_sync_token, |
409 double consumer_resource_utilization) { | 408 double consumer_resource_utilization) { |
410 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 409 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
411 Send(new VideoCaptureHostMsg_BufferReady(device_id_, buffer_id, | 410 Send(new VideoCaptureHostMsg_BufferReady(device_id_, buffer_id, |
412 release_sync_point, | 411 release_sync_token, |
413 consumer_resource_utilization)); | 412 consumer_resource_utilization)); |
414 } | 413 } |
415 void VideoCaptureImpl::OnClientBufferFinished2( | 414 void VideoCaptureImpl::OnClientBufferFinished2( |
416 int buffer_id, | 415 int buffer_id, |
417 const scoped_refptr<ClientBuffer2>& gpu_memory_buffer /* ignored_buffer */, | 416 const scoped_refptr<ClientBuffer2>& gpu_memory_buffer /* ignored_buffer */, |
418 uint32 release_sync_point, | 417 const gpu::SyncToken& release_sync_token, |
419 double consumer_resource_utilization) { | 418 double consumer_resource_utilization) { |
420 OnClientBufferFinished(buffer_id, scoped_refptr<ClientBuffer>(), | 419 OnClientBufferFinished(buffer_id, scoped_refptr<ClientBuffer>(), |
421 release_sync_point, consumer_resource_utilization); | 420 release_sync_token, consumer_resource_utilization); |
422 } | 421 } |
423 | 422 |
424 void VideoCaptureImpl::OnStateChanged(VideoCaptureState state) { | 423 void VideoCaptureImpl::OnStateChanged(VideoCaptureState state) { |
425 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 424 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
426 | 425 |
427 switch (state) { | 426 switch (state) { |
428 case VIDEO_CAPTURE_STATE_STARTED: | 427 case VIDEO_CAPTURE_STATE_STARTED: |
429 // Camera has started in the browser process. Since we have already | 428 // Camera has started in the browser process. Since we have already |
430 // told all clients that we have started there's nothing to do. | 429 // told all clients that we have started there's nothing to do. |
431 break; | 430 break; |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
547 it->second.state_update_cb.Run(VIDEO_CAPTURE_STATE_STOPPED); | 546 it->second.state_update_cb.Run(VIDEO_CAPTURE_STATE_STOPPED); |
548 clients->erase(it); | 547 clients->erase(it); |
549 found = true; | 548 found = true; |
550 } | 549 } |
551 return found; | 550 return found; |
552 } | 551 } |
553 | 552 |
554 // static | 553 // static |
555 void VideoCaptureImpl::DidFinishConsumingFrame( | 554 void VideoCaptureImpl::DidFinishConsumingFrame( |
556 const media::VideoFrameMetadata* metadata, | 555 const media::VideoFrameMetadata* metadata, |
557 uint32* release_sync_point_storage, | 556 gpu::SyncToken* release_sync_token_storage, |
558 const base::Callback<void(uint32, double)>& callback_to_io_thread) { | 557 const BufferFinishedCallback& callback_to_io_thread) { |
559 // Note: This function may be called on any thread by the VideoFrame | 558 // Note: This function may be called on any thread by the VideoFrame |
560 // destructor. |metadata| is still valid for read-access at this point. | 559 // destructor. |metadata| is still valid for read-access at this point. |
561 | 560 gpu::SyncToken release_sync_token; |
562 uint32 release_sync_point = 0u; | 561 if (release_sync_token_storage) { |
563 if (release_sync_point_storage) { | 562 release_sync_token = *release_sync_token_storage; |
564 release_sync_point = *release_sync_point_storage; | 563 delete release_sync_token_storage; |
565 delete release_sync_point_storage; | |
566 } | 564 } |
567 | 565 |
568 double consumer_resource_utilization = -1.0; | 566 double consumer_resource_utilization = -1.0; |
569 if (!metadata->GetDouble(media::VideoFrameMetadata::RESOURCE_UTILIZATION, | 567 if (!metadata->GetDouble(media::VideoFrameMetadata::RESOURCE_UTILIZATION, |
570 &consumer_resource_utilization)) { | 568 &consumer_resource_utilization)) { |
571 consumer_resource_utilization = -1.0; | 569 consumer_resource_utilization = -1.0; |
572 } | 570 } |
573 | 571 |
574 callback_to_io_thread.Run(release_sync_point, consumer_resource_utilization); | 572 callback_to_io_thread.Run(release_sync_token, consumer_resource_utilization); |
575 } | 573 } |
576 | 574 |
577 } // namespace content | 575 } // namespace content |
OLD | NEW |