| Index: media/gpu/android_video_surface_chooser_impl.cc
|
| diff --git a/media/gpu/android_video_surface_chooser_impl.cc b/media/gpu/android_video_surface_chooser_impl.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d1df41371d873bc61f3bcdcb43c305794080e37d
|
| --- /dev/null
|
| +++ b/media/gpu/android_video_surface_chooser_impl.cc
|
| @@ -0,0 +1,141 @@
|
| +// Copyright 2017 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "media/gpu/android_video_surface_chooser_impl.h"
|
| +
|
| +namespace media {
|
| +
|
| +AndroidVideoSurfaceChooserImpl::AndroidVideoSurfaceChooserImpl()
|
| + : weak_factory_(this) {}
|
| +
|
| +AndroidVideoSurfaceChooserImpl::~AndroidVideoSurfaceChooserImpl() {}
|
| +
|
| +void AndroidVideoSurfaceChooserImpl::Initialize(
|
| + UseOverlayCB use_overlay_cb,
|
| + UseSurfaceTextureCB use_surface_texture_cb,
|
| + StopUsingOverlayImmediatelyCB stop_immediately_cb,
|
| + std::unique_ptr<AndroidOverlayFactory> initial_factory) {
|
| + use_overlay_cb_ = std::move(use_overlay_cb);
|
| + use_surface_texture_cb_ = std::move(use_surface_texture_cb);
|
| + stop_immediately_cb_ = std::move(stop_immediately_cb);
|
| +
|
| + if (initial_factory) {
|
| + // We requested an overlay. Wait to see if it succeeds or fails, since
|
| + // hopefully this will be fast. On M+, we could ask it to start with a
|
| + // SurfaceTexture either way. Before M, we can't switch surfaces. In that
|
| + // case, it's important not to request a SurfaceTexture if we have an
|
| + // overlay pending, so that we know not to transition to SurfaceTexture.
|
| + client_notification_pending_ = true;
|
| + ReplaceOverlayFactory(std::move(initial_factory));
|
| + }
|
| +
|
| + if (!overlay_) {
|
| + // We haven't requested an overlay yet. Just ask the client to start with
|
| + // SurfaceTexture now.
|
| + use_surface_texture_cb_.Run();
|
| + return;
|
| + }
|
| +}
|
| +
|
| +void AndroidVideoSurfaceChooserImpl::ReplaceOverlayFactory(
|
| + std::unique_ptr<AndroidOverlayFactory> factory) {
|
| + // If we have an overlay, then we should transition away from it. It
|
| + // doesn't matter if we have a new factory or no factory; the old overlay goes
|
| + // with the old factory.
|
| +
|
| + // Notify the client to transition to SurfaceTexture, which it might already
|
| + // be using. If |!client_notification_pending_|, then we're still during
|
| + // initial startup, so we don't switch the client. Otherwise, we'd cause
|
| + // pre-M to break, since we'd start with a SurfaceTexture in all cases.
|
| + if (!client_notification_pending_)
|
| + use_surface_texture_cb_.Run();
|
| +
|
| + // If we started construction of an overlay, but it's not ready yet, then
|
| + // just drop it.
|
| + if (overlay_)
|
| + overlay_ = nullptr;
|
| +
|
| + overlay_factory_ = std::move(factory);
|
| +
|
| + // If we don't have a new factory, then just stop here.
|
| + if (!overlay_factory_)
|
| + return;
|
| +
|
| + // We just got an overlay factory. Get an overlay immediately. This is
|
| + // the right behavior to match what AVDA does with CVV. For DS, we should
|
| + // probably check to see if it's a good idea, at least on M+.
|
| + // Also note that for pre-M, AVDA depends on this behavior, else it will get
|
| + // a SurfaceTexture then be unable to switch. Perhaps there should be a
|
| + // pre-M implementation of this class that guarantees that it won't change
|
| + // between the two.
|
| + AndroidOverlay::Config config;
|
| + // We bind all of our callbacks with weak ptrs, since we don't know how long
|
| + // the client will hold on to overlays. They could, in principle, show up
|
| + // long after the client is destroyed too, if codec destruction hangs.
|
| + config.ready_cb = base::Bind(&AndroidVideoSurfaceChooserImpl::OnOverlayReady,
|
| + weak_factory_.GetWeakPtr());
|
| + config.failed_cb =
|
| + base::Bind(&AndroidVideoSurfaceChooserImpl::OnOverlayFailed,
|
| + weak_factory_.GetWeakPtr());
|
| + config.destroyed_cb =
|
| + base::Bind(&AndroidVideoSurfaceChooserImpl::OnSurfaceDestroyed,
|
| + weak_factory_.GetWeakPtr());
|
| + // TODO(liberato): where do we get the initial size from? For CVV, it's
|
| + // set via the natural size, and this is ignored anyway. The client should
|
| + // provide this.
|
| + config.rect = gfx::Rect(0, 0, 1, 1);
|
| + overlay_ = overlay_factory_->CreateOverlay(config);
|
| +}
|
| +
|
| +void AndroidVideoSurfaceChooserImpl::OnOverlayReady(AndroidOverlay* overlay) {
|
| + // |overlay_| is the only overlay for which we haven't gotten a ready callback
|
| + // back yet.
|
| + DCHECK_EQ(overlay, overlay_.get());
|
| +
|
| + // If we haven't sent the client notification yet, we're doing so now.
|
| + client_notification_pending_ = false;
|
| +
|
| + use_overlay_cb_.Run(std::move(overlay_));
|
| +}
|
| +
|
| +void AndroidVideoSurfaceChooserImpl::OnOverlayFailed(AndroidOverlay* overlay) {
|
| + // We shouldn't get a failure for any overlay except the incoming one.
|
| + DCHECK_EQ(overlay, overlay_.get());
|
| +
|
| + // If we owe the client a notification callback, then send it.
|
| + if (client_notification_pending_) {
|
| + // The overlay that we requested failed, so notify the client to try
|
| + // using SurfaceTexture instead.
|
| + client_notification_pending_ = false;
|
| + use_surface_texture_cb_.Run();
|
| + }
|
| +
|
| + overlay_ = nullptr;
|
| +}
|
| +
|
| +void AndroidVideoSurfaceChooserImpl::OnSurfaceDestroyed(
|
| + AndroidOverlay* overlay) {
|
| + // We shouldn't get OnSurfaceDestroyed unless we previously got Ready. In
|
| + // that case, we should have notified the client then.
|
| + DCHECK(!client_notification_pending_);
|
| +
|
| + // We should not get OnSurfaceDestroyed for the incoming overlay, since we
|
| + // should't get OnSurfaceDestroyed before OnSurfaceReady. OnSurfaceReady
|
| + // should imply that this isn't the incoming overlay.
|
| + DCHECK_NE(overlay_.get(), overlay);
|
| +
|
| + // We unconditionally send 'stop immediately', since we don't know what
|
| + // overlay this is. Even if we revoked the overlay before, we may have done
|
| + // so with the slow transition, which isn't good enough now. The client has
|
| + // to be smart enoug to understand if it's currently using |overlay| or not.
|
| +
|
| + // Also remember that we don't know when the client drops the overlay, after
|
| + // we revoke it. We can get callbacks until that happens, even if (for
|
| + // example), the overlay is waiting for MediaCodec destruction. So, it's
|
| + // likely that we'll send callbacks for overlays that the client is already
|
| + // not using.
|
| + stop_immediately_cb_.Run(overlay);
|
| +}
|
| +
|
| +} // namespace media
|
|
|