xref: /aosp_15_r20/external/libaom/test/monochrome_test.cc (revision 77c1e3ccc04c968bd2bc212e87364f250e820521)
1 /*
2  * Copyright (c) 2016, 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 <climits>
13 #include <vector>
14 #include "gtest/gtest.h"
15 #include "test/codec_factory.h"
16 #include "test/encode_test_driver.h"
17 #include "test/i420_video_source.h"
18 #include "test/video_source.h"
19 #include "test/util.h"
20 
21 namespace {
22 
23 const unsigned int kCqLevel = 18;
24 const double kMaxPsnr = 100.0;
25 
26 // kPsnrThreshold represents the psnr threshold used to validate the quality of
27 // the first frame. The indices correspond to one/two-pass, allintra and
28 // realtime encoding modes.
29 const double kPsnrThreshold[3] = { 29.0, 41.5, 41.5 };
30 
31 // kPsnrFluctuation represents the maximum allowed psnr fluctuation w.r.t first
32 // frame. The indices correspond to one/two-pass, allintra and realtime
33 // encoding modes.
34 const double kPsnrFluctuation[3] = { 2.5, 0.3, 17.0 };
35 
36 class MonochromeTest
37     : public ::libaom_test::CodecTestWith3Params<libaom_test::TestMode, int,
38                                                  int>,
39       public ::libaom_test::EncoderTest {
40  protected:
MonochromeTest()41   MonochromeTest()
42       : EncoderTest(GET_PARAM(0)), lossless_(GET_PARAM(2)),
43         frame0_psnr_y_(0.0) {}
44 
45   ~MonochromeTest() override = default;
46 
SetUp()47   void SetUp() override { InitializeConfig(GET_PARAM(1)); }
48 
PreEncodeFrameHook(::libaom_test::VideoSource * video,::libaom_test::Encoder * encoder)49   void PreEncodeFrameHook(::libaom_test::VideoSource *video,
50                           ::libaom_test::Encoder *encoder) override {
51     if (video->frame() == 0) {
52       encoder->Control(AOME_SET_CPUUSED, GET_PARAM(3));
53       if (mode_ == ::libaom_test::kAllIntra) {
54         encoder->Control(AOME_SET_CQ_LEVEL, kCqLevel);
55       }
56       if (lossless_) {
57         encoder->Control(AV1E_SET_LOSSLESS, 1);
58       }
59     }
60   }
61 
DecompressedFrameHook(const aom_image_t & img,aom_codec_pts_t pts)62   void DecompressedFrameHook(const aom_image_t &img,
63                              aom_codec_pts_t pts) override {
64     (void)pts;
65 
66     // Get value of top-left corner pixel of U plane
67     int chroma_value = img.planes[AOM_PLANE_U][0];
68 
69     bool is_chroma_constant =
70         ComparePlaneToValue(img, AOM_PLANE_U, chroma_value) &&
71         ComparePlaneToValue(img, AOM_PLANE_V, chroma_value);
72 
73     // Chroma planes should be constant
74     EXPECT_TRUE(is_chroma_constant);
75 
76     // Monochrome flag on image should be set
77     EXPECT_EQ(img.monochrome, 1);
78 
79     chroma_value_list_.push_back(chroma_value);
80   }
81 
82   // Returns true if all pixels on the plane are equal to value, and returns
83   // false otherwise.
ComparePlaneToValue(const aom_image_t & img,const int plane,const int value)84   bool ComparePlaneToValue(const aom_image_t &img, const int plane,
85                            const int value) {
86     const int w = aom_img_plane_width(&img, plane);
87     const int h = aom_img_plane_height(&img, plane);
88     const uint8_t *const buf = img.planes[plane];
89     const int stride = img.stride[plane];
90 
91     for (int r = 0; r < h; ++r) {
92       for (int c = 0; c < w; ++c) {
93         if (buf[r * stride + c] != value) return false;
94       }
95     }
96     return true;
97   }
98 
PSNRPktHook(const aom_codec_cx_pkt_t * pkt)99   void PSNRPktHook(const aom_codec_cx_pkt_t *pkt) override {
100     // Check average PSNR value is >= 100 db in case of lossless encoding.
101     if (lossless_) {
102       EXPECT_GE(pkt->data.psnr.psnr[0], kMaxPsnr);
103       return;
104     }
105     const int psnr_index = (mode_ == ::libaom_test::kRealTime)   ? 2
106                            : (mode_ == ::libaom_test::kAllIntra) ? 1
107                                                                  : 0;
108     // Check that the initial Y PSNR value is 'high enough', and check that
109     // subsequent Y PSNR values are 'close' to this initial value.
110     if (frame0_psnr_y_ == 0.0) {
111       frame0_psnr_y_ = pkt->data.psnr.psnr[1];
112       EXPECT_GT(frame0_psnr_y_, kPsnrThreshold[psnr_index]);
113     }
114     EXPECT_NEAR(pkt->data.psnr.psnr[1], frame0_psnr_y_,
115                 kPsnrFluctuation[psnr_index]);
116   }
117 
118   int lossless_;
119   std::vector<int> chroma_value_list_;
120   double frame0_psnr_y_;
121 };
122 
TEST_P(MonochromeTest,TestMonochromeEncoding)123 TEST_P(MonochromeTest, TestMonochromeEncoding) {
124   ::libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
125                                        30, 1, 0, 5);
126 
127   init_flags_ = AOM_CODEC_USE_PSNR;
128 
129   cfg_.rc_buf_initial_sz = 500;
130   cfg_.rc_buf_optimal_sz = 600;
131   cfg_.rc_buf_sz = 1000;
132   cfg_.rc_min_quantizer = 2;
133   cfg_.rc_max_quantizer = 56;
134   cfg_.rc_undershoot_pct = 50;
135   cfg_.rc_overshoot_pct = 50;
136   cfg_.rc_end_usage = AOM_CBR;
137   cfg_.g_lag_in_frames = 1;
138   cfg_.kf_min_dist = cfg_.kf_max_dist = 3000;
139   // Enable dropped frames.
140   cfg_.rc_dropframe_thresh = 1;
141   // Run at low bitrate.
142   cfg_.rc_target_bitrate = 40;
143   // Set monochrome encoding flag
144   cfg_.monochrome = 1;
145 
146   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
147 
148   // Check that the chroma planes are equal across all frames
149   std::vector<int>::const_iterator iter = chroma_value_list_.begin();
150   int initial_chroma_value = *iter;
151   for (; iter != chroma_value_list_.end(); ++iter) {
152     // Check that all decoded frames have the same constant chroma planes.
153     EXPECT_EQ(*iter, initial_chroma_value);
154   }
155 }
156 
157 class MonochromeAllIntraTest : public MonochromeTest {};
158 
TEST_P(MonochromeAllIntraTest,TestMonochromeEncoding)159 TEST_P(MonochromeAllIntraTest, TestMonochromeEncoding) {
160   ::libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
161                                        30, 1, 0, 5);
162   init_flags_ = AOM_CODEC_USE_PSNR;
163   // Set monochrome encoding flag
164   cfg_.monochrome = 1;
165   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
166 
167   // Check that the chroma planes are equal across all frames
168   std::vector<int>::const_iterator iter = chroma_value_list_.begin();
169   int initial_chroma_value = *iter;
170   for (; iter != chroma_value_list_.end(); ++iter) {
171     // Check that all decoded frames have the same constant chroma planes.
172     EXPECT_EQ(*iter, initial_chroma_value);
173   }
174 }
175 
176 class MonochromeRealtimeTest : public MonochromeTest {};
177 
TEST_P(MonochromeRealtimeTest,TestMonochromeEncoding)178 TEST_P(MonochromeRealtimeTest, TestMonochromeEncoding) {
179   ::libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
180                                        30, 1, 0, 30);
181   init_flags_ = AOM_CODEC_USE_PSNR;
182   // Set monochrome encoding flag
183   cfg_.monochrome = 1;
184   // Run at low bitrate.
185   cfg_.rc_target_bitrate = 40;
186   cfg_.rc_buf_sz = 6000;
187   cfg_.rc_buf_initial_sz = 4000;
188   cfg_.rc_buf_optimal_sz = 5000;
189   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
190 
191   // Check that the chroma planes are equal across all frames
192   std::vector<int>::const_iterator iter = chroma_value_list_.begin();
193   int initial_chroma_value = *iter;
194   for (; iter != chroma_value_list_.end(); ++iter) {
195     // Check that all decoded frames have the same constant chroma planes.
196     EXPECT_EQ(*iter, initial_chroma_value);
197   }
198 }
199 
200 AV1_INSTANTIATE_TEST_SUITE(MonochromeTest,
201                            ::testing::Values(::libaom_test::kOnePassGood,
202                                              ::libaom_test::kTwoPassGood),
203                            ::testing::Values(0),   // lossless
204                            ::testing::Values(0));  // cpu_used
205 
206 AV1_INSTANTIATE_TEST_SUITE(MonochromeAllIntraTest,
207                            ::testing::Values(::libaom_test::kAllIntra),
208                            ::testing::Values(0, 1),   // lossless
209                            ::testing::Values(6, 9));  // cpu_used
210 
211 AV1_INSTANTIATE_TEST_SUITE(MonochromeRealtimeTest,
212                            ::testing::Values(::libaom_test::kRealTime),
213                            ::testing::Values(0),          // lossless
214                            ::testing::Values(6, 8, 10));  // cpu_used
215 
216 }  // namespace
217