vp9[loongarch]: Optimize fdct4x4/8x8_lsx
[platform/upstream/libvpx.git] / test / frame_size_tests.cc
1 /*
2  *  Copyright (c) 2014 The WebM project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 #include <memory>
11
12 #include "third_party/googletest/src/include/gtest/gtest.h"
13 #include "test/codec_factory.h"
14 #include "test/register_state_check.h"
15 #include "test/video_source.h"
16
17 namespace {
18
19 class EncoderWithExpectedError : public ::libvpx_test::Encoder {
20  public:
21   EncoderWithExpectedError(vpx_codec_enc_cfg_t cfg,
22                            unsigned long deadline,          // NOLINT
23                            const unsigned long init_flags,  // NOLINT
24                            ::libvpx_test::TwopassStatsStore *stats)
25       : ::libvpx_test::Encoder(cfg, deadline, init_flags, stats) {}
26   // This overrides with expected error code.
27   void EncodeFrame(::libvpx_test::VideoSource *video,
28                    const unsigned long frame_flags,  // NOLINT
29                    const vpx_codec_err_t expected_err) {
30     if (video->img()) {
31       EncodeFrameInternal(*video, frame_flags, expected_err);
32     } else {
33       Flush();
34     }
35
36     // Handle twopass stats
37     ::libvpx_test::CxDataIterator iter = GetCxData();
38
39     while (const vpx_codec_cx_pkt_t *pkt = iter.Next()) {
40       if (pkt->kind != VPX_CODEC_STATS_PKT) continue;
41
42       stats_->Append(*pkt);
43     }
44   }
45
46  protected:
47   void EncodeFrameInternal(const ::libvpx_test::VideoSource &video,
48                            const unsigned long frame_flags,  // NOLINT
49                            const vpx_codec_err_t expected_err) {
50     vpx_codec_err_t res;
51     const vpx_image_t *img = video.img();
52
53     // Handle frame resizing
54     if (cfg_.g_w != img->d_w || cfg_.g_h != img->d_h) {
55       cfg_.g_w = img->d_w;
56       cfg_.g_h = img->d_h;
57       res = vpx_codec_enc_config_set(&encoder_, &cfg_);
58       ASSERT_EQ(res, VPX_CODEC_OK) << EncoderError();
59     }
60
61     // Encode the frame
62     API_REGISTER_STATE_CHECK(res = vpx_codec_encode(&encoder_, img, video.pts(),
63                                                     video.duration(),
64                                                     frame_flags, deadline_));
65     ASSERT_EQ(expected_err, res) << EncoderError();
66   }
67
68   virtual vpx_codec_iface_t *CodecInterface() const {
69 #if CONFIG_VP9_ENCODER
70     return &vpx_codec_vp9_cx_algo;
71 #else
72     return nullptr;
73 #endif
74   }
75 };
76
77 class VP9FrameSizeTestsLarge : public ::libvpx_test::EncoderTest,
78                                public ::testing::Test {
79  protected:
80   VP9FrameSizeTestsLarge()
81       : EncoderTest(&::libvpx_test::kVP9), expected_res_(VPX_CODEC_OK) {}
82   virtual ~VP9FrameSizeTestsLarge() {}
83
84   virtual void SetUp() {
85     InitializeConfig();
86     SetMode(::libvpx_test::kRealTime);
87   }
88
89   virtual bool HandleDecodeResult(const vpx_codec_err_t res_dec,
90                                   const libvpx_test::VideoSource & /*video*/,
91                                   libvpx_test::Decoder *decoder) {
92     EXPECT_EQ(expected_res_, res_dec) << decoder->DecodeError();
93     return !::testing::Test::HasFailure();
94   }
95
96   virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
97                                   ::libvpx_test::Encoder *encoder) {
98     if (video->frame() == 0) {
99       encoder->Control(VP8E_SET_CPUUSED, 7);
100       encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
101       encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7);
102       encoder->Control(VP8E_SET_ARNR_STRENGTH, 5);
103       encoder->Control(VP8E_SET_ARNR_TYPE, 3);
104     }
105   }
106
107   using ::libvpx_test::EncoderTest::RunLoop;
108   virtual void RunLoop(::libvpx_test::VideoSource *video,
109                        const vpx_codec_err_t expected_err) {
110     stats_.Reset();
111
112     ASSERT_TRUE(passes_ == 1 || passes_ == 2);
113     for (unsigned int pass = 0; pass < passes_; pass++) {
114       last_pts_ = 0;
115
116       if (passes_ == 1) {
117         cfg_.g_pass = VPX_RC_ONE_PASS;
118       } else if (pass == 0) {
119         cfg_.g_pass = VPX_RC_FIRST_PASS;
120       } else {
121         cfg_.g_pass = VPX_RC_LAST_PASS;
122       }
123
124       BeginPassHook(pass);
125       std::unique_ptr<EncoderWithExpectedError> encoder(
126           new EncoderWithExpectedError(cfg_, deadline_, init_flags_, &stats_));
127       ASSERT_NE(encoder.get(), nullptr);
128
129       ASSERT_NO_FATAL_FAILURE(video->Begin());
130       encoder->InitEncoder(video);
131       ASSERT_FALSE(::testing::Test::HasFatalFailure());
132       for (bool again = true; again; video->Next()) {
133         again = (video->img() != nullptr);
134
135         PreEncodeFrameHook(video, encoder.get());
136         encoder->EncodeFrame(video, frame_flags_, expected_err);
137
138         PostEncodeFrameHook(encoder.get());
139
140         ::libvpx_test::CxDataIterator iter = encoder->GetCxData();
141
142         while (const vpx_codec_cx_pkt_t *pkt = iter.Next()) {
143           pkt = MutateEncoderOutputHook(pkt);
144           again = true;
145           switch (pkt->kind) {
146             case VPX_CODEC_CX_FRAME_PKT:
147               ASSERT_GE(pkt->data.frame.pts, last_pts_);
148               last_pts_ = pkt->data.frame.pts;
149               FramePktHook(pkt);
150               break;
151
152             case VPX_CODEC_PSNR_PKT: PSNRPktHook(pkt); break;
153             case VPX_CODEC_STATS_PKT: StatsPktHook(pkt); break;
154             default: break;
155           }
156         }
157
158         if (!Continue()) break;
159       }
160
161       EndPassHook();
162
163       if (!Continue()) break;
164     }
165   }
166
167   vpx_codec_err_t expected_res_;
168 };
169
170 TEST_F(VP9FrameSizeTestsLarge, TestInvalidSizes) {
171   ::libvpx_test::RandomVideoSource video;
172
173 #if CONFIG_SIZE_LIMIT
174   video.SetSize(DECODE_WIDTH_LIMIT + 16, DECODE_HEIGHT_LIMIT + 16);
175   video.set_limit(2);
176   expected_res_ = VPX_CODEC_MEM_ERROR;
177   ASSERT_NO_FATAL_FAILURE(RunLoop(&video, expected_res_));
178 #endif
179 }
180
181 TEST_F(VP9FrameSizeTestsLarge, ValidSizes) {
182   ::libvpx_test::RandomVideoSource video;
183
184 #if CONFIG_SIZE_LIMIT
185   video.SetSize(DECODE_WIDTH_LIMIT, DECODE_HEIGHT_LIMIT);
186   video.set_limit(2);
187   expected_res_ = VPX_CODEC_OK;
188   ASSERT_NO_FATAL_FAILURE(::libvpx_test::EncoderTest::RunLoop(&video));
189 #else
190 // This test produces a pretty large single frame allocation,  (roughly
191 // 25 megabits). The encoder allocates a good number of these frames
192 // one for each lag in frames (for 2 pass), and then one for each possible
193 // reference buffer (8) - we can end up with up to 30 buffers of roughly this
194 // size or almost 1 gig of memory.
195 // In total the allocations will exceed 2GiB which may cause a failure with
196 // mingw + wine, use a smaller size in that case.
197 #if defined(_WIN32) && !defined(_WIN64) || defined(__OS2__)
198   video.SetSize(4096, 3072);
199 #else
200   video.SetSize(4096, 4096);
201 #endif
202   video.set_limit(2);
203   expected_res_ = VPX_CODEC_OK;
204   ASSERT_NO_FATAL_FAILURE(::libvpx_test::EncoderTest::RunLoop(&video));
205 #endif
206 }
207
208 TEST_F(VP9FrameSizeTestsLarge, OneByOneVideo) {
209   ::libvpx_test::RandomVideoSource video;
210
211   video.SetSize(1, 1);
212   video.set_limit(2);
213   expected_res_ = VPX_CODEC_OK;
214   ASSERT_NO_FATAL_FAILURE(::libvpx_test::EncoderTest::RunLoop(&video));
215 }
216 }  // namespace