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/android_video_surface_chooser_impl.h" |
| 6 |
| 7 #include <stdint.h> |
| 8 |
| 9 #include <memory> |
| 10 |
| 11 #include "base/bind.h" |
| 12 #include "base/logging.h" |
| 13 #include "base/memory/ptr_util.h" |
| 14 #include "media/base/android/android_overlay_factory.h" |
| 15 #include "media/base/android/mock_android_overlay.h" |
| 16 #include "testing/gmock/include/gmock/gmock.h" |
| 17 #include "testing/gtest/include/gtest/gtest.h" |
| 18 |
| 19 using ::testing::_; |
| 20 using ::testing::AnyNumber; |
| 21 using ::testing::NiceMock; |
| 22 using ::testing::NotNull; |
| 23 using ::testing::Return; |
| 24 using ::testing::StrictMock; |
| 25 |
| 26 namespace { |
| 27 using ::media::AndroidOverlay; |
| 28 using ::media::AndroidOverlayFactory; |
| 29 using ::media::MockAndroidOverlay; |
| 30 |
| 31 class MockClient { |
| 32 public: |
| 33 MOCK_METHOD1(UseOverlay, void(AndroidOverlay*)); |
| 34 |
| 35 void UseOverlayImpl(std::unique_ptr<AndroidOverlay> overlay) { |
| 36 UseOverlay(overlay.get()); |
| 37 |
| 38 // Also take ownership of the overlay, so that it's not destroyed. |
| 39 overlay_ = std::move(overlay); |
| 40 } |
| 41 |
| 42 // Note that this won't clear |overlay_|, which is helpful. |
| 43 MOCK_METHOD0(UseSurfaceTexture, void(void)); |
| 44 MOCK_METHOD1(StopUsingOverlayImmediately, void(AndroidOverlay*)); |
| 45 |
| 46 private: |
| 47 std::unique_ptr<AndroidOverlay> overlay_; |
| 48 }; |
| 49 |
| 50 // Mock factory which will return one overlay. |
| 51 class MockAndroidOverlayFactory : public AndroidOverlayFactory { |
| 52 public: |
| 53 MockAndroidOverlayFactory() |
| 54 : overlay_(base::MakeUnique<MockAndroidOverlay>()), |
| 55 weak_this_factory_(this) {} |
| 56 |
| 57 // Called by CreateOverlay. |
| 58 MOCK_METHOD0(MockCreateOverlay, void()); |
| 59 |
| 60 std::unique_ptr<AndroidOverlay> CreateOverlay( |
| 61 const AndroidOverlay::Config& config) override { |
| 62 MockCreateOverlay(); |
| 63 |
| 64 // Notify the overlay about the config that was used to create it. We |
| 65 // can't do this during overlay construction since we might want the |
| 66 // overlay to set test expectations. |
| 67 if (overlay_) |
| 68 overlay_->SetConfig(config); |
| 69 |
| 70 return std::move(overlay_); |
| 71 } |
| 72 |
| 73 // Return the overlay, if we still own it. One the client creates an |
| 74 // overlay, we'll re-assign ownership. |
| 75 MockAndroidOverlay* overlay() { return overlay_.get(); } |
| 76 |
| 77 // Set the overlay that we'll provide next, or nullptr. |
| 78 void SetOverlay(std::unique_ptr<MockAndroidOverlay> overlay) { |
| 79 overlay_ = std::move(overlay); |
| 80 } |
| 81 |
| 82 base::WeakPtr<MockAndroidOverlayFactory> GetWeakPtr() { |
| 83 return weak_this_factory_.GetWeakPtr(); |
| 84 } |
| 85 |
| 86 private: |
| 87 std::unique_ptr<MockAndroidOverlay> overlay_; |
| 88 |
| 89 base::WeakPtrFactory<MockAndroidOverlayFactory> weak_this_factory_; |
| 90 }; |
| 91 } // namespace |
| 92 |
| 93 namespace media { |
| 94 |
| 95 // Unit tests for AndroidVideoSurfaceChooserImpl |
| 96 class AndroidVideoSurfaceChooserImplTest : public testing::Test { |
| 97 public: |
| 98 ~AndroidVideoSurfaceChooserImplTest() override {} |
| 99 |
| 100 void SetUp() override { |
| 101 chooser_ = base::MakeUnique<AndroidVideoSurfaceChooserImpl>(); |
| 102 factory_ = base::MakeUnique<NiceMock<MockAndroidOverlayFactory>>(); |
| 103 factory_weak_ = factory_->GetWeakPtr(); |
| 104 |
| 105 // We create a destruction observer. By default, the overlay must not be |
| 106 // destroyed until the test completes. Of course, the test may ask the |
| 107 // observer to expect something else. |
| 108 destruction_observer_ = factory_->overlay()->CreateDestructionObserver(); |
| 109 destruction_observer_->DoNotAllowDestruction(); |
| 110 overlay_callbacks_ = factory_->overlay()->GetCallbacks(); |
| 111 } |
| 112 |
| 113 void TearDown() override { |
| 114 // If we get this far, the assume that whatever |destruction_observer_| |
| 115 // was looking for should have already happened. We don't want the |
| 116 // lifetime of the observer to matter with respect to the overlay when |
| 117 // checking expectations. |
| 118 // Note that it might already be null. |
| 119 destruction_observer_ = nullptr; |
| 120 } |
| 121 |
| 122 void StartHelper(std::unique_ptr<MockAndroidOverlayFactory> factory) { |
| 123 chooser_->Initialize( |
| 124 base::Bind(&MockClient::UseOverlayImpl, base::Unretained(&client_)), |
| 125 base::Bind(&MockClient::UseSurfaceTexture, base::Unretained(&client_)), |
| 126 base::Bind(&MockClient::StopUsingOverlayImmediately, |
| 127 base::Unretained(&client_)), |
| 128 std::move(factory)); |
| 129 } |
| 130 |
| 131 std::unique_ptr<AndroidVideoSurfaceChooserImpl> chooser_; |
| 132 StrictMock<MockClient> client_; |
| 133 std::unique_ptr<NiceMock<MockAndroidOverlayFactory>> factory_; |
| 134 base::WeakPtr<MockAndroidOverlayFactory> factory_weak_; |
| 135 |
| 136 // Callbacks to control the overlay that will be vended by |factory_| |
| 137 MockAndroidOverlay::Callbacks overlay_callbacks_; |
| 138 |
| 139 std::unique_ptr<MockAndroidOverlay::DestructionObserver> |
| 140 destruction_observer_; |
| 141 }; |
| 142 |
| 143 TEST_F(AndroidVideoSurfaceChooserImplTest, |
| 144 InitializeWithoutFactoryUsesSurfaceTexture) { |
| 145 // Calling Initialize() with no factory should result in a callback to use |
| 146 // surface texture. |
| 147 EXPECT_CALL(client_, UseSurfaceTexture()); |
| 148 StartHelper(nullptr); |
| 149 } |
| 150 |
| 151 TEST_F(AndroidVideoSurfaceChooserImplTest, ProvideInitialOverlaySuccessfully) { |
| 152 // Providing a factory at startup should result in a switch to overlay. It |
| 153 // should not switch to SurfaceTexture initially, since pre-M requires it. |
| 154 // Note that post-M (especially DS), it might be fine to start with ST. We |
| 155 // just don't differentiate those cases yet in the impl. |
| 156 |
| 157 EXPECT_CALL(client_, UseSurfaceTexture()).Times(0); |
| 158 StartHelper(std::move(factory_)); |
| 159 |
| 160 // Notify the chooser that the overlay is ready. Expect that |client_| will |
| 161 // be told to use it. |
| 162 EXPECT_CALL(client_, UseOverlay(NotNull())); |
| 163 overlay_callbacks_.OverlayReady.Run(); |
| 164 } |
| 165 |
| 166 TEST_F(AndroidVideoSurfaceChooserImplTest, |
| 167 InitializingWithFactoryCreatesOverlay) { |
| 168 // Providing a factory at startup should result in a switch to overlay. It |
| 169 // should not switch to SurfaceTexture initially, since pre-M requires it. |
| 170 // Note that post-M (especially DS), it might be fine to start with ST. We |
| 171 // just don't differentiate those cases yet in the impl. |
| 172 |
| 173 // Initially, there should be no callback into |client_|, since we haven't |
| 174 // told |chooser_| that the overlay is ready. It should, however, request the |
| 175 // overlay from |factory_|. |
| 176 EXPECT_CALL(*factory_, MockCreateOverlay()); |
| 177 StartHelper(std::move(factory_)); |
| 178 } |
| 179 |
| 180 TEST_F(AndroidVideoSurfaceChooserImplTest, |
| 181 NullInitialOverlayUsesSurfaceTexture) { |
| 182 // If we provide a factory, but it fails to create an overlay, then |client_| |
| 183 // should be notified to use a surface texture. |
| 184 |
| 185 EXPECT_CALL(*factory_, MockCreateOverlay()); |
| 186 EXPECT_CALL(client_, UseSurfaceTexture()); |
| 187 // Replacing the overlay with null will destroy it. |
| 188 destruction_observer_->ExpectDestruction(); |
| 189 factory_->SetOverlay(nullptr); |
| 190 StartHelper(std::move(factory_)); |
| 191 } |
| 192 |
| 193 TEST_F(AndroidVideoSurfaceChooserImplTest, |
| 194 FailedInitialOverlayUsesSurfaceTexture) { |
| 195 // If we provide a factory, but the overlay that it provides returns 'failed', |
| 196 // then |client_| should use surface texture. |
| 197 EXPECT_CALL(*factory_, MockCreateOverlay()); |
| 198 StartHelper(std::move(factory_)); |
| 199 |
| 200 testing::Mock::VerifyAndClearExpectations(&client_); |
| 201 testing::Mock::VerifyAndClearExpectations(factory_weak_.get()); |
| 202 |
| 203 // The overlay may be destroyed at any time after we send OverlayFailed. It |
| 204 // doesn't have to be destroyed. We just care that it hasn't been destroyed |
| 205 // before now. |
| 206 destruction_observer_ = nullptr; |
| 207 EXPECT_CALL(client_, UseSurfaceTexture()); |
| 208 overlay_callbacks_.OverlayFailed.Run(); |
| 209 } |
| 210 |
| 211 TEST_F(AndroidVideoSurfaceChooserImplTest, |
| 212 OnSurfaceDestroyedSendsNotification) { |
| 213 // If |chooser_| is notified about OnSurfaceDestroyed, then |client_| should |
| 214 // also be notified. |
| 215 |
| 216 EXPECT_CALL(*factory_, MockCreateOverlay()); |
| 217 StartHelper(std::move(factory_)); |
| 218 EXPECT_CALL(client_, UseOverlay(NotNull())); |
| 219 overlay_callbacks_.OverlayReady.Run(); |
| 220 |
| 221 testing::Mock::VerifyAndClearExpectations(&client_); |
| 222 testing::Mock::VerifyAndClearExpectations(factory_weak_.get()); |
| 223 |
| 224 // Switch to a surface texture. OnSurfaceDestroyed should still be sent. |
| 225 EXPECT_CALL(client_, UseSurfaceTexture()); |
| 226 chooser_->ReplaceOverlayFactory(nullptr); |
| 227 testing::Mock::VerifyAndClearExpectations(&client_); |
| 228 |
| 229 EXPECT_CALL(client_, StopUsingOverlayImmediately(NotNull())); |
| 230 overlay_callbacks_.SurfaceDestroyed.Run(); |
| 231 } |
| 232 |
| 233 TEST_F(AndroidVideoSurfaceChooserImplTest, |
| 234 OnSurfaceDestroyedSendsNotificationAfterSwitch) { |
| 235 // This tests two things. First: |
| 236 // If |chooser_| is notified about OnSurfaceDestroyed, then |client_| should |
| 237 // also be notified even if |chooser_| has already told |client_| to |
| 238 // transition to SurfaceTexture. It has no idea if |client_| has actually |
| 239 // transitioned, so it has to notify it to stop immediately, in case it |
| 240 // hasn't. Second: |chooser_| should notify |client_| to switch to surface |
| 241 // texture if it provided an overlay, and the factory is changed. This |
| 242 // indicates that whoever provided the factory is revoking it, so we shouldn't |
| 243 // be using overlays from that factory anymore. We specifically test overlay |
| 244 // => no factory, since |chooser_| could elide multiple calls to switch to |
| 245 // surface texture. |
| 246 // |
| 247 // We test these together, since switching the factory is the only way we have |
| 248 // to make |chooser_| transition to SurfaceTexture without sending destroyed. |
| 249 |
| 250 EXPECT_CALL(*factory_, MockCreateOverlay()); |
| 251 StartHelper(std::move(factory_)); |
| 252 EXPECT_CALL(client_, UseOverlay(NotNull())); |
| 253 overlay_callbacks_.OverlayReady.Run(); |
| 254 |
| 255 testing::Mock::VerifyAndClearExpectations(&client_); |
| 256 testing::Mock::VerifyAndClearExpectations(factory_weak_.get()); |
| 257 |
| 258 // Switch factories, to notify the client back to switch to SurfaceTexture. |
| 259 EXPECT_CALL(client_, UseSurfaceTexture()); |
| 260 chooser_->ReplaceOverlayFactory(nullptr); |
| 261 testing::Mock::VerifyAndClearExpectations(&client_); |
| 262 |
| 263 // Destroy the original surface. |
| 264 EXPECT_CALL(client_, StopUsingOverlayImmediately(NotNull())); |
| 265 overlay_callbacks_.SurfaceDestroyed.Run(); |
| 266 } |
| 267 |
| 268 TEST_F(AndroidVideoSurfaceChooserImplTest, NullLaterOverlayUsesSurfaceTexture) { |
| 269 // If an overlay factory is provided after startup that returns a null overlay |
| 270 // from CreateOverlay, |chooser_| should, at most, notify |client_| to use |
| 271 // SurfaceTexture zero or more times. |
| 272 |
| 273 // Start with SurfaceTexture. |
| 274 EXPECT_CALL(client_, UseSurfaceTexture()); |
| 275 StartHelper(nullptr); |
| 276 testing::Mock::VerifyAndClearExpectations(&client_); |
| 277 |
| 278 // Provide a factory that will return a null overlay. |
| 279 EXPECT_CALL(*factory_, MockCreateOverlay()); |
| 280 EXPECT_CALL(client_, UseSurfaceTexture()).Times(AnyNumber()); |
| 281 chooser_->ReplaceOverlayFactory(std::move(factory_)); |
| 282 factory_weak_->SetOverlay(nullptr); |
| 283 } |
| 284 |
| 285 TEST_F(AndroidVideoSurfaceChooserImplTest, FailedLaterOverlayDoesNothing) { |
| 286 // If we send an overlay factory that returns an overlay, and that overlay |
| 287 // fails, then the client should not be notified except for zero or more |
| 288 // callbacks to switch to surface texture. |
| 289 |
| 290 // Start with SurfaceTexture. |
| 291 EXPECT_CALL(client_, UseSurfaceTexture()); |
| 292 StartHelper(nullptr); |
| 293 testing::Mock::VerifyAndClearExpectations(&client_); |
| 294 |
| 295 // Provide a factory. |
| 296 EXPECT_CALL(*factory_, MockCreateOverlay()); |
| 297 EXPECT_CALL(client_, UseSurfaceTexture()).Times(AnyNumber()); |
| 298 chooser_->ReplaceOverlayFactory(std::move(factory_)); |
| 299 testing::Mock::VerifyAndClearExpectations(&client_); |
| 300 |
| 301 // Fail the overlay. We don't care if it's destroyed after that, as long as |
| 302 // it hasn't been destroyed yet. |
| 303 destruction_observer_ = nullptr; |
| 304 overlay_callbacks_.OverlayFailed.Run(); |
| 305 } |
| 306 |
| 307 TEST_F(AndroidVideoSurfaceChooserImplTest, |
| 308 SuccessfulLaterOverlayNotifiesClient) { |
| 309 // |client_| is notified if we provide a factory that gets an overlay. |
| 310 |
| 311 // Start with SurfaceTexture. |
| 312 EXPECT_CALL(client_, UseSurfaceTexture()); |
| 313 StartHelper(nullptr); |
| 314 testing::Mock::VerifyAndClearExpectations(&client_); |
| 315 |
| 316 // Provide a factory. |chooser_| should try to create an overlay. We don't |
| 317 // care if a call to UseSurfaceTexture is elided or not. Note that AVDA will |
| 318 // ignore duplicate calls anyway (MultipleSurfaceTextureCallbacksAreIgnored). |
| 319 EXPECT_CALL(*factory_, MockCreateOverlay()); |
| 320 EXPECT_CALL(client_, UseSurfaceTexture()).Times(AnyNumber()); |
| 321 chooser_->ReplaceOverlayFactory(std::move(factory_)); |
| 322 testing::Mock::VerifyAndClearExpectations(&client_); |
| 323 testing::Mock::VerifyAndClearExpectations(factory_weak_.get()); |
| 324 |
| 325 // Notify |chooser_| that the overlay is ready. |
| 326 EXPECT_CALL(client_, UseOverlay(NotNull())); |
| 327 overlay_callbacks_.OverlayReady.Run(); |
| 328 } |
| 329 |
| 330 } // namespace media |
OLD | NEW |