1 /*
2  * Copyright (c) 2018, Alliance for Open Media. All rights reserved
3  *
4  * This source code is subject to the terms of the BSD 2 Clause License and
5  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6  * was not distributed with this source code in the LICENSE file, you can
7  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8  * Media Patent License 1.0 was not distributed with this source code in the
9  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10  */
11 
12 #include "third_party/googletest/src/googletest/include/gtest/gtest.h"
13 
14 #include "av1/encoder/encoder.h"
15 
16 #include "test/codec_factory.h"
17 #include "test/encode_test_driver.h"
18 #include "test/util.h"
19 #include "test/y4m_video_source.h"
20 #include "test/yuv_video_source.h"
21 
22 namespace {
23 
24 using ::testing::make_tuple;
25 using ::testing::tuple;
26 
27 /* TESTING PARAMETERS */
28 
29 #define NUM_TEST_VIDEOS 3
30 
31 const int kBitrate = 40;
32 
33 // PSNR thresholds found by experiment
34 const double kPSNRThresholds[] = { 26.0, 28.0, 20.0 };
35 
36 typedef struct {
37   const char *filename;
38   aom_img_fmt fmt;
39   aom_bit_depth_t bit_depth;
40   unsigned int profile;
41   unsigned int limit;
42   unsigned int screen_content;
43 } TestVideoParam;
44 
45 const TestVideoParam kTestVideoVectors[] = {
46   { "park_joy_90p_8_420.y4m", AOM_IMG_FMT_I420, AOM_BITS_8, 0, 5, 0 },
47   { "park_joy_90p_10_444.y4m", AOM_IMG_FMT_I44416, AOM_BITS_10, 1, 5, 0 },
48   { "screendata.y4m", AOM_IMG_FMT_I420, AOM_BITS_8, 0, 4, 1 },
49 };
50 
51 // Superres modes tested
52 // SUPERRES_QTHRESH is not included, as it has its own test
53 const SUPERRES_MODE kSuperresModesNotQThresh[] = { SUPERRES_FIXED,
54                                                    SUPERRES_RANDOM };
55 
56 // Superres denominators and superres kf denominators to be tested
57 typedef tuple<int, int> SuperresDenominatorPair;
58 const SuperresDenominatorPair kSuperresDenominators[] = {
59   make_tuple(16, 9),  make_tuple(13, 11), make_tuple(9, 9),
60   make_tuple(13, 13), make_tuple(11, 16), make_tuple(8, 16),
61   make_tuple(16, 8),  make_tuple(8, 8),   make_tuple(9, 14),
62 };
63 
64 // Superres q thresholds and superres kf q thresholds to be tested
65 typedef tuple<int, int> SuperresQThresholdPair;
66 const SuperresQThresholdPair kSuperresQThresholds[] = {
67   make_tuple(63, 63), make_tuple(63, 41), make_tuple(17, 63),
68   make_tuple(41, 11), make_tuple(1, 37),  make_tuple(11, 11),
69   make_tuple(1, 1),   make_tuple(17, 29), make_tuple(29, 11),
70 };
71 
72 /* END (TESTING PARAMETERS) */
73 
74 // Test parameter list:
75 //  <[needed for EncoderTest], test_video_idx_, superres_mode_,
76 //  tuple(superres_denom_, superres_kf_denom_)>
77 typedef tuple<const libaom_test::CodecFactory *, int, SUPERRES_MODE,
78               SuperresDenominatorPair>
79     HorzSuperresTestParam;
80 
81 class HorzSuperresEndToEndTest
82     : public ::testing::TestWithParam<HorzSuperresTestParam>,
83       public ::libaom_test::EncoderTest {
84  protected:
HorzSuperresEndToEndTest()85   HorzSuperresEndToEndTest()
86       : EncoderTest(GET_PARAM(0)), test_video_idx_(GET_PARAM(1)),
87         superres_mode_(GET_PARAM(2)), psnr_(0.0), frame_count_(0) {
88     test_video_param_ = kTestVideoVectors[test_video_idx_];
89 
90     SuperresDenominatorPair denoms = GET_PARAM(3);
91     superres_denom_ = ::testing::get<0>(denoms);
92     superres_kf_denom_ = ::testing::get<1>(denoms);
93   }
94 
~HorzSuperresEndToEndTest()95   virtual ~HorzSuperresEndToEndTest() {}
96 
SetUp()97   virtual void SetUp() {
98     InitializeConfig();
99     SetMode(::libaom_test::kTwoPassGood);
100     cfg_.g_lag_in_frames = 5;
101     cfg_.rc_end_usage = AOM_VBR;
102     cfg_.rc_target_bitrate = kBitrate;
103     cfg_.g_error_resilient = 0;
104     cfg_.g_profile = test_video_param_.profile;
105     cfg_.g_input_bit_depth = (unsigned int)test_video_param_.bit_depth;
106     cfg_.g_bit_depth = test_video_param_.bit_depth;
107     init_flags_ = AOM_CODEC_USE_PSNR;
108     if (cfg_.g_bit_depth > 8) init_flags_ |= AOM_CODEC_USE_HIGHBITDEPTH;
109 
110     // Set superres parameters
111     cfg_.rc_superres_mode = superres_mode_;
112     cfg_.rc_superres_denominator = superres_denom_;
113     cfg_.rc_superres_kf_denominator = superres_kf_denom_;
114   }
115 
BeginPassHook(unsigned int)116   virtual void BeginPassHook(unsigned int) {
117     psnr_ = 0.0;
118     frame_count_ = 0;
119   }
120 
PSNRPktHook(const aom_codec_cx_pkt_t * pkt)121   virtual void PSNRPktHook(const aom_codec_cx_pkt_t *pkt) {
122     psnr_ += pkt->data.psnr.psnr[0];
123     frame_count_++;
124   }
125 
PreEncodeFrameHook(::libaom_test::VideoSource * video,::libaom_test::Encoder * encoder)126   virtual void PreEncodeFrameHook(::libaom_test::VideoSource *video,
127                                   ::libaom_test::Encoder *encoder) {
128     if (video->frame() == 1) {
129       encoder->Control(AV1E_SET_FRAME_PARALLEL_DECODING, 1);
130       encoder->Control(AV1E_SET_TILE_COLUMNS, 4);
131 
132       // Set cpu-used = 8 for speed
133       encoder->Control(AOME_SET_CPUUSED, 8);
134 
135       // Test screen coding tools
136       if (test_video_param_.screen_content)
137         encoder->Control(AV1E_SET_TUNE_CONTENT, AOM_CONTENT_SCREEN);
138       else
139         encoder->Control(AV1E_SET_TUNE_CONTENT, AOM_CONTENT_DEFAULT);
140 
141       encoder->Control(AOME_SET_ENABLEAUTOALTREF, 1);
142       encoder->Control(AOME_SET_ARNR_MAXFRAMES, 7);
143       encoder->Control(AOME_SET_ARNR_STRENGTH, 5);
144     }
145   }
146 
GetAveragePsnr() const147   double GetAveragePsnr() const {
148     if (frame_count_) return psnr_ / frame_count_;
149     return 0.0;
150   }
151 
GetPsnrThreshold()152   double GetPsnrThreshold() { return kPSNRThresholds[test_video_idx_]; }
153 
DoTest()154   void DoTest() {
155     testing::internal::scoped_ptr<libaom_test::VideoSource> video;
156     video.reset(new libaom_test::Y4mVideoSource(test_video_param_.filename, 0,
157                                                 test_video_param_.limit));
158     ASSERT_TRUE(video.get() != NULL);
159 
160     ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
161     const double psnr = GetAveragePsnr();
162     EXPECT_GT(psnr, GetPsnrThreshold())
163         << "superres_mode_ = " << superres_mode_
164         << ", superres_denom_ = " << superres_denom_
165         << ", superres_kf_denom_ = " << superres_kf_denom_;
166 
167     EXPECT_EQ(test_video_param_.limit, frame_count_)
168         << "superres_mode_ = " << superres_mode_
169         << ", superres_denom_ = " << superres_denom_
170         << ", superres_kf_denom_ = " << superres_kf_denom_;
171   }
172 
173   int test_video_idx_;
174   TestVideoParam test_video_param_;
175   SUPERRES_MODE superres_mode_;
176   int superres_denom_;
177   int superres_kf_denom_;
178 
179  private:
180   double psnr_;
181   unsigned int frame_count_;
182 };
183 
TEST_P(HorzSuperresEndToEndTest,HorzSuperresEndToEndPSNRTest)184 TEST_P(HorzSuperresEndToEndTest, HorzSuperresEndToEndPSNRTest) { DoTest(); }
185 
186 AV1_INSTANTIATE_TEST_CASE(HorzSuperresEndToEndTest,
187                           ::testing::Range(0, NUM_TEST_VIDEOS),
188                           ::testing::ValuesIn(kSuperresModesNotQThresh),
189                           ::testing::ValuesIn(kSuperresDenominators));
190 
191 // Test parameter list:
192 //  <[needed for EncoderTest], test_video_idx_, tuple(superres_denom_,
193 //  superres_kf_denom_), tuple(superres_qthresh_,superres_kf_qthresh_)>
194 typedef tuple<const libaom_test::CodecFactory *, int, SuperresDenominatorPair,
195               SuperresQThresholdPair>
196     HorzSuperresQThreshTestParam;
197 
198 class HorzSuperresQThreshEndToEndTest
199     : public ::testing::TestWithParam<HorzSuperresQThreshTestParam>,
200       public ::libaom_test::EncoderTest {
201  protected:
HorzSuperresQThreshEndToEndTest()202   HorzSuperresQThreshEndToEndTest()
203       : EncoderTest(GET_PARAM(0)), test_video_idx_(GET_PARAM(1)),
204         superres_mode_(SUPERRES_QTHRESH), psnr_(0.0), frame_count_(0) {
205     test_video_param_ = kTestVideoVectors[test_video_idx_];
206 
207     SuperresDenominatorPair denoms = GET_PARAM(2);
208     superres_denom_ = ::testing::get<0>(denoms);
209     superres_kf_denom_ = ::testing::get<1>(denoms);
210 
211     SuperresQThresholdPair qthresholds = GET_PARAM(3);
212     superres_qthresh_ = ::testing::get<0>(qthresholds);
213     superres_kf_qthresh_ = ::testing::get<1>(qthresholds);
214   }
215 
~HorzSuperresQThreshEndToEndTest()216   virtual ~HorzSuperresQThreshEndToEndTest() {}
217 
SetUp()218   virtual void SetUp() {
219     InitializeConfig();
220     SetMode(::libaom_test::kTwoPassGood);
221     cfg_.g_lag_in_frames = 5;
222     cfg_.rc_end_usage = AOM_VBR;
223     cfg_.rc_target_bitrate = kBitrate;
224     cfg_.g_error_resilient = 0;
225     cfg_.g_profile = test_video_param_.profile;
226     cfg_.g_input_bit_depth = (unsigned int)test_video_param_.bit_depth;
227     cfg_.g_bit_depth = test_video_param_.bit_depth;
228     init_flags_ = AOM_CODEC_USE_PSNR;
229     if (cfg_.g_bit_depth > 8) init_flags_ |= AOM_CODEC_USE_HIGHBITDEPTH;
230 
231     // Set superres parameters
232     cfg_.rc_superres_mode = superres_mode_;
233     cfg_.rc_superres_denominator = superres_denom_;
234     cfg_.rc_superres_kf_denominator = superres_kf_denom_;
235     cfg_.rc_superres_qthresh = superres_qthresh_;
236     cfg_.rc_superres_kf_qthresh = superres_kf_qthresh_;
237   }
238 
BeginPassHook(unsigned int)239   virtual void BeginPassHook(unsigned int) {
240     psnr_ = 0.0;
241     frame_count_ = 0;
242   }
243 
PSNRPktHook(const aom_codec_cx_pkt_t * pkt)244   virtual void PSNRPktHook(const aom_codec_cx_pkt_t *pkt) {
245     psnr_ += pkt->data.psnr.psnr[0];
246     frame_count_++;
247   }
248 
PreEncodeFrameHook(::libaom_test::VideoSource * video,::libaom_test::Encoder * encoder)249   virtual void PreEncodeFrameHook(::libaom_test::VideoSource *video,
250                                   ::libaom_test::Encoder *encoder) {
251     if (video->frame() == 1) {
252       encoder->Control(AV1E_SET_FRAME_PARALLEL_DECODING, 1);
253       encoder->Control(AV1E_SET_TILE_COLUMNS, 0);
254 
255       // Set cpu-used = 8 for speed
256       encoder->Control(AOME_SET_CPUUSED, 8);
257 
258       // Test screen coding tools
259       if (test_video_param_.screen_content)
260         encoder->Control(AV1E_SET_TUNE_CONTENT, AOM_CONTENT_SCREEN);
261       else
262         encoder->Control(AV1E_SET_TUNE_CONTENT, AOM_CONTENT_DEFAULT);
263 
264       encoder->Control(AOME_SET_ENABLEAUTOALTREF, 1);
265       encoder->Control(AOME_SET_ARNR_MAXFRAMES, 7);
266       encoder->Control(AOME_SET_ARNR_STRENGTH, 5);
267     }
268   }
269 
GetAveragePsnr() const270   double GetAveragePsnr() const {
271     if (frame_count_) return psnr_ / frame_count_;
272     return 0.0;
273   }
274 
GetPsnrThreshold()275   double GetPsnrThreshold() { return kPSNRThresholds[test_video_idx_]; }
276 
DoTest()277   void DoTest() {
278     testing::internal::scoped_ptr<libaom_test::VideoSource> video;
279     video.reset(new libaom_test::Y4mVideoSource(test_video_param_.filename, 0,
280                                                 test_video_param_.limit));
281     ASSERT_TRUE(video.get() != NULL);
282 
283     ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
284     const double psnr = GetAveragePsnr();
285     EXPECT_GT(psnr, GetPsnrThreshold())
286         << "superres_mode_ = " << superres_mode_
287         << ", superres_denom_ = " << superres_denom_
288         << ", superres_kf_denom_ = " << superres_kf_denom_
289         << ", superres_qthresh_ = " << superres_qthresh_
290         << ", superres_kf_qthresh_ = " << superres_kf_qthresh_;
291 
292     EXPECT_EQ(test_video_param_.limit, frame_count_)
293         << "superres_mode_ = " << superres_mode_
294         << ", superres_denom_ = " << superres_denom_
295         << ", superres_kf_denom_ = " << superres_kf_denom_
296         << ", superres_qthresh_ = " << superres_qthresh_
297         << ", superres_kf_qthresh_ = " << superres_kf_qthresh_;
298   }
299 
300   int test_video_idx_;
301   TestVideoParam test_video_param_;
302   SUPERRES_MODE superres_mode_;
303   int superres_denom_;
304   int superres_kf_denom_;
305   int superres_qthresh_;
306   int superres_kf_qthresh_;
307 
308  private:
309   double psnr_;
310   unsigned int frame_count_;
311 };
312 
TEST_P(HorzSuperresQThreshEndToEndTest,HorzSuperresQThreshEndToEndPSNRTest)313 TEST_P(HorzSuperresQThreshEndToEndTest, HorzSuperresQThreshEndToEndPSNRTest) {
314   DoTest();
315 }
316 
317 AV1_INSTANTIATE_TEST_CASE(HorzSuperresQThreshEndToEndTest,
318                           ::testing::Range(0, NUM_TEST_VIDEOS),
319                           ::testing::ValuesIn(kSuperresDenominators),
320                           ::testing::ValuesIn(kSuperresQThresholds));
321 
322 }  // namespace
323