maybe_render_early_manager.cc 5.4 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/android/maybe_render_early_manager.h"
  5. #include <algorithm>
  6. #include "base/containers/cxx20_erase.h"
  7. #include "base/memory/weak_ptr.h"
  8. #include "base/threading/sequence_bound.h"
  9. #include "media/gpu/android/codec_image_group.h"
  10. #include "media/gpu/android/codec_surface_bundle.h"
  11. namespace media {
  12. // GPU-thread side of the default MaybeRenderEarlyManager. This handles doing
  13. // the actual rendering.
  14. class GpuMaybeRenderEarlyImpl {
  15. public:
  16. GpuMaybeRenderEarlyImpl() {}
  17. GpuMaybeRenderEarlyImpl(const GpuMaybeRenderEarlyImpl&) = delete;
  18. GpuMaybeRenderEarlyImpl& operator=(const GpuMaybeRenderEarlyImpl&) = delete;
  19. ~GpuMaybeRenderEarlyImpl() = default;
  20. void SetCodecImageGroup(scoped_refptr<CodecImageGroup> image_group) {
  21. image_group_ = std::move(image_group);
  22. }
  23. void AddCodecImage(scoped_refptr<CodecImageHolder> codec_image_holder) {
  24. // Register to find out when this CodecImage is unused, so that we can try
  25. // to render a new image early.
  26. codec_image_holder->codec_image_raw()->AddUnusedCB(base::BindOnce(
  27. &GpuMaybeRenderEarlyImpl::OnImageUnused, weak_factory_.GetWeakPtr()));
  28. DCHECK(std::find(images_.begin(), images_.end(),
  29. codec_image_holder->codec_image_raw()) == images_.end());
  30. images_.push_back(codec_image_holder->codec_image_raw());
  31. // Add |image| to our current image group. This makes sure that any overlay
  32. // lasts as long as the images. For TextureOwner, it doesn't do much.
  33. image_group_->AddCodecImage(codec_image_holder->codec_image_raw());
  34. }
  35. void MaybeRenderEarly(scoped_refptr<gpu::RefCountedLock> drdc_lock) {
  36. base::AutoLockMaybe auto_lock(drdc_lock ? drdc_lock->GetDrDcLockPtr()
  37. : nullptr);
  38. internal::MaybeRenderEarly(&images_);
  39. }
  40. private:
  41. void OnImageUnused(CodecImage* image) {
  42. // |image| is no longer used, so try to render a new image speculatively.
  43. DCHECK(std::find(images_.begin(), images_.end(), image) != images_.end());
  44. // Remember that |image_group_| might not be the same one that |image|
  45. // belongs to.
  46. base::Erase(images_, image);
  47. internal::MaybeRenderEarly(&images_);
  48. }
  49. // Outstanding images that should be considered for early rendering.
  50. std::vector<CodecImage*> images_;
  51. // Current image group to which new images (frames) will be added. We'll
  52. // replace this when SetImageGroup() is called.
  53. scoped_refptr<CodecImageGroup> image_group_;
  54. base::WeakPtrFactory<GpuMaybeRenderEarlyImpl> weak_factory_{this};
  55. };
  56. // Default implementation of MaybeRenderEarlyManager. Lives on whatever thread
  57. // you like, but will hop to the gpu thread to do real work.
  58. class MaybeRenderEarlyManagerImpl : public MaybeRenderEarlyManager,
  59. public gpu::RefCountedLockHelperDrDc {
  60. public:
  61. MaybeRenderEarlyManagerImpl(
  62. scoped_refptr<base::SequencedTaskRunner> gpu_task_runner,
  63. scoped_refptr<gpu::RefCountedLock> drdc_lock)
  64. : gpu::RefCountedLockHelperDrDc(std::move(drdc_lock)),
  65. gpu_task_runner_(gpu_task_runner),
  66. gpu_impl_(std::move(gpu_task_runner)) {}
  67. MaybeRenderEarlyManagerImpl(const MaybeRenderEarlyManagerImpl&) = delete;
  68. MaybeRenderEarlyManagerImpl& operator=(const MaybeRenderEarlyManagerImpl&) =
  69. delete;
  70. ~MaybeRenderEarlyManagerImpl() override = default;
  71. void SetSurfaceBundle(
  72. scoped_refptr<CodecSurfaceBundle> surface_bundle) override {
  73. // Start a new image group. Note that there's no reason that we can't have
  74. // more than one group per surface bundle; it's okay if we're called
  75. // multiple times with the same surface bundle. It just helps to combine
  76. // the callbacks if we don't, especially since AndroidOverlay doesn't know
  77. // how to remove destruction callbacks. That's one reason why we don't just
  78. // make the CodecImage register itself. The other is that the threading is
  79. // easier if we do it this way, since the image group is constructed on the
  80. // proper thread to talk to the overlay.
  81. auto image_group = base::MakeRefCounted<CodecImageGroup>(
  82. gpu_task_runner_, std::move(surface_bundle), GetDrDcLock());
  83. // Give the image group to |gpu_impl_|. Note that we don't drop our ref to
  84. // |image_group| on this thread. It can only be constructed here.
  85. gpu_impl_.AsyncCall(&GpuMaybeRenderEarlyImpl::SetCodecImageGroup)
  86. .WithArgs(std::move(image_group));
  87. }
  88. void AddCodecImage(
  89. scoped_refptr<CodecImageHolder> codec_image_holder) override {
  90. gpu_impl_.AsyncCall(&GpuMaybeRenderEarlyImpl::AddCodecImage)
  91. .WithArgs(std::move(codec_image_holder));
  92. }
  93. void MaybeRenderEarly() override {
  94. gpu_impl_.AsyncCall(&GpuMaybeRenderEarlyImpl::MaybeRenderEarly)
  95. .WithArgs(GetDrDcLock());
  96. }
  97. private:
  98. scoped_refptr<base::SequencedTaskRunner> gpu_task_runner_;
  99. // Gpu-side.
  100. base::SequenceBound<GpuMaybeRenderEarlyImpl> gpu_impl_;
  101. };
  102. // static
  103. std::unique_ptr<MaybeRenderEarlyManager> MaybeRenderEarlyManager::Create(
  104. scoped_refptr<base::SequencedTaskRunner> task_runner,
  105. scoped_refptr<gpu::RefCountedLock> lock) {
  106. return std::make_unique<MaybeRenderEarlyManagerImpl>(std::move(task_runner),
  107. std::move(lock));
  108. }
  109. } // namespace media