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

Side by Side Diff: media/gpu/android_video_decode_accelerator_unittest.cc

Issue 2813303003: Add AndroidVideoSurfaceChooser to manage overlays. (Closed)
Patch Set: gn fixes for non-android 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/gpu/android_video_decode_accelerator.h" 5 #include "media/gpu/android_video_decode_accelerator.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <memory> 9 #include <memory>
10 10
11 #include "base/android/jni_android.h" 11 #include "base/android/jni_android.h"
12 #include "base/bind.h" 12 #include "base/bind.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/memory/ptr_util.h"
15 #include "base/memory/weak_ptr.h"
14 #include "base/message_loop/message_loop.h" 16 #include "base/message_loop/message_loop.h"
15 #include "base/run_loop.h" 17 #include "base/run_loop.h"
16 #include "base/threading/thread_task_runner_handle.h" 18 #include "base/threading/thread_task_runner_handle.h"
17 #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" 19 #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h"
18 #include "media/base/android/media_codec_util.h" 20 #include "media/base/android/media_codec_util.h"
19 #include "media/base/android/media_jni_registrar.h" 21 #include "media/base/android/media_jni_registrar.h"
22 #include "media/base/android/mock_android_overlay.h"
23 #include "media/base/android/mock_media_codec_bridge.h"
20 #include "media/gpu/android_video_decode_accelerator.h" 24 #include "media/gpu/android_video_decode_accelerator.h"
21 #include "media/gpu/avda_codec_allocator.h" 25 #include "media/gpu/avda_codec_allocator.h"
26 #include "media/gpu/avda_overlay_helper.h"
22 #include "media/video/picture.h" 27 #include "media/video/picture.h"
23 #include "media/video/video_decode_accelerator.h" 28 #include "media/video/video_decode_accelerator.h"
24 #include "testing/gmock/include/gmock/gmock.h" 29 #include "testing/gmock/include/gmock/gmock.h"
25 #include "testing/gtest/include/gtest/gtest.h" 30 #include "testing/gtest/include/gtest/gtest.h"
31 #include "ui/gl/android/surface_texture.h"
26 #include "ui/gl/gl_context.h" 32 #include "ui/gl/gl_context.h"
27 #include "ui/gl/gl_surface.h" 33 #include "ui/gl/gl_surface.h"
28 #include "ui/gl/init/gl_factory.h" 34 #include "ui/gl/init/gl_factory.h"
29 35
30 using ::testing::_; 36 using ::testing::_;
31 using ::testing::NiceMock; 37 using ::testing::NiceMock;
38 using ::testing::NotNull;
39 using ::testing::Return;
40 using ::testing::StrictMock;
32 41
33 namespace media { 42 namespace media {
34 namespace { 43 namespace {
35 44
36 #define SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE() \ 45 #define SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE() \
37 do { \ 46 do { \
38 if (!MediaCodecUtil::IsMediaCodecAvailable()) \ 47 if (!MediaCodecUtil::IsMediaCodecAvailable()) \
39 return; \ 48 return; \
40 } while (false) 49 } while (false)
41 50
42 bool MakeContextCurrent() { 51 bool MakeContextCurrent() {
43 return true; 52 return true;
44 } 53 }
45 54
46 base::WeakPtr<gpu::gles2::GLES2Decoder> GetGLES2Decoder( 55 base::WeakPtr<gpu::gles2::GLES2Decoder> GetGLES2Decoder(
47 const base::WeakPtr<gpu::gles2::GLES2Decoder>& decoder) { 56 const base::WeakPtr<gpu::gles2::GLES2Decoder>& decoder) {
48 return decoder; 57 return decoder;
49 } 58 }
50 59
51 ACTION(PostNullCodec) {
52 base::ThreadTaskRunnerHandle::Get()->PostTask(
53 FROM_HERE, base::Bind(&media::AVDACodecAllocatorClient::OnCodecConfigured,
54 arg0, nullptr));
55 }
56
57 } // namespace 60 } // namespace
58 61
59 class MockVDAClient : public VideoDecodeAccelerator::Client {
60 public:
61 MOCK_METHOD1(NotifyInitializationComplete, void(bool));
62 MOCK_METHOD5(
63 ProvidePictureBuffers,
64 void(uint32_t, VideoPixelFormat, uint32_t, const gfx::Size&, uint32_t));
65 MOCK_METHOD1(DismissPictureBuffer, void(int32_t));
66 MOCK_METHOD1(PictureReady, void(const Picture&));
67 MOCK_METHOD1(NotifyEndOfBitstreamBuffer, void(int32_t));
68 MOCK_METHOD0(NotifyFlushDone, void());
69 MOCK_METHOD0(NotifyResetDone, void());
70 MOCK_METHOD1(NotifyError, void(VideoDecodeAccelerator::Error));
71 };
72
73 class MockCodecAllocator : public AVDACodecAllocator {
74 public:
75 MOCK_METHOD2(CreateMediaCodecAsync,
76 void(base::WeakPtr<AVDACodecAllocatorClient>,
77 scoped_refptr<CodecConfig>));
78 };
79
80 class AndroidVideoDecodeAcceleratorTest : public testing::Test { 62 class AndroidVideoDecodeAcceleratorTest : public testing::Test {
81 public: 63 public:
64 class MockVDAClient : public VideoDecodeAccelerator::Client {
65 public:
66 MOCK_METHOD1(NotifyInitializationComplete, void(bool));
67 MOCK_METHOD5(
68 ProvidePictureBuffers,
69 void(uint32_t, VideoPixelFormat, uint32_t, const gfx::Size&, uint32_t));
70 MOCK_METHOD1(DismissPictureBuffer, void(int32_t));
71 MOCK_METHOD1(PictureReady, void(const Picture&));
72 MOCK_METHOD1(NotifyEndOfBitstreamBuffer, void(int32_t));
73 MOCK_METHOD0(NotifyFlushDone, void());
74 MOCK_METHOD0(NotifyResetDone, void());
75 MOCK_METHOD1(NotifyError, void(VideoDecodeAccelerator::Error));
76 };
77
78 // Codec allocator that lets you count calls on Mock* methods, and also
79 // lets you answer the codec.
80 class FakeCodecAllocator : public StrictMock<AVDACodecAllocator> {
81 public:
82 // These are called with some parameters of the codec config by our
83 // implementatin of their respective functions. This allows tests to set
84 // expectations on them.
85 MOCK_METHOD2(MockCreateMediaCodecSync,
86 void(AndroidOverlay*, gl::SurfaceTexture*));
87 MOCK_METHOD2(MockCreateMediaCodecAsync,
88 void(AndroidOverlay*, gl::SurfaceTexture*));
89
90 // Note that this doesn't exactly match the signature, since unique_ptr
91 // doesn't work. plus, we expand |surface_bundle| a bit to make it more
92 // convenient to set expectations.
93 MOCK_METHOD3(MockReleaseMediaCodec,
94 void(MediaCodecBridge*, AndroidOverlay*, gl::SurfaceTexture*));
95
96 std::unique_ptr<MediaCodecBridge> CreateMediaCodecSync(
97 scoped_refptr<CodecConfig> codec_config) override {
98 MockCreateMediaCodecSync(
99 codec_config->surface_bundle->overlay.get(),
100 codec_config->surface_bundle->surface_texture.get());
101
102 CopyCodecAllocParams(codec_config);
103
104 std::unique_ptr<MockMediaCodecBridge> codec;
105 if (allow_sync_creation)
106 codec = base::MakeUnique<MockMediaCodecBridge>();
107
108 if (codec)
109 most_recent_codec_ = codec->GetWeakPtr();
110 else
111 most_recent_codec_ = nullptr;
112
113 return std::move(codec);
114 }
115
116 void CreateMediaCodecAsync(base::WeakPtr<AVDACodecAllocatorClient> client,
117 scoped_refptr<CodecConfig> config) override {
118 // Clear |most_recent_codec_| until somebody calls Provide*CodecAsync().
119 most_recent_codec_ = nullptr;
120 CopyCodecAllocParams(config);
121 client_ = client;
122
123 MockCreateMediaCodecAsync(most_recent_overlay(),
124 most_recent_surface_texture());
125 }
126
127 void ReleaseMediaCodec(
128 std::unique_ptr<MediaCodecBridge> media_codec,
129 TaskType task_type,
130 const scoped_refptr<AVDASurfaceBundle>& surface_bundle) override {
131 MockReleaseMediaCodec(media_codec.get(), surface_bundle->overlay.get(),
132 surface_bundle->surface_texture.get());
133 }
134
135 // Provide AVDA with a mock codec.
136 void ProvideMockCodecAsync() {
137 // If AVDA hasn't requested a codec, then get mad.
138 ASSERT_TRUE(client_);
139 if (!client_)
140 return;
141
142 std::unique_ptr<MockMediaCodecBridge> codec =
143 base::MakeUnique<MockMediaCodecBridge>();
144 most_recent_codec_ = codec->GetWeakPtr();
145 client_->OnCodecConfigured(std::move(codec));
146 }
147
148 // Provide AVDA will a null codec.
149 void ProvideNullCodecAsync() {
150 // If AVDA hasn't requested a codec, then get mad.
151 ASSERT_TRUE(client_);
152 if (!client_)
153 return;
154
155 most_recent_codec_ = nullptr;
156 client_->OnCodecConfigured(nullptr);
157 }
158
159 // Return the most recent bundle that we've received for codec allocation.
160 scoped_refptr<AVDASurfaceBundle> most_recent_bundle() {
161 return most_recent_bundle_;
162 }
163
164 // Return the most recent codec that we provided, or null if it has been
165 // freed already.
166 MockMediaCodecBridge* most_recent_codec() {
167 return most_recent_codec_.get();
168 }
169
170 // Return the most recent overlay / etc. that we were given during codec
171 // allocation (sync or async).
172 AndroidOverlay* most_recent_overlay() { return most_recent_overlay_; }
173 gl::SurfaceTexture* most_recent_surface_texture() {
174 return most_recent_surface_texture_;
175 }
176
177 // Most recent codec that we've created via CreateMockCodec, since we have
178 // to assign ownership.
179 base::WeakPtr<MockMediaCodecBridge> most_recent_codec_;
180
181 // Most recent surface bundle that we've gotten during codec allocation.
182 // This should be the same as |config_->surface_bundle| initially, but AVDA
183 // might change it.
184 scoped_refptr<AVDASurfaceBundle> most_recent_bundle_;
185
186 // Most recent overlay provided during codec allocation.
187 AndroidOverlay* most_recent_overlay_ = nullptr;
188
189 // Most recent surface texture provided during codec allocation.
190 gl::SurfaceTexture* most_recent_surface_texture_ = nullptr;
191
192 // Should a call to CreateMediaCodecSync succeed?
193 bool allow_sync_creation = true;
194
195 private:
196 // Copy |config| and all of the parameters we care about. We don't leave
197 // them all in config, since AVDA could change them at any time.
198 void CopyCodecAllocParams(scoped_refptr<CodecConfig> config) {
199 config_ = config;
200 most_recent_bundle_ = config->surface_bundle;
201 most_recent_overlay_ = config->surface_bundle->overlay.get();
202
203 most_recent_surface_texture_ =
204 config->surface_bundle->surface_texture.get();
205 }
206
207 base::WeakPtr<AVDACodecAllocatorClient> client_;
208 scoped_refptr<CodecConfig> config_;
209 };
210
211 // Overlay helper that calls mocked functions to allow counting calls, but
212 // also records arguments. Note that gmock can't mock out unique_ptrs
213 // anyway, so we can't mock AVDAOverlayHelper directly.
214 class FakeOverlayHelper : public StrictMock<AVDAOverlayHelper> {
215 public:
216 FakeOverlayHelper() : weak_factory_(this) {}
217
218 // These are called by the real functions. You may set expectations on
219 // them if you like.
220 MOCK_METHOD0(MockStartup, void());
221 MOCK_METHOD0(MockOnOverlayFactory, void());
222
223 base::WeakPtr<FakeOverlayHelper> GetWeakPtr() {
224 return weak_factory_.GetWeakPtr();
225 }
226
227 void Startup(
228 const UseOverlayCB& use_overlay_cb,
229 const UseSurfaceTextureCB& use_surface_texture_cb,
230 const StopUsingOverlayImmediatelyCB& stop_immediately_cb,
231 std::unique_ptr<AndroidOverlayFactory> initial_factory) override {
232 MockStartup();
233
234 factory_ = std::move(initial_factory);
235 use_overlay_cb_ = use_overlay_cb;
236 use_surface_texture_cb_ = use_surface_texture_cb;
237 stop_immediately_cb_ = stop_immediately_cb;
238 }
239
240 void OnOverlayFactory(
241 std::unique_ptr<AndroidOverlayFactory> factory) override {
242 MockOnOverlayFactory();
243 factory_ = std::move(factory);
244 }
245
246 // Notify AVDA to use a surface texture.
247 void ProvideSurfaceTexture() {
248 use_surface_texture_cb_.Run();
249 base::RunLoop().RunUntilIdle();
250 }
251
252 void ProvideOverlay(std::unique_ptr<AndroidOverlay> overlay) {
253 use_overlay_cb_.Run(std::move(overlay));
254 base::RunLoop().RunUntilIdle();
255 }
256
257 void StopImmediately(AndroidOverlay* overlay) {
258 stop_immediately_cb_.Run(overlay);
259 base::RunLoop().RunUntilIdle();
260 }
261
262 UseOverlayCB use_overlay_cb_;
263 UseSurfaceTextureCB use_surface_texture_cb_;
264 StopUsingOverlayImmediatelyCB stop_immediately_cb_;
265
266 std::unique_ptr<AndroidOverlayFactory> factory_;
267
268 base::WeakPtrFactory<FakeOverlayHelper> weak_factory_;
269 };
DaleCurtis 2017/04/20 19:10:43 DISALLOW_COPY_AND_ASSIGN
liberato (no reviews please) 2017/04/20 22:01:39 Done, and elsewhere.
270
271 // We pick this profile since it's always supported.
272 AndroidVideoDecodeAcceleratorTest() : config_(H264PROFILE_BASELINE) {}
273
82 ~AndroidVideoDecodeAcceleratorTest() override {} 274 ~AndroidVideoDecodeAcceleratorTest() override {}
83 275
84 void SetUp() override { 276 void SetUp() override {
85 JNIEnv* env = base::android::AttachCurrentThread(); 277 JNIEnv* env = base::android::AttachCurrentThread();
86 RegisterJni(env); 278 RegisterJni(env);
87 279
280 main_task_runner_ = base::ThreadTaskRunnerHandle::Get();
281
88 gl::init::ShutdownGL(); 282 gl::init::ShutdownGL();
89 ASSERT_TRUE(gl::init::InitializeGLOneOff()); 283 ASSERT_TRUE(gl::init::InitializeGLOneOff());
90 surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size(16, 16)); 284 surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size(16, 16));
91 context_ = gl::init::CreateGLContext(nullptr, surface_.get(), 285 context_ = gl::init::CreateGLContext(nullptr, surface_.get(),
92 gl::GLContextAttribs()); 286 gl::GLContextAttribs());
93 context_->MakeCurrent(surface_.get()); 287 context_->MakeCurrent(surface_.get());
94 288
95 vda_.reset(new AndroidVideoDecodeAccelerator( 289 helper_that_is_usually_null_ = base::MakeUnique<FakeOverlayHelper>();
96 &codec_allocator_, base::Bind(&MakeContextCurrent), 290 helper_ = helper_that_is_usually_null_->GetWeakPtr();
97 base::Bind(&GetGLES2Decoder, gl_decoder_.AsWeakPtr()))); 291
292 platform_config_.sdk_int = base::android::SDK_VERSION_MARSHMALLOW;
293 platform_config_.allow_setsurface = true;
294 platform_config_.force_deferred_surface_creation = false;
295
296 // By default, allow deferred init.
297 config_.is_deferred_initialization_allowed = true;
298 }
299
300 // Create and initialize AVDA with |config_|, and return the result.
301 bool InitializeAVDA() {
302 // Because VDA has a custom deleter, we must assign it to |vda_| carefully.
303 AndroidVideoDecodeAccelerator* avda = new AndroidVideoDecodeAccelerator(
304 &codec_allocator_, std::move(helper_that_is_usually_null_),
305 base::Bind(&MakeContextCurrent),
306 base::Bind(&GetGLES2Decoder, gl_decoder_.AsWeakPtr()),
307 &platform_config_);
308 avda_ = avda->GetWeakPtr();
309 vda_.reset(avda);
310
311 bool result = vda_->Initialize(config_, &client_);
312 base::RunLoop().RunUntilIdle();
313 return result;
314 }
315
316 // Initialize |vda_|, providing a new surface for it. You may get the surface
317 // by asking |codec_allocator_|.
318 void InitializeAVDAWithOverlay() {
319 EXPECT_CALL(*helper_, MockStartup());
320
321 config_.surface_id = 123;
322 ASSERT_TRUE(InitializeAVDA());
323 base::RunLoop().RunUntilIdle();
324 ASSERT_TRUE(helper_->factory_ != nullptr);
325
326 // Have the factory provide an overlay, and verify that codec creation is
327 // provided with that overlay.
328 std::unique_ptr<MockAndroidOverlay> overlay =
329 base::MakeUnique<MockAndroidOverlay>();
330 // Set the expectations first, since ProvideOverlay might cause callbacks.
331 EXPECT_CALL(codec_allocator_,
332 MockCreateMediaCodecAsync(overlay.get(), nullptr));
333 helper_->ProvideOverlay(std::move(overlay));
334
335 // Provide the codec so that we can check if it's freed properly.
336 EXPECT_CALL(client_, NotifyInitializationComplete(true));
337 codec_allocator_.ProvideMockCodecAsync();
338 base::RunLoop().RunUntilIdle();
339 }
340
341 void InitializeAVDAWithSurfaceTexture() {
342 EXPECT_CALL(*helper_, MockStartup());
343
344 ASSERT_TRUE(InitializeAVDA());
345 base::RunLoop().RunUntilIdle();
346 // We do not expect a factory, since we are using SurfaceTexture.
347 ASSERT_TRUE(helper_->factory_ == nullptr);
348
349 // Set the expectations first, since ProvideOverlay might cause callbacks.
350 EXPECT_CALL(codec_allocator_,
351 MockCreateMediaCodecAsync(nullptr, NotNull()));
352 helper_->ProvideSurfaceTexture();
353
354 // Provide the codec so that we can check if it's freed properly.
355 EXPECT_CALL(client_, NotifyInitializationComplete(true));
356 codec_allocator_.ProvideMockCodecAsync();
357 base::RunLoop().RunUntilIdle();
358 }
359
360 // Set whether HasUnrendereredPictureBuffers will return true or false.
361 // TODO(liberato): We can't actually do this yet. It turns out to be okay,
362 // because AVDA doesn't actually SetSurface before DequeueOutput. It could do
363 // so, though, if there aren't unrendered buffers. Should AVDA ever start
364 // switching surfaces immediately upon receiving them, rather than waiting for
365 // DequeueOutput, then we'll want to be able to indicate that it has
366 // unrendered pictures to prevent that behavior.
367 void SetHasUnrenderedPictureBuffers(bool flag) {}
368
369 // Tell |avda_| to switch surfaces to its incoming surface. This is a method
370 // since we're a friend of AVDA, and the tests are subclasses. It's also
371 // somewhat hacky, but much less hacky than trying to run it via a timer.
372 void LetAVDAUpdateSurface() {
373 SetHasUnrenderedPictureBuffers(false);
374 avda_->DequeueOutput();
98 } 375 }
99 376
100 base::MessageLoop message_loop_; 377 base::MessageLoop message_loop_;
101 scoped_refptr<gl::GLSurface> surface_; 378 scoped_refptr<gl::GLSurface> surface_;
102 scoped_refptr<gl::GLContext> context_; 379 scoped_refptr<gl::GLContext> context_;
380 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
103 NiceMock<gpu::gles2::MockGLES2Decoder> gl_decoder_; 381 NiceMock<gpu::gles2::MockGLES2Decoder> gl_decoder_;
104 NiceMock<MockVDAClient> client_; 382 StrictMock<MockVDAClient> client_;
105 NiceMock<MockCodecAllocator> codec_allocator_; 383 FakeCodecAllocator codec_allocator_;
384 VideoDecodeAccelerator::Config config_;
385
386 AndroidVideoDecodeAccelerator::PlatformConfig platform_config_;
387
388 // We maintain a weak ref to this since AVDA owns it.
389 base::WeakPtr<FakeOverlayHelper> helper_;
106 390
107 // This must be a unique pointer to a VDA, not an AVDA, to ensure the 391 // This must be a unique pointer to a VDA, not an AVDA, to ensure the
108 // the default_delete specialization that calls Destroy() will be used. 392 // the default_delete specialization that calls Destroy() will be used.
109 std::unique_ptr<VideoDecodeAccelerator> vda_; 393 std::unique_ptr<VideoDecodeAccelerator> vda_;
394
395 // Weak ptr to |vda_| as an AVDA.
396 base::WeakPtr<AndroidVideoDecodeAccelerator> avda_;
397
398 private:
399 // This is the object that |helper_| points to, or nullptr once we assign
400 // ownership to AVDA.
401 std::unique_ptr<FakeOverlayHelper> helper_that_is_usually_null_;
110 }; 402 };
111 403
112 TEST_F(AndroidVideoDecodeAcceleratorTest, ConfigureUnsupportedCodec) { 404 TEST_F(AndroidVideoDecodeAcceleratorTest, ConfigureUnsupportedCodec) {
113 SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE(); 405 SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE();
114 406
115 ASSERT_FALSE(vda_->Initialize( 407 config_ = VideoDecodeAccelerator::Config(VIDEO_CODEC_PROFILE_UNKNOWN);
116 VideoDecodeAccelerator::Config(VIDEO_CODEC_PROFILE_UNKNOWN), &client_)); 408 ASSERT_FALSE(InitializeAVDA());
117 } 409 }
118 410
119 TEST_F(AndroidVideoDecodeAcceleratorTest, ConfigureSupportedCodec) { 411 TEST_F(AndroidVideoDecodeAcceleratorTest,
120 SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE(); 412 ConfigureSupportedCodecSynchronously) {
121 413 SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE();
122 // H264 is always supported by AVDA. 414
123 ASSERT_TRUE(vda_->Initialize( 415 config_.is_deferred_initialization_allowed = false;
124 VideoDecodeAccelerator::Config(H264PROFILE_BASELINE), &client_)); 416
125 } 417 EXPECT_CALL(codec_allocator_, MockCreateMediaCodecSync(nullptr, NotNull()));
126 418 ASSERT_TRUE(InitializeAVDA());
127 TEST_F(AndroidVideoDecodeAcceleratorTest, FailingToCreateACodecIsAnError) { 419 }
128 EXPECT_CALL(codec_allocator_, CreateMediaCodecAsync(_, _)) 420
129 .WillOnce(PostNullCodec()); 421 TEST_F(AndroidVideoDecodeAcceleratorTest, FailingToCreateACodecSyncIsAnError) {
422 // Failuew to create a codec during sync init should cause Initialize to fail.
423 SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE();
424
425 config_.is_deferred_initialization_allowed = false;
426 codec_allocator_.allow_sync_creation = false;
427
428 EXPECT_CALL(codec_allocator_, MockCreateMediaCodecSync(nullptr, NotNull()));
429 ASSERT_FALSE(InitializeAVDA());
430 }
431
432 TEST_F(AndroidVideoDecodeAcceleratorTest, FailingToCreateACodecAsyncIsAnError) {
433 // Verify that a null codec signals error for async init when it doesn't get a
434 // mediacodec instance.
435 //
436 // Also assert that there's only one call to CreateMediaCodecAsync. And since
437 // it replies with a null codec, AVDA will be in an error state when it shuts
438 // down. Since we know that it's constructed before we destroy the VDA, we
439 // verify that AVDA doens't create codecs during destruction.
440 SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE();
441
442 // Note that if we somehow end up deferring surface creation, then this would
443 // no longer be expected to fail. It would signal success before asking for a
444 // surface or codec.
445 EXPECT_CALL(*helper_, MockStartup());
446 EXPECT_CALL(codec_allocator_, MockCreateMediaCodecAsync(_, NotNull()));
130 EXPECT_CALL(client_, NotifyInitializationComplete(false)); 447 EXPECT_CALL(client_, NotifyInitializationComplete(false));
131 448
132 VideoDecodeAccelerator::Config config(H264PROFILE_BASELINE); 449 ASSERT_TRUE(InitializeAVDA());
133 config.is_deferred_initialization_allowed = true; 450 helper_->ProvideSurfaceTexture();
134 vda_->Initialize(config, &client_); 451 codec_allocator_.ProvideNullCodecAsync();
135 base::RunLoop().RunUntilIdle(); 452
136 } 453 // Make sure that codec allocation has happened before destroying the VDA.
137 454 testing::Mock::VerifyAndClearExpectations(&codec_allocator_);
138 TEST_F(AndroidVideoDecodeAcceleratorTest, NoCodecsAreCreatedDuringDestruction) { 455
139 // Assert that there's only one call to CreateMediaCodecAsync. And since it 456 vda_ = nullptr;
140 // replies with a null codec, AVDA will be in an error state when it shuts 457 base::RunLoop().RunUntilIdle();
141 // down. 458 }
142 EXPECT_CALL(codec_allocator_, CreateMediaCodecAsync(_, _)) 459
143 .WillOnce(PostNullCodec()); 460 TEST_F(AndroidVideoDecodeAcceleratorTest,
144 461 LowEndDevicesSucceedInitWithoutASurface) {
145 VideoDecodeAccelerator::Config config(H264PROFILE_BASELINE); 462 // If AVDA decides that we should defer surface creation, then it should
146 config.is_deferred_initialization_allowed = true; 463 // signal success before we provide a surface. It should still ask for a
147 vda_->Initialize(config, &client_); 464 // surface, though.
148 base::RunLoop().RunUntilIdle(); 465 SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE();
149 } 466
150 467 // It would be nicer if we didn't just force this on, since we might do so
468 // in a state that AVDA isn't supposed to handle (e.g., if we give it a
469 // surface, then it would never decide to defer surface creation).
470 platform_config_.force_deferred_surface_creation = true;
471 config_.surface_id = SurfaceManager::kNoSurfaceID;
472
473 EXPECT_CALL(*helper_, MockStartup()).Times(0);
474 EXPECT_CALL(client_, NotifyInitializationComplete(true));
475
476 InitializeAVDA();
477 }
478
479 TEST_F(AndroidVideoDecodeAcceleratorTest, WillStartHelperImmediately) {
480 // AVDA should initialize |helper_| immediately if it's not waiting for a Cdm.
481 // It should provide a null factory, since |config_| defaults to
482 // SurfaceTexture. We also expect that AVDA will not create a codec before it
483 // gets a surface, nor will it signal deferred init success to us.
484 SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE();
485
486 EXPECT_CALL(*helper_, MockStartup());
487 EXPECT_CALL(codec_allocator_, MockCreateMediaCodecAsync(_, NotNull()))
488 .Times(0);
489 EXPECT_CALL(client_, NotifyInitializationComplete(_)).Times(0);
490
491 InitializeAVDA();
492 ASSERT_TRUE(helper_->factory_ == nullptr);
493 }
494
495 TEST_F(AndroidVideoDecodeAcceleratorTest,
496 AsyncInitWithSurfaceTextureAndDelete) {
497 // When configuring with a SurfaceTexture and deferred init, we should be
498 // asked for a codec, and be notified of init success if we provide one. When
499 // AVDA is destroyed, it should release the codec and surface texture.
500 SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE();
501
502 InitializeAVDAWithSurfaceTexture();
503
504 // Delete the VDA, and make sure that it tries to free the codec and the right
505 // surface texture.
506 EXPECT_CALL(
507 codec_allocator_,
508 MockReleaseMediaCodec(codec_allocator_.most_recent_codec(),
509 codec_allocator_.most_recent_overlay(),
510 codec_allocator_.most_recent_surface_texture()));
511 vda_ = nullptr;
512 base::RunLoop().RunUntilIdle();
513 }
514
515 TEST_F(AndroidVideoDecodeAcceleratorTest, AsyncInitWithSurfaceAndDelete) {
516 // When |config_| specifies a surface, we should be given a factory during
517 // startup for it. When |helper_| provides an overlay, the codec should be
518 // allocated using it. Shutdown should provide the overlay when releasing the
519 // media codec.
520 SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE();
521
522 InitializeAVDAWithOverlay();
523
524 // Delete the VDA, and make sure that it tries to free the codec and the
525 // overlay that it provided to us.
526 EXPECT_CALL(
527 codec_allocator_,
528 MockReleaseMediaCodec(codec_allocator_.most_recent_codec(),
529 codec_allocator_.most_recent_overlay(),
530 codec_allocator_.most_recent_surface_texture()));
531 vda_ = nullptr;
532 base::RunLoop().RunUntilIdle();
533 }
534
535 TEST_F(AndroidVideoDecodeAcceleratorTest,
536 SwitchesToSurfaceTextureWhenSurfaceDestroyed) {
537 // Provide a surface, and a codec, then destroy the surface. AVDA should use
538 // SetSurface to switch to SurfaceTexture.
539 SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE();
540
541 InitializeAVDAWithOverlay();
542
543 // It would be nice if we knew that this was a surface texture. As it is, we
544 // just destroy the VDA and expect that we're provided with one. Hopefully,
545 // AVDA is actually calling SetSurface properly.
546 EXPECT_CALL(*codec_allocator_.most_recent_codec(), SetSurface(_))
547 .WillOnce(Return(true));
548 helper_->StopImmediately(codec_allocator_.most_recent_overlay());
549
550 EXPECT_CALL(codec_allocator_,
551 MockReleaseMediaCodec(codec_allocator_.most_recent_codec(),
552 nullptr, NotNull()));
553 vda_ = nullptr;
554 base::RunLoop().RunUntilIdle();
555 }
556
557 TEST_F(AndroidVideoDecodeAcceleratorTest, SwitchesToSurfaceTextureEventually) {
558 // Provide a surface, and a codec, then request that AVDA switches to a
559 // surface texture. Verify that it does.
560 SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE();
561
562 InitializeAVDAWithOverlay();
563
564 EXPECT_CALL(*codec_allocator_.most_recent_codec(), SetSurface(_))
565 .WillOnce(Return(true));
566
567 // Note that it's okay if |avda_| switches before ProvideSurfaceTexture
568 // returns, since it has no queued output anyway.
569 helper_->ProvideSurfaceTexture();
570 LetAVDAUpdateSurface();
571
572 // Verify that we're now using some surface texture.
573 EXPECT_CALL(codec_allocator_,
574 MockReleaseMediaCodec(codec_allocator_.most_recent_codec(),
575 nullptr, NotNull()));
576 vda_ = nullptr;
577 base::RunLoop().RunUntilIdle();
578 }
579
580 TEST_F(AndroidVideoDecodeAcceleratorTest,
581 SetSurfaceFailureDoesntSwitchSurfaces) {
582 // Initialize AVDA with a surface, then request that AVDA switches to a
583 // surface texture. When it tries to UpdateSurface, pretend to fail. AVDA
584 // should notify error, and also release the original surface.
585 SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE();
586
587 InitializeAVDAWithOverlay();
588
589 EXPECT_CALL(*codec_allocator_.most_recent_codec(), SetSurface(_))
590 .WillOnce(Return(false));
591 EXPECT_CALL(client_,
592 NotifyError(AndroidVideoDecodeAccelerator::PLATFORM_FAILURE))
593 .Times(1);
594 helper_->ProvideSurfaceTexture();
595
596 // Verify that we're still using an overlay.
597 EXPECT_CALL(codec_allocator_,
598 MockReleaseMediaCodec(codec_allocator_.most_recent_codec(),
599 NotNull(), nullptr));
600
601 // Also destroy the VDA to be sure that it cleans up the codec. It can do so
602 // earlier if it wants to, but isn't required to.
603 LetAVDAUpdateSurface();
604 vda_ = nullptr;
605 base::RunLoop().RunUntilIdle();
606 }
607
608 TEST_F(AndroidVideoDecodeAcceleratorTest,
609 SwitchToSurfaceAndBackBeforeSetSurface) {
610 // Ask AVDA to switch from ST to overlay, then back to ST before it has a
611 // chance to do the first switch. It should simply drop the overlay.
612 SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE();
613
614 InitializeAVDAWithSurfaceTexture();
615
616 // Don't let AVDA switch immediately, else it could choose to SetSurface when
617 // it first gets the overlay.
618 SetHasUnrenderedPictureBuffers(true);
619 EXPECT_CALL(*codec_allocator_.most_recent_codec(), SetSurface(_)).Times(0);
620 std::unique_ptr<MockAndroidOverlay> overlay =
621 base::MakeUnique<MockAndroidOverlay>();
622 auto overlay_weak = overlay->GetWeakPtr();
623 helper_->ProvideOverlay(std::move(overlay));
624 // ProvideOverlay should not drop |overlay_weak| yet.
625 ASSERT_TRUE(overlay_weak.get() != nullptr);
626
627 // While the incoming surface is pending, switch back to SurfaceTexture.
628 helper_->ProvideSurfaceTexture();
629 // ProvideOverlay should drop |overlay_weak|.
630 ASSERT_TRUE(overlay_weak.get() == nullptr);
631
632 // Cleanup should free the the original SurfaceTexture. It would probably be
633 // fine to free a new one, but that seems like a waste of resources. So, we
634 // enforce that it should elide the switch entirely.
635 EXPECT_CALL(
636 codec_allocator_,
637 MockReleaseMediaCodec(codec_allocator_.most_recent_codec(), nullptr,
638 codec_allocator_.most_recent_surface_texture()));
639 LetAVDAUpdateSurface();
640 vda_ = nullptr;
641 base::RunLoop().RunUntilIdle();
642 }
643
644 TEST_F(AndroidVideoDecodeAcceleratorTest,
645 ChangingOutputSurfaceVoluntarilyWithoutSetSurfaceIsIgnored) {
646 // If we ask AVDA to change to SurfaceTexture should be ignored on platforms
647 // that don't support SetSurface (pre-M or blacklisted). It should also
648 // ignore SurfaceTexture => overlay, but we don't check that.
649 //
650 // Also note that there are other probably reasonable things to do (like
651 // signal an error), but we want to be sure that it doesn't try to SetSurface.
652 // We also want to be sure that, if it doesn't signal an error, that it also
653 // doesn't get confused about which surface is in use. So, we assume that it
654 // doesn't signal an error, and we check that it releases the right surface
655 // with the codec.
656 EXPECT_CALL(client_, NotifyError(_)).Times(0);
657
658 platform_config_.allow_setsurface = false;
659 InitializeAVDAWithOverlay();
660 EXPECT_CALL(*codec_allocator_.most_recent_codec(), SetSurface(_)).Times(0);
661
662 // This should not switch to SurfaceTexture.
663 helper_->ProvideSurfaceTexture();
664 LetAVDAUpdateSurface();
665
666 // It should free an overlay with the codec.
667 EXPECT_CALL(
668 codec_allocator_,
669 MockReleaseMediaCodec(codec_allocator_.most_recent_codec(),
670 codec_allocator_.most_recent_overlay(), nullptr));
671 vda_ = nullptr;
672 base::RunLoop().RunUntilIdle();
673 }
674
675 TEST_F(AndroidVideoDecodeAcceleratorTest,
676 OnSurfaceDestroyedWithoutSetSurfaceFreesTheCodec) {
677 // If AVDA receives OnSurfaceDestroyed without support for SetSurface, then it
678 // should free the codec.
679 platform_config_.allow_setsurface = false;
680 InitializeAVDAWithOverlay();
681 EXPECT_CALL(*codec_allocator_.most_recent_codec(), SetSurface(_)).Times(0);
682
683 // This should free the codec.
684 EXPECT_CALL(
685 codec_allocator_,
686 MockReleaseMediaCodec(codec_allocator_.most_recent_codec(),
687 codec_allocator_.most_recent_overlay(), nullptr));
688 helper_->StopImmediately(codec_allocator_.most_recent_overlay());
689 base::RunLoop().RunUntilIdle();
690
691 // Verify that the codec has been released, since |vda_| will be destroyed
692 // soon. The expectations must be met before that.
693 testing::Mock::VerifyAndClearExpectations(&codec_allocator_);
694 }
695
696 TEST_F(AndroidVideoDecodeAcceleratorTest,
697 MultipleSurfaceTextureCallbacksAreIgnored) {
698 // Ask AVDA to switch to ST when it's already using ST, nothing should happen.
699 SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE();
700
701 InitializeAVDAWithSurfaceTexture();
702
703 // This should do nothing.
704 EXPECT_CALL(*codec_allocator_.most_recent_codec(), SetSurface(_)).Times(0);
705 helper_->ProvideSurfaceTexture();
706
707 base::RunLoop().RunUntilIdle();
708 }
709
151 } // namespace media 710 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698