[M120 Migration][MM][CAPI] Fix the logic for media using capi player.
[platform/framework/web/chromium-efl.git] / media / mojo / services / stable_video_decoder_service_unittest.cc
1 // Copyright 2022 The Chromium Authors
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 <sys/mman.h>
6
7 #include "base/posix/eintr_wrapper.h"
8 #include "base/test/mock_callback.h"
9 #include "base/test/task_environment.h"
10 #include "gpu/ipc/common/gpu_memory_buffer_support.h"
11 #include "media/mojo/common/mojo_decoder_buffer_converter.h"
12 #include "media/mojo/mojom/media_log.mojom.h"
13 #include "media/mojo/mojom/video_decoder.mojom.h"
14 #include "media/mojo/services/stable_video_decoder_factory_service.h"
15 #include "media/mojo/services/stable_video_decoder_service.h"
16 #include "mojo/public/cpp/bindings/associated_receiver.h"
17 #include "mojo/public/cpp/bindings/remote.h"
18 #include "mojo/public/cpp/system/data_pipe.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "ui/gfx/gpu_memory_buffer.h"
22
23 using testing::_;
24 using testing::ByMove;
25 using testing::Mock;
26 using testing::Return;
27 using testing::SaveArg;
28 using testing::StrictMock;
29 using testing::WithArgs;
30
31 namespace media {
32
33 namespace {
34
35 VideoDecoderConfig CreateValidVideoDecoderConfig() {
36   const VideoDecoderConfig config(
37       VideoCodec::kH264, VideoCodecProfile::H264PROFILE_BASELINE,
38       VideoDecoderConfig::AlphaMode::kHasAlpha, VideoColorSpace::REC709(),
39       VideoTransformation(VIDEO_ROTATION_90, /*mirrored=*/true),
40       /*coded_size=*/gfx::Size(640, 368),
41       /*visible_rect=*/gfx::Rect(1, 1, 630, 360),
42       /*natural_size=*/gfx::Size(1260, 720),
43       /*extra_data=*/std::vector<uint8_t>{1, 2, 3},
44       EncryptionScheme::kUnencrypted);
45   DCHECK(config.IsValidConfig());
46   return config;
47 }
48
49 scoped_refptr<VideoFrame> CreateTestNV12GpuMemoryBufferVideoFrame() {
50   gfx::GpuMemoryBufferHandle gmb_handle;
51   gmb_handle.type = gfx::NATIVE_PIXMAP;
52
53   // We need to create something that looks like a dma-buf in order to pass the
54   // validation in the mojo traits, so we use memfd_create() + ftruncate().
55   auto y_fd = base::ScopedFD(memfd_create("nv12_dummy_buffer", 0));
56   if (!y_fd.is_valid()) {
57     return nullptr;
58   }
59   if (HANDLE_EINTR(ftruncate(y_fd.get(), 280000 + 140000)) < 0) {
60     return nullptr;
61   }
62   auto uv_fd = base::ScopedFD(HANDLE_EINTR(dup(y_fd.get())));
63   if (!uv_fd.is_valid()) {
64     return nullptr;
65   }
66
67   gfx::NativePixmapPlane y_plane;
68   y_plane.stride = 700;
69   y_plane.offset = 0;
70   y_plane.size = 280000;
71   y_plane.fd = std::move(y_fd);
72   gmb_handle.native_pixmap_handle.planes.push_back(std::move(y_plane));
73
74   gfx::NativePixmapPlane uv_plane;
75   uv_plane.stride = 700;
76   uv_plane.offset = 280000;
77   uv_plane.size = 140000;
78   uv_plane.fd = std::move(uv_fd);
79   gmb_handle.native_pixmap_handle.planes.push_back(std::move(uv_plane));
80
81   gpu::GpuMemoryBufferSupport gmb_support;
82   auto gmb = gmb_support.CreateGpuMemoryBufferImplFromHandle(
83       std::move(gmb_handle), gfx::Size(640, 368),
84       gfx::BufferFormat::YUV_420_BIPLANAR, gfx::BufferUsage::SCANOUT_VDA_WRITE,
85       base::DoNothing());
86   if (!gmb) {
87     return nullptr;
88   }
89
90   gpu::MailboxHolder dummy_mailbox[media::VideoFrame::kMaxPlanes];
91   auto gmb_video_frame = VideoFrame::WrapExternalGpuMemoryBuffer(
92       /*visible_rect=*/gfx::Rect(640, 368),
93       /*natural_size=*/gfx::Size(640, 368), std::move(gmb), dummy_mailbox,
94       base::NullCallback(), base::TimeDelta());
95   if (!gmb_video_frame) {
96     return nullptr;
97   }
98
99   gmb_video_frame->metadata().allow_overlay = true;
100   gmb_video_frame->metadata().end_of_stream = false;
101   gmb_video_frame->metadata().read_lock_fences_enabled = true;
102   gmb_video_frame->metadata().power_efficient = true;
103
104   return gmb_video_frame;
105 }
106
107 class MockVideoFrameHandleReleaser : public mojom::VideoFrameHandleReleaser {
108  public:
109   explicit MockVideoFrameHandleReleaser(
110       mojo::PendingReceiver<mojom::VideoFrameHandleReleaser>
111           video_frame_handle_releaser)
112       : video_frame_handle_releaser_receiver_(
113             this,
114             std::move(video_frame_handle_releaser)) {}
115   MockVideoFrameHandleReleaser(const MockVideoFrameHandleReleaser&) = delete;
116   MockVideoFrameHandleReleaser& operator=(const MockVideoFrameHandleReleaser&) =
117       delete;
118   ~MockVideoFrameHandleReleaser() override = default;
119
120   // mojom::VideoFrameHandleReleaser implementation.
121   MOCK_METHOD2(ReleaseVideoFrame,
122                void(const base::UnguessableToken& release_token,
123                     const absl::optional<gpu::SyncToken>& release_sync_token));
124
125  private:
126   mojo::Receiver<mojom::VideoFrameHandleReleaser>
127       video_frame_handle_releaser_receiver_;
128 };
129
130 class MockVideoDecoder : public mojom::VideoDecoder {
131  public:
132   MockVideoDecoder() = default;
133   MockVideoDecoder(const MockVideoDecoder&) = delete;
134   MockVideoDecoder& operator=(const MockVideoDecoder&) = delete;
135   ~MockVideoDecoder() override = default;
136
137   mojo::AssociatedRemote<mojom::VideoDecoderClient> TakeClientRemote() {
138     return std::move(client_remote_);
139   }
140   mojo::Remote<mojom::MediaLog> TakeMediaLogRemote() {
141     return std::move(media_log_remote_);
142   }
143   std::unique_ptr<StrictMock<MockVideoFrameHandleReleaser>>
144   TakeVideoFrameHandleReleaser() {
145     return std::move(video_frame_handle_releaser_);
146   }
147   std::unique_ptr<MojoDecoderBufferReader> TakeMojoDecoderBufferReader() {
148     return std::move(mojo_decoder_buffer_reader_);
149   }
150
151   // mojom::VideoDecoder implementation.
152   MOCK_METHOD1(GetSupportedConfigs, void(GetSupportedConfigsCallback callback));
153   void Construct(
154       mojo::PendingAssociatedRemote<mojom::VideoDecoderClient> client,
155       mojo::PendingRemote<mojom::MediaLog> media_log,
156       mojo::PendingReceiver<mojom::VideoFrameHandleReleaser>
157           video_frame_handle_releaser,
158       mojo::ScopedDataPipeConsumerHandle decoder_buffer_pipe,
159       mojom::CommandBufferIdPtr command_buffer_id,
160       const gfx::ColorSpace& target_color_space) final {
161     client_remote_.Bind(std::move(client));
162     media_log_remote_.Bind(std::move(media_log));
163     video_frame_handle_releaser_ =
164         std::make_unique<StrictMock<MockVideoFrameHandleReleaser>>(
165             std::move(video_frame_handle_releaser));
166     mojo_decoder_buffer_reader_ = std::make_unique<MojoDecoderBufferReader>(
167         std::move(decoder_buffer_pipe));
168     DoConstruct(std::move(command_buffer_id), target_color_space);
169   }
170   MOCK_METHOD2(DoConstruct,
171                void(mojom::CommandBufferIdPtr command_buffer_id,
172                     const gfx::ColorSpace& target_color_space));
173   MOCK_METHOD4(Initialize,
174                void(const VideoDecoderConfig& config,
175                     bool low_delay,
176                     const absl::optional<base::UnguessableToken>& cdm_id,
177                     InitializeCallback callback));
178   MOCK_METHOD2(Decode,
179                void(mojom::DecoderBufferPtr buffer, DecodeCallback callback));
180   MOCK_METHOD1(Reset, void(ResetCallback callback));
181   MOCK_METHOD1(OnOverlayInfoChanged, void(const OverlayInfo& overlay_info));
182
183  private:
184   mojo::AssociatedRemote<mojom::VideoDecoderClient> client_remote_;
185   mojo::Remote<mojom::MediaLog> media_log_remote_;
186   std::unique_ptr<StrictMock<MockVideoFrameHandleReleaser>>
187       video_frame_handle_releaser_;
188   std::unique_ptr<MojoDecoderBufferReader> mojo_decoder_buffer_reader_;
189 };
190
191 class MockStableVideoDecoderTracker
192     : public stable::mojom::StableVideoDecoderTracker {};
193
194 class MockStableVideoDecoderClient : public stable::mojom::VideoDecoderClient {
195  public:
196   explicit MockStableVideoDecoderClient(
197       mojo::PendingAssociatedReceiver<stable::mojom::VideoDecoderClient>
198           pending_receiver)
199       : receiver_(this, std::move(pending_receiver)) {}
200   MockStableVideoDecoderClient(const MockStableVideoDecoderClient&) = delete;
201   MockStableVideoDecoderClient& operator=(const MockStableVideoDecoderClient&) =
202       delete;
203   ~MockStableVideoDecoderClient() override = default;
204
205   // stable::mojom::VideoDecoderClient implementation.
206   MOCK_METHOD3(OnVideoFrameDecoded,
207                void(stable::mojom::VideoFramePtr frame,
208                     bool can_read_without_stalling,
209                     const base::UnguessableToken& release_token));
210   MOCK_METHOD1(OnWaiting, void(WaitingReason reason));
211
212  private:
213   mojo::AssociatedReceiver<stable::mojom::VideoDecoderClient> receiver_;
214 };
215
216 class MockStableMediaLog : public stable::mojom::MediaLog {
217  public:
218   explicit MockStableMediaLog(
219       mojo::PendingReceiver<stable::mojom::MediaLog> pending_receiver)
220       : receiver_(this, std::move(pending_receiver)) {}
221   MockStableMediaLog(const MockStableMediaLog&) = delete;
222   MockStableMediaLog& operator=(const MockStableMediaLog&) = delete;
223   ~MockStableMediaLog() override = default;
224
225   // stable::mojom::MediaLog implementation.
226   MOCK_METHOD1(AddLogRecord, void(const MediaLogRecord& event));
227
228  private:
229   mojo::Receiver<stable::mojom::MediaLog> receiver_;
230 };
231
232 // AuxiliaryEndpoints groups the endpoints that support the operation of a
233 // StableVideoDecoderService and that come from the Construct() call. That way,
234 // tests can easily poke at one endpoint and set expectations on the other. For
235 // example, a test might want to simulate the scenario in which a frame has been
236 // decoded by the underlying mojom::VideoDecoder. In this case, the test can
237 // call |video_decoder_client_remote|->OnVideoFrameDecoded() and then set an
238 // expectation on |mock_stable_video_decoder_client|->OnVideoFrameDecoded().
239 struct AuxiliaryEndpoints {
240   // |video_decoder_client_remote| is the client that the underlying
241   // mojom::VideoDecoder receives through the Construct() call. Tests can make
242   // calls on it and those calls should ultimately be received by the
243   // |mock_stable_video_decoder_client|.
244   mojo::AssociatedRemote<mojom::VideoDecoderClient> video_decoder_client_remote;
245   std::unique_ptr<StrictMock<MockStableVideoDecoderClient>>
246       mock_stable_video_decoder_client;
247
248   // |media_log_remote| is the MediaLog that the underlying mojom::VideoDecoder
249   // receives through the Construct() call. Tests can make calls on it and those
250   // calls should ultimately be received by the |mock_stable_media_log|.
251   mojo::Remote<mojom::MediaLog> media_log_remote;
252   std::unique_ptr<StrictMock<MockStableMediaLog>> mock_stable_media_log;
253
254   // Tests can use |stable_video_frame_handle_releaser_remote| to simulate
255   // releasing a VideoFrame.
256   // |mock_video_frame_handle_releaser| is the VideoFrameHandleReleaser that's
257   // setup when the underlying mojom::VideoDecoder receives a Construct() call.
258   // Tests can make calls on |stable_video_frame_handle_releaser_remote| and
259   // they should be ultimately received by the
260   // |mock_video_frame_handle_releaser|.
261   mojo::Remote<stable::mojom::VideoFrameHandleReleaser>
262       stable_video_frame_handle_releaser_remote;
263   std::unique_ptr<StrictMock<MockVideoFrameHandleReleaser>>
264       mock_video_frame_handle_releaser;
265
266   // |mojo_decoder_buffer_reader| wraps the reading end of the data pipe that
267   // the underlying mojom::VideoDecoder receives through the Construct() call.
268   // Tests can write data using the |mojo_decoder_buffer_writer| and that data
269   // should be ultimately received by the |mojo_decoder_buffer_reader|.
270   std::unique_ptr<MojoDecoderBufferWriter> mojo_decoder_buffer_writer;
271   std::unique_ptr<MojoDecoderBufferReader> mojo_decoder_buffer_reader;
272 };
273
274 // Calls Construct() on |stable_video_decoder_remote| and, if
275 // |expect_construct_call| is true, expects a corresponding Construct() call on
276 // |mock_video_decoder| which is assumed to be the backing decoder of
277 // |stable_video_decoder_remote|. Returns nullptr if the expectations on
278 // |mock_video_decoder| are violated. Otherwise, returns an AuxiliaryEndpoints
279 // instance that contains the supporting endpoints that tests can use to
280 // interact with the auxiliary interfaces used by the
281 // |stable_video_decoder_remote|.
282 std::unique_ptr<AuxiliaryEndpoints> ConstructStableVideoDecoder(
283     mojo::Remote<stable::mojom::StableVideoDecoder>&
284         stable_video_decoder_remote,
285     StrictMock<MockVideoDecoder>& mock_video_decoder,
286     bool expect_construct_call) {
287   constexpr gfx::ColorSpace kTargetColorSpace = gfx::ColorSpace::CreateSRGB();
288   if (expect_construct_call) {
289     EXPECT_CALL(mock_video_decoder,
290                 DoConstruct(/*command_buffer_id=*/_,
291                             /*target_color_space=*/kTargetColorSpace));
292   }
293   mojo::PendingAssociatedRemote<stable::mojom::VideoDecoderClient>
294       stable_video_decoder_client_remote;
295   auto mock_stable_video_decoder_client =
296       std::make_unique<StrictMock<MockStableVideoDecoderClient>>(
297           stable_video_decoder_client_remote
298               .InitWithNewEndpointAndPassReceiver());
299
300   mojo::PendingRemote<stable::mojom::MediaLog> stable_media_log_remote;
301   auto mock_stable_media_log = std::make_unique<StrictMock<MockStableMediaLog>>(
302       stable_media_log_remote.InitWithNewPipeAndPassReceiver());
303
304   mojo::Remote<stable::mojom::VideoFrameHandleReleaser>
305       video_frame_handle_releaser_remote;
306
307   mojo::ScopedDataPipeConsumerHandle remote_consumer_handle;
308   std::unique_ptr<MojoDecoderBufferWriter> mojo_decoder_buffer_writer =
309       MojoDecoderBufferWriter::Create(
310           GetDefaultDecoderBufferConverterCapacity(DemuxerStream::VIDEO),
311           &remote_consumer_handle);
312
313   stable_video_decoder_remote->Construct(
314       std::move(stable_video_decoder_client_remote),
315       std::move(stable_media_log_remote),
316       video_frame_handle_releaser_remote.BindNewPipeAndPassReceiver(),
317       std::move(remote_consumer_handle), kTargetColorSpace);
318   stable_video_decoder_remote.FlushForTesting();
319
320   if (!Mock::VerifyAndClearExpectations(&mock_video_decoder))
321     return nullptr;
322
323   auto auxiliary_endpoints = std::make_unique<AuxiliaryEndpoints>();
324
325   auxiliary_endpoints->video_decoder_client_remote =
326       mock_video_decoder.TakeClientRemote();
327   auxiliary_endpoints->mock_stable_video_decoder_client =
328       std::move(mock_stable_video_decoder_client);
329
330   auxiliary_endpoints->media_log_remote =
331       mock_video_decoder.TakeMediaLogRemote();
332   auxiliary_endpoints->mock_stable_media_log = std::move(mock_stable_media_log);
333
334   auxiliary_endpoints->stable_video_frame_handle_releaser_remote =
335       std::move(video_frame_handle_releaser_remote);
336   auxiliary_endpoints->mock_video_frame_handle_releaser =
337       mock_video_decoder.TakeVideoFrameHandleReleaser();
338
339   auxiliary_endpoints->mojo_decoder_buffer_writer =
340       std::move(mojo_decoder_buffer_writer);
341   auxiliary_endpoints->mojo_decoder_buffer_reader =
342       mock_video_decoder.TakeMojoDecoderBufferReader();
343
344   return auxiliary_endpoints;
345 }
346
347 class StableVideoDecoderServiceTest : public testing::Test {
348  public:
349   StableVideoDecoderServiceTest()
350       : stable_video_decoder_factory_service_(
351             gpu::GpuFeatureInfo(),
352             /*enable_direct_video_decoder=*/true) {
353     stable_video_decoder_factory_service_
354         .SetVideoDecoderCreationCallbackForTesting(
355             video_decoder_creation_cb_.Get());
356   }
357
358   StableVideoDecoderServiceTest(const StableVideoDecoderServiceTest&) = delete;
359   StableVideoDecoderServiceTest& operator=(
360       const StableVideoDecoderServiceTest&) = delete;
361   ~StableVideoDecoderServiceTest() override = default;
362
363   void SetUp() override {
364     mojo::PendingReceiver<stable::mojom::StableVideoDecoderFactory>
365         stable_video_decoder_factory_receiver;
366     stable_video_decoder_factory_remote_ =
367         mojo::Remote<stable::mojom::StableVideoDecoderFactory>(
368             stable_video_decoder_factory_receiver
369                 .InitWithNewPipeAndPassRemote());
370     stable_video_decoder_factory_service_.BindReceiver(
371         std::move(stable_video_decoder_factory_receiver),
372         /*disconnect_cb=*/base::DoNothing());
373     ASSERT_TRUE(stable_video_decoder_factory_remote_.is_connected());
374   }
375
376  protected:
377   mojo::Remote<stable::mojom::StableVideoDecoder> CreateStableVideoDecoder(
378       std::unique_ptr<StrictMock<MockVideoDecoder>> dst_video_decoder,
379       mojo::PendingRemote<stable::mojom::StableVideoDecoderTracker> tracker) {
380     // Each CreateStableVideoDecoder() should result in exactly one call to the
381     // video decoder creation callback, i.e., the
382     // StableVideoDecoderFactoryService should not re-use mojom::VideoDecoder
383     // implementation instances.
384     EXPECT_CALL(video_decoder_creation_cb_, Run(_, _))
385         .WillOnce(Return(ByMove(std::move(dst_video_decoder))));
386     mojo::PendingReceiver<stable::mojom::StableVideoDecoder>
387         stable_video_decoder_receiver;
388     mojo::Remote<stable::mojom::StableVideoDecoder> video_decoder_remote(
389         stable_video_decoder_receiver.InitWithNewPipeAndPassRemote());
390     stable_video_decoder_factory_remote_->CreateStableVideoDecoder(
391         std::move(stable_video_decoder_receiver), std::move(tracker));
392     stable_video_decoder_factory_remote_.FlushForTesting();
393     if (!Mock::VerifyAndClearExpectations(&video_decoder_creation_cb_))
394       return {};
395     return video_decoder_remote;
396   }
397
398   base::test::TaskEnvironment task_environment_;
399   StrictMock<base::MockRepeatingCallback<std::unique_ptr<
400       mojom::VideoDecoder>(MojoMediaClient*, MojoCdmServiceContext*)>>
401       video_decoder_creation_cb_;
402   StableVideoDecoderFactoryService stable_video_decoder_factory_service_;
403   mojo::Remote<stable::mojom::StableVideoDecoderFactory>
404       stable_video_decoder_factory_remote_;
405   mojo::Remote<stable::mojom::StableVideoDecoder> stable_video_decoder_remote_;
406 };
407
408 // Tests that we can create multiple StableVideoDecoder implementation instances
409 // through the StableVideoDecoderFactory and that they can exist concurrently.
410 TEST_F(StableVideoDecoderServiceTest, FactoryCanCreateStableVideoDecoders) {
411   std::vector<mojo::Remote<stable::mojom::StableVideoDecoder>>
412       stable_video_decoder_remotes;
413   constexpr size_t kNumConcurrentDecoders = 5u;
414   for (size_t i = 0u; i < kNumConcurrentDecoders; i++) {
415     auto mock_video_decoder = std::make_unique<StrictMock<MockVideoDecoder>>();
416     auto stable_video_decoder_remote =
417         CreateStableVideoDecoder(std::move(mock_video_decoder), /*tracker=*/{});
418     stable_video_decoder_remotes.push_back(
419         std::move(stable_video_decoder_remote));
420   }
421   for (const auto& remote : stable_video_decoder_remotes) {
422     ASSERT_TRUE(remote.is_bound());
423     ASSERT_TRUE(remote.is_connected());
424   }
425 }
426
427 // Tests that a call to stable::mojom::VideoDecoder::Construct() gets routed
428 // correctly to the underlying mojom::VideoDecoder.
429 TEST_F(StableVideoDecoderServiceTest, StableVideoDecoderCanBeConstructed) {
430   auto mock_video_decoder = std::make_unique<StrictMock<MockVideoDecoder>>();
431   auto* mock_video_decoder_raw = mock_video_decoder.get();
432   auto stable_video_decoder_remote =
433       CreateStableVideoDecoder(std::move(mock_video_decoder), /*tracker=*/{});
434   ASSERT_TRUE(stable_video_decoder_remote.is_bound());
435   ASSERT_TRUE(stable_video_decoder_remote.is_connected());
436   ASSERT_TRUE(ConstructStableVideoDecoder(stable_video_decoder_remote,
437                                           *mock_video_decoder_raw,
438                                           /*expect_construct_call=*/true));
439 }
440
441 // Tests that if two calls to stable::mojom::VideoDecoder::Construct() are made,
442 // only one is routed to the underlying mojom::VideoDecoder.
443 TEST_F(StableVideoDecoderServiceTest,
444        StableVideoDecoderCannotBeConstructedTwice) {
445   auto mock_video_decoder = std::make_unique<StrictMock<MockVideoDecoder>>();
446   auto* mock_video_decoder_raw = mock_video_decoder.get();
447   auto stable_video_decoder_remote =
448       CreateStableVideoDecoder(std::move(mock_video_decoder), /*tracker=*/{});
449   ASSERT_TRUE(stable_video_decoder_remote.is_bound());
450   ASSERT_TRUE(stable_video_decoder_remote.is_connected());
451   EXPECT_TRUE(ConstructStableVideoDecoder(stable_video_decoder_remote,
452                                           *mock_video_decoder_raw,
453                                           /*expect_construct_call=*/true));
454   EXPECT_TRUE(ConstructStableVideoDecoder(stable_video_decoder_remote,
455                                           *mock_video_decoder_raw,
456                                           /*expect_construct_call=*/false));
457 }
458
459 // Tests that a call to stable::mojom::VideoDecoder::GetSupportedConfigs() gets
460 // routed correctly to the underlying mojom::VideoDecoder. Also tests that the
461 // underlying mojom::VideoDecoder's reply gets routed correctly back to the
462 // client.
463 TEST_F(StableVideoDecoderServiceTest,
464        StableVideoDecoderCanGetSupportedConfigs) {
465   auto mock_video_decoder = std::make_unique<StrictMock<MockVideoDecoder>>();
466   auto* mock_video_decoder_raw = mock_video_decoder.get();
467   auto stable_video_decoder_remote =
468       CreateStableVideoDecoder(std::move(mock_video_decoder), /*tracker=*/{});
469   ASSERT_TRUE(stable_video_decoder_remote.is_bound());
470   ASSERT_TRUE(stable_video_decoder_remote.is_connected());
471
472   StrictMock<base::MockOnceCallback<void(
473       const std::vector<SupportedVideoDecoderConfig>& supported_configs,
474       VideoDecoderType decoder_type)>>
475       get_supported_configs_cb_to_send;
476   mojom::VideoDecoder::GetSupportedConfigsCallback
477       received_get_supported_configs_cb;
478   constexpr VideoDecoderType kDecoderTypeToReplyWith = VideoDecoderType::kVaapi;
479   const std::vector<SupportedVideoDecoderConfig>
480       supported_configs_to_reply_with({
481           {/*profile_min=*/H264PROFILE_MIN, /*profile_max=*/H264PROFILE_MAX,
482            /*coded_size_min=*/gfx::Size(320, 180),
483            /*coded_size_max=*/gfx::Size(1280, 720), /*allow_encrypted=*/false,
484            /*require_encrypted=*/false},
485           {/*profile_min=*/VP9PROFILE_MIN, /*profile_max=*/VP9PROFILE_MAX,
486            /*coded_size_min=*/gfx::Size(8, 8),
487            /*coded_size_max=*/gfx::Size(640, 360), /*allow_encrypted=*/true,
488            /*require_encrypted=*/true},
489       });
490   std::vector<SupportedVideoDecoderConfig> received_supported_configs;
491
492   EXPECT_CALL(*mock_video_decoder_raw, GetSupportedConfigs(/*callback=*/_))
493       .WillOnce([&](mojom::VideoDecoder::GetSupportedConfigsCallback callback) {
494         received_get_supported_configs_cb = std::move(callback);
495       });
496   EXPECT_CALL(get_supported_configs_cb_to_send, Run(_, kDecoderTypeToReplyWith))
497       .WillOnce(SaveArg<0>(&received_supported_configs));
498
499   stable_video_decoder_remote->GetSupportedConfigs(
500       get_supported_configs_cb_to_send.Get());
501   stable_video_decoder_remote.FlushForTesting();
502   ASSERT_TRUE(Mock::VerifyAndClearExpectations(mock_video_decoder_raw));
503
504   std::move(received_get_supported_configs_cb)
505       .Run(supported_configs_to_reply_with, kDecoderTypeToReplyWith);
506   task_environment_.RunUntilIdle();
507
508   EXPECT_EQ(received_supported_configs, supported_configs_to_reply_with);
509 }
510
511 // Tests that a call to stable::mojom::VideoDecoder::Initialize() gets routed
512 // correctly to the underlying mojom::VideoDecoder. Also tests that when the
513 // underlying mojom::VideoDecoder calls the initialization callback, the call
514 // gets routed to the client.
515 TEST_F(StableVideoDecoderServiceTest, StableVideoDecoderCanBeInitialized) {
516   auto mock_video_decoder = std::make_unique<StrictMock<MockVideoDecoder>>();
517   auto* mock_video_decoder_raw = mock_video_decoder.get();
518   auto stable_video_decoder_remote =
519       CreateStableVideoDecoder(std::move(mock_video_decoder), /*tracker=*/{});
520   ASSERT_TRUE(stable_video_decoder_remote.is_bound());
521   ASSERT_TRUE(stable_video_decoder_remote.is_connected());
522   auto auxiliary_endpoints = ConstructStableVideoDecoder(
523       stable_video_decoder_remote, *mock_video_decoder_raw,
524       /*expect_construct_call=*/true);
525   ASSERT_TRUE(auxiliary_endpoints);
526
527   const VideoDecoderConfig config_to_send = CreateValidVideoDecoderConfig();
528   VideoDecoderConfig received_config;
529   constexpr bool kLowDelay = true;
530   constexpr absl::optional<base::UnguessableToken> kCdmId = absl::nullopt;
531   StrictMock<base::MockOnceCallback<void(
532       const media::DecoderStatus& status, bool needs_bitstream_conversion,
533       int32_t max_decode_requests, VideoDecoderType decoder_type,
534       bool needs_transcryption)>>
535       initialize_cb_to_send;
536   mojom::VideoDecoder::InitializeCallback received_initialize_cb;
537   const DecoderStatus kDecoderStatus = DecoderStatus::Codes::kAborted;
538   constexpr bool kNeedsBitstreamConversion = true;
539   constexpr int32_t kMaxDecodeRequests = 123;
540   constexpr VideoDecoderType kDecoderType = VideoDecoderType::kVda;
541
542   EXPECT_CALL(*mock_video_decoder_raw,
543               Initialize(/*config=*/_, kLowDelay, kCdmId,
544                          /*callback=*/_))
545       .WillOnce([&](const VideoDecoderConfig& config, bool low_delay,
546                     const absl::optional<base::UnguessableToken>& cdm_id,
547                     mojom::VideoDecoder::InitializeCallback callback) {
548         received_config = config;
549         received_initialize_cb = std::move(callback);
550       });
551   EXPECT_CALL(initialize_cb_to_send,
552               Run(kDecoderStatus, kNeedsBitstreamConversion, kMaxDecodeRequests,
553                   kDecoderType, /*needs_transcryption=*/false));
554   stable_video_decoder_remote->Initialize(
555       config_to_send, kLowDelay,
556       mojo::PendingRemote<stable::mojom::StableCdmContext>(),
557       initialize_cb_to_send.Get());
558   stable_video_decoder_remote.FlushForTesting();
559   ASSERT_TRUE(Mock::VerifyAndClearExpectations(mock_video_decoder_raw));
560
561   std::move(received_initialize_cb)
562       .Run(kDecoderStatus, kNeedsBitstreamConversion, kMaxDecodeRequests,
563            kDecoderType);
564   task_environment_.RunUntilIdle();
565 }
566
567 // Tests that the StableVideoDecoderService rejects a call to
568 // stable::mojom::VideoDecoder::Initialize() before
569 // stable::mojom::VideoDecoder::Construct() gets called.
570 TEST_F(StableVideoDecoderServiceTest,
571        StableVideoDecoderCannotBeInitializedBeforeConstruction) {
572   auto mock_video_decoder = std::make_unique<StrictMock<MockVideoDecoder>>();
573   auto stable_video_decoder_remote =
574       CreateStableVideoDecoder(std::move(mock_video_decoder), /*tracker=*/{});
575   ASSERT_TRUE(stable_video_decoder_remote.is_bound());
576   ASSERT_TRUE(stable_video_decoder_remote.is_connected());
577
578   const VideoDecoderConfig config_to_send = CreateValidVideoDecoderConfig();
579   constexpr bool kLowDelay = true;
580   StrictMock<base::MockOnceCallback<void(
581       const media::DecoderStatus& status, bool needs_bitstream_conversion,
582       int32_t max_decode_requests, VideoDecoderType decoder_type,
583       bool needs_transcryption)>>
584       initialize_cb_to_send;
585
586   EXPECT_CALL(initialize_cb_to_send,
587               Run(DecoderStatus(DecoderStatus::Codes::kFailed),
588                   /*needs_bitstream_conversion=*/false,
589                   /*max_decode_requests=*/1, VideoDecoderType::kUnknown,
590                   /*needs_transcryption=*/false));
591   stable_video_decoder_remote->Initialize(
592       config_to_send, kLowDelay,
593       mojo::PendingRemote<stable::mojom::StableCdmContext>(),
594       initialize_cb_to_send.Get());
595   stable_video_decoder_remote.FlushForTesting();
596 }
597
598 // Tests that a call to stable::mojom::VideoDecoder::Decode() gets routed
599 // correctly to the underlying mojom::VideoDecoder and that the data pipe is
600 // plumbed correctly. Also tests that when the underlying mojom::VideoDecoder
601 // calls the decode callback, the call gets routed to the client.
602 TEST_F(StableVideoDecoderServiceTest, StableVideoDecoderCanDecode) {
603   auto mock_video_decoder = std::make_unique<StrictMock<MockVideoDecoder>>();
604   auto* mock_video_decoder_raw = mock_video_decoder.get();
605   auto stable_video_decoder_remote =
606       CreateStableVideoDecoder(std::move(mock_video_decoder), /*tracker=*/{});
607   ASSERT_TRUE(stable_video_decoder_remote.is_bound());
608   ASSERT_TRUE(stable_video_decoder_remote.is_connected());
609   auto auxiliary_endpoints = ConstructStableVideoDecoder(
610       stable_video_decoder_remote, *mock_video_decoder_raw,
611       /*expect_construct_call=*/true);
612   ASSERT_TRUE(auxiliary_endpoints);
613   ASSERT_TRUE(auxiliary_endpoints->mojo_decoder_buffer_writer);
614   ASSERT_TRUE(auxiliary_endpoints->mojo_decoder_buffer_reader);
615
616   constexpr uint8_t kEncodedData[] = {1, 2, 3};
617   scoped_refptr<DecoderBuffer> decoder_buffer_to_send =
618       DecoderBuffer::CopyFrom(kEncodedData, std::size(kEncodedData));
619   decoder_buffer_to_send->WritableSideData().secure_handle = 42;
620   ASSERT_TRUE(decoder_buffer_to_send);
621   mojom::DecoderBufferPtr received_decoder_buffer_ptr;
622   scoped_refptr<DecoderBuffer> received_decoder_buffer;
623   StrictMock<base::MockOnceCallback<void(const media::DecoderStatus& status)>>
624       decode_cb_to_send;
625   mojom::VideoDecoder::DecodeCallback received_decode_cb;
626   const DecoderStatus kDecoderStatus = DecoderStatus::Codes::kAborted;
627
628   EXPECT_CALL(*mock_video_decoder_raw, Decode(/*buffer=*/_, /*callback=*/_))
629       .WillOnce([&](mojom::DecoderBufferPtr buffer,
630                     mojom::VideoDecoder::DecodeCallback callback) {
631         received_decoder_buffer_ptr = std::move(buffer);
632         received_decode_cb = std::move(callback);
633       });
634   EXPECT_CALL(decode_cb_to_send, Run(kDecoderStatus));
635   ASSERT_TRUE(
636       auxiliary_endpoints->mojo_decoder_buffer_writer->WriteDecoderBuffer(
637           decoder_buffer_to_send));
638   stable_video_decoder_remote->Decode(decoder_buffer_to_send,
639                                       decode_cb_to_send.Get());
640   stable_video_decoder_remote.FlushForTesting();
641   ASSERT_TRUE(Mock::VerifyAndClearExpectations(mock_video_decoder_raw));
642
643   ASSERT_TRUE(received_decoder_buffer_ptr);
644   auxiliary_endpoints->mojo_decoder_buffer_reader->ReadDecoderBuffer(
645       std::move(received_decoder_buffer_ptr),
646       base::BindOnce(
647           [](scoped_refptr<DecoderBuffer>* dst_buffer,
648              scoped_refptr<DecoderBuffer> buffer) {
649             *dst_buffer = std::move(buffer);
650           },
651           &received_decoder_buffer));
652   task_environment_.RunUntilIdle();
653   ASSERT_TRUE(received_decoder_buffer);
654   EXPECT_TRUE(
655       received_decoder_buffer->MatchesForTesting(*decoder_buffer_to_send));
656
657   std::move(received_decode_cb).Run(kDecoderStatus);
658   task_environment_.RunUntilIdle();
659 }
660
661 // Tests that the StableVideoDecoderService rejects a call to
662 // stable::mojom::VideoDecoder::Decode() before
663 // stable::mojom::VideoDecoder::Construct() gets called.
664 TEST_F(StableVideoDecoderServiceTest,
665        StableVideoDecoderCannotDecodeBeforeConstruction) {
666   auto mock_video_decoder = std::make_unique<StrictMock<MockVideoDecoder>>();
667   auto stable_video_decoder_remote =
668       CreateStableVideoDecoder(std::move(mock_video_decoder), /*tracker=*/{});
669   ASSERT_TRUE(stable_video_decoder_remote.is_bound());
670   ASSERT_TRUE(stable_video_decoder_remote.is_connected());
671
672   constexpr uint8_t kEncodedData[] = {1, 2, 3};
673   scoped_refptr<DecoderBuffer> decoder_buffer_to_send =
674       DecoderBuffer::CopyFrom(kEncodedData, std::size(kEncodedData));
675   ASSERT_TRUE(decoder_buffer_to_send);
676   StrictMock<base::MockOnceCallback<void(const media::DecoderStatus& status)>>
677       decode_cb_to_send;
678
679   EXPECT_CALL(decode_cb_to_send,
680               Run(DecoderStatus(DecoderStatus::Codes::kFailed)));
681   stable_video_decoder_remote->Decode(decoder_buffer_to_send,
682                                       decode_cb_to_send.Get());
683   stable_video_decoder_remote.FlushForTesting();
684 }
685
686 // Tests that a call to stable::mojom::VideoDecoder::Reset() gets routed
687 // correctly to the underlying mojom::VideoDecoder. Also tests that when the
688 // underlying mojom::VideoDecoder calls the reset callback, the call gets routed
689 // to the client.
690 TEST_F(StableVideoDecoderServiceTest, StableVideoDecoderCanBeReset) {
691   auto mock_video_decoder = std::make_unique<StrictMock<MockVideoDecoder>>();
692   auto* mock_video_decoder_raw = mock_video_decoder.get();
693   auto stable_video_decoder_remote =
694       CreateStableVideoDecoder(std::move(mock_video_decoder), /*tracker=*/{});
695   ASSERT_TRUE(stable_video_decoder_remote.is_bound());
696   ASSERT_TRUE(stable_video_decoder_remote.is_connected());
697   auto auxiliary_endpoints = ConstructStableVideoDecoder(
698       stable_video_decoder_remote, *mock_video_decoder_raw,
699       /*expect_construct_call=*/true);
700   ASSERT_TRUE(auxiliary_endpoints);
701
702   StrictMock<base::MockOnceCallback<void()>> reset_cb_to_send;
703   mojom::VideoDecoder::ResetCallback received_reset_cb;
704
705   EXPECT_CALL(*mock_video_decoder_raw, Reset(/*callback=*/_))
706       .WillOnce([&](mojom::VideoDecoder::ResetCallback callback) {
707         received_reset_cb = std::move(callback);
708       });
709   EXPECT_CALL(reset_cb_to_send, Run());
710   stable_video_decoder_remote->Reset(reset_cb_to_send.Get());
711   stable_video_decoder_remote.FlushForTesting();
712   ASSERT_TRUE(Mock::VerifyAndClearExpectations(mock_video_decoder_raw));
713
714   std::move(received_reset_cb).Run();
715   task_environment_.RunUntilIdle();
716 }
717
718 // Tests that the StableVideoDecoderService doesn't route a
719 // stable::mojom::VideoDecoder::Reset() call to the underlying
720 // mojom::VideoDecoder before stable::mojom::VideoDecoder::Construct() gets
721 // called and that it just calls the reset callback.
722 TEST_F(StableVideoDecoderServiceTest,
723        StableVideoDecoderCannotBeResetBeforeConstruction) {
724   auto mock_video_decoder = std::make_unique<StrictMock<MockVideoDecoder>>();
725   auto stable_video_decoder_remote =
726       CreateStableVideoDecoder(std::move(mock_video_decoder), /*tracker=*/{});
727   ASSERT_TRUE(stable_video_decoder_remote.is_bound());
728   ASSERT_TRUE(stable_video_decoder_remote.is_connected());
729
730   StrictMock<base::MockOnceCallback<void()>> reset_cb_to_send;
731
732   EXPECT_CALL(reset_cb_to_send, Run());
733   stable_video_decoder_remote->Reset(reset_cb_to_send.Get());
734   stable_video_decoder_remote.FlushForTesting();
735 }
736
737 // Tests that a call to
738 // stable::mojom::VideoFrameHandleReleaser::ReleaseVideoFrame() gets routed
739 // correctly to the underlying mojom::VideoFrameHandleReleaser.
740 TEST_F(StableVideoDecoderServiceTest, VideoFramesCanBeReleased) {
741   auto mock_video_decoder = std::make_unique<StrictMock<MockVideoDecoder>>();
742   auto* mock_video_decoder_raw = mock_video_decoder.get();
743   auto stable_video_decoder_remote =
744       CreateStableVideoDecoder(std::move(mock_video_decoder), /*tracker=*/{});
745   ASSERT_TRUE(stable_video_decoder_remote.is_bound());
746   ASSERT_TRUE(stable_video_decoder_remote.is_connected());
747   auto auxiliary_endpoints = ConstructStableVideoDecoder(
748       stable_video_decoder_remote, *mock_video_decoder_raw,
749       /*expect_construct_call=*/true);
750   ASSERT_TRUE(auxiliary_endpoints);
751   ASSERT_TRUE(auxiliary_endpoints->stable_video_frame_handle_releaser_remote);
752   ASSERT_TRUE(auxiliary_endpoints->mock_video_frame_handle_releaser);
753
754   const base::UnguessableToken release_token_to_send =
755       base::UnguessableToken::Create();
756   const absl::optional<gpu::SyncToken> expected_release_sync_token =
757       absl::nullopt;
758
759   EXPECT_CALL(
760       *auxiliary_endpoints->mock_video_frame_handle_releaser,
761       ReleaseVideoFrame(release_token_to_send, expected_release_sync_token));
762   auxiliary_endpoints->stable_video_frame_handle_releaser_remote
763       ->ReleaseVideoFrame(release_token_to_send);
764   auxiliary_endpoints->stable_video_frame_handle_releaser_remote
765       .FlushForTesting();
766 }
767
768 TEST_F(StableVideoDecoderServiceTest,
769        StableVideoDecoderClientReceivesOnVideoFrameDecodedEvent) {
770   auto mock_video_decoder = std::make_unique<StrictMock<MockVideoDecoder>>();
771   auto* mock_video_decoder_raw = mock_video_decoder.get();
772   auto stable_video_decoder_remote =
773       CreateStableVideoDecoder(std::move(mock_video_decoder), /*tracker=*/{});
774   ASSERT_TRUE(stable_video_decoder_remote.is_bound());
775   ASSERT_TRUE(stable_video_decoder_remote.is_connected());
776   auto auxiliary_endpoints = ConstructStableVideoDecoder(
777       stable_video_decoder_remote, *mock_video_decoder_raw,
778       /*expect_construct_call=*/true);
779   ASSERT_TRUE(auxiliary_endpoints);
780   ASSERT_TRUE(auxiliary_endpoints->video_decoder_client_remote);
781   ASSERT_TRUE(auxiliary_endpoints->mock_stable_video_decoder_client);
782
783   const auto token_for_release = base::UnguessableToken::Create();
784   scoped_refptr<VideoFrame> video_frame_to_send =
785       CreateTestNV12GpuMemoryBufferVideoFrame();
786   ASSERT_TRUE(video_frame_to_send);
787   stable::mojom::VideoFramePtr video_frame_received;
788   constexpr bool kCanReadWithoutStalling = true;
789   EXPECT_CALL(
790       *auxiliary_endpoints->mock_stable_video_decoder_client,
791       OnVideoFrameDecoded(_, kCanReadWithoutStalling, token_for_release))
792       .WillOnce(WithArgs<0>(
793           [&video_frame_received](stable::mojom::VideoFramePtr frame) {
794             video_frame_received = std::move(frame);
795           }));
796   auxiliary_endpoints->video_decoder_client_remote->OnVideoFrameDecoded(
797       video_frame_to_send, kCanReadWithoutStalling, token_for_release);
798   auxiliary_endpoints->video_decoder_client_remote.FlushForTesting();
799   ASSERT_TRUE(video_frame_received);
800   EXPECT_FALSE(video_frame_received->metadata.end_of_stream);
801   EXPECT_TRUE(video_frame_received->metadata.read_lock_fences_enabled);
802   EXPECT_TRUE(video_frame_received->metadata.power_efficient);
803   EXPECT_TRUE(video_frame_received->metadata.allow_overlay);
804 }
805
806 // Tests that a mojom::VideoDecoderClient::OnWaiting() call originating from the
807 // underlying mojom::VideoDecoder gets forwarded to the
808 // stable::mojom::VideoDecoderClient correctly.
809 TEST_F(StableVideoDecoderServiceTest,
810        StableVideoDecoderClientReceivesOnWaitingEvent) {
811   auto mock_video_decoder = std::make_unique<StrictMock<MockVideoDecoder>>();
812   auto* mock_video_decoder_raw = mock_video_decoder.get();
813   auto stable_video_decoder_remote =
814       CreateStableVideoDecoder(std::move(mock_video_decoder), /*tracker=*/{});
815   ASSERT_TRUE(stable_video_decoder_remote.is_bound());
816   ASSERT_TRUE(stable_video_decoder_remote.is_connected());
817   auto auxiliary_endpoints = ConstructStableVideoDecoder(
818       stable_video_decoder_remote, *mock_video_decoder_raw,
819       /*expect_construct_call=*/true);
820   ASSERT_TRUE(auxiliary_endpoints);
821   ASSERT_TRUE(auxiliary_endpoints->video_decoder_client_remote);
822   ASSERT_TRUE(auxiliary_endpoints->mock_stable_video_decoder_client);
823
824   constexpr WaitingReason kWaitingReason = WaitingReason::kNoDecryptionKey;
825   EXPECT_CALL(*auxiliary_endpoints->mock_stable_video_decoder_client,
826               OnWaiting(kWaitingReason));
827   auxiliary_endpoints->video_decoder_client_remote->OnWaiting(kWaitingReason);
828   auxiliary_endpoints->video_decoder_client_remote.FlushForTesting();
829 }
830
831 // Tests that a mojom::MediaLog::AddLogRecord() call originating from the
832 // underlying mojom::VideoDecoder gets forwarded to the stable::mojom::MediaLog
833 // correctly.
834 TEST_F(StableVideoDecoderServiceTest,
835        StableVideoDecoderClientReceivesAddLogRecordEvent) {
836   auto mock_video_decoder = std::make_unique<StrictMock<MockVideoDecoder>>();
837   auto* mock_video_decoder_raw = mock_video_decoder.get();
838   auto stable_video_decoder_remote =
839       CreateStableVideoDecoder(std::move(mock_video_decoder), /*tracker=*/{});
840   ASSERT_TRUE(stable_video_decoder_remote.is_bound());
841   ASSERT_TRUE(stable_video_decoder_remote.is_connected());
842   auto auxiliary_endpoints = ConstructStableVideoDecoder(
843       stable_video_decoder_remote, *mock_video_decoder_raw,
844       /*expect_construct_call=*/true);
845   ASSERT_TRUE(auxiliary_endpoints);
846   ASSERT_TRUE(auxiliary_endpoints->media_log_remote);
847   ASSERT_TRUE(auxiliary_endpoints->mock_stable_media_log);
848
849   MediaLogRecord media_log_record_to_send;
850   media_log_record_to_send.id = 2;
851   media_log_record_to_send.type = MediaLogRecord::Type::kMediaStatus;
852   media_log_record_to_send.params.Set("Test", "Value");
853   media_log_record_to_send.time = base::TimeTicks::Now();
854
855   EXPECT_CALL(*auxiliary_endpoints->mock_stable_media_log,
856               AddLogRecord(media_log_record_to_send));
857   auxiliary_endpoints->media_log_remote->AddLogRecord(media_log_record_to_send);
858   auxiliary_endpoints->media_log_remote.FlushForTesting();
859 }
860
861 // Tests that a StableVideoDecoderTracker can be used to know when the remote
862 // StableVideoDecoder implementation dies.
863 TEST_F(StableVideoDecoderServiceTest,
864        StableVideoDecoderTrackerDisconnectsWhenStableVideoDecoderDies) {
865   auto mock_video_decoder = std::make_unique<StrictMock<MockVideoDecoder>>();
866
867   MockStableVideoDecoderTracker tracker;
868   mojo::Receiver<stable::mojom::StableVideoDecoderTracker> tracker_receiver(
869       &tracker);
870   mojo::PendingRemote<stable::mojom::StableVideoDecoderTracker> tracker_remote =
871       tracker_receiver.BindNewPipeAndPassRemote();
872   StrictMock<base::MockOnceCallback<void()>> tracker_disconnect_cb;
873   tracker_receiver.set_disconnect_handler(tracker_disconnect_cb.Get());
874
875   auto stable_video_decoder_remote = CreateStableVideoDecoder(
876       std::move(mock_video_decoder), std::move(tracker_remote));
877   ASSERT_TRUE(stable_video_decoder_remote.is_bound());
878   ASSERT_TRUE(stable_video_decoder_remote.is_connected());
879
880   // Until now, nothing in particular should happen.
881   task_environment_.RunUntilIdle();
882   ASSERT_TRUE(Mock::VerifyAndClearExpectations(&tracker_disconnect_cb));
883
884   // Once we reset the |stable_video_decoder_remote|, the StableVideoDecoder
885   // implementation should die and the |tracker| should get disconnected.
886   EXPECT_CALL(tracker_disconnect_cb, Run());
887   stable_video_decoder_remote.reset();
888   task_environment_.RunUntilIdle();
889 }
890
891 }  // namespace
892
893 }  // namespace media