OLD | NEW |
(Empty) | |
| 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 |
| 5 #include "media/gpu/avda_overlay_helper_impl.h" |
| 6 |
| 7 namespace media { |
| 8 |
| 9 AVDAOverlayHelperImpl::AVDAOverlayHelperImpl() : weak_factory_(this) {} |
| 10 |
| 11 AVDAOverlayHelperImpl::~AVDAOverlayHelperImpl() {} |
| 12 |
| 13 void AVDAOverlayHelperImpl::Startup( |
| 14 const UseOverlayCB& use_overlay_cb, |
| 15 const UseSurfaceTextureCB& use_surface_texture_cb, |
| 16 const StopUsingOverlayImmediatelyCB& stop_immediately_cb, |
| 17 std::unique_ptr<AndroidOverlayFactory> initial_factory) { |
| 18 use_overlay_cb_ = use_overlay_cb; |
| 19 use_surface_texture_cb_ = use_surface_texture_cb; |
| 20 stop_immediately_cb_ = stop_immediately_cb; |
| 21 |
| 22 if (initial_factory) { |
| 23 // We requested an overlay. Wait to see if it succeeds or fails, since |
| 24 // hopefully this will be fast. On M+, we could ask it to start with a |
| 25 // SurfaceTexture either way. Before M, we can't switch surfaces. In that |
| 26 // case, it's important not to request a SurfaceTexture if we have an |
| 27 // overlay pending, so that we know not to transition to SurfaceTexture. |
| 28 client_notification_pending_ = true; |
| 29 OnOverlayFactory(std::move(initial_factory)); |
| 30 } |
| 31 |
| 32 if (!overlay_) { |
| 33 // We haven't requested an overlay yet. Just ask the client to start with |
| 34 // SurfaceTexture now. |
| 35 use_surface_texture_cb_.Run(); |
| 36 return; |
| 37 } |
| 38 } |
| 39 |
| 40 void AVDAOverlayHelperImpl::OnOverlayFactory( |
| 41 std::unique_ptr<AndroidOverlayFactory> factory) { |
| 42 // If we have an overlay, then we should transition away from it. It |
| 43 // doesn't matter if we have a new factory or no factory; the old overlay goes |
| 44 // with the old factory. |
| 45 |
| 46 // Notify the client to transition to SurfaceTexture, which it might already |
| 47 // be using. If |!client_notification_pending_|, then we're still during |
| 48 // initial startup, so we don't switch the client. Otherwise, we'd cause |
| 49 // pre-M to break, since we'd start with a SurfaceTexture in all cases. |
| 50 // TODO(liberato): should we switch immediately away, at least for CVV, if |
| 51 // |!factory|? It means that we're probably leaving full screen. |
| 52 // We don't do this just to match previous behavior, which always went through |
| 53 // AVDA::SetSurface, which was the slower transition. However, the CVV |
| 54 // won't be visible soon, so maybe that's the wrong thing to do. For DS, |
| 55 // it would be fine to transition slower to avoid dropping frames. Note |
| 56 // that we'd have to not only remember the most recent overlay that we sent |
| 57 // to the client, but we'd also have to find out when the client drops it. |
| 58 // We'd have a raw ptr only, which might be re-used. |
| 59 if (!client_notification_pending_) |
| 60 use_surface_texture_cb_.Run(); |
| 61 |
| 62 // If we started construction of an overlay, but it's not ready yet, then |
| 63 // just drop it. |
| 64 if (overlay_) |
| 65 overlay_ = nullptr; |
| 66 |
| 67 overlay_factory_ = std::move(factory); |
| 68 |
| 69 // If we don't have a new factory, then just stop here. |
| 70 if (!overlay_factory_) |
| 71 return; |
| 72 |
| 73 // We just got an overlay factory. Get an overlay immediately. This is |
| 74 // the right behavior to match what AVDA does with CVV. For DS, we should |
| 75 // probably check to see if it's a good idea, at least on M+. |
| 76 // Also note that for pre-M, AVDA depends on this behavior, else it will get |
| 77 // a SurfaceTexture then be unable to switch. Perhaps there should be a |
| 78 // pre-M implementation of this class that guarantees that it won't change |
| 79 // between the two. |
| 80 AndroidOverlay::Config config; |
| 81 // We bind all of our callbacks with weak ptrs, since we don't know how long |
| 82 // the client will hold on to overlays. They could, in principle, show up |
| 83 // long after the client is destroyed too, if codec destruction hangs. |
| 84 config.ready_cb = base::Bind(&AVDAOverlayHelperImpl::OnOverlayReady, |
| 85 weak_factory_.GetWeakPtr()); |
| 86 config.failed_cb = base::Bind(&AVDAOverlayHelperImpl::OnOverlayFailed, |
| 87 weak_factory_.GetWeakPtr()); |
| 88 config.destroyed_cb = base::Bind(&AVDAOverlayHelperImpl::OnSurfaceDestroyed, |
| 89 weak_factory_.GetWeakPtr()); |
| 90 // TODO(liberato): where do we get the initial size from? For CVV, it's |
| 91 // set via the natural size, and this is ignored anyway. The client should |
| 92 // provide this. |
| 93 config.rect = gfx::Rect(0, 0, 1, 1); |
| 94 overlay_ = overlay_factory_->CreateOverlay(config); |
| 95 } |
| 96 |
| 97 void AVDAOverlayHelperImpl::OnOverlayReady(AndroidOverlay* overlay) { |
| 98 // We |overlay_| is the only overlay for which we haven't gotten a ready |
| 99 // callback yet. |
| 100 DCHECK_EQ(overlay, overlay_.get()); |
| 101 |
| 102 // If we haven't sent the client notification yet, we're doing so now. |
| 103 client_notification_pending_ = false; |
| 104 |
| 105 use_overlay_cb_.Run(std::move(overlay_)); |
| 106 } |
| 107 |
| 108 void AVDAOverlayHelperImpl::OnOverlayFailed(AndroidOverlay* overlay) { |
| 109 // We shouldn't get a failure for any overlay except the incoming one. |
| 110 DCHECK_EQ(overlay, overlay_.get()); |
| 111 |
| 112 // If we owe the client a notification callback, then send it. |
| 113 if (client_notification_pending_) { |
| 114 // The overlay that we requested failed, so notify the client to try |
| 115 // using SurfaceTexture instead. |
| 116 client_notification_pending_ = false; |
| 117 use_surface_texture_cb_.Run(); |
| 118 } |
| 119 |
| 120 overlay_ = nullptr; |
| 121 } |
| 122 |
| 123 void AVDAOverlayHelperImpl::OnSurfaceDestroyed(AndroidOverlay* overlay) { |
| 124 // We shouldn't get OnSurfaceDestroyed unless we previously got Ready. In |
| 125 // that case, we should have notified the client then. |
| 126 DCHECK(!client_notification_pending_); |
| 127 |
| 128 // We should not get OnSurfaceDestroyed for the incoming overlay, since we |
| 129 // should't get OnSurfaceDestroyed before OnSurfaceReady. OnSurfaceReady |
| 130 // should imply that this isn't the incoming overlay. |
| 131 DCHECK_NE(overlay_.get(), overlay); |
| 132 |
| 133 // We unconditionally send 'stop immediately', since we don't know what |
| 134 // overlay this is. Even if we revoked the overlay before, we may have done |
| 135 // so with the slow transition, which isn't good enough now. The client has |
| 136 // to be smart enoug to understand if it's currently using |overlay| or not. |
| 137 |
| 138 // Also remember that we don't know when the client drops the overlay, after |
| 139 // we revoke it. We can get callbacks until that happens, even if (for |
| 140 // example), the overlay is waiting for MediaCodec destruction. So, it's |
| 141 // likely that we'll send callbacks for overlays that the client is already |
| 142 // not using. |
| 143 stop_immediately_cb_.Run(overlay); |
| 144 } |
| 145 |
| 146 } // namespace media |
OLD | NEW |