image_processor_with_pool.cc 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "media/gpu/chromeos/image_processor_with_pool.h"
  5. #include "base/bind.h"
  6. #include "base/memory/ptr_util.h"
  7. #include "media/base/media_serializers.h"
  8. #include "media/gpu/chromeos/gpu_buffer_layout.h"
  9. #include "media/gpu/macros.h"
  10. namespace media {
  11. // static
  12. CroStatus::Or<std::unique_ptr<ImageProcessorWithPool>>
  13. ImageProcessorWithPool::Create(
  14. std::unique_ptr<ImageProcessor> image_processor,
  15. DmabufVideoFramePool* const frame_pool,
  16. size_t num_frames,
  17. bool use_protected,
  18. const scoped_refptr<base::SequencedTaskRunner> task_runner) {
  19. const ImageProcessor::PortConfig& config = image_processor->output_config();
  20. const gfx::Size coded_size = config.size;
  21. DCHECK(gfx::Rect(coded_size).Contains(config.visible_rect));
  22. const gfx::Size natural_size = config.visible_rect.size();
  23. CroStatus::Or<GpuBufferLayout> status_or_layout = frame_pool->Initialize(
  24. config.fourcc, coded_size, config.visible_rect, natural_size, num_frames,
  25. use_protected, image_processor->needs_linear_output_buffers());
  26. if (status_or_layout.has_error()) {
  27. VLOGF(1) << "Failed to initialize the pool.";
  28. return std::move(status_or_layout).error();
  29. }
  30. const GpuBufferLayout layout = std::move(status_or_layout).value();
  31. if (layout.size() != config.size) {
  32. VLOGF(1) << "Failed to request frame with correct size. "
  33. << config.size.ToString() << " != " << layout.size().ToString();
  34. return CroStatus(CroStatus::Codes::kInvalidLayoutSize)
  35. .WithData("expected_size", config.size)
  36. .WithData("actual_size", layout.size());
  37. }
  38. return base::WrapUnique<ImageProcessorWithPool>(new ImageProcessorWithPool(
  39. std::move(image_processor), frame_pool, std::move(task_runner)));
  40. }
  41. ImageProcessorWithPool::ImageProcessorWithPool(
  42. std::unique_ptr<ImageProcessor> image_processor,
  43. DmabufVideoFramePool* const frame_pool,
  44. const scoped_refptr<base::SequencedTaskRunner> task_runner)
  45. : image_processor_(std::move(image_processor)),
  46. frame_pool_(frame_pool),
  47. task_runner_(std::move(task_runner)) {
  48. DVLOGF(3);
  49. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  50. weak_this_ = weak_this_factory_.GetWeakPtr();
  51. }
  52. ImageProcessorWithPool::~ImageProcessorWithPool() {
  53. DVLOGF(3);
  54. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  55. }
  56. void ImageProcessorWithPool::Reset() {
  57. DVLOGF(4);
  58. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  59. image_processor_->Reset();
  60. pending_frames_ = {};
  61. num_frames_in_ip_ = 0;
  62. // Cancel pending tasks to avoid returning previous frames to the client.
  63. weak_this_factory_.InvalidateWeakPtrs();
  64. weak_this_ = weak_this_factory_.GetWeakPtr();
  65. }
  66. bool ImageProcessorWithPool::HasPendingFrames() const {
  67. DVLOGF(4);
  68. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  69. return !pending_frames_.empty() || num_frames_in_ip_ > 0;
  70. }
  71. void ImageProcessorWithPool::Process(scoped_refptr<VideoFrame> frame,
  72. FrameReadyCB ready_cb) {
  73. DVLOGF(4);
  74. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  75. pending_frames_.push(std::make_pair(std::move(frame), std::move(ready_cb)));
  76. PumpProcessFrames();
  77. }
  78. void ImageProcessorWithPool::PumpProcessFrames() {
  79. DVLOGF(4);
  80. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  81. while (!pending_frames_.empty()) {
  82. scoped_refptr<VideoFrame> output_frame = frame_pool_->GetFrame();
  83. if (!output_frame) {
  84. // Notify when pool is available.
  85. frame_pool_->NotifyWhenFrameAvailable(base::BindOnce(
  86. base::IgnoreResult(&base::SequencedTaskRunner::PostTask),
  87. task_runner_, FROM_HERE,
  88. base::BindOnce(&ImageProcessorWithPool::PumpProcessFrames,
  89. weak_this_)));
  90. break;
  91. }
  92. scoped_refptr<VideoFrame> input_frame =
  93. std::move(pending_frames_.front().first);
  94. FrameReadyCB ready_cb = std::move(pending_frames_.front().second);
  95. pending_frames_.pop();
  96. ++num_frames_in_ip_;
  97. image_processor_->Process(
  98. std::move(input_frame), std::move(output_frame),
  99. base::BindOnce(&ImageProcessorWithPool::OnFrameProcessed, weak_this_,
  100. std::move(ready_cb)));
  101. }
  102. }
  103. void ImageProcessorWithPool::OnFrameProcessed(FrameReadyCB ready_cb,
  104. scoped_refptr<VideoFrame> frame) {
  105. DVLOGF(4);
  106. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  107. DCHECK_NE(num_frames_in_ip_, 0u);
  108. --num_frames_in_ip_;
  109. std::move(ready_cb).Run(std::move(frame));
  110. }
  111. } // namespace media