Upload upstream chromium 108.0.5359.1
[platform/framework/web/chromium-efl.git] / media / filters / offloading_video_decoder_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 "media/filters/offloading_video_decoder.h"
6
7 #include "base/bind.h"
8 #include "base/callback_helpers.h"
9 #include "base/memory/raw_ptr.h"
10 #include "base/run_loop.h"
11 #include "base/test/gmock_callback_support.h"
12 #include "base/test/task_environment.h"
13 #include "media/base/decoder_buffer.h"
14 #include "media/base/mock_filters.h"
15 #include "media/base/test_data_util.h"
16 #include "media/base/test_helpers.h"
17 #include "media/base/video_frame.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19
20 using base::test::RunClosure;
21 using base::test::RunOnceCallback;
22 using base::test::RunOnceClosure;
23 using testing::_;
24 using testing::DoAll;
25 using testing::SaveArg;
26
27 namespace media {
28
29 ACTION_P(VerifyOn, task_runner) {
30   ASSERT_TRUE(task_runner->RunsTasksInCurrentSequence());
31 }
32
33 ACTION_P(VerifyNotOn, task_runner) {
34   ASSERT_FALSE(task_runner->RunsTasksInCurrentSequence());
35 }
36
37 class MockOffloadableVideoDecoder : public OffloadableVideoDecoder {
38  public:
39   // OffloadableVideoDecoder implementation.
40   VideoDecoderType GetDecoderType() const override {
41     return VideoDecoderType::kTesting;
42   }
43
44   void Initialize(const VideoDecoderConfig& config,
45                   bool low_delay,
46                   CdmContext* cdm_context,
47                   InitCB init_cb,
48                   const OutputCB& output_cb,
49                   const WaitingCB& waiting_cb) override {
50     Initialize_(config, low_delay, cdm_context, init_cb, output_cb, waiting_cb);
51   }
52   MOCK_METHOD6(Initialize_,
53                void(const VideoDecoderConfig& config,
54                     bool low_delay,
55                     CdmContext* cdm_context,
56                     InitCB& init_cb,
57                     const OutputCB& output_cb,
58                     const WaitingCB& waiting_cb));
59   void Decode(scoped_refptr<DecoderBuffer> buffer, DecodeCB cb) override {
60     Decode_(std::move(buffer), cb);
61   }
62   MOCK_METHOD2(Decode_, void(scoped_refptr<DecoderBuffer> buffer, DecodeCB&));
63   void Reset(base::OnceClosure cb) override { Reset_(cb); }
64   MOCK_METHOD1(Reset_, void(base::OnceClosure&));
65   MOCK_METHOD0(Detach, void(void));
66 };
67
68 class OffloadingVideoDecoderTest : public testing::Test {
69  public:
70   OffloadingVideoDecoderTest()
71       : task_env_(
72             base::test::TaskEnvironment::MainThreadType::DEFAULT,
73             base::test::TaskEnvironment::ThreadPoolExecutionMode::QUEUED) {}
74
75   OffloadingVideoDecoderTest(const OffloadingVideoDecoderTest&) = delete;
76   OffloadingVideoDecoderTest& operator=(const OffloadingVideoDecoderTest&) =
77       delete;
78
79   void CreateWrapper(int offload_width, VideoCodec codec) {
80     decoder_ = new testing::StrictMock<MockOffloadableVideoDecoder>();
81     offloading_decoder_ = std::make_unique<OffloadingVideoDecoder>(
82         offload_width, std::vector<VideoCodec>(1, codec),
83         std::unique_ptr<OffloadableVideoDecoder>(decoder_));
84   }
85
86   VideoDecoder::InitCB ExpectInitCB(bool success) {
87     EXPECT_CALL(*this, InitDone(success))
88         .WillOnce(VerifyOn(task_env_.GetMainThreadTaskRunner()));
89     return base::BindOnce(
90         [](base::OnceCallback<void(bool)> cb, DecoderStatus status) {
91           std::move(cb).Run(status.is_ok());
92         },
93         base::BindOnce(&OffloadingVideoDecoderTest::InitDone,
94                        base::Unretained(this)));
95   }
96
97   VideoDecoder::OutputCB ExpectOutputCB() {
98     EXPECT_CALL(*this, OutputDone(_))
99         .WillOnce(VerifyOn(task_env_.GetMainThreadTaskRunner()));
100     return base::BindRepeating(&OffloadingVideoDecoderTest::OutputDone,
101                                base::Unretained(this));
102   }
103
104   VideoDecoder::DecodeCB ExpectDecodeCB(DecoderStatus status) {
105     EXPECT_CALL(*this, DecodeDone(HasStatusCode(status)))
106         .WillOnce(VerifyOn(task_env_.GetMainThreadTaskRunner()));
107     return base::BindOnce(&OffloadingVideoDecoderTest::DecodeDone,
108                           base::Unretained(this));
109   }
110
111   base::OnceClosure ExpectResetCB() {
112     EXPECT_CALL(*this, ResetDone())
113         .WillOnce(VerifyOn(task_env_.GetMainThreadTaskRunner()));
114     return base::BindOnce(&OffloadingVideoDecoderTest::ResetDone,
115                           base::Unretained(this));
116   }
117
118   void TestNoOffloading(const VideoDecoderConfig& config) {
119     // Display name should be a simple passthrough.
120     EXPECT_EQ(offloading_decoder_->GetDecoderType(),
121               decoder_->GetDecoderType());
122
123     // When offloading decodes should not be parallelized.
124     EXPECT_EQ(offloading_decoder_->GetMaxDecodeRequests(), 1);
125
126     // Verify methods are called on the current thread since the offload codec
127     // requirement is not satisfied.
128     VideoDecoder::OutputCB output_cb;
129     EXPECT_CALL(*decoder_, Initialize_(_, false, nullptr, _, _, _))
130         .WillOnce(DoAll(VerifyOn(task_env_.GetMainThreadTaskRunner()),
131                         RunOnceCallback<3>(DecoderStatus::Codes::kOk),
132                         SaveArg<4>(&output_cb)));
133     offloading_decoder_->Initialize(config, false, nullptr, ExpectInitCB(true),
134                                     ExpectOutputCB(), base::NullCallback());
135     task_env_.RunUntilIdle();
136
137     // Verify decode works and is called on the right thread.
138     EXPECT_CALL(*decoder_, Decode_(_, _))
139         .WillOnce(DoAll(VerifyOn(task_env_.GetMainThreadTaskRunner()),
140                         RunOnceClosure(base::BindOnce(output_cb, nullptr)),
141                         RunOnceCallback<1>(DecoderStatus::Codes::kOk)));
142     offloading_decoder_->Decode(DecoderBuffer::CreateEOSBuffer(),
143                                 ExpectDecodeCB(DecoderStatus::Codes::kOk));
144     task_env_.RunUntilIdle();
145
146     // Reset so we can call Initialize() again.
147     EXPECT_CALL(*decoder_, Reset_(_))
148         .WillOnce(DoAll(VerifyOn(task_env_.GetMainThreadTaskRunner()),
149                         RunOnceCallback<0>()));
150     offloading_decoder_->Reset(ExpectResetCB());
151     task_env_.RunUntilIdle();
152   }
153
154   void TestOffloading(const VideoDecoderConfig& config, bool detach = false) {
155     // Display name should be a simple passthrough.
156     EXPECT_EQ(offloading_decoder_->GetDecoderType(),
157               decoder_->GetDecoderType());
158
159     // Prior to Initialize() max decode requests is still 1.
160     EXPECT_EQ(offloading_decoder_->GetMaxDecodeRequests(), 1);
161
162     // Since this Initialize() should be happening on another thread, set the
163     // expectation after we make the call.
164     VideoDecoder::OutputCB output_cb;
165     if (detach) {
166       EXPECT_CALL(*decoder_, Detach())
167           .WillOnce(VerifyOn(task_env_.GetMainThreadTaskRunner()));
168     }
169     offloading_decoder_->Initialize(config, false, nullptr, ExpectInitCB(true),
170                                     ExpectOutputCB(), base::NullCallback());
171     EXPECT_CALL(*decoder_, Initialize_(_, false, nullptr, _, _, _))
172         .WillOnce(DoAll(VerifyNotOn(task_env_.GetMainThreadTaskRunner()),
173                         RunOnceCallback<3>(DecoderStatus::Codes::kOk),
174                         SaveArg<4>(&output_cb)));
175     task_env_.RunUntilIdle();
176
177     // When offloading decodes should be parallelized.
178     EXPECT_GT(offloading_decoder_->GetMaxDecodeRequests(), 1);
179
180     // Verify decode works and is called on the right thread.
181     offloading_decoder_->Decode(DecoderBuffer::CreateEOSBuffer(),
182                                 ExpectDecodeCB(DecoderStatus::Codes::kOk));
183     EXPECT_CALL(*decoder_, Decode_(_, _))
184         .WillOnce(DoAll(VerifyNotOn(task_env_.GetMainThreadTaskRunner()),
185                         RunOnceClosure(base::BindOnce(output_cb, nullptr)),
186                         RunOnceCallback<1>(DecoderStatus::Codes::kOk)));
187     task_env_.RunUntilIdle();
188
189     // Reset so we can call Initialize() again.
190     offloading_decoder_->Reset(ExpectResetCB());
191     EXPECT_CALL(*decoder_, Reset_(_))
192         .WillOnce(DoAll(VerifyNotOn(task_env_.GetMainThreadTaskRunner()),
193                         RunOnceCallback<0>()));
194     task_env_.RunUntilIdle();
195   }
196
197   MOCK_METHOD1(InitDone, void(bool));
198   MOCK_METHOD1(OutputDone, void(scoped_refptr<VideoFrame>));
199   MOCK_METHOD1(DecodeDone, void(DecoderStatus));
200   MOCK_METHOD0(ResetDone, void(void));
201
202   base::test::TaskEnvironment task_env_;
203   std::unique_ptr<OffloadingVideoDecoder> offloading_decoder_;
204   raw_ptr<testing::StrictMock<MockOffloadableVideoDecoder>> decoder_ =
205       nullptr;  // Owned by |offloading_decoder_|.
206 };
207
208 TEST_F(OffloadingVideoDecoderTest, NoOffloadingTooSmall) {
209   auto offload_config = TestVideoConfig::Large(VideoCodec::kVP9);
210   CreateWrapper(offload_config.coded_size().width(), VideoCodec::kVP9);
211   TestNoOffloading(TestVideoConfig::Normal(VideoCodec::kVP9));
212 }
213
214 TEST_F(OffloadingVideoDecoderTest, NoOffloadingDifferentCodec) {
215   auto offload_config = TestVideoConfig::Large(VideoCodec::kVP9);
216   CreateWrapper(offload_config.coded_size().width(), VideoCodec::kVP9);
217   TestNoOffloading(TestVideoConfig::Large(VideoCodec::kVP8));
218 }
219
220 TEST_F(OffloadingVideoDecoderTest, NoOffloadingHasEncryption) {
221   auto offload_config = TestVideoConfig::Large(VideoCodec::kVP9);
222   CreateWrapper(offload_config.coded_size().width(), VideoCodec::kVP9);
223   TestNoOffloading(TestVideoConfig::LargeEncrypted(VideoCodec::kVP9));
224 }
225
226 TEST_F(OffloadingVideoDecoderTest, Offloading) {
227   auto offload_config = TestVideoConfig::Large(VideoCodec::kVP9);
228   CreateWrapper(offload_config.coded_size().width(), VideoCodec::kVP9);
229   TestOffloading(offload_config);
230 }
231
232 TEST_F(OffloadingVideoDecoderTest, OffloadingAfterNoOffloading) {
233   auto offload_config = TestVideoConfig::Large(VideoCodec::kVP9);
234   CreateWrapper(offload_config.coded_size().width(), VideoCodec::kVP9);
235
236   // Setup and test the no offloading path first.
237   TestNoOffloading(TestVideoConfig::Normal(VideoCodec::kVP9));
238
239   // Test offloading now.
240   TestOffloading(offload_config, true);
241
242   // Reinitialize decoder with a stream which should not be offloaded. Detach()
243   // should be called on the right thread. Again since the first part of this
244   // should happen asynchronously, set expectation after the call.
245   VideoDecoder::OutputCB output_cb;
246   offloading_decoder_->Initialize(
247       TestVideoConfig::Normal(VideoCodec::kVP9), false, nullptr,
248       ExpectInitCB(true),
249       base::BindRepeating(&OffloadingVideoDecoderTest::OutputDone,
250                           base::Unretained(this)),
251       base::NullCallback());
252   EXPECT_CALL(*decoder_, Detach())
253       .WillOnce(VerifyNotOn(task_env_.GetMainThreadTaskRunner()));
254   EXPECT_CALL(*decoder_, Initialize_(_, false, nullptr, _, _, _))
255       .WillOnce(DoAll(VerifyOn(task_env_.GetMainThreadTaskRunner()),
256                       RunOnceCallback<3>(DecoderStatus::Codes::kOk),
257                       SaveArg<4>(&output_cb)));
258   task_env_.RunUntilIdle();
259 }
260
261 TEST_F(OffloadingVideoDecoderTest, InitializeWithoutDetach) {
262   auto offload_config = TestVideoConfig::Large(VideoCodec::kVP9);
263   CreateWrapper(offload_config.coded_size().width(), VideoCodec::kVP9);
264
265   EXPECT_CALL(*decoder_, Detach()).Times(0);
266   TestNoOffloading(TestVideoConfig::Normal(VideoCodec::kVP9));
267   TestNoOffloading(TestVideoConfig::Normal(VideoCodec::kVP9));
268 }
269
270 TEST_F(OffloadingVideoDecoderTest, ParallelizedOffloading) {
271   auto offload_config = TestVideoConfig::Large(VideoCodec::kVP9);
272   CreateWrapper(offload_config.coded_size().width(), VideoCodec::kVP9);
273
274   // Since this Initialize() should be happening on another thread, set the
275   // expectation after we make the call.
276   VideoDecoder::OutputCB output_cb;
277   offloading_decoder_->Initialize(
278       offload_config, false, nullptr, ExpectInitCB(true),
279       base::BindRepeating(&OffloadingVideoDecoderTest::OutputDone,
280                           base::Unretained(this)),
281       base::NullCallback());
282   EXPECT_CALL(*decoder_, Initialize_(_, false, nullptr, _, _, _))
283       .WillOnce(DoAll(VerifyNotOn(task_env_.GetMainThreadTaskRunner()),
284                       RunOnceCallback<3>(DecoderStatus::Codes::kOk),
285                       SaveArg<4>(&output_cb)));
286   task_env_.RunUntilIdle();
287
288   // When offloading decodes should be parallelized.
289   EXPECT_GT(offloading_decoder_->GetMaxDecodeRequests(), 1);
290
291   // Verify decode works and is called on the right thread.
292   offloading_decoder_->Decode(
293       DecoderBuffer::CreateEOSBuffer(),
294       base::BindOnce(&OffloadingVideoDecoderTest::DecodeDone,
295                      base::Unretained(this)));
296   offloading_decoder_->Decode(
297       DecoderBuffer::CreateEOSBuffer(),
298       base::BindOnce(&OffloadingVideoDecoderTest::DecodeDone,
299                      base::Unretained(this)));
300
301   EXPECT_CALL(*decoder_, Decode_(_, _))
302       .Times(2)
303       .WillRepeatedly(DoAll(VerifyNotOn(task_env_.GetMainThreadTaskRunner()),
304                             RunClosure(base::BindRepeating(output_cb, nullptr)),
305                             RunOnceCallback<1>(DecoderStatus::Codes::kOk)));
306   EXPECT_CALL(*this, DecodeDone(IsOkStatus()))
307       .Times(2)
308       .WillRepeatedly(VerifyOn(task_env_.GetMainThreadTaskRunner()));
309   EXPECT_CALL(*this, OutputDone(_))
310       .Times(2)
311       .WillRepeatedly(VerifyOn(task_env_.GetMainThreadTaskRunner()));
312   task_env_.RunUntilIdle();
313
314   // Reset so we can call Initialize() again.
315   offloading_decoder_->Reset(ExpectResetCB());
316   EXPECT_CALL(*decoder_, Reset_(_))
317       .WillOnce(DoAll(VerifyNotOn(task_env_.GetMainThreadTaskRunner()),
318                       RunOnceCallback<0>()));
319   task_env_.RunUntilIdle();
320 }
321
322 TEST_F(OffloadingVideoDecoderTest, ParallelizedOffloadingResetAbortsDecodes) {
323   auto offload_config = TestVideoConfig::Large(VideoCodec::kVP9);
324   CreateWrapper(offload_config.coded_size().width(), VideoCodec::kVP9);
325
326   // Since this Initialize() should be happening on another thread, set the
327   // expectation after we make the call.
328   VideoDecoder::OutputCB output_cb;
329   offloading_decoder_->Initialize(
330       offload_config, false, nullptr, ExpectInitCB(true),
331       base::BindRepeating(&OffloadingVideoDecoderTest::OutputDone,
332                           base::Unretained(this)),
333       base::NullCallback());
334   EXPECT_CALL(*decoder_, Initialize_(_, false, nullptr, _, _, _))
335       .WillOnce(DoAll(VerifyNotOn(task_env_.GetMainThreadTaskRunner()),
336                       RunOnceCallback<3>(DecoderStatus::Codes::kOk),
337                       SaveArg<4>(&output_cb)));
338   task_env_.RunUntilIdle();
339
340   // When offloading decodes should be parallelized.
341   EXPECT_GT(offloading_decoder_->GetMaxDecodeRequests(), 1);
342
343   // Verify decode works and is called on the right thread.
344   offloading_decoder_->Decode(
345       DecoderBuffer::CreateEOSBuffer(),
346       base::BindOnce(&OffloadingVideoDecoderTest::DecodeDone,
347                      base::Unretained(this)));
348   offloading_decoder_->Decode(
349       DecoderBuffer::CreateEOSBuffer(),
350       base::BindOnce(&OffloadingVideoDecoderTest::DecodeDone,
351                      base::Unretained(this)));
352
353   EXPECT_CALL(*decoder_, Decode_(_, _)).Times(0);
354   EXPECT_CALL(*this, DecodeDone(HasStatusCode(DecoderStatus::Codes::kAborted)))
355       .Times(2)
356       .WillRepeatedly(VerifyOn(task_env_.GetMainThreadTaskRunner()));
357   offloading_decoder_->Reset(ExpectResetCB());
358   EXPECT_CALL(*decoder_, Reset_(_))
359       .WillOnce(DoAll(VerifyNotOn(task_env_.GetMainThreadTaskRunner()),
360                       RunOnceClosure<0>()));
361   task_env_.RunUntilIdle();
362 }
363
364 }  // namespace media