1 // Copyright 2016 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/media_codec_video_decoder.h"
6
7 #include "base/android/jni_android.h"
8 #include "base/bind.h"
9 #include "base/callback_helpers.h"
10 #include "base/run_loop.h"
11 #include "base/test/gmock_callback_support.h"
12 #include "base/test/mock_callback.h"
13 #include "base/test/task_environment.h"
14 #include "base/threading/thread_task_runner_handle.h"
15 #include "gpu/command_buffer/service/mock_texture_owner.h"
16 #include "gpu/config/gpu_preferences.h"
17 #include "media/base/android/media_codec_util.h"
18 #include "media/base/android/mock_android_overlay.h"
19 #include "media/base/android/mock_media_crypto_context.h"
20 #include "media/base/async_destroy_video_decoder.h"
21 #include "media/base/decoder_buffer.h"
22 #include "media/base/media_util.h"
23 #include "media/base/test_helpers.h"
24 #include "media/base/video_frame.h"
25 #include "media/gpu/android/android_video_surface_chooser_impl.h"
26 #include "media/gpu/android/fake_codec_allocator.h"
27 #include "media/gpu/android/mock_android_video_surface_chooser.h"
28 #include "media/gpu/android/mock_device_info.h"
29 #include "media/gpu/android/video_frame_factory.h"
30 #include "media/video/supported_video_decoder_config.h"
31 #include "testing/gtest/include/gtest/gtest.h"
32
33 using base::test::RunCallback;
34 using testing::_;
35 using testing::InvokeWithoutArgs;
36 using testing::NiceMock;
37 using testing::NotNull;
38 using testing::Return;
39 using testing::ReturnRef;
40 using testing::SaveArg;
41
42 namespace media {
43 namespace {
44
OutputCb(scoped_refptr<VideoFrame> * output,scoped_refptr<VideoFrame> frame)45 void OutputCb(scoped_refptr<VideoFrame>* output,
46 scoped_refptr<VideoFrame> frame) {
47 *output = std::move(frame);
48 }
49
CreateAndroidOverlayCb(const base::UnguessableToken &,AndroidOverlayConfig)50 std::unique_ptr<AndroidOverlay> CreateAndroidOverlayCb(
51 const base::UnguessableToken&,
52 AndroidOverlayConfig) {
53 return nullptr;
54 }
55
56 } // namespace
57
58 class MockVideoFrameFactory : public VideoFrameFactory {
59 public:
60 MOCK_METHOD2(Initialize, void(OverlayMode overlay_mode, InitCB init_cb));
61 MOCK_METHOD1(MockSetSurfaceBundle, void(scoped_refptr<CodecSurfaceBundle>));
62 MOCK_METHOD5(
63 MockCreateVideoFrame,
64 void(CodecOutputBuffer* raw_output_buffer,
65 scoped_refptr<gpu::TextureOwner> texture_owner,
66 base::TimeDelta timestamp,
67 gfx::Size natural_size,
68 PromotionHintAggregator::NotifyPromotionHintCB promotion_hint_cb));
69 MOCK_METHOD1(MockRunAfterPendingVideoFrames,
70 void(base::OnceClosure* closure));
71 MOCK_METHOD0(CancelPendingCallbacks, void());
72
SetSurfaceBundle(scoped_refptr<CodecSurfaceBundle> surface_bundle)73 void SetSurfaceBundle(
74 scoped_refptr<CodecSurfaceBundle> surface_bundle) override {
75 MockSetSurfaceBundle(surface_bundle);
76 if (!surface_bundle) {
77 texture_owner_ = nullptr;
78 } else {
79 texture_owner_ = surface_bundle->overlay()
80 ? nullptr
81 : surface_bundle->codec_buffer_wait_coordinator()
82 ->texture_owner();
83 }
84 }
85
CreateVideoFrame(std::unique_ptr<CodecOutputBuffer> output_buffer,base::TimeDelta timestamp,gfx::Size natural_size,PromotionHintAggregator::NotifyPromotionHintCB promotion_hint_cb,VideoFrameFactory::OnceOutputCB output_cb)86 void CreateVideoFrame(
87 std::unique_ptr<CodecOutputBuffer> output_buffer,
88 base::TimeDelta timestamp,
89 gfx::Size natural_size,
90 PromotionHintAggregator::NotifyPromotionHintCB promotion_hint_cb,
91 VideoFrameFactory::OnceOutputCB output_cb) override {
92 MockCreateVideoFrame(output_buffer.get(), texture_owner_, timestamp,
93 natural_size, promotion_hint_cb);
94 last_output_buffer_ = std::move(output_buffer);
95 std::move(output_cb).Run(VideoFrame::CreateBlackFrame(gfx::Size(10, 10)));
96 }
97
RunAfterPendingVideoFrames(base::OnceClosure closure)98 void RunAfterPendingVideoFrames(base::OnceClosure closure) override {
99 last_closure_ = std::move(closure);
100 MockRunAfterPendingVideoFrames(&last_closure_);
101 }
102
103 std::unique_ptr<CodecOutputBuffer> last_output_buffer_;
104 scoped_refptr<gpu::TextureOwner> texture_owner_;
105 base::OnceClosure last_closure_;
106 };
107
108 class MediaCodecVideoDecoderTest : public testing::TestWithParam<VideoCodec> {
109 public:
MediaCodecVideoDecoderTest()110 MediaCodecVideoDecoderTest() : codec_(GetParam()) {}
111
SetUp()112 void SetUp() override {
113 uint8_t data = 0;
114 fake_decoder_buffer_ = DecoderBuffer::CopyFrom(&data, 1);
115 codec_allocator_ = std::make_unique<FakeCodecAllocator>(
116 base::ThreadTaskRunnerHandle::Get());
117 device_info_ = std::make_unique<NiceMock<MockDeviceInfo>>();
118 }
119
TearDown()120 void TearDown() override {
121 // For VP8, make MCVD skip the drain by resetting it. Otherwise, it's hard
122 // to finish the drain.
123 if (mcvd_ && codec_ == kCodecVP8 && codec_allocator_->most_recent_codec)
124 DoReset();
125
126 // MCVD calls DeleteSoon() on itself, so we have to run a RunLoop.
127 mcvd_.reset();
128 base::RunLoop().RunUntilIdle();
129 }
130
CreateMcvd()131 void CreateMcvd() {
132 auto surface_chooser =
133 std::make_unique<NiceMock<MockAndroidVideoSurfaceChooser>>();
134 surface_chooser_ = surface_chooser.get();
135
136 auto texture_owner = base::MakeRefCounted<NiceMock<gpu::MockTextureOwner>>(
137 0, nullptr, nullptr);
138 texture_owner_ = texture_owner.get();
139
140 auto video_frame_factory =
141 std::make_unique<NiceMock<MockVideoFrameFactory>>();
142 video_frame_factory_ = video_frame_factory.get();
143 // Set up VFF to pass |texture_owner_| via its InitCB.
144 ON_CALL(*video_frame_factory_, Initialize(ExpectedOverlayMode(), _))
145 .WillByDefault(RunCallback<1>(texture_owner));
146
147 auto* mcvd = new MediaCodecVideoDecoder(
148 gpu_preferences_, gpu_feature_info_, std::make_unique<NullMediaLog>(),
149 device_info_.get(), codec_allocator_.get(), std::move(surface_chooser),
150 base::BindRepeating(&CreateAndroidOverlayCb),
151 base::BindRepeating(&MediaCodecVideoDecoderTest::RequestOverlayInfoCb,
152 base::Unretained(this)),
153 std::move(video_frame_factory));
154 mcvd_ = std::make_unique<AsyncDestroyVideoDecoder<MediaCodecVideoDecoder>>(
155 base::WrapUnique(mcvd));
156 mcvd_raw_ = mcvd;
157 }
158
ExpectedOverlayMode() const159 VideoFrameFactory::OverlayMode ExpectedOverlayMode() const {
160 const bool want_promotion_hint =
161 device_info_->IsSetOutputSurfaceSupported();
162 return want_promotion_hint
163 ? VideoFrameFactory::OverlayMode::kRequestPromotionHints
164 : VideoFrameFactory::OverlayMode::kDontRequestPromotionHints;
165 }
166
CreateCdm(bool has_media_crypto_context,bool require_secure_video_decoder)167 void CreateCdm(bool has_media_crypto_context,
168 bool require_secure_video_decoder) {
169 cdm_ = std::make_unique<MockMediaCryptoContext>(has_media_crypto_context);
170 require_secure_video_decoder_ = require_secure_video_decoder;
171
172 // We need to send an object as the media crypto, but MCVD shouldn't
173 // use it for anything. Just send in some random java object, so that
174 // it's not null.
175 media_crypto_ = base::android::ScopedJavaGlobalRef<jobject>(
176 gl::SurfaceTexture::Create(0)->j_surface_texture());
177 }
178
179 // Just call Initialize(). MCVD will be waiting for a call to Decode() before
180 // continuining initialization.
Initialize(VideoDecoderConfig config)181 bool Initialize(VideoDecoderConfig config) {
182 if (!mcvd_)
183 CreateMcvd();
184 bool result = false;
185 auto init_cb = [](bool* result_out, Status result) {
186 *result_out = result.is_ok();
187 };
188 mcvd_->Initialize(
189 config, false, cdm_.get(), base::BindOnce(init_cb, &result),
190 base::BindRepeating(&OutputCb, &most_recent_frame_), base::DoNothing());
191 base::RunLoop().RunUntilIdle();
192
193 // If there is a CDM available, then we expect that MCVD will be waiting
194 // for the media crypto object.
195 // TODO(liberato): why does CreateJavaObjectPtr() not link?
196 if (cdm_ && cdm_->media_crypto_ready_cb) {
197 std::move(cdm_->media_crypto_ready_cb)
198 .Run(std::make_unique<base::android::ScopedJavaGlobalRef<jobject>>(
199 media_crypto_),
200 require_secure_video_decoder_);
201 // The callback is consumed, mark that we ran it so tests can verify.
202 cdm_->ran_media_crypto_ready_cb = true;
203 base::RunLoop().RunUntilIdle();
204 }
205
206 return result;
207 }
208
209 // Call Initialize() and Decode() to start lazy init. MCVD will be waiting for
210 // a codec and have one decode pending.
InitializeWithOverlay_OneDecodePending(VideoDecoderConfig config)211 MockAndroidOverlay* InitializeWithOverlay_OneDecodePending(
212 VideoDecoderConfig config) {
213 Initialize(config);
214 mcvd_->Decode(fake_decoder_buffer_, decode_cb_.Get());
215 OverlayInfo info;
216 info.routing_token = base::UnguessableToken::Deserialize(1, 2);
217 provide_overlay_info_cb_.Run(info);
218 auto overlay_ptr = std::make_unique<MockAndroidOverlay>();
219 auto* overlay = overlay_ptr.get();
220
221 if (!java_surface_) {
222 java_surface_ = base::android::ScopedJavaGlobalRef<jobject>(
223 gl::SurfaceTexture::Create(0)->j_surface_texture());
224 }
225 EXPECT_CALL(*overlay, GetJavaSurface())
226 .WillRepeatedly(ReturnRef(java_surface_));
227
228 surface_chooser_->ProvideOverlay(std::move(overlay_ptr));
229 return overlay;
230 }
231
232 // Call Initialize() and Decode() to start lazy init. MCVD will be waiting for
233 // a codec and have one decode pending.
InitializeWithTextureOwner_OneDecodePending(VideoDecoderConfig config)234 void InitializeWithTextureOwner_OneDecodePending(VideoDecoderConfig config) {
235 Initialize(config);
236 mcvd_->Decode(fake_decoder_buffer_, decode_cb_.Get());
237 provide_overlay_info_cb_.Run(OverlayInfo());
238 surface_chooser_->ProvideTextureOwner();
239 }
240
241 // Fully initializes MCVD and returns the codec it's configured with. MCVD
242 // will have one decode pending.
InitializeFully_OneDecodePending(VideoDecoderConfig config)243 MockMediaCodecBridge* InitializeFully_OneDecodePending(
244 VideoDecoderConfig config) {
245 InitializeWithTextureOwner_OneDecodePending(config);
246 return codec_allocator_->ProvideMockCodecAsync();
247 }
248
249 // Provide access to MCVD's private PumpCodec() to drive the state transitions
250 // that depend on queueing and dequeueing buffers. It uses |mcvd_raw_| so that
251 // it can be called after |mcvd_| is reset.
PumpCodec()252 void PumpCodec() { mcvd_raw_->PumpCodec(false); }
253
254 // Start and finish a reset.
DoReset()255 void DoReset() {
256 bool reset_complete = false;
257 mcvd_->Reset(base::BindOnce(
258 [](bool* reset_complete) { *reset_complete = true; }, &reset_complete));
259 base::RunLoop().RunUntilIdle();
260 if (!reset_complete) {
261 // Note that there might be more pending decodes, and this will arrive
262 // out of order. We assume that MCVD doesn't care.
263 codec_allocator_->most_recent_codec->ProduceOneOutput(
264 MockMediaCodecBridge::kEos);
265 PumpCodec();
266 EXPECT_TRUE(reset_complete);
267 }
268 }
269
RequestOverlayInfoCb(bool restart_for_transitions,ProvideOverlayInfoCB provide_overlay_info_cb)270 void RequestOverlayInfoCb(bool restart_for_transitions,
271 ProvideOverlayInfoCB provide_overlay_info_cb) {
272 restart_for_transitions_ = restart_for_transitions;
273 provide_overlay_info_cb_ = std::move(provide_overlay_info_cb);
274 }
275
276 protected:
277 const VideoCodec codec_;
278 base::test::SingleThreadTaskEnvironment task_environment_;
279 base::android::ScopedJavaGlobalRef<jobject> java_surface_;
280 scoped_refptr<DecoderBuffer> fake_decoder_buffer_;
281 std::unique_ptr<MockDeviceInfo> device_info_;
282 std::unique_ptr<FakeCodecAllocator> codec_allocator_;
283 MockAndroidVideoSurfaceChooser* surface_chooser_;
284 gpu::MockTextureOwner* texture_owner_;
285 MockVideoFrameFactory* video_frame_factory_;
286 NiceMock<base::MockCallback<VideoDecoder::DecodeCB>> decode_cb_;
287 ProvideOverlayInfoCB provide_overlay_info_cb_;
288 bool restart_for_transitions_;
289 gpu::GpuPreferences gpu_preferences_;
290 gpu::GpuFeatureInfo gpu_feature_info_;
291 scoped_refptr<VideoFrame> most_recent_frame_;
292
293 // This is not an actual media crypto object.
294 base::android::ScopedJavaGlobalRef<jobject> media_crypto_;
295 bool require_secure_video_decoder_ = false;
296
297 // This must outlive |mcvd_| .
298 std::unique_ptr<MockMediaCryptoContext> cdm_;
299
300 // |mcvd_raw_| lets us call PumpCodec() even after |mcvd_| is dropped, for
301 // testing the teardown path.
302 MediaCodecVideoDecoder* mcvd_raw_;
303 std::unique_ptr<VideoDecoder> mcvd_;
304 };
305
306 // Tests which only work for a single codec.
307 class MediaCodecVideoDecoderAV1Test : public MediaCodecVideoDecoderTest {};
308 class MediaCodecVideoDecoderH264Test : public MediaCodecVideoDecoderTest {};
309 class MediaCodecVideoDecoderVp8Test : public MediaCodecVideoDecoderTest {};
310 class MediaCodecVideoDecoderVp9Test : public MediaCodecVideoDecoderTest {};
311
TEST_P(MediaCodecVideoDecoderTest,UnknownCodecIsRejected)312 TEST_P(MediaCodecVideoDecoderTest, UnknownCodecIsRejected) {
313 ASSERT_FALSE(Initialize(TestVideoConfig::Invalid()));
314 }
315
TEST_P(MediaCodecVideoDecoderH264Test,H264IsSupported)316 TEST_P(MediaCodecVideoDecoderH264Test, H264IsSupported) {
317 ASSERT_TRUE(Initialize(TestVideoConfig::NormalH264()));
318 }
319
TEST_P(MediaCodecVideoDecoderVp8Test,SmallVp8IsRejected)320 TEST_P(MediaCodecVideoDecoderVp8Test, SmallVp8IsRejected) {
321 auto configs = MediaCodecVideoDecoder::GetSupportedConfigs();
322 auto small_vp8_config = TestVideoConfig::Normal();
323 for (const auto& c : configs)
324 ASSERT_FALSE(c.Matches(small_vp8_config));
325 }
326
TEST_P(MediaCodecVideoDecoderAV1Test,Av1IsSupported)327 TEST_P(MediaCodecVideoDecoderAV1Test, Av1IsSupported) {
328 EXPECT_CALL(*device_info_, IsAv1DecoderAvailable()).WillOnce(Return(true));
329 ASSERT_TRUE(Initialize(TestVideoConfig::Normal(kCodecAV1)));
330 }
331
TEST_P(MediaCodecVideoDecoderTest,InitializeDoesntInitSurfaceOrCodec)332 TEST_P(MediaCodecVideoDecoderTest, InitializeDoesntInitSurfaceOrCodec) {
333 CreateMcvd();
334 EXPECT_CALL(*video_frame_factory_, Initialize(ExpectedOverlayMode(), _))
335 .Times(0);
336 EXPECT_CALL(*surface_chooser_, MockUpdateState()).Times(0);
337 EXPECT_CALL(*codec_allocator_, MockCreateMediaCodecAsync()).Times(0);
338 Initialize(TestVideoConfig::Large(codec_));
339 }
340
TEST_P(MediaCodecVideoDecoderTest,FirstDecodeTriggersFrameFactoryInit)341 TEST_P(MediaCodecVideoDecoderTest, FirstDecodeTriggersFrameFactoryInit) {
342 Initialize(TestVideoConfig::Large(codec_));
343 EXPECT_CALL(*video_frame_factory_, Initialize(ExpectedOverlayMode(), _));
344 mcvd_->Decode(fake_decoder_buffer_, decode_cb_.Get());
345 }
346
TEST_P(MediaCodecVideoDecoderTest,FirstDecodeTriggersOverlayInfoRequestIfSupported)347 TEST_P(MediaCodecVideoDecoderTest,
348 FirstDecodeTriggersOverlayInfoRequestIfSupported) {
349 Initialize(TestVideoConfig::Large(codec_));
350 // Requesting overlay info sets this cb.
351 ASSERT_FALSE(provide_overlay_info_cb_);
352 mcvd_->Decode(fake_decoder_buffer_, decode_cb_.Get());
353 ASSERT_TRUE(provide_overlay_info_cb_);
354 }
355
TEST_P(MediaCodecVideoDecoderTest,OverlayInfoIsNotRequestedIfOverlaysNotSupported)356 TEST_P(MediaCodecVideoDecoderTest,
357 OverlayInfoIsNotRequestedIfOverlaysNotSupported) {
358 Initialize(TestVideoConfig::Large(codec_));
359 ON_CALL(*device_info_, SupportsOverlaySurfaces())
360 .WillByDefault(Return(false));
361 mcvd_->Decode(fake_decoder_buffer_, decode_cb_.Get());
362 ASSERT_FALSE(provide_overlay_info_cb_);
363 }
364
TEST_P(MediaCodecVideoDecoderTest,RestartForOverlayTransitionsFlagIsCorrect)365 TEST_P(MediaCodecVideoDecoderTest, RestartForOverlayTransitionsFlagIsCorrect) {
366 ON_CALL(*device_info_, IsSetOutputSurfaceSupported())
367 .WillByDefault(Return(true));
368 Initialize(TestVideoConfig::Large(codec_));
369 mcvd_->Decode(fake_decoder_buffer_, decode_cb_.Get());
370 ASSERT_FALSE(restart_for_transitions_);
371 }
372
TEST_P(MediaCodecVideoDecoderTest,OverlayInfoIsNotRequestedIfThreadedTextureMailboxesEnabled)373 TEST_P(MediaCodecVideoDecoderTest,
374 OverlayInfoIsNotRequestedIfThreadedTextureMailboxesEnabled) {
375 gpu_preferences_.enable_threaded_texture_mailboxes = true;
376 Initialize(TestVideoConfig::Large(codec_));
377 mcvd_->Decode(fake_decoder_buffer_, decode_cb_.Get());
378 ASSERT_FALSE(provide_overlay_info_cb_);
379 }
380
TEST_P(MediaCodecVideoDecoderTest,OverlayInfoDuringInitUpdatesSurfaceChooser)381 TEST_P(MediaCodecVideoDecoderTest, OverlayInfoDuringInitUpdatesSurfaceChooser) {
382 InitializeWithTextureOwner_OneDecodePending(TestVideoConfig::Large(codec_));
383 EXPECT_CALL(*surface_chooser_, MockUpdateState());
384 provide_overlay_info_cb_.Run(OverlayInfo());
385 }
386
TEST_P(MediaCodecVideoDecoderTest,CodecIsCreatedAfterSurfaceChosen)387 TEST_P(MediaCodecVideoDecoderTest, CodecIsCreatedAfterSurfaceChosen) {
388 Initialize(TestVideoConfig::Large(codec_));
389 mcvd_->Decode(fake_decoder_buffer_, decode_cb_.Get());
390 provide_overlay_info_cb_.Run(OverlayInfo());
391 EXPECT_CALL(*codec_allocator_, MockCreateMediaCodecAsync());
392 surface_chooser_->ProvideTextureOwner();
393 }
394
TEST_P(MediaCodecVideoDecoderTest,FrameFactoryInitFailureIsAnError)395 TEST_P(MediaCodecVideoDecoderTest, FrameFactoryInitFailureIsAnError) {
396 Initialize(TestVideoConfig::Large(codec_));
397 ON_CALL(*video_frame_factory_, Initialize(ExpectedOverlayMode(), _))
398 .WillByDefault(RunCallback<1>(nullptr));
399 EXPECT_CALL(decode_cb_, Run(IsDecodeErrorStatus())).Times(1);
400 EXPECT_CALL(*surface_chooser_, MockUpdateState()).Times(0);
401 mcvd_->Decode(fake_decoder_buffer_, decode_cb_.Get());
402 }
403
TEST_P(MediaCodecVideoDecoderTest,CodecCreationFailureIsAnError)404 TEST_P(MediaCodecVideoDecoderTest, CodecCreationFailureIsAnError) {
405 InitializeWithTextureOwner_OneDecodePending(TestVideoConfig::Large(codec_));
406 mcvd_->Decode(fake_decoder_buffer_, decode_cb_.Get());
407 EXPECT_CALL(decode_cb_, Run(IsDecodeErrorStatus())).Times(2);
408 // Failing to create a codec should put MCVD into an error state.
409 codec_allocator_->ProvideNullCodecAsync();
410 }
411
TEST_P(MediaCodecVideoDecoderTest,CodecFailuresAreAnError)412 TEST_P(MediaCodecVideoDecoderTest, CodecFailuresAreAnError) {
413 auto* codec =
414 InitializeFully_OneDecodePending(TestVideoConfig::Large(codec_));
415 EXPECT_CALL(*codec, DequeueInputBuffer(_, _))
416 .WillOnce(Return(MEDIA_CODEC_ERROR));
417 EXPECT_CALL(decode_cb_, Run(IsDecodeErrorStatus()));
418 PumpCodec();
419 }
420
TEST_P(MediaCodecVideoDecoderTest,AfterInitCompletesTheCodecIsPolled)421 TEST_P(MediaCodecVideoDecoderTest, AfterInitCompletesTheCodecIsPolled) {
422 auto* codec =
423 InitializeFully_OneDecodePending(TestVideoConfig::Large(codec_));
424 // Run a RunLoop until the first time the codec is polled for an available
425 // input buffer.
426 base::RunLoop loop;
427 EXPECT_CALL(*codec, DequeueInputBuffer(_, _))
428 .WillOnce(InvokeWithoutArgs([&loop]() {
429 loop.Quit();
430 return MEDIA_CODEC_TRY_AGAIN_LATER;
431 }));
432 loop.Run();
433 }
434
TEST_P(MediaCodecVideoDecoderTest,CodecIsReleasedOnDestruction)435 TEST_P(MediaCodecVideoDecoderTest, CodecIsReleasedOnDestruction) {
436 auto* codec =
437 InitializeFully_OneDecodePending(TestVideoConfig::Large(codec_));
438 EXPECT_CALL(*codec_allocator_, MockReleaseMediaCodec(codec));
439 }
440
TEST_P(MediaCodecVideoDecoderTest,SurfaceChooserIsUpdatedOnOverlayChanges)441 TEST_P(MediaCodecVideoDecoderTest, SurfaceChooserIsUpdatedOnOverlayChanges) {
442 InitializeWithTextureOwner_OneDecodePending(TestVideoConfig::Large(codec_));
443
444 EXPECT_CALL(*surface_chooser_, MockReplaceOverlayFactory(_)).Times(2);
445 OverlayInfo info;
446 info.routing_token = base::UnguessableToken::Deserialize(1, 2);
447 provide_overlay_info_cb_.Run(info);
448 ASSERT_TRUE(surface_chooser_->factory_);
449 info.routing_token = base::UnguessableToken::Deserialize(3, 4);
450 provide_overlay_info_cb_.Run(info);
451 ASSERT_TRUE(surface_chooser_->factory_);
452 }
453
TEST_P(MediaCodecVideoDecoderTest,OverlayInfoUpdatesAreIgnoredInStateError)454 TEST_P(MediaCodecVideoDecoderTest, OverlayInfoUpdatesAreIgnoredInStateError) {
455 InitializeWithTextureOwner_OneDecodePending(TestVideoConfig::Large(codec_));
456 // Enter the error state.
457 codec_allocator_->ProvideNullCodecAsync();
458
459 EXPECT_CALL(*surface_chooser_, MockUpdateState()).Times(0);
460 OverlayInfo info;
461 info.routing_token = base::UnguessableToken::Deserialize(1, 2);
462 provide_overlay_info_cb_.Run(info);
463 }
464
TEST_P(MediaCodecVideoDecoderTest,DuplicateOverlayInfoUpdatesAreIgnored)465 TEST_P(MediaCodecVideoDecoderTest, DuplicateOverlayInfoUpdatesAreIgnored) {
466 InitializeWithTextureOwner_OneDecodePending(TestVideoConfig::Large(codec_));
467
468 // The second overlay info update should be ignored.
469 EXPECT_CALL(*surface_chooser_, MockReplaceOverlayFactory(_)).Times(1);
470 OverlayInfo info;
471 info.routing_token = base::UnguessableToken::Deserialize(1, 2);
472 provide_overlay_info_cb_.Run(info);
473 provide_overlay_info_cb_.Run(info);
474 }
475
TEST_P(MediaCodecVideoDecoderTest,CodecIsCreatedWithChosenOverlay)476 TEST_P(MediaCodecVideoDecoderTest, CodecIsCreatedWithChosenOverlay) {
477 EXPECT_CALL(*codec_allocator_, MockCreateMediaCodecAsync());
478 InitializeWithOverlay_OneDecodePending(TestVideoConfig::Large(codec_));
479 EXPECT_TRUE(base::android::AttachCurrentThread()->IsSameObject(
480 java_surface_.obj(),
481 codec_allocator_->most_recent_config->surface.obj()));
482 }
483
TEST_P(MediaCodecVideoDecoderTest,CodecCreationWeakPtrIsInvalidatedBySurfaceDestroyed)484 TEST_P(MediaCodecVideoDecoderTest,
485 CodecCreationWeakPtrIsInvalidatedBySurfaceDestroyed) {
486 ON_CALL(*device_info_, IsSetOutputSurfaceSupported())
487 .WillByDefault(Return(false));
488 auto* overlay =
489 InitializeWithOverlay_OneDecodePending(TestVideoConfig::Large(codec_));
490 overlay->OnSurfaceDestroyed();
491
492 // MCVD handles release of the MediaCodec after WeakPtr invalidation.
493 EXPECT_CALL(*codec_allocator_, MockReleaseMediaCodec(NotNull()));
494 auto* codec = codec_allocator_->ProvideMockCodecAsync();
495 ASSERT_TRUE(!!codec);
496 }
497
TEST_P(MediaCodecVideoDecoderTest,SurfaceChangedWhileCodecCreationPending)498 TEST_P(MediaCodecVideoDecoderTest, SurfaceChangedWhileCodecCreationPending) {
499 auto* overlay =
500 InitializeWithOverlay_OneDecodePending(TestVideoConfig::Large(codec_));
501 overlay->OnSurfaceDestroyed();
502 auto codec = std::make_unique<NiceMock<MockMediaCodecBridge>>();
503
504 // SetSurface() is called as soon as the codec is created to switch away from
505 // the destroyed surface.
506 EXPECT_CALL(*codec, SetSurface(_)).WillOnce(Return(true));
507 codec_allocator_->ProvideMockCodecAsync(std::move(codec));
508 }
509
TEST_P(MediaCodecVideoDecoderTest,SurfaceDestroyedDoesSyncSurfaceTransition)510 TEST_P(MediaCodecVideoDecoderTest, SurfaceDestroyedDoesSyncSurfaceTransition) {
511 auto* overlay =
512 InitializeWithOverlay_OneDecodePending(TestVideoConfig::Large(codec_));
513 auto* codec = codec_allocator_->ProvideMockCodecAsync();
514
515 // MCVD must synchronously switch the codec's surface (to surface
516 // texture), and delete the overlay.
517 EXPECT_CALL(*codec, SetSurface(_)).WillOnce(Return(true));
518 auto observer = overlay->CreateDestructionObserver();
519 observer->ExpectDestruction();
520 overlay->OnSurfaceDestroyed();
521 }
522
TEST_P(MediaCodecVideoDecoderTest,SurfaceDestroyedReleasesCodecIfSetSurfaceIsNotSupported)523 TEST_P(MediaCodecVideoDecoderTest,
524 SurfaceDestroyedReleasesCodecIfSetSurfaceIsNotSupported) {
525 ON_CALL(*device_info_, IsSetOutputSurfaceSupported())
526 .WillByDefault(Return(false));
527 auto* overlay =
528 InitializeWithOverlay_OneDecodePending(TestVideoConfig::Large(codec_));
529 auto* codec = codec_allocator_->ProvideMockCodecAsync();
530
531 // MCVD must synchronously release the codec.
532 EXPECT_CALL(*codec, SetSurface(_)).Times(0);
533 EXPECT_CALL(*codec_allocator_, MockReleaseMediaCodec(codec));
534 overlay->OnSurfaceDestroyed();
535 // Verify expectations before we delete the MCVD.
536 testing::Mock::VerifyAndClearExpectations(codec_allocator_.get());
537 }
538
TEST_P(MediaCodecVideoDecoderTest,PumpCodecPerformsPendingSurfaceTransitions)539 TEST_P(MediaCodecVideoDecoderTest, PumpCodecPerformsPendingSurfaceTransitions) {
540 InitializeWithOverlay_OneDecodePending(TestVideoConfig::Large(codec_));
541 auto* codec = codec_allocator_->ProvideMockCodecAsync();
542
543 // Set a pending surface transition and then call PumpCodec().
544 surface_chooser_->ProvideTextureOwner();
545 EXPECT_CALL(*codec, SetSurface(_)).WillOnce(Return(true));
546 PumpCodec();
547 }
548
TEST_P(MediaCodecVideoDecoderTest,SetSurfaceFailureReleasesTheCodecAndSignalsError)549 TEST_P(MediaCodecVideoDecoderTest,
550 SetSurfaceFailureReleasesTheCodecAndSignalsError) {
551 InitializeWithOverlay_OneDecodePending(TestVideoConfig::Large(codec_));
552 auto* codec = codec_allocator_->ProvideMockCodecAsync();
553
554 surface_chooser_->ProvideTextureOwner();
555 EXPECT_CALL(*codec, SetSurface(_)).WillOnce(Return(false));
556 EXPECT_CALL(decode_cb_, Run(IsDecodeErrorStatus())).Times(2);
557 EXPECT_CALL(*codec_allocator_, MockReleaseMediaCodec(codec));
558 mcvd_->Decode(fake_decoder_buffer_, decode_cb_.Get());
559 // Verify expectations before we delete the MCVD.
560 testing::Mock::VerifyAndClearExpectations(codec_allocator_.get());
561 }
562
TEST_P(MediaCodecVideoDecoderTest,SurfaceTransitionsCanBeCanceled)563 TEST_P(MediaCodecVideoDecoderTest, SurfaceTransitionsCanBeCanceled) {
564 InitializeWithTextureOwner_OneDecodePending(TestVideoConfig::Large(codec_));
565 auto* codec = codec_allocator_->ProvideMockCodecAsync();
566
567 // Set a pending transition to an overlay, and then back to a texture owner.
568 // They should cancel each other out and leave the codec as-is.
569 EXPECT_CALL(*codec, SetSurface(_)).Times(0);
570 auto overlay = std::make_unique<MockAndroidOverlay>();
571 auto observer = overlay->CreateDestructionObserver();
572 surface_chooser_->ProvideOverlay(std::move(overlay));
573
574 // Switching back to texture owner should delete the pending overlay.
575 observer->ExpectDestruction();
576 surface_chooser_->ProvideTextureOwner();
577 observer.reset();
578
579 // Verify that Decode() does not transition the surface
580 mcvd_->Decode(fake_decoder_buffer_, decode_cb_.Get());
581 }
582
TEST_P(MediaCodecVideoDecoderTest,TransitionToSameSurfaceIsIgnored)583 TEST_P(MediaCodecVideoDecoderTest, TransitionToSameSurfaceIsIgnored) {
584 InitializeWithTextureOwner_OneDecodePending(TestVideoConfig::Large(codec_));
585 auto* codec = codec_allocator_->ProvideMockCodecAsync();
586 EXPECT_CALL(*codec, SetSurface(_)).Times(0);
587 surface_chooser_->ProvideTextureOwner();
588 mcvd_->Decode(fake_decoder_buffer_, decode_cb_.Get());
589 }
590
TEST_P(MediaCodecVideoDecoderTest,ResetBeforeCodecInitializedSucceedsImmediately)591 TEST_P(MediaCodecVideoDecoderTest,
592 ResetBeforeCodecInitializedSucceedsImmediately) {
593 InitializeWithTextureOwner_OneDecodePending(TestVideoConfig::Large(codec_));
594 base::MockCallback<base::OnceClosure> reset_cb;
595 EXPECT_CALL(reset_cb, Run());
596 mcvd_->Reset(reset_cb.Get());
597 testing::Mock::VerifyAndClearExpectations(&reset_cb);
598 }
599
TEST_P(MediaCodecVideoDecoderTest,ResetAbortsPendingDecodes)600 TEST_P(MediaCodecVideoDecoderTest, ResetAbortsPendingDecodes) {
601 InitializeWithTextureOwner_OneDecodePending(TestVideoConfig::Large(codec_));
602 EXPECT_CALL(decode_cb_, Run(HasStatusCode(StatusCode::kAborted)));
603 DoReset();
604 testing::Mock::VerifyAndClearExpectations(&decode_cb_);
605 }
606
TEST_P(MediaCodecVideoDecoderTest,ResetAbortsPendingEosDecode)607 TEST_P(MediaCodecVideoDecoderTest, ResetAbortsPendingEosDecode) {
608 // EOS is treated differently by MCVD. This verifies that it's also aborted.
609 auto* codec =
610 InitializeFully_OneDecodePending(TestVideoConfig::Large(codec_));
611 base::MockCallback<VideoDecoder::DecodeCB> eos_decode_cb;
612 mcvd_->Decode(DecoderBuffer::CreateEOSBuffer(), eos_decode_cb.Get());
613
614 // Accept the two pending decodes.
615 codec->AcceptOneInput();
616 PumpCodec();
617 codec->AcceptOneInput(MockMediaCodecBridge::kEos);
618 PumpCodec();
619
620 EXPECT_CALL(eos_decode_cb, Run(HasStatusCode(StatusCode::kAborted)));
621 DoReset();
622 // Should be run before |mcvd_| is destroyed.
623 testing::Mock::VerifyAndClearExpectations(&eos_decode_cb);
624 }
625
TEST_P(MediaCodecVideoDecoderTest,ResetDoesNotFlushAnAlreadyFlushedCodec)626 TEST_P(MediaCodecVideoDecoderTest, ResetDoesNotFlushAnAlreadyFlushedCodec) {
627 auto* codec =
628 InitializeFully_OneDecodePending(TestVideoConfig::Large(codec_));
629
630 // The codec is still in the flushed state so Reset() doesn't need to flush.
631 EXPECT_CALL(*codec, Flush()).Times(0);
632 base::MockCallback<base::OnceClosure> reset_cb;
633 EXPECT_CALL(reset_cb, Run());
634 mcvd_->Reset(reset_cb.Get());
635 testing::Mock::VerifyAndClearExpectations(&decode_cb_);
636 }
637
TEST_P(MediaCodecVideoDecoderVp8Test,ResetDrainsVP8CodecsBeforeFlushing)638 TEST_P(MediaCodecVideoDecoderVp8Test, ResetDrainsVP8CodecsBeforeFlushing) {
639 auto* codec =
640 InitializeFully_OneDecodePending(TestVideoConfig::Large(codec_));
641 // Accept the first decode to transition out of the flushed state.
642 codec->AcceptOneInput();
643 PumpCodec();
644
645 // The reset should not complete immediately because the codec needs to be
646 // drained.
647 EXPECT_CALL(*codec, Flush()).Times(0);
648 base::MockCallback<base::OnceClosure> reset_cb;
649 EXPECT_CALL(reset_cb, Run()).Times(0);
650 mcvd_->Reset(reset_cb.Get());
651
652 // The next input should be an EOS.
653 codec->AcceptOneInput(MockMediaCodecBridge::kEos);
654 PumpCodec();
655 testing::Mock::VerifyAndClearExpectations(codec);
656
657 // After the EOS is dequeued, the reset should complete.
658 EXPECT_CALL(reset_cb, Run());
659 codec->ProduceOneOutput(MockMediaCodecBridge::kEos);
660 PumpCodec();
661 testing::Mock::VerifyAndClearExpectations(&reset_cb);
662 }
663
TEST_P(MediaCodecVideoDecoderVp8Test,ResetDoesNotDrainVp8WithAsyncApi)664 TEST_P(MediaCodecVideoDecoderVp8Test, ResetDoesNotDrainVp8WithAsyncApi) {
665 EXPECT_CALL(*device_info_, IsAsyncApiSupported())
666 .WillRepeatedly(Return(true));
667
668 auto* codec =
669 InitializeFully_OneDecodePending(TestVideoConfig::Large(codec_));
670 // Accept the first decode to transition out of the flushed state.
671 codec->AcceptOneInput();
672 PumpCodec();
673
674 // The reset should complete immediately because the codec is not VP8 so
675 // it doesn't need draining. We don't expect a call to Flush on the codec
676 // since it will be deferred until the first decode after the reset.
677 base::MockCallback<base::OnceClosure> reset_cb;
678 EXPECT_CALL(reset_cb, Run());
679 mcvd_->Reset(reset_cb.Get());
680 // The reset should complete before destroying the codec, since TearDown will
681 // complete the drain for VP8. It still might not call reset since a drain
682 // for destroy probably doesn't, but either way we expect it before the drain.
683 testing::Mock::VerifyAndClearExpectations(&reset_cb);
684 }
685
TEST_P(MediaCodecVideoDecoderH264Test,ResetDoesNotDrainNonVp8Codecs)686 TEST_P(MediaCodecVideoDecoderH264Test, ResetDoesNotDrainNonVp8Codecs) {
687 auto* codec =
688 InitializeFully_OneDecodePending(TestVideoConfig::Large(codec_));
689 // Accept the first decode to transition out of the flushed state.
690 codec->AcceptOneInput();
691 PumpCodec();
692
693 // The reset should complete immediately because the codec is not VP8 so
694 // it doesn't need draining. We don't expect a call to Flush on the codec
695 // since it will be deferred until the first decode after the reset.
696 base::MockCallback<base::OnceClosure> reset_cb;
697 EXPECT_CALL(reset_cb, Run());
698 mcvd_->Reset(reset_cb.Get());
699 // The reset should complete before destroying the codec, since TearDown will
700 // complete the drain for VP8. It still might not call reset since a drain
701 // for destroy probably doesn't, but either way we expect it before the drain.
702 testing::Mock::VerifyAndClearExpectations(&reset_cb);
703 }
704
TEST_P(MediaCodecVideoDecoderVp8Test,TeardownCompletesPendingReset)705 TEST_P(MediaCodecVideoDecoderVp8Test, TeardownCompletesPendingReset) {
706 auto* codec =
707 InitializeFully_OneDecodePending(TestVideoConfig::Large(codec_));
708
709 // Accept the first decode to transition out of the flushed state.
710 codec->AcceptOneInput();
711 PumpCodec();
712
713 base::MockCallback<base::OnceClosure> reset_cb;
714 EXPECT_CALL(reset_cb, Run()).Times(0);
715 mcvd_->Reset(reset_cb.Get());
716 EXPECT_CALL(reset_cb, Run());
717 mcvd_.reset();
718
719 // VP8 codecs requiring draining for teardown to complete (tested below).
720 codec->ProduceOneOutput(MockMediaCodecBridge::kEos);
721 PumpCodec();
722 }
723
TEST_P(MediaCodecVideoDecoderTest,CodecFlushIsDeferredAfterDraining)724 TEST_P(MediaCodecVideoDecoderTest, CodecFlushIsDeferredAfterDraining) {
725 auto* codec =
726 InitializeFully_OneDecodePending(TestVideoConfig::Large(codec_));
727 mcvd_->Decode(DecoderBuffer::CreateEOSBuffer(), decode_cb_.Get());
728
729 // Produce one output that VFF will hold onto.
730 codec->AcceptOneInput();
731 codec->ProduceOneOutput();
732 PumpCodec();
733
734 // Drain the codec.
735 EXPECT_CALL(*codec, Flush()).Times(0);
736 codec->AcceptOneInput(MockMediaCodecBridge::kEos);
737 codec->ProduceOneOutput(MockMediaCodecBridge::kEos);
738 PumpCodec();
739
740 // Create a pending decode. The codec should still not be flushed because
741 // there is an unrendered output buffer.
742 mcvd_->Decode(fake_decoder_buffer_, decode_cb_.Get());
743 PumpCodec();
744
745 // Releasing the output buffer should now trigger a flush.
746 video_frame_factory_->last_output_buffer_.reset();
747 EXPECT_CALL(*codec, Flush());
748 PumpCodec();
749 }
750
TEST_P(MediaCodecVideoDecoderTest,EosDecodeCbIsRunAfterEosIsDequeued)751 TEST_P(MediaCodecVideoDecoderTest, EosDecodeCbIsRunAfterEosIsDequeued) {
752 auto* codec =
753 InitializeFully_OneDecodePending(TestVideoConfig::Large(codec_));
754 codec->AcceptOneInput();
755 PumpCodec();
756
757 base::MockCallback<VideoDecoder::DecodeCB> eos_decode_cb;
758 EXPECT_CALL(eos_decode_cb, Run(_)).Times(0);
759 mcvd_->Decode(DecoderBuffer::CreateEOSBuffer(), eos_decode_cb.Get());
760 codec->AcceptOneInput(MockMediaCodecBridge::kEos);
761 PumpCodec();
762
763 // On dequeueing EOS, MCVD will post a closure to run eos_decode_cb after
764 // pending video frames.
765 EXPECT_CALL(*video_frame_factory_, MockRunAfterPendingVideoFrames(_));
766 codec->ProduceOneOutput(MockMediaCodecBridge::kEos);
767 PumpCodec();
768
769 EXPECT_CALL(eos_decode_cb, Run(IsOkStatus()));
770 std::move(video_frame_factory_->last_closure_).Run();
771 }
772
TEST_P(MediaCodecVideoDecoderTest,TeardownInvalidatesCodecCreationWeakPtr)773 TEST_P(MediaCodecVideoDecoderTest, TeardownInvalidatesCodecCreationWeakPtr) {
774 InitializeWithTextureOwner_OneDecodePending(TestVideoConfig::Large(codec_));
775 mcvd_.reset();
776 EXPECT_CALL(*codec_allocator_, MockReleaseMediaCodec(NotNull()));
777 ASSERT_TRUE(codec_allocator_->ProvideMockCodecAsync());
778 }
779
TEST_P(MediaCodecVideoDecoderTest,TeardownInvalidatesCodecCreationWeakPtrButDoesNotCallReleaseMediaCodec)780 TEST_P(MediaCodecVideoDecoderTest,
781 TeardownInvalidatesCodecCreationWeakPtrButDoesNotCallReleaseMediaCodec) {
782 InitializeWithTextureOwner_OneDecodePending(TestVideoConfig::Large(codec_));
783 mcvd_.reset();
784
785 // A null codec should not be released via ReleaseMediaCodec().
786 EXPECT_CALL(*codec_allocator_, MockReleaseMediaCodec(_)).Times(0);
787 codec_allocator_->ProvideNullCodecAsync();
788 }
789
TEST_P(MediaCodecVideoDecoderTest,TeardownDoesNotDrainFlushedCodecs)790 TEST_P(MediaCodecVideoDecoderTest, TeardownDoesNotDrainFlushedCodecs) {
791 InitializeFully_OneDecodePending(TestVideoConfig::Large(codec_));
792 // Since we assert that MCVD is destructed by default, this test verifies that
793 // MCVD is destructed without requiring the codec to output an EOS buffer.
794
795 // We assert this since, otherwise, we'll complete the drain for VP8 codecs in
796 // TearDown. This guarantees that we won't, so any drain started by MCVD
797 // won't complete. Otherwise, this tests nothing. Note that 'Drained' here
798 // is a bit of a misnomer; the mock codec doesn't track flushed.
799 ASSERT_TRUE(codec_allocator_->most_recent_codec->IsDrained());
800 }
801
TEST_P(MediaCodecVideoDecoderH264Test,TeardownDoesNotDrainNonVp8Codecs)802 TEST_P(MediaCodecVideoDecoderH264Test, TeardownDoesNotDrainNonVp8Codecs) {
803 auto* codec =
804 InitializeFully_OneDecodePending(TestVideoConfig::Large(codec_));
805 // Accept the first decode to transition out of the flushed state.
806 codec->AcceptOneInput();
807 PumpCodec();
808 // Since we assert that MCVD is destructed by default, this test verifies that
809 // MCVD is destructed without requiring the codec to output an EOS buffer.
810 // Remember that we do not complete the drain for non-VP8 codecs in TearDown.
811 }
812
TEST_P(MediaCodecVideoDecoderVp8Test,TeardownDrainsVp8CodecsBeforeDestruction)813 TEST_P(MediaCodecVideoDecoderVp8Test,
814 TeardownDrainsVp8CodecsBeforeDestruction) {
815 auto* codec =
816 InitializeFully_OneDecodePending(TestVideoConfig::Large(codec_));
817 // Accept the first decode to transition out of the flushed state.
818 codec->AcceptOneInput();
819 PumpCodec();
820
821 // MCVD should not be destructed immediately.
822 mcvd_.reset();
823 base::RunLoop().RunUntilIdle();
824
825 // It should be destructed after draining completes.
826 codec->AcceptOneInput(MockMediaCodecBridge::kEos);
827 codec->ProduceOneOutput(MockMediaCodecBridge::kEos);
828 EXPECT_CALL(*codec, Flush()).Times(0);
829 PumpCodec();
830 base::RunLoop().RunUntilIdle();
831 }
832
TEST_P(MediaCodecVideoDecoderTest,CdmInitializationWorksForL3)833 TEST_P(MediaCodecVideoDecoderTest, CdmInitializationWorksForL3) {
834 // Make sure that MCVD uses the cdm, and sends it along to the codec.
835 CreateCdm(true, false);
836 InitializeWithOverlay_OneDecodePending(
837 TestVideoConfig::NormalEncrypted(codec_));
838 ASSERT_TRUE(!!cdm_->ran_media_crypto_ready_cb);
839 ASSERT_EQ(surface_chooser_->current_state_.is_secure, true);
840 ASSERT_EQ(surface_chooser_->current_state_.is_required, false);
841 ASSERT_EQ(codec_allocator_->most_recent_config->codec_type, CodecType::kAny);
842 // We can't check for equality safely, but verify that something was provided.
843 ASSERT_TRUE(codec_allocator_->most_recent_config->media_crypto);
844 }
845
TEST_P(MediaCodecVideoDecoderTest,CdmInitializationWorksForL1)846 TEST_P(MediaCodecVideoDecoderTest, CdmInitializationWorksForL1) {
847 // Make sure that MCVD uses the cdm, and sends it along to the codec.
848 CreateCdm(true, true);
849 InitializeWithOverlay_OneDecodePending(
850 TestVideoConfig::NormalEncrypted(codec_));
851 ASSERT_TRUE(!!cdm_->ran_media_crypto_ready_cb);
852 ASSERT_EQ(surface_chooser_->current_state_.is_secure, true);
853 ASSERT_EQ(surface_chooser_->current_state_.is_required, true);
854 ASSERT_EQ(codec_allocator_->most_recent_config->codec_type,
855 CodecType::kSecure);
856 ASSERT_TRUE(codec_allocator_->most_recent_config->media_crypto);
857 }
858
TEST_P(MediaCodecVideoDecoderTest,CdmIsSetEvenForClearStream)859 TEST_P(MediaCodecVideoDecoderTest, CdmIsSetEvenForClearStream) {
860 // Make sure that MCVD uses the cdm, and sends it along to the codec.
861 CreateCdm(true, false);
862 // We use the Large config, since VPx can be rejected if it's too small, in
863 // favor of software decode, since this is unencrypted.
864 InitializeWithOverlay_OneDecodePending(TestVideoConfig::Large(codec_));
865 ASSERT_TRUE(!!cdm_->ran_media_crypto_ready_cb);
866 ASSERT_EQ(surface_chooser_->current_state_.is_secure, true);
867 ASSERT_EQ(surface_chooser_->current_state_.is_required, false);
868 ASSERT_NE(codec_allocator_->most_recent_config->codec_type,
869 CodecType::kSecure);
870 // We can't check for equality safely, but verify that something was provided.
871 ASSERT_TRUE(codec_allocator_->most_recent_config->media_crypto);
872 }
873
TEST_P(MediaCodecVideoDecoderTest,NoMediaCryptoContext_ClearStream)874 TEST_P(MediaCodecVideoDecoderTest, NoMediaCryptoContext_ClearStream) {
875 // Make sure that MCVD initializes for clear stream when MediaCryptoContext
876 // is not available.
877 CreateCdm(false, false);
878 InitializeWithOverlay_OneDecodePending(TestVideoConfig::Normal(codec_));
879 ASSERT_FALSE(!!cdm_->media_crypto_ready_cb);
880 ASSERT_FALSE(!!cdm_->ran_media_crypto_ready_cb);
881 ASSERT_EQ(surface_chooser_->current_state_.is_secure, false);
882 ASSERT_EQ(surface_chooser_->current_state_.is_required, false);
883 ASSERT_NE(codec_allocator_->most_recent_config->codec_type,
884 CodecType::kSecure);
885 ASSERT_FALSE(codec_allocator_->most_recent_config->media_crypto);
886 }
887
TEST_P(MediaCodecVideoDecoderTest,NoMediaCryptoContext_EncryptedStream)888 TEST_P(MediaCodecVideoDecoderTest, NoMediaCryptoContext_EncryptedStream) {
889 // Make sure that MCVD fails to initialize for encrypted stream when
890 // MediaCryptoContext is not available.
891 CreateCdm(false, false);
892 ASSERT_FALSE(Initialize(TestVideoConfig::NormalEncrypted(codec_)));
893 }
894
TEST_P(MediaCodecVideoDecoderTest,MissingMediaCryptoFailsInit)895 TEST_P(MediaCodecVideoDecoderTest, MissingMediaCryptoFailsInit) {
896 // Encrypted media that doesn't get a mediacrypto should fail to init.
897 CreateCdm(true, true);
898 media_crypto_ = nullptr;
899 ASSERT_FALSE(Initialize(TestVideoConfig::NormalEncrypted(codec_)));
900 }
901
TEST_P(MediaCodecVideoDecoderTest,MissingCdmFailsInit)902 TEST_P(MediaCodecVideoDecoderTest, MissingCdmFailsInit) {
903 // MCVD should fail init if we don't provide a cdm with an encrypted config.
904 ASSERT_FALSE(Initialize(TestVideoConfig::NormalEncrypted(codec_)));
905 }
906
TEST_P(MediaCodecVideoDecoderTest,VideoFramesArePowerEfficient)907 TEST_P(MediaCodecVideoDecoderTest, VideoFramesArePowerEfficient) {
908 // MCVD should mark video frames as POWER_EFFICIENT.
909 auto* codec =
910 InitializeFully_OneDecodePending(TestVideoConfig::Large(codec_));
911
912 // Produce one output.
913 codec->AcceptOneInput();
914 codec->ProduceOneOutput();
915 EXPECT_CALL(*video_frame_factory_, MockCreateVideoFrame(_, _, _, _, _));
916 PumpCodec();
917 base::RunLoop().RunUntilIdle();
918
919 EXPECT_TRUE(!!most_recent_frame_);
920 EXPECT_TRUE(most_recent_frame_->metadata()->power_efficient);
921 }
922
TEST_P(MediaCodecVideoDecoderH264Test,CsdIsIncludedInCodecConfig)923 TEST_P(MediaCodecVideoDecoderH264Test, CsdIsIncludedInCodecConfig) {
924 // Make sure that any CSD is included in the CodecConfig that MCVD uses to
925 // allocate the codec.
926 VideoDecoderConfig config = TestVideoConfig::NormalH264();
927
928 // Csd, excluding '0 0 0 1'.
929 std::vector<uint8_t> csd0 = {103, 77, 64, 30, 232, 128, 80, 23,
930 252, 184, 8, 128, 0, 0, 3, 0,
931 128, 0, 0, 30, 7, 139, 22, 137};
932 std::vector<uint8_t> csd1 = {104, 235, 239, 32};
933 std::vector<uint8_t> extra_data_separator = {1, 0, 4};
934 std::vector<uint8_t> extra_data = {1, 77, 64, 30, 255, 225, 0, 24};
935 extra_data.insert(extra_data.end(), csd0.begin(), csd0.end());
936 extra_data.insert(extra_data.end(), extra_data_separator.begin(),
937 extra_data_separator.end());
938 extra_data.insert(extra_data.end(), csd1.begin(), csd1.end());
939 config.SetExtraData(extra_data);
940
941 EXPECT_TRUE(InitializeFully_OneDecodePending(config));
942
943 // Prepend the headers and check for equality.
944 std::vector<uint8_t> csd_header = {0, 0, 0, 1};
945 csd0.insert(csd0.begin(), csd_header.begin(), csd_header.end());
946 EXPECT_EQ(csd0, codec_allocator_->most_recent_config->csd0);
947 csd1.insert(csd1.begin(), csd_header.begin(), csd_header.end());
948 EXPECT_EQ(csd1, codec_allocator_->most_recent_config->csd1);
949 }
950
TEST_P(MediaCodecVideoDecoderVp9Test,ColorSpaceIsIncludedInCodecConfig)951 TEST_P(MediaCodecVideoDecoderVp9Test, ColorSpaceIsIncludedInCodecConfig) {
952 VideoColorSpace color_space(VideoColorSpace::PrimaryID::BT2020,
953 VideoColorSpace::TransferID::SMPTEST2084,
954 VideoColorSpace::MatrixID::BT2020_CL,
955 gfx::ColorSpace::RangeID::LIMITED);
956 VideoDecoderConfig config =
957 TestVideoConfig::NormalWithColorSpace(kCodecVP9, color_space);
958 EXPECT_TRUE(InitializeFully_OneDecodePending(config));
959
960 EXPECT_EQ(color_space,
961 codec_allocator_->most_recent_config->container_color_space);
962 }
963
TEST_P(MediaCodecVideoDecoderVp9Test,HdrMetadataIsIncludedInCodecConfig)964 TEST_P(MediaCodecVideoDecoderVp9Test, HdrMetadataIsIncludedInCodecConfig) {
965 VideoDecoderConfig config = TestVideoConfig::Normal(kCodecVP9);
966 gfx::HDRMetadata hdr_metadata;
967 hdr_metadata.max_frame_average_light_level = 123;
968 hdr_metadata.max_content_light_level = 456;
969 hdr_metadata.mastering_metadata.primary_r.set_x(0.1f);
970 hdr_metadata.mastering_metadata.primary_r.set_y(0.2f);
971 hdr_metadata.mastering_metadata.primary_g.set_x(0.3f);
972 hdr_metadata.mastering_metadata.primary_g.set_y(0.4f);
973 hdr_metadata.mastering_metadata.primary_b.set_x(0.5f);
974 hdr_metadata.mastering_metadata.primary_b.set_y(0.6f);
975 hdr_metadata.mastering_metadata.white_point.set_x(0.7f);
976 hdr_metadata.mastering_metadata.white_point.set_y(0.8f);
977 hdr_metadata.mastering_metadata.luminance_max = 1000;
978 hdr_metadata.mastering_metadata.luminance_min = 0;
979
980 config.set_hdr_metadata(hdr_metadata);
981
982 EXPECT_TRUE(InitializeFully_OneDecodePending(config));
983
984 EXPECT_EQ(hdr_metadata, codec_allocator_->most_recent_config->hdr_metadata);
985 }
986
GetTestList()987 static std::vector<VideoCodec> GetTestList() {
988 std::vector<VideoCodec> test_codecs;
989
990 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
991 if (MediaCodecUtil::IsMediaCodecAvailable())
992 test_codecs.push_back(kCodecH264);
993 #endif
994
995 if (MediaCodecUtil::IsVp8DecoderAvailable())
996 test_codecs.push_back(kCodecVP8);
997 if (MediaCodecUtil::IsVp9DecoderAvailable())
998 test_codecs.push_back(kCodecVP9);
999 return test_codecs;
1000 }
1001
1002 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
GetH264IfAvailable()1003 static std::vector<VideoCodec> GetH264IfAvailable() {
1004 return MediaCodecUtil::IsMediaCodecAvailable()
1005 ? std::vector<VideoCodec>(1, kCodecH264)
1006 : std::vector<VideoCodec>();
1007 }
1008 #endif
1009
GetVp8IfAvailable()1010 static std::vector<VideoCodec> GetVp8IfAvailable() {
1011 return MediaCodecUtil::IsVp8DecoderAvailable()
1012 ? std::vector<VideoCodec>(1, kCodecVP8)
1013 : std::vector<VideoCodec>();
1014 }
1015
1016 INSTANTIATE_TEST_SUITE_P(MediaCodecVideoDecoderTest,
1017 MediaCodecVideoDecoderTest,
1018 testing::ValuesIn(GetTestList()));
1019
1020 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
1021 INSTANTIATE_TEST_SUITE_P(MediaCodecVideoDecoderH264Test,
1022 MediaCodecVideoDecoderH264Test,
1023 testing::ValuesIn(GetH264IfAvailable()));
1024 #endif
1025
1026 INSTANTIATE_TEST_SUITE_P(MediaCodecVideoDecoderVp8Test,
1027 MediaCodecVideoDecoderVp8Test,
1028 testing::ValuesIn(GetVp8IfAvailable()));
1029
1030 } // namespace media
1031