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