Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1224)

Unified Diff: media/gpu/android_video_surface_chooser_impl_unittest.cc

Issue 2813303003: Add AndroidVideoSurfaceChooser to manage overlays. (Closed)
Patch Set: fixed AVDAManager comment Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: media/gpu/android_video_surface_chooser_impl_unittest.cc
diff --git a/media/gpu/android_video_surface_chooser_impl_unittest.cc b/media/gpu/android_video_surface_chooser_impl_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..82f30e5b1e5aa0ccb721a1fa3c36516768092edb
--- /dev/null
+++ b/media/gpu/android_video_surface_chooser_impl_unittest.cc
@@ -0,0 +1,325 @@
+// 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"
+
+#include <stdint.h>
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "media/base/android/android_overlay_factory.h"
+#include "media/base/android/mock_android_overlay.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+using ::testing::AnyNumber;
+using ::testing::NiceMock;
+using ::testing::NotNull;
+using ::testing::Return;
+using ::testing::StrictMock;
+
+namespace media {
+
+// Unit tests for AndroidVideoSurfaceChooserImpl
+class AndroidVideoSurfaceChooserImplTest : public testing::Test {
+ public:
+ class MockClient {
watk 2017/05/02 21:00:01 Same comment as above about these inner classes.
liberato (no reviews please) 2017/05/02 21:50:05 Done.
+ public:
+ MOCK_METHOD1(UseOverlay, void(AndroidOverlay*));
+
+ void UseOverlayImpl(std::unique_ptr<AndroidOverlay> overlay) {
+ UseOverlay(overlay.get());
+
+ // Also take ownership of the overlay, so that it's not destroyed.
+ overlay_ = std::move(overlay);
+ }
+
+ // Note that this won't clear |overlay_|, which is helpful.
+ MOCK_METHOD0(UseSurfaceTexture, void(void));
+ MOCK_METHOD1(StopUsingOverlayImmediately, void(AndroidOverlay*));
+
+ private:
+ std::unique_ptr<AndroidOverlay> overlay_;
+ };
+
+ // Mock factory which will return one overlay.
+ class MockAndroidOverlayFactory : public AndroidOverlayFactory {
+ public:
+ MockAndroidOverlayFactory()
+ : overlay_(base::MakeUnique<MockAndroidOverlay>()),
+ weak_this_factory_(this) {}
+
+ // Called by CreateOverlay.
+ MOCK_METHOD0(MockCreateOverlay, void());
+
+ std::unique_ptr<AndroidOverlay> CreateOverlay(
+ const AndroidOverlay::Config& config) override {
+ MockCreateOverlay();
+
+ // Notify the overlay about the config that was used to create it. We
+ // can't do this during overlay construction since we might want the
+ // overlay to set test expectations.
+ if (overlay_)
+ overlay_->SetConfig(config);
+
+ return std::move(overlay_);
+ }
+
+ // Return the overlay, if we still own it. One the client creates an
+ // overlay, we'll re-assign ownership.
+ MockAndroidOverlay* overlay() { return overlay_.get(); }
+
+ // Set the overlay that we'll provide next, or nullptr.
+ void SetOverlay(std::unique_ptr<MockAndroidOverlay> overlay) {
+ overlay_ = std::move(overlay);
+ }
+
+ base::WeakPtr<MockAndroidOverlayFactory> GetWeakPtr() {
+ return weak_this_factory_.GetWeakPtr();
+ }
+
+ private:
+ std::unique_ptr<MockAndroidOverlay> overlay_;
+
+ base::WeakPtrFactory<MockAndroidOverlayFactory> weak_this_factory_;
+ };
+
+ ~AndroidVideoSurfaceChooserImplTest() override {}
+
+ void SetUp() override {
+ helper_ = base::MakeUnique<AndroidVideoSurfaceChooserImpl>();
+ factory_ = base::MakeUnique<NiceMock<MockAndroidOverlayFactory>>();
+ factory_weak_ = factory_->GetWeakPtr();
+
+ // We create a destruction observer. By default, the overlay must not be
+ // destroyed until the test completes. Of course, the test may ask the
+ // observer to expect something else.
+ destruction_observer_ = factory_->overlay()->CreateDestructionObserver();
+ destruction_observer_->DoNotAllowDestruction();
+ overlay_callbacks_ = factory_->overlay()->GetCallbacks();
+ }
+
+ void TearDown() override {
+ // If we get this far, the assume that whatever |destruction_observer_|
+ // was looking for should have already happened. We don't want the
+ // lifetime of the observer to matter with respect to the overlay when
+ // checking expectations.
+ // Note that it might already be null.
+ destruction_observer_ = nullptr;
+ }
+
+ void StartHelper(std::unique_ptr<MockAndroidOverlayFactory> factory) {
+ helper_->Initialize(
+ base::Bind(&MockClient::UseOverlayImpl, base::Unretained(&client_)),
+ base::Bind(&MockClient::UseSurfaceTexture, base::Unretained(&client_)),
+ base::Bind(&MockClient::StopUsingOverlayImmediately,
+ base::Unretained(&client_)),
+ std::move(factory));
+ }
+
+ std::unique_ptr<AndroidVideoSurfaceChooserImpl> helper_;
+ StrictMock<MockClient> client_;
+ std::unique_ptr<NiceMock<MockAndroidOverlayFactory>> factory_;
+ base::WeakPtr<MockAndroidOverlayFactory> factory_weak_;
+
+ // Callbacks to control the overlay that will be vended by |factory_|
+ MockAndroidOverlay::Callbacks overlay_callbacks_;
+
+ std::unique_ptr<MockAndroidOverlay::DestructionObserver>
+ destruction_observer_;
+};
+
+TEST_F(AndroidVideoSurfaceChooserImplTest,
+ InitializeWithoutFactoryUsesSurfaceTexture) {
+ // Calling Initialize() with no factory should result in a callback to use
+ // surface texture.
+ EXPECT_CALL(client_, UseSurfaceTexture());
+ StartHelper(nullptr);
+}
+
+TEST_F(AndroidVideoSurfaceChooserImplTest, ProvideInitialOverlaySuccessfully) {
+ // Providing a factory at startup should result in a switch to overlay. It
+ // should not switch to SurfaceTexture initially, since pre-M requires it.
+ // Note that post-M (especially DS), it might be fine to start with ST. We
+ // just don't differentiate those cases yet in the impl.
+
+ EXPECT_CALL(client_, UseSurfaceTexture()).Times(0);
+ StartHelper(std::move(factory_));
+
+ // Notify the helper that the overlay is ready. Expect that |client_| will
+ // be told to use it.
+ EXPECT_CALL(client_, UseOverlay(NotNull()));
+ overlay_callbacks_.OverlayReady.Run();
+}
+
+TEST_F(AndroidVideoSurfaceChooserImplTest,
+ InitializingWithFactoryCreatesOverlay) {
+ // Providing a factory at startup should result in a switch to overlay. It
+ // should not switch to SurfaceTexture initially, since pre-M requires it.
+ // Note that post-M (especially DS), it might be fine to start with ST. We
+ // just don't differentiate those cases yet in the impl.
+
+ // Initially, there should be no callback into |client_|, since we haven't
+ // told |helper_| that the overlay is ready. It should, however, request the
+ // overlay from |factory_|.
+ EXPECT_CALL(*factory_, MockCreateOverlay());
+ StartHelper(std::move(factory_));
+}
+
+TEST_F(AndroidVideoSurfaceChooserImplTest,
+ NullInitialOverlayUsesSurfaceTexture) {
+ // If we provide a factory, but it fails to create an overlay, then |client_|
+ // should be notified to use a surface texture.
+
+ EXPECT_CALL(*factory_, MockCreateOverlay());
+ EXPECT_CALL(client_, UseSurfaceTexture());
+ // Replacing the overlay with null will destroy it.
+ destruction_observer_->ExpectDestruction();
+ factory_->SetOverlay(nullptr);
+ StartHelper(std::move(factory_));
+}
+
+TEST_F(AndroidVideoSurfaceChooserImplTest,
+ FailedInitialOverlayUsesSurfaceTexture) {
+ // If we provide a factory, but the overlay that it provides returns 'failed',
+ // then |client_| should use surface texture.
+ EXPECT_CALL(*factory_, MockCreateOverlay());
+ StartHelper(std::move(factory_));
+
+ testing::Mock::VerifyAndClearExpectations(&client_);
+ testing::Mock::VerifyAndClearExpectations(factory_weak_.get());
+
+ // The overlay may be destroyed at any time after we send OverlayFailed. It
+ // doesn't have to be destroyed. We just care that it hasn't been destroyed
+ // before now.
+ destruction_observer_ = nullptr;
+ EXPECT_CALL(client_, UseSurfaceTexture());
+ overlay_callbacks_.OverlayFailed.Run();
+}
+
+TEST_F(AndroidVideoSurfaceChooserImplTest,
+ OnSurfaceDestroyedSendsNotification) {
+ // If |helper_| is notified about OnSurfaceDestroyed, then |client_| should
+ // also be notified.
+
+ EXPECT_CALL(*factory_, MockCreateOverlay());
+ StartHelper(std::move(factory_));
+ EXPECT_CALL(client_, UseOverlay(NotNull()));
+ overlay_callbacks_.OverlayReady.Run();
+
+ testing::Mock::VerifyAndClearExpectations(&client_);
+ testing::Mock::VerifyAndClearExpectations(factory_weak_.get());
+
+ // Switch to a surface texture. OnSurfaceDestroyed should still be sent.
+ EXPECT_CALL(client_, UseSurfaceTexture());
+ helper_->ReplaceOverlayFactory(nullptr);
+ testing::Mock::VerifyAndClearExpectations(&client_);
+
+ EXPECT_CALL(client_, StopUsingOverlayImmediately(NotNull()));
+ overlay_callbacks_.SurfaceDestroyed.Run();
+}
+
+TEST_F(AndroidVideoSurfaceChooserImplTest,
+ OnSurfaceDestroyedSendsNotificationAfterSwitch) {
+ // This tests two things. First:
+ // If |helper_| is notified about OnSurfaceDestroyed, then |client_| should
+ // also be notified even if |helper_| has already told |client_| to transition
+ // to SurfaceTexture. It has no idea if |client_| has actually transitioned,
+ // so it has to notify it to stop immediately, in case it hasn't.
+ // Second:
+ // |helper_| should notify |client_| to switch to surface texture if it
+ // provided an overlay, and the factory is changed. This indicates that
+ // whoever provided the factory is revoking it, so we shouldn't be using
+ // overlays from that factory anymore.
+ // We specifically test overlay => no factory, since |helper_| could elide
+ // multiple calls to switch to surface texture.
+ //
+ // We test these together, since switching the factory is the only way we have
+ // to make |helper_| transition to SurfaceTexture without sending destroyed.
+
+ EXPECT_CALL(*factory_, MockCreateOverlay());
+ StartHelper(std::move(factory_));
+ EXPECT_CALL(client_, UseOverlay(NotNull()));
+ overlay_callbacks_.OverlayReady.Run();
+
+ testing::Mock::VerifyAndClearExpectations(&client_);
+ testing::Mock::VerifyAndClearExpectations(factory_weak_.get());
+
+ // Switch factories, to notify the client back to switch to SurfaceTexture.
+ EXPECT_CALL(client_, UseSurfaceTexture());
+ helper_->ReplaceOverlayFactory(nullptr);
+ testing::Mock::VerifyAndClearExpectations(&client_);
+
+ // Destroy the original surface.
+ EXPECT_CALL(client_, StopUsingOverlayImmediately(NotNull()));
+ overlay_callbacks_.SurfaceDestroyed.Run();
+}
+
+TEST_F(AndroidVideoSurfaceChooserImplTest, NullLaterOverlayUsesSurfaceTexture) {
+ // If an overlay factory is provided after startup that returns a null overlay
+ // from CreateOverlay, |helper_| should, at most, notify |client_| to use
+ // SurfaceTexture zero or more times.
+
+ // Start with SurfaceTexture.
+ EXPECT_CALL(client_, UseSurfaceTexture());
+ StartHelper(nullptr);
+ testing::Mock::VerifyAndClearExpectations(&client_);
+
+ // Provide a factory that will return a null overlay.
+ EXPECT_CALL(*factory_, MockCreateOverlay());
+ EXPECT_CALL(client_, UseSurfaceTexture()).Times(AnyNumber());
+ helper_->ReplaceOverlayFactory(std::move(factory_));
+ factory_weak_->SetOverlay(nullptr);
+}
+
+TEST_F(AndroidVideoSurfaceChooserImplTest, FailedLaterOverlayDoesNothing) {
+ // If we send an overlay factory that returns an overlay, and that overlay
+ // fails, then the client should not be notified except for zero or more
+ // callbacks to switch to surface texture.
+
+ // Start with SurfaceTexture.
+ EXPECT_CALL(client_, UseSurfaceTexture());
+ StartHelper(nullptr);
+ testing::Mock::VerifyAndClearExpectations(&client_);
+
+ // Provide a factory.
+ EXPECT_CALL(*factory_, MockCreateOverlay());
+ EXPECT_CALL(client_, UseSurfaceTexture()).Times(AnyNumber());
+ helper_->ReplaceOverlayFactory(std::move(factory_));
+ testing::Mock::VerifyAndClearExpectations(&client_);
+
+ // Fail the overlay. We don't care if it's destroyed after that, as long as
+ // it hasn't been destroyed yet.
+ destruction_observer_ = nullptr;
+ overlay_callbacks_.OverlayFailed.Run();
+}
+
+TEST_F(AndroidVideoSurfaceChooserImplTest,
+ SuccessfulLaterOverlayNotifiesClient) {
+ // |client_| is notified if we provide a factory that gets an overlay.
+
+ // Start with SurfaceTexture.
+ EXPECT_CALL(client_, UseSurfaceTexture());
+ StartHelper(nullptr);
+ testing::Mock::VerifyAndClearExpectations(&client_);
+
+ // Provide a factory. |helper_| should try to create an overlay. We don't
+ // care if a call to UseSurfaceTexture is elided or not. Note that AVDA will
+ // ignore duplicate calls anyway (MultipleSurfaceTextureCallbacksAreIgnored).
+ EXPECT_CALL(*factory_, MockCreateOverlay());
+ EXPECT_CALL(client_, UseSurfaceTexture()).Times(AnyNumber());
+ helper_->ReplaceOverlayFactory(std::move(factory_));
+ testing::Mock::VerifyAndClearExpectations(&client_);
+ testing::Mock::VerifyAndClearExpectations(factory_weak_.get());
+
+ // Notify |helper_| that the overlay is ready.
+ EXPECT_CALL(client_, UseOverlay(NotNull()));
+ overlay_callbacks_.OverlayReady.Run();
+}
+
+} // namespace media

Powered by Google App Engine
This is Rietveld 408576698