PageRenderTime 53ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/media/gpu/android/surface_chooser_helper.cc

http://github.com/chromium/chromium
C++ | 171 lines | 110 code | 28 blank | 33 comment | 13 complexity | b1cdd867c3f44b83564f5167208e19d8 MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.0, BSD-2-Clause, LGPL-2.1, MPL-2.0, 0BSD, EPL-1.0, MPL-2.0-no-copyleft-exception, GPL-2.0, BitTorrent-1.0, CPL-1.0, LGPL-3.0, Unlicense, BSD-3-Clause, CC0-1.0, JSON, MIT, GPL-3.0, CC-BY-SA-3.0, AGPL-1.0
  1. // Copyright 2017 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/surface_chooser_helper.h"
  5. #include <memory>
  6. #include "base/time/default_tick_clock.h"
  7. #include "base/time/tick_clock.h"
  8. #include "media/gpu/android/android_video_surface_chooser.h"
  9. #include "media/gpu/android/promotion_hint_aggregator_impl.h"
  10. namespace media {
  11. namespace {
  12. // Number of frames to defer overlays for when entering fullscreen. This lets
  13. // blink relayout settle down a bit. If overlay positions were synchronous,
  14. // then we wouldn't need this.
  15. enum { kFrameDelayForFullscreenLayout = 15 };
  16. // How often do we let the surface chooser try for an overlay? While we'll
  17. // retry if some relevant state changes on our side (e.g., fullscreen state),
  18. // there's plenty of state that we don't know about (e.g., power efficiency,
  19. // memory pressure => cancelling an old overlay, etc.). We just let the chooser
  20. // retry every once in a while for those things.
  21. constexpr base::TimeDelta RetryChooserTimeout = base::TimeDelta::FromSeconds(5);
  22. } // namespace
  23. SurfaceChooserHelper::SurfaceChooserHelper(
  24. std::unique_ptr<AndroidVideoSurfaceChooser> surface_chooser,
  25. bool is_overlay_required,
  26. bool promote_aggressively,
  27. bool always_use_texture_owner,
  28. std::unique_ptr<PromotionHintAggregator> promotion_hint_aggregator,
  29. const base::TickClock* tick_clock)
  30. : surface_chooser_(std::move(surface_chooser)),
  31. is_overlay_required_(is_overlay_required),
  32. promotion_hint_aggregator_(
  33. promotion_hint_aggregator
  34. ? std::move(promotion_hint_aggregator)
  35. : std::make_unique<PromotionHintAggregatorImpl>()),
  36. tick_clock_(tick_clock ? tick_clock
  37. : base::DefaultTickClock::GetInstance()) {
  38. surface_chooser_state_.is_required = is_overlay_required_;
  39. surface_chooser_state_.promote_aggressively = promote_aggressively;
  40. surface_chooser_state_.always_use_texture_owner = always_use_texture_owner;
  41. }
  42. SurfaceChooserHelper::~SurfaceChooserHelper() {}
  43. void SurfaceChooserHelper::SetSecureSurfaceMode(SecureSurfaceMode mode) {
  44. bool is_secure = false;
  45. requires_secure_video_surface_ = false;
  46. switch (mode) {
  47. case SecureSurfaceMode::kInsecure:
  48. break;
  49. case SecureSurfaceMode::kRequested:
  50. is_secure = true;
  51. break;
  52. case SecureSurfaceMode::kRequired:
  53. is_secure = true;
  54. requires_secure_video_surface_ = true;
  55. break;
  56. }
  57. surface_chooser_state_.is_secure = is_secure;
  58. surface_chooser_state_.is_required =
  59. requires_secure_video_surface_ || is_overlay_required_;
  60. }
  61. void SurfaceChooserHelper::SetIsFullscreen(bool is_fullscreen) {
  62. // TODO(liberato): AVDA previously only set is_expecting_relayout when
  63. // getting overlay info, not when checking fullscreen for the first time.
  64. // This might affect pre-M devices. I think the pre-M path doesn't care.
  65. if (is_fullscreen && !surface_chooser_state_.is_fullscreen) {
  66. // It would be nice if we could just delay until we get a hint from an
  67. // overlay that's "in fullscreen" in the sense that the CompositorFrame it
  68. // came from had some flag set to indicate that the renderer was in
  69. // fullscreen mode when it was generated. However, even that's hard, since
  70. // there's no real connection between "renderer finds out about fullscreen"
  71. // and "blink has completed layouts for it". The latter is what we really
  72. // want to know.
  73. surface_chooser_state_.is_expecting_relayout = true;
  74. hints_until_clear_relayout_flag_ = kFrameDelayForFullscreenLayout;
  75. }
  76. surface_chooser_state_.is_fullscreen = is_fullscreen;
  77. }
  78. void SurfaceChooserHelper::SetVideoRotation(VideoRotation video_rotation) {
  79. surface_chooser_state_.video_rotation = video_rotation;
  80. }
  81. void SurfaceChooserHelper::SetIsPersistentVideo(bool is_persistent_video) {
  82. surface_chooser_state_.is_persistent_video = is_persistent_video;
  83. }
  84. void SurfaceChooserHelper::UpdateChooserState(
  85. base::Optional<AndroidOverlayFactoryCB> new_factory) {
  86. surface_chooser_->UpdateState(std::move(new_factory), surface_chooser_state_);
  87. }
  88. void SurfaceChooserHelper::NotifyPromotionHintAndUpdateChooser(
  89. const PromotionHintAggregator::Hint& hint,
  90. bool is_using_overlay) {
  91. bool update_state = false;
  92. promotion_hint_aggregator_->NotifyPromotionHint(hint);
  93. // If we're expecting a full screen relayout, then also use this hint as a
  94. // notification that another frame has happened.
  95. if (hints_until_clear_relayout_flag_ > 0) {
  96. hints_until_clear_relayout_flag_--;
  97. if (hints_until_clear_relayout_flag_ == 0) {
  98. surface_chooser_state_.is_expecting_relayout = false;
  99. update_state = true;
  100. }
  101. }
  102. surface_chooser_state_.initial_position = hint.screen_rect;
  103. bool promotable = promotion_hint_aggregator_->IsSafeToPromote();
  104. if (promotable != surface_chooser_state_.is_compositor_promotable) {
  105. surface_chooser_state_.is_compositor_promotable = promotable;
  106. update_state = true;
  107. }
  108. // If we've been provided with enough new frames, then update the state even
  109. // if it hasn't changed. This lets |surface_chooser_| retry for an overlay.
  110. // It's especially helpful for power-efficient overlays, since we don't know
  111. // when an overlay becomes power efficient. It also helps retry any failure
  112. // that's not accompanied by a state change, such as if android destroys the
  113. // overlay asynchronously for a transient reason.
  114. //
  115. // If we're already using an overlay, then there's no need to do this.
  116. base::TimeTicks now = tick_clock_->NowTicks();
  117. if (!is_using_overlay &&
  118. now - most_recent_chooser_retry_ >= RetryChooserTimeout) {
  119. update_state = true;
  120. }
  121. if (update_state) {
  122. most_recent_chooser_retry_ = now;
  123. UpdateChooserState(base::Optional<AndroidOverlayFactoryCB>());
  124. }
  125. }
  126. SurfaceChooserHelper::FrameInformation
  127. SurfaceChooserHelper::ComputeFrameInformation(bool is_using_overlay) {
  128. if (!is_using_overlay) {
  129. // Not an overlay.
  130. return surface_chooser_state_.is_secure
  131. ? FrameInformation::NON_OVERLAY_L3
  132. : FrameInformation::NON_OVERLAY_INSECURE;
  133. }
  134. // Overlay.
  135. if (surface_chooser_state_.is_secure) {
  136. return surface_chooser_state_.is_required ? FrameInformation::OVERLAY_L1
  137. : FrameInformation::OVERLAY_L3;
  138. }
  139. return surface_chooser_state_.is_fullscreen
  140. ? FrameInformation::OVERLAY_INSECURE_PLAYER_ELEMENT_FULLSCREEN
  141. : FrameInformation::OVERLAY_INSECURE_NON_PLAYER_ELEMENT_FULLSCREEN;
  142. }
  143. } // namespace media