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 #include "media/filters/gpu_video_decoder.h" | 5 #include "media/filters/gpu_video_decoder.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
11 #include "base/cpu.h" | 11 #include "base/cpu.h" |
12 #include "base/message_loop/message_loop.h" | 12 #include "base/message_loop/message_loop.h" |
13 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
14 #include "base/stl_util.h" | 14 #include "base/stl_util.h" |
| 15 #include "base/synchronization/waitable_event.h" |
15 #include "base/task_runner_util.h" | 16 #include "base/task_runner_util.h" |
16 #include "gpu/command_buffer/common/mailbox_holder.h" | 17 #include "gpu/command_buffer/common/mailbox_holder.h" |
17 #include "media/base/bind_to_current_loop.h" | 18 #include "media/base/bind_to_current_loop.h" |
18 #include "media/base/decoder_buffer.h" | 19 #include "media/base/decoder_buffer.h" |
19 #include "media/base/media_log.h" | 20 #include "media/base/media_log.h" |
20 #include "media/base/pipeline.h" | 21 #include "media/base/pipeline.h" |
21 #include "media/base/pipeline_status.h" | 22 #include "media/base/pipeline_status.h" |
22 #include "media/base/video_decoder_config.h" | 23 #include "media/base/video_decoder_config.h" |
23 #include "media/filters/gpu_video_accelerator_factories.h" | 24 #include "media/filters/gpu_video_accelerator_factories.h" |
| 25 #include "third_party/skia/include/core/SkBitmap.h" |
24 | 26 |
25 namespace media { | 27 namespace media { |
26 | 28 |
27 // Maximum number of concurrent VDA::Decode() operations GVD will maintain. | 29 // Maximum number of concurrent VDA::Decode() operations GVD will maintain. |
28 // Higher values allow better pipelining in the GPU, but also require more | 30 // Higher values allow better pipelining in the GPU, but also require more |
29 // resources. | 31 // resources. |
30 enum { kMaxInFlightDecodes = 4 }; | 32 enum { kMaxInFlightDecodes = 4 }; |
31 | 33 |
32 // Size of shared-memory segments we allocate. Since we reuse them we let them | 34 // Size of shared-memory segments we allocate. Since we reuse them we let them |
33 // be on the beefy side. | 35 // be on the beefy side. |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 next_picture_buffer_id_(0), | 68 next_picture_buffer_id_(0), |
67 next_bitstream_buffer_id_(0), | 69 next_bitstream_buffer_id_(0), |
68 available_pictures_(0) { | 70 available_pictures_(0) { |
69 DCHECK(factories_.get()); | 71 DCHECK(factories_.get()); |
70 } | 72 } |
71 | 73 |
72 void GpuVideoDecoder::Reset(const base::Closure& closure) { | 74 void GpuVideoDecoder::Reset(const base::Closure& closure) { |
73 DVLOG(3) << "Reset()"; | 75 DVLOG(3) << "Reset()"; |
74 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 76 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
75 | 77 |
76 if (state_ == kDrainingDecoder && !factories_->IsAborted()) { | 78 if (state_ == kDrainingDecoder) { |
77 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 79 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind( |
78 &GpuVideoDecoder::Reset, weak_this_, closure)); | 80 &GpuVideoDecoder::Reset, weak_this_, closure)); |
79 // NOTE: if we're deferring Reset() until a Flush() completes, return | 81 // NOTE: if we're deferring Reset() until a Flush() completes, return |
80 // queued pictures to the VDA so they can be used to finish that Flush(). | 82 // queued pictures to the VDA so they can be used to finish that Flush(). |
81 if (pending_decode_cb_.is_null()) | 83 if (pending_decode_cb_.is_null()) |
82 ready_video_frames_.clear(); | 84 ready_video_frames_.clear(); |
83 return; | 85 return; |
84 } | 86 } |
85 | 87 |
86 // Throw away any already-decoded, not-yet-delivered frames. | 88 // Throw away any already-decoded, not-yet-delivered frames. |
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
414 CHECK_GT(available_pictures_, 0); | 416 CHECK_GT(available_pictures_, 0); |
415 --available_pictures_; | 417 --available_pictures_; |
416 } else { | 418 } else { |
417 // Texture in display. Postpone deletion until after it's returned to us. | 419 // Texture in display. Postpone deletion until after it's returned to us. |
418 bool inserted = dismissed_picture_buffers_.insert(std::make_pair( | 420 bool inserted = dismissed_picture_buffers_.insert(std::make_pair( |
419 id, buffer_to_dismiss)).second; | 421 id, buffer_to_dismiss)).second; |
420 DCHECK(inserted); | 422 DCHECK(inserted); |
421 } | 423 } |
422 } | 424 } |
423 | 425 |
| 426 static void ReadPixelsSyncInner( |
| 427 const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories, |
| 428 uint32 texture_id, |
| 429 const gfx::Rect& visible_rect, |
| 430 const SkBitmap& pixels, |
| 431 base::WaitableEvent* event) { |
| 432 factories->ReadPixels(texture_id, visible_rect, pixels); |
| 433 event->Signal(); |
| 434 } |
| 435 |
| 436 static void ReadPixelsSync( |
| 437 const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories, |
| 438 uint32 texture_id, |
| 439 const gfx::Rect& visible_rect, |
| 440 const SkBitmap& pixels) { |
| 441 base::WaitableEvent event(true, false); |
| 442 if (!factories->GetTaskRunner()->PostTask(FROM_HERE, |
| 443 base::Bind(&ReadPixelsSyncInner, |
| 444 factories, |
| 445 texture_id, |
| 446 visible_rect, |
| 447 pixels, |
| 448 &event))) |
| 449 return; |
| 450 event.Wait(); |
| 451 } |
| 452 |
424 void GpuVideoDecoder::PictureReady(const media::Picture& picture) { | 453 void GpuVideoDecoder::PictureReady(const media::Picture& picture) { |
425 DVLOG(3) << "PictureReady()"; | 454 DVLOG(3) << "PictureReady()"; |
426 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 455 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
427 | 456 |
428 PictureBufferMap::iterator it = | 457 PictureBufferMap::iterator it = |
429 assigned_picture_buffers_.find(picture.picture_buffer_id()); | 458 assigned_picture_buffers_.find(picture.picture_buffer_id()); |
430 if (it == assigned_picture_buffers_.end()) { | 459 if (it == assigned_picture_buffers_.end()) { |
431 NOTREACHED() << "Missing picture buffer: " << picture.picture_buffer_id(); | 460 NOTREACHED() << "Missing picture buffer: " << picture.picture_buffer_id(); |
432 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); | 461 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); |
433 return; | 462 return; |
(...skipping 11 matching lines...) Expand all Loading... |
445 scoped_refptr<VideoFrame> frame(VideoFrame::WrapNativeTexture( | 474 scoped_refptr<VideoFrame> frame(VideoFrame::WrapNativeTexture( |
446 make_scoped_ptr(new gpu::MailboxHolder( | 475 make_scoped_ptr(new gpu::MailboxHolder( |
447 pb.texture_mailbox(), decoder_texture_target_, 0 /* sync_point */)), | 476 pb.texture_mailbox(), decoder_texture_target_, 0 /* sync_point */)), |
448 BindToCurrentLoop(base::Bind(&GpuVideoDecoder::ReusePictureBuffer, | 477 BindToCurrentLoop(base::Bind(&GpuVideoDecoder::ReusePictureBuffer, |
449 weak_this_, | 478 weak_this_, |
450 picture.picture_buffer_id())), | 479 picture.picture_buffer_id())), |
451 pb.size(), | 480 pb.size(), |
452 visible_rect, | 481 visible_rect, |
453 natural_size, | 482 natural_size, |
454 timestamp, | 483 timestamp, |
455 base::Bind(&GpuVideoAcceleratorFactories::ReadPixels, | 484 base::Bind(&ReadPixelsSync, factories_, pb.texture_id(), visible_rect))); |
456 factories_, | |
457 pb.texture_id(), | |
458 gfx::Size(visible_rect.width(), visible_rect.height())))); | |
459 CHECK_GT(available_pictures_, 0); | 485 CHECK_GT(available_pictures_, 0); |
460 --available_pictures_; | 486 --available_pictures_; |
461 bool inserted = | 487 bool inserted = |
462 picture_buffers_at_display_.insert(picture.picture_buffer_id()).second; | 488 picture_buffers_at_display_.insert(picture.picture_buffer_id()).second; |
463 DCHECK(inserted); | 489 DCHECK(inserted); |
464 | 490 |
465 EnqueueFrameAndTriggerFrameDelivery(frame); | 491 EnqueueFrameAndTriggerFrameDelivery(frame); |
466 } | 492 } |
467 | 493 |
468 void GpuVideoDecoder::EnqueueFrameAndTriggerFrameDelivery( | 494 void GpuVideoDecoder::EnqueueFrameAndTriggerFrameDelivery( |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
620 return; | 646 return; |
621 } | 647 } |
622 } | 648 } |
623 | 649 |
624 void GpuVideoDecoder::DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent() | 650 void GpuVideoDecoder::DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent() |
625 const { | 651 const { |
626 DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread()); | 652 DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread()); |
627 } | 653 } |
628 | 654 |
629 } // namespace media | 655 } // namespace media |
OLD | NEW |