[M120 Migration][MM][CAPI] Fix the logic for media using capi player.
[platform/framework/web/chromium-efl.git] / media / mojo / services / mojo_video_encode_accelerator_service_unittest.cc
1 // Copyright 2017 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 <stddef.h>
6
7 #include "base/functional/bind.h"
8 #include "base/functional/callback_helpers.h"
9 #include "base/memory/ptr_util.h"
10 #include "base/memory/unsafe_shared_memory_region.h"
11 #include "base/run_loop.h"
12 #include "base/task/single_thread_task_runner.h"
13 #include "base/test/task_environment.h"
14 #include "gpu/config/gpu_driver_bug_workarounds.h"
15 #include "gpu/config/gpu_info.h"
16 #include "gpu/config/gpu_preferences.h"
17 #include "media/mojo/clients/mojo_media_log_service.h"
18 #include "media/mojo/mojom/video_encode_accelerator.mojom.h"
19 #include "media/mojo/services/mojo_video_encode_accelerator_service.h"
20 #include "media/video/fake_video_encode_accelerator.h"
21 #include "media/video/video_encode_accelerator.h"
22 #include "mojo/public/cpp/bindings/associated_remote.h"
23 #include "mojo/public/cpp/bindings/pending_associated_remote.h"
24 #include "mojo/public/cpp/bindings/pending_remote.h"
25 #include "mojo/public/cpp/bindings/self_owned_associated_receiver.h"
26 #include "testing/gmock/include/gmock/gmock.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28
29 namespace gpu {
30 struct GpuPreferences;
31 }  // namespace gpu
32
33 using ::testing::_;
34
35 namespace media {
36
37 static const gfx::Size kInputVisibleSize(64, 48);
38
39 std::unique_ptr<VideoEncodeAccelerator> CreateAndInitializeFakeVEA(
40     bool will_initialization_succeed,
41     const VideoEncodeAccelerator::Config& config,
42     VideoEncodeAccelerator::Client* client,
43     const gpu::GpuPreferences& gpu_preferences,
44     const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
45     const gpu::GPUInfo::GPUDevice& gpu_device,
46     std::unique_ptr<MediaLog> media_log) {
47   // Use FakeVEA as scoped_ptr to guarantee proper destruction via Destroy().
48   auto vea = std::make_unique<FakeVideoEncodeAccelerator>(
49       base::SingleThreadTaskRunner::GetCurrentDefault());
50   vea->SetWillInitializationSucceed(will_initialization_succeed);
51   const bool result = vea->Initialize(config, client, media_log->Clone());
52
53   // Mimic the behaviour of GpuVideoEncodeAcceleratorFactory::CreateVEA().
54   return result ? base::WrapUnique<VideoEncodeAccelerator>(vea.release())
55                 : nullptr;
56 }
57
58 class MockMojoVideoEncodeAcceleratorClient
59     : public mojom::VideoEncodeAcceleratorClient {
60  public:
61   MockMojoVideoEncodeAcceleratorClient() = default;
62
63   MockMojoVideoEncodeAcceleratorClient(
64       const MockMojoVideoEncodeAcceleratorClient&) = delete;
65   MockMojoVideoEncodeAcceleratorClient& operator=(
66       const MockMojoVideoEncodeAcceleratorClient&) = delete;
67
68   MOCK_METHOD3(RequireBitstreamBuffers,
69                void(uint32_t, const gfx::Size&, uint32_t));
70   MOCK_METHOD2(BitstreamBufferReady,
71                void(int32_t, const media::BitstreamBufferMetadata&));
72   MOCK_METHOD1(NotifyErrorStatus, void(const EncoderStatus&));
73   MOCK_METHOD1(NotifyEncoderInfoChange, void(const VideoEncoderInfo& info));
74 };
75
76 // Test harness for a MojoVideoEncodeAcceleratorService; the tests manipulate it
77 // via its MojoVideoEncodeAcceleratorService interface while observing a
78 // "remote" mojo::VideoEncodeAcceleratorClient (that we keep inside a Mojo
79 // binding). The class under test uses a FakeVideoEncodeAccelerator as
80 // implementation.
81 class MojoVideoEncodeAcceleratorServiceTest : public ::testing::Test {
82  public:
83   MojoVideoEncodeAcceleratorServiceTest() = default;
84
85   MojoVideoEncodeAcceleratorServiceTest(
86       const MojoVideoEncodeAcceleratorServiceTest&) = delete;
87   MojoVideoEncodeAcceleratorServiceTest& operator=(
88       const MojoVideoEncodeAcceleratorServiceTest&) = delete;
89
90   void TearDown() override {
91     // The destruction of a mojo::SelfOwnedReceiver closes the bound message
92     // pipe but does not destroy the implementation object: needs to happen
93     // manually, otherwise we leak it. This only applies if BindAndInitialize()
94     // has been called.
95     if (mojo_vea_receiver_)
96       mojo_vea_receiver_->Close();
97   }
98
99   // Creates the class under test, configuring the underlying FakeVEA to succeed
100   // upon initialization (by default) or not.
101   void CreateMojoVideoEncodeAccelerator(
102       bool will_fake_vea_initialization_succeed = true) {
103     mojo_vea_service_ = std::make_unique<MojoVideoEncodeAcceleratorService>(
104         base::BindRepeating(&CreateAndInitializeFakeVEA,
105                             will_fake_vea_initialization_succeed),
106         gpu::GpuPreferences(), gpu::GpuDriverBugWorkarounds(),
107         gpu::GPUInfo::GPUDevice());
108   }
109
110   void BindAndInitialize() {
111     // Create an Mojo VEA Client remote and bind it to our Mock.
112     mojo::PendingAssociatedRemote<mojom::VideoEncodeAcceleratorClient>
113         pending_client_remote;
114     auto pending_client_receiver =
115         pending_client_remote.InitWithNewEndpointAndPassReceiver();
116     pending_client_receiver.EnableUnassociatedUsage();
117
118     mojo_vea_receiver_ = mojo::MakeSelfOwnedAssociatedReceiver(
119         std::make_unique<MockMojoVideoEncodeAcceleratorClient>(),
120         std::move(pending_client_receiver));
121
122     EXPECT_CALL(*mock_mojo_vea_client(),
123                 RequireBitstreamBuffers(_, kInputVisibleSize, _));
124
125     constexpr media::Bitrate kInitialBitrate =
126         media::Bitrate::ConstantBitrate(100000u);
127     const media::VideoEncodeAccelerator::Config config(
128         PIXEL_FORMAT_I420, kInputVisibleSize, H264PROFILE_MIN, kInitialBitrate);
129
130     mojo::PendingReceiver<mojom::MediaLog> media_log_pending_receiver;
131     auto media_log_pending_remote =
132         media_log_pending_receiver.InitWithNewPipeAndPassRemote();
133
134     mojo_vea_service()->Initialize(
135         config, std::move(pending_client_remote),
136         std::move(media_log_pending_remote),
137         base::BindOnce([](bool success) { ASSERT_TRUE(success); }));
138     base::RunLoop().RunUntilIdle();
139   }
140
141   MojoVideoEncodeAcceleratorService* mojo_vea_service() {
142     return mojo_vea_service_.get();
143   }
144
145   MockMojoVideoEncodeAcceleratorClient* mock_mojo_vea_client() const {
146     return static_cast<media::MockMojoVideoEncodeAcceleratorClient*>(
147         mojo_vea_receiver_->impl());
148   }
149
150   FakeVideoEncodeAccelerator* fake_vea() const {
151     return static_cast<FakeVideoEncodeAccelerator*>(
152         mojo_vea_service_->encoder_.get());
153   }
154
155  private:
156   base::test::SingleThreadTaskEnvironment task_environment_;
157
158   mojo::SelfOwnedAssociatedReceiverRef<mojom::VideoEncodeAcceleratorClient>
159       mojo_vea_receiver_;
160
161   // The class under test.
162   std::unique_ptr<MojoVideoEncodeAcceleratorService> mojo_vea_service_;
163 };
164
165 // This test verifies the BindAndInitialize() communication prologue in
166 // isolation.
167 TEST_F(MojoVideoEncodeAcceleratorServiceTest,
168        InitializeAndRequireBistreamBuffers) {
169   CreateMojoVideoEncodeAccelerator();
170   BindAndInitialize();
171 }
172
173 // This test verifies the BindAndInitialize() communication prologue followed by
174 // a sharing of a single bitstream buffer and the Encode() of one frame.
175 TEST_F(MojoVideoEncodeAcceleratorServiceTest, EncodeOneFrame) {
176   CreateMojoVideoEncodeAccelerator();
177   BindAndInitialize();
178
179   const int32_t kBitstreamBufferId = 17;
180   {
181     const uint64_t kShMemSize = fake_vea()->minimum_output_buffer_size();
182     auto region = base::UnsafeSharedMemoryRegion::Create(kShMemSize);
183
184     mojo_vea_service()->UseOutputBitstreamBuffer(kBitstreamBufferId,
185                                                  std::move(region));
186     base::RunLoop().RunUntilIdle();
187   }
188
189   {
190     const auto video_frame = VideoFrame::CreateBlackFrame(kInputVisibleSize);
191     EXPECT_CALL(*mock_mojo_vea_client(),
192                 BitstreamBufferReady(kBitstreamBufferId, _));
193
194     media::VideoEncoder::EncodeOptions options(/* key_frame */ true);
195     mojo_vea_service()->Encode(video_frame, options, base::DoNothing());
196     base::RunLoop().RunUntilIdle();
197   }
198 }
199
200 // Tests that a RequestEncodingParametersChange() ripples through correctly.
201 TEST_F(MojoVideoEncodeAcceleratorServiceTest, EncodingParametersChange) {
202   CreateMojoVideoEncodeAccelerator();
203   BindAndInitialize();
204
205   const uint32_t kNewBitrate = 123123u;
206   const uint32_t kNewFramerate = 321321u;
207   VideoBitrateAllocation bitrate_allocation;
208   bitrate_allocation.SetBitrate(0, 0, kNewBitrate);
209   mojo_vea_service()->RequestEncodingParametersChangeWithLayers(
210       bitrate_allocation, kNewFramerate);
211   base::RunLoop().RunUntilIdle();
212
213   ASSERT_TRUE(fake_vea());
214   VideoBitrateAllocation expected_allocation;
215   expected_allocation.SetBitrate(0, 0, kNewBitrate);
216   EXPECT_EQ(expected_allocation,
217             fake_vea()->stored_bitrate_allocations().back());
218 }
219
220 // Tests that a RequestEncodingParametersChange() ripples through correctly.
221 TEST_F(MojoVideoEncodeAcceleratorServiceTest,
222        EncodingParametersWithBitrateAllocation) {
223   CreateMojoVideoEncodeAccelerator();
224   BindAndInitialize();
225
226   const uint32_t kNewFramerate = 321321u;
227   const size_t kMaxNumBitrates = VideoBitrateAllocation::kMaxSpatialLayers *
228                                  VideoBitrateAllocation::kMaxTemporalLayers;
229
230   // Verify translation of VideoBitrateAllocation into vector of bitrates for
231   // everything from empty array up to max number of layers.
232   VideoBitrateAllocation bitrate_allocation;
233   for (size_t i = 0; i <= kMaxNumBitrates; ++i) {
234     if (i > 0) {
235       uint32_t layer_bitrate = i * 1000;
236       const size_t si = (i - 1) / VideoBitrateAllocation::kMaxTemporalLayers;
237       const size_t ti = (i - 1) % VideoBitrateAllocation::kMaxTemporalLayers;
238       bitrate_allocation.SetBitrate(si, ti, layer_bitrate);
239     }
240
241     mojo_vea_service()->RequestEncodingParametersChangeWithLayers(
242         bitrate_allocation, kNewFramerate);
243     base::RunLoop().RunUntilIdle();
244
245     ASSERT_TRUE(fake_vea());
246     EXPECT_EQ(bitrate_allocation,
247               fake_vea()->stored_bitrate_allocations().back());
248   }
249 }
250
251 // This test verifies that MojoVEA::Initialize() fails with an invalid |client|.
252 TEST_F(MojoVideoEncodeAcceleratorServiceTest,
253        InitializeWithInvalidClientFails) {
254   CreateMojoVideoEncodeAccelerator();
255
256   mojo::PendingAssociatedRemote<mojom::VideoEncodeAcceleratorClient>
257       invalid_mojo_vea_client;
258
259   constexpr media::Bitrate kInitialBitrate =
260       media::Bitrate::ConstantBitrate(100000u);
261   const media::VideoEncodeAccelerator::Config config(
262       PIXEL_FORMAT_I420, kInputVisibleSize, H264PROFILE_MIN, kInitialBitrate);
263   mojo::PendingReceiver<mojom::MediaLog> media_log_pending_receiver;
264   auto media_log_pending_remote =
265       media_log_pending_receiver.InitWithNewPipeAndPassRemote();
266
267   mojo_vea_service()->Initialize(
268       config, std::move(invalid_mojo_vea_client),
269       std::move(media_log_pending_remote),
270       base::BindOnce([](bool success) { ASSERT_FALSE(success); }));
271   base::RunLoop().RunUntilIdle();
272 }
273
274 // This test verifies that when FakeVEA is configured to fail upon start,
275 // MojoVEA::Initialize() causes a NotifyError().
276 TEST_F(MojoVideoEncodeAcceleratorServiceTest, InitializeFailure) {
277   CreateMojoVideoEncodeAccelerator(
278       false /* will_fake_vea_initialization_succeed */);
279
280   mojo::PendingAssociatedRemote<mojom::VideoEncodeAcceleratorClient>
281       mojo_vea_client;
282   auto mojo_vea_receiver = mojo::MakeSelfOwnedAssociatedReceiver(
283       std::make_unique<MockMojoVideoEncodeAcceleratorClient>(),
284       mojo_vea_client.InitWithNewEndpointAndPassReceiver());
285
286   constexpr media::Bitrate kInitialBitrate =
287       media::Bitrate::ConstantBitrate(100000u);
288   const media::VideoEncodeAccelerator::Config config(
289       PIXEL_FORMAT_I420, kInputVisibleSize, H264PROFILE_MIN, kInitialBitrate);
290   mojo::PendingReceiver<mojom::MediaLog> media_log_pending_receiver;
291   auto media_log_pending_remote =
292       media_log_pending_receiver.InitWithNewPipeAndPassRemote();
293
294   mojo_vea_service()->Initialize(
295       config, std::move(mojo_vea_client), std::move(media_log_pending_remote),
296       base::BindOnce([](bool success) { ASSERT_FALSE(success); }));
297   base::RunLoop().RunUntilIdle();
298
299   mojo_vea_receiver->Close();
300 }
301
302 // This test verifies that UseOutputBitstreamBuffer() with a wrong ShMem size
303 // causes NotifyError().
304 TEST_F(MojoVideoEncodeAcceleratorServiceTest,
305        UseOutputBitstreamBufferWithWrongSizeFails) {
306   CreateMojoVideoEncodeAccelerator();
307   BindAndInitialize();
308
309   const int32_t kBitstreamBufferId = 17;
310   const uint64_t wrong_size = fake_vea()->minimum_output_buffer_size() / 2;
311   auto region = base::UnsafeSharedMemoryRegion::Create(wrong_size);
312
313   EXPECT_CALL(*mock_mojo_vea_client(), NotifyErrorStatus);
314
315   mojo_vea_service()->UseOutputBitstreamBuffer(kBitstreamBufferId,
316                                                std::move(region));
317   base::RunLoop().RunUntilIdle();
318 }
319
320 // This test verifies that Encode() with wrong coded size causes NotifyError().
321 TEST_F(MojoVideoEncodeAcceleratorServiceTest, EncodeWithWrongSizeFails) {
322   CreateMojoVideoEncodeAccelerator();
323   BindAndInitialize();
324
325   // We should send a UseOutputBitstreamBuffer() first but in unit tests we can
326   // skip that prologue.
327
328   const gfx::Size wrong_size(kInputVisibleSize.width() / 2,
329                              kInputVisibleSize.height() / 2);
330   const auto video_frame = VideoFrame::CreateBlackFrame(wrong_size);
331
332   EXPECT_CALL(*mock_mojo_vea_client(), NotifyErrorStatus);
333
334   media::VideoEncoder::EncodeOptions options(/* key_frame */ true);
335   mojo_vea_service()->Encode(video_frame, options, base::DoNothing());
336   base::RunLoop().RunUntilIdle();
337 }
338
339 // This test verifies that an any mojom::VEA method call (e.g. Encode(),
340 // UseOutputBitstreamBuffer() etc) before MojoVEA::Initialize() is ignored (we
341 // can't expect NotifyError()s since there's no mojo client registered).
342 TEST_F(MojoVideoEncodeAcceleratorServiceTest, CallsBeforeInitializeAreIgnored) {
343   CreateMojoVideoEncodeAccelerator();
344   {
345     const auto video_frame = VideoFrame::CreateBlackFrame(kInputVisibleSize);
346     media::VideoEncoder::EncodeOptions options(/* key_frame */ true);
347     mojo_vea_service()->Encode(video_frame, options, base::DoNothing());
348     base::RunLoop().RunUntilIdle();
349   }
350   {
351     const int32_t kBitstreamBufferId = 17;
352     const uint64_t kShMemSize = 10;
353     auto region = base::UnsafeSharedMemoryRegion::Create(kShMemSize);
354     mojo_vea_service()->UseOutputBitstreamBuffer(kBitstreamBufferId,
355                                                  std::move(region));
356     base::RunLoop().RunUntilIdle();
357   }
358   {
359     const uint32_t kNewBitrate = 123123u;
360     const uint32_t kNewFramerate = 321321u;
361     media::VideoBitrateAllocation bitrate_allocation;
362     bitrate_allocation.SetBitrate(0, 0, kNewBitrate);
363     mojo_vea_service()->RequestEncodingParametersChangeWithLayers(
364         bitrate_allocation, kNewFramerate);
365     base::RunLoop().RunUntilIdle();
366   }
367 }
368
369 // This test verifies that IsFlushSupported/Flush on FakeVEA.
370 TEST_F(MojoVideoEncodeAcceleratorServiceTest, IsFlushSupportedAndFlush) {
371   CreateMojoVideoEncodeAccelerator();
372   BindAndInitialize();
373
374   ASSERT_TRUE(fake_vea());
375
376   // media::VideoEncodeAccelerator::IsFlushSupported and Flush are return
377   // false as default, so here expect false for both IsFlushSupported and
378   // Flush.
379   auto flush_support =
380       base::BindOnce([](bool status) { EXPECT_EQ(status, false); });
381   mojo_vea_service()->IsFlushSupported(std::move(flush_support));
382   base::RunLoop().RunUntilIdle();
383
384   auto flush_callback =
385       base::BindOnce([](bool status) { EXPECT_EQ(status, false); });
386   mojo_vea_service()->IsFlushSupported(std::move(flush_callback));
387 }
388
389 }  // namespace media