Upload upstream chromium 108.0.5359.1
[platform/framework/web/chromium-efl.git] / media / filters / gav1_video_decoder_unittest.cc
1 // Copyright 2019 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 <memory>
6 #include <string>
7 #include <utility>
8 #include <vector>
9
10 #include "base/bind.h"
11 #include "base/callback_helpers.h"
12 #include "base/hash/md5.h"
13 #include "base/run_loop.h"
14 #include "base/strings/string_piece.h"
15 #include "base/test/task_environment.h"
16 #include "build/build_config.h"
17 #include "media/base/decoder_buffer.h"
18 #include "media/base/limits.h"
19 #include "media/base/mock_media_log.h"
20 #include "media/base/test_data_util.h"
21 #include "media/base/test_helpers.h"
22 #include "media/base/video_frame.h"
23 #include "media/ffmpeg/ffmpeg_common.h"
24 #include "media/filters/gav1_video_decoder.h"
25 #include "media/filters/in_memory_url_protocol.h"
26 #include "testing/gmock/include/gmock/gmock.h"
27
28 using ::testing::_;
29
30 namespace media {
31
32 namespace {
33
34 MATCHER(ContainsDecoderErrorLog, "") {
35   return CONTAINS_STRING(arg, "libgav1::Decoder::DequeueFrame failed");
36 }
37
38 // Similar to VideoFrame::HashFrameForTesting(), but uses visible_data() and
39 // visible_rect() instead of data() and coded_size() to determine the region to
40 // hash.
41 //
42 // The VideoFrame objects created by Gav1VideoDecoder have extended pixels
43 // outside the visible_rect(). Those extended pixels are for libgav1 internal
44 // use and are not part of the actual video frames. Unlike
45 // VideoFrame::HashFrameForTesting(), this function excludes the extended pixels
46 // and hashes only the actual video frames.
47 void HashFrameVisibleRectForTesting(base::MD5Context* context,
48                                     const VideoFrame& frame) {
49   DCHECK(context);
50   for (size_t plane = 0; plane < VideoFrame::NumPlanes(frame.format());
51        ++plane) {
52     int rows = frame.Rows(plane, frame.format(), frame.visible_rect().height());
53     for (int row = 0; row < rows; ++row) {
54       int row_bytes =
55           frame.RowBytes(plane, frame.format(), frame.visible_rect().width());
56       base::MD5Update(context, base::StringPiece(reinterpret_cast<const char*>(
57                                                      frame.visible_data(plane) +
58                                                      frame.stride(plane) * row),
59                                                  row_bytes));
60     }
61   }
62 }
63
64 }  // namespace
65
66 class Gav1VideoDecoderTest : public testing::Test {
67  public:
68   Gav1VideoDecoderTest()
69       : decoder_(new Gav1VideoDecoder(&media_log_)),
70         i_frame_buffer_(ReadTestDataFile("av1-I-frame-320x240")) {}
71
72   Gav1VideoDecoderTest(const Gav1VideoDecoderTest&) = delete;
73   Gav1VideoDecoderTest& operator=(const Gav1VideoDecoderTest&) = delete;
74
75   ~Gav1VideoDecoderTest() override { Destroy(); }
76
77   void Initialize() {
78     InitializeWithConfig(TestVideoConfig::Normal(VideoCodec::kAV1));
79   }
80
81   void InitializeWithConfigWithResult(const VideoDecoderConfig& config,
82                                       bool success) {
83     decoder_->Initialize(config, false, nullptr,
84                          base::BindOnce(
85                              [](bool success, DecoderStatus status) {
86                                EXPECT_EQ(status.is_ok(), success);
87                              },
88                              success),
89                          base::BindRepeating(&Gav1VideoDecoderTest::FrameReady,
90                                              base::Unretained(this)),
91                          base::NullCallback());
92     base::RunLoop().RunUntilIdle();
93   }
94
95   void InitializeWithConfig(const VideoDecoderConfig& config) {
96     InitializeWithConfigWithResult(config, true);
97   }
98
99   void Reinitialize() {
100     InitializeWithConfig(TestVideoConfig::Large(VideoCodec::kAV1));
101   }
102
103   void Reset() {
104     decoder_->Reset(NewExpectedClosure());
105     base::RunLoop().RunUntilIdle();
106   }
107
108   void Destroy() {
109     decoder_.reset();
110     base::RunLoop().RunUntilIdle();
111   }
112
113   // Sets up expectations and actions to put Gav1VideoDecoder in an active
114   // decoding state.
115   void ExpectDecodingState() {
116     EXPECT_TRUE(DecodeSingleFrame(i_frame_buffer_).is_ok());
117     ASSERT_EQ(1U, output_frames_.size());
118   }
119
120   // Sets up expectations and actions to put Gav1VideoDecoder in an end
121   // of stream state.
122   void ExpectEndOfStreamState() {
123     EXPECT_TRUE(DecodeSingleFrame(DecoderBuffer::CreateEOSBuffer()).is_ok());
124     ASSERT_FALSE(output_frames_.empty());
125   }
126
127   using InputBuffers = std::vector<scoped_refptr<DecoderBuffer>>;
128   using OutputFrames = std::vector<scoped_refptr<VideoFrame>>;
129
130   // Decodes all buffers in |input_buffers| and push all successfully decoded
131   // output frames into |output_frames|. Returns the last decode status returned
132   // by the decoder.
133   DecoderStatus DecodeMultipleFrames(const InputBuffers& input_buffers) {
134     for (auto iter = input_buffers.begin(); iter != input_buffers.end();
135          ++iter) {
136       DecoderStatus status = Decode(*iter);
137       switch (status.code()) {
138         case DecoderStatus::Codes::kOk:
139           break;
140         case DecoderStatus::Codes::kAborted:
141           NOTREACHED();
142           [[fallthrough]];
143         default:
144           DCHECK(output_frames_.empty());
145           return status;
146       }
147     }
148     return DecoderStatus::Codes::kOk;
149   }
150
151   // Decodes the single compressed frame in |buffer|.
152   DecoderStatus DecodeSingleFrame(scoped_refptr<DecoderBuffer> buffer) {
153     InputBuffers input_buffers;
154     input_buffers.push_back(std::move(buffer));
155     return DecodeMultipleFrames(input_buffers);
156   }
157
158   // Decodes |i_frame_buffer_| and then decodes the data contained in the file
159   // named |test_file_name|. This function expects both buffers to decode to
160   // frames that are the same size.
161   void DecodeIFrameThenTestFile(const std::string& test_file_name,
162                                 const gfx::Size& expected_size) {
163     Initialize();
164     scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(test_file_name);
165
166     InputBuffers input_buffers;
167     input_buffers.push_back(i_frame_buffer_);
168     input_buffers.push_back(buffer);
169     input_buffers.push_back(DecoderBuffer::CreateEOSBuffer());
170
171     EXPECT_TRUE(DecodeMultipleFrames(input_buffers).is_ok());
172     ASSERT_EQ(2U, output_frames_.size());
173
174     gfx::Size original_size = TestVideoConfig::NormalCodedSize();
175     EXPECT_EQ(original_size.width(),
176               output_frames_[0]->visible_rect().size().width());
177     EXPECT_EQ(original_size.height(),
178               output_frames_[0]->visible_rect().size().height());
179     EXPECT_EQ(expected_size.width(),
180               output_frames_[1]->visible_rect().size().width());
181     EXPECT_EQ(expected_size.height(),
182               output_frames_[1]->visible_rect().size().height());
183   }
184
185   DecoderStatus Decode(scoped_refptr<DecoderBuffer> buffer) {
186     DecoderStatus status;
187     EXPECT_CALL(*this, DecodeDone(_)).WillOnce(testing::SaveArg<0>(&status));
188
189     decoder_->Decode(std::move(buffer),
190                      base::BindOnce(&Gav1VideoDecoderTest::DecodeDone,
191                                     base::Unretained(this)));
192     base::RunLoop().RunUntilIdle();
193
194     return status;
195   }
196
197   void FrameReady(scoped_refptr<VideoFrame> frame) {
198     DCHECK(!frame->metadata().end_of_stream);
199     output_frames_.push_back(std::move(frame));
200   }
201
202   std::string GetVideoFrameHash(const VideoFrame& frame) {
203     base::MD5Context md5_context;
204     base::MD5Init(&md5_context);
205     HashFrameVisibleRectForTesting(&md5_context, frame);
206     base::MD5Digest digest;
207     base::MD5Final(&digest, &md5_context);
208     return base::MD5DigestToBase16(digest);
209   }
210
211   MOCK_METHOD1(DecodeDone, void(DecoderStatus));
212
213   testing::StrictMock<MockMediaLog> media_log_;
214
215   base::test::SingleThreadTaskEnvironment task_environment_;
216   std::unique_ptr<Gav1VideoDecoder> decoder_;
217
218   scoped_refptr<DecoderBuffer> i_frame_buffer_;
219   OutputFrames output_frames_;
220 };
221
222 TEST_F(Gav1VideoDecoderTest, Initialize_Normal) {
223   Initialize();
224 }
225
226 TEST_F(Gav1VideoDecoderTest, Reinitialize_Normal) {
227   Initialize();
228   Reinitialize();
229 }
230
231 TEST_F(Gav1VideoDecoderTest, Reinitialize_AfterDecodeFrame) {
232   Initialize();
233   ExpectDecodingState();
234   Reinitialize();
235 }
236
237 TEST_F(Gav1VideoDecoderTest, Reinitialize_AfterReset) {
238   Initialize();
239   ExpectDecodingState();
240   Reset();
241   Reinitialize();
242 }
243
244 TEST_F(Gav1VideoDecoderTest, DecodeFrame_Normal) {
245   Initialize();
246
247   // Simulate decoding a single frame.
248   EXPECT_TRUE(DecodeSingleFrame(i_frame_buffer_).is_ok());
249   ASSERT_EQ(1U, output_frames_.size());
250
251   const auto& frame = output_frames_.front();
252   EXPECT_EQ(PIXEL_FORMAT_I420, frame->format());
253   EXPECT_EQ("589dc641b7742ffe7a2b0d4c16aa3e86", GetVideoFrameHash(*frame));
254 }
255
256 TEST_F(Gav1VideoDecoderTest, DecodeFrame_8bitMono) {
257   Initialize();
258   EXPECT_TRUE(
259       DecodeSingleFrame(ReadTestDataFile("av1-monochrome-I-frame-320x240-8bpp"))
260           .is_ok());
261   ASSERT_EQ(1U, output_frames_.size());
262
263   const auto& frame = output_frames_.front();
264   EXPECT_EQ(PIXEL_FORMAT_I420, frame->format());
265   EXPECT_EQ("eeba03dcc9c22c4632bf74b481db36b2", GetVideoFrameHash(*frame));
266 }
267
268 TEST_F(Gav1VideoDecoderTest, DecodeFrame_10bitMono) {
269   Initialize();
270   EXPECT_TRUE(DecodeSingleFrame(
271                   ReadTestDataFile("av1-monochrome-I-frame-320x240-10bpp"))
272                   .is_ok());
273   ASSERT_EQ(1U, output_frames_.size());
274
275   const auto& frame = output_frames_.front();
276   EXPECT_EQ(PIXEL_FORMAT_YUV420P10, frame->format());
277   EXPECT_EQ("026c1fed9e161f09d816ac7278458a80", GetVideoFrameHash(*frame));
278 }
279
280 // libgav1 does not support bit depth 12.
281 TEST_F(Gav1VideoDecoderTest, DISABLED_DecodeFrame_12bitMono) {
282   Initialize();
283   EXPECT_TRUE(DecodeSingleFrame(
284                   ReadTestDataFile("av1-monochrome-I-frame-320x240-12bpp"))
285                   .is_ok());
286   ASSERT_EQ(1U, output_frames_.size());
287
288   const auto& frame = output_frames_.front();
289   EXPECT_EQ(PIXEL_FORMAT_YUV420P12, frame->format());
290   EXPECT_EQ("32115092dc00fbe86823b0b714a0f63e", GetVideoFrameHash(*frame));
291 }
292
293 // Decode |i_frame_buffer_| and then a frame with a larger width and verify
294 // the output size was adjusted.
295 TEST_F(Gav1VideoDecoderTest, DecodeFrame_LargerWidth) {
296   DecodeIFrameThenTestFile("av1-I-frame-1280x720", gfx::Size(1280, 720));
297 }
298
299 // Decode a VP9 frame which should trigger a decoder error.
300 TEST_F(Gav1VideoDecoderTest, DecodeFrame_Error) {
301   Initialize();
302   EXPECT_MEDIA_LOG(ContainsDecoderErrorLog());
303   DecodeSingleFrame(ReadTestDataFile("vp9-I-frame-320x240"));
304 }
305
306 // Test resetting when decoder has initialized but not decoded.
307 TEST_F(Gav1VideoDecoderTest, Reset_Initialized) {
308   Initialize();
309   Reset();
310 }
311
312 // Test resetting when decoder has decoded single frame.
313 TEST_F(Gav1VideoDecoderTest, Reset_Decoding) {
314   Initialize();
315   ExpectDecodingState();
316   Reset();
317 }
318
319 // Test resetting when decoder has hit end of stream.
320 TEST_F(Gav1VideoDecoderTest, Reset_EndOfStream) {
321   Initialize();
322   ExpectDecodingState();
323   ExpectEndOfStreamState();
324   Reset();
325 }
326
327 // Test destruction when decoder has initialized but not decoded.
328 TEST_F(Gav1VideoDecoderTest, Destroy_Initialized) {
329   Initialize();
330   Destroy();
331 }
332
333 // Test destruction when decoder has decoded single frame.
334 TEST_F(Gav1VideoDecoderTest, Destroy_Decoding) {
335   Initialize();
336   ExpectDecodingState();
337   Destroy();
338 }
339
340 // Test destruction when decoder has hit end of stream.
341 TEST_F(Gav1VideoDecoderTest, Destroy_EndOfStream) {
342   Initialize();
343   ExpectDecodingState();
344   ExpectEndOfStreamState();
345   Destroy();
346 }
347
348 TEST_F(Gav1VideoDecoderTest, FrameValidAfterPoolDestruction) {
349   Initialize();
350   Decode(i_frame_buffer_);
351   Destroy();
352
353   ASSERT_FALSE(output_frames_.empty());
354
355   // Write to the Y plane. The memory tools should detect a
356   // use-after-free if the storage was actually removed by pool destruction.
357   memset(output_frames_.front()->writable_data(VideoFrame::kYPlane), 0xff,
358          output_frames_.front()->rows(VideoFrame::kYPlane) *
359              output_frames_.front()->stride(VideoFrame::kYPlane));
360 }
361
362 }  // namespace media